home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 April: Mac OS SDK / Dev.CD Apr 97 SDK1.toast / Development Kits (Disc 1) / QuickDraw 3D / Samples / SampleCode / SimpleViewer / SimpleViewer.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-21  |  26.6 KB  |  1,092 lines  |  [TEXT/MPCC]

  1. //--------------------------------------------------------------------------------------------
  2. // simple viewer application 
  3. // DEVELOPER SUPPORT May 95
  4. //
  5. // This is a simple viewer application, that illustrates a minimal, but
  6. // functionally complete viewer application.
  7. //
  8. // Nick Thompson, Developer Support, Apple Computer (DEVSUPPORT),
  9. // ©1995, Apple Computer Inc., All Rights Reserved
  10.  
  11. #include <AppleEvents.h>
  12. #include <menus.h>
  13. #include <PictUtil.h>
  14. #include <QDOffScreen.h>
  15. #include <Errors.h>
  16.  
  17. #include "QD3DViewer.h"
  18.  
  19. //--------------------------------------------------------------------------------------------
  20. //
  21. const int    kWindowWidth = 220 ;
  22. const int    kWindowHeight = 150 ;
  23.  
  24. //--------------------------------------------------------------------------------------------
  25. //
  26. #define HiWrd(aLong)    (((aLong) >> 16) & 0xFFFF)
  27. #define LoWrd(aLong)    ((aLong) & 0xFFFF)
  28.  
  29.     
  30.  
  31. //--------------------------------------------------------------------------------------------
  32. // menu id's
  33. enum {
  34.     mApple = 128,
  35.     mFile,
  36.     mEdit
  37. } ;
  38.  
  39. //--------------------------------------------------------------------------------------------
  40. // command id's, Apple menu
  41. enum {
  42.     iAbout = 1
  43. } ;
  44.  
  45. //--------------------------------------------------------------------------------------------
  46. // command id's, File menu
  47. enum {
  48.     iNew = 1,
  49.     iOpen,
  50.     iUnused1,
  51.     iClose,
  52.     iSave,
  53.     iSaveAs,
  54.     iRevert,
  55.     iUnused2,
  56.     iQuit
  57. } ;
  58.  
  59. //--------------------------------------------------------------------------------------------
  60. // command id's, Edit menu
  61. enum {
  62.     iUndo = 1,
  63.     iUnused3,
  64.     iCut,
  65.     iCopy,
  66.     iPaste,
  67.     iClear
  68. } ;
  69.  
  70. //--------------------------------------------------------------------------------------------
  71. // static control variables
  72.  
  73. static Boolean gQuitFlag = false ;                // we ain't quittin yet
  74. static Point gStaggerPos = {50,50} ;            // start opening staggered windows at this point
  75. static AEAddressDesc    gSelfAddress;            // A self-addressed address descriptor record
  76. static ProcessSerialNumber    gSelfPSN;            // This application's psn
  77.  
  78. //--------------------------------------------------------------------------------------------
  79. // function prototypes
  80.  
  81. Boolean SupportsQuickDraw3D(void) ;
  82. Boolean     SupportsQuickDraw3DViewer(void) ;
  83. void         InitToolbox( void ) ;
  84. void        FailIfErr(OSErr something ) ;
  85. void         MainEventLoop( void ) ;
  86. void         HandleKeyPress( EventRecord *event ) ;
  87. Boolean        HandleEvent( EventRecord *theEvent ) ;
  88. void         HandleMenuCommand( long menuResult ) ;
  89. void         MyAdjustMenus( void ) ;
  90. OSErr        MyDisposeViewerWindow( WindowPtr theWindow ) ;
  91. CGrafPtr     MyCreateViewerWindow( void ) ;
  92.  
  93. //-- AppleEvent Related
  94.  
  95. Boolean SupportsAEVT(void) ;
  96. void RegisterMyEvents(void) ;
  97. pascal OSErr MyAEHandleOAPP( AppleEvent *theAppleEvent, AppleEvent *reply, long refCon) ;
  98. pascal OSErr MyAEHandleODOC(AppleEvent *theAppleEvent, AppleEvent *reply, long refCon) ;
  99. pascal OSErr MyAEHandlePDOC(AppleEvent *theAppleEvent,AppleEvent *reply,long refCon) ;
  100. pascal OSErr MyAEHandleQUIT(AppleEvent *theAppleEvent,AppleEvent *reply,long refCon) ;
  101. void DoAppOpenCommand( void ) ;
  102. void MySendQuitApp( void ) ;
  103. void MySendOpenDoc(FSSpec *myFSSpec) ;
  104.  
  105. //--------------------------------------------------------------------------------------------
  106. // Constants
  107.  
  108. const RGBColor    kRGBBlack = { 0x0000, 0x0000, 0x0000 } ;
  109. const RGBColor    kRGBWhite = { 0xFFFF, 0xFFFF, 0xFFFF } ;
  110. const int         kMyAboutDialogID = 128 ;
  111. const int         kMyFatalDialogID = 129 ;
  112. const int        kQD3DAlertID = 27309 ;
  113. //--------------------------------------------------------------------------------------------
  114. // Types
  115. typedef struct _viewerData {
  116.     TQ3ViewerObject        theViewer ;
  117.     FSSpec                theFile ;
  118.     Boolean                isFileValid ;
  119. } ViewerData, *ViewerDataPtr, **ViewerDataHandle ;
  120.  
  121. //--------------------------------------------------------------------------------------------
  122. //
  123. //
  124.  
  125. main()
  126. {
  127.     MoreMasters(); MoreMasters() ; MoreMasters() ;
  128.     MaxApplZone() ;            // Maximise the heap - the viewer requires at least 32k
  129.     InitToolbox() ;
  130.  
  131.     // WE DON'T CHECK FOR 68K machine.
  132.     // Instead I use the NotPPC.rsrc resource file.  This is a file with a 68k CODE 0
  133.     // and CODE 1 resource that puts up a dialog that says "this app only runs on a power
  134.     // macintosh computer.
  135.     
  136.     if( SupportsAEVT() && SupportsQuickDraw3D() && SupportsQuickDraw3DViewer()  ) {
  137.     
  138.         // AppleEvent stuff:
  139.         // Set up the self-addressed descriptor record.
  140.          gSelfPSN.highLongOfPSN = 0;
  141.          gSelfPSN.lowLongOfPSN = kCurrentProcess;        //* Use this instead of GetCurrentProcess *//
  142.          FailIfErr(AECreateDesc(typeProcessSerialNumber,(Ptr)&gSelfPSN,sizeof(ProcessSerialNumber),&gSelfAddress));
  143.  
  144.         RegisterMyEvents() ;    // register the appleevents for this app
  145.  
  146.         MainEventLoop() ;        // Handle events 'til we die
  147.     } 
  148.     else {
  149.         Str255 theString ;
  150.         GetIndString(theString,kQD3DAlertID,3);
  151.         ParamText( theString, 0L,  0L,  0L ) ;
  152.         (void)Alert(kQD3DAlertID,nil);
  153.     }
  154. }
  155. //---------------------------------------------------------------------
  156.  
  157. Boolean SupportsQuickDraw3D(void) 
  158. {
  159.     OSErr err;
  160.     long response;
  161.         
  162.     err = Gestalt(gestaltQD3D,&response);
  163.     if (err!=noErr)
  164.         return false;
  165.         
  166.     return (response && (response << gestaltQD3DAvailable));
  167. }
  168.  
  169. //---------------------------------------------------------------------
  170.  
  171. Boolean SupportsQuickDraw3DViewer(void) 
  172. {
  173.     OSErr err;
  174.     long response;
  175.         
  176.     err = Gestalt( gestaltQD3DViewer,&response );
  177.     if (err!=noErr)
  178.         return false;
  179.         
  180.     return (response && ( response << gestaltQD3DViewerAvailable ));
  181. }
  182.  
  183. //--------------------------------------------------------------------------------------------
  184. //
  185. //
  186. void FailIfErr( OSErr something )
  187.     OSErr myErr ; 
  188.     if(( myErr = something) != noErr ) { 
  189.         ModalFilterUPP         theProc ;
  190.         DialogPtr            theDialog ; 
  191.         short                itemHit ;
  192.         Str255                theError ;
  193.         
  194.         NumToString(something,theError);
  195.     
  196.         theDialog = GetNewDialog ( kMyFatalDialogID, nil, (WindowPtr)-1 );
  197.         
  198.         // these two lil' snappers are system 7 only
  199.         // so if you use them, check before!!
  200.         // in this app we will only run on Power
  201.         // Macintosh, so we don't check
  202.         
  203.         GetStdFilterProc( &theProc ) ;
  204.         SetDialogDefaultItem(theDialog, ok) ;
  205.         
  206.         ParamText( theError, 0L, 0L, 0L ) ;
  207.         
  208.         // put the dialog up and loop 'til
  209.         // the user hits the OK button
  210.  
  211.         do {
  212.             ModalDialog ( theProc, &itemHit );
  213.         } while( itemHit != ok ) ;
  214.         
  215.         DisposeDialog ( theDialog );
  216.         
  217.         ExitToShell() ; 
  218.     } 
  219.  
  220. //--------------------------------------------------------------------------------------------
  221. //
  222. //
  223.  
  224. void InitToolbox()
  225. {
  226.     Handle        menuBar = nil;
  227.  
  228.  
  229.     InitGraf((Ptr) &qd.thePort);
  230.     InitFonts();
  231.     InitWindows();
  232.     InitMenus();
  233.     TEInit();
  234.     InitDialogs((long)nil);
  235.     InitCursor();
  236.  
  237.     // initialize application globals
  238.     
  239.     gQuitFlag = false;
  240.     
  241.     
  242.     menuBar = GetNewMBar(128);                // Read menus into menu bar, MBAR res id is 128
  243.     
  244.     if ( menuBar == nil )
  245.          ExitToShell();                        // if we dont have it then quit - your app 
  246.                                              // needs a dialog here
  247.  
  248.     SetMenuBar(menuBar);                    // Install menus
  249.     DisposeHandle(menuBar);
  250.     
  251.     AppendResMenu(GetMenuHandle(mApple), 'DRVR');    // Add DA names to Apple menu, ID 128
  252.  
  253.     MyAdjustMenus() ;
  254.     DrawMenuBar();
  255. }
  256.  
  257.  
  258. //--------------------------------------------------------------------------------------------
  259. //
  260. //
  261. void MainEventLoop()
  262. {
  263.     EventRecord         event;
  264.     WindowPtr           theWindow;
  265.     Boolean                wasViewerEvent ;
  266.     GrafPtr             savedPort ;
  267.     Point                localPt ;
  268.     TQ3ViewerObject     theViewer ;
  269.     ViewerDataHandle    myData ;
  270.  
  271.     MyAdjustMenus() ;
  272.     while( !gQuitFlag )
  273.     {
  274.         if (WaitNextEvent( everyEvent, &event, 0, nil ))
  275.         {
  276.             
  277.             if((theWindow = FrontWindow()) != nil ) {
  278.             
  279.                 myData = (ViewerDataHandle)GetWRefCon(theWindow);
  280.                 theViewer = (**myData).theViewer;
  281.             }
  282.             
  283.             if( theViewer ) {
  284.                 GetPort( &savedPort ) ;
  285.                 SetPort( (GrafPtr)theWindow ) ;
  286.                 GetMouse(&localPt);
  287.                 if (!Q3ViewerAdjustCursor(theViewer, &localPt))
  288.                     InitCursor();
  289.                 wasViewerEvent = Q3ViewerEvent ( theViewer, &event );
  290.                 SetPort( savedPort ) ;
  291.             }
  292.             else
  293.                 wasViewerEvent = false ;
  294.             
  295.             // was it a viewer event????
  296.             if( !wasViewerEvent )
  297.                 HandleEvent( &event );
  298.         }
  299.     }
  300. }
  301.  
  302. //----------------------------------------------------------------------------------
  303. //    HandleActivateWindow is called when an event is received that reports that
  304. //    a window is being either activated or deactivated.
  305.  
  306. static void HandleActivateWindow(WindowPtr theWindow, short activate)
  307. {
  308.     if (theWindow) {
  309.         if (activate) {
  310.         
  311.             // do whatever else you'd like to do for a activate event
  312.             LoadScrap() ;
  313.  
  314.         } else {
  315.         
  316.             // do whatever you'd like to do for a deactivate event
  317.             UnloadScrap() ;
  318.         }
  319.     }
  320. }
  321.  
  322. //--------------------------------------------------------------------------------------------
  323. //
  324. //
  325. Boolean        HandleEvent( EventRecord *theEvent )
  326. {
  327.     short               thePart;
  328.     WindowPtr            theWindow ;
  329.     Rect                screenRect;
  330.     GrafPtr                oldPort ;
  331.     Point                aPoint = {100, 100};
  332.     TQ3ViewerObject     theViewer ;
  333.     ViewerDataHandle    myData ;
  334.     
  335.     switch (theEvent->what) {
  336.         case mouseDown:
  337.         
  338.             thePart = FindWindow( theEvent->where, &theWindow );
  339.             
  340.             switch( thePart ) {
  341.                 case inMenuBar: 
  342.                     MyAdjustMenus() ;
  343.                     HandleMenuCommand(MenuSelect(theEvent->where));
  344.                     break;
  345.                 
  346.                 case inDrag:
  347.                     screenRect = (**GetGrayRgn()).rgnBBox;
  348.                     DragWindow( theWindow, theEvent->where, &screenRect );
  349.                     break ;
  350.             
  351.                 case inContent:
  352.                     if (theWindow != FrontWindow())
  353.                         SelectWindow( theWindow );
  354.                     break ;
  355.             
  356.                 case inGoAway:
  357.                     if (TrackGoAway( theWindow, theEvent->where )) {
  358.                         MyDisposeViewerWindow( theWindow ) ;
  359.                     }
  360.                     break ;
  361.                     
  362.                 default:
  363.                     break ;
  364.             }
  365.             break ;
  366.                     
  367.                 
  368.         case updateEvt:
  369.         
  370.             theWindow = (WindowPtr)theEvent->message;
  371.             myData = (ViewerDataHandle)GetWRefCon( theWindow ) ;
  372.             theViewer = (**myData).theViewer ;
  373.             
  374.             GetPort(&oldPort ) ;    
  375.             SetPort( theWindow );
  376.             
  377.             BeginUpdate( theWindow );
  378.             Q3ViewerDraw( theViewer ) ;
  379.             EndUpdate( theWindow );
  380.             
  381.             SetPort( oldPort ) ;
  382.             
  383.             break ;
  384.             
  385.         case keyDown:
  386.         case autoKey:
  387.             HandleKeyPress(theEvent);
  388.             break;
  389.             
  390.         case diskEvt:
  391.             if ( HiWrd(theEvent->message) != noErr ) 
  392.                 (void) DIBadMount(aPoint, theEvent->message);
  393.             break;
  394.             
  395.         case osEvt:
  396.             break ;
  397.         case activateEvt:
  398.             if ((theWindow = (WindowPtr) theEvent->message) != nil) {
  399.                 HandleActivateWindow(theWindow, (theEvent->modifiers & activeFlag));
  400.             }
  401.  
  402.             break;
  403.  
  404.         case kHighLevelEvent:                        // Let the Apple Event Manager handle high level event.
  405.             AEProcessAppleEvent(theEvent);
  406.             break;
  407.  
  408.     }
  409.     return true ;
  410. }
  411.  
  412.  
  413. //--------------------------------------------------------------------------------------------
  414. //
  415. //
  416. void HandleKeyPress(EventRecord *event)
  417. {
  418.     char    key;
  419.  
  420.     key = event->message & charCodeMask;
  421.     
  422.     // just check to see if we want to quit...
  423.     
  424.     if ( event->modifiers & cmdKey ) {        /* Command key down? */
  425.         HandleMenuCommand(MenuKey(key));
  426.     } 
  427. }
  428.  
  429. //--------------------------------------------------------------------------------------------
  430. //
  431. //
  432.  
  433. static void HandleAboutApp( void )
  434. {
  435.     ModalFilterUPP         theProc ;
  436.     DialogPtr            theDialog ; 
  437.     short                itemHit ;
  438.  
  439.     theDialog = GetNewDialog ( kMyAboutDialogID, nil, (WindowPtr)-1 );
  440.     
  441.     // these two lil' snappers are system 7 only
  442.     // so if you use them, check before!!
  443.     // in this app we will only run on Power
  444.     // Macintosh, so we don't check
  445.     
  446.     GetStdFilterProc( &theProc ) ;
  447.     SetDialogDefaultItem(theDialog, ok) ;
  448.     
  449.     // put the dialog up and loop 'til
  450.     // the user hits the OK button
  451.     
  452.     do {
  453.         ModalDialog ( theProc, &itemHit );
  454.     } while( itemHit != ok ) ;
  455.     
  456.     DisposeDialog ( theDialog );
  457. }
  458.  
  459. //--------------------------------------------------------------------------------------------
  460. //
  461. //
  462. static OSErr HandleOpenDoc(FSSpec *theFile)
  463. {
  464.     OSErr                err ;
  465.     short                theRef ;
  466.     ViewerDataHandle    myData ;
  467.     TQ3ViewerObject     theViewer ;
  468.     WindowPtr            theWindow ;
  469.  
  470.     // display the contents
  471.     theWindow = (WindowPtr)MyCreateViewerWindow() ;
  472.     
  473.     // open the file
  474.     err = FSpOpenDF( theFile, fsRdPerm, &theRef ) ;
  475.     if (err == noErr)
  476.     {
  477.         myData = (ViewerDataHandle)GetWRefCon( theWindow ) ;
  478.         theViewer = (**myData).theViewer ;
  479.         (**myData).theFile = *theFile ;
  480.         (**myData).isFileValid = true ;
  481.         Q3ViewerUseFile(theViewer, theRef) ;
  482.         err = FSClose(theRef) ;
  483.     }
  484.     
  485.     // set the window title
  486.     SetWTitle( theWindow, theFile->name );
  487.     MyAdjustMenus() ;
  488.     return err ;
  489. }
  490.  
  491.  
  492. //--------------------------------------------------------------------------------------------
  493. //
  494. //
  495. void HandleMenuCommand(long menuResult)
  496. {
  497.     short                menuID;
  498.     short                menuItem;
  499.     Str255                daName;
  500.     
  501.  
  502.     short                numTypes = 2 ;
  503.     SFTypeList            myTypes = { '3DMF', 'TEXT', 0 } ;
  504.     OSErr                err ;
  505.     short                theRef ;
  506.     
  507.     ViewerDataHandle    myData ;
  508.     TQ3ViewerObject     theViewer ;
  509.     WindowPtr            theWindow ;
  510.     GrafPtr                savedPort ;
  511.     
  512.     FSSpec                theFile ;
  513.         
  514.     StandardFileReply    theSFReply ;
  515.  
  516.     menuID = HiWrd(menuResult);
  517.     menuItem = LoWrd(menuResult);
  518.     
  519.     switch ( menuID ) {
  520.         //
  521.         //--------------------------------------------------------------------------    
  522.         //
  523.         case mApple:
  524.             switch ( menuItem ) {
  525.  
  526.                 case iAbout:
  527.                     HandleAboutApp() ;    
  528.                     break ;
  529.                                 
  530.                 default:
  531.                     GetMenuItemText(GetMenuHandle(mApple), menuItem, daName);
  532.                     (void) OpenDeskAcc(daName);
  533.                     break;
  534.             }
  535.             break;
  536.         //
  537.         //--------------------------------------------------------------------------    
  538.         //
  539.         case mFile:
  540.             switch ( menuItem ) {
  541.                 case iNew:
  542.                     // display the contents
  543.                     (void)MyCreateViewerWindow() ;
  544.                     break ;
  545.                 
  546.                 case iOpen:
  547.                     // Get the file name to open
  548.                     StandardGetFile( nil, numTypes, myTypes, &theSFReply ) ;
  549.                     
  550.                     // did the user cancel, if not open the file?
  551.                     if(theSFReply.sfGood)
  552.                         MySendOpenDoc(&theSFReply.sfFile) ;
  553.  
  554.                     break ;
  555.                     
  556.                     
  557.                 case iRevert:
  558.                 
  559.                     // we know this can't be called as long as there
  560.                     // is an app window open (MyAdjustMenus) so get the refcon
  561.                     // from the front window and get the FSSpec from that
  562.                     theWindow = FrontWindow() ;
  563.                     myData = (ViewerDataHandle)GetWRefCon( theWindow ) ;
  564.                     theFile = (**myData).theFile ;
  565.                     
  566.                     // open the file and read it back into the viewer
  567.                     err = FSpOpenDF( &theFile, fsRdPerm, &theRef ) ;
  568.                     if (err == noErr)
  569.                     {
  570.                         theViewer = (**myData).theViewer ;
  571.                         Q3ViewerUseFile(theViewer, theRef) ;
  572.                         err = FSClose(theRef) ;
  573.                     }
  574.                     GetPort( &savedPort ) ;
  575.                     SetPort((GrafPtr)theWindow) ;
  576.                     InvalRect( &theWindow->portRect ) ;
  577.                     SetPort( savedPort ) ;
  578.                     break ;        
  579.                             
  580.                 case iSave:                
  581.                 
  582.                     // we know this can't be called as long as there
  583.                     // is an app window open (MyAdjustMenus) so get the refcon
  584.                     // from the front window and get the FSSpec from that
  585.                     theWindow = FrontWindow() ;
  586.                     myData = (ViewerDataHandle)GetWRefCon( theWindow ) ;
  587.                     theFile = (**myData).theFile ;
  588.                     theViewer = (**myData).theViewer ;
  589.  
  590.                     // assumes the original file still exists
  591.                     err = FSpOpenDF(&theFile, fsWrPerm, &theRef);
  592.                     if (err == noErr)
  593.                     {
  594.                         Q3ViewerWriteFile(theViewer, theRef);
  595.                         err = FSClose(theRef);
  596.                     }
  597.                     break ;
  598.                 
  599.                 case iSaveAs:
  600.                     // we know this can't be called as long as there
  601.                     // is an app window open (MyAdjustMenus) so get the refcon
  602.                     // from the front window and get the FSSpec from that
  603.                     theWindow = FrontWindow() ;
  604.                     myData = (ViewerDataHandle)GetWRefCon( theWindow ) ;
  605.                     theViewer = (**myData).theViewer ;
  606.  
  607.                     StandardPutFile("\pSave model as:", "\pUntitled", &theSFReply);
  608.                     if (theSFReply.sfGood)
  609.                     {
  610.                         err = FSpOpenDF(&theSFReply.sfFile, fsWrPerm, &theRef);
  611.                         if (err != noErr)
  612.                         {
  613.                             err = FSpCreate(&theSFReply.sfFile, '????', '3DMF', theSFReply.sfScript);
  614.                             if (err == noErr)
  615.                                 err = FSpOpenDF(&theSFReply.sfFile, fsCurPerm, &theRef);
  616.                         }
  617.                         if (err == noErr)
  618.                         {
  619.                             Q3ViewerWriteFile(theViewer, theRef);
  620.                             err = FSClose(theRef);
  621.                         }
  622.                         
  623.                         // set up our record of the file location,
  624.                         // update the structure
  625.                         theWindow = FrontWindow() ;
  626.                         myData = (ViewerDataHandle)GetWRefCon( theWindow ) ;
  627.                         theViewer = (**myData).theViewer ;
  628.                         (**myData).theFile = theSFReply.sfFile ;
  629.                         (**myData).isFileValid = true ;
  630.                         
  631.                         // reset the window title
  632.                         SetWTitle( theWindow, theSFReply.sfFile.name );
  633.                     }
  634.                     break;                
  635.                 
  636.                 case iClose:
  637.                     MyDisposeViewerWindow ( FrontWindow() );
  638.                     break ;
  639.                     
  640.                 case iQuit:
  641.                     MySendQuitApp();
  642.                     break;
  643.             }
  644.             break;
  645.             
  646.             
  647.         //
  648.         //--------------------------------------------------------------------------    
  649.         //
  650.         case mEdit:
  651.             // display the contents
  652.             theWindow = FrontWindow() ;
  653.             myData = (ViewerDataHandle)GetWRefCon( theWindow ) ;
  654.             theViewer = (**myData).theViewer ;
  655.             switch(menuItem)
  656.             {
  657.                 case iCut:
  658.                     Q3ViewerCut(theViewer);
  659.                     break;
  660.                 case iCopy:
  661.                     Q3ViewerCopy(theViewer);
  662.                     break;
  663.                 case iPaste:
  664.                     Q3ViewerPaste(theViewer);
  665.                     break;
  666.                 case iClear:
  667.                     Q3ViewerClear(theViewer);
  668.                     break;
  669.                 default:
  670.                     break;
  671.             }
  672.             break; 
  673.  
  674.     }
  675.     HiliteMenu(0);        // Unhighlight whatever MenuSelect or MenuKey hilited
  676. }
  677.  
  678. //--------------------------------------------------------------------------------------------
  679. //
  680. //
  681. void MyAdjustMenus( void ) 
  682. {
  683.     WindowPtr            theWindow ;
  684.     ViewerDataHandle    myData ;
  685.     MenuHandle            theMenu ;
  686.  
  687.     theWindow = FrontWindow() ;
  688.     
  689.     
  690.     if( theWindow != nil ) {
  691.     
  692.         theMenu =  GetMenuHandle ( mFile ) ;
  693.         
  694.         EnableItem ( theMenu, iClose );
  695.         EnableItem ( theMenu, iSaveAs );
  696.                  
  697.         myData = (ViewerDataHandle)GetWRefCon( theWindow ) ;
  698.         
  699.          if(    (**myData).isFileValid) {
  700.             EnableItem ( theMenu, iSave );
  701.             EnableItem (theMenu, iRevert );
  702.          }
  703.          else {
  704.             DisableItem ( theMenu, iSave );
  705.             DisableItem ( theMenu, iRevert );
  706.          
  707.          }
  708.          
  709.          EnableItem ( GetMenuHandle ( mEdit ), 0 );
  710.  
  711.     }
  712.     else {
  713.  
  714.         theMenu =  GetMenuHandle ( mFile ) ;
  715.  
  716.         DisableItem ( theMenu, iClose );
  717.         DisableItem ( theMenu, iRevert );
  718.         DisableItem ( theMenu, iSave );
  719.         DisableItem ( theMenu, iSaveAs );
  720.         
  721.         DisableItem ( GetMenuHandle ( mEdit ), 0 );
  722.     }
  723.     
  724.     // we don't support undo
  725.     DisableItem ( GetMenuHandle ( mEdit ), iUndo );
  726.     
  727.     DrawMenuBar() ;
  728. }
  729.  
  730.  
  731. //--------------------------------------------------------------------------------------------
  732. //
  733. //
  734. OSErr    MyDisposeViewerWindow( WindowPtr theWindow )
  735. {
  736.     TQ3ViewerObject     theViewer ;
  737.     ViewerDataHandle    myData ;
  738.     
  739.     if( theWindow == nil)
  740.         return paramErr ;
  741.  
  742.     myData = (ViewerDataHandle)GetWRefCon( theWindow ) ;
  743.     theViewer = (**myData).theViewer ;
  744.     
  745.     DisposeHandle((Handle)myData);
  746.     DisposeWindow(theWindow);
  747.     
  748.     MyAdjustMenus() ;
  749.     return     Q3ViewerDispose(theViewer);
  750. }
  751.  
  752.  
  753. //--------------------------------------------------------------------------------------------
  754. //
  755. //
  756. CGrafPtr MyCreateViewerWindow(  )
  757. {
  758.  
  759.     Rect                theRect ;
  760.     GrafPtr                savedPort ;
  761.     TQ3ViewerObject        myViewerObj ;
  762.     WindowPtr            theWindow ;
  763.     ViewerDataHandle    myData = (ViewerDataHandle)NewHandle(sizeof(ViewerData)) ;
  764.     
  765.     GetPort( &savedPort ) ;
  766.         
  767.     // set the new rect up with a stagger for multiple windows
  768.     SetRect(    &theRect, 
  769.                 gStaggerPos.h, 
  770.                 gStaggerPos.v, 
  771.                 gStaggerPos.h + kWindowWidth, 
  772.                 gStaggerPos.v + kWindowHeight );
  773.  
  774.     gStaggerPos.h += 16 ;
  775.     gStaggerPos.v += 16 ;        // this is not "real staggering code, it don't wrap ;        
  776.                          
  777.     theWindow  = NewCWindow(    nil, 
  778.                                 &theRect, 
  779.                                 "\pUntitled", 
  780.                                 false, 
  781.                                 documentProc, 
  782.                                 (WindowPtr)-1, 
  783.                                 true, 
  784.                                 0L );    
  785.                     
  786.     SetPort( (GrafPtr)theWindow ) ;
  787.     
  788.     // set up the viewer object here
  789.     myViewerObj = Q3ViewerNew ((CGrafPtr)theWindow,  &theWindow->portRect,  kQ3ViewerDefault) ; 
  790.     
  791.     //stuff the reference to the viewer in the RefCon field of the Window
  792.     (**myData).theViewer = myViewerObj ;
  793.     (**myData).isFileValid = false ;
  794.     SetWRefCon( theWindow, (long)myData );
  795.     
  796.     // make sure it is visible
  797.     ShowWindow( theWindow ) ;
  798.     
  799.     // invalidate the content region of the window - 
  800.     // we don't do any drawing to it here.
  801.     InvalRect ( &theRect );
  802.     SetPort( savedPort ) ;
  803.     
  804.     return (CGrafPtr)theWindow ;
  805. }
  806.  
  807.  
  808. //-----------------------------------------------------------------------
  809. // returns true if the platform supports appleevents - we won't run
  810. // if it doesn't
  811.  
  812. Boolean SupportsAEVT(void)
  813. {
  814.     OSErr err;
  815.     long response;
  816.         
  817.     err = Gestalt(gestaltAppleEventsAttr,&response);
  818.     if (err!=noErr)
  819.         return false;
  820.         
  821.     return (response && (response << gestaltAppleEventsPresent));
  822. }
  823.  
  824. //-----------------------------------------------------------------------
  825. // called to register our appleevent handlers
  826.  
  827. void RegisterMyEvents(void)
  828. {
  829.     OSErr err;
  830.     
  831.     if (!SupportsAEVT())
  832.         return;
  833.     
  834.     err = AEInstallEventHandler(kCoreEventClass,kAEOpenApplication,NewAEEventHandlerProc(MyAEHandleOAPP),0L,false);
  835.     if (err!=noErr)
  836.         return;
  837.                 
  838.     err = AEInstallEventHandler(kCoreEventClass,kAEOpenDocuments,NewAEEventHandlerProc(MyAEHandleODOC),0L,false);
  839.     if (err!=noErr)
  840.         return;
  841.                 
  842.     err = AEInstallEventHandler(kCoreEventClass,kAEPrintDocuments,NewAEEventHandlerProc(MyAEHandlePDOC),0L,false);
  843.     if (err!=noErr)
  844.         return;
  845.                 
  846.     err = AEInstallEventHandler(kCoreEventClass,kAEQuitApplication,NewAEEventHandlerProc(MyAEHandleQUIT),0L,false);
  847.     if (err!=noErr)
  848.         return;
  849. }
  850.  
  851. //-----------------------------------------------------------------------
  852. // open application event handler for the core event suite, 
  853. // by default we just want a blank new document
  854.  
  855. pascal OSErr MyAEHandleOAPP( AppleEvent *theAppleEvent, AppleEvent *reply, long refCon)
  856. {
  857.     // we don't actually do anything on open - you could,
  858.     // for example you might want to open a blank untitled 
  859.     // window
  860.     
  861.     OSErr err = noErr ;
  862.     return err;
  863. }
  864.  
  865.  
  866. //-----------------------------------------------------------------------
  867. // handler for the open document appleevent handler
  868.  
  869. pascal OSErr MyAEHandleODOC(AppleEvent *theAppleEvent, AppleEvent *reply, long refCon)
  870. {
  871.     FSSpec         myFSS;
  872.     AEDescList    docList;
  873.     OSErr        err,
  874.                 ignoreErr;
  875.     long        index,
  876.                 itemsInList;
  877.     Size         actualSize;
  878.     AEKeyword    keywd;
  879.     DescType    returnedType;
  880.  
  881.     
  882.     err = AEGetParamDesc(theAppleEvent,keyDirectObject,typeAEList,&docList);
  883.     if (err == noErr) {
  884.     
  885.         // see how many descriptor items are in the list
  886.         // this is the number of documents we want to open
  887.         err = AECountItems(&docList,&itemsInList);
  888.  
  889.         // now get each descriptor record from the list
  890.         // coerce the returned data to an FSSpec record, and
  891.         // open the asoociated file
  892.         
  893.         for (index=1; index <= itemsInList && err == noErr; index++) {
  894.         
  895.             err = AEGetNthPtr(    &docList, 
  896.                                 index,
  897.                                 typeFSS,
  898.                                 &keywd,
  899.                                 &returnedType,
  900.                                 (Ptr)&myFSS,
  901.                                 sizeof(myFSS),
  902.                                 &actualSize);
  903.     
  904.             if (err == noErr)    {
  905.             
  906.                 FInfo        fndrInfo ;
  907.                 
  908.                 // we now have a valid FSSpec to reference the file, we need to know 
  909.                 // what type the file is to determine which file open function to call
  910.                 // we can determine this from the finder info for the file
  911.                 
  912.                 err = FSpGetFInfo( &myFSS, &fndrInfo );    
  913.                 
  914.                 // if we got that ok, then we switch on the file  
  915.                 // type (we don't care about the creator type)    
  916.                         
  917.                 if (err == noErr)    {
  918.                 
  919.                     switch( fndrInfo.fdType ) {
  920.                         case 'TEXT':
  921.                         case '3DMF':
  922.                             err =  HandleOpenDoc(&myFSS);
  923.                             break ;
  924.                     }
  925.                 }
  926.             }
  927.         }
  928.         ignoreErr = AEDisposeDesc(&docList);
  929.     }
  930.     return err ;
  931. }
  932.  
  933. //-----------------------------------------------------------------------
  934. // handler for the print document event handler
  935.  
  936. pascal OSErr MyAEHandlePDOC(AppleEvent *theAppleEvent,AppleEvent *reply,long refCon)
  937. {
  938.     FSSpec         myFSS;
  939.     AEDescList    docList;
  940.     OSErr        err;
  941.     long        index,
  942.                 itemsInList;
  943.     Size         actualSize;
  944.     AEKeyword    keywd;
  945.     DescType    returnedType;
  946.  
  947.     
  948.     err = AEGetParamDesc(theAppleEvent,keyDirectObject,typeAEList,&docList);
  949.     if (err == noErr) {
  950.     
  951.         // see how many descriptor items are in the list
  952.         // this is the number of documents we want to open
  953.         err = AECountItems(&docList,&itemsInList);
  954.  
  955.         // now get each descriptor record from the list
  956.         // coerce the returned data to an FSSpec record, and
  957.         // open the asoociated file
  958.         
  959.         for (index=1; index <= itemsInList && err == noErr; index++) {
  960.         
  961.             err = AEGetNthPtr(    &docList, 
  962.                                 index,
  963.                                 typeFSS,
  964.                                 &keywd,
  965.                                 &returnedType,
  966.                                 (Ptr)&myFSS,
  967.                                 sizeof(myFSS),
  968.                                 &actualSize);
  969.     
  970.             if (err == noErr)    {                    
  971.                 // err = HandlePrintDoc( &myFSS );
  972.                 err = errAEEventNotHandled ;         // we don't do this yet...
  973.             }
  974.         }
  975.         err = AEDisposeDesc(&docList);
  976.     }
  977.     return err ;
  978. }
  979.  
  980. //-----------------------------------------------------------------------
  981. // quit appleevent handler
  982.  
  983. pascal OSErr MyAEHandleQUIT(AppleEvent *theAppleEvent,AppleEvent *reply,long refCon)
  984. {
  985.     OSErr             err = noErr ;        // used as return value
  986.     WindowPtr        theWindow ;
  987.     Boolean            quitting = true ;
  988.  
  989.     
  990.     // close all windows and signal to Quit
  991.  
  992.         
  993.     // attempt to close all documents
  994.     while(( theWindow = FrontWindow()) != nil && quitting )
  995.         quitting = (MyDisposeViewerWindow( theWindow ) == noErr);    
  996.         
  997.  
  998.     // if we closed everything up successfully, we can return noErr, otherwise
  999.     // indicate to sender of the 'quit' aevt that we canceled
  1000.     
  1001.     if (quitting) {
  1002.         gQuitFlag = true;                    // user didn't cancel
  1003.          AEDisposeDesc(&gSelfAddress);        // Dispose of my self-addressed descriptor.
  1004.     }
  1005.     else {
  1006.         err = userCanceledErr ;
  1007.     }
  1008.             
  1009.     return err ;
  1010. }
  1011.  
  1012.  
  1013. //----------------------------------------------------------------------------------//
  1014. //    Send a Quit Application Apple Event to myself to terminate this app.        
  1015.  
  1016. void MySendQuitApp( void )
  1017. {
  1018.     AppleEvent    myAppleEvent, reply;
  1019.     
  1020.     //    Create the Apple Event.
  1021.     FailIfErr(AECreateAppleEvent( kCoreEventClass, 
  1022.                                   kAEQuitApplication, 
  1023.                                   &gSelfAddress,
  1024.                                   kAutoGenerateReturnID, 
  1025.                                   kAnyTransactionID, 
  1026.                                   &myAppleEvent));
  1027.                                   
  1028.     //    Send the Apple Event.
  1029.       FailIfErr(AESend( &myAppleEvent, 
  1030.                         &reply, 
  1031.                         kAENoReply+kAENeverInteract, 
  1032.                         kAENormalPriority,
  1033.                         kAEDefaultTimeout, 
  1034.                         nil, 
  1035.                         nil));
  1036.                         
  1037.       AEDisposeDesc(&myAppleEvent);                // Dispose of the Apple Event.
  1038. } // MySendQuitApp
  1039.  
  1040.  
  1041. //----------------------------------------------------------------------------------//
  1042. //    Send a Open Document Application Apple Event to myself to open a document.        
  1043.  
  1044. void MySendOpenDoc(FSSpec *myFSSpec)
  1045. {
  1046.      AppleEvent    myAppleEvent;
  1047.     AppleEvent    defReply;
  1048.     AEDescList    docList;
  1049.     OSErr         myErr;
  1050.     OSErr         ignoreErr;
  1051.     
  1052.     myAppleEvent.dataHandle = nil;
  1053.     docList.dataHandle  = nil;
  1054.     defReply.dataHandle = nil;
  1055.         
  1056.     // Create empty list and add one file spec
  1057.     FailIfErr(AECreateList(nil,0,false, &docList));
  1058.     
  1059.     FailIfErr(AEPutPtr(&docList,1,typeFSS,(Ptr)myFSSpec,sizeof(FSSpec)));
  1060.         
  1061.     FailIfErr(AECreateAppleEvent(    kCoreEventClass,
  1062.                                     kAEOpenDocuments,
  1063.                                     &gSelfAddress,
  1064.                                     kAutoGenerateReturnID,
  1065.                                     kAnyTransactionID,
  1066.                                     &myAppleEvent));
  1067.  
  1068.     // Put Params into our event and send it
  1069.  
  1070.     FailIfErr(AEPutParamDesc( &myAppleEvent,
  1071.                               keyDirectObject,
  1072.                               &docList));
  1073.  
  1074.     FailIfErr(AESend( &myAppleEvent,
  1075.                       &defReply,
  1076.                       kAENoReply+kAENeverInteract,
  1077.                       kAENormalPriority,
  1078.                       kAEDefaultTimeout,
  1079.                       nil,
  1080.                       nil));
  1081.         
  1082.         
  1083.     if (myAppleEvent.dataHandle) 
  1084.         ignoreErr = AEDisposeDesc(&myAppleEvent);
  1085.         
  1086.     if (docList.dataHandle) 
  1087.         ignoreErr = AEDisposeDesc(&docList);
  1088.             
  1089. }    // MySendOpenDoc 
  1090.