home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1996 January / macformat-033.iso / mac / Shareware City / Developers / ABox.v1.8 / ABoxTest.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-23  |  29.7 KB  |  1,097 lines  |  [TEXT/MMCC]

  1. /*    
  2.     Copyright © 1991-1995 by TopSoft Inc.  All rights reserved.
  3.  
  4.     You may distribute this file under the terms of the TopSoft
  5.     Artistic License, accompanying this package.
  6.     
  7.     This file was developed by George (ty) Tempel in connection with 
  8.     TopSoft, Inc.
  9.     
  10.     See the Modification History for more details.
  11.  
  12. Product
  13.     About Box Test/Demo application
  14.  
  15. FILE
  16.     ABoxTest.c
  17.  
  18. NAME
  19.     ABoxTest.c, part of the ABox project source code,
  20.     responsible for the demonstration and testing of the ABox.
  21.  
  22. DESCRIPTION
  23.     This file contains the entire source for the ABoxTest application,
  24.     including defines.
  25.     
  26. DEVELOPED BY
  27.     George (ty) Tempel                netromancr@aol.com
  28.     All code in this file, and its associated header file was
  29.     Created by George (ty) Tempel in connection with TopSoft, Inc.
  30.     "FilterTop" application development, except where noted.
  31.  
  32.     This shell--ABoxTest.c--is shamelessly based upon MModal.c by
  33.     C.K. Haun of Apple DTS, and borrows portions of ModelessSample
  34.     by Nitin Ganatra of Apple DTS.
  35.     
  36. CARETAKER - George (ty) Tempel <netromancr@aol.com>
  37.      Please consult this person for any changes or suggestions to this file.
  38.  
  39. MODIFICATION HISTORY
  40.  
  41.     dd mmm yy    -    xxx    -    patchxx: description of patch
  42.     10 June 94    -    ty    -    Initial Version Created
  43.     12-jan-95    -    ty    -    updated for release 1.1; cleaned up for CodeWarrior 5
  44.                             release; substituted UpdateWindowUPP where I was
  45.                             using proc pointers.
  46.     23-may-95    -    ty    -    changes for compatibility with the CodeWarrior CW6
  47.                             release and the associated Universal Headers from Apple:
  48.                             most methods that returned references now have "Ref" at
  49.                             the end of their methods names to prevent possible collisions
  50.                             with datatypes and classes of the same name (older versions
  51.                             of the compiler didn't have a problem with this).
  52.  
  53. */
  54.  
  55. /*===========================================================================*/
  56.  
  57. /*======= Segmentation directives ========*/
  58.  
  59. /*============ Header files ==============*/
  60.  
  61. #include    "ABox.h"
  62.  
  63.  
  64. /*============ Enumerations ==============*/
  65.  
  66. enum  {
  67.     kMBarID = 128
  68. };
  69.  
  70. enum  {
  71.     kAppleMenu = 128, 
  72.     kFileMenu, 
  73.     kEditMenu, 
  74.     kToolsMenu, 
  75.     kDebuggerMenu
  76. };
  77.  
  78. enum {
  79.     kEnterDebugger = 1,
  80.     kToggleLeaks,
  81.     kToggleHeapScramble
  82. };
  83.  
  84. enum {
  85.     kToggleLeaksOn = 1,
  86.     kToggleLeaksOff,
  87.     kToggleHeapScrambleOn,
  88.     kToggleHeapScrambleOff
  89. };
  90.  
  91. #define    kResumeMask    1          /* bit of message field for resume vs. suspend */
  92. #define    kSampHelp    129 
  93. #define    kAboutBox    128 
  94. #define    kHelpString    128 
  95. #define    kNewItem        1
  96. #define    kCloseButton    128 
  97. #define    kQuitItem    10 
  98. #define    kGenStrings    128
  99. #define    kMyModalKind        1000
  100. #define    kMyDocumentKind    1002
  101.  
  102. enum  {
  103.     kItem1 = 1
  104. };
  105.  
  106.  
  107. //============ for use with GetDebuggerInfo ==========
  108. //
  109. //    from "debugger.c", from the Apple _develop_ #18 CD collection
  110. //    of DTS Snippets
  111. //
  112. /* stuff that should be defined in C, but isn't (it's in Private.a) */
  113. #define    MacJmp            (Ptr *)  0x120        /* MACSBUG jumptable [pointer] */
  114. #define    MacJmpByte        (char *) 0x120        /* MACSBUG flags in 24 bit mode [byte] */
  115. #define MacJmpFlag        (char *) 0xBFF        /* MacsBug flag [byte] */
  116.  
  117. enum dTypes {
  118.     noDebugger,
  119.     macsbug,
  120.     tmon,
  121.     other
  122. };
  123.  
  124. typedef enum dTypes    debuggerTypes;
  125.  
  126. // stuff for use in this code
  127. #define    DebuggerInstalled    5
  128.  
  129.  
  130. /*============ Globals ==============*/
  131.  
  132. MenuHandle             gAppleMenuHandle, 
  133.                     gFileMenuHandle, 
  134.                     gEditMenuHandle, 
  135.                     gToolMenuHandle,
  136.                     gDebuggerMenuHandle;
  137.                     
  138. Boolean             gQuit, 
  139.                     gInBackground;
  140. short                gAppResFile;
  141.  
  142. ABox                *gABox = NULL;
  143. UpdateWindowUPP        gUpdateUPP;
  144.  
  145. short                gDummyResFileRefNum;
  146. Str255                gDummyResFile = "\pABoxTest test-file";
  147. WindowPtr            gFirstWindow,
  148.                     gSecondWindow;
  149. Boolean                gDoSomethingSilly;
  150. Boolean                gDebuggerPresent = false;
  151.  
  152.  
  153. /*============ Prototypes ==============*/
  154.  
  155. void     HandleUpdate(WindowPtr window);
  156. OSErr    PrepareABox (ABox *abox, 
  157.                     ABoxSplashTimeType splashTimeSeconds, 
  158.                     ABoxModalIndicator modality, 
  159.                     FSSpecPtr homeSpec);
  160. void    Initialize(void);
  161.  
  162.  
  163. void    DoDaCall(MenuHandle themenu, long theit);
  164. void    DrawMain(WindowPtr drawIt);
  165. void    DrawMain2(WindowPtr drawIt);
  166. Boolean DoSelected(long val);
  167. void    DoDebuggerMenu(short loval);
  168. void    DoHighLevel(EventRecord *AERecord);
  169. void    OpenTheABox(short aboxTypes);
  170. void    CloseTheABox(void);
  171. OSErr    DoEvents(void);
  172. void    DoDiskEvents(long dinfo);    // hi word is error code, lo word is drive number
  173.  
  174. OSErr    DoSomethingSilly(void);
  175.  
  176.  
  177. Boolean        GetDebuggerInfo(debuggerTypes *kind, short *signature);
  178.  
  179.  
  180.  
  181.  
  182. //============ code begins here.... =====================
  183.  
  184.  
  185.  
  186.  
  187. /*=============================== GetDebuggerInfo ================================*/
  188. //
  189. //    from "debugger.c", from the Apple _develop_ #18 CD collection
  190. //    of DTS Snippets
  191. //
  192. /*
  193. ** GetDebuggerInfo
  194. ** as documented in the "Macsbug Reference & Debugging Guide", page 412
  195. ** if we have a 32 bit capable Memory Manager, debugger flags are at $BFF
  196. ** if we have a 24 bit capable Memory Manager, debugger flags are at $120
  197. ** Ptr at $120 
  198. **
  199. ** Note that the documentation is slightly obscure--you check if the machine
  200. ** is capable of 32-bit mode, _not_ if you are running in 32 bit mode.
  201. **/
  202. /*
  203. **  This is a small snippet of code that can be used to to detect if
  204. **  macsbug is installed or not. NOTE:  This code is intended to only
  205. **  work with version 6.2 of macsbug.  You should refer to your Low Level
  206. **  Debugger's manual for more information on how they install
  207. **  themselves.
  208. **  
  209. **  This code is based on information obtained from the MacsBug
  210. **  Reference. The basic assumptions are that macsbug will install itself
  211. **  in the following manner:
  212. **  
  213. **  If you are running with a Memory Manager that only works in 24 bit
  214. **  mode, then the high -order byte of MacJmp is a flags byte that
  215. **  contains the following information:
  216. **  
  217. **  Bit    Meaning
  218. **  ---    --------------------------------------
  219. **  7    -   Set if debugger is running
  220. **  6    -   Set if debugger can handle system errors
  221. **  5    -   Set if debugger is installed
  222. **  4     -   Set if debugger can support discipline utility
  223. **  
  224. **  The lower 3 bytes are used to store the address of the debugger's
  225. **  entry point.
  226. **  
  227. **  If you are running with a Memory Manager that works in 32-bit mode,
  228. **  the flags byte is moved to address 0xBFF and the long word at MacJmp
  229. **  becomes a full 32-bit address that points to the debugger's entry
  230. **  point..
  231. **  
  232. **  Symantec has a comment in the Think Reference 2.0.1 which states:
  233. **  
  234. **  "ADDENDUM:  The above information seems to be incorrect in the
  235. **  reference manual. I have found through testing etc. that in both
  236. **  modes, the Flag Byte appears at location 0xBFF.  The code reflects
  237. **  these findings."
  238. **  
  239. **  This is because they confused running in 24 bit mode, running in 32
  240. **  bit mode, and the _ability_ to run in 32 bit mode.  It is the latter
  241. **  ability which you must test to determine the location of the debugger
  242. **  flags.
  243. **
  244. */
  245. Boolean    GetDebuggerInfo(debuggerTypes *callerKind, short *callerSignature)
  246. {
  247.     short    debugFlags;
  248.     Ptr        debugEntry;
  249.     short    **debugWorld;
  250.     Ptr        ROMBaseWorld;
  251.     long    addressingMode;
  252.     
  253.     debuggerTypes    kind;
  254.     short            signature;
  255.     Boolean            gotIt = false;
  256.     
  257.     //     initialize defaults, assuming no debugger present
  258.     kind = noDebugger;
  259.     signature = '  ';
  260.  
  261.     Gestalt(gestaltAddressingModeAttr, &addressingMode);
  262.     if (addressingMode & (1 << gestalt32BitCapable))
  263.         debugFlags = *MacJmpFlag;
  264.     else
  265.         debugFlags = *MacJmpByte;
  266.  
  267.     if ( debugFlags & (1 << DebuggerInstalled) ) 
  268.     {
  269.  
  270.         //    we've got a debugger. what is it? 
  271.         debugEntry = StripAddress(*MacJmp);
  272.         ROMBaseWorld = StripAddress(LMGetROMBase());
  273.  
  274.         if (debugEntry < ROMBaseWorld) 
  275.         {    //    not ROM based debugger
  276.  
  277.             debugWorld = (short **)StripAddress(debugEntry - sizeof(Ptr));
  278.             signature = **debugWorld;
  279.             switch (signature) 
  280.             {
  281.                 case 'MT':
  282.                     kind = macsbug;
  283.                     break;
  284.                 case 'WH':
  285.                     kind = tmon;
  286.                     break;
  287.                 default:
  288.                     kind = other;
  289.                     break;
  290.             } // end switch block
  291.         } // end if (debugEntry...) block
  292.         
  293.         gotIt = true;
  294.     } // end if (debugFlags... ) block
  295.  
  296.     if (callerKind)
  297.         *callerKind = kind;
  298.     if (callerSignature)
  299.         *callerSignature = signature;
  300.             
  301.     return gotIt;
  302. } // end GetDebuggerInfo()
  303.  
  304.  
  305.  
  306.  
  307.  
  308.  
  309. /*=============================== HandleUpdate ================================*/
  310. void HandleUpdate(WindowPtr window)
  311. {
  312.     GrafPtr        oldPort;
  313.     UpdateWindowUPP        drawProc;
  314.     short        tempKind;
  315.             
  316.     
  317.     if (!window)
  318.         return;
  319.     
  320.     GetPort(&oldPort);
  321.     tempKind = ((WindowPeek)window)->windowKind;
  322.     // Make sure it's my window before I jump through the refCon
  323.     // Why, since DA's have they're own layer in 7.0?
  324.     // BECAUSE there are other people in the universe who will
  325.     // add things to your windowList.BalloonWriter, for example
  326.     // so you still need to be careful
  327.     //
  328.     // ty: HOWEVER---this majorly does not work with modal dialogs,
  329.     //        because the System reserves a special kind for ModalDialog,
  330.     //        and if you stomp on it things wont behave properly. So
  331.     //        be nice!
  332.     //
  333.     if (tempKind == kMyModalKind || tempKind == kMyDocumentKind) 
  334.     {
  335.         // get the drawing proc from the refCon
  336.         drawProc = (UpdateWindowUPP)GetWRefCon(window);
  337.         // jump to it
  338.         //drawProc(window);
  339.         // 1.1--updated for new compiler, and might as well make use
  340.         //    of the UPP i defined a long time ago...
  341.         if (drawProc)
  342.             CallWindowUpdateProc(drawProc, window);
  343.         if (gDoSomethingSilly)
  344.             (void)DoSomethingSilly();
  345.     } // end if block
  346.     
  347.     SetPort (oldPort);           
  348. }    //    end of test function HandleUpdate()
  349.  
  350.  
  351.  
  352.  
  353. /*=============================== Initialize ================================*/
  354. void    Initialize(void)
  355. {
  356.     short         i;
  357.     Handle        myMenu;
  358.     
  359.     Str255        theName;
  360.  
  361.     //    begin here...
  362.     
  363.     MaxApplZone();
  364.     for (i = 1; i <= 10; i++)
  365.         MoreMasters();
  366.  
  367.     //    initialize the globals here...
  368.     
  369.     InitGraf (&qd.thePort);
  370.     InitFonts();
  371.     FlushEvents(everyEvent, 0);
  372.     InitWindows();
  373.     InitMenus();
  374.     TEInit();
  375.     InitDialogs(0L);
  376.     InitCursor();
  377.     
  378.     // set up my menu junk
  379.     myMenu = GetNewMBar(kMBarID);
  380.     SetMenuBar(myMenu);
  381.     gAppleMenuHandle = GetMHandle(kAppleMenu);
  382.     gFileMenuHandle = GetMHandle(kFileMenu);
  383.     gEditMenuHandle = GetMHandle(kEditMenu);
  384.     gToolMenuHandle = GetMHandle(kToolsMenu);
  385.     gDebuggerMenuHandle = GetMHandle(kDebuggerMenu);
  386.     AddResMenu(gAppleMenuHandle, 'DRVR');
  387.     DrawMenuBar();
  388.  
  389.     //    we of course don't do anything here in this simple app
  390.     //    except open our window
  391.     gFirstWindow = GetNewWindow(128, nil, (WindowPtr)-1);
  392.     ((WindowPeek)gFirstWindow)->windowKind = kMyDocumentKind;
  393.     
  394.     //    install drawing proc
  395.     UpdateWindowUPP        drawProc = NewWindowUpdateProc(DrawMain);
  396.     SetWRefCon(gFirstWindow, (long)drawProc);
  397.     
  398.     // open another one, so we can demonstrate shuffling inhibiting
  399.     gSecondWindow = GetNewWindow(128, nil, (WindowPtr)-1);
  400.     ((WindowPeek)gSecondWindow)->windowKind = kMyDocumentKind;
  401.     
  402.     //    install drawing proc
  403.     UpdateWindowUPP        drawProc2 = NewWindowUpdateProc(DrawMain);
  404.     SetWRefCon(gSecondWindow, (long)drawProc2);
  405.     GetIndString(theName, kGenStrings, 1);
  406.     SetWTitle(gSecondWindow, theName);
  407.     SelectWindow(gFirstWindow);
  408.     SetPort(gFirstWindow);
  409.  
  410.     gAppResFile = CurResFile();
  411.  
  412.     //    check for the presense of a debugger...if we can't find one
  413.     //    then disable the entire gDebuggerMenuHandle menu in the menu bar
  414.     
  415.     gDebuggerPresent = GetDebuggerInfo(NULL, NULL);
  416.     if (!gDebuggerPresent)
  417.         DisableItem(gDebuggerMenuHandle, 0);
  418.     
  419.     return;
  420. } // end Initialize
  421.  
  422.  
  423.  
  424.  
  425.  
  426. /*=============================== main ================================*/
  427. void    main(void)
  428. {
  429.     OSErr    error = noErr;
  430.     
  431.     //    begin here...
  432.     Initialize();
  433.     
  434.     gUpdateUPP = NewWindowUpdateProc(HandleUpdate);
  435.     
  436.     //    open up a silly resource file just to toss a wrench
  437.     //    into the spokes, so to speak...
  438.     gDummyResFileRefNum = OpenResFile (gDummyResFile);
  439.     error = ResError();
  440.     if (error)
  441.         //    oops! something's wrong, so we'll use the system for
  442.         //    for some extra resource stuff
  443.         gDummyResFileRefNum = 0;
  444.         
  445.     DoEvents();
  446.  
  447.     //    ===========
  448.     
  449.     
  450.     //    ok, we're all finished here, so leave
  451.     DisposeRoutineDescriptor (gUpdateUPP);
  452.  
  453.     //    if we had a silly resource file open, close it up
  454.     //    before we leave.
  455.     if (gDummyResFileRefNum > 0)
  456.         CloseResFile (gDummyResFileRefNum);
  457.         
  458.     delete gABox;
  459.     
  460. }    // end of function main()
  461.  
  462.  
  463.  
  464. /*=============================== DoSomethingSilly ================================*/
  465. //
  466. //    this function will just do something silly and meaningless, like
  467. //    read from a bunch of string resources. This is used to simulate
  468. //    the real application busy doing something while the abox is up
  469. //    doing something as a splash screen.
  470. //
  471. OSErr    DoSomethingSilly(void)
  472. {
  473.     OSErr            error = noErr;
  474.     short            limit;
  475.     short            index;
  476.     StringHandle    stringHandle = NULL;
  477.     short            curResFile = CurResFile();
  478.     GrafPtr            oldPort;
  479.     const ResType    stringType = 'STR ';
  480.     
  481.     //    begin here...
  482.     
  483.     //    switch to our silly resource file and read
  484.     //    some random string from it
  485.     
  486.     UseResFile (gDummyResFileRefNum);
  487.     limit = Count1Resources (stringType);
  488.     error = ResError();
  489.     if (limit < 1)
  490.         limit = 1;
  491.     
  492.     index = (TickCount() % limit) + 1;
  493.     stringHandle = (StringHandle)Get1IndResource (stringType, index);
  494.     error = ResError();
  495.     
  496.     //    now draw the string into one of the windows...we'll alternate
  497.     //    which one we want based upon some bizarre method
  498.     //
  499.     //    phase of the moon? color of the entrails? alignment of the planets?
  500.     //    Nah...we'll just modulate on the index
  501.     //
  502.     if (!error)
  503.     {
  504.         WindowPtr    theWindow = (TickCount() % 2) ? gFirstWindow : gSecondWindow;
  505.         Rect        theRect = theWindow->portRect;
  506.         
  507.         GetPort (&oldPort);
  508.         SetPort (theWindow);
  509.  
  510.         theRect.left = 20;
  511.         theRect.bottom -= 15;
  512.         theRect.top = theRect.bottom - 20;
  513.         EraseRect (&theRect);
  514.         theRect.bottom -= 5;
  515.         
  516.         MoveTo (theRect.left, theRect.bottom);
  517.         if (stringHandle)
  518.         {
  519.             HLock((Handle)stringHandle);
  520.             DrawString (*stringHandle);
  521.             HUnlock((Handle)stringHandle);
  522.         } else {
  523.             DrawString ("\pDuh....no 'STR ' resource to work with");
  524.         } // end if else block
  525.         
  526.         SetPort (oldPort);
  527.         //localTick = TickCount();
  528.     } // end if block
  529.     
  530.     UseResFile (curResFile);
  531.     return error;
  532. } // end DoSomethingSilly
  533.  
  534.  
  535.  
  536.  
  537. /*=============================== DoEvents ================================*/
  538. //
  539. OSErr    DoEvents(void)
  540. {
  541.     EventRecord            eRecord;
  542.     unsigned long        mySleep = 30;
  543.     OSErr                error;
  544.     WindowPtr            aboxWindow = NULL;
  545.     ABoxModalIndicator    aboxModality = kABoxModeless;
  546.     WindowPtr            twindow;
  547.     Boolean                aboxHandled = false;
  548.     short                index = 0, limit = 250;
  549.     
  550.     //    begin here...
  551.     
  552.     if (gABox)
  553.     {
  554.         error = gABox->GetProperty (kABoxWindow, &aboxWindow, NULL);
  555.         error = gABox->GetProperty (kABoxModalIndicator, &aboxModality, NULL);
  556.     } // end if block
  557.     
  558.     do 
  559.     {
  560.         
  561.         WaitNextEvent(everyEvent, &eRecord, mySleep, nil);
  562.         
  563.         if (gDoSomethingSilly)
  564.         {
  565.             if (index < limit)
  566.             {
  567.                 error = DoSomethingSilly();
  568.                 ++index;
  569.             } else {
  570.                 gDoSomethingSilly = false;
  571.                 index = 0;
  572.                 CloseTheABox();
  573.             } // end if block
  574.             
  575.         } // end if block
  576.         
  577.         if (gABox)
  578.         {
  579.             Boolean    aboxFinished = false;
  580.             
  581.             aboxHandled = gABox->Event(&eRecord);
  582.             error = gABox->GetProperty (kABoxIsFinished, &aboxFinished, NULL);
  583.             if (aboxFinished)
  584.             {
  585.                 CloseTheABox();
  586.             } else if (aboxHandled) {
  587.                 continue;
  588.             } // end if block
  589.         } // end if block
  590.         
  591.         
  592.         switch (eRecord.what) 
  593.         {
  594.             case nullEvent:
  595.                 if (gDoSomethingSilly)
  596.                     error = DoSomethingSilly();
  597.             
  598.                 break;
  599.                 
  600.             case updateEvt:
  601.                 if (((WindowPtr)eRecord.message) != aboxWindow)
  602.                     HandleUpdate((WindowPtr)(eRecord.message));
  603.                     
  604.                 break;
  605.                 
  606.             case mouseDown:
  607.                 // first see where the hit was
  608.                 // When you first think about the Movable Modal issue, you may
  609.                 // say to yerself "Hey!if there's a mouseDown all I have to do is
  610.                 // see if it's in the portRect of the front window, and SysBeep if it isn't!"
  611.                 // Nah, too easy.Remember, you want a user to be able to switch out
  612.                 // of your application when a movable modal is up, so you still need
  613.                 // to call FindWindow and see if it was a hit in the desktop, other
  614.                 // app window (same as desktop), or in the Help or Application menus.
  615.                 
  616.                 switch (FindWindow(eRecord.where, &twindow)) 
  617.                 {
  618.                     
  619.                     case inDesk:      // if they hit in desk, then the process manager
  620.                         break;        //    will switch us out, we don't need to do anything
  621.                         
  622.                     case inMenuBar:
  623.                         // let Help and Application menus happen always
  624.                         DoSelected(MenuSelect(eRecord.where));
  625.                         break;
  626.                         
  627.                     case inSysWindow:
  628.                         // pass to the system
  629.                         SystemClick(&eRecord, twindow);
  630.                         break;
  631.                         
  632.                     case inContent:
  633.                         // Handle content and control clicks here
  634.  
  635.                         SelectWindow(twindow);      // select the window
  636.  
  637.                         break;
  638.                         
  639.                     case inDrag:
  640.                         SelectWindow(twindow);
  641.                         DragWindow(twindow, eRecord.where, &qd.screenBits.bounds);
  642.                         break;
  643.                         
  644.                     case inGrow:
  645.                         // Call GrowWindow here if you have a grow box
  646.                         break;
  647.                         
  648.                     case inGoAway:
  649.                         // Click in Close box
  650.                         break;
  651.                 }
  652.                 break;
  653.             case mouseUp:
  654.                 // don't care
  655.                 break;
  656.                 // same action for key or auto key
  657.             case keyDown:
  658.             case autoKey:
  659.                 if (eRecord.modifiers & cmdKey)
  660.                     DoSelected(MenuKey(eRecord.message & charCodeMask));
  661.                 break;
  662.                 
  663.             case keyUp:
  664.                 // don't care
  665.                 break;
  666.                 
  667.             case diskEvt:
  668.                 // I don't do anything special for disk events, this just passes them
  669.                 //    to a function that checks for an error on the mount
  670.                 DoDiskEvents(eRecord.message);
  671.                 break;
  672.                 
  673.             case activateEvt:
  674.                 // not doing anything on activates
  675.                 break;
  676.                 
  677.             case networkEvt:
  678.                 // don't care
  679.                 break;
  680.                 
  681.             case driverEvt:
  682.                 // don't care
  683.                 break;
  684.                 
  685.             case app4Evt:
  686.                 // If we're switching layers and I have my MModal up, I want to
  687.                 // change the state of the control
  688.                 switch ((eRecord.message >> 24) & 0x0FF) 
  689.                 {     // high byte of message
  690.                     
  691.                     case suspendResumeMessage:              // suspend/resume is also an activate/deactivate
  692.                         gInBackground = (eRecord.message & kResumeMask) == 0;
  693.                         break;
  694.                         
  695.                 }
  696.                 break;
  697.                 
  698.                 // This dispatches high level events (AppleEvents, for example)
  699.                 // to our dispatch routine.This is NEW in the event loop for
  700.                 // System 7
  701.             case kHighLevelEvent:
  702.                 DoHighLevel(&eRecord);
  703.                 break;
  704.             default:
  705.                 break;
  706.                 
  707.         }
  708.  
  709.     }    while (gQuit != true);
  710.     
  711.     return error;
  712. }    //    end doevents
  713.  
  714.  
  715.  
  716. /*=============================== DoDiskEvents ================================*/
  717. //
  718. // DoDiskEvents just checks the error code from the disk mount,
  719. // and puts up the 'Format' dialog (through DIBadMount) if need be
  720. // You can do much more here if you care about what disks are
  721. // in the drive
  722. void DoDiskEvents(long dinfo)    // hi word is error code, lo word is drive number
  723. {
  724.     short hival, loval, tommy;
  725.     Point fredpoint =  {  40, 40 };
  726.     
  727.     hival = HiWord(dinfo);
  728.     loval = LoWord(dinfo);
  729.     if (hival != noErr) // something happened 
  730.     {
  731.         tommy = DIBadMount(fredpoint, dinfo);
  732.     }
  733. }
  734.  
  735.  
  736. /*=============================== DoDaCall ================================*/
  737. //
  738. // DoDaCall opens the requested DA.It's here as a seperate routine if you'd
  739. // like to perform some action or just know when a DA is opened in your
  740. // layer.Can be handy to track memory problems when a DA is opened
  741. // with an Option-open
  742. void DoDaCall(MenuHandle themenu, long theit)
  743. {
  744.     long qq;
  745.     Str255 DAname;
  746.     GetItem(themenu, theit, DAname);
  747.     qq = OpenDeskAcc(DAname);
  748. } // end DoDaCall
  749.  
  750.  
  751. /*=============================== DrawMain ================================*/
  752. //
  753. // draws my window.Pretty simple
  754. void DrawMain(WindowPtr drawIt)
  755. {
  756.     Handle theText;
  757.     WindowPtr tempWP;
  758.     GetPort(&tempWP);
  759.     BeginUpdate(drawIt);
  760.     SetPort(drawIt);
  761.     EraseRect(&drawIt->portRect);
  762.     theText = GetResource('TEXT', 128);
  763.     if (theText) {
  764.         Rect textRect;
  765.         HLock(theText);
  766.         HUnlock(theText);
  767.         textRect = drawIt->portRect;
  768.         InsetRect(&textRect, 20, 20);
  769.         TextBox(*theText, GetHandleSize(theText), &textRect, 0);
  770.         ReleaseResource(theText);
  771.     }
  772.     EndUpdate(drawIt);
  773.     SetPort(tempWP);
  774. }
  775.  
  776.  
  777. /*=============================== DrawMain2 ================================*/
  778. //
  779. // a second version for variety
  780. void DrawMain2(WindowPtr drawIt)
  781. {
  782.     Handle theText;
  783.     WindowPtr tempWP;
  784.     GetPort(&tempWP);
  785.     
  786.     BeginUpdate(drawIt);
  787.     SetPort(drawIt);
  788.     EraseRect(&drawIt->portRect);
  789.     theText = GetResource('TEXT', 130);
  790.     if (theText) {
  791.         Rect textRect;
  792.         HLock(theText);
  793.         HUnlock(theText);
  794.         textRect = drawIt->portRect;
  795.         InsetRect(&textRect, 20, 20);
  796.         TextBox(*theText, GetHandleSize(theText), &textRect, 0);
  797.         ReleaseResource(theText);
  798.     }
  799.     EndUpdate(drawIt);
  800.     SetPort(tempWP);
  801. }
  802.  
  803.  
  804.  
  805. /*=============================== DoSelected ================================*/
  806. //
  807. // my menu action taker.It returns a Boolean which I usually ignore, but it
  808. // might be handy someday
  809. Boolean DoSelected(long val)
  810. {
  811.     short loval, hival;
  812.     Boolean returnVal = false;
  813.     loval = LoWord(val);
  814.     hival = HiWord(val);
  815.     
  816.     switch (hival) {                                        // switch off the menu number selected
  817.         case kAppleMenu:                                    // Apple menu
  818.             if (loval != 1) {                               // if this was not About, it's a DA
  819.                 DoDaCall(gAppleMenuHandle, loval);
  820.             } else {
  821.                 OpenTheABox(loval);                            // do about box
  822.             }
  823.             returnVal = true;
  824.             break;
  825.         case kFileMenu:                                     // File menu
  826.             switch (loval) {
  827.                 case kQuitItem:
  828.                     gQuit = true;                           // onlyitem
  829.                     returnVal = true;
  830.                     break;
  831.                 default:
  832.                     break;
  833.             }
  834.             break;
  835.             
  836.         case kEditMenu:
  837.             // edit menu junk
  838.             // don't care
  839.             break;
  840.             
  841.         case kToolsMenu:
  842.             // add all your test stuff here
  843.             OpenTheABox(loval);
  844.             break;
  845.         case kDebuggerMenu:
  846.             //    do some debugger stuff...
  847.             DoDebuggerMenu(loval);
  848.             break;
  849.         case kHMHelpMenuID:                      // Defined in Balloons.h
  850.             // I only care about this item. If anything else is returned here, I don't know what
  851.             // it is, so I leave it alone.Remember, the Help Manager chapter says that
  852.             // Apple reserves the right to add and change things in the Help menu
  853.             break;
  854.             
  855.     }
  856.     HiliteMenu(0);
  857.     return(returnVal);
  858. }
  859.  
  860.  
  861. /*=============================== DoHighLevel ================================*/
  862. //
  863. // I'm not doing error handling in this sample for clarities sake, you should. Hah,
  864. // easy for me to say, huh?
  865. void DoHighLevel(EventRecord *AERecord)
  866. {
  867.     
  868.     AEProcessAppleEvent(AERecord);
  869.     
  870. }
  871.  
  872.  
  873.  
  874. /*=============================== DoDebuggerMenu ================================*/
  875. //
  876. //
  877. void    DoDebuggerMenu (short menuItem)
  878. {
  879.     OSErr    error = noErr;
  880.     
  881.     Str255    debuggerString;
  882.     
  883.     //    begin here...
  884.     
  885.     GetItem (gDebuggerMenuHandle, menuItem, debuggerString);
  886.     DebugStr (debuggerString);
  887.     
  888.     return;
  889. } // end DoDebuggerMenu
  890.  
  891.  
  892.  
  893.  
  894.  
  895. /*=============================== OpenTheABox ================================*/
  896. //
  897. // Opens the MModal dialog.
  898. //
  899. void OpenTheABox(short aboxTypes)
  900. {
  901.     OSErr                error = noErr;
  902.     long                dirID = 0;
  903.     short                vRefNum = 0;
  904.     FSSpec                homeSpec;
  905.     
  906.     ABoxSplashTimeType    splashTime;
  907.     ABoxModalIndicator    modality;
  908.     
  909.     //    begin here...
  910.     
  911.     if (aboxTypes % 4 == 0)
  912.         //    not an item...sorry
  913.         return;
  914.         
  915.     //    create the FSSpec that should point to the "home" for the application
  916.     //
  917.     //    application developers note: this FSSpec should point to the root of some
  918.     //    file tree that contains information for the about box. The tree can be anywhere,
  919.     //    just make sure that the FSSpec is set and passed to the AboutBox. The example
  920.     //    below sets the FSSpec to the same directory (folder) as this application; you would
  921.     //    perhaps do something different.
  922.  
  923.     error = FSMakeFSSpec (    vRefNum,
  924.                             dirID, 
  925.                             "\p:ABox info...",
  926.                             &homeSpec);
  927.  
  928.     switch (aboxTypes)
  929.     {
  930.         case    1:
  931.         case    5:
  932.         case    9:
  933.                     modality = kABoxModal;
  934.                     break;
  935.         case    2:
  936.         case    6:
  937.         case    10:
  938.                     modality = kABoxMoveableModal;
  939.                     break;
  940.         case    3:
  941.         case    7:
  942.         case    11:
  943.                     modality = kABoxModeless;
  944.                     break;
  945.     } // end switch block
  946.     
  947.     switch (aboxTypes / 4)
  948.     {
  949.         case    0: splashTime = kABoxNoSplash; break;
  950.         case    1: splashTime = kABoxWaitForClickSplash; break;
  951.         case    2: splashTime = kABoxWaitForApplicationSplash; gDoSomethingSilly = true; break;
  952.         case    3: splashTime = 5 /* seconds */; break;
  953.     } // end switch block
  954.     
  955.     // kill all the menus except the Test, Help, and App
  956.     if (modality != kABoxModeless)
  957.     {
  958.         DisableItem(gAppleMenuHandle, 0);
  959.         DisableItem(gFileMenuHandle, 0);
  960.         DisableItem(gEditMenuHandle, 0);
  961.         DisableItem(gToolMenuHandle, 0);
  962.         DisableItem(gDebuggerMenuHandle, 0);
  963.         DrawMenuBar();
  964.     } // end if block
  965.     
  966.     if (gABox)
  967.     {
  968.         CloseTheABox();
  969.         delete gABox;
  970.     } // end if block
  971.     
  972.     gABox = new ABox;
  973.     if (gABox)
  974.     {
  975.         error = PrepareABox (gABox, splashTime, modality, &homeSpec);
  976.         if (error == noErr)
  977.             error = gABox->Draw(NULL);
  978.         if (error == noErr)
  979.             error = gABox->Event(NULL);
  980.     }
  981.     
  982. }
  983.  
  984.  
  985. /*=============================== PrepareABox ================================*/
  986. OSErr    PrepareABox (ABox *abox, 
  987.                     ABoxSplashTimeType splashTimeSeconds, 
  988.                     ABoxModalIndicator modality, 
  989.                     FSSpecPtr homeSpec)
  990. {
  991.     OSErr                error = noErr;
  992.     
  993.     StringHandle        nameAndVersion = (StringHandle)NewHandleClear(sizeof(Str255));
  994.     StringHandle        modalityString = (StringHandle)NewHandleClear(sizeof(Str255));
  995.     ABIndex                firstItem = 1;
  996.     ABoxTextFontType    textFace = 0;
  997.     ABoxTextFontType    textSize = 9;
  998.     ABoxTextFontType    textFont = geneva;
  999.     
  1000.     UpdateWindowUPP        windowUpdater = NewWindowUpdateProc(HandleUpdate);
  1001.     
  1002.     //    begin here...
  1003.     
  1004.     if (!abox)
  1005.         return paramErr;
  1006.         
  1007.     error = abox->SetProperty (kABoxModalIndicator, &modality, kABoxModalIndicatorSize);
  1008.     error = abox->SetProperty (kABoxSplashTimeSeconds, &splashTimeSeconds, sizeof(splashTimeSeconds));
  1009.     error = abox->SetProperty (kABoxHomeFolder, homeSpec, kABoxHomeFolderSize);
  1010.     error = abox->SetProperty (kABoxAppResFile, &gAppResFile, sizeof(gAppResFile));
  1011.     error = abox->SetProperty (kABoxFirstTopicNumber, &firstItem, sizeof(firstItem));
  1012.     error = abox->SetProperty (kABoxFirstSlideNumber, &firstItem, sizeof(firstItem));
  1013.     error = abox->SetProperty (kABoxTextFont, &textFont, sizeof(textFont));
  1014.     error = abox->SetProperty (kABoxTextFace, &textFace, sizeof(textFace));
  1015.     error = abox->SetProperty (kABoxTextSize, &textSize, sizeof(textSize));
  1016.     error = abox->SetProperty (kABoxUpdater, &windowUpdater, kABoxUpdaterSize);
  1017.     
  1018.     switch (splashTimeSeconds)
  1019.     {
  1020.         case    kABoxNoSplash:
  1021.                 SetString (nameAndVersion, "\pNo splash screen.");
  1022.                 break;
  1023.         case    kABoxWaitForClickSplash:
  1024.                 SetString (nameAndVersion, "\pWait for click splash screen...please click.");
  1025.                 break;
  1026.         case    kABoxWaitForApplicationSplash:
  1027.                 SetString (nameAndVersion, "\pApplication controlled splash screen...");
  1028.                 break;
  1029.         default:
  1030.                 SetString (nameAndVersion, "\pTimed splash screen...just watch...");
  1031.                 break;
  1032.     } // end switch block
  1033.     
  1034.     switch (modality)
  1035.     {
  1036.         case    kABoxModal:
  1037.                 SetString (modalityString, "\pModal Dialog");
  1038.                 break;
  1039.         case    kABoxModeless:
  1040.                 SetString (modalityString, "\pModeless Dialog");
  1041.                 break;
  1042.         case    kABoxMoveableModal:
  1043.                 SetString (modalityString, "\pMoveable Modal Dialog");
  1044.                 break;
  1045.         default:
  1046.                 SetString (modalityString, "\pClueless Dialog");
  1047.                 break;
  1048.     } // end switch block
  1049.     
  1050.     error = HandAndHand ((Handle)modalityString, (Handle)nameAndVersion);
  1051.     
  1052.     HLock ((Handle)nameAndVersion);
  1053.     error = abox->SetProperty (kABoxAppNameAndVersion, *nameAndVersion, **nameAndVersion + 1);
  1054.     HUnlock ((Handle)nameAndVersion);
  1055.     
  1056.     HLock ((Handle)modalityString);
  1057.     error = abox->SetProperty (kABoxWindowTitle, *modalityString, **modalityString + 1);
  1058.     HUnlock ((Handle)modalityString);
  1059.     
  1060.     return error;
  1061. } // end PrepareABox
  1062.  
  1063.  
  1064.  
  1065.  
  1066. /*=============================== CloseTheABox ================================*/
  1067. //
  1068. void CloseTheABox(void)
  1069. {
  1070.     OSErr    error = noErr;
  1071.     
  1072.     //    begin here...
  1073.     
  1074.     if (gABox)
  1075.     {
  1076.         error = gABox->Close();
  1077.         delete gABox;
  1078.         gABox = NULL;
  1079.     } // end if block
  1080.  
  1081.     /* turn our menus back on */
  1082.     EnableItem(gAppleMenuHandle, 0);
  1083.     EnableItem(gFileMenuHandle, 0);
  1084.     EnableItem(gEditMenuHandle, 0);
  1085.     EnableItem(gToolMenuHandle, 0);
  1086.     if (gDebuggerPresent)
  1087.         EnableItem(gDebuggerMenuHandle, 0);
  1088.     
  1089.     DrawMenuBar();
  1090.  
  1091.     gDoSomethingSilly = false;
  1092. }
  1093.  
  1094.  
  1095.  
  1096.  
  1097. //    end of file ABoxTest.c