home *** CD-ROM | disk | FTP | other *** search
- /* FindBrowser.c
- * Look for and launch a Web browser that supports the GetURL event
- * Copyright ©1996 Michael D. Crawford. All Rights Reserved.
- * You may use this code on the condition that you read the following web page:
- * http://www.scruznet.com/~crawford/WordServices/wdsvindex.html
- * 1 Jul 96 Mike Crawford crawford@scruznet.com
- */
-
- #include "FindBrowser.h"
- #include "FindProcess.h"
-
- OSErr LookForProcess( OSType creator, Boolean *gotItPtr );
- OSErr LaunchTheApp( FSSpecPtr specPtr );
- OSErr SearchVolForBrowser( short vRef,
- Boolean *gotItPtr,
- OSType **creators,
- short numCreators,
- FSSpecPtr specPtr,
- OSType *creatorPtr );
-
- OSErr FindBrowser( OSType *creatorPtr )
- {
- OSType **creators;
- OSErr err;
- short i;
- short numCreators;
- Boolean gotIt;
- ProcessSerialNumber psn;
- ProcessInfoRec pInfo;
- FSSpec fSpec;
- Str255 procName;
- VolumeParam vPB;
-
- *creatorPtr = 'null';
-
- creators = (OSType**)GetResource( 'Cr8r', 128 );
- if ( !creators )
- return resNotFound;
-
- numCreators = GetHandleSize( (Handle)creators ) / sizeof( OSType );
-
- // Search the running processes for one we know about
-
- for ( i = 0; i < numCreators; i++ ){
- gotIt = FindAProcess( (*creators)[ i ],
- &psn,
- &pInfo,
- &fSpec,
- procName );
- if ( gotIt ){
- *creatorPtr = (*creators)[ i ];
- return noErr;
- }
- }
-
- vPB.ioCompletion = (IOCompletionUPP)NULL;
- vPB.ioVolIndex = 1;
- vPB.ioNamePtr = (StringPtr)NULL;
-
- do {
- err = PBGetVInfoSync( (ParamBlockRec*)&vPB );
- if ( err == nsvErr )
- return noErr; // Out of volumes to search, haven't found any browsers
- if ( err )
- return err;
-
- err = SearchVolForBrowser( vPB.ioVRefNum,
- &gotIt,
- creators,
- numCreators,
- &fSpec,
- creatorPtr );
- if ( gotIt ){
- err = LaunchTheApp( &fSpec );
- return err;
-
- }
-
- vPB.ioVolIndex++;
- }while( !err && !gotIt );
-
- return noErr;
- }
-
- OSErr SearchVolForBrowser( short vRef,
- Boolean *gotItPtr,
- OSType **creators,
- short numCreators,
- FSSpecPtr specPtr,
- OSType *creatorPtr )
- {
- short i;
- DTPBRec dPB;
- short refNum;
- Str255 name;
- FInfo fndrInfo;
- OSErr err;
-
- *gotItPtr = false;
-
- dPB.ioNamePtr = (StringPtr)NULL;
- dPB.ioVRefNum = vRef;
-
- err = PBDTGetPath( &dPB );
- if ( err )
- return err;
-
- refNum = dPB.ioDTRefNum;
-
- dPB.ioCompletion = (IOCompletionUPP)NULL;
- dPB.ioNamePtr = name;
-
- for ( i = 0; i < numCreators; i++ ){
- dPB.ioFileCreator = (*creators)[ i ];
-
- dPB.ioIndex = 1;
-
- do{
- err = PBDTGetAPPL( &dPB, false );
- if ( err == afpItemNotFound )
- break;
- if ( err )
- return err;
-
- // We got the application info, but it is possible that the application
- // has been deleted without the desktop file being updated. Check to
- // see that the file is still there.
-
- err = HGetFInfo( vRef, dPB.ioAPPLParID, name, &fndrInfo );
- if ( !err ){
- err = FSMakeFSSpec( vRef, dPB.ioAPPLParID, name, specPtr );
- if ( err )
- return err;
-
- *creatorPtr = dPB.ioFileCreator;
-
- *gotItPtr = true;
- return noErr;
- }
- }while( !err );
- }
-
- return noErr;
- }
-
- OSErr LaunchTheApp( FSSpecPtr specPtr )
- {
- OSErr err;
- Boolean changed;
- AppleEvent launchEvent;
- AppleEvent replyEvent;
- AEDesc aliasDesc;
- AEDesc folderDesc;
- FSSpec folderSpec;
- AEDesc finderAddr;
- DescType finderSig;
- AliasHandle fAliasHdl;
- AliasHandle appAliasHdl;
- AEDescList aliasList;
-
- // Launch the browser by sending an Open Selection apple event to the Finder.
- // We need to do this so that the process shows up in the application menu, so that
- // we see zoomrects on launch, and so that the application's icon is dimmed in its
- // Finder window
-
- // Taken from Writeswell Jr.'s LaunchSpeller in DoChecking.c
-
-
- /* make an alias for the parent folder */
-
- err = FSMakeFSSpec( specPtr->vRefNum,
- specPtr->parID,
- (StringPtr)NULL,
- &folderSpec );
- if ( err ){
- return err;
- }
-
- err = NewAlias( (FSSpecPtr)NULL, &folderSpec, &fAliasHdl );
- if ( err ){
- return err;
- }
-
- /* Create the event to send to the Finder */
-
- finderSig = 'MACS'; /* Creator code of finder; type is 'FNDR' */
- err = AECreateDesc( typeApplSignature,
- (Ptr)&finderSig,
- sizeof( finderSig ),
- &finderAddr );
- if ( err ){
- return err;
- }
-
- err = AECreateAppleEvent( kAEFinderEvents,
- kAEOpenSelection,
- &finderAddr,
- kAutoGenerateReturnID,
- kAnyTransactionID,
- &launchEvent );
-
- if ( err ){
- return err;
- }
- err = AEDisposeDesc( &finderAddr );
- if ( err ){
- return err;
- }
-
- /* Insert the folder alias record as the direct object of the batch event */
-
- /* First make a descriptor of the alias */
- HLock( (Handle) fAliasHdl );
-
- err = AECreateDesc( typeAlias,
- (Ptr)*fAliasHdl,
- (*fAliasHdl)->aliasSize,
- &folderDesc );
-
- HUnlock( (Handle) fAliasHdl );
- DisposHandle( (Handle) fAliasHdl );
-
- if ( err ){
- return err;
- }
-
- err = AEPutParamDesc( &launchEvent,
- keyDirectObject,
- &folderDesc );
- if ( err ){
- return err;
- }
- err = AEDisposeDesc( &folderDesc );
- if ( err ){
- return err;
- }
-
- /* Put the application alias on the event */
- err = NewAlias( (FSSpecPtr)NULL, specPtr, &appAliasHdl );
- if ( err ){
- return err;
- }
-
- HLock( (Handle) appAliasHdl );
-
- err = AECreateDesc( typeAlias,
- (Ptr)*appAliasHdl,
- (*appAliasHdl)->aliasSize,
- &aliasDesc );
-
- HUnlock( (Handle) appAliasHdl );
- DisposeHandle( (Handle)appAliasHdl );
-
- if ( err ){
- return err;
- }
-
- /* Now make a list of the alias descriptor. There is only one element in this
- * list
- */
-
- err = AECreateList( (Ptr)NULL, (Size)0, false, &aliasList );
-
- if ( err ){
- return err;
- }
-
- err = AEPutDesc( &aliasList, 1L, &aliasDesc );
-
- if ( err ){
- return err;
- }
-
- err = AEDisposeDesc( &aliasDesc );
- if ( err ){
- return err;
- }
-
- err = AEPutParamDesc( &launchEvent,
- keySelection,
- &aliasList );
- if ( err ){
- return err;
- }
-
- err = AEDisposeDesc( &aliasList );
- if ( err ){
- return err;
- }
-
- err = AESend( &launchEvent,
- &replyEvent,
- kAEWaitReply + kAECanInteract, /* Don't allow later switch */
- kAENormalPriority,
- 1800, // Thirty seconds; browser can take a long time to initialize
- (AEIdleUPP)NULL,
- (AEFilterUPP)NULL );
-
- if ( err ){
- return err;
- }
- err = AEDisposeDesc( &launchEvent );
- if ( err ){
- return err;
- }
-
- err = AEDisposeDesc( &replyEvent );
- if ( err ){
- return err;
- }
-
- return noErr;
- }
-