home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Mac Game Programming Gurus / TricksOfTheMacGameProgrammingGurus.iso / Demos / Tools / QC™ 1.1.3 / QCAPI / BadAPPL / BadAPPL src / BadUtils.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-04-21  |  13.5 KB  |  494 lines  |  [TEXT/R*ch]

  1. /*________________________________________________________________________________
  2.  
  3.     BadUtils.c
  4.  
  5.     Copyright © 1993-1995 Onyx Technology - All rights reserved
  6.  
  7.     Various utility routines used by BadAPPL.
  8. ________________________________________________________________________________*/
  9.  
  10. #ifndef    _H_BadAPPL
  11. #include "BadAPPL.h"
  12. #endif
  13. #ifndef    _H_BadUtils
  14. #include "BadUtils.h"
  15. #endif
  16. #ifndef    _H_BadGestalt
  17. #include "BadGestalt.h"
  18. #endif
  19. #ifndef    _H_BadGlobs
  20. #include "BadGlobs.h"
  21. #endif
  22. #ifndef    _H_BadMacros
  23. #include "BadMacros.h"
  24. #endif
  25. #ifndef    _H_BadErrors
  26. #include "BadErrors.h"
  27. #endif
  28. #ifndef    _H_BadWindows
  29. #include "BadWindows.h"
  30. #endif
  31. #ifndef    _H_QCAPI
  32. #include "QCAPI.h"
  33. #endif
  34. #ifdef    USESROUTINEDESCRIPTORS
  35. #include <LowMem.h>
  36. #endif
  37.  
  38. /*________________________________________________________________________________
  39.  
  40.     MaintainCursor()
  41.  
  42.     info:     Maintain the cursor based upon where it is on the screen.
  43. ________________________________________________________________________________*/
  44.  
  45. void MaintainCursor(void)
  46. {
  47.     // if we had different cursors to maintain, this is where we would do it.
  48.     // because BadAPPL does allow editing of the TextEdit record (huh?) we dont
  49.     // need and dont use the I-beam cursor.
  50. }
  51.  
  52.  
  53. /*________________________________________________________________________________
  54.  
  55.     SetUpMenus()
  56.  
  57.     info:     Initialize our menus and build the menu bar
  58.             Please note that there are much more automatic ways to setup all our menus,
  59.             this example was coded this way to remain as simplistic as possible.
  60.  
  61.     return:    false if the menu couldn't be built.
  62. ________________________________________________________________________________*/
  63. short SetUpMenus(void)
  64. {
  65.     QCTestPtr        testListP;
  66.     MenuHandle        menuH;
  67.     long            testCnt;
  68.     short            loop, result = true;    // default to an okay status
  69.  
  70.     gTestListH = QCGetTestList(&gTestCnt);
  71.  
  72.     gMenus[appleM] = GetMenu(kAppleID);
  73.     if (!gMenus[appleM])
  74.         result = false;
  75.  
  76.     AddResMenu(gMenus[appleM], 'DRVR');
  77.     
  78.     // if any one of these GetMenu calls fails, we all fail!
  79.  
  80.     if (result && !(gMenus[fileM]         = GetMenu(kFileID)))
  81.         result = false;
  82.     if (result && !(gMenus[editM]         = GetMenu(kEditID)))
  83.         result = false;
  84.     if (result && !(gMenus[controlM]    = GetMenu(kControlID)))
  85.         result = false;
  86.     else
  87.         {
  88.         if (gTestListH)
  89.             {
  90.             testCnt = gTestCnt;
  91.             menuH = gMenus[controlM];
  92.             HLock((Handle)gTestListH);
  93.             testListP = *gTestListH;
  94.             while (testCnt)
  95.                 {
  96.                 // Safely append menu titles by first appending an item with a dummy
  97.                 //    name, then changing the name to the test. This avoids slashes that
  98.                 //    may appear in test names showing up w/command keys next to them.
  99.  
  100.                 AppendMenu(menuH, "\pdummy");
  101.                 SetItem(menuH, CountMItems(menuH), testListP->testName);
  102.                 testListP++;
  103.                 testCnt--;
  104.                 }
  105.             HUnlock((Handle)gTestListH);
  106.             }
  107.         }
  108.  
  109.     if (result && !(gMenus[errorsM]     = GetMenu(kErrorsID)))
  110.         result = false;
  111.     if (result && !(gMenus[stateM]        = GetMenu(kStateID)))
  112.         result = false;
  113.  
  114.     //    now get our heir-menus
  115.     if (result && !(gMenus[handleM]    = GetMenu(handleID)))
  116.         result = false;
  117.     if (result && !(gMenus[ptrM]        = GetMenu(ptrID)))
  118.         result = false;
  119.     if (result && !(gMenus[addrZeroM]    = GetMenu(addrZeroID)))
  120.         result = false;
  121.     if (result && !(gMenus[purgeM]        = GetMenu(purgeID)))
  122.         result = false;
  123.  
  124.     if (result)                                    // if we are still okay
  125.         {
  126.         // please note that we cant just go into a loop from 0 to NUM_MENUS because
  127.         // some of the menus included in that count are heir menus.  we have to include
  128.         // them as items in a given menu, not as items in the main menu bar.
  129.         
  130.         for ((loop=appleM); (loop <= stateM); loop++)
  131.             {
  132.             // if we got to here, gMenus[] contains all needed menus, don't need to check
  133.             // the array for !nil handle...we didn't initialize them all to nil anyway.
  134.  
  135.             InsertMenu(gMenus[loop], 0);
  136.             switch    (loop)
  137.                 {
  138.                 case    errorsM:
  139.                     InsertMenu(gMenus[handleM],     -1);
  140.                     InsertMenu(gMenus[ptrM],         -1);
  141.                     InsertMenu(gMenus[addrZeroM],    -1);
  142.                     InsertMenu(gMenus[purgeM],     -1);
  143.                     break;
  144.                 
  145.                 // if we add more menus we can handle inserting their heir menus here
  146.                 }
  147.             }
  148.  
  149.         DrawMenuBar();
  150.         }
  151.  
  152.     return(result);
  153. }
  154.  
  155. /*________________________________________________________________________________
  156.  
  157.     MaintainMenus()
  158.  
  159.     info:     Update the menus by enabling/disabling items as needed.
  160.  
  161. ________________________________________________________________________________*/
  162. void MaintainMenus(void)
  163. {
  164.     long        testCnt;
  165.  
  166.     if (gQCInstalled)                                    // we are installed, enable items & menus
  167.         {
  168.         if (QCIsActive())
  169.             SetItem(gMenus[fileM], onCommand, "\pTurn QC™ Off");
  170.         else
  171.             SetItem(gMenus[fileM], onCommand, "\pTurn QC™ On");
  172.  
  173.         testCnt = gTestCnt;
  174.         do
  175.             MaintainControlMenu(testCnt, kCheckMenus);
  176.         while(testCnt--);
  177.  
  178.         if (gQCSavedStateH)                                // is there state info present?
  179.             {
  180.             DisableItem(gMenus[stateM], saveCommand);
  181.             EnableItem(gMenus[stateM], restoreCommand);
  182.             }
  183.         else
  184.             {
  185.             EnableItem(gMenus[stateM], saveCommand);
  186.             DisableItem(gMenus[stateM], restoreCommand);
  187.             }
  188.         }
  189.     else                                                // disable all these items & menus
  190.         {
  191.         SetItem(gMenus[fileM], onCommand, "\pQC™ Not Loaded");
  192.         DisableItem(gMenus[fileM], onCommand);
  193.  
  194.         DisableItem(gMenus[controlM], 0);
  195.         DisableItem(gMenus[stateM], 0);
  196.         }
  197. }
  198.  
  199. /*________________________________________________________________________________
  200.     MaintainControlMenu()
  201.  
  202.     info:     Handle the Control (tests) menu by performing two important
  203.             functions for BadAPPL.
  204.  
  205.     entry:    theItem        - menu item to work with
  206.             controlCmd    - test if the particular test is on (kCheckState)
  207.                             set/clear the particular test (kDoState)
  208. ________________________________________________________________________________*/
  209. void    MaintainControlMenu(short theItem, short controlCmd)
  210. {
  211.     QCTestPtr    testP;
  212.     QCType        testID;
  213.     long        state;
  214.     short        err;
  215.     Boolean        checkIt;
  216.  
  217.     if ((theItem < 0) || (theItem > gTestCnt))
  218.         return;
  219.         
  220.     testP = *(gTestListH);                            // point to the first one
  221.     testP += (theItem-1);                            // advance to the desired QCTestRec
  222.     testID = testP->testID;                            //    and grab that test’s testID
  223.  
  224.     err = QCGetTestState(testID, &state);            // Now test whether that test is active or not
  225.     if (err)
  226.         OutputString( kErrStringsID, kQCGetTestState, (long) err);
  227.     else
  228.         {
  229.         switch (controlCmd)
  230.             {
  231.             case    kCheckMenus:
  232.                 if (state)
  233.                     checkIt = true;
  234.                 else
  235.                     checkIt = false;
  236.                 CheckItem(gMenus[controlM], theItem, checkIt);
  237.                 break;
  238.             
  239.             case    kDoState:
  240.                 QCSetTestState(testID, !state);        // just toggle it on/off
  241.                 break;
  242.             }
  243.         }
  244. }
  245.  
  246. /*________________________________________________________________________________
  247.  
  248.     DoDialog()
  249.  
  250.     info:     Display a given dialog and handle events by calling ModalDialog and
  251.             dispose of it properly when the user exits.     DoDialog can be used for
  252.             dialogs that don't require user interaction within the dialog, other
  253.             than clicking on a button to dismiss it.
  254.  
  255. ________________________________________________________________________________*/
  256. short DoDialog(short DLOGid)
  257. {
  258.     DialogPtr    my_dialog;
  259.     short        item_hit    =    0;
  260.     short        type;
  261.     Rect         boxT;
  262.     GrafPtr        savePort;
  263.     Handle        temp_H;
  264.     Point        dlgOrigin;
  265.  
  266.     if (!gAtleastSys7)                                // if we are pre 7.0, we need to
  267.         CenterDialog('DLOG', DLOGid, &dlgOrigin);    // center it ourselves
  268.  
  269.     if ((my_dialog = GetNewDialog(DLOGid, 0, (WindowPtr)-1L)))
  270.         {
  271.         ShowWindow(my_dialog);                        // because we have it initially
  272.                                                     // inivisible in the DLOG tmpl
  273.         GetPort( &savePort);
  274.         SetPort(my_dialog);
  275.  
  276.         // Here we do a quick modification to this otherwise generic dialog display code.
  277.         //    If we're compiling for PowerPC, then we want code that checks if we're displaying
  278.         //    the About dialog so we can display a small PowerPC logo (if available). Of course
  279.         //    if this wasn't just a sample, we'd check for monitor depth and display the right
  280.         //    picture for that depth so we always look good. As it is now, things don't look as
  281.         //    neat in 1-bit mode.  We don't need to extra code in this sample just to do that.
  282.  
  283.         #ifdef    powerc
  284.         if (DLOGid == aboutDLOG)                    // are we displaying the about box?
  285.             {
  286.             PicHandle    ppcLogoH = GetPicture(kPowerPCLogo);
  287.             if (ppcLogoH)
  288.                 {
  289.                 GetDItem(my_dialog, iPowerPCLogo, &type, &temp_H, &boxT);
  290.                 DrawPicture (ppcLogoH, &boxT);
  291.                 ReleaseResource((Handle) ppcLogoH);
  292.                 }
  293.             }
  294.         #endif
  295.  
  296.         GetDItem(my_dialog, iOkay, &type, &temp_H, &boxT);
  297.         FrameDefault( &boxT);
  298.  
  299.         ModalDialog(0L, &item_hit);                    // go running along now until the user
  300.                                                     //    interacts with us.
  301.         DisposDialog(my_dialog);
  302.  
  303.         SetPort(savePort);
  304.         }
  305.  
  306.     return(item_hit);
  307. }
  308.  
  309. /*________________________________________________________________________________
  310.  
  311.     BadAlert()
  312.  
  313.     info:     Display a generic Alert with a specified string in it.  This routine
  314.             relies on a DLOG with static text items in it and then calls DoDialog
  315.             to display that dialog.
  316.  
  317.     entry:    theString0    - pointer to text string to be used as Param0
  318.             theString1     - pointer to text string to be used as Param1
  319.             theString2    - pointer to text string to be used as Param2
  320.             Note that ParamText allows four param strings…we only use three
  321.  
  322. ________________________________________________________________________________*/
  323.  
  324. void BadAlert(StringPtr theString0, StringPtr theString1, StringPtr theString2)
  325. {
  326.     GrafPtr        savedPort;
  327.  
  328.     GetPort(&savedPort);
  329.  
  330.     ParamText(theString0, theString1, theString2, 0L);
  331.     DoDialog(errorDLOG);
  332.  
  333.     SetPort(savedPort);
  334. }
  335.  
  336.  
  337. /*________________________________________________________________________________
  338.  
  339.     CenterDialog()
  340.  
  341.     info:    Center dialog or alert template.
  342.             This routine 
  343.  
  344.     entry:    templateType    -    'DLOG' or 'ALRT'
  345.             templateID        -    the id of the rsrc template.
  346.             
  347.     return:    true if successful; false if not
  348.  
  349. ________________________________________________________________________________*/
  350.  
  351. short    CenterDialog( regvar long templateType, regvar short templateID, Point *dlgOrigin)
  352. {
  353. regvar    Rect        *dialog_rect;
  354. regvar    Rect        **the_H;                        // Templates start with boundsRect
  355. regvar    short        width;
  356. regvar    short        height;
  357.         Rect        scrn_rect;                        // the rect of the screen to center on
  358.         GDHandle    gHndl;
  359.         RgnHandle    deskRgn;                        // used temporarily here
  360.         short        result        =    true;
  361.  
  362.     if (ColorQDIsPresent())                            // are we using Color QuickDraw?
  363.         {
  364.         gHndl = GetMainDevice();                    // then get rect of main device
  365.         scrn_rect = (**gHndl).gdRect;                // and use it for the screen rect
  366.         }
  367.     else                                            // nope, no Color QuickDraw available
  368.         {
  369.         deskRgn         =    GetGrayRgn();            // so grab the Gray region
  370.         scrn_rect = (**deskRgn).rgnBBox;            // and use its bouding box
  371.         }
  372.     
  373.     if ( !(the_H = (Rect **)GetResource(templateType, templateID)) )    // try to get the DLOG or ALRT
  374.         {
  375.         // see ‘Macros.h’ for the Dbug macro which is only “live” if _CHECKPOINTS_ is #defined
  376.         DbugStr("\pCenterDialog failed GetResource");
  377.         result    =    false;    
  378.         }
  379.  
  380.     if (result)
  381.         {
  382.         #ifdef    USESROUTINEDESCRIPTORS
  383.         scrn_rect.top        += LMGetMBarHeight();
  384.         #else
  385.         scrn_rect.top         += MBarHeight;            // add the menu bar height to the top
  386.         #endif
  387.         dialog_rect         = *the_H;                // point to the DLOG or ALRT rectangle
  388.         // note, we dont call anything that moves memory near here so we can dereference the_H
  389.         
  390.         width                 = dialog_rect->right    - dialog_rect->left;
  391.         height                 = dialog_rect->bottom    - dialog_rect->top;
  392.         
  393.         dialog_rect->top     = scrn_rect.top        + ((scrn_rect.bottom - scrn_rect.top - height) / 3);
  394.         dialog_rect->bottom    = dialog_rect->top    + height;
  395.         dialog_rect->left    = scrn_rect.left     + ((scrn_rect.right - scrn_rect.left - width) / 2);
  396.         dialog_rect->right    = dialog_rect->left    + width;
  397.     
  398.         dlgOrigin->h        = dialog_rect->left;
  399.         dlgOrigin->v        = dialog_rect->top;
  400.         }
  401.  
  402.     return(result);    
  403. }
  404.  
  405. /*________________________________________________________________________________
  406.  
  407.     FrameDefault()
  408.  
  409.     info:     Frames default dialog buttons (usually OK buttons)
  410.  
  411.     entry:    r is the rect containing the button to frame
  412.  
  413. ________________________________________________________________________________*/
  414.  
  415. void    FrameDefault( Rect *r)
  416.         {
  417.         Rect    theRect    =    *r;
  418.         GrafPtr    port;
  419.         Point    savePenSize;
  420.         
  421.         GetPort(&port);
  422.         savePenSize = port->pnSize;
  423.  
  424.         PenSize(3, 3);
  425.         InsetRect( &theRect, -4, -4);    
  426.         FrameRoundRect( &theRect,16,16);
  427.         PenSize(savePenSize.h, savePenSize.v);
  428.         }
  429.  
  430. char *strcpy(char *s1, char *s2);
  431. /*________________________________________________________________________________
  432.  
  433.     HexToString()
  434.     
  435.     info:      Like NumToString except it converts the number to 
  436.             an unsigned hex string.
  437.             
  438.     entry:    n        -    The long to be converted
  439.             str        -    Must point to a Str255
  440.     exit:    str        -    Will contain an 9 character hex string, like \p00010AB4
  441.  
  442. ________________________________________________________________________________*/
  443. void HexToString (regvar ulong number, uchar *hex)
  444.     {
  445.     char    digits[16]    = {'0','1','2','3','4','5','6','7','8','9',
  446.                             'A','B','C','D','E','F'};
  447.     char    zeros[9]    = {8,0,0,0,0,0,0,0,0};
  448.     int        n;
  449.  
  450.     // Get those leading zeros
  451.     strcpy ((char *) hex, (char *) zeros);
  452.  
  453.     hex[0] = 8;
  454.     for (n = 8; n >= 1; n--)
  455.         {
  456.         hex[n] = digits[number % 16];
  457.         number = number / 16;
  458.         }
  459.     }
  460.  
  461. /*________________________________________________________________________________
  462.  
  463.     format:   void AppendString( uchar * origStr, uchar * addStr);
  464.  
  465.     info:      Appends contents of addStr onto origStr, clipping it at
  466.               255 characters.
  467.  
  468.     entry:      Two Pascal Str255 ptrs.
  469.  
  470.     exit:      alters origStr.
  471. ________________________________________________________________________________*/
  472. void AppendString( regvar uchar *origStr, regvar uchar *addStr)
  473. {
  474. regvar    short    origLen = *origStr;
  475. regvar    short    addLen    = *addStr++;
  476. regvar    short    newLen;
  477.  
  478.     if (origLen + addLen > 255)            // Prevent overwriting memory
  479.         {
  480.         newLen = 255;
  481.         addLen = 255 - origLen;
  482.         }
  483.     else
  484.         newLen = origLen + addLen;
  485.  
  486.  
  487.     *origStr++ = newLen;                // Increase size
  488.     origStr      += origLen;                // Append on end
  489.  
  490.     while (addLen--)
  491.         *origStr++ = *addStr++;
  492. }
  493.  
  494.