home *** CD-ROM | disk | FTP | other *** search
/ QuickTime 2.0 Beta / Quicktime 2.0 Beta.iso / Programming Stuff / Sample Code / DTS Sample Code / MyQuickTimeApp ƒ / MyApplication Shell (2.01).c next >
Encoding:
C/C++ Source or Header  |  1994-03-14  |  24.5 KB  |  889 lines  |  [TEXT/KAHL]

  1. /*
  2.     File:        MyApplication Shell (2.01).c
  3.     
  4.     Contains:    My Application Shell.
  5.  
  6.     Written by:    John Wang
  7.  
  8.     Copyright:    © 1994 by Apple Computer, Inc., all rights reserved.
  9.  
  10.     Change History (most recent first):
  11.  
  12.         <2>        04/19/94    JW        Added changes to init routine to create large master pointer blocks.
  13.         <1>        03/14/94    JW        Re-Created for Universal Headers.
  14.  
  15.     To Do:
  16.     
  17. */
  18.  
  19. #ifdef THINK_C
  20. #define        applec
  21. #endif
  22.  
  23. #include    <Types.h>
  24. #include    <Memory.h>
  25. #include    <QuickDraw.h>
  26. #include    <Palettes.h>
  27. #include    <QDOffscreen.h>
  28. #include    <Errors.h>
  29. #include    <Fonts.h>
  30. #include    <Dialogs.h>
  31. #include    <Windows.h>
  32. #include    <Menus.h>
  33. #include    <Events.h>
  34. #include    <Desk.h>
  35. #include    <DiskInit.h>
  36. #include    <OSUtils.h>
  37. #include    <Resources.h>
  38. #include    <ToolUtils.h>
  39. #include    <AppleEvents.h>
  40. #include    <EPPC.h>
  41. #include    <GestaltEqu.h>
  42. #include    <Processes.h>
  43. #include    <Balloons.h>
  44. #include    <Aliases.h>
  45. #include    <MixedMode.h>
  46. #include    <Scrap.h>
  47. #include    <LowMem.h>
  48.  
  49. #include    "MyApplication Shell (2.01).h"
  50. #include    "MyApplication.h"
  51.  
  52. #ifdef powerc
  53. QDGlobals        qd;
  54. #endif
  55.  
  56. Boolean            gDoneFlag;            //    Set to true if you want to Application to kindly quit.
  57. Boolean            gHasAppleEvents;    //    true if Gestalt returns saying AppleEvents is available.
  58. short            gScrapCount;        //    Keep track of scrap count.
  59. OSType            gScrapType;            //    Needed to know what type scrap it is.
  60. Handle            gScrap;                //    Must keep a handle to the scrap for update events that
  61.                                     //    happen in the background.  The reason is that when the app
  62.                                     //    is in the background, it does not have access to GetScrap().
  63.  
  64. /* ------------------------------------------------------------------------- */
  65.  
  66. void main()
  67. {
  68.     EventRecord     myEvent;
  69.     long            yieldTime;
  70.     WindowPtr        foundWindow;
  71.     short            windowPart;
  72.     Boolean            isEvent;
  73.     GrafPtr            savePort;
  74.     GDHandle        saveGD;
  75.     PScrapStuff        myScrapStuff;
  76.  
  77.     //    Initialize here.  Set the yield time too.
  78.     Initialize();
  79.     yieldTime = MyYieldTime(suspendResumeMessage);
  80.  
  81.     //    Event loop.
  82.     for ( ; ; ) {
  83.  
  84.         //    Get the event.
  85.         isEvent = WaitNextEvent(everyEvent, &myEvent, yieldTime, nil);
  86.  
  87.         //    Allow application specific event handling.  We have three cases:
  88.         //        MYEVENTDEF == 2: MyEvent gets called for each window.
  89.         //        MYEVENTDEF == 1: MyEvent gets once with window parameter = nil.
  90.         //        MYEVENTDEF == 0: MyEvent never gets called.
  91.         //    MyEvent returns true to indicate that the event is handled and can be ignored.
  92.         //    As the safe thing to do, we always set the port if we know what window is being used.
  93.         #if kMYEVENTDEF == 2
  94.             if ( isEvent ) {
  95.                 foundWindow = (WindowPtr) LMGetWindowList();
  96.                 while ( foundWindow != nil ) {
  97.                     if ( IsMyWindow(foundWindow) ) {
  98.                         GetPort(&savePort);
  99.                         saveGD = GetGDevice();
  100.                         SetPort(foundWindow);
  101.                         SetGDevice(GetMainDevice());
  102.                         if ( MyEvent(foundWindow, &myEvent) )
  103.                             isEvent = false;
  104.                         SetPort(savePort);
  105.                         SetGDevice(saveGD);
  106.                     }
  107.                     foundWindow = (WindowPtr) ((CWindowPeek) foundWindow)->nextWindow;
  108.                 }
  109.             }
  110.         #elif kMYEVENTDEF == 1
  111.             if ( isEvent ) {
  112.                 if ( MyEvent(nil, &myEvent) ) {
  113.                     isEvent = false;
  114.                 }
  115.             }
  116.         #elif kMYEVENTDEF == 0
  117.         #endif
  118.         
  119.         //    If the event is unhandled by app specific event handling, then we proceed.
  120.         if ( isEvent ) {
  121.             switch ( myEvent.what ) {
  122.  
  123.                 case mouseDown:
  124.                     //    Get current port and device.
  125.                     GetPort(&savePort);
  126.                     saveGD = GetGDevice();
  127.                     
  128.                     //    Set the port and gdevice to the window if we own the window.
  129.                     //    We can then assume anytime the event occured in one of our windows,
  130.                     //       that the port and gdevice are set correctly.
  131.                     windowPart = FindWindow(myEvent.where, &foundWindow);
  132.                     if ( IsMyWindow(foundWindow) || IsMyClipWindow(foundWindow) ) {
  133.                         SetPort(foundWindow);
  134.                         SetGDevice(GetMainDevice());
  135.                     }
  136.                     
  137.                     //    Handle the different mouse down events.
  138.                     switch ( windowPart ) {
  139.                         case inSysWindow:
  140.                             SystemClick(&myEvent, foundWindow);
  141.                             break;
  142.                         case inMenuBar:
  143.                             AdjustMenus();
  144.                             DoCommand(MenuSelect(myEvent.where));
  145.                             break;
  146.                         case inContent:
  147.                             //    If in the content area of application's window, then select
  148.                             //    the window and call app specific routine.
  149.                             if ( IsMyWindow(foundWindow) ) {
  150.                                 SelectWindow(foundWindow);
  151.                                 MyInContent(foundWindow, myEvent.where);
  152.                             } else if ( IsMyClipWindow(foundWindow) ) {
  153.                                 SelectWindow(foundWindow);
  154.                             }
  155.                             break;
  156.                         case inDrag:
  157.                             //    If dragging one of the application's windows, then handle it.
  158.                             //    However, if we are dragging a zoomed window, we
  159.                             //    must remember to save the new window location into the
  160.                             //    zoomed rect in the data handle.  Otherwise, the event
  161.                             //    manager will think that we are no longer zoomed.
  162.                             if ( IsMyWindow(foundWindow) || IsMyClipWindow(foundWindow) ) {
  163.                                 WStateData    *zoomData;
  164.                                 Rect        windowRect;
  165.                                 
  166.                                 //    Get window location before drag.
  167.                                 GetGlobalWindow(foundWindow, &windowRect);
  168.                                 
  169.                                 //    Drag window.
  170.                                 DragWindow (foundWindow, myEvent.where, &qd.screenBits.bounds);
  171.  
  172.                                 //    If the windowRect in global coordinates matches the zoom rect,
  173.                                 //    then assume that we are dragging the zoomed window.  update
  174.                                 //    zoom rect.
  175.                                 zoomData = (WStateData *) *(((CWindowPeek) foundWindow)->dataHandle);
  176.                                 if ( EqualRect(&(zoomData->stdState), &windowRect) ) {
  177.                                     GetGlobalWindow(foundWindow, &windowRect);
  178.                                     zoomData = (WStateData *) *(((CWindowPeek) foundWindow)->dataHandle);
  179.                                     zoomData->stdState = windowRect;
  180.                                 }
  181.                             }
  182.                             break;
  183.                         case inGrow:
  184.                             //    If growing one of the application's windows, then handle it.
  185.                             //    This also includes the clip window.
  186.                             //    See inDrag for details.
  187.                             if ( IsMyWindow(foundWindow) || IsMyClipWindow(foundWindow) ) {
  188.                                 WStateData    *zoomData;
  189.                                 Rect        windowRect;
  190.                                 Rect        tempRect;
  191.                                 long        tempLong;
  192.                                 Str255        tempStr;
  193.                                 
  194.                                 //    Get window location before drag.
  195.                                 GetGlobalWindow(foundWindow, &windowRect);
  196.                                 
  197.                                 //    Grow the window.
  198.                                 tempRect = qd.screenBits.bounds;
  199.                                 tempRect.left = tempRect.top = 50;
  200.                                 GetWTitle(foundWindow, tempStr);
  201.                                 tempRect.left = StringWidth(tempStr) + 50;
  202.                                 tempLong = GrowWindow(foundWindow, myEvent.where, &tempRect);
  203.                                 if ( tempLong ) {
  204.                                     tempRect = foundWindow->portRect;
  205.                                     InvalRect(&tempRect);
  206.                                     EraseRect(&tempRect);
  207.                                     InvalRect(&tempRect);
  208.                                     SizeWindow(foundWindow, tempLong, tempLong >> 16, true);
  209.                                 }
  210.  
  211.                                 //    If the windowRect in global coordinates matches the zoom rect,
  212.                                 //    then assume that we are dragging the zoomed window.  update
  213.                                 //    zoom rect.
  214.                                 zoomData = (WStateData *) *(((CWindowPeek) foundWindow)->dataHandle);
  215.                                 if ( EqualRect(&(zoomData->stdState), &windowRect) ) {
  216.                                     GetGlobalWindow(foundWindow, &windowRect);
  217.                                     zoomData = (WStateData *) *(((CWindowPeek) foundWindow)->dataHandle);
  218.                                     zoomData->stdState = windowRect;
  219.                                 }
  220.                             }
  221.                             break;
  222.                         case inGoAway:
  223.                             //    Handle clicking on the go away.  If it is the clip window,
  224.                             //    then hide it.
  225.                             if ( TrackGoAway (foundWindow, myEvent.where) ) {
  226.                                 if ( IsMyWindow(foundWindow) ) {
  227.                                     BringToFront(foundWindow);
  228.                                     MyClose();
  229.                                 } else if ( IsMyClipWindow(foundWindow) ) {
  230.                                     SetItem(GetMHandle(kMENU_EDITID), kMENU_EDITSHOWCLIP, "\pShow Clipboard");
  231.                                     HideClip(foundWindow);
  232.                                 }
  233.                             }
  234.                             break;
  235.                         case inZoomIn:
  236.                         case inZoomOut:
  237.                             //    Zoom application window and the clip window.
  238.                             if ( TrackBox(foundWindow, myEvent.where, windowPart) ) {
  239.                                 if ( IsMyWindow(foundWindow) )
  240.                                     MyZoomWindow(foundWindow, windowPart);
  241.                                 else if ( IsMyClipWindow(foundWindow) )
  242.                                     ZoomClip(foundWindow, windowPart);
  243.                             }
  244.                             break;
  245.                             break;
  246.                         default:
  247.                             break;
  248.                     }
  249.                     
  250.                     //    Restore port and device.
  251.                     SetPort(savePort);
  252.                     SetGDevice(saveGD);
  253.                     
  254.                     break;
  255.                 case keyDown:
  256.                 case autoKey:
  257.                     if ( myEvent.modifiers & cmdKey ) {
  258.                         if ( myEvent.what == keyDown ) {
  259.                             AdjustMenus();
  260.                             DoCommand(MenuKey(myEvent.message & charCodeMask));
  261.                         }
  262.                     } else
  263.                         MyDoKeyDown(&myEvent);
  264.                     break;
  265.                 case updateEvt:
  266.                     //    Handle update events for window and clip window.
  267.                     foundWindow = (WindowPtr) myEvent.message;
  268.                     GetPort(&savePort);
  269.                     saveGD = GetGDevice();
  270.                     SetPort(foundWindow);
  271.                     SetGDevice(GetMainDevice());
  272.                     BeginUpdate(foundWindow);
  273.                     if ( IsMyWindow(foundWindow) )
  274.                         MyDraw(foundWindow);
  275.                     else if ( IsMyClipWindow(foundWindow) )
  276.                         DrawClip(foundWindow);
  277.                     EndUpdate(foundWindow);
  278.                     SetPort(savePort);
  279.                     SetGDevice(saveGD);
  280.                     break;
  281.                 case diskEvt:
  282.                     //    This handles a bad disk.  Otherwise the disk will not eject.
  283.                     if ( myEvent.message >> 16 ) {
  284.                         Point    tempPoint;
  285.                         tempPoint.v = 50; tempPoint.h = 50;
  286.                         DIBadMount(tempPoint, myEvent.message);
  287.                     }
  288.                     break;
  289.                 case activateEvt:
  290.                     break;
  291.                 case app4Evt:
  292.                     switch ( myEvent.message >> 24 ) {
  293.                         case suspendResumeMessage:
  294.                             yieldTime = MyYieldTime(myEvent.message & 0x01);
  295.                             break;
  296.                         default:
  297.                             DebugStr("\pUnexpected suspend/resume message.");
  298.                     }
  299.                     break;
  300.                 case kHighLevelEvent:
  301.                     if ( gHasAppleEvents )
  302.                         AEProcessAppleEvent(&myEvent);
  303.                 default:
  304.                     break;
  305.             }
  306.         }
  307.     
  308.         //    If DoneFlag set, then quit.
  309.         if ( gDoneFlag )
  310.             Finishup();
  311.  
  312.         //    Do Idle routine.
  313.         //        MYIDLEDEF == 2: MyEvent gets called for each window.
  314.         //        MYIDLEDEF == 1: MyEvent gets once with window parameter = nil.
  315.         //        MYIDLEDEF == 0: MyEvent never gets called.
  316.         //    As the safe thing to do, we always set the port if we know what window is being used.
  317.         #if kMYIDLEDEF == 2
  318.             foundWindow = (WindowPtr) LMGetWindowList();
  319.             while ( foundWindow != nil ) {
  320.                 if ( IsMyWindow(foundWindow) ) {
  321.                     GetPort(&savePort);
  322.                     saveGD = GetGDevice();
  323.                     SetPort(foundWindow);
  324.                     SetGDevice(GetMainDevice());
  325.                     MyIdle(foundWindow);
  326.                     SetPort(savePort);
  327.                     SetGDevice(saveGD);
  328.                 }
  329.                 foundWindow = (WindowPtr) ((CWindowPeek) foundWindow)->nextWindow;
  330.             }
  331.         #elif kMYIDLEDEF == 1
  332.             MyIdle(nil);
  333.         #elif kMYIDLEDEF == 0
  334.         #endif
  335.  
  336.         //    See if scrap changed.  If so, redraw if the clip window is found.
  337.         myScrapStuff = InfoScrap();
  338.         if ( gScrapCount != myScrapStuff->scrapCount ) {
  339.             foundWindow = (WindowPtr) LMGetWindowList();
  340.             while ( foundWindow != nil ) {
  341.                 if ( IsMyClipWindow(foundWindow) ) {
  342.                     GetPort(&savePort);
  343.                     saveGD = GetGDevice();
  344.                     SetPort(foundWindow);
  345.                     SetGDevice(GetMainDevice());
  346.                     DrawClip(foundWindow);
  347.                     SetPort(savePort);
  348.                     SetGDevice(saveGD);
  349.                 }
  350.                 foundWindow = (WindowPtr) ((CWindowPeek) foundWindow)->nextWindow;
  351.             }
  352.         }
  353.     }
  354. }
  355.  
  356. /* ------------------------------------------------------------------------- */
  357.  
  358. //    MyApplication Shell support routines (Initialize, DoCommand, and Finishup):
  359.  
  360. #define        kMasterBlockSize        0x400
  361.  
  362. void Initialize()
  363. {
  364.     OSErr                err;
  365.     long                vers;
  366.     Handle                myMenu;
  367.     THz                    curZone;
  368.     short                oldMoreMast;
  369.     
  370.     //    Create a heap with lots of master pointers.
  371.     MaxApplZone();
  372.     curZone = LMGetTheZone();
  373.     oldMoreMast = curZone->moreMast;
  374.     if ( curZone->moreMast < kMasterBlockSize )
  375.         curZone->moreMast = kMasterBlockSize;
  376.     MoreMasters(); MoreMasters(); MoreMasters(); MoreMasters();
  377.     MoreMasters(); MoreMasters(); MoreMasters(); MoreMasters();
  378.     MoreMasters(); MoreMasters(); MoreMasters(); MoreMasters();
  379.     MoreMasters(); MoreMasters(); MoreMasters(); MoreMasters();
  380.     curZone->moreMast = oldMoreMast;
  381.     
  382.     //    Initialize managers.
  383.     InitGraf(&qd.thePort);
  384.     FlushEvents(everyEvent, 0);
  385.     InitWindows();
  386.     InitDialogs(nil);
  387.     InitCursor();
  388.  
  389.     //    Set up menus.
  390.     myMenu = GetNewMBar(kMENUBAR);
  391.     SetMenuBar(myMenu);
  392.     DisposHandle(myMenu);
  393.     AddResMenu(GetMHandle(kMENU_APPLEID), 'DRVR');
  394.     DrawMenuBar();
  395.     
  396.     //    Require at least System 7.0 and Color QuickDraw.  We don't really need to be strict
  397.     //    about this.  So, this can be removed if necessary.  But, test thoroughly with
  398.     //    System 6 and non-color if you do.
  399.     Gestalt(gestaltSystemVersion, &vers);
  400.     vers = (vers >> 8) & 0x0f;
  401.     if ( vers < 7 ) {
  402.         ReportError("\pThis Application does not run under System 6!", -1);
  403.         ExitToShell();
  404.     }
  405.     Gestalt(gestaltQuickdrawVersion, &vers);
  406.     if ( vers < 0x100 ) {
  407.         ReportError("\pThis Application requires Color QuickDraw!", -1);
  408.         ExitToShell();
  409.     }
  410.     
  411.     //    Initialize AppleEvents if available.
  412.     gHasAppleEvents = (Gestalt(gestaltAppleEventsAttr, &vers) == noErr);
  413.     if ( gHasAppleEvents ) {
  414.         err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication, NewAEEventHandlerProc(AEOpenHandler), 0, false);
  415.         if ( err ) {
  416.             ReportError("\pError installing AppleEvent handlers.", err);
  417.             ExitToShell();
  418.         }
  419.         err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments, NewAEEventHandlerProc(AEOpenDocHandler), 0, false);
  420.         if ( err ) {
  421.             ReportError("\pError installing AppleEvent handlers.", err);
  422.             ExitToShell();
  423.         }
  424.         err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication, NewAEEventHandlerProc(AEQuitHandler), 0, false);
  425.         if ( err ) {
  426.             ReportError("\pError installing AppleEvent handlers.", err);
  427.             ExitToShell();
  428.         }
  429.         err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments, NewAEEventHandlerProc(AEPrintHandler), 0, false);
  430.         if ( err ) {
  431.             ReportError("\pError installing AppleEvent handlers.", err);
  432.             ExitToShell();
  433.         }
  434.     }
  435.     
  436.     //    Setup other globals.
  437.     gDoneFlag = false;
  438.  
  439.     //    Call app specific Intialization.
  440.     if ( ReportError("\pError returned from MyInitialize:", MyInitialize()) )
  441.         ExitToShell();
  442. }
  443.  
  444. void DoCommand(long mResult)
  445. {
  446.     short             theMenu, theItem;
  447.     Str255            myStr;
  448.     GrafPtr            savePort;
  449.     GDHandle        saveGD;
  450.     WindowPtr        foundWindow;
  451.     
  452.     theItem = LoWord(mResult);
  453.     theMenu = HiWord(mResult);
  454.     
  455.     if ( theItem != 0 || theMenu != 0 ) {
  456.         switch ( theMenu ) {
  457.             case kMENU_APPLEID:
  458.                 if ( theItem == 1 ) {
  459.                     ParamText(gMyAboutTitle, gMyAboutDesc, nil, nil);
  460.                     Alert(kALERT_ABOUT, nil);
  461.                 } else {
  462.                     GetItem(GetMHandle(kMENU_APPLEID), theItem, myStr);
  463.                     GetPort(&savePort);
  464.                     saveGD = GetGDevice();
  465.                     (void) OpenDeskAcc(myStr);
  466.                     SetPort(savePort);
  467.                     SetGDevice(saveGD);
  468.                 }
  469.                 break;
  470.     
  471.             case kMENU_FILEID:
  472.                 switch ( theItem ) {
  473.                     case kMENU_FILENEW:
  474.                         MyNew();
  475.                         break;
  476.                     case kMENU_FILEOPEN:
  477.                         MyOpen(nil);
  478.                         break;
  479.                     case kMENU_FILECLOSE:
  480.                         if ( IsMyClipWindow(FrontWindow()) ) {
  481.                             SetItem(GetMHandle(kMENU_EDITID), kMENU_EDITSHOWCLIP, "\pShow Clipboard");
  482.                             HideClip(FrontWindow());
  483.                         } else if ( IsMyWindow(FrontWindow()) )
  484.                             MyClose();
  485.                         else
  486.                             SysBeep(50);
  487.                         break;
  488.                     case kMENU_FILESAVE:
  489.                         if ( IsMyWindow(FrontWindow()) )
  490.                             MySave();
  491.                         else
  492.                             SysBeep(50);
  493.                         break;
  494.                     case kMENU_FILESAVEAS:
  495.                         if ( IsMyWindow(FrontWindow()) )
  496.                             MySaveAs();
  497.                         else
  498.                             SysBeep(50);
  499.                         break;
  500.                     case kMENU_FILEPAGESETUP:
  501.                         if ( IsMyWindow(FrontWindow()) )
  502.                             MyPageSetup();
  503.                         else
  504.                             SysBeep(50);
  505.                         break;
  506.                     case kMENU_FILEPRINT:
  507.                         if ( IsMyWindow(FrontWindow()) )
  508.                             MyPrint();
  509.                         else
  510.                             SysBeep(50);
  511.                         break;
  512.                     case kMENU_FILEQUIT:
  513.                         gDoneFlag = true;
  514.                         break;
  515.                     default:
  516.                         if ( ReportError("\pError in handling file menu:", theItem) )
  517.                             ExitToShell();
  518.                 }
  519.                 break;
  520.     
  521.             case kMENU_EDITID:
  522.                 switch ( theItem ) {
  523.                     case kMENU_EDITUNDO:
  524.                         MyUndo();
  525.                         break;
  526.                     case kMENU_EDITCUT:
  527.                         MyCut();
  528.                         break;
  529.                     case kMENU_EDITCOPY:
  530.                         MyCopy();
  531.                         break;
  532.                     case kMENU_EDITPASTE:
  533.                         MyPaste();
  534.                         break;
  535.                     case kMENU_EDITCLEAR:
  536.                         MyClear();
  537.                         break;
  538.                     case kMENU_EDITSELECTALL:
  539.                         MySelectAll();
  540.                         break;
  541.                     case kMENU_EDITSHOWCLIP:
  542.                         GetItem(GetMHandle(kMENU_EDITID), kMENU_EDITSHOWCLIP, myStr);
  543.                         if ( myStr[1] == 'S' ) {        //    Obviously not very internationalizeable.
  544.                             ShowClip();
  545.                             SetItem(GetMHandle(kMENU_EDITID), kMENU_EDITSHOWCLIP, "\pHide Clipboard");
  546.                         } else {
  547.                             foundWindow = (WindowPtr) LMGetWindowList();
  548.                             while ( foundWindow != nil ) {
  549.                                 if ( IsMyClipWindow(foundWindow) ) {
  550.                                     SetItem(GetMHandle(kMENU_EDITID), kMENU_EDITSHOWCLIP, "\pShow Clipboard");
  551.                                     HideClip(foundWindow);
  552.                                 }
  553.                                 foundWindow = (WindowPtr) ((CWindowPeek) foundWindow)->nextWindow;
  554.                             }
  555.                         }
  556.                         break;
  557.                     default:
  558.                         if ( ReportError("\pError in handling edit menu:", theItem) )
  559.                             ExitToShell();
  560.                 }
  561.                 break;
  562.  
  563.             default:
  564.                 //    If not handled above, then allow app specific handling to occur.
  565.                 if ( ReportError("\pError returned from MyDoCommand:", MyDoCommand(theMenu, theItem)) )
  566.                     ExitToShell();
  567.         }
  568.     }
  569.     HiliteMenu(0);
  570.     return;
  571. }
  572.  
  573. void AdjustMenus()
  574. {
  575.     MenuHandle        mHandle;
  576.     
  577.     if ( IsMyClipWindow(FrontWindow()) ) {
  578.         mHandle = GetMHandle(kMENU_FILEID);
  579.         DisableItem(mHandle, kMENU_FILESAVE);
  580.         DisableItem(mHandle, kMENU_FILESAVEAS);
  581.         DisableItem(mHandle, kMENU_FILEPAGESETUP);
  582.         DisableItem(mHandle, kMENU_FILEPRINT);
  583.         mHandle = GetMHandle(kMENU_EDITID);
  584.         DisableItem(mHandle, kMENU_EDITUNDO);
  585.         DisableItem(mHandle, kMENU_EDITCUT);
  586.         DisableItem(mHandle, kMENU_EDITCOPY);
  587.         DisableItem(mHandle, kMENU_EDITPASTE);
  588.         DisableItem(mHandle, kMENU_EDITCLEAR);
  589.         DisableItem(mHandle, kMENU_EDITSELECTALL);
  590.     } else {
  591.         mHandle = GetMHandle(kMENU_FILEID);
  592.         if (IsMyWindow(FrontWindow())) {
  593.             EnableItem(mHandle, kMENU_FILESAVE);
  594.             EnableItem(mHandle, kMENU_FILESAVEAS);
  595.             EnableItem(mHandle, kMENU_FILEPAGESETUP);
  596.             EnableItem(mHandle, kMENU_FILEPRINT);
  597.         } else {
  598.             DisableItem(mHandle, kMENU_FILESAVE);
  599.             DisableItem(mHandle, kMENU_FILESAVEAS);
  600.             DisableItem(mHandle, kMENU_FILEPAGESETUP);
  601.             DisableItem(mHandle, kMENU_FILEPRINT);
  602.         }
  603.         mHandle = GetMHandle(kMENU_EDITID);
  604.         EnableItem(mHandle, kMENU_EDITUNDO);
  605.         EnableItem(mHandle, kMENU_EDITCUT);
  606.         EnableItem(mHandle, kMENU_EDITCOPY);
  607.         EnableItem(mHandle, kMENU_EDITPASTE);
  608.         EnableItem(mHandle, kMENU_EDITCLEAR);
  609.         EnableItem(mHandle, kMENU_EDITSELECTALL);
  610.     }
  611.     
  612.     MyAdjustMenus();
  613. }
  614.  
  615. void Finishup()
  616. {
  617.     WindowPtr        frontWindow, nxtWindow;
  618.     
  619.     frontWindow = FrontWindow();
  620.     while ( frontWindow != nil ) {
  621.         nxtWindow = (WindowPtr) ((WindowPeek)frontWindow)->nextWindow;
  622.         if ( IsMyClipWindow(frontWindow) ) {
  623.             HideClip(frontWindow);
  624.         }
  625.         frontWindow = nxtWindow;
  626.     }
  627.     
  628.     //    Cleanup app specific stuff since all of the shell handles will be disposed of
  629.     //    when the heap disappears...
  630.     MyFinishup();
  631.  
  632.     //    Finally, quit app.
  633.     ExitToShell();
  634. }
  635.  
  636. /* ------------------------------------------------------------------------- */
  637.  
  638. //    Clip Window support (ShowClip, DrawClip, HideClip, and ZoomClip):
  639.  
  640. void ShowClip()
  641. {
  642.     WindowPtr    myWindow;
  643.     Rect        clipBounds;
  644.     
  645.     myWindow = (WindowPtr) LMGetWindowList();
  646.     while ( myWindow != nil ) {
  647.         if ( IsMyClipWindow(myWindow) ) {
  648.             return;
  649.         }
  650.         myWindow = (WindowPtr) ((CWindowPeek) myWindow)->nextWindow;
  651.     }
  652.     
  653.     SetRect(&clipBounds, 10, 400, 510, 480);    
  654.     myWindow = NewCWindow(0L, &clipBounds, "\pClipboard", true, zoomDocProc, (WindowPtr) -1, true, 0L);
  655.     SetMyClipWindow(myWindow);
  656.     SetPort(myWindow);
  657.  
  658.     gScrapCount = 0;
  659.     gScrapType = 'NONE';    
  660.     if ( (gScrap = NewHandle(0)) == nil ) {
  661.         ReportError("\pCould not create handle for scrap storage:", -1);
  662.         ExitToShell();
  663.     }
  664. }
  665.  
  666. void DrawClip(WindowPtr clipWindow)
  667. {
  668.     PScrapStuff    myScrapStuff;
  669.     long        scrapOffset, scrapLength;
  670.     Rect        myFrame;
  671.     Str255        myStr;
  672.     short        moveSize;
  673.     
  674.     //    See if scrap changed.
  675.     myScrapStuff = InfoScrap();
  676.     if ( gScrapCount != myScrapStuff->scrapCount ) {
  677.         gScrapCount = myScrapStuff->scrapCount;
  678.         if ( (scrapLength = GetScrap(gScrap, 'PICT', &scrapOffset)) > 0 ) {
  679.             gScrapType = 'PICT';    
  680.         } else if ( (scrapLength = GetScrap(gScrap, 'TEXT', &scrapOffset)) > 0 ) {
  681.             gScrapType = 'TEXT';    
  682.         } else
  683.             gScrapType = 'NONE';    
  684.     }
  685.  
  686.     //    Erase the window.
  687.     EraseRect(&(clipWindow->portRect));
  688.  
  689.     //    Draw something
  690.     if ( gScrapType == 'PICT' ) {
  691.         myFrame = (**(PicHandle) gScrap).picFrame;
  692.         SetWTitle(clipWindow, "\pClipboard contents: picture");
  693.         DrawPicture((PicHandle) gScrap, &myFrame);
  694.  
  695.     } else if ( gScrapType == 'TEXT' ) {
  696.         SetWTitle(clipWindow, "\pClipboard contents: text");
  697.         moveSize = GetHandleSize(gScrap);
  698.         if ( moveSize > 255 )
  699.             moveSize = 255;
  700.         BlockMove(*gScrap, myStr+1, moveSize);
  701.         myStr[0] = moveSize;
  702.         MoveTo(10, 40);
  703.         DrawString(myStr);
  704.     } else
  705.         SetWTitle(clipWindow, "\pNo PICT or TEXT to display.");
  706. }
  707.  
  708. void HideClip(WindowPtr clipWindow)
  709. {
  710.     DisposeWindow(clipWindow);
  711.     gScrapCount = 0;
  712.     gScrapType = 'NONE';
  713.     DisposeHandle(gScrap);
  714. }
  715.  
  716. void ZoomClip(WindowPtr clipWindow, short windowPart)
  717. {
  718.     WStateData    *zoomData;
  719.     
  720.     //    IMPORTANT: Must not change stdState if not zooming out.  Otherwise, it will fool
  721.     //    the WDEF into thinking that it is not zoomed out when it really is.
  722.     
  723.     //    Don't call anything else since zoomData handle is not locked.
  724.     zoomData = (WStateData *) *(((CWindowPeek) clipWindow)->dataHandle);
  725.     
  726.     if ( gScrapType == 'PICT' ) {
  727.         if ( windowPart == 8 ) {
  728.             (zoomData->stdState).right = (zoomData->stdState).left +
  729.                                             ((**(PicHandle) gScrap).picFrame).right;
  730.             (zoomData->stdState).bottom = (zoomData->stdState).top +
  731.                                             ((**(PicHandle) gScrap).picFrame).bottom;
  732.         }
  733.     } else if ( gScrapType == 'TEXT' ) {
  734.         if ( windowPart == 8 ) {
  735.             (zoomData->stdState).right = (zoomData->stdState).left + 620;
  736.         }    
  737.     }
  738.     ZoomWindow(clipWindow, windowPart, true);
  739. }
  740.  
  741. /* ------------------------------------------------------------------------- */
  742.  
  743. //    Shell utilities (ReportError, and GetGlobalWindow):
  744.  
  745. //    Show Alert.  Then, return true is err != noErr.
  746. Boolean ReportError(Str255 procStr, OSErr err)
  747. {
  748.     long    longerr = err;
  749.     Str255    myStr;
  750.     
  751.     if ( longerr ) {
  752.         NumToString(longerr, myStr);
  753.         ParamText("\pFATAL ERROR", procStr, myStr, nil);
  754.         Alert(kALERT_ERROR, nil);
  755.         return ( true );
  756.     } else
  757.         return ( false );
  758. }
  759.  
  760. void GetGlobalWindow(WindowPtr theWindow, Rect *windowRect)
  761. {
  762.     //    Get the windowRect in global coordinates.
  763.     *windowRect = theWindow->portRect;
  764.     LocalToGlobal(&topLeft(*windowRect));
  765.     LocalToGlobal(&botRight(*windowRect));
  766. }
  767.  
  768. /* ------------------------------------------------------------------------- */
  769.  
  770. //    AppleEvents handling (AEOpenHandler, AEOpenDocHandler, AEPrintHandler,
  771. //       and AECloseHandler) :
  772.  
  773. pascal OSErr AEOpenHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
  774. {
  775.     //    We don't do anything more than simply call MyNew().
  776.     //    Thus, when app is opened from finder, MyNew will be called because the Finder
  777.     //    will send an open app AppleEvent message.
  778.     if ( kNEWDOCATSTARTUP )
  779.         MyNew();
  780.     
  781.     return ( noErr );
  782. }
  783.  
  784. pascal OSErr AEOpenDocHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
  785. {
  786.     OSErr            err;
  787.     AEDescList        docList;
  788.     long            numItems;
  789.     FSSpec            myFSS;
  790.     Size            actualSize;
  791.     long            i;
  792.     DescType        typeCode;
  793.     AEKeyword        theKeyword;
  794.     
  795.     err = AEGetParamDesc(messagein, keyDirectObject, typeAEList, &docList);
  796.     if ( err )
  797.         return ( err );
  798.     
  799.     err = AECountItems(&docList, &numItems);
  800.     if ( err )
  801.         return ( err );
  802.         
  803.     for ( i=1; i<=numItems; i++ ) {
  804.         err = AEGetNthPtr(&docList, i, typeFSS, &theKeyword, &typeCode, (Ptr) &myFSS,
  805.                             sizeof(FSSpec), &actualSize);
  806.         if ( err )
  807.             return ( err );
  808.         
  809.         MyOpen(&myFSS);
  810.     }
  811.     
  812.     return ( noErr );
  813. }
  814.  
  815. pascal OSErr AEPrintHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
  816. {
  817.     OSErr            err;
  818.     AEDescList        docList;
  819.     long            numItems;
  820.     FSSpec            myFSS;
  821.     Size            actualSize;
  822.     long            i;
  823.     DescType        typeCode;
  824.     AEKeyword        theKeyword;
  825.     
  826.     err = AEGetParamDesc(messagein, keyDirectObject, typeAEList, &docList);
  827.     if ( err )
  828.         return ( err );
  829.     
  830.     err = AECountItems(&docList, &numItems);
  831.     if ( err )
  832.         return ( err );
  833.     
  834.     for ( i=1; i<=numItems; i++ ) {
  835.         err = AEGetNthPtr(&docList, i, typeFSS, &theKeyword, &typeCode, (Ptr) &myFSS,
  836.                             sizeof(FSSpec), &actualSize);
  837.         if ( err )
  838.             return ( err );
  839.         
  840.         //    Open each file.  Print it.  Then close it.  MyOpen must make window frontmost.
  841.         MyOpen(&myFSS);
  842.         MyPrint();
  843.         MyClose();
  844.     }
  845.     
  846.     return ( noErr );
  847. }
  848.  
  849. pascal OSErr AEQuitHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
  850. {
  851.     gDoneFlag = true;
  852.     
  853.     return ( noErr );
  854. }
  855.  
  856. /* ------------------------------------------------------------------------- */
  857.  
  858. //    Called to determine if the window is owned by app.
  859. Boolean IsMyWindow(WindowPtr theWindow)
  860. {
  861.     if ( theWindow )
  862.         return ( ((CWindowPeek) theWindow)->windowKind == kWINDOWDOC );
  863.     else
  864.         return ( false );
  865. }
  866.  
  867. //    Called to set the window's creator.
  868. void SetMyWindow(WindowPtr theWindow)
  869. {
  870.     if ( theWindow )
  871.         ((CWindowPeek) theWindow)->windowKind = kWINDOWDOC;
  872. }
  873.  
  874. //    Called to determine if window is a show clipboard window.
  875. Boolean IsMyClipWindow(WindowPtr theWindow)
  876. {
  877.     if ( theWindow )
  878.         return ( ((CWindowPeek) theWindow)->windowKind == kWINDOWCLIP );
  879.     else
  880.         return ( false );
  881. }
  882.  
  883. //    Called to set the creator as the window clip.
  884. void SetMyClipWindow(WindowPtr theWindow)
  885. {
  886.     if ( theWindow )
  887.         ((CWindowPeek) theWindow)->windowKind = kWINDOWCLIP;
  888. }
  889.