home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 March / macformat-022.iso / Shareware City / Developers / src / out-of-phase-102-c / OutOfPhase 1.02 Source / OutOfPhase Folder / Level 1 Extensions 29Sep94 / WindowDispatcher.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-23  |  11.0 KB  |  363 lines  |  [TEXT/KAHL]

  1. /* WindowDispatcher.c */
  2. /*****************************************************************************/
  3. /*                                                                           */
  4. /*    System Dependency Library for Building Portable Software               */
  5. /*    Macintosh Version                                                      */
  6. /*    Written by Thomas R. Lawrence, 1993 - 1994.                            */
  7. /*                                                                           */
  8. /*    This file is Public Domain; it may be used for any purpose whatsoever  */
  9. /*    without restriction.                                                   */
  10. /*                                                                           */
  11. /*    This package is distributed in the hope that it will be useful,        */
  12. /*    but WITHOUT ANY WARRANTY; without even the implied warranty of         */
  13. /*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                   */
  14. /*                                                                           */
  15. /*    Thomas R. Lawrence can be reached at tomlaw@world.std.com.             */
  16. /*                                                                           */
  17. /*****************************************************************************/
  18.  
  19. #include "MiscInfo.h"
  20. #include "Audit.h"
  21. #include "Debug.h"
  22. #include "Definitions.h"
  23.  
  24. #include "WindowDispatcher.h"
  25. #include "Array.h"
  26. #include "Memory.h"
  27.  
  28.  
  29. struct GenericWindowRec
  30.     {
  31.         /* Level 0 window ID for identifying it from the event loop */
  32.         WinType*                ScreenID;
  33.         /* reference value for callbacks */
  34.         void*                        Reference;
  35.         /* callback hooks */
  36.         void                        (*WindowDoIdle)(void* Reference, MyBoolean CheckCursorFlag,
  37.                                             OrdType XLoc, OrdType YLoc, ModifierFlags Modifiers);
  38.         void                        (*WindowBecomeActive)(void* Reference);
  39.         void                        (*WindowBecomeInactive)(void* Reference);
  40.         void                        (*WindowResized)(void* Reference);
  41.         void                        (*WindowDoMouseDown)(OrdType XLoc, OrdType YLoc,
  42.                                             ModifierFlags Modifiers, void* Reference);
  43.         void                        (*WindowDoKeyDown)(unsigned char KeyCode,
  44.                                             ModifierFlags Modifiers, void* Reference);
  45.         void                        (*WindowClose)(void* Reference);
  46.         void                        (*WindowMenuSetup)(void* Reference);
  47.         void                        (*WindowDoMenuCommand)(void* Reference, MenuItemType* MenuItem);
  48.     };
  49.  
  50.  
  51. /* this is a list of all of the windows registered with us */
  52. static ArrayRec*                            TotalWindowList;
  53.  
  54. /* this contains the window that was last active.  NIL means no active window. */
  55. static GenericWindowRec*            TheActiveWindow = NIL;
  56.  
  57.  
  58. struct IdleTaskSignature
  59.     {
  60.         void                        (*IdleCallback)(void* Refcon);
  61.         void*                        IdleRefcon;
  62.     };
  63.  
  64.  
  65. /* list of installed idle tasks */
  66. static ArrayRec*                            IdleTaskList;
  67.  
  68.  
  69. /* initialize internal data structures for the window dispatch handler */
  70. MyBoolean                        InitializeWindowDispatcher(void)
  71.     {
  72.         APRINT(("+InitializeWindowDispatcher"));
  73.         TotalWindowList = NewArray();
  74.         if (TotalWindowList == NIL)
  75.             {
  76.              FailurePoint1:
  77.                 APRINT(("-InitializeWindowDispatcher failed"));
  78.                 return False;
  79.             }
  80.         IdleTaskList = NewArray();
  81.         if (IdleTaskList == NIL)
  82.             {
  83.              FailurePoint2:
  84.                 DisposeArray(TotalWindowList);
  85.                 goto FailurePoint1;
  86.             }
  87.         APRINT(("-InitializeWindowDispatcher"));
  88.         return True;
  89.     }
  90.  
  91.  
  92. /* dispose of internal data structures for the window dispatch handler */
  93. void                                ShutdownWindowDispatcher(void)
  94.     {
  95.         APRINT(("+ShutdownWindowDispatcher"));
  96.         ERROR(ArrayGetLength(TotalWindowList) != 0,PRERR(AllowResume,
  97.             "ShutdownWindowDispatcher:  some windows haven't been disposed of"));
  98.         ERROR(ArrayGetLength(IdleTaskList) != 0,PRERR(AllowResume,
  99.             "ShutdownWindowDispatcher:  some idle tasks are still installed"));
  100.         DisposeArray(TotalWindowList);
  101.         DisposeArray(IdleTaskList);
  102.         APRINT(("-ShutdownWindowDispatcher"));
  103.     }
  104.  
  105.  
  106. /* check in a new window, install callback routines, and obtain a unique identifier */
  107. GenericWindowRec*        CheckInNewWindow(WinType* ScreenID, void* Reference,
  108.                                             void (*WindowDoIdle)(void* Reference, MyBoolean CheckCursorFlag,
  109.                                                         OrdType XLoc, OrdType YLoc, ModifierFlags Modifiers),
  110.                                             void (*WindowBecomeActive)(void* Reference),
  111.                                             void (*WindowBecomeInactive)(void* Reference),
  112.                                             void (*WindowResized)(void* Reference),
  113.                                             void (*WindowDoMouseDown)(OrdType XLoc, OrdType YLoc,
  114.                                                         ModifierFlags Modifiers, void* Reference),
  115.                                             void (*WindowDoKeyDown)(unsigned char KeyCode,
  116.                                                         ModifierFlags Modifiers, void* Reference),
  117.                                             void (*WindowClose)(void* Reference),
  118.                                             void (*WindowMenuSetup)(void* Reference),
  119.                                             void (*WindowDoMenuCommand)(void* Reference,
  120.                                                         MenuItemType* MenuItem))
  121.     {
  122.         GenericWindowRec*    WindowRecord;
  123.  
  124.         EXECUTE({long Scan; for (Scan = 0; Scan < ArrayGetLength(TotalWindowList);
  125.             Scan += 1) {if (ScreenID == (*(GenericWindowRec*)ArrayGetElement(
  126.             TotalWindowList,Scan)).ScreenID){PRERR(AllowResume,
  127.             "CheckInNewWindow:  Window is already checked in");}}})
  128.         ERROR((WindowDoIdle == NIL) || (WindowBecomeActive == NIL)
  129.             || (WindowBecomeInactive == NIL) || (WindowResized == NIL)
  130.             || (WindowDoMouseDown == NIL) || (WindowDoKeyDown == NIL)
  131.             || (WindowClose == NIL) || (WindowMenuSetup == NIL)
  132.             || (WindowDoMenuCommand == NIL),PRERR(ForceAbort,
  133.             "CheckInNewWindow:  a callback has not been specified"));
  134.         CheckPtrExistence(ScreenID);
  135.         WindowRecord = (GenericWindowRec*)AllocPtrCanFail(sizeof(GenericWindowRec),
  136.             "GenericWindowRec");
  137.         if (WindowRecord != NIL)
  138.             {
  139.                 if (ArrayAppendElement(TotalWindowList,WindowRecord))
  140.                     {
  141.                         WindowRecord->ScreenID = ScreenID;
  142.                         WindowRecord->Reference = Reference;
  143.                         WindowRecord->WindowDoIdle = WindowDoIdle;
  144.                         WindowRecord->WindowBecomeActive = WindowBecomeActive;
  145.                         WindowRecord->WindowBecomeInactive = WindowBecomeInactive;
  146.                         WindowRecord->WindowResized = WindowResized;
  147.                         WindowRecord->WindowDoMouseDown = WindowDoMouseDown;
  148.                         WindowRecord->WindowDoKeyDown = WindowDoKeyDown;
  149.                         WindowRecord->WindowClose = WindowClose;
  150.                         WindowRecord->WindowMenuSetup = WindowMenuSetup;
  151.                         WindowRecord->WindowDoMenuCommand = WindowDoMenuCommand;
  152.                     }
  153.                  else
  154.                     {
  155.                         ReleasePtr((char*)WindowRecord);
  156.                         WindowRecord = NIL;
  157.                     }
  158.             }
  159.         return WindowRecord;
  160.     }
  161.  
  162.  
  163. /* notify the window dispatcher that this window is no longer with us */
  164. void                                CheckOutDyingWindow(GenericWindowRec* Window)
  165.     {
  166.         /* if the active window is dying, then clear the active window register */
  167.         if (TheActiveWindow == Window)
  168.             {
  169.                 TheActiveWindow = NIL;
  170.             }
  171.         /* delete element from array.  causes error if window isn't in list */
  172.         ArrayDeleteElement(TotalWindowList,ArrayFindElement(TotalWindowList,Window));
  173.         /* dump the window record */
  174.         ReleasePtr((char*)Window);
  175.     }
  176.  
  177.  
  178. /* get the identifier for the currently active window */
  179. GenericWindowRec*        GetCurrentWindowID(void)
  180.     {
  181.         return TheActiveWindow;
  182.     }
  183.  
  184.  
  185. /* internal routine to deal with Level 0 window IDs */
  186. static GenericWindowRec*    MapWindowIDToRecord(WinType* ScreenID)
  187.     {
  188.         long                                    Scan;
  189.  
  190.         for (Scan = 0; Scan < ArrayGetLength(TotalWindowList); Scan += 1)
  191.             {
  192.                 GenericWindowRec*            Window;
  193.  
  194.                 Window = (GenericWindowRec*)ArrayGetElement(TotalWindowList,Scan);
  195.                 if (Window->ScreenID == ScreenID)
  196.                     {
  197.                         CheckPtrExistence(Window);
  198.                         return (GenericWindowRec*)ArrayGetElement(TotalWindowList,Scan);
  199.                     }
  200.             }
  201.         EXECUTE(PRERR(ForceAbort,"MapWindowIDToRecord:  Couldn't find window"));
  202.     }
  203.  
  204.  
  205. void                                DispatchDoIdle(WinType* Window, MyBoolean CheckCursorFlag,
  206.                                             OrdType XLoc, OrdType YLoc, ModifierFlags Modifiers)
  207.     {
  208.         if (Window != NIL)
  209.             {
  210.                 GenericWindowRec*        OtherWindow;
  211.  
  212.                 OtherWindow = MapWindowIDToRecord(Window);
  213.                 (*(OtherWindow->WindowDoIdle))(OtherWindow->Reference,
  214.                     CheckCursorFlag,XLoc,YLoc,Modifiers);
  215.             }
  216.         DispatchIdleTaskCallback();
  217.     }
  218.  
  219.  
  220. void                                DispatchActiveWindowJustChanged(WinType* NewWindow)
  221.     {
  222.         /* deactivate the current window */
  223.         if (TheActiveWindow != NIL)
  224.             {
  225.                 (*(TheActiveWindow->WindowBecomeInactive))(TheActiveWindow->Reference);
  226.                 TheActiveWindow = NIL;
  227.             }
  228.         /* find the new active window (if there are any windows) */
  229.         if (NewWindow != NIL)
  230.             {
  231.                 TheActiveWindow = MapWindowIDToRecord(NewWindow);
  232.             }
  233.         /* activate it (if there is one) */
  234.         if (TheActiveWindow != NIL)
  235.             {
  236.                 (*(TheActiveWindow->WindowBecomeActive))(TheActiveWindow->Reference);
  237.             }
  238.     }
  239.  
  240.  
  241. void                                DispatchWindowJustResized(WinType* Window)
  242.     {
  243.         if (Window != NIL)
  244.             {
  245.                 GenericWindowRec*        OtherWindow;
  246.  
  247.                 OtherWindow = MapWindowIDToRecord(Window);
  248.                 (*(OtherWindow->WindowResized))(OtherWindow->Reference);
  249.             }
  250.     }
  251.  
  252.  
  253. void                                DispatchDoMouseDown(WinType* Window, OrdType XLoc, OrdType YLoc,
  254.                                             ModifierFlags Modifiers)
  255.     {
  256.         if (Window != NIL)
  257.             {
  258.                 GenericWindowRec*        OtherWindow;
  259.  
  260.                 OtherWindow = MapWindowIDToRecord(Window);
  261.                 (*(OtherWindow->WindowDoMouseDown))(XLoc,YLoc,Modifiers,OtherWindow->Reference);
  262.             }
  263.     }
  264.  
  265.  
  266. void                                DispatchDoKeyDown(WinType* Window, unsigned char KeyCode,
  267.                                             ModifierFlags Modifiers)
  268.     {
  269.         if (Window != NIL)
  270.             {
  271.                 GenericWindowRec*        OtherWindow;
  272.  
  273.                 OtherWindow = MapWindowIDToRecord(Window);
  274.                 (*(OtherWindow->WindowDoKeyDown))(KeyCode,Modifiers,OtherWindow->Reference);
  275.             }
  276.     }
  277.  
  278.  
  279. void                                DispatchCloseWindow(WinType* Window)
  280.     {
  281.         if (Window != NIL)
  282.             {
  283.                 GenericWindowRec*        OtherWindow;
  284.  
  285.                 OtherWindow = MapWindowIDToRecord(Window);
  286.                 (*(OtherWindow->WindowClose))(OtherWindow->Reference);
  287.             }
  288.     }
  289.  
  290.  
  291. void                                DispatchMenuStarting(WinType* Window)
  292.     {
  293.         if (Window != NIL)
  294.             {
  295.                 GenericWindowRec*        OtherWindow;
  296.  
  297.                 OtherWindow = MapWindowIDToRecord(Window);
  298.                 (*(OtherWindow->WindowMenuSetup))(OtherWindow->Reference);
  299.             }
  300.     }
  301.  
  302.  
  303. void                                DispatchProcessMenuCommand(WinType* Window, MenuItemType* MenuItem)
  304.     {
  305.         if (Window != NIL)
  306.             {
  307.                 GenericWindowRec*        OtherWindow;
  308.  
  309.                 OtherWindow = MapWindowIDToRecord(Window);
  310.                 (*(OtherWindow->WindowDoMenuCommand))(OtherWindow->Reference,MenuItem);
  311.             }
  312.     }
  313.  
  314.  
  315. /* install an idle task to be executed whenever an idle event occurs */
  316. IdleTaskSignature*    DispatchInstallIdleTask(void (*Proc)(void* Refcon), void* Refcon)
  317.     {
  318.         IdleTaskSignature*    Signature;
  319.  
  320.         Signature = (IdleTaskSignature*)AllocPtrCanFail(sizeof(IdleTaskSignature),
  321.             "IdleTaskSignature");
  322.         if (Signature == NIL)
  323.             {
  324.              FailurePoint1:
  325.                 return NIL;
  326.             }
  327.         Signature->IdleCallback = Proc;
  328.         Signature->IdleRefcon = Refcon;
  329.         if (!ArrayAppendElement(IdleTaskList,Signature))
  330.             {
  331.              FailurePoint2:
  332.                 ReleasePtr((char*)Signature);
  333.                 goto FailurePoint1;
  334.             }
  335.         return Signature;
  336.     }
  337.  
  338.  
  339. /* remove an idle task */
  340. void                                DispatchRemoveIdleTask(IdleTaskSignature* Signature)
  341.     {
  342.         CheckPtrExistence(Signature);
  343.         ArrayDeleteElement(IdleTaskList,ArrayFindElement(IdleTaskList,Signature));
  344.         ReleasePtr((char*)Signature);
  345.     }
  346.  
  347.  
  348. /* dispatch a callback to all installed idle tasks */
  349. void                                DispatchIdleTaskCallback(void)
  350.     {
  351.         long                            Scan;
  352.  
  353.         Scan = 0;
  354.         while (Scan < ArrayGetLength(IdleTaskList))
  355.             {
  356.                 IdleTaskSignature*    Signature;
  357.  
  358.                 Signature = (IdleTaskSignature*)ArrayGetElement(IdleTaskList,Scan);
  359.                 (*(Signature->IdleCallback))(Signature->IdleRefcon);
  360.                 Scan += 1;
  361.             }
  362.     }
  363.