home *** CD-ROM | disk | FTP | other *** search
/ Mac Mania 2 / MacMania 2.toast / Demo's / Tools&Utilities / Programming / MPS disk 1.0.1 / Chapter 04 / Standard Stuff.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-05-19  |  22.4 KB  |  751 lines  |  [TEXT/KAHL]

  1. #include "Standard Stuff.h"
  2. #include "Neat Stuff.h"
  3. #include "Traps.h"
  4.  
  5. /*******************************************************************************
  6.  
  7.     The “g” prefix is used to emphasize that a variable is global.
  8.  
  9. *******************************************************************************/
  10.  
  11. SysEnvRec    gMac;                /*    gMac is used to hold the result of a
  12.                                     SysEnvirons call. This makes it convenient
  13.                                     for any routine to check the environment. */
  14.  
  15. Boolean        gQuit;                /*    We set this to TRUE when the user selects
  16.                                     Quit from the File menu. Our main event
  17.                                     loop exists when gQuit is TRUE. */
  18.  
  19. Boolean        gInBackground;        /*    gInBackground is maintained by our osEvent
  20.                                     handling routines. Any part of the program
  21.                                     can check it to find out if it is currently
  22.                                     in the background. */
  23.  
  24. Boolean        gInModalState;        /*    Set to true whenever we want to treat the
  25.                                     frontmost window modally. This Boolean
  26.                                     alters our mouse-down handling routine and
  27.                                     our menu setup routine. +++ */
  28.  
  29. /*******************************************************************************
  30.  
  31.     Define HiWrd and LoWrd macros for efficiency.
  32.  
  33. *******************************************************************************/
  34.  
  35. #define HiWrd(aLong)    (((aLong) >> 16) & 0xFFFF)
  36. #define LoWrd(aLong)    ((aLong) & 0xFFFF)
  37.  
  38.  
  39. /*******************************************************************************
  40.  
  41.     main
  42.  
  43.     Entry point for our program. We initialize the toolbox, make sure we are
  44.     running on a sufficiently studly machine, and put up the menubar. Finally,
  45.     we start polling for events and handling them by entering our main event
  46.     loop.
  47.  
  48. *******************************************************************************/
  49. main()
  50. {
  51.     /*    If you have stack requirements that differ from the default,
  52.         then you could use SetApplLimit to increase StackSpace at
  53.         this point, before calling MaxApplZone. */
  54.  
  55.     MaxApplZone();                    /* Expand the heap so code segments load
  56.                                        at the top */
  57.     InitToolbox();                    /* Initialize the program */
  58.     MainEventLoop();                /* Call the main event loop */
  59. }
  60.  
  61.  
  62. /*******************************************************************************
  63.  
  64.     InitToolbox
  65.  
  66.     Set up the whole world, including global variables, Toolbox managers, and
  67.     menus.
  68.  
  69. *******************************************************************************/
  70. void InitToolbox()
  71. {
  72.     Handle        menuBar;
  73.     EventRecord event;
  74.     short        count;
  75.  
  76.     gInBackground = FALSE;
  77.     gQuit = FALSE;
  78.  
  79.     InitGraf((Ptr) &qd.thePort);
  80.     InitFonts();
  81.     InitWindows();
  82.     InitMenus();
  83.     TEInit();
  84.     InitDialogs(NIL);
  85.     InitCursor();
  86.  
  87.     /*    This next bit of code waits until MultiFinder brings our application
  88.         to the front. This gives us a better effect if we open a window at
  89.         startup. */
  90.  
  91.     for (count = 1; count <= 3; ++count)
  92.         EventAvail(everyEvent, &event);
  93.  
  94.     SysEnvirons(curSysEnvVers, &gMac);
  95.  
  96.     if (gMac.machineType < 0)
  97.         DeathAlert(errWimpyROMs);
  98.  
  99.     if (gMac.systemVersion < 0x0600)
  100.         DeathAlert(errWimpySystem);
  101.  
  102.     if (!TrapExists(_WaitNextEvent))
  103.         DeathAlert(errWeirdSystem);
  104.  
  105.     menuBar = GetNewMBar(rMenuBar);            /* Read menus into menu bar */
  106.     if ( menuBar == NIL )
  107.          DeathAlert(errNoMenuBar);
  108.     SetMenuBar(menuBar);                    /* Install menus */
  109.     DisposHandle(menuBar);
  110.     AddResMenu(GetMHandle(mApple), 'DRVR');    /* Add DA names to Apple menu */
  111.     AdjustMenus();
  112.     DrawMenuBar();
  113. }
  114.  
  115.  
  116. /*******************************************************************************
  117.  
  118.     MainEventLoop
  119.  
  120.     Get events forever, and handle them by calling HandleEvent. First, call
  121.     DoAdjustCursor to set our cursor shape, and to set the cursor region. We
  122.     then call WaitNextEvent() to get the event. This is OK, because we know
  123.     we’re running on System 6.0 or later by this time. If we got an event, we
  124.     handle it by calling HandleEvent(). But before doing that, we call
  125.     DoAdjustCursor again in case our application had fallen asleep under
  126.     MultiFinder.
  127.  
  128. *******************************************************************************/
  129. void MainEventLoop()
  130. {
  131.     RgnHandle    cursorRgn;
  132.     Boolean        gotEvent;
  133.     EventRecord    event;
  134.     Point        mouse;
  135.  
  136.     long        sleepyTime;                                            /* +++ */
  137.     Boolean        passToDialog;                                        /* +++ */
  138.     DialogPtr    theDialog;                                            /* +++ */
  139.     short        itemHit;                                            /* +++ */
  140.     Boolean        itemWasHit;                                            /* +++ */
  141.  
  142.     cursorRgn = NIL;
  143.     while ( !gQuit ) {
  144.         sleepyTime = (gPeriodicTask ? 1 : MAXLONG);                    /* +++ */
  145.         gotEvent = WaitNextEvent(everyEvent, &event, sleepyTime, cursorRgn);    /* +++ */
  146.  
  147.         //
  148.         // Note: all of the stuff from here to the check of "gotEvent"
  149.         // is just so we can handle modeless dialogs. It involves some
  150.         // pretty hairy logic and, even so, still doesn't handle things
  151.         // like hitting <Return> or <Command-.>. In light of this, some
  152.         // people recomment _against_ using the Dialog Manager for
  153.         // modeless dialogs, and suggest that you simple handle dialogs
  154.         // just as you would any other window. In an extreme, yet
  155.         // superlative, example of this, MacApp implements all of its
  156.         // modal and modeless dialogs using its own code.
  157.         //
  158.         // Systems before 7.0 would corrupt low-memory if you called
  159.         // IsDialogEvent() without any open windows.
  160.         //
  161.  
  162.         passToDialog = TRUE;                                        /* +++ */
  163.         if ((FrontWindow() == NIL)                                    /* +++ */
  164.             || (event.what == diskEvt)                                /* +++ */
  165.             || ((event.what == keyDown) && ((event.modifiers & cmdKey) != 0)))    /* +++ */
  166.                 passToDialog = FALSE;                                /* +++ */
  167.  
  168.         if (passToDialog) {                                            /* +++ */
  169.             if (IsDialogEvent(&event)) {                            /* +++ */
  170.                 itemWasHit =  DialogSelect(&event, &theDialog, &itemHit);    /* +++ */
  171.                 if (itemWasHit) {                                    /* +++ */
  172.                     DoDialogHit(theDialog, itemHit);                /* +++ */
  173.                 }                                                    /* +++ */
  174.                 gotEvent = FALSE;                                    /* +++ */
  175.             }                                                        /* +++ */
  176.         }                                                            /* +++ */
  177.  
  178.         if ( gotEvent ) {
  179.             HandleEvent(&event);
  180.         }
  181.         if (gPeriodicTask)                                            /* +++ */
  182.             DoMainLoopTasks();                                        /* +++ */
  183.     }
  184. }
  185.  
  186.  
  187. /*******************************************************************************
  188.  
  189.     HandleEvent
  190.  
  191.     Do the right thing for an event. Determine what kind of event it is, and
  192.     call the appropriate routines.
  193.  
  194. *******************************************************************************/
  195. void HandleEvent(EventRecord *event)
  196. {
  197.     switch ( event->what ) {
  198.         case mouseDown:
  199.             HandleMouseDown(event);
  200.             break;
  201.         case keyDown:
  202.         case autoKey:
  203.             HandleKeyPress(event);
  204.             break;
  205.         case activateEvt:
  206.             HandleActivate(event);
  207.             break;
  208.         case updateEvt:
  209.             HandleUpdate(event);
  210.             break;
  211.         case diskEvt:
  212.             HandleDiskInsert(event);
  213.             break;
  214.         case osEvt:
  215.             HandleOSEvent(event);
  216.             break;
  217.     }
  218. }
  219.  
  220.  
  221. /*******************************************************************************
  222.  
  223.     HandleActivate
  224.  
  225.     This is called when a window is activated or deactivated. In this sample,
  226.     the Window Manager’s handling of activate and deactivate events is
  227.     sufficient. Other applications may have TextEdit records, controls, lists,
  228.     etc., to activate/deactivate.
  229.  
  230. *******************************************************************************/
  231. void HandleActivate(EventRecord *event)
  232. {
  233.     WindowPtr    theWindow;
  234.     Boolean        becomingActive;
  235.  
  236.     theWindow = (WindowPtr) event->message;
  237.     becomingActive = (event->modifiers & activeFlag) != 0;
  238.     if ( IsAppWindow(theWindow) ) {
  239.         DrawGrowIcon(theWindow);
  240.         /* DoActivateWindow(theWindow, becomingActive) */;
  241.     }
  242. }
  243.  
  244.  
  245. /*******************************************************************************
  246.  
  247.     HandleDiskInsert
  248.  
  249.     Called when we get a disk inserted event. Check the upper word of the
  250.     event message; if it’s non-zero, then a bad disk was inserted, and it
  251.     needs to be formatted.
  252.  
  253. *******************************************************************************/
  254. void HandleDiskInsert(EventRecord *event)
  255. {
  256.     Point    aPoint = {100, 100};
  257.  
  258.     if ( HiWrd(event->message) != noErr ) {
  259.         (void) DIBadMount(aPoint, event->message);
  260.     }
  261. }
  262.  
  263.  
  264. /*******************************************************************************
  265.  
  266.     HandleKeyPress
  267.  
  268.     The user pressed a key. What are you going to do about it?
  269.  
  270. *******************************************************************************/
  271. void HandleKeyPress(EventRecord *event)
  272. {
  273.     char    key;
  274.  
  275.     key = event->message & charCodeMask;
  276.     if ( event->modifiers & cmdKey ) {        /* Command key down? */
  277.         AdjustMenus();                        /* Enable/disable/check menu items properly */
  278.         HandleMenuCommand(MenuKey(key));
  279.     } else {
  280.         /* DoKeyPress(event) */;
  281.     }
  282. }
  283.  
  284.  
  285. /*******************************************************************************
  286.  
  287.     HandleMouseDown
  288.  
  289.     Called to handle mouse clicks. The user could have clicked anywhere, so
  290.     let’s first find out where by calling FindWindow. That returns a number
  291.     indicating where in the screen the mouse was clicked. “switch” on that
  292.     number and call the appropriate routine.
  293.  
  294.     +++ Note our additional check for gModalState in this routine. This is
  295.     +++ one of the few places we have to make this check in order to support
  296.     +++ movable-modal windows (or even plain old modal dialogs if we wanted
  297.     +++ to manage them by hand). The other place would be in our menu setup
  298.     +++ routines.
  299.  
  300. *******************************************************************************/
  301. void HandleMouseDown(EventRecord *event)
  302. {
  303.     long        newSize;
  304.     Rect        growRect;
  305.     WindowPtr    theWindow;
  306.     short        part = FindWindow(event->where, &theWindow);
  307.  
  308.     if (gInModalState && (theWindow != FrontWindow()) && (part != inMenuBar)) {    /* +++ */
  309.         SysBeep(5);                                                                /* +++ */
  310.         return;                                                                    /* +++ */
  311.     }                                                                            /* +++ */
  312.  
  313.     switch ( part ) {
  314.         case inMenuBar:                /* Process a mouse menu command (if any) */
  315.             AdjustMenus();
  316.             HandleMenuCommand(MenuSelect(event->where));
  317.             break;
  318.         case inSysWindow:            /* Let the system handle the mouseDown */
  319.             SystemClick(event, theWindow);
  320.             break;
  321.         case inContent:
  322.             if ( theWindow != FrontWindow() )
  323.                 SelectWindow(theWindow);
  324.             else
  325.                 /* DoContentClick(event, theWindow) */;
  326.             break;
  327.         case inDrag:                /* Pass screenBits.bounds to get all gDevices */
  328.             DragWindow(theWindow, event->where, &qd.screenBits.bounds);
  329.             break;
  330.         case inGrow:
  331.             growRect = qd.screenBits.bounds;
  332.             growRect.top = growRect.left = 80;        /* Arbitrary minimum size. */
  333.             newSize = GrowWindow(theWindow, event->where, &growRect);
  334.             if (newSize != 0) {
  335.                 InvalidateScrollbars(theWindow);
  336.                 SizeWindow(theWindow, LoWrd(newSize), HiWrd(newSize), TRUE);
  337.                 InvalidateScrollbars(theWindow);
  338.             }
  339.             break;
  340.         case inGoAway:
  341.             if (TrackGoAway(theWindow, event->where))  {
  342.                 CloseAnyWindow(theWindow);
  343.             }
  344.             break;
  345.         case inZoomIn:
  346.         case inZoomOut:
  347.             if (TrackBox(theWindow, event->where, part)) {
  348.                 SetPort(theWindow);
  349.                 EraseRect(&theWindow->portRect);
  350.                 ZoomWindow(theWindow, part, TRUE);
  351.                 InvalRect(&theWindow->portRect);
  352.             }
  353.             break;
  354.     }
  355. }
  356.  
  357.  
  358. /*******************************************************************************
  359.  
  360.     HandleOSEvent
  361.  
  362.     Deal with OSEvents (formerly, app4Events). These are message that
  363.     MultiFinder -- known as the Process Manager under System 7.0 -- sends to
  364.     us. Here, we deal with suspend and resume message.
  365.  
  366. *******************************************************************************/
  367. void HandleOSEvent(EventRecord *event)
  368. {
  369.     switch ((event->message >> 24) & 0x00FF) {        /* High byte of message */
  370.         case suspendResumeMessage:
  371.  
  372.             /*    In our SIZE resource, we say that we are MultiFinder aware.
  373.                 This means that we take on the responsibility of activating
  374.                 and deactivating our own windows on suspend/resume events. */
  375.  
  376.             gInBackground = (event->message & resumeFlag) == 0;
  377.             if (FrontWindow()) {
  378.                 DrawGrowIcon(FrontWindow());
  379.                 /* DoActivateWindow(FrontWindow(), !gInBackground); */
  380.             }
  381.             break;
  382.         case mouseMovedMessage:
  383.             break;
  384.     }
  385. }
  386.  
  387.  
  388. /*******************************************************************************
  389.  
  390.     HandleUpdate
  391.  
  392.     This is called when an update event is received for a window. It calls
  393.     DoUpdateWindow to draw the contents of an application window. As an
  394.     efficiency measure that does not have to be followed, it calls the drawing
  395.     routine only if the visRgn is non-empty. This will handle situations where
  396.     calculations for drawing or drawing itself is very time-consuming.
  397.  
  398. *******************************************************************************/
  399. void HandleUpdate(EventRecord *event)
  400. {
  401.     WindowPtr    theWindow = (WindowPtr) event->message;
  402.     if ( IsAppWindow(theWindow) ) {
  403.         BeginUpdate(theWindow);                /* This sets up the visRgn */
  404.         if (!EmptyRgn(theWindow->visRgn)) {    /* Draw if updating needs to be done */
  405.             SetPort(theWindow);
  406.             EraseRgn(theWindow->visRgn);
  407.             /* DoUpdateWindow(event) */;
  408.             DrawGrowIcon(theWindow);
  409.         }
  410.         EndUpdate(theWindow);
  411.     }
  412. }
  413.  
  414.  
  415. /*******************************************************************************
  416.  
  417.     AdjustMenus
  418.  
  419.     Enable and disable menus based on the current state. The user can only
  420.     select enabled menu items. We set up all the menu items before calling
  421.     MenuSelect or MenuKey, since these are the only times that a menu item can
  422.     be selected. Note that MenuSelect is also the only time the user will see
  423.     menu items. This approach to deciding what enable/disable state a menu
  424.     item has the advantage of concentrating all the decision-making in one
  425.     routine, as opposed to being spread throughout the application. Other
  426.     application designs may take a different approach that is just as valid.
  427.  
  428. *******************************************************************************/
  429. void AdjustMenus()
  430. {
  431.     WindowPtr    window;
  432.     MenuHandle    menu;
  433.  
  434.     if (!gInModalState) {                                            /* +++ */
  435.         window = FrontWindow();
  436.  
  437.         menu = GetMHandle(mFile);
  438.         EnableItem(menu, 0);                                        /* +++ */
  439.         if ( window != NIL )
  440.             EnableItem(menu, iClose);
  441.         else
  442.             DisableItem(menu, iClose);
  443.  
  444.         menu = GetMHandle(mEdit);
  445.         if ( IsDAWindow(window) ) {        /* A desk accessory might need the edit menu… */
  446.             EnableItem(menu, 0);                                    /* +++ */
  447.             EnableItem(menu, iUndo);
  448.             EnableItem(menu, iCut);
  449.             EnableItem(menu, iCopy);
  450.             EnableItem(menu, iClear);
  451.             EnableItem(menu, iPaste);
  452.         } else {                        /* …but we don’t use it */
  453.             DisableItem(menu, 0);                                    /* +++ */
  454.             DisableItem(menu, iUndo);
  455.             DisableItem(menu, iCut);
  456.             DisableItem(menu, iCopy);
  457.             DisableItem(menu, iClear);
  458.             DisableItem(menu, iPaste);
  459.         }
  460.  
  461.         menu = GetMHandle(mDialog);                                    /* +++ */
  462.         EnableItem(menu, 0);                                        /* +++ */
  463.  
  464.     } else {                                                        /* +++ */
  465.  
  466.         menu = GetMHandle(mFile);                                    /* +++ */
  467.         DisableItem(menu, 0);                                        /* +++ */
  468.  
  469.         menu = GetMHandle(mEdit);                                    /* +++ */
  470.         DisableItem(menu, 0);                                        /* +++ */
  471.  
  472.         menu = GetMHandle(mDialog);                                    /* +++ */
  473.         DisableItem(menu, 0);                                        /* +++ */
  474.     }                                                                /* +++ */
  475.     DrawMenuBar();
  476. }
  477.  
  478.  
  479. /*******************************************************************************
  480.  
  481.     HandleMenuCommand
  482.  
  483.     This is called when an item is chosen from the menu bar (after calling
  484.     MenuSelect or MenuKey). It performs the right operation for each command.
  485.     It is good to have both the result of MenuSelect and MenuKey go to one
  486.     routine like this to keep everything organized.
  487.  
  488. *******************************************************************************/
  489. void HandleMenuCommand(menuResult)
  490.     long        menuResult;
  491. {
  492.     short        menuID;                /* The resource ID of the selected menu */
  493.     short        menuItem;            /* The item number of the selected menu */
  494.     Str255        daName;
  495.  
  496.     menuID = HiWrd(menuResult);
  497.     menuItem = LoWrd(menuResult);
  498.     switch ( menuID ) {
  499.         case mApple:
  500.             switch ( menuItem ) {
  501.                 case iAbout:
  502.                     (void) Alert(rAboutAlert, NIL);
  503.                     break;
  504.                 default:            /* All non-About items in this menu are DAs */
  505.                     GetItem(GetMHandle(mApple), menuItem, daName);
  506.                     (void) OpenDeskAcc(daName);
  507.                     break;
  508.             }
  509.             break;
  510.         case mFile:
  511.             switch ( menuItem ) {
  512.                 case iNew:
  513.                     /* DoNewWindow(); */
  514.                     break;
  515.                 case iClose:
  516.                     CloseAnyWindow(FrontWindow());
  517.                     break;
  518.                 case iQuit:
  519.                     gQuit = TRUE;
  520.                     break;
  521.             }
  522.             break;
  523.         case mEdit:
  524.             switch (menuItem) {
  525.                 /* Call SystemEdit for DA editing & MultiFinder */
  526.                 /* since we don’t do any Editing */
  527.                 case iUndo:
  528.                 case iCut:
  529.                 case iCopy:
  530.                 case iPaste:
  531.                 case iClear:
  532.                     (void) SystemEdit(menuItem-1);
  533.                     break;
  534.             }
  535.             break;
  536.         case mDialog:                                                /* +++ */
  537.             switch ( menuItem ) {                                    /* +++ */
  538.                 case iModalDialog:                                    /* +++ */
  539.                     DoMusicMaker();                                    /* +++ */
  540.                     break;                                            /* +++ */
  541.                 case iModelessDialog:                                /* +++ */
  542.                     ShowModeless();                                    /* +++ */
  543.                     break;                                            /* +++ */
  544.                 case iMovableModalDialog:                            /* +++ */
  545.                     StartMovable();                                    /* +++ */
  546.                     break;                                            /* +++ */
  547.             }                                                        /* +++ */
  548.             break;                                                    /* +++ */
  549.     }
  550.     HiliteMenu(0);        /* Unhighlight what MenuSelect or MenuKey hilited */
  551. }
  552.  
  553.  
  554. /*******************************************************************************
  555.  
  556.     CloseAnyWindow
  557.  
  558.     Close the given window in a manner appropriate for that window. If the
  559.     window belongs to a DA, we call CloseDeskAcc. For dialogs, we simply hide
  560.     the window. If we had any document windows, we would probably call either
  561.     DisposeWindow or CloseWindow after disposing of any document data and/or
  562.     controls.
  563.  
  564. *******************************************************************************/
  565. void CloseAnyWindow(WindowPtr window)
  566. {
  567.     if (IsDAWindow(window)) {
  568.         CloseDeskAcc( ( (WindowPeek) window )->windowKind );
  569.     } else if (IsDialogWindow(window)) {
  570.         HideWindow(window);
  571.     } else if (IsAppWindow(window)) {
  572.         /* Do something significant for document windows. */
  573.     }
  574. }
  575.  
  576.  
  577. /*******************************************************************************
  578.  
  579.     DeathAlert
  580.  
  581.     Display an alert that tells the user an error occurred, then exit the
  582.     program. This routine is used as an ultimate bail-out for serious errors
  583.     that prohibit the continuation of the application. The error number is
  584.     used to index an 'STR#' resource so that a relevant message can be
  585.     displayed.
  586.  
  587. *******************************************************************************/
  588. void DeathAlert(short errNumber)
  589. {
  590.     short        itemHit;
  591.     Str255        theMessage;
  592.  
  593.     SetCursor(&qd.arrow);
  594.     GetIndString(theMessage, rErrorStrings, errNumber);
  595.     ParamText(theMessage, NIL, NIL, NIL);
  596.     itemHit = StopAlert(rErrorAlert, NIL);
  597.     ExitToShell();
  598. }
  599.  
  600.  
  601. /*******************************************************************************
  602.  
  603.     IsAppWindow
  604.  
  605.     Check to see if a window belongs to the application. If the window pointer
  606.     passed was NIL, then it could not be an application window. WindowKinds
  607.     that are negative belong to the system and windowKinds less than userKind
  608.     are reserved by Apple except for windowKinds equal to dialogKind, which
  609.     mean it is a dialog.
  610.  
  611. *******************************************************************************/
  612. Boolean IsAppWindow(WindowPtr window)
  613. {
  614.     short        windowKind;
  615.  
  616.     if ( window == NIL )
  617.         return false;
  618.     else {
  619.         windowKind = ((WindowPeek) window)->windowKind;
  620.         return ((windowKind >= userKind) || (windowKind == dialogKind));
  621.     }
  622. }
  623.  
  624.  
  625. /*******************************************************************************
  626.  
  627.     IsDAWindow
  628.  
  629.     Check to see if a window belongs to a desk accessory. It belongs to a DA
  630.     if the windowKind field of the window record is negative.
  631.  
  632. *******************************************************************************/
  633. Boolean IsDAWindow(WindowPtr window)
  634. {
  635.     if ( window == NIL )
  636.         return false;
  637.     else
  638.         return ( ((WindowPeek) window)->windowKind < 0 );
  639. }
  640.  
  641.  
  642. /*******************************************************************************
  643.  
  644.     IsDialogWindow
  645.  
  646.     Check to see if a window is a dialog window. We can determine this be
  647.     checking to see if the windowKind field is equal to dialogKind.
  648.  
  649. *******************************************************************************/
  650. Boolean IsDialogWindow(WindowPtr window)
  651. {
  652.     if ( window == NIL )
  653.         return false;
  654.     else
  655.         return ( ((WindowPeek) window)->windowKind == dialogKind );
  656. }
  657.  
  658.  
  659. /*******************************************************************************
  660.  
  661.     InvalidateScrollbars
  662.  
  663.     Call InvalRect on the right and bottom edges of a window. This routine is
  664.     called during the resizing of a window to take care of the scrollbar lines
  665.     and grow icon.
  666.  
  667. *******************************************************************************/
  668. void InvalidateScrollbars(WindowPtr theWindow)
  669. {
  670.     Rect    tempRect;
  671.  
  672.     SetPort(theWindow);
  673.  
  674.     tempRect = theWindow->portRect;
  675.     tempRect.left = tempRect.right - 15;
  676.     InvalRect(&tempRect);
  677.     EraseRect(&tempRect);
  678.  
  679.     tempRect = theWindow->portRect;
  680.     tempRect.top = tempRect.bottom - 15;
  681.     InvalRect(&tempRect);
  682.     EraseRect(&tempRect);
  683. }
  684.  
  685.  
  686. /*******************************************************************************
  687.  
  688.     TrapExists
  689.  
  690.     Check to see if a given trap is implemented. The recommended approach to
  691.     see if a trap is implemented is to see if the address of the trap routine
  692.     is the same as the address of the _Unimplemented trap. However, we must
  693.     also make sure that the trap is contained in the trap table on the machine
  694.     we’re running on. Not all Macintoshes have the same sized trap tables. We
  695.     call NumToolboxTraps to find out the size of the table. If the trap we are
  696.     examining falls off the end, then we treat it as automatically being
  697.     unimplemented.
  698.  
  699. *******************************************************************************/
  700. Boolean    TrapExists(short theTrap)
  701. {
  702.     TrapType    theTrapType;
  703.  
  704.     theTrapType = GetTrapType(theTrap);
  705.     if ((theTrapType == ToolTrap) && ((theTrap &= 0x07FF) >= NumToolboxTraps()))
  706.         return false;
  707.     else
  708.         return (NGetTrapAddress(_Unimplemented, ToolTrap) !=
  709.                 NGetTrapAddress(theTrap, theTrapType));
  710. }
  711.  
  712.  
  713. /*******************************************************************************
  714.  
  715.     GetTrapType
  716.  
  717.     Check the bits of a trap number to determine its type. If bit 11 is set,
  718.     it’s a toolbox trap. Otherwise, it’s an OS trap.
  719.  
  720. *******************************************************************************/
  721. TrapType    GetTrapType(short theTrap)
  722. {
  723.     if ((theTrap & 0x0800) == 0)                    /* Per D.A. */
  724.         return (OSTrap);
  725.     else
  726.         return (ToolTrap);
  727. }
  728.  
  729.  
  730. /*******************************************************************************
  731.  
  732.     NumToolboxTraps
  733.  
  734.     Find the size of the Toolbox trap table. This can be either 0x0200 or
  735.     0x0400 bytes, depending on which Macintosh we are running on. We determine
  736.     the size by taking advantage of an anomaly of the smaller trap table: any
  737.     entries that fall beyond the end of the table are mirrored back down into
  738.     the lower part. For example, on a large table, trap numbers A86E and AA6E
  739.     correspond to different routines. However, on a small table, they
  740.     correspond to the same routine. By checking the addresses of these
  741.     routines, we can determine the size of the table.
  742.  
  743. *******************************************************************************/
  744. short    NumToolboxTraps(void)
  745. {
  746.     if (NGetTrapAddress(0xA86E, ToolTrap) == NGetTrapAddress(0xAA6E, ToolTrap))
  747.         return (0x200);
  748.     else
  749.         return (0x400);
  750. }
  751.