home *** CD-ROM | disk | FTP | other *** search
- /* ========== the commmand file: ==========
-
- launch.c
-
- Copyright (c) 1993,1994 Newport Software Development
-
- You may distribute unmodified copies of this file for
- noncommercial purposes. You may use this file as a
- reference when writing your own nShell(tm) commands.
-
- All other rights are reserved.
-
- ========== the commmand file: ========== */
-
- #include <Aliases.h>
- #include <appleevents.h>
- #include <GestaltEqu.h>
- #include <processes.h>
-
- #include "nshc.h"
-
- #include "arg_utl.proto.h"
- #include "fss_utl.proto.h"
- #include "nshc_utl.proto.h"
- #include "str_utl.proto.h"
-
- /* ======================================== */
-
- // prototypes
-
- int Pre7( void );
- int is_it_running( OSType targetSignature );
- int launch( int gotFSSpec, FSSpec *launchApp, FSSpec *launchDoc, t_nshc_calls *nshc_calls );
- OSErr odoc( int gotFSSpec, FSSpec *doc_fss, OSType app_sig, t_nshc_calls *nshc_calls );
-
- /* ======================================== */
-
- // return true if 'sysv' is previous to 7.0
-
- int Pre7( void )
- {
- OSErr error;
- long response;
-
- if ( error = Gestalt( 'sysv', &response ) )
- return(true);
-
- if ( response < 0x700 )
- return(true);
- else
- return(false);
- }
-
- /* ======================================== */
-
- int is_it_running( OSType targetSignature )
- {
- Str255 name;
- ProcessSerialNumber psn_p;
- ProcessInfoRec pi;
-
- pi.processName = name;
- pi.processInfoLength = sizeof(pi);
- pi.processAppSpec = NULL;
-
- psn_p.highLongOfPSN = 0;
- psn_p.lowLongOfPSN = kNoProcess;
-
- while(!GetNextProcess(&psn_p))
- if(!GetProcessInformation(&psn_p,&pi))
- if ( pi.processSignature == targetSignature )
- return( 1 );
-
- return( 0 );
- }
-
- /* ======================================== */
-
- int launch( int gotFSSpec, FSSpec *launchApp, FSSpec *launchDoc, t_nshc_calls *nshc_calls )
- {
- AEDesc docDesc;
- AEDesc parmDesc;
- AEDesc adrDesc;
- AEDescList docList;
- AliasHandle docAlias;
- AppleEvent fakeEvent;
- AppParametersPtr docParm;
- LaunchParamBlockRec launchThis;
- OSErr myErr;
- ProcessSerialNumber myPSN;
-
- // initialize
-
- docDesc.dataHandle = nil;
- parmDesc.dataHandle = nil;
- adrDesc.dataHandle = nil;
- docList.dataHandle = nil;
- docAlias = nil;
- fakeEvent.dataHandle = nil;
-
- GetCurrentProcess(&myPSN); // used to initialize new AE things
-
- // create the address desc for the event
-
- myErr = AECreateDesc(typeProcessSerialNumber, (Ptr)&myPSN, sizeof(ProcessSerialNumber), &adrDesc);
- if (myErr) goto Cleanup;
-
- // stuff it in my launch parameter block
-
- launchThis.launchAppSpec = launchApp;
-
- if (launchDoc) {
-
- // create an apple event for "open doc"
- myErr = AECreateAppleEvent(kCoreEventClass, kAEOpenDocuments, &adrDesc, kAutoGenerateReturnID, kAnyTransactionID, &fakeEvent);
- if (myErr) goto Cleanup;
-
- // create a list to hold the doc alias
- myErr = AECreateList(nil, 0, false, &docList);
- if (myErr) goto Cleanup;
-
- // ae needs an alias to the doc
- myErr = NewAlias(nil, launchDoc, &docAlias);
- if (myErr) goto Cleanup;
-
- // and a descriptor for the alias
- HLock((Handle)docAlias);
- myErr = AECreateDesc(typeAlias, (Ptr)*docAlias, GetHandleSize((Handle)docAlias), &docDesc);
- HUnlock((Handle)docAlias);
- if (myErr) goto Cleanup;
-
- // the descriptor goes in the list
- myErr = AEPutDesc(&docList, 0, &docDesc);
- if (myErr) goto Cleanup;
-
- // and the list goes into the event
- myErr = AEPutParamDesc(&fakeEvent, keyDirectObject, &docList);
- if (myErr) goto Cleanup;
-
- // but the fake event is REALLY a parameter!
- myErr = AECoerceDesc(&fakeEvent, typeAppParameters, &parmDesc);
- if (myErr) goto Cleanup;
-
- docParm = (AppParametersPtr)*(parmDesc.dataHandle);
- }
- else
- docParm = nil;
-
- // stuff the LaunchParamBlockRec and send it
-
- HLock((Handle)fakeEvent.dataHandle);
-
- launchThis.launchAppParameters = docParm;
- launchThis.launchBlockID = extendedBlock;
- launchThis.launchEPBLength = extendedBlockLen;
- launchThis.launchFileFlags = 0;
- launchThis.launchControlFlags = launchContinue + launchNoFileFlags;
-
- myErr = LaunchApplication(&launchThis);
-
- HUnlock((Handle)fakeEvent.dataHandle);
-
- Cleanup:
-
- if (myErr) nshc_calls->NSH_putStr_err("\plaunch: Message could not be sent.\r");
-
- if ( docDesc.dataHandle ) AEDisposeDesc(&docDesc);
- if ( parmDesc.dataHandle ) AEDisposeDesc(&parmDesc);
- if ( adrDesc.dataHandle ) AEDisposeDesc(&adrDesc);
- if ( docList.dataHandle ) AEDisposeDesc(&docDesc);
- if ( fakeEvent.dataHandle )AEDisposeDesc(&fakeEvent);
-
- if ( docAlias ) DisposeHandle((Handle)docAlias);
-
- return(myErr);
- }
-
- /* ======================================== */
-
- OSErr odoc( int gotFSSpec, FSSpec *doc_fss, OSType app_sig, t_nshc_calls *nshc_calls )
- {
- OSErr myErr;
- FInfo finfo;
- int appRunning;
- AEDesc appDesc;
- AliasHandle docAlias;
- AppleEvent openAE;
- AppleEvent replyAE;
- AEDescList docList;
-
- // initialize
-
- openAE.dataHandle = nil;
- replyAE.dataHandle = nil;
- appDesc.dataHandle = nil;
- docList.dataHandle = nil;
-
- docAlias = nil;
-
- // see if the app is running
-
- appRunning = is_it_running( app_sig );
-
- if (!appRunning) {
- nshc_calls->NSH_putStr_err("\podoc: Target process is not running\r");
- return(1);
- }
-
- myErr = AECreateDesc(typeApplSignature,
- (Ptr)&app_sig,
- sizeof(app_sig),
- &appDesc);
- if (myErr) goto Cleanup;
-
- myErr = NewAlias(nil,doc_fss,&docAlias);
- if (myErr) goto Cleanup;
-
- myErr = AECreateAppleEvent(kCoreEventClass,
- kAEOpenDocuments,
- &appDesc,
- kAutoGenerateReturnID,
- kAnyTransactionID,
- &openAE);
- if (myErr) goto Cleanup;
-
- myErr = AECreateList(nil,0,false,&docList);
- if (myErr) goto Cleanup;
-
- HLock(docAlias);
- myErr = AEPutPtr(&docList,
- 0,
- typeAlias,
- (Ptr)*docAlias,
- sizeof(AliasHandle)+(**docAlias).aliasSize);
- HUnlock(docAlias);
- if (myErr) goto Cleanup;
-
- myErr = AEPutParamDesc(&openAE,keyDirectObject,&docList);
- if (myErr) goto Cleanup;
-
- myErr = AESend(&openAE,&replyAE,kAENoReply,kAENormalPriority,kAEDefaultTimeout,nil,nil);
-
- Cleanup:
-
- if (myErr) nshc_calls->NSH_putStr_err("\podoc: Message could not be sent.\r");
-
- if (docList.dataHandle) AEDisposeDesc(&docList);
- if (openAE.dataHandle) AEDisposeDesc(&openAE);
- if (replyAE.dataHandle) AEDisposeDesc(&replyAE);
- if (appDesc.dataHandle) AEDisposeDesc(&appDesc);
-
- if (docAlias) DisposHandle(docAlias);
-
- return(myErr);
- }
-
- /* ======================================== */
-
- void main(t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls)
- {
- FInfo finfo;
- FSSpec app_fss;
- FSSpec doc_fss;
- int gotFSSpec;
- int result;
-
- nshc_parms->action = nsh_idle; // always one pass to this command
- gotFSSpec = fss_test(); // find out if fss is there
-
- // *** reason not to run 1 - bad included version
-
- if (nshc_bad_version( nshc_parms, nshc_calls, NSHC_VERSION )) return;
-
- // *** reason not to run 2 - bad os version
-
- if ( Pre7() ) {
- nshc_calls->NSH_putStr_err("\plaunch: This command requires System 7.\r");
- nshc_parms->result = NSHC_ERR_GENERAL;
- return;
- }
-
- // *** reason not to run 3 - bad parameters
-
- if (( nshc_parms->argc < 2 ) || ( nshc_parms->argc > 3 )) {
- nshc_calls->NSH_putStr_err("\pUsage: launch app_path [doc_path]\r");
- nshc_parms->result = NSHC_ERR_PARMS;
- return;
- }
-
- // *** reason not to run 4 - can't find doc
-
- if ( nshc_parms->argc > 2 ) {
-
- result = arg_to_fss( nshc_parms, nshc_calls, 2, &doc_fss );
-
- if (!result)
- result = fss_GetFInfo( gotFSSpec, &doc_fss, &finfo );
-
- if (result) {
- nshc_calls->NSH_putStr_err("\plaunch: Document not found.\r");
- nshc_parms->result = NSHC_ERR_PARMS;
- return;
- }
-
- }
-
- // *** reason not to run 5 - can't find app
-
- result = arg_to_fss( nshc_parms, nshc_calls, 1, &app_fss );
-
- if (!result)
- result = fss_GetFInfo( gotFSSpec, &app_fss, &finfo );
-
- if (result || (finfo.fdType != 'APPL') ) {
- nshc_calls->NSH_putStr_err("\plaunch: Application not found.\r");
- nshc_parms->result = NSHC_ERR_PARMS;
- return;
- }
-
- // *** finally try to launch the thing
-
- if ( is_it_running( finfo.fdCreator ) ) {
-
- // if it is running but there is no doc ... don't worry
-
- if ( nshc_parms->argc > 2 )
- result = odoc( gotFSSpec, &doc_fss, finfo.fdCreator, nshc_calls );
-
- }
- else {
-
- if ( nshc_parms->argc > 2 )
- result = launch( gotFSSpec, &app_fss, &doc_fss, nshc_calls );
- else
- result = launch( gotFSSpec, &app_fss, nil, nshc_calls );
-
- }
-
- // *** log the result and return
-
- nshc_parms->result = result;
- }
-