home *** CD-ROM | disk | FTP | other *** search
Text File | 2000-06-23 | 28.4 KB | 1,000 lines |
- /******************************************************************************
- **
- ** Project Name: DropShell
- ** File Name: DropShell.c
- **
- ** Description: Main application code for the QuickShell
- **
- *******************************************************************************
- ** A U T H O R I D E N T I T Y
- *******************************************************************************
- **
- ** Initials Name
- ** -------- -----------------------------------------------
- ** LDR Leonard Rosenthol
- ** MTC Marshall Clow
- ** SCS Stephan Somogyi
- **
- *******************************************************************************
- ** R E V I S I O N H I S T O R Y
- *******************************************************************************
- **
- ** Date Author Description
- ** --------- ------ ---------------------------------------------
- ** 22 Aug 96 MTC Merged the AppleEvent stuff into this file.
- ** 22 Jul 96 MTC Now in C++!
- ** 23 Jun 94 LDR Implemented support for disk insertion events
- ** 02 Feb 94 LDR Updated for Final SDK & CodeWarrior a2
- ** Removed the ResumeProc as per new Apple recommendations
- ** 11 Dec 93 SCS Universal Headers/UPPs (Phoenix 68k/PPC & PPCC)
- ** Skipped System 6 compatible rev of DropShell source
- ** 09 Dec 91 LDR Added support for new "Select File…" menu item
- ** Quit now sends AEVT to self to be politically correct
- ** Added support for the new gSplashScreen
- ** 24 Nov 91 LDR Added support for the Apple Menu (duh!)
- ** 29 Oct 91 SCS Changes for THINK C 5
- ** 28 Oct 91 LDR Officially renamed DropShell (from QuickShell)
- ** Added a bunch of comments for clarification
- ** 06 Oct 91 MTC Converted to MPW C
- ** 09 Apr 91 LDR Added to Projector
- **
- ******************************************************************************/
-
- #include <Types.h>
- #include <Dialogs.h>
- #include <DiskInit.h>
- #include <Errors.h>
- #include <Files.h>
- #include <Fonts.h>
- #include <Memory.h>
- #include <Menus.h>
- #include <StandardFile.h>
- #include <TextEdit.h>
- #include <Windows.h>
-
- #ifndef __DROPSHELL3__
- #include "DropShell3.h"
- #endif
-
- #ifndef _FILEITERATORS_
- #include "FileIterators.h"
- #endif
-
- #include "DS3Resources.h"
-
-
- struct DSConfigRec {
- UInt32 mmCount; // How many times should we call MoreMasters?
- UInt32 tpCount; // How big a thread pool should we allocate?
- };
- typedef struct DSConfigRec DSConfigRec, *DSConfigPtr, **DSConfigHdl;
-
-
- pascal void DoHighLevelEvent(EventRecord *event);
- static void SendQuitToSelf (void);
- static void ErrorAlert ( short alertID, short stringListID, short stringIndexID, short errorID );
-
-
- /*
- Nothing fancy. Just setting up the basic menus.
- */
- #pragma segment Initialize
- void CDropShell::SetUpMenus (void) {
-
- // Add the Apple Menu
- fAppleMenu = GetMenu ( kAppleNum );
- // AssertStr ( ValidHandle ((Handle) fAppleMenu ), "\pCan't load Apple Menu" );
- AppendResMenu ( fAppleMenu, 'DRVR' );
- InsertMenu ( fAppleMenu, 0 );
-
- // Add the file menu
- fFileMenu = GetMenu ( kFileNum );
- // AssertStr ( ValidHandle ((Handle) fAppleMenu ), "\pCan't load File Menu" );
- InsertMenu ( fFileMenu, 0 );
-
- // And the edit menu
- fEditMenu = GetMenu ( kEditNum );
- // AssertStr ( ValidHandle ((Handle) fAppleMenu ), "\pCan't load Edit Menu" );
- if ( fEditMenu != nil )
- InsertMenu ( fEditMenu, 0 );
- }
-
- /*
- This routine is called during startup to display a splash screen.
-
- This was recommend by the Blue Team HI person, John Sullivan, who
- feels that all apps should display something so that users can easily
- tell what is running, and be able to switch by clicking. Thanks John!
- */
- #pragma segment Initialize
- static void CenterWindow ( WindowRef theWindow ) {
- SInt16 menuBarHeight = LMGetMBarHeight ();
- GDHandle gd = GetMainDevice ();
- Rect wRect = GetWindowPort ( theWindow )->portRect;
- SInt16 r, c, b;
-
- b = (*gd)->gdRect.bottom;
- r = b - (*gd)->gdRect.top;
- c = wRect.bottom - wRect.top;
-
- // Original code was: if (c / r > 0.9)
- // I changed it to remove floating point dependencies
- // Note that c is never going to be greater than 2000 here, so *10 is harmless.
- if (( 10 * c ) / r > 9 )
- c = ( b - wRect.bottom - wRect.top ) / 2 + menuBarHeight;
- else
- c = (b - wRect.bottom - wRect.top ) / 3 + menuBarHeight;
-
- r = ((*gd)->gdRect.right - wRect.right - wRect.left ) / 2;
-
- MoveWindow ( theWindow, r, c, false);
- }
-
-
- #pragma segment Initialize
- void CDropShell::InstallSplashScreen ( void ) {
- #define windowPicID 128
-
- PicHandle picH;
-
- if ( fSplashScreen == nil ) { // show the splash screen window
- picH = GetPicture ( windowPicID );
- if ( picH != NULL ) {
- Rect r = (*picH)->picFrame;
- fSplashScreen = GetNewWindow ( windowPicID, NULL, (WindowPtr) -1L );
- if ( fSplashScreen != nil ) {
- // Make the window the same size as the picture
- SizeWindow ( fSplashScreen, r.right - r.left, r.bottom - r.top, true );
- CenterWindow ( fSplashScreen );
- SetWindowPic ( fSplashScreen, picH );
- }
- }
- }
- }
-
-
- /* --------------- Standard Event Handling routines ---------------------- */
- #pragma segment Main
- void CDropShell::ShowAbout () {
- (void) Alert ( 128, NULL );
- }
-
-
- #pragma segment Main
- void CDropShell::DoMenu ( long menuChoice ) {
- short menuID, itemID;
- Str255 itemStr;
-
- menuID = HiWord ( menuChoice );
- itemID = LoWord ( menuChoice );
-
- switch ( menuID ) {
- case kAppleNum:
- if ( itemID == 1 )
- ShowAbout (); /* Show the about box */
- else {
- GetMenuItemText ( GetMenuHandle ( kAppleNum ), itemID, itemStr );
- OpenDeskAcc ( itemStr );
- }
- break;
-
- // Handle the first and the last items in the file menu
- // other ones are up to the actual app.
- case kFileNum:
- if ( itemID == 1 )
- SelectFile (); // call file selection userProc
- else if ( itemID == CountMItems ( fFileMenu ))
- SendQuitToSelf (); // send self a 'quit' event
- break;
-
- default:
- break;
-
- }
-
- HiliteMenu ( 0 ); // turn off the menu
- }
-
-
- #pragma segment Main
- void CDropShell::DoMouseDown ( EventRecord *curEvent ) {
- WindowPtr whichWindow;
- short whichPart;
-
- whichPart = FindWindow ( curEvent->where, &whichWindow );
- switch ( whichPart ) {
- case inMenuBar:
- DoMenu ( MenuSelect ( curEvent->where ));
- break;
-
- case inSysWindow:
- SystemClick ( curEvent, whichWindow );
- break;
-
- case inDrag:
- {
- Rect boundsRect = (*GetGrayRgn())->rgnBBox;
- DragWindow ( whichWindow, curEvent->where, &boundsRect );
- }
- default:
- break;
- }
- }
-
-
- #pragma segment Main
- void CDropShell::DoKeyDown ( EventRecord *curEvent ) {
- if ( curEvent->modifiers & cmdKey )
- DoMenu ( MenuKey ((char) curEvent->message & charCodeMask ));
- }
-
-
- #pragma segment Main
- void CDropShell::EventLoop( void )
- {
- EventRecord anEvent;
-
- if ( WaitNextEvent ( everyEvent, &anEvent, 0, NULL )) {
- switch ( anEvent.what ) {
- case kHighLevelEvent:
- DoHighLevelEvent ( &anEvent );
- break;
-
- case mouseDown:
- DoMouseDown ( &anEvent );
- break;
-
- case keyDown:
- case autoKey:
- DoKeyDown ( &anEvent );
- break;
-
- case diskEvt:
- if ( HiWord ( anEvent.message )) {
- Point diskInitPt = { 100, 100 };
-
- DILoad ();
- DIBadMount ( diskInitPt, anEvent.message );
- DIUnload ();
- }
- break;
-
- default:
- break;
- }
- }
- }
-
- #pragma segment Main
- void CDropShell::Run ( ) {
- OSErr err = noErr;
-
- // We don't run if there are no AppleEvents!
- if ( !fHasAppleEvents )
- ErrorAlert ( kAlertID, kErrStringID, kCantRunErr, 0 );
- else {
-
- // Install the required appleEvent handlers
- if (( err = InitAEVTStuff ()) != noErr )
- ErrorAlert ( kAlertID, kErrStringID, kInitAErr, err );
- else {
- // We want to draw the menu bar ourselves instead of
- // letting SetupMenus call it, because SetupMenus might be
- // overridden, and we don't want a flash mtc 08-14-96
- SetUpMenus ();
- DrawMenuBar ();
-
- // Install the splash screen. This only shows if the user
- // double-clicked on the application.
- InstallSplashScreen ();
-
- if (( err = InitGlobals ()) != noErr )
- ErrorAlert ( kAlertID, kErrStringID, kInitProgErr, err );
- else {
- while ( !fDone ) {
- EventLoop();
- }
-
- // Clean up whatever globals we need
- DeInitGlobals ();
- }
- }
- }
- }
-
-
- #ifdef MPW
- extern "C" { void _DataInit (); }
- #endif
-
- CDropShell::CDropShell ( Boolean walkFolders ) : fWalkFolders ( walkFolders ) {
- long aLong;
-
- #ifdef MPW
- UnloadSeg ((Ptr) _DataInit );
- #endif
-
- // Initialize the toolbox
- InitGraf ( &qd.thePort );
- InitFonts ();
- InitWindows ();
- InitMenus ();
- TEInit ();
- InitDialogs ( 0 );
- InitCursor ();
- FlushEvents ( everyEvent, 0 );
-
- // Initialize the globals for the app
- fDone = false;
- fOApped = false; // probably not since users are supposed to DROP things!
- fHasAppleEvents = Gestalt ( gestaltAppleEventsAttr, &aLong ) == noErr;
- fHasThreadMgr = Gestalt ( gestaltThreadMgrAttr, &aLong ) == noErr && ( aLong & ( 1 << gestaltThreadMgrPresent )) != 0;
- fSplashScreen = NULL;
- fAppleMenu = NULL;
- fFileMenu = NULL;
- fEditMenu = NULL;
-
- // Load a resource for params
- UInt32 mmCount = 2;
- UInt32 tpCount = 0;
- DSConfigHdl conf = (DSConfigHdl) GetResource ( 'Conf', 128 );
- if ( conf != nil ) {
- mmCount = (*conf)->mmCount;
- tpCount = (*conf)->tpCount;
- ReleaseResource ((Handle) conf );
- }
-
- MaxApplZone();
- for ( UInt32 i = 0; i < mmCount; i++ )
- MoreMasters ();
-
- // If we don't want threaded apps, then pretend we don't have it!
- if ( fHasThreadMgr && tpCount == 0 )
- fHasThreadMgr = false;
-
- // Allocate a thread pool
- if ( fHasThreadMgr && tpCount > 0 ) {
- }
- }
-
- CDropShell::~CDropShell() {}
-
- #pragma mark ---AppleEvents---
-
- OSErr GotRequiredParams(AppleEvent *theAppleEvent);
-
- //pascal OSErr _HandleDocs ( AppleEvent *theAppleEvent, AppleEvent *reply, long handlerRefcon, Boolean opening );
-
- pascal OSErr HandleOAPP(AppleEvent *theAppleEvent, AppleEvent *reply, long handlerRefcon);
- pascal OSErr HandleQuit(AppleEvent *theAppleEvent, AppleEvent *reply, long handlerRefcon);
- pascal OSErr HandleODOC(AppleEvent *theAppleEvent, AppleEvent *reply, long handlerRefcon);
- pascal OSErr HandlePDOC(AppleEvent *theAppleEvent, AppleEvent *reply, long handlerRefcon);
-
- /*
- This routine does all initialization for AEM, including the
- creation and then population of the dispatch table.
- */
- #pragma segment Initialize
- OSErr CDropShell::InitAEVTStuff () {
- OSErr err = noErr;
-
- if ( err == noErr )
- err = AEInstallEventHandler ( kCoreEventClass, kAEOpenApplication,
- NewAEEventHandlerProc ( HandleOAPP ), (long) this, false );
-
- if ( err == noErr )
- err = AEInstallEventHandler ( kCoreEventClass, kAEOpenDocuments,
- NewAEEventHandlerProc ( HandleODOC ), (long) this, false );
-
- if ( err == noErr )
- err = AEInstallEventHandler ( kCoreEventClass, kAEPrintDocuments,
- NewAEEventHandlerProc ( HandlePDOC ), (long) this, false );
-
- if ( err == noErr )
- err = AEInstallEventHandler ( kCoreEventClass, kAEQuitApplication,
- NewAEEventHandlerProc ( HandleQuit ), (long) this, false );
-
- // ReportError ( err );
- return err;
- }
-
-
-
- /*
- This routine will create a targetDesc for sending to self.
-
- We take IM VI's advice and use the typePSN form with
- kCurrentProcess as the targetPSN.
- */
- static OSErr GetTargetFromSelf ( AEAddressDesc *targetDesc ) {
- OSErr err = noErr;
- ProcessSerialNumber psn;
-
- psn.highLongOfPSN = 0;
- psn.lowLongOfPSN = kCurrentProcess;
-
- err = AECreateDesc(typeProcessSerialNumber, (Ptr)&psn, sizeof(ProcessSerialNumber), targetDesc );
-
- // ReportError ( err );
- return err;
- }
-
-
- /*
- This routine is the low level routine used by the SendODOCToSelf
- routine. It gets passed the list of files (in an AEDescList)
- to be sent as the data for the 'odoc', builds up the event
- and sends off the event.
-
- It is broken out from SendODOCToSelf so that a SendODOCListToSelf could
- easily be written and it could then call this routine - but that is left
- as an exercise to the reader.
-
- Read the comments in the code for the order and details
- */
- static void _SendDocsToSelf ( AEDescList *fileList ) {
- OSErr err = noErr;
- AEAddressDesc theTarget;
- AppleEvent openDocAE, replyAE;
-
- /*
- First we create the target for the event. We call another
- utility routine for creating the target.
- */
- err = GetTargetFromSelf ( &theTarget );
- if ( err == noErr ) {
- /* Next we create the Apple event that will later get sent. */
- err = AECreateAppleEvent ( kCoreEventClass, kAEOpenDocuments,
- &theTarget, kAutoGenerateReturnID, kAnyTransactionID, &openDocAE );
-
- if ( err == noErr ) {
- /* Now add the fileDescList to the openDocAE */
- err = AEPutParamDesc ( &openDocAE, keyDirectObject, fileList );
-
- if ( err == noErr ) {
- /* and finally send the event */
- /* Since we are sending to ourselves, no need for reply. */
- err = AESend ( &openDocAE, &replyAE, kAENoReply + kAECanInteract,
- kAENormalPriority, 3600, NULL, NULL );
- // AssertStr ( err == noErr, "\pError Sending 'odoc' Apple Event" );
-
- /* NOTE: Since we are not requesting a reply, we do not need to */
- /* need to dispose of the replyAE. It is there simply as a */
- /* placeholder. */
- }
-
- /* Dispose of the fileList descriptor
- We do this instead of the caller since it needs to be done
- before disposing the AEVT
- */
- err = AEDisposeDesc ( fileList );
- // AssertStr ( err == noErr, "\pError Disposing of File list" );
-
- /* and of course dispose of the openDoc AEVT itself*/
- err = AEDisposeDesc ( &openDocAE );
- // AssertStr ( err == noErr, "\pError Disposing of AppleEvent" );
- }
-
- /* and of course dispose of the Target */
- err = AEDisposeDesc ( &theTarget );
- // AssertStr ( err == noErr, "\pError Disposing of Target" );
- }
-
- // AssertStr ( err == noErr, "\p_SendDocsToSelf" );
- }
-
- /*
- This is the routine called by SelectFile to send a single odoc to ourselves.
-
- It calls the above low level routine to do the dirty work of sending the AEVT -
- all we do here is build a AEDescList of the file to be opened.
- */
- void SendODOCToSelf ( FSSpecPtr theFileSpec ) {
- OSErr err = noErr;
- AEDescList fileList;
-
- /* Create the descList to hold the list of files */
- err = AECreateList ( NULL, 0, false, &fileList );
-
- if ( err == noErr ) {
- /* Add the FSSpec to the list */
- err = AEPutPtr ( &fileList, 0, typeFSS, theFileSpec, sizeof ( FSSpec ));
- // AssertStr ( err == noErr, "\pError Adding FSSpec to AEDesc" );
-
- /* Now call the real gut level routine to do the dirty work*/
- if ( err == noErr )
- _SendDocsToSelf ( &fileList );
-
- /* _SendDocsToSelf will dispose of fileList for me */
- }
-
- // AssertStr ( err == noErr, "\pSendODOCToSelf" );
- }
-
-
- static void SendQuitToSelf ( void ) {
- OSErr err = noErr;
- AEAddressDesc theTarget;
- AppleEvent quitAE, replyAE;
-
- /*
- First we create the target for the event. We call another
- utility routine for creating the target.
- */
- err = GetTargetFromSelf ( &theTarget );
- if ( err == noErr ) {
-
- /* Next we create the Apple event that will later get sent. */
- err = AECreateAppleEvent ( kCoreEventClass, kAEQuitApplication,
- &theTarget, kAutoGenerateReturnID, kAnyTransactionID, &quitAE );
-
- if ( err == noErr ) {
- /*
- and finally send the event
- Since we are sending to ourselves, no need for reply.
- */
- err = AESend ( &quitAE, &replyAE, kAENoReply + kAECanInteract, kAENormalPriority, 3600, NULL, NULL );
- // AssertStr ( err == noErr, "\pError Sending 'quit' Apple Event" );
-
- /*
- NOTE: Since we are not requesting a reply, we do not need to
- need to dispose of the replyAE. It is there simply as a
- placeholder.
- */
-
- /* Dispose of the quit AEVT */
- err = AEDisposeDesc ( &quitAE );
- // AssertStr ( err == noErr, "\pError disposing 'quit' Apple Event" );
- }
-
- /* Dispose of the target. */
- err = AEDisposeDesc ( &theTarget );
- // AssertStr ( err == noErr, "\pError disposing target" );
- }
-
- // AssertStr ( err == noErr, "\pSendQuitToSelf" );
- }
-
- /*
- This routine is a utility routine for checking that all required
- parameters in the Apple event have been used.
- */
- #pragma segment Main
- OSErr GotRequiredParams ( AppleEvent *theAppleEvent ) {
- DescType typeCode;
- Size actualSize;
- OSErr retErr, err;
-
- err = AEGetAttributePtr ( theAppleEvent, keyMissedKeywordAttr,
- typeWildCard, &typeCode, NULL, 0, &actualSize );
-
- if ( err == errAEDescNotFound ) // we got all the required params: all is ok
- retErr = noErr;
- else if ( err == noErr )
- retErr = errAEEventNotHandled;
- else
- retErr = err;
-
- // ReportError ( retErr );
- return retErr;
- }
-
- /*
- This routine is the handler for the oapp (Open Application) event.
-
- It first checks the number of parameters to make sure we got them all
- (even though we don't want any) and then calls the OpenApp userProc in QSUserProcs.
- Finally it checks to see if the caller wanted a reply & sends one, setting any error.
- */
- #pragma segment Main
- pascal OSErr HandleOAPP ( AppleEvent * /*theAppleEvent*/, AppleEvent *reply, long handlerRefcon ) {
- CDropShell *theApp = (CDropShell *) handlerRefcon;
- OSErr err = noErr;
-
- theApp->OpenApp (); // pass it on to the app specific routine
-
- if ( reply->dataHandle != NULL ) /* a reply is sought */
- err = AEPutParamPtr ( reply, 'errs', 'TEXT', "Opening", 7 );
-
- // Report an error here!
- if ( err != noErr ) {
- ErrorAlert ( kAlertID, kErrStringID, kAEVTErr, err );
- }
-
- // ReportError ( err );
- return err;
- }
-
-
- /*
- This routine is the handler for the quit (Quit Application) event.
- It calls the QuitApp method for the app.
- Finally it checks to see if the caller wanted a reply & sends one, setting any error.
- */
-
- #pragma segment Main
- pascal OSErr HandleQuit ( AppleEvent * /*theAppleEvent*/, AppleEvent *reply, long handlerRefcon ) {
- CDropShell *theApp = (CDropShell *) handlerRefcon;
- OSErr err = noErr;
-
- theApp->QuitApp (); // pass it on to the app specific routine
- if ( reply->dataHandle != NULL ) /* a reply is sought */
- err = AEPutParamPtr ( reply, 'errs', 'TEXT', "Qutting", 7 );
-
- // Report an error here!
- if ( err != noErr ) {
- ErrorAlert ( kAlertID, kErrStringID, kAEVTErr, err );
- }
-
- // ReportError ( err );
- return err;
- }
-
-
- /*
- This routine is the low level processing routine for both the
- odoc (Open Document) and pdoc (Print Document) events.
-
- This routine is the key one, since this is how we get the list of
- files/folders/disks to process. The first thing to do is the get the
- list of files, and then make sure that's all the parameters (should be!).
- We then send call the PreflightDocs routine (from DSUserProcs), process
- each file in the list by calling OpenDoc (again in DSUserProcs), and finally
- call PostflightDocs (you know where) and setting a return value.
- */
- #pragma segment Main
- static pascal OSErr _HandleDocs ( AppleEvent *theAppleEvent, AppleEvent *reply, long handlerRefcon, Boolean opening ) {
- CDropShell *theApp = (CDropShell *) handlerRefcon;
- OSErr err = noErr;
- OSErr err2;
- AEDescList docList;
-
- // Get the list
- // Note that (for some reason) we have to call AEGetParamDesc _before_ we call
- // GotRequiredParams, or GotRequiredParams will return an error.
- err = AEGetParamDesc ( theAppleEvent, keyDirectObject, typeAEList, &docList );
- if ( err == noErr ) {
- err = GotRequiredParams ( theAppleEvent );
-
- /* How many items do we have?. */
- /* NOTE: Moved here in DS 2.0 due to requests for this info in preflighter */
- if ( err == noErr ) {
- long itemsInList;
- err = AECountItems ( &docList, &itemsInList );
-
- if ( err == noErr ) {
- if ( !theApp->PreFlightDocs ( opening, (short) itemsInList ))
- err = errAEEventNotHandled; // tells AEM that we didn't handle it!
- else {
- FSSpec myFSS;
- long index;
- Size actualSize;
- AEKeyword keywd;
- DescType typeCode;
-
- // process each file in the list
- for ( index = 1; err == noErr && index <= itemsInList; index++ ) {
- if (( err = AEGetNthPtr ( &docList, index, typeFSS, &keywd, &typeCode,
- (Ptr) &myFSS, sizeof ( myFSS ), &actualSize )) == noErr )
- err = theApp->OpenDoc ( myFSS, opening ); // call the userProc
- }
-
- OSErr err2 = theApp->PostFlightDocs ( opening, (short) itemsInList ); // cleanup time
- if ( err == noErr )
- err = err2; // return the first error
- }
- }
- }
-
- // If we got the list successfully, dispose of it, saving any existing error
- err2 = AEDisposeDesc ( &docList );
- if ( err == noErr )
- err = err2;
- }
-
- // Reply only if the caller said to
- if ( reply->dataHandle != NULL ) {
- err2 = AEPutParamPtr ( reply, 'errn', 'shor', (Ptr) &err, sizeof ( err ));
- if ( err == noErr )
- err = err2;
- }
-
- // Report an error here!
- if ( err != noErr ) {
- ErrorAlert ( kAlertID, kErrStringID, kAEVTErr, err );
- }
-
- // ReportError ( err );
- return err;
- }
-
-
- /*
- This routine is the handler for the odoc (Open Document) event.
- The odoc event simply calls the common _HandleDocs routines, which will
- do the dirty work of parsing the AEVT & calling the userProcs.
- */
- #pragma segment Main
- pascal OSErr HandleODOC ( AppleEvent *theAppleEvent, AppleEvent *reply, long handlerRefcon ) {
- OSErr err = noErr;
-
- // call the low-level routine
- err = _HandleDocs ( theAppleEvent, reply, handlerRefcon, true );
-
- // ReportError ( err );
- return err;
- }
-
-
- /*
- This routine is the handler for the pdoc (Print Document) event.
- The pdoc event like the odoc simply calls the common _HandleDocs routines
- */
- #pragma segment Main
- pascal OSErr HandlePDOC ( AppleEvent *theAppleEvent, AppleEvent *reply, long handlerRefcon ) {
- OSErr err = noErr;
-
- // call the low-level routine
- err = _HandleDocs ( theAppleEvent, reply, handlerRefcon, false );
-
- // ReportError ( err );
- return err;
- }
-
-
- /*
- This is the routine called by the main event loop, when a high level
- event is found. Since we only deal with Apple events, and not other
- high level events, we just pass everything onto the AEM via AEProcessAppleEvent
- */
- #pragma segment Main
- pascal void DoHighLevelEvent ( EventRecord *event ) {
- // FailErr ( AEProcessAppleEvent ( event ));
- AEProcessAppleEvent ( event );
- }
-
-
- #pragma segment Main
- static void ErrorAlert ( short alertID, short stringListID, short stringIndexID, short errorID ) {
- Str255 param, errorStr;
-
- // Set the cursor back to an arrow
- SetCursor ( &qd.arrow );
-
- // Fill in the info.
- NumToString ( errorID, errorStr );
- GetIndString ( param, stringListID, stringIndexID );
- ParamText ( param, errorStr, NULL, NULL );
-
- // Show the alert
- (void) Alert ( alertID, NULL );
- }
-
- #pragma mark ---User Procs---
-
- /*
- These routines let you do one-time setup and teardown.
- They are called at app startup and shutdown.
- */
- #pragma segment Main
- OSErr CDropShell::InitGlobals ( void ) { return noErr; }
-
- #pragma segment Main
- void CDropShell::DeInitGlobals ( void ) {}
-
-
-
- /*
- This routine is called when an OAPP event is received.
-
- Currently, all it does is set the gOApped flag, so you know that
- you were called initally with no docs, and therefore you shouldn't
- quit when done processing any following odocs.
- */
- #pragma segment Main
- void CDropShell::OpenApp ( void ) {
- fOApped = true;
-
- // let's show the user the splash screen
- if ( fSplashScreen != nil )
- ShowWindow ( fSplashScreen );
- }
-
-
- /*
- This routine is called when an QUIT event is received.
-
- We simply set the global done flag so that the main event loop can
- gracefully exit. We DO NOT call ExitToShell for two reasons:
- 1) It is a pretty ugly thing to do, but more importantly
- 2) The Apple event manager will get REAL upset!
- */
- #pragma segment Main
- void CDropShell::QuitApp (void) { fDone = true; }
-
-
- /*
- This routine is called when the user chooses "Select File…" from the
- File Menu.
-
- Currently it simply calls the new StandardGetFile routine to have the
- user select a single file (any type, numTypes = -1) and then calls the
- SendODOCToSelf routine in order to process it.
-
- The reason we send an odoc to ourselves is two fold: 1) it keeps the code
- cleaner as all file openings go through the same process, and 2) if events
- are ever recordable, the right things happen (this is called Factoring!)
-
- Modification of this routine to only select certain types of files, selection
- of multiple files, and/or handling of folder & disk selection is left
- as an exercise to the reader.
- */
- #pragma segment Main
- void CDropShell::SelectFile () {
- StandardFileReply stdReply;
- SFTypeList theTypeList;
-
- StandardGetFile ( NULL, -1, theTypeList, &stdReply );
- if ( stdReply.sfGood ) // user did not cancel
- SendODOCToSelf ( &stdReply.sfFile ); // so send me an event!
- }
-
-
- #pragma mark --Document Handling--
-
- /*
- This routine is the first one called when an ODOC or PDOC event is received.
-
- In this routine you would place code used to setup structures, etc.
- which would be used in a 'for all docs' situation (like "Archive all
- dropped files")
-
- Obviously, the opening boolean tells you whether you should be opening
- or printing these files based on the type of event recieved.
-
- NEW IN 2.0!
- The itemCount parameter is simply the number of items that were dropped on
- the application and that you will be processing. This gives you the ability
- to do a single preflight for memory allocation needs, rather than doing it
- once for each item as in previous versions.
-
- We also return a boolean to tell the caller if you support this type
- of event. By default, our dropboxes don't support the pdoc, so when
- opening is FALSE, we return FALSE to let the caller send back the
- proper error code to the AEManager.
-
- */
- #pragma segment Main
- Boolean CDropShell::PreFlightDocs (Boolean opening, short /*itemCount*/) {
- return opening; // we support opening, but not printing - see above
- }
-
-
- /*
- This routine is called for each file passed in the ODOC event.
-
- In this routine you would place code for processing each file/folder/disk that
- was dropped on top of you.
- */
- #pragma segment Main
- /* Is the “file” represented by this FSSpec really a folder? */
- static Boolean FSpIsFolder ( FSSpecPtr theFSSpec ) {
- OSErr err = noErr;
- CInfoPBRec pb;
- Str255 fName;
-
- if ( theFSSpec->parID == fsRtParID ) // it's a volume!!
- return true;
-
- BlockMoveData (theFSSpec->name, fName, 32);
- pb.hFileInfo.ioDirID = theFSSpec->parID;
- pb.hFileInfo.ioCompletion = NULL;
- pb.hFileInfo.ioNamePtr = fName;
- pb.hFileInfo.ioVRefNum = theFSSpec->vRefNum;
- pb.hFileInfo.ioFDirIndex = 0;
- pb.hFileInfo.ioFVersNum = 0;
- err = PBGetCatInfoSync ( &pb );
-
- if ( err == noErr && ( pb.hFileInfo.ioFlAttrib & ioDirMask ) != 0 )
- return true;
-
- return false;
- }
-
- OSErr CDropShell::OpenDoc ( FSSpec &myFSSpec, Boolean opening ) {
- OSErr err = noErr;
-
- if ( opening )
- if ( fWalkFolders ) {
- /* For this case we need to determine if the FSSpec is a file or folder. */
- /* If it's a folder, we then need to process each item in that folder, */
- /* otherwise just process the item. */
- if ( FSpIsFolder ( &myFSSpec ))
- err = ProcessFolder ( myFSSpec );
- else
- err = ProcessItem ( myFSSpec );
- }
- else {
- /* For this case we just call ProcessItem on the FSSpec above. */
- err = ProcessItem ( myFSSpec );
- }
-
- // ReportError ( err );
- return err;
- }
-
-
- /*
- This routine is the last routine called as part of an ODOC event.
-
- In this routine you would place code to process any structures, etc.
- that you setup in the PreflightDocs routine.
-
- NEW IN 2.0!
- The itemCount parameter was the number of items that you processed.
- It is passed here just in case you need it ;)
-
- */
- #pragma segment Main
- OSErr CDropShell::PostFlightDocs ( Boolean opening, short /*itemCount*/ ) {
- OSErr err = noErr;
-
- if ( opening && !fOApped )
- fDone = true; // close everything up!
-
- /*
- The reason we do not auto quit is based on a recommendation in the
- Apple event Registry which specifically states that you should NOT
- quit on a 'pdoc' as the Finder will send you a 'quit' when it is
- ready for you to do so.
- */
- // ReportError ( err );
- return err;
- }
-
-
- /*
- This routine gets called for each item (which could be either a file or a folder)
- that the caller wants dropped. The determining factor is the definition of the
- qWalkFolder compiler directive. Either way, the item in question should be
- processed as a single item and not "dissected" into component units (like subfiles
- of a folder!)
- */
- OSErr CDropShell::ProcessItem ( FSSpec & /* theFile */ ) {
- OSErr err = noErr;
-
- // do something here
-
- // ReportError ( err );
- return err;
- }
-
-
- /*
- This routine gets called for any folder (or disk) that the caller wants
- processed as a set of component items, instead of as a single entity.
- The determining factor is the definition of the qWalkFolder compiler directive.
- */
- OSErr CDropShell::ProcessFolder ( FSSpec &theFile ) {
- OSErr err = noErr;
- TDirectoryIterator iter ( &theFile );
- FSSpec aSpec;
- Boolean isFolder;
-
- iter.Start ();
- while ( err == noErr && iter.More ()) {
- err = iter.Next ( &aSpec, &isFolder );
- if ( err == noErr ) {
- if ( isFolder )
- err = ProcessFolder ( aSpec );
- else
- err = ProcessItem ( aSpec );
- }
- }
-
- // ReportError ( err );
- return err;
- }
-
- #pragma segment CompilerCruft
-