home *** CD-ROM | disk | FTP | other *** search
- /****
- File.....: FakeStart.c
- Date.....: Thursday, April 04 1996
- By.......: Ken Earle. No rights reserved.
- Status...: tested.
- Spec.....: "main" for the Fake Start project.
- Fake app to start up a "real" application, forcing it low in memory.
- Which application is determined by the "creator" code in
- STR# 1001, string 1.
- User double-clicks us or drags documents onto us.
- On Startup:
- -grab any opening Apple Event
- -check if the "real" application is open yet: if not,
- -allocate big chunks of system memory, locked and high
- -open the real application low in memory
- -pass any documents from opening AE along to real application
- -free system memory if allocated (not really needed)
- -Quit.
- This app has no interface, except for error Alerts.
- ****/
-
- #include <Traps.h>
- #include <GestaltEqu.h>
-
- #define _GestaltDispatch 0xA0AD
-
- #include "FakeStart.h"
- #include "MultiFnder.h"
- #include "FS_Memory.h"
-
- // Globals for system 7
- SysDetails gSysDetails;
- SysEnvRec gMac;
-
- // AE handling globals
- FSSpecElementPtr gSpecElementP = NULL; // for documents to open
- Boolean gWasOpenAE = FALSE; // received odoc event here
- Boolean gWasPrintAE = FALSE; // received pdoc event here
-
-
- // Functions in this file
- void main(void);
- void GetOut
- (short alertID, // eg ALRT 1000
- ErrorIndex theErrorMessageIndex, // into a STR# rsrc
- OSType realApplicationCreator // eg 'JAGO', app to launch
- );
- void DoMostStandardMacInits(void);
- OSType GetRealApplicationCreator(void);
- OSErr GrabStartupAppleEvent(void);
- OSErr OpenDocumentsInRunningApp
- (ProcessSerialNumber *serialNumP, // ->PSN of application
- FSSpecElementPtr specElementP // ->list of doc file specs
- );
- OSErr OpenItemInFinder(FSSpecElementPtr specElementP); // ->list of doc file specs
- // Utility functions
- // Gestalt and trap support
- static void InitGestaltGlobals(void);
- Boolean HasGestaltAbility
- (OSType selector, // eg gestaltFSAttr
- short bitNumber // eg gestaltHasFSSpecCalls
- );
- static Boolean System7Available(void);
- Boolean TrapIsAvailable(short theTrap);
- // AppleEvent handlers: we just remember any file specs passed along.
- void AEInstallEventHandlers(void);
- pascal OSErr Handle_aevt_oapp(AppleEvent *theAppleEventP, AppleEvent *reply,
- long myRefCon);
- pascal OSErr Handle_aevt_odoc(AppleEvent *theAppleEventP, AppleEvent *reply,
- long myRefCon);
- pascal OSErr Handle_aevt_pdoc(AppleEvent *theAppleEventP, AppleEvent *reply,
- long myRefCon);
- pascal OSErr Handle_aevt_quit(AppleEvent *theAppleEventP, AppleEvent *reply,
- long myRefCon);
- static OSErr ExtractFSSpecListFromAE(AppleEvent *theAppleEventP); // typ. 'odoc'
- OSErr AddFSSToAEList
- (AEDescList *aeDescListP, // <->becomes direct object of event
- short index, // 0 means add at end
- FSSpec *fsspecFileP // ->the document spec to add
- );
- // Process handling
- OSErr FindAProcess
- (OSType typeToFind, // eg 'APPL' or 'FNDR'
- OSType creatorToFind, // eg 'JAGO' or 'MACS'
- ProcessSerialNumberPtr processSN // <- PSN of process
- );
- // File handling
- static void GetErrorMessage
- (StringPtr messageP, // Str255 for ParamText
- ErrorIndex theErrorMessageIndex // into a STR# rsrc
- );
- static void GetGeneralMessage
- (StringPtr messageP, // Str255 for ParamText
- GeneralIndex theGeneralMessageIndex // into a STR# rsrc
- );
- OSErr LocateFileByTypeCreator
- (OSType fdType, // eg 'APPL'
- OSType fdCreator, // eg 'JAGO'
- short vRefNum, // 0 for default drive
- FSSpec *spec // <- file spec
- );
- OSErr LaunchIt
- (FSSpec *theAppP, // ->Specs which application to launch
- ProcessSerialNumber *serialNumP // <-filled in if we succeed
- );
- static OSErr AddSpecElement
- (FSSpecPtr theSpecP, // ->a document file spec
- FSSpecElementPtr *specElementPP // <->head of spec list or NULL first time
- );
-
-
- /* Do it all and quit, see spec at top.
- */
- void main(void)
- {
- EventRecord event; // used at end
- FSSpec realApplicationSpec; // for real Application
- ProcessSerialNumber realApplicationPSN; // ditto
- Handle bigChunkHA[NUM_HANDLES_TOP]; // to seize hi mem
- OSType realApplicationCreator; // eg 'JAGO', app to launch
- short i;
- OSErr theErr = noErr;
- Boolean realAppIsRunning = FALSE; // !avoid launching twice!
-
- // Clear system handles to be allocated
- for (i = 0; i < NUM_HANDLES_TOP; ++i)
- bigChunkHA[i] = NULL;
-
- // Do standard Mac inits.
- DoMostStandardMacInits();
-
- // Can we proceed? If not, alert and exit.
- if (gMac.machineType < 0) //does not have 128K ROMS
- GetOut(kCannotFunctionAlertID, eMachineTooOld_ErrorIndex, 0);
- if (!gSysDetails.hasSystem7 ) // too primitive
- GetOut(kCannotFunctionAlertID, ePreSystem7_ErrorIndex, 0);
- if (!gSysDetails.hasAE) // Can't start real app
- GetOut(kCannotFunctionAlertID, eNoAppleEvents_ErrorIndex, 0);
-
- // Get real Application Creator (eg 'JAGO') from our resources, or use default.
- realApplicationCreator = GetRealApplicationCreator();
-
- // Grab any startup Apple Event.
- theErr = GrabStartupAppleEvent(); // fills in global list gSpecElementP
- if (theErr != noErr)
- gSpecElementP = NULL;
-
- // Find real Application on disk, or get out.
- theErr = LocateFileByTypeCreator(realApplication_type, realApplicationCreator,
- 0, &realApplicationSpec);
- if (theErr != noErr)
- {
- GetOut( kCannotFunctionAlertID, eApplicationNotFound_ErrorIndex,
- realApplicationCreator );
- }
-
- // See if the real app is running.
- theErr = FindAProcess( realApplication_type, realApplicationCreator,
- &realApplicationPSN );
- if (theErr == noErr)
- realAppIsRunning = TRUE;
-
- // If not running, will need to grab upper memory to force app low.
- // If we can't grab the memory, get out.
- if (!realAppIsRunning)
- {
- // Leave just a piece of low system memory free for the real app.
- theErr =
- GrabUpperSystemMemory(&realApplicationSpec, bigChunkHA, NUM_HANDLES_TOP);
- if (theErr != noErr)
- {
- GetOut(kCannotFunctionAlertID, eMemoryOut_ErrorIndex, 0);
- }
- }
-
- // Launch real Application if it isn't running yet.
- if (!realAppIsRunning)
- {
- // Case with documents is the tricky one: if app understand AEs, then
- // launch app and send odoc; else ask Finder to do the open.
- if (gSpecElementP != NULL)
- {
- if (APP_IS_AE_AWARE)// see FakeStart.h
- {
- theErr = LaunchIt(&realApplicationSpec, &realApplicationPSN);
- if (theErr == noErr)
- theErr = OpenDocumentsInRunningApp( &realApplicationPSN,
- gSpecElementP );
- }
- else // old dumb thing, ask Finder to do the open
- theErr = OpenItemInFinder(gSpecElementP);
- }
- else // no document, just do a simple LaunchApplication
- theErr = LaunchIt(&realApplicationSpec, &realApplicationPSN);
- }
- else // already open, just pass the documents along
- {
- // Pass list of docs to real Application.
- if (gSpecElementP != NULL && theErr == noErr)
- theErr = OpenDocumentsInRunningApp(&realApplicationPSN, gSpecElementP);
- }
-
- // Deallocate system memory.
- if (bigChunkHA[0] != NULL)
- ReleaseUpperSystemMemory(bigChunkHA, NUM_HANDLES_TOP);
-
- // Spend a couple of events to start app.
- for (i = 0; i < 2; ++i)
- {
- (void)WaitNextEvent(everyEvent, &event, 2, NULL);
- }
- // Exit, all done.
- }
-
- /* Show alert and exit.
- */
- void GetOut
- (short alertID, // eg ALRT 1000
- ErrorIndex theErrorMessageIndex, // into a STR# rsrc
- OSType realApplicationCreator // eg 'JAGO', app to launch
- )
- {
- Str255 messageP; // put into param text
-
- // Read error message from STR# resource, put in param text.
- GetErrorMessage(messageP, theErrorMessageIndex);
-
- if (theErrorMessageIndex == eApplicationNotFound_ErrorIndex)
- {
- Str31 creatorString;
-
- // Put creator in front, followed by resource message
- BlockMove( &realApplicationCreator, creatorString + 1,
- sizeof(realApplicationCreator) );
- creatorString[0] = sizeof(realApplicationCreator);
- ParamText("\pCreator ", creatorString, messageP, "\p");
- }
- else
- {
- ParamText(messageP, "\p", "\p", "\p");
- }
- // Show a stop alert.
- StopAlert(alertID, NULL);
-
- // Die.
- ExitToShell();
- }
-
- /* Routine stuff, plus do SysEnv and a few Gestalt calls.
- */
- void DoMostStandardMacInits(void)
- {
-
- MaxApplZone();
- MoreMasters();
-
- InitGraf(&qd.thePort);
- InitCursor();
- InitFonts();
- InitWindows();
- InitMenus();
- InitDialogs(NULL);
- TEInit();
-
- // See if we have system 7 etc
- InitGestaltGlobals();
-
- // Finish AppleEvent init, object handling
- if (gSysDetails.hasAE)
- {
- AEObjectInit();
- }
- // Get standard environment information, complements gestalt info
- SysEnvirons(kSysEnvironsVersion, &gMac);
- // note the "blessed folder" is gMac.sysVRefNum
-
- // Can we do color? Hey, I was just curious....
- gSysDetails.hasColor = gMac.hasColorQD;
-
- // Install AE handlers
- if (gSysDetails.hasAE)
- AEInstallEventHandlers();
- }
-
- /* Grab STR# that holds real app's creator--if not found, use a default.
- */
- OSType GetRealApplicationCreator(void)
- {
- Str255 rawString; // big enough to hold any string
- OSType realApplicationCreator; // eg 'JAGO', returned value
-
- // Get raw string, using a large holder to be safe.
- GetGeneralMessage(rawString, eAppCreator_GeneralIndex);
-
- // If string "looks" like an OSType, use it, else use a default
- if (rawString[0] == 4)
- realApplicationCreator = *( (OSType *)(rawString + 1) );
- else
- realApplicationCreator = kDefaultAppCreator;
-
- return realApplicationCreator;
- }
-
- /* Do a few WNE's, waiting for an AE. If get an AE, collect file specs
- and return (handling of events done in Handle_aevt functions).
- */
- OSErr GrabStartupAppleEvent(void)
- {
- EventRecord event; // we wait for a hi-level event
- short i;
- Boolean gotEvent;
- Boolean receivedAE = FALSE; // what we're waiting for
- OSErr theErr = noErr;
-
- for (i = 0; i < 3 && !receivedAE; ++i)
- {
- gotEvent = WaitNextEvent(everyEvent, &event, 2, NULL);
- if (gotEvent)
- {
- switch (event.what)
- {
- case kHighLevelEvent:
- theErr = AEProcessAppleEvent(&event);
- receivedAE = TRUE;
- break;
- }
- }
- }
- return theErr;
- }
-
- /* Pass AE to a running app asking it to open some documents. Call ONLY
- if specElementP != NULL. Well it won't crash, but it also won't do much.
- */
- OSErr OpenDocumentsInRunningApp
- (ProcessSerialNumber *serialNumP, // ->PSN of application
- FSSpecElementPtr specElementP // ->list of doc file specs
- )
- {
- AEDesc target = {typeNull, NULL};
- AppleEvent aeEvent = {typeNull, NULL};
- AppleEvent aeReply = {typeNull, NULL};
- AEDescList aeDescFileList = {typeNull, NULL};
- AEEventID theAEEventID;
- AESendMode sendMode;
- OSErr theErr = noErr;
-
- // Sanity check
- if (specElementP == NULL)
- return noErr;
-
- // Which event, open or print?
- if (gWasOpenAE)
- theAEEventID = kAEOpenDocuments;
- else if (gWasPrintAE)
- theAEEventID = kAEPrintDocuments;
- else
- return noErr;
-
- // Create AE for target application.
- theErr = AECreateDesc(typeProcessSerialNumber, serialNumP,
- sizeof(*serialNumP), &target);
- if (theErr == noErr)
- theErr = AECreateAppleEvent(kCoreEventClass, theAEEventID,
- &target, kAutoGenerateReturnID,
- kAnyTransactionID, &aeEvent);
-
- // Prepare AEDesc for doc(s) to be launched.
- if (theErr == noErr)
- theErr = AECreateList(NULL, 0, FALSE, &aeDescFileList);
- while ( specElementP != NULL
- && theErr == noErr )
- {
- theErr = AddFSSToAEList(&aeDescFileList, 0, &specElementP->fss);
- specElementP = specElementP->next;
- }
- // Put list of docs in as direct object of the event.
- if (theErr == noErr)
- theErr = AEPutParamDesc(&aeEvent, keyDirectObject, &aeDescFileList);
-
- // Send 'odoc' or 'pdoc' AE to application, waiting for reply.
- sendMode = kAEWaitReply + kAECanSwitchLayer + kAENeverInteract;
- if (theErr == noErr)
- theErr = AESend(&aeEvent, &aeReply,
- sendMode, kAEHighPriority,
- kNoTimeOut, NULL, NULL);
- // Clean up.
- (void)AEDisposeDesc(&target);
- (void)AEDisposeDesc(&aeEvent);
- (void)AEDisposeDesc(&aeReply);
- (void)AEDisposeDesc(&aeDescFileList);
-
- return theErr;
- }
-
- /* Send in a list of FSSpec of items you wish the Finder to launch.
- */
- OSErr OpenItemInFinder(FSSpecElementPtr specElementP) // ->list of doc file specs
- {
- AEDesc target = {typeNull, NULL};
- AEDescList aeDescFileList = {typeNull, NULL};
- AppleEvent aeEvent = {typeNull, NULL},
- aeReply = {typeNull, NULL};
- AESendMode sendMode;
- ProcessSerialNumber psnOfFinder;
- OSErr theErr = noErr;
-
- // Use Gestalt to check for OSL compliance
- if (!HasGestaltAbility(gestaltFinderAttr, gestaltOSLCompliantFinder))
- {
- return 1; // codeword for OSL not supported here
- }
-
- // Grab process for finder
- theErr = FindAProcess(kostypeFinder, kostypeCreatorMac, &psnOfFinder);
- if (theErr == noErr)
- {
- // Prepare 'odoc' AE for finder
- theErr = AECreateDesc(typeProcessSerialNumber, &psnOfFinder,
- sizeof(ProcessSerialNumber), &target);
- if (theErr == noErr)
- theErr = AECreateAppleEvent(kCoreEventClass, kAEOpenDocuments,
- &target, kAutoGenerateReturnID,
- kAnyTransactionID, &aeEvent);
-
- // Prepare FSSpec(s) to send to finder
- if (theErr == noErr)
- theErr = AECreateList(NULL, 0, FALSE, &aeDescFileList);
- while ( specElementP != NULL
- && theErr == noErr )
- {
- theErr = AddFSSToAEList(&aeDescFileList, 0, &specElementP->fss);
- specElementP = specElementP->next;
- }
- // Put list of docs in as direct object of the event.
- if (theErr == noErr)
- theErr = AEPutParamDesc(&aeEvent, keyDirectObject, &aeDescFileList);
-
- // Send AE to Finder
- if (theErr == noErr)
- {
- // Set AE switches, wait for reply etc.
- sendMode = kAEWaitReply + kAECanSwitchLayer + kAENeverInteract;
- theErr = AESend(&aeEvent, &aeReply, sendMode,
- kAEHighPriority, kAEDefaultTimeout,
- NULL, NULL);
- }
- // Tidy up
- AEDisposeDesc(&aeEvent);
- AEDisposeDesc(&aeReply);
- AEDisposeDesc(&aeDescFileList);
- AEDisposeDesc(&target);
- }
- return theErr;
- }
-
- // Utility functions
-
- /* See if we have system 7 etc, fill in gSysDetails.
- */
- static void InitGestaltGlobals(void)
- {
- long response; // bits (flags) from Gestalt call
-
- // Do we have Gestalt? If not, don't do anything.
- gSysDetails.hasGestalt = TrapIsAvailable(_GestaltDispatch);
- if (!gSysDetails.hasGestalt)
- return;
- // Do we have system 7? Do nothing if not.
- gSysDetails.hasSystem7 = System7Available();
- if (!gSysDetails.hasSystem7)
- return;
- // Do we have the "new" file system?
- gSysDetails.hasFSS = HasGestaltAbility(gestaltFSAttr, gestaltHasFSSpecCalls);
- //...and certain standard new features?
- if (gSysDetails.hasFSS)
- gSysDetails.hasFSS =
- HasGestaltAbility(gestaltStandardFileAttr, gestaltStandardFile58);
- // Are Apple Events possible?
- if ( !Gestalt(gestaltAppleEventsAttr, &response)
- && !Gestalt(gestaltPPCToolboxAttr, &response) )
- {
- // Init communications
- gSysDetails.hasAE = (PPCInit() == noErr);
- }
- }
-
- /* Note call this only after setting global gSysDetails.hasGestalt.
- */
- Boolean HasGestaltAbility
- (OSType selector, // eg gestaltFSAttr
- short bitNumber // eg gestaltHasFSSpecCalls
- )
- {
- long response; // bits (flags) from Gestalt call
- Boolean hasThing = FALSE; // return value
-
- if (!gSysDetails.hasGestalt)
- return FALSE;
- if (!Gestalt(selector, &response))
- hasThing = (response & (1<<bitNumber));
- return hasThing;
- }
-
- /* See if we have at least system 7.
- */
- static Boolean System7Available(void)
- {
- long sysVersion;
-
- if (!Gestalt(gestaltSystemVersion,&sysVersion))
- {
- if (sysVersion >= 0x700)
- return TRUE;
- }
- return FALSE;
- }
-
- /* Determine if a particular call is available.
- */
- Boolean TrapIsAvailable(short theTrap)
- {
- TrapType theTrapType; // ToolTrap or OSTrap
- short numToolboxTraps;
-
- if ( (theTrap & 0x0800) > 0 )
- theTrapType = ToolTrap;
- else
- theTrapType = OSTrap;
-
- if (theTrapType == ToolTrap)
- {
- theTrap = theTrap & 0x07ff;
- if (NGetTrapAddress(_InitGraf, ToolTrap) == NGetTrapAddress(0xaa6e, ToolTrap))
- numToolboxTraps = 0x0200;
- else
- numToolboxTraps = 0x0400;
- if (theTrap >= numToolboxTraps)
- theTrap = _Unimplemented;
- }
-
- return (NGetTrapAddress(theTrap, theTrapType)
- != NGetTrapAddress(_Unimplemented, ToolTrap));
- }
-
- /* Install standard AE handlers.
- */
- void AEInstallEventHandlers(void)
- {
- AEEventHandlerUPP aHandler;
-
- aHandler = NewAEEventHandlerProc(Handle_aevt_oapp);
- (void)AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
- aHandler, 0L, FALSE);
- aHandler = NewAEEventHandlerProc(Handle_aevt_odoc);
- (void)AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
- aHandler, 0L, FALSE);
- aHandler = NewAEEventHandlerProc(Handle_aevt_pdoc);
- (void)AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
- aHandler, 0L, FALSE);
- aHandler = NewAEEventHandlerProc(Handle_aevt_quit);
- (void)AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
- aHandler, 0L, FALSE);
- }
-
-
- // AppleEvent handler functions
-
- /* Open the application (without documents).
- */
- pascal OSErr Handle_aevt_oapp(AppleEvent *theAppleEventP, AppleEvent *reply,
- long myRefCon)
- {
- #pragma unused(theAppleEventP, reply, myRefCon)
- return noErr;
- }
-
- /* Open app with a list of documents: we just grab the list to gSpecElementP.
- */
- pascal OSErr Handle_aevt_odoc(AppleEvent *theAppleEventP, AppleEvent *reply,
- long myRefCon)
- {
- OSErr theErr;
-
- #pragma unused(reply, myRefCon)
- // Remember the event type, for resending to real Application
- gWasOpenAE = TRUE;
- theErr = ExtractFSSpecListFromAE(theAppleEventP);
- return theErr;
- }
-
- /* Print a list of documents.
- */
- pascal OSErr Handle_aevt_pdoc(AppleEvent *theAppleEventP, AppleEvent *reply,
- long myRefCon)
- {
- OSErr theErr;
-
- #pragma unused(reply, myRefCon)
- // Remember the event type, for resending to real Application
- gWasPrintAE = TRUE;
- theErr = ExtractFSSpecListFromAE(theAppleEventP);
- return theErr;
- }
-
- /* Quit--we quit immediately anyway.
- */
- pascal OSErr Handle_aevt_quit(AppleEvent *theAppleEventP, AppleEvent *reply,
- long myRefCon)
- {
- #pragma unused(theAppleEventP, reply, myRefCon)
- return noErr;
- }
-
- /* Common to open and print, grab list of files to gSpecElementP.
- */
- static OSErr ExtractFSSpecListFromAE(AppleEvent *theAppleEventP) // typ. 'odoc'
- {
- AEDescList theAEDescList = { typeNull, NULL };
- AEKeyword theAEKeyword; // value not used
- FSSpec theSpec; // extracted from direct object of event
- DescType typeCode; // value not used
- Size actualSize; // value not used
- long i;
- long count; // count of file specs in direct object
- OSErr theErr = noErr;
-
- // Get direct object, containing file list.
- theErr = AEGetParamDesc( theAppleEventP, keyDirectObject,
- typeAEList, &theAEDescList );
- // Count the file items
- if (theErr == noErr)
- theErr = AECountItems(&theAEDescList, &count);
-
- // Loop over list, add FSSpecs to linked list gSpecElementP
- if (theErr == noErr)
- {
- for (i = 1; i <= count && theErr == noErr; ++i)
- {
- theErr = AEGetNthPtr(&theAEDescList, i, typeFSS, &theAEKeyword, &typeCode,
- &theSpec, sizeof(FSSpec), &actualSize);
- if (theErr == noErr)
- {
- theErr = AddSpecElement(&theSpec, &gSpecElementP);
- }
- }
- }
-
- // Clean up and return error result.
- AEDisposeDesc(&theAEDescList);
- return theErr;
- }
-
- /* Add one FSSpec as an alias to an AEDescList at position "index".
- To add at end, pass index = 0.
- */
- OSErr AddFSSToAEList
- (AEDescList *aeDescListP, // <->becomes direct object of event
- short index, // 0 means add at end
- FSSpec *fsspecFileP // ->the document spec to add
- )
- {
- AliasHandle hAliasFile;
- OSErr theErr = noErr;
-
- // create alias handle & insert into AEDescList
- theErr = NewAlias(NULL, fsspecFileP, &hAliasFile);
- if (theErr == noErr)
- {
- HLock( (Handle) hAliasFile );
- theErr = AEPutPtr(aeDescListP, index, typeAlias,
- *hAliasFile, (*hAliasFile)->aliasSize);
- DisposeHandle( (Handle)hAliasFile );
- }
- return theErr;
- }
-
-
- // Process handling
-
- /* This runs through the process list looking for the indicated thing,
- based on type and creator.
- */
- OSErr FindAProcess
- (OSType typeToFind, // eg 'APPL' or 'FNDR'
- OSType creatorToFind, // eg 'JAGO' or 'MACS'
- ProcessSerialNumberPtr processSN // <- PSN of process
- )
- {
- ProcessInfoRec tempInfo; // to check type/creator
- FSSpec procSpec; // value not used
- Str31 processName; // value not used
- OSErr theErr = noErr;
-
- // nul out the PSN so we're starting at the beginning of the list
- processSN->lowLongOfPSN = kNoProcess;
- processSN->highLongOfPSN = kNoProcess;
- // initialize the process information record
- tempInfo.processInfoLength = sizeof(ProcessInfoRec);
- tempInfo.processName = processName;
- tempInfo.processAppSpec = &procSpec;
-
- // loop through all the processes until we
- // 1) find the process we want, or
- // 2) error out because of some reason (usually, no more processes)
- // (NOTE this loop, stolen originally i think from THINK Ref, is wrong
- // in many published versions, having "...|| theErr != noErr...".
- do
- {
- theErr = GetNextProcess(processSN);
- if (theErr == noErr)
- GetProcessInformation(processSN, &tempInfo);
- } while ( (tempInfo.processSignature != creatorToFind
- || tempInfo.processType != typeToFind)
- && theErr == noErr);
- return theErr;
- }
-
-
- // File handling
-
- /* Retrieve indexed string from STR# resource.
- */
- static void GetErrorMessage
- (StringPtr messageP, // Str255 for ParamText
- ErrorIndex theErrorMessageIndex // into a STR# rsrc
- )
- {
- GetIndString(messageP, kErrorStringID, (short)theErrorMessageIndex);
- }
-
- /* Retrieve indexed string from STR# resource.
- */
- static void GetGeneralMessage
- (StringPtr messageP, // Str255 for ParamText
- GeneralIndex theGeneralMessageIndex // into a STR# rsrc
- )
- {
- GetIndString(messageP, kGeneralStringID, (short)theGeneralMessageIndex);
- }
-
- /* Locate file (app) based on type, creator. If found, fill in the spec. Borrowed
- with changes from Paul Celestin's InterLaunch (check the "Apprentice 4" CD from
- Celestin Co.).
- */
- OSErr LocateFileByTypeCreator
- (OSType fdType, // eg 'APPL'
- OSType fdCreator, // eg 'JAGO'
- short vRefNum, // 0 for default drive
- FSSpec *spec // <- file spec
- )
- {
- CSParam cs; // for PBCatSearch
- HFileInfo spec1; // start criteria for PBCatSearch
- HFileInfo spec2; // stop criteria for PBCatSearch
- Ptr buffer; // to speed things up, optional
- OSErr theErr;
-
- // Use buffer for speed, but proceed if memory not available.
- buffer = NewPtr(16384L);
- if (MemError() != noErr)
- buffer = NewPtr(8192L);
- if (MemError() != noErr)
- buffer = NULL;
-
- cs.ioNamePtr = NULL; // name of volume, we don't need it
- cs.ioVRefNum = vRefNum; // volume number
- cs.ioMatchPtr = spec; // spec for first match (if any)
- cs.ioReqMatchCount = 1; // we want at most one spec
- cs.ioSearchBits = fsSBFlFndrInfo; // We are searching for Finder info
- cs.ioSearchInfo1 = (CInfoPBPtr)&spec1;
- cs.ioSearchInfo2 = (CInfoPBPtr)&spec2;
- cs.ioSearchTime = 0; // no timeout on search
- cs.ioCatPosition.initialize = 0; // start at beginning of catalog
- // Use the buffer if we have one.
- cs.ioOptBuffer = buffer;
- if (buffer != NULL)
- cs.ioOptBufSize = GetPtrSize(buffer);
- else
- cs.ioOptBufSize = 0;
-
- // Set values and lower bounds in spec1
- spec1.ioFlFndrInfo.fdType = fdType;
- spec1.ioFlFndrInfo.fdCreator = fdCreator;
- spec1.ioFlFndrInfo.fdFlags = 0;
- *(long *)&spec1.ioFlFndrInfo.fdLocation = 0L;
- spec1.ioFlFndrInfo.fdFldr = 0;
-
- // Set masks and upper bounds in spec2
- spec2.ioFlFndrInfo.fdType = (ResType)0xffffffff; // match type
- spec2.ioFlFndrInfo.fdCreator = (ResType)0xffffffff; // match creator
- spec2.ioFlFndrInfo.fdFlags = 0x4000; // require file to be visible
- *(long *)&spec2.ioFlFndrInfo.fdLocation = 0; // ignore icon position
- spec2.ioFlFndrInfo.fdFldr = 0; // obsolete field, ignore
-
- // Whew, do the actual search...result if any goes in "spec"
- theErr = PBCatSearch(&cs,FALSE);
- // Clean up and return result
- if (buffer != NULL)
- DisposePtr(buffer);
- return theErr;
- }
-
- /* Launch an application, without files, using preferred size.
- */
- OSErr LaunchIt
- (FSSpec *theAppP, // ->Specs which application to launch
- ProcessSerialNumber *serialNumP // <-filled in if we succeed
- )
- {
- LaunchParamBlockRec launchParams; // See Processes.h
- OSErr theErr = noErr;
-
- launchParams.launchBlockID = extendedBlock;
- launchParams.launchEPBLength = extendedBlockLen;
- launchParams.launchFileFlags = 0; // ignored due to launchNoFileFlags below
- launchParams.launchControlFlags = launchContinue + launchNoFileFlags;
- launchParams.launchAppSpec = theAppP;
- launchParams.launchAppParameters = NULL; // no high-level event
-
- // Launch app without docs, using preferred size.
- theErr = LaunchApplication(&launchParams);
-
- // Set serial number of running process if we succeeded.
- if (theErr == noErr)
- *serialNumP = launchParams.launchProcessSN;
- return theErr;
- }
-
-
- /* Make new FSSpecElement, fill in and add to tail of *specElementPP list.
- *specElementPP->secondInList->...currentLastInList->newElement->NULL.
- Error only if out of memory.
- */
- static OSErr AddSpecElement
- (FSSpecPtr theSpecP, // ->a document file spec
- FSSpecElementPtr *specElementPP // <->head of spec list or NULL first time
- )
- {
- FSSpecElementPtr lastElemP; // last element in current list
- FSSpecElementPtr newElemP; // created here
- OSErr theErr = noErr;
-
- // Make a new element for the linked list
- newElemP = (FSSpecElementPtr)NewPtr( sizeof(FSSpecElement) );
- theErr = MemError();
-
- // Add it to the list (set *specElementPP if it's the first one).
- if (theErr == noErr)
- {
- // Fill in the values for the new element, add to end of list.
- newElemP->fss = *theSpecP;
- newElemP->next = NULL;
- // First one is special, goes in *specElementPP.
- if (*specElementPP == NULL)
- {
- *specElementPP = newElemP;
- }
- else
- {
- // Walk list and add new one at end.
- lastElemP = *specElementPP;
- while (lastElemP->next != NULL)
- lastElemP = lastElemP->next;
- lastElemP->next = newElemP;
- }
- }
- return theErr;
- }
-
-