home *** CD-ROM | disk | FTP | other *** search
/ AppleScript - The Beta Release / AppleScript - The Beta Release.iso / Development Tools / Sample Applications / CoreSample / CoreSample Source / CoreSample.c next >
Encoding:
Text File  |  1992-11-24  |  80.8 KB  |  2,203 lines  |  [TEXT/MPS ]

  1. //----------------------------------------------------------------------------------//
  2. //                                                                                    //
  3. //    CoreSample  -      An application that is Apple Event-aware, Scripting Compatible,    //
  4. //                    and recordable. It supports the Required and Core Suite of         //
  5. //                    Apple Events, the Object Model, and the Open Scripting            //
  6. //                    Architecture.                                                    //
  7. //                                                                                    //
  8. //    by:    Sue Dumont                                                                    //
  9. //        Applications Scripting Group                                                //
  10. //                                                                                    //
  11. //    Version 1.01                                                                    //
  12. //    Copyright © Apple Computer, Inc. 1991,1992                                        //
  13. //    All rights reserved.                                                            //
  14. //                                                                                    //
  15. //    NOTE:  This application conforms to the "Apple Event Registry, Standard Suites    //
  16. //    Winter 1992, Vers. 1.0". CoreSample replaces the SimpleSample application that    //
  17. //    was    distributed at the Scripting QuickStart Conference on January 15,1992.        //
  18. //                                                                                    //
  19. //    The main purpose of this sample code is to demonstrate how to develop an         //
  20. //    application that is Apple event-aware, scripting compatible, uses the Object    //
  21. //    Support Library, and supports Apple's Open Scripting Architecture.  In             //
  22. //    addition, it has its own 'aete' (Apple Event Terminology Extension) resource    //
  23. //    (CoreSampleAETE.r). By    incorporating these technologies into your application,    //
  24. //    your application will support Apple's Open Scripting Architecture.                //
  25. //                                                                                    //
  26. //    The functionality of CoreSample is basic window manipulation. The user may        //
  27. //    create, drag, size, zoom, and close windows.  All these actions    may be            //
  28. //    performed through Apple events.                                                    //
  29. //                                                                                    //
  30. //    This application is also "factored", which means that user interactions (such    //
  31. //    as dragging or sizing a window, selecting a menuitem) are converted into Apple    //
  32. //    events which the application sends off to itself, and then is handled by the    //
  33. //    corresponding event handler.  Factoring makes it possible to access the appli-    //
  34. //    cation's functionality through Apple events. It also makes it easier to record    //
  35. //    the user's actions in the form of Apple events.                                    //
  36. //                                                                                    //
  37. //    CoreSample supports the Required and Core suites of events, and the application    //
  38. //    and window object classes. One additional property has been added to the window //
  39. //    class, and that is its position, the top left-hand coordinates of the window.    //
  40. //    Some events only apply to the window class, such as Create, Move, Clone, and     //
  41. //    Set Data (application properties are not modifiable, except for pClipboard,     //
  42. //    which I do not support).  Currently, CoreSample supports the Simple Grammar,    //
  43. //    as defined in the "Object Support Library Developer Note".                        //
  44. //                                                                                    //
  45. //    The properties you may access with the Get Data Apple event are as follows:        //
  46. //        Application - Best Type, Default Type, Class, Name, IsFrontProcess, Version    //
  47. //        Window - Best Type, Default Type, Bounds, Class, Index, Name, Position,        //
  48. //                 Closeable, Titled, Resizable, Zoomable, Floating, Modal, Zoomed,    //
  49. //                 and Visible.                                                        //
  50. //    The properties you may set with the Set Data Apple event are as follows:        //
  51. //        Window - Bounds, Index, Zoomed, Name, Position, and Visible.                //
  52. //                                                                                    //
  53. //    When you create a new element, you may pass it initial data values. This        //
  54. //    application will create the    new element accordingly if either or both of the    //
  55. //    initial data parameters exist. In addition, with CoreSample, you may create or    //
  56. //    move a window without passing it an insertion location record. By default, a    //
  57. //    window will be created/moved to the frontmost position.                            //
  58. //                                                                                    //
  59. //    (NOTE: Some portions of this code are derived from TESample, a                    //
  60. //    sample application provided by Apple Developer Technical Support.)                //
  61. //                                                                                    //
  62. //                                                                                    //
  63. //    Modification History:                                                            //
  64. //    11/91      <smd>    -    Initial code implementation.                                //
  65. //    01/06/92  <kc>    -    Added code for Count Elements, Do Objects Exist, Move,        //
  66. //                        and Get Data Size.                                            //
  67. //    01/09/92  <kc>    -    Quick clean up for Scripting QuickStart.                    //
  68. //    01/10/92  <smd>    -    Made insertion location parameter optional in the Create     //
  69. //                        and Move events, and provided my own default behavior.        //
  70. //    01/21/92  <smd>    -    Positive and negative offset when referencing by index.      //
  71. //    01/30/92  <smd>    -    Adding complete support for core suite and properties.        //
  72. //    02/05/92  <smd>    -    Handling optional parameters in Create Element event.        //
  73. //    02/17/92  <smd>    -  Added InitializeDescs() and DisposeDescs() routines.            //
  74. //    02/21/92  <smd> -    Fixed bug where the same AEDesc was being passed as source    //
  75. //                        and dest to AECoerceDesc().                                    //
  76. //                     -    Send myself a Move event when user clicks in content of a    //
  77. //                        window.                                                        //
  78. //    02/24/92  <smd> -    Now sends a Move event when just making a window active.    //
  79. //                        This is done in the DoEvent routine, drag region.            //
  80. //    02/25/92  <smd> -    Modified GetWindowWithTitle, GetWidnowWithIndex, and        //
  81. //                        GetWindowIndexNum routines to use WindowList so ALL windows    //
  82. //                        will be accessed (even invisible ones).                        //
  83. //                     -    Changed InitializeDescs to MyInitDescs and DisposeDescs to    //
  84. //                        MyDisposeDescs.                                                //
  85. //                     -    Removed the FailIfErr calls from the AE Handlers so that    //
  86. //                        they will return the error code rather than dying.            //
  87. //    02/28/92  <smd> -    Added coercion routines (thanks Kevin) to clean up code.    //
  88. //                        These convert from descs to boolean, long, and pstrings.    //
  89. //    04/20/92  <smd> -  Fixed a bug with setting the visibility property of a window.//
  90. //    04/27/92  <smd>    -  Fixed bug in DoSetData where data was set to a pointer, and    //
  91. //                        then the pointer was diposed of.                            //
  92. //    04/30/92  <smd> -  Check if replacing the same window in HandleMove                //
  93. //                        (i.e., "move window 2 to window 2"). If so, do nothing.        //
  94. //    06/25/92  <smd> -    Changed FindRelativeWindow to return the windowPtr of the    //
  95. //                        window being replaced rather than closing it. This caused    //
  96. //                        an error when trying to replace the same window, in which    //
  97. //                        case nothing should happen. (Ex. move window 2 to window 2).//
  98. //    07/19/92  <smd>    -    Fixed bug where the Move event was not recording the        //
  99. //                        correct window being moved when the data was being passed    //
  100. //                        by index rather than by name.                                //
  101. //    10/01/92  <smd> -    Added pVersion to application and now set the port before    //
  102. //                        setting the pPosition property.                                //
  103. //----------------------------------------------------------------------------------//
  104. #include    <SysEqu.h>                        // To use WindowList.
  105. #include    <Types.h>
  106. #include     <Quickdraw.h>
  107. #include     <Events.h>
  108. #include     <AppleEvents.h>
  109. #include     <AEObjects.h>
  110. #include     <AEPackObject.h>
  111. #include    <Resources.h>                    // for version resource
  112. #include     <Windows.h>
  113. #include     <Menus.h>
  114. #include     <Dialogs.h>
  115. #include     <Desk.h>
  116. #include     <Scrap.h>
  117. #include    <Values.h>
  118. #include     <ToolUtils.h>
  119. #include     <Memory.h>
  120. #include     <SegLoad.h>
  121. #include     <OSUtils.h>
  122. #include     <OSEvents.h>
  123. #include     <DiskInit.h>
  124. #include     <Packages.h>
  125. #include     <Traps.h>
  126. #include    <String.h>
  127. #include    <Strings.h>
  128. #include    <StdArg.h>
  129. #include    "AERegistry.h"                // Constants defined in the Registry.
  130. #include     "CoreSample.h"
  131.  
  132. #define HiWrd(aLong)    (((aLong) >> 16) & 0xFFFF)
  133. #define LoWrd(aLong)    ((aLong) & 0xFFFF)
  134.  
  135. typedef  long*            LongPtr;
  136. typedef  WindowPeek*    PeekPtr;
  137.  
  138.     //    Globals.
  139. SysEnvRec        gMac;                    // Contains the system environment
  140. Boolean            gHasWaitNextEvent;        // True if WaitNextEvent trap is available
  141. Boolean            gInBackground;            // Determines if currently in the background
  142. long            gNumWindowsOpen;        // The number of windows open
  143. short            gNewWindows;            // The number of new windows created
  144. Boolean            gQuitApp;                // True to quit the application
  145. AEDesc            gNullDesc;                // A null descriptor record
  146. AEAddressDesc    gSelfAddress;            // A self-addressed address descriptor record
  147. ProcessSerialNumber    gSelfPSN;            // This application's psn
  148. short            gRefNum;                // reference number of rescource file
  149.  
  150. //----------------------------------------------------------------------------------//
  151. //            PROTOTYPES                                                                //
  152. //----------------------------------------------------------------------------------//
  153. void        AdjustMenuStates(void);
  154. void        AlertUser(short error);
  155. void        CloseTheWindow(WindowPtr window);
  156. WindowPtr    CreateNewWindow(WindowPtr behind);
  157. OSErr        CreateWindowObjectSpec(WindowPtr window,short formType,AEDesc *objectSpec);
  158. void        DoEvent(EventRecord *event);
  159. void        DoGrowWindow(WindowPtr window, EventRecord *event);
  160. void        DoMenuCommand(long menuResult);
  161. OSErr         DoSetData(AEDesc *token, AEDesc *data);
  162. void        DoUpdate(WindowPtr window);
  163. void        EventLoop(void);
  164. void        FailIfErr(OSErr error);
  165. OSErr        FindRelativeWindow(WindowPtr *window,AEDesc *object,DescType pos,WindowPtr *replaceWindow);
  166. OSErr        GetAppData(DescType theProperty, AEDesc *result);
  167. OSErr        GetMissingParams(AppleEvent *theAppleEvent);
  168. OSErr        GetWindowData(DescType property, WindowPtr window, AEDesc *result);
  169. long        GetWindowIndexNum(WindowPtr window);
  170. WindowPtr    GetWindowAtIndex(long index);
  171. WindowPtr    GetWindowWithTitle(ConstStr255Param title);
  172. void        InitAEHandlers(void);
  173. void        Initialize(void);
  174. Boolean     IsAppWindow(WindowPtr window);
  175. Boolean     IsDAWindow(WindowPtr window);
  176. Boolean     IsTrapAvailable(short tNumber, TrapType tType);
  177. void        ReportError(AppleEvent *reply, long err);
  178. WindowPtr    ResolveToWindow(AEDesc *objectSpecifier);
  179. void        SendClose(WindowPtr  window);
  180. void        SendCreateElement(void);
  181. void        SendMoveEvent(WindowPtr windowToMove, long index);
  182. void        SendQuitApp(void);
  183. void         SendSetData(AEDesc *pDesc, AEDesc *pData, AEDesc *object);
  184. void        SetUpPropertyData(WindowPtr window,DescType propType,DescType dataType,Size dataSize);
  185. void        SignalError(short error);
  186. void        Terminate(void);
  187. void        ZoomIt(WindowPtr window, short part);
  188.  
  189. extern pascal OSErr CreateObjSpecifier(DescType theClass, AEDesc *theContainer,
  190.                         DescType keyForm, AEDesc *keyData, Boolean disposeInputs, 
  191.                         AEDesc *objSpecifier);
  192. extern void _DataInit();
  193.  
  194.  
  195. //----------------------------------------------------------------------------------//
  196. #pragma segment Main
  197. main()
  198. {
  199.     UnloadSeg((Ptr) _DataInit);        // Note that _DataInit must not be in Main!
  200.     MaxApplZone();                    // Expand the heap so code segments load at the top.
  201.     Initialize();                    // Initialize the program
  202.     UnloadSeg((Ptr)Initialize);        // Note that Initialize must not be in Main!
  203.     EventLoop();                    // Call the main event loop
  204. }
  205.  
  206. //----------------------------------------------------------------------------------//
  207. // Continue retrieving events until the application terminates.                        //
  208. //----------------------------------------------------------------------------------//
  209. #pragma segment Main
  210. void EventLoop()
  211. {
  212.     RgnHandle        cursorRgn;
  213.     Boolean            gotEvent;
  214.     EventRecord        event;
  215.  
  216.     cursorRgn = NewRgn();
  217.     gQuitApp = false;                // This is set to true in Terminate().        
  218.     
  219.     while (!gQuitApp)                // Loop until user quits or error.
  220.     {
  221.         if (gHasWaitNextEvent)
  222.             gotEvent = WaitNextEvent(everyEvent, &event ,MAXLONG, cursorRgn);
  223.         else 
  224.         {
  225.             SystemTask();
  226.             gotEvent = GetNextEvent(everyEvent, &event);
  227.         }
  228.         if (gotEvent)
  229.             DoEvent(&event);
  230.     }
  231. }
  232.  
  233. //----------------------------------------------------------------------------------//
  234. //    Find out which event this is and send it off to its appropriate handler.        //
  235. //    When the user clicks in the drag region, either one of two events may be        //
  236. //    triggered. The set position property (set data event) would occur if the widnow //
  237. //    is dragged to another location, or the move event would be sent if the window    //
  238. //    is just made active. In the latter case, the window's index before being        //
  239. //    moved to the front is passed to SendMoveEvent for recording purposes.            //
  240. //----------------------------------------------------------------------------------//
  241. #pragma segment Main
  242. void DoEvent( EventRecord*  event )
  243. {
  244.     long        index=0;
  245.     short        part, err;
  246.     WindowPtr    window;
  247.     char        key;
  248.     Rect        bounds1, bounds2;
  249.     Point        aPoint;
  250.  
  251.     switch (event->what)
  252.     {
  253.         case mouseDown:
  254.             part = FindWindow(event->where, &window);
  255.             switch (part) 
  256.             {
  257.                 case inMenuBar:
  258.                     AdjustMenuStates();            
  259.                     DoMenuCommand(MenuSelect(event->where));
  260.                     break;
  261.                     
  262.                 case inSysWindow:
  263.                     SystemClick(event, window);
  264.                     break;
  265.                     
  266.                 case inContent:
  267.                     if (window != FrontWindow()) 
  268.                         SendMoveEvent(window, index);
  269.                     break;
  270.                     
  271.                 case inDrag:
  272.                     index = GetWindowIndexNum(window);
  273.                     bounds1 = (*((WindowPeek)window)->contRgn)->rgnBBox;
  274.                     DragWindow(window, event->where, &qd.screenBits.bounds);
  275.                     bounds2 = (*((WindowPeek)window)->contRgn)->rgnBBox;
  276.                     if (bounds1 == bounds2)
  277.                         SendMoveEvent(GetWindowAtIndex(index), index);
  278.                     else
  279.                         SetUpPropertyData(window,pPosition,typeQDPoint,sizeof(Point));
  280.                     break;
  281.                     
  282.                 case inGoAway:
  283.                     if (TrackGoAway(window, event->where))
  284.                         SendClose(window);
  285.                     break;
  286.                     
  287.                 case inGrow:
  288.                     DoGrowWindow(window, event);
  289.                     break;
  290.                     
  291.                 case inZoomIn:                            // For recording purposes, we send an Apple
  292.                 case inZoomOut:                            // event to ourselves to set the bounds property.
  293.                     if (TrackBox(window, event->where, part))
  294.                     {
  295.                         ZoomIt(window, part);
  296.                         SetUpPropertyData(window, pIsZoomed, typeBoolean, sizeof(Boolean));
  297.                     }
  298.                     break;
  299.             }
  300.             break;
  301.             
  302.         case keyDown:
  303.         case autoKey:                               // Only handle menu key equivalents
  304.             key = event->message & charCodeMask;
  305.             if (event->modifiers & cmdKey)        // Command key down
  306.             {
  307.                 if (event->what == keyDown) 
  308.                 {
  309.                     AdjustMenuStates();                // Enable/disable/check menu items properly
  310.                     DoMenuCommand(MenuKey(key));
  311.                 }
  312.             } 
  313.             break;
  314.             
  315.         case activateEvt:
  316.             DrawGrowIcon((WindowPtr)event->message);
  317.             break;
  318.             
  319.         case updateEvt:
  320.             DoUpdate((WindowPtr) event->message);
  321.             break;
  322.             
  323.         case diskEvt:
  324.             if (HiWord(event->message) != noErr)
  325.             {
  326.                 SetPt(&aPoint, kDILeft, kDITop);
  327.                 err = DIBadMount(aPoint, event->message);
  328.             }
  329.             break;
  330.             
  331.         case kOSEvent:
  332.             {
  333.                 switch ((event->message >> 24) & 0x0FF)            // High byte of message.
  334.                 {
  335.                     case kMouseMovedMessage:
  336.                         break;                        // Do nothing if mouse moved.
  337.                     
  338.                     case kSuspendResumeMessage:        // suspend/resume is also an activate/deactivate
  339.                         SetCursor(&qd.arrow);
  340.                         if (IsAppWindow(window = FrontWindow()))
  341.                             DrawGrowIcon(window);
  342.                         break;
  343.                 }
  344.             }
  345.             break;
  346.             
  347.         case kHighLevelEvent:                        // Let the Apple Event Manager handle high level event.
  348.             AEProcessAppleEvent(event);
  349.             break;
  350.  
  351.         default:
  352.             break;
  353.     }
  354. }
  355.  
  356. //----------------------------------------------------------------------------------//
  357. //    Handle the mouseDown event in the grow box region of the window.  If the         //
  358. //    window has been resized, an Apple Event is sent to set the bounds property.        //
  359. //    This is done for recording purposes.                                            //
  360. //----------------------------------------------------------------------------------//
  361. #pragma segment Main
  362. void DoGrowWindow(    WindowPtr     window,
  363.                     EventRecord* event    )
  364. {
  365.     long            result;
  366.     Rect            tempRect;
  367.  
  368.     tempRect = qd.screenBits.bounds;        // Set up the limiting values.
  369.     tempRect.top = kMinWinDim;
  370.     tempRect.left = kMinWinDim;
  371.     result = GrowWindow(window, event->where, &tempRect);
  372.     if (result)                            // Did window actually change size?
  373.     {
  374.         SetPort(window);
  375.         InvalRect(&window->portRect);
  376.         SizeWindow(window, LoWrd(result), HiWrd(result), true);
  377.         InvalRect(&window->portRect);        // Send event for recording purposes.
  378.         SetUpPropertyData(window, pBounds, typeQDRectangle, sizeof(Rect));
  379.     }
  380. }
  381.  
  382. //----------------------------------------------------------------------------------//
  383. //    Zoom the window and set the refcon field to reflect its zoomed state.            //
  384. //----------------------------------------------------------------------------------//
  385. #pragma segment Main
  386. void ZoomIt( WindowPtr    window,
  387.              short        part  )
  388. {
  389.     SetPort(window);
  390.     EraseRect(&window->portRect);            // We just have a blank window.
  391.     ZoomWindow(window, part, window == FrontWindow());
  392.     SetWRefCon(window, (long)part == inZoomOut);    // Set to true if zoomed.
  393.     InvalRect(&window->portRect);
  394. }
  395.  
  396. //----------------------------------------------------------------------------------//
  397. //    This is called when an update event is received for a window.                    //
  398. //----------------------------------------------------------------------------------//
  399. #pragma segment Main
  400. void DoUpdate( WindowPtr  window )
  401. {
  402.     if (IsAppWindow(window)) 
  403.     {
  404.         BeginUpdate(window);
  405.         SetPort(window);
  406.         EraseRect(&window->portRect);            // We just have an empty window.
  407.         DrawGrowIcon(window);
  408.         EndUpdate(window);
  409.     }
  410. }
  411.  
  412. //----------------------------------------------------------------------------------//
  413. //    Set up the menus according to the current state.                                //
  414. //----------------------------------------------------------------------------------//
  415. #pragma segment Main
  416. void AdjustMenuStates()
  417. {
  418.     WindowPtr        window;
  419.     MenuHandle        menu;
  420.  
  421.     window = FrontWindow();
  422.     menu = GetMHandle(mFile);
  423.     if (gNumWindowsOpen < kMaxOpenWindows)
  424.         EnableItem(menu, iNew);            // Enable New if we can open more windows.
  425.     else
  426.         DisableItem(menu, iNew);
  427.     if (window)
  428.         EnableItem(menu, iClose);        // Enable Close if there is a window to close.
  429.     else
  430.         DisableItem(menu, iClose);
  431. }
  432.  
  433. //----------------------------------------------------------------------------------//
  434. //    This is called when an item is chosen from the menu bar.                        //
  435. //----------------------------------------------------------------------------------//
  436. #pragma segment Main
  437. void DoMenuCommand(long  menuResult)
  438. {
  439.     short        menuID, menuItem;
  440.     short        itemHit, daRefNum;
  441.     Str255        daName;
  442.     WindowPtr    window;
  443.  
  444.     window = FrontWindow();
  445.     menuID = HiWord(menuResult);
  446.     menuItem = LoWord(menuResult);
  447.     switch (menuID)
  448.     {
  449.         case mApple:
  450.             switch (menuItem) 
  451.             {
  452.                 case iAbout:
  453.                     itemHit = Alert(rAboutAlert, nil);
  454.                     break;
  455.                 default:            // all other items in this menu are DA's.
  456.                     GetItem(GetMHandle(mApple), menuItem, daName);
  457.                     daRefNum = OpenDeskAcc(daName);
  458.                     break;
  459.             }
  460.             break;
  461.             
  462.         case mFile:
  463.             switch (menuItem)                // All these items send Apple events to
  464.             {                                // handle the selection.
  465.                 case iNew:
  466.                     SendCreateElement();
  467.                     break;
  468.                 case iClose:
  469.                     SendClose(FrontWindow());
  470.                     break;
  471.                 case iQuit:
  472.                     SendQuitApp();
  473.                     break;
  474.             }
  475.             break;
  476.         
  477.         case mEdit:                    // Call SystemEdit for DA editing & MultiFinder.
  478.             SystemEdit(menuItem-1);
  479.             break;
  480.     }
  481.     HiliteMenu(0);                    // Unhighlight what MenuSelect (or MenuKey) hilited.
  482. }
  483.  
  484. //----------------------------------------------------------------------------------//
  485. //    This routine appends the ascii representation of num to the title string.        //
  486. //----------------------------------------------------------------------------------//
  487. #pragma segment Main
  488. void MakeNewWindowTitle( short        num,                // Window number.
  489.                          Str255        title)                // Window title.
  490. {
  491.     short        i, count, index;
  492.     char        numStr[5];
  493.     
  494.     i = 0;
  495.     do {
  496.             numStr[i++] = num % 10 + '0';
  497.         } while (num /= 10);
  498.         
  499.     index = title[0] + 1;                    // Get length of title string.
  500.     
  501.     for (count = i-1; count >= 0; count--)
  502.         title[index++] = numStr[count];
  503.     title[0] += i;
  504. }        
  505.  
  506. //----------------------------------------------------------------------------------//
  507. //    Create a new window behind the given window.  Use the window's refCon            //
  508. //    field to indicate whether the window is zoomed or not.                            //
  509. //----------------------------------------------------------------------------------//
  510. #pragma segment Main
  511. WindowPtr CreateNewWindow(WindowPtr behindWindow)
  512. {
  513.     Ptr            storage;
  514.     WindowPtr    newWindow, firstWindow;
  515.     Rect        bounds;
  516.     Str255        title;
  517.  
  518.     if (gNumWindowsOpen < kMaxOpenWindows)
  519.     {
  520.         storage = NewPtr(sizeof(WindowRecord));
  521.         if (storage != nil) 
  522.         {
  523.             newWindow = GetNewWindow(rDocWindow, storage, behindWindow);
  524.             if (newWindow != nil)
  525.             {
  526.                 gNumWindowsOpen++;            // Increment the number of windows currently open.
  527.                 gNewWindows++;                // Increment the number of new windows created.
  528.                 GetWTitle(newWindow, title);
  529.                 MakeNewWindowTitle(gNewWindows, title);
  530.                 SetWTitle(newWindow, title);
  531.                 if (firstWindow = FrontWindow())
  532.                 {
  533.                       bounds = (*((WindowPeek)firstWindow)->contRgn)->rgnBBox;
  534.                     MoveWindow(newWindow, bounds.left+30, bounds.top+30, false);
  535.                 }
  536.                 SetWRefCon(newWindow, 0L);            // set zoom state to false.
  537.                 SetPort(newWindow);
  538.                 return(newWindow);
  539.             }
  540.         else
  541.             DisposPtr(storage);        // Dispose of the storage if it is not used.
  542.         }
  543.     }
  544.     return(nil);
  545. }
  546.  
  547. //----------------------------------------------------------------------------------//
  548. //    Close the given window or desk accessory.                                        //
  549. //----------------------------------------------------------------------------------//
  550. #pragma segment Main
  551. void CloseTheWindow(WindowPtr  window)
  552. {
  553.     if (IsDAWindow(window))
  554.         CloseDeskAcc(((WindowPeek)window)->windowKind);
  555.     else 
  556.         if (IsAppWindow(window))
  557.         {
  558.             CloseWindow(window);
  559.             DisposPtr((Ptr)window);
  560.             gNumWindowsOpen--;
  561.         }
  562. }
  563.  
  564. //----------------------------------------------------------------------------------//
  565. //    Returns true if the window belongs to this application, else false.                //
  566. //----------------------------------------------------------------------------------//
  567. #pragma segment Main
  568. Boolean IsAppWindow(WindowPtr  window)
  569. {
  570.     if (!window)
  571.         return(false);
  572.     else 
  573.         return(((WindowPeek)window)->windowKind == userKind);
  574. }
  575.  
  576. //----------------------------------------------------------------------------------//
  577. //    Returns true if the given window belongs to a DA, else false is returned.        //
  578. //----------------------------------------------------------------------------------//
  579. #pragma segment Main
  580. Boolean IsDAWindow(WindowPtr  window)
  581. {
  582.     if (window == nil)
  583.         return(false);
  584.     else                    // DA windows have negative windowKinds.
  585.         return(((WindowPeek)window)->windowKind < 0);
  586. }
  587.  
  588. //----------------------------------------------------------------------------------//
  589. //  If an error has occurred, I check the user interaction level. If I can            //
  590. //    interact with the user, I put up a dialog and exit the application; otherwise,    //
  591. //    I just exit the application.                                                    //
  592. //                                                                                    //
  593. //    ***NOTE: Real applications would not handle errors in this fashion!  If they    //
  594. //    cannot interact with the user, they should abort the Apple event handler and    //
  595. // return the error in the reply parameter.                                            //
  596. //----------------------------------------------------------------------------------//
  597. #pragma segment    Main
  598. void FailIfErr(OSErr  error)
  599. {
  600.     if (error)
  601.     {
  602.         if (!(AEInteractWithUser(kNoTimeOut, nil, nil)))            // Can we interact?
  603.             AlertUser(eAEError);                                    // Yes, so put up the dialog.
  604.         ExitToShell();
  605.     }
  606. }
  607.  
  608. //----------------------------------------------------------------------------------//
  609. //    Display an alert for the user to indicate that an error has occurred.            //
  610. //----------------------------------------------------------------------------------//
  611. #pragma segment Main
  612. void AlertUser(short  error)
  613. {
  614.     short        itemHit;
  615.     Str255        message;
  616.  
  617.     GetIndString(message, kErrStrings, error);
  618.     ParamText(message, "", "", "");
  619.     itemHit = Alert(rUserAlert, nil);
  620. }
  621.  
  622. //----------------------------------------------------------------------------------//
  623. //    Quit the application by closing all windows and setting the quit flag to true.    //
  624. //----------------------------------------------------------------------------------// 
  625. #pragma segment Main
  626. void Terminate()
  627. {
  628.     WindowPtr    aWindow;
  629.  
  630.     while(aWindow = FrontWindow())
  631.         CloseTheWindow(aWindow);
  632.       AEDisposeDesc(&gSelfAddress);            // Dispose of my self-addressed descriptor.
  633.     gQuitApp = true;
  634. }
  635.  
  636. //----------------------------------------------------------------------------------//
  637. //    Perform the initialization necessary at start-up time.  Note that we use        //
  638. //    kCurrentProcess in our psn rather than calling GetCurrentProcess.  Using        //
  639. //    kCurrentProcess will allow us to record those events we send to ourselves,        //
  640. //    otherwise, the recorder won't recognize the psn and won't record our event!        //
  641. //----------------------------------------------------------------------------------//
  642. #pragma segment Initialize
  643. void Initialize()
  644. {
  645.     Handle                    menuBar;
  646.     long                    total, contig;
  647.     EventRecord             event;
  648.     short                    count;
  649.  
  650.     gInBackground = false;
  651.     InitGraf((Ptr)&qd.thePort);
  652.     InitWindows();
  653.     InitMenus();
  654.     InitDialogs(nil);
  655.     InitCursor();
  656.     InitAEHandlers();
  657.     for (count = 1; count <= 3; count++)
  658.         EventAvail(everyEvent, &event);
  659.      
  660.     SysEnvirons(kSysEnvironsVersion, &gMac);    
  661.     if (gMac.machineType < 0) 
  662.         SignalError(eWrongMachine);                // Less than 128K ROM's.
  663.     gHasWaitNextEvent = IsTrapAvailable(_WaitNextEvent, ToolTrap);
  664.      
  665.     if ((long)GetApplLimit() - (long)ApplicZone() < kMinHeap) 
  666.         SignalError(eSmallSize);
  667.     
  668.     PurgeSpace(&total, &contig);
  669.     if (total < kMinSpace)
  670.         if (UnloadScrap() != noErr)
  671.             SignalError(eNoMemory);
  672.         else
  673.         {
  674.             PurgeSpace(&total, &contig);
  675.             if (total < kMinSpace)
  676.                 SignalError(eNoMemory);
  677.         }
  678.  
  679.     if (!(menuBar = GetNewMBar(rMenuBar)))        // Set up menu bar.
  680.         SignalError(eNoMemory);
  681.     SetMenuBar(menuBar);
  682.     DisposHandle(menuBar);
  683.     AddResMenu(GetMHandle(mApple), 'DRVR');            // Add DA's to menu.
  684.     DrawMenuBar();
  685.  
  686.         // Set up the self-addressed descriptor record.
  687.       gSelfPSN.highLongOfPSN = 0;
  688.       gSelfPSN.lowLongOfPSN = kCurrentProcess;        //* Use this instead of GetCurrentProcess *//
  689.       FailIfErr(AECreateDesc(typeProcessSerialNumber,(Ptr)&gSelfPSN,sizeof(ProcessSerialNumber),&gSelfAddress));
  690.     gNullDesc.descriptorType = typeNull;        // Initialize the global null descriptor record.
  691.     gNullDesc.dataHandle = nil;
  692.  
  693.     gRefNum = CurResFile();
  694.     gNumWindowsOpen = 0;
  695.     gNewWindows = 0;
  696. }
  697.  
  698. //----------------------------------------------------------------------------------//
  699. //    Returns true if the given trap number is implemented, else returns false.        //
  700. //----------------------------------------------------------------------------------//
  701. #pragma segment Initialize
  702. Boolean IsTrapAvailable(short trapNum, TrapType  tType)
  703. {
  704.     if ((tType == (unsigned char)ToolTrap) && (gMac.machineType > envMachUnknown) &&
  705.          (gMac.machineType < envMacII))
  706.     {                                            // it's a 512K, Plus, or SE
  707.         trapNum = trapNum & 0x03FF;
  708.         if (trapNum > 0x01FF)                    // which means the tool traps
  709.             trapNum = _Unimplemented;            // only go to 0x01FF
  710.     }
  711.     return(NGetTrapAddress(trapNum, tType) != GetTrapAddress(_Unimplemented));
  712. }
  713.  
  714. //----------------------------------------------------------------------------------//
  715. #pragma segment Initialize
  716. void SignalError(short error)
  717. {
  718.     AlertUser(error);
  719.     ExitToShell();
  720. }
  721.  
  722. //**********************************************************************************//
  723. //                    *  Apple Events and Object Model Support *                        //
  724. //**********************************************************************************//
  725.  
  726. //----------------------------------------------------------------------------------//
  727. //    Initializes all descriptor records passed in to this routine.  The variable        //
  728. //    argument list is null terminated.                                                //
  729. //----------------------------------------------------------------------------------//
  730. #pragma segment Main
  731. void MyInitDescs(AEDesc*  desc1, ... )            // Variable, null terminated argument list.
  732. {
  733.     va_list        argptr;                            // pointer to each argument in list.
  734.     AEDesc*        nextDesc;                        // next descriptor argument in list.
  735.  
  736.     va_start(argptr, desc1);
  737.     desc1->descriptorType = typeNull;
  738.     desc1->dataHandle = nil;
  739.     
  740.     while(nextDesc = va_arg(argptr, AEDesc *))
  741.     {
  742.         nextDesc->descriptorType = typeNull;
  743.         nextDesc->dataHandle = nil;
  744.     }
  745.     va_end(argptr);
  746. }
  747.     
  748. //----------------------------------------------------------------------------------//
  749. //    Dispose all descriptor records passed into this routine. (Variable arg. list).    //
  750. //----------------------------------------------------------------------------------//
  751. #pragma segment Main
  752. void MyDisposeDescs(AEDesc*  desc1, ... )        // Null terminated argument list.
  753. {
  754.     va_list        argptr;            // pointer to each argument in list.
  755.     AEDesc*        nextDesc;        // descriptor argument in list.
  756.  
  757.     va_start(argptr, desc1);
  758.     if (desc1->dataHandle)
  759.         AEDisposeDesc(desc1);
  760.  
  761.     while(nextDesc = va_arg(argptr, AEDesc *))
  762.     {
  763.         if (nextDesc->dataHandle)
  764.             AEDisposeDesc(nextDesc);
  765.     }
  766.     va_end(argptr);
  767. }
  768.  
  769. //----------------------------------------------------------------------------------//
  770. //    Converts a descriptor to a boolean.                                                //
  771. //----------------------------------------------------------------------------------//
  772. #pragma segment AppleEvents
  773. OSErr DescToBoolean(const AEDesc* desc, Boolean* boolvalue)
  774. {
  775.     AEDesc            tempDesc;
  776.     Handle            dataHandle;
  777.  
  778.     tempDesc.dataHandle = nil;
  779.     if (desc->descriptorType == typeBoolean)
  780.         dataHandle = desc->dataHandle;
  781.     else
  782.         if (AECoerceDesc(desc, typeBoolean, &tempDesc) == noErr)
  783.             dataHandle = tempDesc.dataHandle;
  784.         else
  785.             return(errAECoercionFail);
  786.     
  787.     *boolvalue = **dataHandle;
  788.     MyDisposeDescs(&tempDesc, kEndOfList);
  789.     return(noErr);
  790. }
  791.  
  792. //----------------------------------------------------------------------------------//
  793. //    Converts a descriptor to a long.                                                //
  794. //----------------------------------------------------------------------------------//
  795. #pragma segment AppleEvents
  796. OSErr DescToLong(const  AEDesc* desc, long* longvalue)
  797. {
  798.     AEDesc            tempDesc;
  799.     Handle            dataHandle;
  800.  
  801.     tempDesc.dataHandle = nil;
  802.     if (desc->descriptorType == typeLongInteger)
  803.         dataHandle = desc->dataHandle;
  804.     else
  805.         if (AECoerceDesc(desc, typeLongInteger, &tempDesc) == noErr)
  806.             dataHandle = tempDesc.dataHandle;
  807.         else
  808.             return(errAECoercionFail);
  809.     
  810.     *longvalue = *(LongPtr)*dataHandle;
  811.     MyDisposeDescs(&tempDesc, kEndOfList);
  812.     return(noErr);
  813. }
  814.  
  815. //----------------------------------------------------------------------------------//
  816. //    Converts a descriptor to a pascal string.                                        //
  817. //----------------------------------------------------------------------------------//
  818. #pragma segment AppleEvents
  819. OSErr DescToPString(const AEDesc* desc, Str255 str, short maxLength)
  820. {
  821.     AEDesc            tempDesc;
  822.     Handle            dataHandle;
  823.     long            charCount;
  824.  
  825.     tempDesc.dataHandle = nil;
  826.     if (desc->descriptorType == typeChar)
  827.         dataHandle = desc->dataHandle;
  828.     else
  829.         if (AECoerceDesc(desc, typeChar, &tempDesc) == noErr)
  830.             dataHandle = tempDesc.dataHandle;
  831.         else
  832.             return(errAECoercionFail);
  833.     
  834.     charCount = GetHandleSize(dataHandle);
  835.     if (charCount > maxLength)
  836.     {
  837.         MyDisposeDescs(&tempDesc, kEndOfList);
  838.         return(errAECoercionFail);
  839.     }
  840.  
  841.     str[0] = charCount;
  842.     HLock(dataHandle);
  843.     BlockMove(*dataHandle, &str[1], charCount);
  844.     HUnlock(dataHandle);        // This may be from desc, so must unlock.
  845.     MyDisposeDescs(&tempDesc, kEndOfList);
  846.     return(noErr);
  847. }
  848.  
  849. //----------------------------------------------------------------------------------//
  850. //    Create the first window in response to the Open Application Apple Event.        //
  851. //----------------------------------------------------------------------------------//
  852. #pragma segment Main
  853. pascal
  854. OSErr HandleOpenApp(AppleEvent *theAppleEvent, AppleEvent* reply, long refCon)
  855. {
  856.     #pragma unused (reply,refCon)
  857.     WindowPtr    window;
  858.     OSErr        err;
  859.     
  860.     if (!(err = GetMissingParams(theAppleEvent)))        // Error if any parameters.
  861.     {
  862.         if (window = CreateNewWindow((WindowPtr)-1))    // Create initial window
  863.             ShowWindow(window);
  864.         else
  865.             err = errAEEventNotHandled;
  866.     }
  867.     return(err);
  868. }
  869.  
  870. //----------------------------------------------------------------------------------//
  871. //    Send a Quit Application Apple Event to myself to terminate this app.            //
  872. //----------------------------------------------------------------------------------//
  873. #pragma segment Main
  874. void SendQuitApp()
  875. {
  876.     AppleEvent    myAppleEvent, reply;
  877.     
  878.         //    Create the Apple Event.
  879.     FailIfErr(AECreateAppleEvent(kCoreEventClass, kAEQuitApplication, &gSelfAddress,
  880.                                     kAutoGenerateReturnID, kAnyTransactionID, &myAppleEvent));
  881.         //    Send the Apple Event.
  882.       FailIfErr(AESend(&myAppleEvent, &reply, kAENoReply+kAENeverInteract, kAENormalPriority,
  883.                                 kAEDefaultTimeout, nil, nil));
  884.       AEDisposeDesc(&myAppleEvent);                // Dispose of the Apple Event.
  885. }
  886.  
  887. //----------------------------------------------------------------------------------//
  888. //    Quit the application.                                                            //
  889. //----------------------------------------------------------------------------------//
  890. #pragma segment Main
  891. pascal
  892. OSErr HandleQuitApp(AppleEvent* theAppleEvent, AppleEvent* reply, long refCon)
  893. {
  894.     #pragma unused (reply,refCon)
  895.     OSErr    err;
  896.     
  897.     if (!(err = GetMissingParams(theAppleEvent)))    // Error if there are any parameters.
  898.         Terminate();
  899.     return(err);
  900. }
  901.  
  902. //----------------------------------------------------------------------------------//
  903. //    This routine makes a clone of the given window by copying its bounds, zoom        //
  904. //    state, and title (with the addition of "copy") properties.                        //
  905. //----------------------------------------------------------------------------------//
  906. #pragma segment Main
  907. WindowPtr CloneWindow(WindowPtr windowToClone, WindowPtr behindWindow)
  908. {
  909.     WindowPtr    clonedWindow;
  910.     Rect        bounds;
  911.     Str255        title;
  912.  
  913.     if (clonedWindow = CreateNewWindow(behindWindow))
  914.     {
  915.         GetWTitle(windowToClone, title);
  916.         p2cstr(title);
  917.         strcat(title, " copy\0");
  918.         c2pstr(title);
  919.         bounds = (*((WindowPeek)windowToClone)->contRgn)->rgnBBox;
  920.         SetWTitle(clonedWindow, title);
  921.         MoveWindow(clonedWindow, bounds.left, bounds.top, false);
  922.         SizeWindow(clonedWindow, bounds.right-bounds.left, bounds.bottom-bounds.top, true);
  923.         SetWRefCon(clonedWindow, GetWRefCon(windowToClone));
  924.         return(clonedWindow);
  925.     }
  926.     return(nil);
  927. }
  928.  
  929. //----------------------------------------------------------------------------------//
  930. //    Handle the Clone Apple Event and create a clone of the given object. To clone    //
  931. //    a window, I clone its bounds, zoom state, and visible properties. In addition,    //
  932. //    I clone the window's title and append " copy" to it for the cloned window's        //
  933. //    title. If the insertion location parameter is not in the event record, I         //
  934. //    perform the default behavior, which is to position the clone behind the         //
  935. //    window being cloned.                                                            //
  936. //----------------------------------------------------------------------------------//
  937. #pragma segment Main
  938. pascal
  939. OSErr HandleClone(AppleEvent* theAppleEvent, AppleEvent* reply, long refCon)
  940. {
  941.     #pragma unused (refCon)
  942.     AEDesc        cloneObject, windowObject, replyObject, insertionLoc;
  943.     AERecord    insertionRec;
  944.     DescType    theType, position;
  945.     WindowPtr    windowToClone, window, rplcWindow, behindWindow = nil;
  946.     Size        paramSize;
  947.     OSErr        err = noErr;
  948.  
  949.  
  950.     MyInitDescs(&cloneObject,&windowObject,&replyObject,&insertionLoc,&insertionRec,kEndOfList);
  951.         //    Let's get the direct object, the object to clone.
  952.     if (err = AEGetParamDesc(theAppleEvent, keyDirectObject, typeObjectSpecifier, &cloneObject))
  953.         goto myExit;
  954.     if (!(windowToClone = ResolveToWindow(&cloneObject)))
  955.     {
  956.         err = errAENoSuchObject;
  957.         goto myExit;
  958.     }
  959.     else        // we have a window to clone.
  960.     {
  961.         if (!(err = AEGetParamDesc(theAppleEvent,keyAEInsertHere,typeInsertionLoc,&insertionLoc)))
  962.             if (!(err = AECoerceDesc(&insertionLoc, typeAERecord, &insertionRec)))
  963.                 // Get object as typeWildCard because it may be null or an object specifier.
  964.                 if (!(err = AEGetKeyDesc(&insertionRec, keyAEObject, typeWildCard, &windowObject)))
  965.                     if (!(err = AEGetKeyPtr(&insertionRec,keyAEPosition,typeEnumeration,&theType,
  966.                                         (Ptr)&position,sizeof(DescType),¶mSize)))
  967.                         err = FindRelativeWindow(&behindWindow, &windowObject, position, &rplcWindow);
  968.  
  969.         if (err)
  970.             if (err == errAEDescNotFound)
  971.                 behindWindow = windowToClone;        // Registry's default behavior.
  972.             else
  973.                 goto myExit;
  974.     }
  975.  
  976.     if (window = CloneWindow(windowToClone, behindWindow))
  977.     {
  978.         if (((WindowPeek)windowToClone)->visible)
  979.             ShowWindow(window);
  980.         if (position == kAEReplace)
  981.             CloseTheWindow(rplcWindow);
  982.  
  983.         if (reply->dataHandle != nil)
  984.         {
  985.             CreateWindowObjectSpec(window, kIndexKeyForm, &replyObject);
  986.             err = AEPutParamDesc(reply, keyAEResult, &replyObject);
  987.         }
  988.     }
  989.     else
  990.         err = errAEEventNotHandled;
  991.  
  992. myExit:
  993.     MyDisposeDescs(&cloneObject,&windowObject,&replyObject,&insertionLoc,&insertionRec,kEndOfList);
  994.     return(err);
  995. }    
  996.  
  997. //----------------------------------------------------------------------------------//
  998. //    Send a Close Apple Event to myself to close the specified window.                //
  999. //----------------------------------------------------------------------------------//
  1000. #pragma segment Main
  1001. void SendClose(WindowPtr  window)
  1002. {
  1003.     AppleEvent        myAppleEvent, reply;
  1004.     AEDesc            windowObject;                // The window object specifier.
  1005.  
  1006.                 //    Create the Close Apple Event.
  1007.     FailIfErr(AECreateAppleEvent(kAECoreSuite, kAEClose, &gSelfAddress, kAutoGenerateReturnID,
  1008.                                     kAnyTransactionID, &myAppleEvent));
  1009.                 //    Create the window object specifier and add this to myAppleEvent.
  1010.     CreateWindowObjectSpec(window, kIndexKeyForm, &windowObject);
  1011.     FailIfErr(AEPutParamDesc(&myAppleEvent, keyDirectObject, &windowObject));
  1012.                 //    Send the Apple Event.
  1013.       FailIfErr(AESend(&myAppleEvent, &reply, kAENoReply+kAECanInteract, kAENormalPriority,
  1014.                                 kAEDefaultTimeout, nil, nil));
  1015.                 //    Now dispose of the AppleEvent and object specifier.                                
  1016.       AEDisposeDesc(&myAppleEvent);
  1017.     AEDisposeDesc(&windowObject);
  1018. }
  1019.  
  1020. //----------------------------------------------------------------------------------//
  1021. //    Respond to the Close Apple Event by closing the specified window object.        //
  1022. //----------------------------------------------------------------------------------//
  1023. #pragma segment Main
  1024. pascal
  1025. OSErr HandleClose(AppleEvent* theAppleEvent, AppleEvent* reply, long refCon)
  1026. {
  1027.     #pragma unused (reply,refCon)
  1028.     AEDesc            windowObject;
  1029.     WindowPtr        windowToClose;
  1030.     OSErr            myErr;
  1031.     
  1032.     MyInitDescs(&windowObject,kEndOfList);
  1033.         //    First, get the direct object which is the object to close.
  1034.     myErr = AEGetParamDesc(theAppleEvent,keyDirectObject,typeObjectSpecifier,&windowObject);
  1035.     if (!myErr && !(myErr = GetMissingParams(theAppleEvent)))
  1036.     {
  1037.         if (windowToClose = ResolveToWindow(&windowObject))
  1038.             CloseTheWindow(windowToClose);
  1039.         else
  1040.             myErr = errAENoSuchObject;
  1041.     }
  1042.     MyDisposeDescs(&windowObject,kEndOfList);
  1043.     return(myErr);
  1044. }
  1045.  
  1046. //----------------------------------------------------------------------------------//
  1047. //    Respond to the Count Elements Apple Event.                                        //
  1048. //----------------------------------------------------------------------------------//
  1049. #pragma segment Main
  1050. pascal
  1051. OSErr HandleCountElements(AppleEvent* theAppleEvent, AppleEvent* reply, long refCon)
  1052. {
  1053.     #pragma unused (refCon)
  1054.     AEDesc            directObject;
  1055.     DescType        theType, theClass;
  1056.     Size            paramSize;
  1057.     OSErr            err;
  1058.     
  1059.  
  1060.     MyInitDescs(&directObject, kEndOfList);
  1061.         //    Get the direct object, should be null.
  1062.     if (!(err = AEGetParamDesc(theAppleEvent, keyDirectObject, typeWildCard, &directObject)))
  1063.         if (!(err = AEGetParamPtr(theAppleEvent,keyAEObjectClass,typeType,&theType,(Ptr)&theClass,
  1064.                     sizeof(DescType),¶mSize)))        // Get class of elements to count.
  1065.             err = GetMissingParams(theAppleEvent);        // Error if more parameters.
  1066.  
  1067.     if (err)
  1068.         goto myExit;
  1069.         
  1070.         //    If we had a deeper object hierarchy, we'd probably call AEResolve here, but...
  1071.         //    we only handle the window class contained within the null object.
  1072.     if (theClass == cWindow && directObject.descriptorType == typeNull)
  1073.         err = AEPutParamPtr(reply, keyAEResult, typeLongInteger, (Ptr)&gNumWindowsOpen, sizeof(long));
  1074.  
  1075. myExit:
  1076.     MyDisposeDescs(&directObject, kEndOfList);
  1077.     return(err);
  1078. }
  1079.  
  1080. //----------------------------------------------------------------------------------//
  1081. //    Send a Create Element Apple Event to myself to create a new window. By default, //
  1082. //    I am setting the position to the beginning of the null container (frontmost).    //
  1083. //    In this case, as well as at the end of the container, the object parameter is    //
  1084. //    the null container. If the position is before, after, or replace, the object    //
  1085. //    parameter must be an object specifier to indicate the relative window.            //
  1086. //----------------------------------------------------------------------------------//
  1087. #pragma segment Main
  1088. void SendCreateElement()
  1089. {
  1090.     AppleEvent        myAppleEvent, reply;
  1091.     AERecord        insertionRec;                    // Insertion Loc record.
  1092.     AEDesc            insertionLoc;                    // The coerced insertionRec.
  1093.     DescType        theType;
  1094.     
  1095.                 //    Create the Apple Event.
  1096.     FailIfErr(AECreateAppleEvent(kAECoreSuite, kAECreateElement, &gSelfAddress, kAutoGenerateReturnID,
  1097.                                     kAnyTransactionID, &myAppleEvent));
  1098.                 //    Attach the class of the new element, which in this case is cWindow.
  1099.     theType = cWindow;
  1100.       FailIfErr(AEPutParamPtr(&myAppleEvent, keyAEObjectClass, typeType, (Ptr)&theType, sizeof(DescType)));
  1101.  
  1102.                 //    Create insertion loc, object is null container and position is beginning.
  1103.     FailIfErr(AECreateList(nil, 0, true, &insertionRec));            // Create an AE Record.
  1104.     theType = kAEBeginning;
  1105.     FailIfErr(AEPutKeyDesc(&insertionRec, keyAEObject, &gNullDesc));
  1106.     FailIfErr(AEPutKeyPtr(&insertionRec, keyAEPosition, typeEnumeration, (Ptr)&theType, sizeof(DescType)));
  1107.     FailIfErr(AECoerceDesc(&insertionRec, typeInsertionLoc, &insertionLoc));
  1108.                 // Now add the insertion location descriptor record to the Apple Event.
  1109.     FailIfErr(AEPutParamDesc(&myAppleEvent, keyAEInsertHere, &insertionLoc));
  1110.                 //    Send the Apple Event.
  1111.       FailIfErr(AESend(&myAppleEvent, &reply, kAENoReply+kAECanInteract, kAENormalPriority,
  1112.                                 kAEDefaultTimeout, nil, nil));
  1113.                 //    Now dispose of the AppleEvent and other records.
  1114.       MyDisposeDescs(&myAppleEvent, &insertionRec, &insertionLoc, kEndOfList);
  1115. }
  1116.  
  1117. //----------------------------------------------------------------------------------//
  1118. //    Respond to the Create Element Apple event and create a new window. For this        //
  1119. //    application, the keyAEInsertHere parameter is optional. If this parameter is     //
  1120. //    not present, a new window is created in the frontmost position.                    //
  1121. //    This routine also handles the optional initial data parameters (keyAEData and    //
  1122. //    keyAEPropData) if they are present. A window object specifier must be in the    //
  1123. //    keyAEData parameter, which is essentially used to make a clone. If the            //
  1124. //    property data exists, these properties will override those previously set.        //
  1125. //----------------------------------------------------------------------------------//
  1126. #pragma segment Main
  1127. pascal
  1128. OSErr HandleCreateElement(AppleEvent* theAppleEvent, AppleEvent* reply, long refCon)
  1129. {
  1130.     #pragma unused (refCon)
  1131.     AEDesc            windowObject, dataObject, propData, propObject, replyObject;
  1132.     AEDesc            insLocParam;
  1133.     AERecord        insLocRec;
  1134.     AERecord        dataPropParam;                    // Initial data parameters.
  1135.     AEKeyword        keyWord;                        // Property id code for PropData.
  1136.     DescType        theType, theClass, position;
  1137.     WindowPtr        window, relativeWindow, dataWindow, rplcWindow;
  1138.     Rect            bounds;
  1139.     Size            theSize;
  1140.     Str255            buffer;
  1141.     long            numItems;
  1142.     short            i;
  1143.     Boolean            isVisible;
  1144.     OSErr            err;
  1145.     
  1146.     if (err = AEGetParamPtr(theAppleEvent, keyAEObjectClass, typeType, &theType, (Ptr)&theClass,
  1147.                     sizeof(DescType), &theSize))
  1148.         return(err);
  1149.     if (theClass != cWindow)            // We only handle elements of the class cWindow.
  1150.         return(errAEEventNotHandled);
  1151.     position = typeNull;
  1152.     MyInitDescs(&windowObject,&dataObject,&propData,&propObject,&insLocParam,&dataPropParam,&replyObject,&insLocRec,kEndOfList);
  1153.             // Now get the insertion location record as an AERecord, if it exists.
  1154.     if (!(err = AEGetParamDesc(theAppleEvent, keyAEInsertHere, typeInsertionLoc, &insLocParam)))
  1155.     {        // coerce the insertion loc record to an AE record.
  1156.         err = AECoerceDesc(&insLocParam, typeAERecord, &insLocRec);
  1157.             //    Get the object as typeWildCard because it may be a null descriptor or an object.
  1158.         if (!(err = AEGetKeyDesc(&insLocRec, keyAEObject, typeWildCard, &windowObject)))
  1159.             if (!(err = AEGetKeyPtr(&insLocRec, keyAEPosition, typeEnumeration, &theType, (Ptr)&position,
  1160.                         sizeof(DescType), &theSize)))
  1161.             {
  1162.                 relativeWindow = nil;
  1163.                 err = FindRelativeWindow(&relativeWindow, &windowObject, position, &rplcWindow);
  1164.             }
  1165.     }
  1166.     else
  1167.         if (err == errAEDescNotFound)    // No insertion loc, make it frontmost by default.
  1168.         {
  1169.             relativeWindow = (WindowPtr)-1;
  1170.             position = kAEBeginning;
  1171.             err = noErr;        // Not an error for me because I make this param optional.
  1172.         }
  1173.  
  1174.     if (err)
  1175.         goto myExit;
  1176.         
  1177.                 // Check if optional data parameter is present.
  1178.     if (!(err = AEGetParamDesc(theAppleEvent,keyAEData,typeObjectSpecifier,&dataObject)))
  1179.     {
  1180.         if (dataWindow = ResolveToWindow(&dataObject))
  1181.         {
  1182.             window = CloneWindow(dataWindow, relativeWindow);
  1183.             isVisible = ((WindowPeek)dataWindow)->visible;
  1184.         }
  1185.         else
  1186.         {
  1187.             err = errAENoSuchObject;
  1188.             goto myExit;
  1189.         }
  1190.     }
  1191.     else
  1192.         if (err == errAEDescNotFound)    // The optional data parameter is not present.
  1193.         {
  1194.             if (window = CreateNewWindow(relativeWindow))
  1195.             {
  1196.             err = noErr;
  1197.             isVisible = true;
  1198.                 if (position == kAEReplace)            // Replace the window in the right position.
  1199.                 {
  1200.                     bounds = (*((WindowPeek)rplcWindow)->contRgn)->rgnBBox;
  1201.                     MoveWindow(window, bounds.left, bounds.top, false);
  1202.                 }
  1203.             }
  1204.             else
  1205.             {
  1206.                 err = errAEEventNotHandled;        // couldn't create a new window.
  1207.                 goto myExit;
  1208.             }
  1209.         }
  1210.         else
  1211.             goto myExit;
  1212.  
  1213.     if (isVisible)                    // We set the visibility here because it may be changed
  1214.         ShowWindow(window);            // by the following property data.
  1215.  
  1216.             // Handle PropData parameter if it exists.        
  1217.     if (!(err = AEGetParamDesc(theAppleEvent,keyAEPropData,typeAERecord,&dataPropParam)))
  1218.     {
  1219.         AECountItems(&dataPropParam, &numItems);
  1220.         for (i = 1; i <= numItems; i++)
  1221.         {
  1222.             if (!(err = AEGetNthPtr(&dataPropParam,i,typeWildCard,&keyWord,&theType,&buffer,sizeof(Str255),&theSize)))
  1223.             {
  1224.                 AECreateDesc(keyWord, (Ptr)&window, sizeof(Ptr), &propObject);
  1225.                 AECreateDesc(theType, (Ptr)&buffer, theSize, &propData);
  1226.                 err = DoSetData(&propObject, &propData);
  1227.                 AEDisposeDesc(&propObject);
  1228.                 AEDisposeDesc(&propData);
  1229.                 if (err)
  1230.                     break;
  1231.             }
  1232.         }
  1233.     }
  1234.     
  1235.     if (!err || err == errAEDescNotFound)
  1236.     {
  1237.         if (position == kAEReplace)
  1238.             CloseTheWindow(rplcWindow);
  1239.         err = noErr;
  1240.         if (reply->dataHandle != nil)
  1241.         {
  1242.             CreateWindowObjectSpec(window, kIndexKeyForm, &replyObject);
  1243.             err = AEPutParamDesc(reply, keyAEResult, &replyObject);
  1244.         }
  1245.     }
  1246.         
  1247. myExit:
  1248.     MyDisposeDescs(&windowObject,&dataObject,&propData,&propObject,&insLocParam,&dataPropParam,&replyObject,&insLocRec,kEndOfList);
  1249.     return(err);
  1250. }
  1251.  
  1252. //----------------------------------------------------------------------------------//
  1253. //    Respond to the Do Objects Exist AE by attempting to resolve the object specifier//
  1254. //----------------------------------------------------------------------------------//
  1255. #pragma segment Main
  1256. pascal
  1257. OSErr HandleDoObjectsExist(AppleEvent* theAppleEvent, AppleEvent* reply, long refCon)
  1258. {
  1259.     #pragma unused (reply,refCon)
  1260.     AEDesc        target, token;
  1261.     Boolean        exists;
  1262.     OSErr        err;
  1263.     
  1264.     MyInitDescs(&target, &token, kEndOfList);
  1265.     if (!(err = AEGetParamDesc(theAppleEvent, keyDirectObject, typeWildCard, &target)))
  1266.         if (!(err = GetMissingParams(theAppleEvent)))            // Check for missing params.
  1267.         {
  1268.             exists = true;
  1269.             token.descriptorType = typeNull;
  1270.             if (target.descriptorType != typeNull)
  1271.                 exists = (AEResolve(&target, kAEIDoMinimum, &token) == noErr);
  1272.  
  1273.                 //    Add data to the reply Apple event record.
  1274.               err = AEPutParamPtr(reply, keyDirectObject,typeBoolean,(Ptr)&exists,sizeof(Boolean));
  1275.         }
  1276. myExit:
  1277.     MyDisposeDescs(&target, &token, kEndOfList);
  1278.     return(err);
  1279. }
  1280.  
  1281. //----------------------------------------------------------------------------------//
  1282. //    Send the Set Data Apple Event with the object, property, and property data.        //
  1283. //    *NOTE*: I am sending myself the Set Data event in response to user interaction.    //
  1284. //    These actions have already occurred by this time, so I am sending the event        //
  1285. //    with the "don't execute" flag set for "smart" recorders.  A "smart" recorder    //
  1286. //    would check this flag when it intercepts the Apple event, and if it was set,    //
  1287. //    it wouldn't pass the event to the application.                                    //
  1288. //----------------------------------------------------------------------------------//
  1289. #pragma segment Main
  1290. void SendSetData( AEDesc*    propDesc,            // the property to set
  1291.                   AEDesc*    propData,            // the property data
  1292.                   AEDesc*    target  )        // object to set property of
  1293. {
  1294.     AppleEvent    myAppleEvent, reply;
  1295.     AEDesc        objectToSet;
  1296.  
  1297.     FailIfErr(AECreateAppleEvent(kAECoreSuite, kAESetData, &gSelfAddress, kAutoGenerateReturnID,
  1298.                                     kAnyTransactionID, &myAppleEvent));
  1299.                 //  Create the object specifier for the property of the object.
  1300.     FailIfErr(CreateObjSpecifier(cProperty, target, formPropertyID, propDesc, 
  1301.                                         false, &objectToSet));
  1302.                 //    Attach the property object specifier.
  1303.     FailIfErr(AEPutParamDesc(&myAppleEvent, keyDirectObject, &objectToSet));
  1304.                 //    Add the property data.
  1305.     FailIfErr(AEPutParamDesc(&myAppleEvent, keyAEData, propData));
  1306.       FailIfErr(AESend(&myAppleEvent, &reply, kAENoReply+kAECanInteract+kAEDontExecute, kAENormalPriority,
  1307.                                 kAEDefaultTimeout, nil, nil));
  1308.  
  1309.     AEDisposeDesc(&objectToSet);                    // Clean up.                                
  1310.     AEDisposeDesc(&myAppleEvent);
  1311. }
  1312.  
  1313. //----------------------------------------------------------------------------------//
  1314. //    To set the data of an object, the expected data is passed in its raw form with    //
  1315. //    the property type in the descriptorType field and the data in the dataHandle.    //
  1316. //----------------------------------------------------------------------------------//
  1317. #pragma segment Main
  1318. pascal
  1319. OSErr HandleSetData(AppleEvent* theAppleEvent, AppleEvent* reply, long refCon)
  1320. {
  1321.     #pragma unused (reply,refCon)
  1322.     AEDesc        target, data, token;
  1323.     OSErr        err;
  1324.     
  1325.     MyInitDescs(&target, &data,&token, kEndOfList);
  1326.         //    First, get the direct object. This is the object whose data is to be set.
  1327.     if (!(err = AEGetParamDesc(theAppleEvent, keyDirectObject, typeObjectSpecifier, &target)))
  1328.         if (!(err = AEResolve(&target, kAEIDoMinimum, &token)))        // Resolve it.
  1329.            if (!(err = AEGetParamDesc(theAppleEvent, keyAEData, typeWildCard, &data)))
  1330.               err = DoSetData(&token, &data);
  1331.     MyDisposeDescs(&target, &data, &token, kEndOfList);
  1332.     return(err);
  1333. }
  1334.  
  1335. //----------------------------------------------------------------------------------//
  1336. //    Return a reply to the Get Data or Get Data Size Apple Event for the requested    //
  1337. //    data. The refcon parameter is used to distinguish the two events. If typeBest    //
  1338. //    is the requested return type, the data's descriptor type is the result type.    //
  1339. //    **NOTE: Do not use the same descriptor as source and dest in AECoerceDesc().    //
  1340. //    This routine creates a copy of the source, and then it is impossible to dispose    //
  1341. //    of the memory originally contained in the source's dataHandle.                    //
  1342. //    2/25/92 - Removed FailIfErr calls. Now the error is returned as a result.        //
  1343. //----------------------------------------------------------------------------------//
  1344. #pragma segment Main
  1345. pascal
  1346. OSErr HandleGetData( AppleEvent*    theAppleEvent,
  1347.                      AppleEvent*    reply,
  1348.                      long            refCon    )        // kAEGetData or kAEGetDataSize.
  1349. {
  1350.     AEDesc            theObject, token;                // direct object and resolved token.
  1351.     AEDesc            objectData, tempDesc;            // object data, and coerced data.
  1352.     DescType        reqType;
  1353.     WindowPtr        window;
  1354.     Size            theSize;
  1355.     OSErr            err;
  1356.     
  1357.     MyInitDescs(&theObject, &objectData, &token, kEndOfList);
  1358.             //    First, get the direct objet.
  1359.     if (err = AEGetParamDesc(theAppleEvent, keyDirectObject, typeObjectSpecifier, &theObject))
  1360.         goto myExit;
  1361.             //    Next, get the requested return type, if it exists.
  1362.     if (err = AEGetParamPtr(theAppleEvent, keyAERequestedType, typeType, &reqType,
  1363.                                 (Ptr)&reqType, sizeof(DescType), &theSize))
  1364.     {
  1365.         if (err == errAEDescNotFound)        // not an error if return type is not found
  1366.         {
  1367.             err = noErr;
  1368.             reqType = typeWildCard;
  1369.         }
  1370.         else
  1371.             goto myExit;
  1372.     }
  1373.     if (err = GetMissingParams(theAppleEvent))            // check for missing params
  1374.         goto myExit;
  1375.  
  1376.             //    Resolve the object specifier and get the token containing the property and container.
  1377.     if (!(err = AEResolve(&theObject, kAEIDoMinimum, &token)))
  1378.         if (window = (WindowPtr)*(LongPtr)*token.dataHandle)        // Nil for application; WindowPtr for window
  1379.             err = GetWindowData(token.descriptorType, window, &objectData);
  1380.         else
  1381.             err = GetAppData(token.descriptorType, &objectData);
  1382.  
  1383.     if (err == noErr && reply->dataHandle != nil)
  1384.     {        //    Add data to the reply Apple event record.
  1385.         if (reqType != typeWildCard && reqType != typeBest &&
  1386.             reqType != objectData.descriptorType)
  1387.         {
  1388.             err = AECoerceDesc(&objectData, reqType, &tempDesc);
  1389.             MyDisposeDescs(&objectData, kEndOfList);
  1390.             objectData.descriptorType = tempDesc.descriptorType;
  1391.             objectData.dataHandle = tempDesc.dataHandle;
  1392.         }
  1393.         if (!err)
  1394.         {
  1395.             if (refCon == kAEGetData)                // return data
  1396.                 err = AEPutParamDesc(reply, keyAEResult, &objectData);
  1397.             else if (refCon == kAEGetDataSize)        // return data size
  1398.             {
  1399.                 theSize = GetHandleSize(objectData.dataHandle);
  1400.                   err = AEPutParamPtr(reply, keyAEResult, typeLongInteger, (Ptr)&theSize, sizeof(long));
  1401.             }
  1402.         }
  1403.     }
  1404.     
  1405. myExit:
  1406.     MyDisposeDescs(&theObject, &objectData, &token, kEndOfList);
  1407.     return(err);
  1408. }
  1409.  
  1410. //----------------------------------------------------------------------------------//
  1411. //    Send a Move Apple event to myself in response to a user selecting a window        //
  1412. //    and making it frontmost. This event is sent with the insertion location record    //
  1413. //    specifying the beginning of the null container. If the index is non-zero, this    //
  1414. //    indicates that the move event has already been performed by DragWindow(). Thus,    //
  1415. //    this event is passed with the don't execute flag set.                            //
  1416. //----------------------------------------------------------------------------------//
  1417. #pragma segment Main
  1418. void SendMoveEvent(WindowPtr windowToMove, long index)
  1419. {
  1420.     AppleEvent        myAppleEvent, reply, windowObject;
  1421.     AERecord        insertionRec;                    // Insertion Loc record.
  1422.     AEDesc            insertionLoc;                    // The coerced insertionRec.
  1423.     DescType        theType;
  1424.     
  1425.         //    Create the Apple Event.
  1426.     FailIfErr(AECreateAppleEvent(kAECoreSuite, kAEMove, &gSelfAddress, kAutoGenerateReturnID,
  1427.                                     kAnyTransactionID, &myAppleEvent));
  1428.         //    Create the object spec for the window to move.
  1429.     FailIfErr(CreateWindowObjectSpec(windowToMove, kIndexKeyForm, &windowObject));
  1430.     FailIfErr(AEPutParamDesc(&myAppleEvent, keyDirectObject, &windowObject));
  1431.  
  1432.         //    Create insertion loc record for beginning of null container.
  1433.     FailIfErr(AECreateList(nil, 0, true, &insertionRec));            // Create an AE Record.
  1434.     theType = kAEBeginning;
  1435.     FailIfErr(AEPutKeyDesc(&insertionRec, keyAEObject, &gNullDesc));
  1436.     FailIfErr(AEPutKeyPtr(&insertionRec,keyAEPosition,typeEnumeration,(Ptr)&theType,sizeof(DescType)));
  1437.     FailIfErr(AECoerceDesc(&insertionRec, typeInsertionLoc, &insertionLoc));
  1438.         // Now add the insertion location descriptor record to the Apple Event.
  1439.     FailIfErr(AEPutParamDesc(&myAppleEvent, keyAEInsertHere, &insertionLoc));
  1440.         //    Send the Apple Event.
  1441.     if (index)
  1442.           FailIfErr(AESend(&myAppleEvent, &reply, kAENoReply+kAECanInteract+kAEDontExecute,
  1443.                             kAENormalPriority, kAEDefaultTimeout, nil, nil));
  1444.     else
  1445.           FailIfErr(AESend(&myAppleEvent, &reply, kAENoReply+kAECanInteract,
  1446.                             kAENormalPriority, kAEDefaultTimeout, nil, nil));
  1447.  
  1448.         //    Now dispose of the AppleEvent and other records.
  1449.     MyDisposeDescs(&myAppleEvent,&windowObject,&insertionRec,&insertionLoc,kEndOfList);
  1450. }
  1451.  
  1452. //----------------------------------------------------------------------------------//
  1453. //    Respond to the Move Apple Event by reordering the window list.  For CoreSample,    //
  1454. //    the keyAEInsertHere parameter is optional. If this parameter does not exist,    //
  1455. //    the specified window will move the  to the front.                                //
  1456. //----------------------------------------------------------------------------------//
  1457. #pragma segment Main
  1458. pascal
  1459. OSErr HandleMove(AppleEvent* theAppleEvent, AppleEvent* reply, long refCon)
  1460. {
  1461.     #pragma unused (refCon)
  1462.     AEDesc            object, windowObj, replyObj, insertionLoc;
  1463.     AERecord        insertionRec;
  1464.     DescType        theType, position;
  1465.     WindowPtr        windowToMove, relativeWindow, rplcWindow;
  1466.     Rect            bounds;
  1467.     Size            paramSize;
  1468.     OSErr            err;
  1469.     
  1470.     MyInitDescs(&object,&windowObj,&insertionLoc,&insertionRec,&replyObj,kEndOfList);
  1471.         //    First, get the direct parameter, the object to move.
  1472.     if (err = AEGetParamDesc(theAppleEvent, keyDirectObject, typeObjectSpecifier, &object))
  1473.         goto myExit;
  1474.     if (!(windowToMove = ResolveToWindow(&object)))            // Check if valid window object.
  1475.     {
  1476.         err = errAENoSuchObject;
  1477.         goto myExit;
  1478.     }
  1479.  
  1480.         // Retrieve the insertion location record, if it exists.
  1481.     if ((err = AEGetParamDesc(theAppleEvent,keyAEInsertHere,typeInsertionLoc,&insertionLoc)) == errAEDescNotFound)
  1482.     {            // Execute *MY* default behavior since insertion loc param not present.
  1483.         SelectWindow(windowToMove);
  1484.         err = noErr;
  1485.         goto myExit;
  1486.     }
  1487.     else
  1488.         if (err)
  1489.             goto myExit;
  1490.         else            // get data from insertion loc and coerce it to typeAERecord.
  1491.         {
  1492.             if ((err = GetMissingParams(theAppleEvent))  ||
  1493.                 (err = AECoerceDesc(&insertionLoc, typeAERecord, &insertionRec)) || 
  1494.                 (err = AEGetKeyDesc(&insertionRec,keyAEObject,typeWildCard,&windowObj)) ||
  1495.                 (err = AEGetKeyPtr(&insertionRec,keyAEPosition,typeEnumeration,&theType,
  1496.                                     (Ptr)&position,sizeof(DescType),¶mSize)))
  1497.                     goto myExit;
  1498.         }
  1499.  
  1500.     if (!(err = FindRelativeWindow(&relativeWindow,&windowObj,position,&rplcWindow)))
  1501.     {
  1502.         if (position == kAEReplace)
  1503.             if (windowToMove == rplcWindow)
  1504.                 goto myExit;                // do nothing.
  1505.             else
  1506.             {
  1507.                 bounds = (*((WindowPeek)rplcWindow)->contRgn)->rgnBBox;
  1508.                 CloseTheWindow(rplcWindow);
  1509.                 MoveWindow(windowToMove, bounds.left, bounds.top, false);
  1510.             }
  1511.  
  1512.         if (relativeWindow == -1)
  1513.             SelectWindow(windowToMove);
  1514.         else
  1515.             if (windowToMove != relativeWindow)
  1516.                 SendBehind(windowToMove, relativeWindow);        // NOTE: may have to call PaintOne and
  1517.                                                                 // CalcVis if after; see IM I-286
  1518.         if (position == kAEReplace && windowToMove != rplcWindow)
  1519.         {
  1520.             bounds = (*((WindowPeek)rplcWindow)->contRgn)->rgnBBox;
  1521.             CloseTheWindow(rplcWindow);
  1522.             MoveWindow(windowToMove, bounds.left, bounds.top, false);
  1523.         }
  1524.     }
  1525.  
  1526. myExit:
  1527.     if (!err)
  1528.         if (reply->dataHandle != nil)
  1529.         {
  1530.             CreateWindowObjectSpec(windowToMove, kIndexKeyForm, &replyObj);
  1531.             err = AEPutParamDesc(reply, keyAEResult, &replyObj);
  1532.         }
  1533.     MyDisposeDescs(&object,&windowObj,&insertionLoc,&insertionRec,&replyObj,kEndOfList);
  1534.     return(err);
  1535. }
  1536.  
  1537. //----------------------------------------------------------------------------------//
  1538. //    Set up the descriptor records needed to set the data for the bounds, position,    //
  1539. //    and zoomed properties.  The bounds is set in response to sizing a window; the    //
  1540. //    position is set after dragging a window; and the isZoomed property is set when    //
  1541. //    zooming a window in or out.                                                        //
  1542. //----------------------------------------------------------------------------------//
  1543. #pragma segment Main
  1544. void SetUpPropertyData( WindowPtr        window,            // Window object.
  1545.                         DescType        propType,        // Property descriptor type.
  1546.                         DescType        dataType,        // Descriptor type for data.
  1547.                         Size            dataSize   )    // Size of data.
  1548. {
  1549.     AEDesc        windowObject, theData, theProperty;
  1550.     Rect        bounds;
  1551.     Boolean        isZoomed;
  1552.     
  1553.     MyInitDescs(&windowObject, &theData, &theProperty, kEndOfList);
  1554.     if (propType == pIsZoomed)
  1555.     {
  1556.         isZoomed = (Boolean)GetWRefCon(window);
  1557.         FailIfErr(AECreateDesc(dataType,(Ptr)&isZoomed,dataSize,&theData));
  1558.     }
  1559.     else        // it's either pBounds or pPosition.
  1560.     {
  1561.           bounds = (*((WindowPeek)window)->contRgn)->rgnBBox;        // Use the content region.
  1562.         FailIfErr(AECreateDesc(dataType, (Ptr)&bounds, dataSize, &theData));
  1563.     }
  1564.         
  1565.     CreateWindowObjectSpec(window, kIndexKeyForm, &windowObject);
  1566.     FailIfErr(AECreateDesc(typeType, (Ptr)&propType, sizeof(DescType), &theProperty));
  1567.  
  1568.     SendSetData(&theProperty, &theData, &windowObject);
  1569.     MyDisposeDescs(&windowObject, &theData, &theProperty, kEndOfList);
  1570. }
  1571.  
  1572. //----------------------------------------------------------------------------------//
  1573. //    Set the property data for the specified object.  For now, we only handle window    //
  1574. //    objects, and you may only set the modifiable properties (defined in Registry).    //
  1575. //    *NOTE*:  We do not allow the application's properties to be modified.            //
  1576. //----------------------------------------------------------------------------------//
  1577. #pragma segment Main
  1578. OSErr DoSetData( AEDesc*    token,                // Contains the property and object.
  1579.                  AEDesc*    data    )            // Contains the data to set.
  1580. {
  1581.     AEDesc            propData;            // Property data.
  1582.     Rect            bounds;
  1583.     GrafPtr            oldPort;
  1584.     WindowPtr        window, behindWindow;
  1585.     Str255            name;
  1586.     long            newIndex;
  1587.     short            part;
  1588.     Boolean            value;
  1589.     Point            pt;
  1590.     OSErr            err;
  1591.  
  1592.     err = noErr;
  1593.     if (window = (WindowPtr)*(LongPtr)*(token->dataHandle))
  1594.     {
  1595.         GetPort(&oldPort);
  1596.         switch (token->descriptorType)
  1597.         {
  1598.             case pBounds:
  1599.                 if (data->descriptorType != typeQDRectangle)
  1600.                 {
  1601.                     propData.dataHandle = nil;
  1602.                     err = AECoerceDesc(data, typeQDRectangle, &propData);
  1603.                     bounds = *(Rect *)*propData.dataHandle;        // Get content region.
  1604.                     MyDisposeDescs(&propData, kEndOfList);
  1605.                 }
  1606.                 else
  1607.                     bounds = *(Rect *)*data->dataHandle;        // Get content region.
  1608.         
  1609.                 if (!err)
  1610.                 {
  1611.                     SetPort(window);
  1612.                     InvalRect(&window->portRect);
  1613.         
  1614.                         // Real applications may want to make a sanity check on the new bounds.        
  1615.                     MoveWindow(window, bounds.left, bounds.top, false);
  1616.                      SizeWindow(window, bounds.right-bounds.left, bounds.bottom-bounds.top, true);
  1617.                     InvalRect(&window->portRect);
  1618.                 }
  1619.                 break;
  1620.             
  1621.             case pIndex:
  1622.                 if (DescToLong(data,&newIndex) != noErr)
  1623.                     return(errAECoercionFail);        // Data cannot be coerced.
  1624.  
  1625.                 if (newIndex > gNumWindowsOpen)
  1626.                     err = errAEIndexTooLarge;
  1627.                 else
  1628.                 {
  1629.                     if (newIndex == 1)
  1630.                         SelectWindow(window);
  1631.                     else
  1632.                         if (behindWindow = GetWindowAtIndex(newIndex))
  1633.                             SendBehind(window, behindWindow);
  1634.                         else
  1635.                             err = errAEEventFailed;
  1636.                 }
  1637.                 break;
  1638.                 
  1639.             case pIsZoomed:
  1640.                 if (DescToBoolean(data,&value) != noErr)
  1641.                     return(errAECoercionFail);            // Data cannot be coerced.
  1642.                     
  1643.                 part = value ? inZoomOut : inZoomIn;
  1644.                 ZoomIt(window, part);
  1645.                 break;
  1646.  
  1647.             case pName:
  1648.                 if (DescToPString(data,name,kMaxStrSize) != noErr)
  1649.                     return(errAECoercionFail);
  1650.                 SetWTitle(window, name);
  1651.                 break;
  1652.             
  1653.             case pPosition:
  1654.                 if (data->descriptorType != typeQDPoint)
  1655.                 {
  1656.                     propData.dataHandle = nil;
  1657.                     err = AECoerceDesc(data, typeQDPoint, &propData);
  1658.                     pt = *(Point *)*propData.dataHandle;
  1659.                     MyDisposeDescs(&propData, kEndOfList);
  1660.                 }
  1661.                 else
  1662.                     pt = *(Point *)*data->dataHandle;
  1663.  
  1664.                 if (!err)
  1665.                 {
  1666.                         // Real applications may want to make a sanity check on the new loc.
  1667.                     SetPort(window);
  1668.                     MoveWindow(window, pt.h, pt.v, false);
  1669.                     InvalRect(&window->portRect);
  1670.                 }
  1671.                 break;
  1672.             
  1673.             case pVisible:
  1674.                 if (DescToBoolean(data,&value) != noErr)
  1675.                     return(errAECoercionFail);        // Data cannot be coerced.
  1676.                 if (value)
  1677.                     ShowWindow(window);
  1678.                 else
  1679.                     HideWindow(window);
  1680.                 break;
  1681.                 
  1682.             default:                        // No other properties are modifiable.
  1683.                 return(errAENotModifiable);
  1684.         }
  1685.         SetPort(oldPort);
  1686.     }
  1687.     else
  1688.         return(errAEEventFailed);
  1689.     return(err);
  1690. }
  1691.  
  1692. //----------------------------------------------------------------------------------//
  1693. //    This is a dummy handler that receives Apple events which I don't handle.  It     //
  1694. //    is mainly provided as a stub in order to support all the events in the             //
  1695. //    required suite, as well as the entire core suite.  This is the handler for the    //
  1696. //    Open Document and Print Document events (required suite); and the Save, Get     //
  1697. //    Class Info,    and Get Event Info events (core suite).  The Get Class Info and Get    //
  1698. //    Event Info events "MAY" be supported internally in the future, so applications    //
  1699. //    will not need to handle these events themselves.  This support may be provided    //
  1700. //    since it would be consistent across all applications, and the information may    //
  1701. //    be retrieved from the 'aeut'/'aete' resources.                                    //
  1702. //----------------------------------------------------------------------------------//
  1703. #pragma segment Main
  1704. pascal
  1705. OSErr DummyHandler( AppleEvent        *theAppleEvent,
  1706.                     AppleEvent        *reply,
  1707.                     long            refCon    )
  1708. {
  1709.     #pragma unused (theAppleEvent,reply,refCon)
  1710.     return(errAEEventNotHandled);
  1711. }
  1712.  
  1713. //----------------------------------------------------------------------------------//
  1714. //    Locate the window that is relative to the specified window object at the        //
  1715. //    insertion position.  If the location is replace, the window to replace is         //
  1716. //    closed, and its bounds are returned to the calling routine.                        //
  1717. //    **Note**: if windowObj is used within this routine, the object param will        //
  1718. //    contain the same dataHandle. This will be disposed of by the calling routine.    //
  1719. //----------------------------------------------------------------------------------//
  1720. #pragma segment Main
  1721. OSErr FindRelativeWindow( WindowPtr*    relativeWindow,    // window before insertion loc.
  1722.                           AEDesc*        object,            // object to be relative to.
  1723.                           DescType        position,            // insertion position.
  1724.                           WindowPtr*    replaceWindow )    // window to replace.
  1725. {
  1726.     AEDesc        windowObj;                    // Coerced descriptor.
  1727.     WindowPtr    windowToReplace;
  1728.     long        index;
  1729.     OSErr        err;
  1730.     
  1731.     err = noErr;
  1732.     *replaceWindow = nil;
  1733.     switch(position)
  1734.     {
  1735.         case kAEBeginning:                        // The object should be the container.
  1736.             if (object->descriptorType == typeNull)
  1737.                 *relativeWindow = (WindowPtr)-1;
  1738.             else
  1739.                 err = errAENoSuchObject;
  1740.             break;
  1741.         
  1742.         case kAEEnd:                            // The object should be the container.
  1743.             if (object->descriptorType == typeNull)
  1744.                 *relativeWindow = nil;
  1745.             else
  1746.                 err = errAENoSuchObject;
  1747.             break;
  1748.             
  1749.         case kAEBefore:                            // The object should be an object specifier.
  1750.         case kAEReplace:
  1751.             if (object->descriptorType != typeObjectSpecifier)
  1752.             {
  1753.                 err = AECoerceDesc(object, typeObjectSpecifier, &windowObj);
  1754.                 MyDisposeDescs(object, kEndOfList);
  1755.                 object->descriptorType = windowObj.descriptorType;
  1756.                 object->dataHandle = windowObj.dataHandle;
  1757.             }
  1758.             
  1759.             if (!err)
  1760.                 if (windowToReplace = ResolveToWindow(object))
  1761.                 {
  1762.                     index = GetWindowIndexNum(windowToReplace);
  1763.                     *relativeWindow = (index==1) ? (WindowPtr)-1 : GetWindowAtIndex(index-1);
  1764.                     if (position == kAEReplace)
  1765.                         *replaceWindow = windowToReplace;
  1766.             }
  1767.             else            // We weren't able to resolve the object specifier to a window.
  1768.                 err = errAENoSuchObject;
  1769.             break;
  1770.             
  1771.         case kAEAfter:                        // The object should be an object specifier.
  1772.             if (object->descriptorType != typeObjectSpecifier)
  1773.             {
  1774.                 err = AECoerceDesc(object,typeObjectSpecifier,&windowObj);
  1775.                 MyDisposeDescs(object, kEndOfList);
  1776.                 object->descriptorType = windowObj.descriptorType;
  1777.                 object->dataHandle = windowObj.dataHandle;
  1778.             }
  1779.  
  1780.             if (!err)
  1781.                 if (!(*relativeWindow = ResolveToWindow(object)))
  1782.                     err = errAENoSuchObject;
  1783.             break;
  1784.             
  1785.         default:
  1786.             return(errAEEventNotHandled);
  1787.     }
  1788.     return(err);
  1789. }
  1790.  
  1791. //----------------------------------------------------------------------------------//
  1792. //    Retrieves the data for the specified property of the window.  The result token    //
  1793. //    contains the type of the data in the descriptorType field, and the data itself    //
  1794. //    in the dataHandle field.  I know my application's window properties             //
  1795. //    (i.e., has title bar, has close box, is zoomable, etc.), so I set up the         //
  1796. //    result token accordingly.  If your application handles various window types,    //
  1797. //    you may need to look at the window defproc to determine which type of window it    //
  1798. //    is.  If the property is pBestType or pDefaultType, I return an object specifier//
  1799. //    for the window which may be used to easily reference it.                        //
  1800. //----------------------------------------------------------------------------------//
  1801. #pragma segment Main
  1802. OSErr GetWindowData( DescType        theProperty,        // Window property.
  1803.                      WindowPtr        window,
  1804.                      AEDesc            *result    )            // Contains the result upon return.
  1805. {
  1806.     DescType        theType;
  1807.     Str255            title;
  1808.     Rect            bounds;
  1809.     long            index;
  1810.     Boolean            myAnswer;
  1811.  
  1812.     switch (theProperty)
  1813.     {
  1814.         case pBestType:
  1815.         case pDefaultType:
  1816.             return(CreateWindowObjectSpec(window, kIndexKeyForm, result));
  1817.  
  1818.         case pBounds:
  1819.               bounds = (*((WindowPeek)window)->contRgn)->rgnBBox;        // Use the content region.
  1820.             return(AECreateDesc(typeQDRectangle, (Ptr)&bounds, sizeof(Rect), result));
  1821.             
  1822.         case pClass:
  1823.             theType = cWindow;
  1824.             return(AECreateDesc(typeType, (Ptr)&theType, sizeof(DescType), result));
  1825.  
  1826.         case pIndex:
  1827.             index = GetWindowIndexNum(window);
  1828.             return(AECreateDesc(typeLongInteger, (Ptr)&index, sizeof(long), result));
  1829.                 
  1830.         case pName:
  1831.             GetWTitle(window, title);
  1832.             return(AECreateDesc(typeChar, (Ptr)&title[1], title[0], result));
  1833.  
  1834.         case pPosition:
  1835.               bounds = (*((WindowPeek)window)->contRgn)->rgnBBox;        // Use the content region.
  1836.             return(AECreateDesc(typeQDPoint, (Ptr)&bounds, sizeof(Point), result));
  1837.  
  1838.         case pHasCloseBox:
  1839.         case pHasTitleBar:
  1840.         case pIsResizable:
  1841.         case pIsZoomable:
  1842.             myAnswer = true;
  1843.             return(AECreateDesc(typeBoolean, (Ptr)&myAnswer, sizeof(Boolean), result));
  1844.  
  1845.         case pIsFloating:
  1846.         case pIsModal:
  1847.             myAnswer = false;
  1848.             return(AECreateDesc(typeBoolean, (Ptr)&myAnswer, sizeof(Boolean), result));
  1849.             
  1850.         case pIsZoomed:
  1851.             myAnswer = GetWRefCon(window);
  1852.             return(AECreateDesc(typeBoolean, (Ptr)&myAnswer, sizeof(Boolean), result));
  1853.         
  1854.         case pVisible:                    // Must check this because it is modifiable.
  1855.             myAnswer = ((WindowPeek)window)->visible;
  1856.             return(AECreateDesc(typeBoolean, (Ptr)&myAnswer, sizeof(Boolean), result));
  1857.  
  1858.         case pSelection:                // No selection in CoreSample.
  1859.             return(errAENoSuchObject);
  1860.  
  1861.         default:                        // We don't handle requested property.
  1862.             return(errAEEventNotHandled);
  1863.     }
  1864. }
  1865.  
  1866. //----------------------------------------------------------------------------------//
  1867. //    Get the property data for the application and return it in the result parameter.//
  1868. //    The result token contains the property type in the descriptorType field, and    //
  1869. //    a nil value in the dataHandle field to represent the null application.            //
  1870. //----------------------------------------------------------------------------------//
  1871. #pragma segment Main
  1872. OSErr GetAppData(    DescType    theProperty,
  1873.                     AEDesc*        result    )        // Descriptor record to hold the property data.
  1874. {
  1875.     DescType                theType;
  1876.     short                    refNum;
  1877.     Str255                    name;
  1878.     Handle                    myHandle;
  1879.     ProcessSerialNumber        thePSN;
  1880.     Boolean                    isFront;
  1881.     OSErr                    err;
  1882.  
  1883.     switch (theProperty)
  1884.     {
  1885.         case pBestType:                    // Return the null descriptor representing
  1886.         case pDefaultType:                // the application.
  1887.             return(AEDuplicateDesc(&gNullDesc, result));
  1888.  
  1889.         case pClass:
  1890.             theType = cApplication;
  1891.             return(AECreateDesc(typeType,(Ptr)&theType,sizeof(DescType),result));
  1892.             
  1893.         case pName:
  1894.             GetAppParms(name, &refNum, &myHandle);
  1895.             return(AECreateDesc(typeChar, (Ptr)&name[1], name[0], result));
  1896.  
  1897.         case pIsFrontProcess:
  1898.             GetFrontProcess(&thePSN);
  1899.             SameProcess(&gSelfPSN, &thePSN, &isFront);
  1900.             return(AECreateDesc(typeBoolean,(Ptr)&isFront,sizeof(Boolean),result));
  1901.             
  1902.         case pVersion:
  1903.             refNum = CurResFile();            // save current resource
  1904.             UseResFile(gRefNum);            // set this resource to be current
  1905.             myHandle = (Handle)Get1Resource((ResType)'vers', 1);
  1906.               HLock(myHandle);
  1907.              err = AECreateDesc(typeVersion, *myHandle, GetHandleSize(myHandle), result);
  1908.               HUnlock(myHandle);
  1909.             UseResFile(refNum);                // reset back to resource previously set
  1910.             return(err);
  1911.  
  1912.         default:                // We don't handle the requested property.
  1913.             return(errAEEventNotHandled);
  1914.     }
  1915. }
  1916.  
  1917. //----------------------------------------------------------------------------------//
  1918. //    Create an object specifier for the window with the indicated key form.            //
  1919. //----------------------------------------------------------------------------------//
  1920. #pragma segment Main
  1921. OSErr CreateWindowObjectSpec( WindowPtr    window,
  1922.                               short        keyForm,        // index or name key form.
  1923.                                 AEDesc*    objectSpec )    // Resulting object specifier.
  1924. {
  1925.     AEDesc        data;
  1926.     Str255        title;
  1927.     long        index;
  1928.     OSErr        err;
  1929.  
  1930.     MyInitDescs(&data, kEndOfList);
  1931.     switch(keyForm)
  1932.     {
  1933.         case kNameKeyForm:                    // Object specifier with name.
  1934.             GetWTitle(window, title);
  1935.             if (!(err = AECreateDesc(typeChar, (Ptr)&title[1], title[0], &data)))                
  1936.                 err = CreateObjSpecifier(cWindow, &gNullDesc, formName, &data,
  1937.                                     false, objectSpec);
  1938.             break;
  1939.             
  1940.         case kIndexKeyForm:                    // Object specifier with index.
  1941.             index = GetWindowIndexNum(window);
  1942.             if (!(err = CreateOffsetDescriptor(index, &data)))
  1943.                 err = CreateObjSpecifier(cWindow, &gNullDesc, formAbsolutePosition, &data,
  1944.                                     false, objectSpec);
  1945.             break;
  1946.     }
  1947.     MyDisposeDescs(&data, kEndOfList);
  1948.     return(err);
  1949. }
  1950.  
  1951. //----------------------------------------------------------------------------------//
  1952. //    Check to see if there exists any additional parameters in the Apple Event.      //
  1953. //    If so, return an error to the calling routine.                                    //
  1954. //----------------------------------------------------------------------------------//
  1955. #pragma segment Main
  1956. OSErr GetMissingParams(AppleEvent*  theAppleEvent)
  1957. {
  1958.     DescType    theType;
  1959.     Size        actualSize;
  1960.     OSErr        err;
  1961.     
  1962.     err = AEGetAttributePtr(theAppleEvent, keyMissedKeywordAttr, typeWildCard,
  1963.                                 &theType, nil, 0, &actualSize);
  1964.     if (err == errAEDescNotFound)
  1965.         return(noErr);
  1966.     else
  1967.         return(errAEEventNotHandled);
  1968. }
  1969.  
  1970. //----------------------------------------------------------------------------------//
  1971. //    If a reply is expected, the error number is returned in the reply parameter.    //
  1972. //----------------------------------------------------------------------------------//
  1973. #pragma segment Main
  1974. void ReportError( AppleEvent*    reply,
  1975.                   long            err    )
  1976. {
  1977.     if (reply->dataHandle != nil && err != noErr)
  1978.         FailIfErr(AEPutParamPtr(reply,keyErrorNumber,typeLongInteger,(Ptr)&err,sizeof(long)));
  1979. }
  1980.  
  1981. //----------------------------------------------------------------------------------//
  1982. //    This routine returns the window object contained in the given object specifier.    //
  1983. //    If the resolution does not return a descriptor record of type cWindow, nil is     //
  1984. //    returned as a result.                                                            //
  1985. //----------------------------------------------------------------------------------//
  1986. #pragma segment Main
  1987. WindowPtr ResolveToWindow(AEDesc*  objectSpecifier)
  1988. {
  1989.     AEDesc        token;
  1990.     WindowPtr    window;
  1991.  
  1992.  
  1993.     MyInitDescs(&token, kEndOfList);
  1994.     window = nil;
  1995.     if (objectSpecifier->descriptorType == typeObjectSpecifier)
  1996.         if (!(AEResolve(objectSpecifier, kAEIDoMinimum, &token)))
  1997.             if (token.descriptorType == cWindow)
  1998.                 window = (WindowPtr)*((LongPtr)*(token.dataHandle));
  1999.  
  2000.     MyDisposeDescs(&token, kEndOfList);
  2001.     return(window);
  2002. }
  2003.  
  2004. //----------------------------------------------------------------------------------//
  2005. //    Retrieve the window from the null container by the key form and return its        //
  2006. //    pointer in the dataHandle field of resultToken.                                    //
  2007. //----------------------------------------------------------------------------------//
  2008. #pragma segment Main
  2009. pascal
  2010. OSErr WindowAccessor( DescType        classWanted,        // window class
  2011.                       AEDesc*        container,            // the application (null container)
  2012.                       DescType        containerClass, 
  2013.                       DescType        keyform,
  2014.                       AEDesc*        selectionData,
  2015.                       AEDesc*        resultToken,        // specified window is returned in result
  2016.                       long             theRefCon     )
  2017. {
  2018.     #pragma unused (classWanted,container,containerClass,theRefCon)
  2019.     WindowPtr        window;
  2020.     DescType        seldataType;
  2021.     Str255            title;
  2022.     long            index;
  2023.     OSErr            err;
  2024.  
  2025.     window = nil;
  2026.     err = noErr;    
  2027.     if (!gNumWindowsOpen)
  2028.         return(errAENoSuchObject);
  2029.     else
  2030.     {
  2031.         seldataType = selectionData->descriptorType;
  2032.     
  2033.         switch(keyform)
  2034.         {
  2035.             case formName:                                    // Window title.
  2036.                 if (DescToPString(selectionData,title,kMaxStrSize) != noErr)
  2037.                     return(errAECoercionFail);
  2038.                 if (!(window = GetWindowWithTitle(title)))
  2039.                     return(errAENoSuchObject);        // Window was not found.
  2040.                 break;
  2041.             
  2042.             case formAbsolutePosition:
  2043.                 if (DescToLong(selectionData,&index) != noErr)
  2044.                     return(errAECoercionFail);        // Data cannot be coerced.
  2045.                 if (!(window = GetWindowAtIndex(index)))
  2046.                     return(errAENoSuchObject);            // Window was not found.
  2047.                 break;    
  2048.             
  2049.             default:                                    // I don't handle any other key forms.
  2050.                 return(errAEEventNotHandled);
  2051.         }
  2052.     }
  2053.     return(AECreateDesc(cWindow, (Ptr)&window, sizeof(Ptr), resultToken));
  2054. }
  2055.  
  2056. //----------------------------------------------------------------------------------//
  2057. //    Return a token representing the property for the containing window.  The token    //
  2058. //    is returned with the property and window pointer.                                //
  2059. //----------------------------------------------------------------------------------//
  2060. #pragma segment Main
  2061. pascal
  2062. OSErr WindowPropertyAccessor( DescType        classWanted,        // Property class
  2063.                                 AEDesc*        container,            // Window object
  2064.                               DescType        containerClass, 
  2065.                               DescType        form,
  2066.                               AEDesc*        selectionData,
  2067.                               AEDesc*        resultToken,
  2068.                               long             theRefCon     )
  2069. {
  2070.     #pragma unused (containerClass, theRefCon)
  2071.     Ptr                window;
  2072.     DescType        propType;
  2073.     
  2074.             //    Let's make sure we're accessing a valid descriptor type.
  2075.     if ((classWanted != cProperty) || (form != formPropertyID))
  2076.         return(errAEWrongDataType);
  2077.  
  2078.     window = (Ptr)*(LongPtr)*(container->dataHandle);        // Get the window pointer.
  2079.     propType = *(LongPtr)*selectionData->dataHandle;        // Get the property type.
  2080.     return(AECreateDesc(propType, (Ptr)&window, sizeof(Ptr), resultToken)); 
  2081. }
  2082.  
  2083. //----------------------------------------------------------------------------------//
  2084. //    Return a token that contains the property type and nil to represent the null    //
  2085. //    container (the application).                                                    //
  2086. //----------------------------------------------------------------------------------//
  2087. #pragma segment Main
  2088. pascal
  2089. OSErr AppPropertyAccessor(    DescType        classWanted,            // Property class.
  2090.                               AEDesc*            container,                // Application.
  2091.                             DescType        containerClass, 
  2092.                             DescType        form,
  2093.                             AEDesc*            selectionData,
  2094.                             AEDesc*            resultToken,
  2095.                             long             theRefCon     )
  2096. {    
  2097.     #pragma unused (container,containerClass,theRefCon)
  2098.     DescType        propType;
  2099.     long            nilValue;
  2100.     
  2101.             //    Let's make sure we're accessing a valid descriptor type.
  2102.     if ((classWanted != cProperty) || (form != formPropertyID))
  2103.         return(errAEWrongDataType);
  2104.     nilValue = nil;        
  2105.     propType = *(LongPtr)*selectionData->dataHandle;            // Get the property type.
  2106.     return(AECreateDesc(propType, (Ptr)&nilValue, sizeof(long), resultToken)); 
  2107. }
  2108.  
  2109. //----------------------------------------------------------------------------------//
  2110. //    Returns the window with the given title if found.  Otherwise, nil is returned.    //
  2111. //    Use WindowList in order to find windows that may be invisible.                    //
  2112. //----------------------------------------------------------------------------------//
  2113. #pragma segment Main
  2114. WindowPtr GetWindowWithTitle( ConstStr255Param  titleToFind )
  2115. {
  2116.     WindowPeek    window;
  2117.     Str255        thisTitle;
  2118.     
  2119.     window = *(PeekPtr)WindowList;        // WindowList finds invisible windows as well.
  2120.     while (window)
  2121.     {
  2122.         GetWTitle((WindowPtr)window, thisTitle);
  2123.         if (EqualString(thisTitle, titleToFind, false, false))
  2124.             return((WindowPtr)window);
  2125.         window = window->nextWindow;
  2126.     }
  2127.     return(nil);
  2128. }
  2129.  
  2130. //----------------------------------------------------------------------------------//
  2131. //    Search all windows (including invisible), and return the window at the given     //
  2132. //    index if found. Otherwise, nil is returned. This routine also handles negative    //
  2133. //    indices which indicates that the offset    is from the end of the container.        //                                    //
  2134. //----------------------------------------------------------------------------------//
  2135. #pragma segment Main
  2136. WindowPtr GetWindowAtIndex(long  index)
  2137. {
  2138.     WindowPeek    window;
  2139.     short        count;
  2140.     
  2141.     index = index < 0 ? gNumWindowsOpen+index+1 : index;
  2142.     count = 1;
  2143.     window = *(PeekPtr)WindowList;        // WindowList contains ALL windows.
  2144.     while (window)
  2145.     {
  2146.         if (count == index)
  2147.             return((WindowPtr)window);
  2148.         window = window->nextWindow;
  2149.         count++;
  2150.     }
  2151.     return(nil);
  2152. }
  2153.  
  2154. //----------------------------------------------------------------------------------//
  2155. //    Returns the index number of the given window, where 1 is the frontmost.            //
  2156. //----------------------------------------------------------------------------------//
  2157. #pragma segment Main
  2158. long GetWindowIndexNum(WindowPtr myWindow)
  2159. {
  2160.     WindowPeek    thisWindow;
  2161.     long        index;
  2162.     
  2163.     thisWindow = *(PeekPtr)WindowList;
  2164.     index = 1;
  2165.     
  2166.     while (thisWindow)
  2167.     {
  2168.         if (thisWindow == myWindow)
  2169.             return(index);
  2170.         thisWindow = thisWindow->nextWindow;
  2171.         index++;
  2172.     }
  2173.     return(nil);
  2174. }
  2175.  
  2176. //----------------------------------------------------------------------------------//
  2177. #pragma    segment Initialize
  2178. void InitAEHandlers()
  2179. {
  2180.     AEInstallEventHandler(kCoreEventClass,kAEOpenApplication,(EventHandlerProcPtr)HandleOpenApp,nil,false);
  2181.     AEInstallEventHandler(kCoreEventClass,kAEOpenDocuments,(EventHandlerProcPtr)DummyHandler,nil,false);
  2182.     AEInstallEventHandler(kCoreEventClass,kAEPrintDocuments,(EventHandlerProcPtr)DummyHandler,nil,false);
  2183.     AEInstallEventHandler(kCoreEventClass, kAEQuitApplication, (EventHandlerProcPtr)HandleQuitApp, nil, false);
  2184.     AEInstallEventHandler(kAECoreSuite, kAEClone, (EventHandlerProcPtr)HandleClone, nil, false);
  2185.     AEInstallEventHandler(kAECoreSuite, kAEClose, (EventHandlerProcPtr)HandleClose, nil, false);
  2186.     AEInstallEventHandler(kAECoreSuite, kAECountElements, (EventHandlerProcPtr)HandleCountElements, nil, false);
  2187.     AEInstallEventHandler(kAECoreSuite, kAECreateElement, (EventHandlerProcPtr)HandleCreateElement, nil, false);
  2188.     AEInstallEventHandler(kAECoreSuite, kAEDelete, (EventHandlerProcPtr)HandleClose, nil, false);
  2189.     AEInstallEventHandler(kAECoreSuite, kAEDoObjectsExist, (EventHandlerProcPtr)HandleDoObjectsExist, nil, false);
  2190.     AEInstallEventHandler(kAECoreSuite, kAEGetData, (EventHandlerProcPtr)HandleGetData, kAEGetData, false);
  2191.     AEInstallEventHandler(kAECoreSuite, kAEGetDataSize, (EventHandlerProcPtr)HandleGetData, kAEGetDataSize, false);
  2192.     AEInstallEventHandler(kAECoreSuite, kAEGetClassInfo, (EventHandlerProcPtr)DummyHandler, nil, false);
  2193.     AEInstallEventHandler(kAECoreSuite, kAEGetEventInfo, (EventHandlerProcPtr)DummyHandler, nil, false);
  2194.     AEInstallEventHandler(kAECoreSuite, kAEMove, (EventHandlerProcPtr)HandleMove, nil, false);
  2195.     AEInstallEventHandler(kAECoreSuite, kAESave, (EventHandlerProcPtr)DummyHandler, nil, false);
  2196.     AEInstallEventHandler(kAECoreSuite, kAESetData, (EventHandlerProcPtr)HandleSetData, nil, false);
  2197.  
  2198.     AEObjectInit();
  2199.     AEInstallObjectAccessor(cWindow, typeNull, (accessorProcPtr)WindowAccessor, nil, false);
  2200.     AEInstallObjectAccessor(cProperty, typeNull, (accessorProcPtr)AppPropertyAccessor, nil, false);
  2201.     AEInstallObjectAccessor(cProperty, cWindow, (accessorProcPtr)WindowPropertyAccessor, nil, false);
  2202. }
  2203.