filelaunch.c

Go to the documentation of this file.
00001 
00002 /*  $Id: filelaunch.c 1214 2006-04-06 01:43:43Z karstenw $    */
00003 
00004 /******************************************************************************
00005 
00006     UserLand Frontier(tm) -- High performance Web content management,
00007     object database, system-level and Internet scripting environment,
00008     including source code editing and debugging.
00009 
00010     Copyright (C) 1992-2004 UserLand Software, Inc.
00011 
00012     This program is free software; you can redistribute it and/or modify
00013     it under the terms of the GNU General Public License as published by
00014     the Free Software Foundation; either version 2 of the License, or
00015     (at your option) any later version.
00016 
00017     This program is distributed in the hope that it will be useful,
00018     but WITHOUT ANY WARRANTY; without even the implied warranty of
00019     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020     GNU General Public License for more details.
00021 
00022     You should have received a copy of the GNU General Public License
00023     along with this program; if not, write to the Free Software
00024     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00025 
00026 ******************************************************************************/
00027 
00028 #include "frontier.h"
00029 #include "standard.h"
00030 
00031 #include "file.h"
00032 #include "filesystem7.h"
00033 #include "ops.h"
00034 
00035 
00036 
00037 #define kAEFinderEvents 'FNDR'
00038 #define kAEShowClipboard 'shcl'
00039 #define kAEPutAway 'sput'
00040 #define keyAEFinderSelection 'fsel'
00041 #define kAEDrag 'drag'
00042 #define keyAEFinderMisc 'fmsc'
00043 #define kAEEmptyTrash 'empt'
00044 #define kAEOpenSelection 'sope'
00045 #define kAEPrintSelection 'spri'
00046 
00047 #if TARGET_API_MAC_CARBON == 1
00048 #else
00049 static ProcessSerialNumber FinderNumber;
00050 //Code change by Timothy Paustian Wednesday, June 21, 2000 4:04:43 PM
00051 //in Carbon you have to use high level apple events. Since what we are trying 
00052 //to do is launch an application, lets try that.
00053 static OSErr GetFinderPort(void) {
00054         
00055     IPCListPortsPBRec ipc;
00056     PPCPortRec port;
00057     LocationNameRec where;
00058     short i;
00059     short err;
00060     long first4;
00061     PortInfoRec FinderPort;
00062 
00063     if (FinderNumber.lowLongOfPSN || FinderNumber.highLongOfPSN) {
00064         err = GetPortNameFromProcessSerialNumber(&FinderPort.name, &FinderNumber);
00065         if (err == noErr) return noErr;
00066     };
00067 
00068     for (i = 0; ; i++) {
00069         ipc.ioCompletion = 0;
00070         ipc.startIndex = i;
00071         ipc.requestCount = 1;
00072         ipc.portName = &port;
00073             port.nameScript = 0;    
00074             port.name[0] = 1;
00075             port.name[1] = '=';
00076             port.portKindSelector = ppcByString;
00077             port.u.portTypeStr[0] = 1;
00078             port.u.portTypeStr[1] = '=';
00079         ipc.locationName = &where;
00080             where.locationKindSelector = ppcNoLocation;
00081         ipc.bufferPtr = &FinderPort;
00082         
00083         err = IPCListPortsSync(&ipc);
00084         if (err != noErr) return err;
00085         if (ipc.actualCount != 1) return -1;
00086         BlockMove(&FinderPort.name.u.portTypeStr[1], &first4, 4);
00087         if (first4 != 'MACS') continue;
00088         GetProcessSerialNumberFromPortName(&FinderPort.name, &FinderNumber);
00089         return 0;
00090     };
00091         
00092 }
00093 #endif
00094 
00095 /*
00096 the MFDispatch calls are only needed if you want to make the request
00097 anonymously.  Normally you don't have to do this.  I do it because I
00098 don't want the Finder sending replies back to the frontmost app.
00099 */
00100 
00101 pascal short MFDispatch(short number) ONEWORDINLINE (0xA88F);
00102 
00103 short System7Open (FSSpec fs2) {
00104 
00105     /*
00106     3/12/92 dmb: commented out MFDispatch calls, seeking A/UX compatibility
00107 
00108     6/1/92 dmb: added return (err) at end of function
00109 
00110     8/20/92 dmb: special case for a/ux
00111     */
00112 
00113     #if TARGET_API_MAC_CARBON == 1
00114     //Code change by Timothy Paustian Wednesday, June 21, 2000 4:06:47 PM
00115     //Maybe I'm nuts, but I think I can do this very easily.
00116     //2/25/2001 Tim P No I can't this needs to be an apple event
00117     //I need to send an apple event to have the thing opened
00118     //The below code works. It is a total rip off of the example code in apples
00119     //Finder launch example. http://developer.apple.com/samplecode/Sample_Code/Interapplication_Comm/FinderLaunch.htm
00120     //I have pretty much left it as is. We could clean it up by not creating a targetList, But
00121     //I am leaving the ability in there in case it's wante later
00122     OSErr err;
00123     AppleEvent theAEvent, theReply;
00124     AEAddressDesc fndrAddress;
00125     AEDescList targetListDesc;
00126     OSType fndrCreator;
00127     Boolean wasChanged;
00128     AliasHandle targetAlias;
00129     long idx;   // 2006-04-03 - kw --- renamed
00130     long nTargets = 1;
00131     FSSpec  targets[1];
00132     FSSpec  *targetList;
00133     targets[0] = fs2;
00134     targetList = targets;
00135 
00136     /* verify parameters */
00137     if (    (nTargets == 0)
00138          || (targetList == NULL))
00139     {
00140         return paramErr;
00141     }
00142 
00143         /* set up locals  */
00144     AECreateDesc(typeNull, NULL, 0, &theAEvent);
00145     AECreateDesc(typeNull, NULL, 0, &fndrAddress);
00146     AECreateDesc(typeNull, NULL, 0, &theReply);
00147     AECreateDesc(typeNull, NULL, 0, &targetListDesc);
00148     targetAlias = NULL;
00149     fndrCreator = 'MACS';
00150 
00151         /* create an open documents event targeting the finder */
00152     err = AECreateDesc(typeApplSignature, (Ptr) &fndrCreator,
00153         sizeof(fndrCreator), &fndrAddress);
00154     if (err != noErr) goto bail;
00155     err = AECreateAppleEvent(kCoreEventClass, kAEOpenDocuments,
00156         &fndrAddress, kAutoGenerateReturnID,
00157         kAnyTransactionID, &theAEvent);
00158     if (err != noErr) goto bail;
00159 
00160         /* create the list of files to open */
00161     err = AECreateList(NULL, 0, false, &targetListDesc);
00162     if (err != noErr) goto bail;
00163     for ( idx = 0; idx < nTargets; idx++) {
00164         if (targetAlias == NULL)
00165             err = NewAlias(NULL, (targetList + idx), &targetAlias);
00166         else err = UpdateAlias(NULL, (targetList + idx), targetAlias, &wasChanged);
00167         if (err != noErr) goto bail;
00168         HLock((Handle) targetAlias);
00169         err = AEPutPtr(&targetListDesc, (idx + 1), typeAlias, *targetAlias, GetHandleSize((Handle) targetAlias));
00170         HUnlock((Handle) targetAlias);
00171         if (err != noErr) goto bail;
00172     }
00173 
00174         /* add the file list to the apple event */
00175     err = AEPutParamDesc(&theAEvent, keyDirectObject, &targetListDesc);
00176     if (err != noErr) goto bail;
00177 
00178         /* send the event to the Finder */
00179     err = AESend(&theAEvent, &theReply, kAENoReply,
00180         kAENormalPriority, kAEDefaultTimeout, NULL, NULL);
00181 
00182         /* clean up and leave */
00183 bail:
00184     if (targetAlias != NULL) DisposeHandle((Handle) targetAlias);
00185     AEDisposeDesc(&targetListDesc);
00186     AEDisposeDesc(&theAEvent);
00187     AEDisposeDesc(&fndrAddress);
00188     AEDisposeDesc(&theReply);
00189     return err;
00190     
00191     #else
00192             
00193     static EventRecord er;
00194     short err;
00195     AliasHandle a1 = 0, a2 = 0;
00196     long hs1, hs2;
00197     FSSpec fs1;
00198     Handle message;
00199     CInfoPBRec  pb;
00200     long version;
00201     
00202     err = GetFinderPort();
00203     
00204     if (err != noErr)
00205         return err;
00206     
00207     /*
00208     err = FSMakeFSSpec(vRefNum, dirID, name, &fs2);         
00209     if (err != noErr)
00210         return err;
00211     */
00212     
00213     /* get some catalog information, which we will use later. */
00214     pb.dirInfo.ioCompletion=0;
00215     pb.dirInfo.ioNamePtr = fs2.name;
00216     pb.dirInfo.ioVRefNum = fs2.vRefNum;
00217     pb.dirInfo.ioFDirIndex = 0;
00218     pb.dirInfo.ioDrDirID = fs2.parID;
00219     
00220     err = PBGetCatInfoSync(&pb);
00221     
00222     if (err != noErr)
00223         return err;
00224     
00225     err = NewAliasMinimal(&fs2, &a2);
00226     
00227     if (err != noErr)
00228         return err;
00229     
00230     fs1 = fs2;
00231     
00232     if (gestalt (gestaltAUXVersion, &version)) { /*running under A/UX; cover bugs*/
00233         
00234         if (fs1.parID == 1) { /*it's a volume*/
00235             
00236             fs1.vRefNum = -1; /*a/ux wants to see the root as the parent*/
00237             }
00238         else { /*not a volume: path parsing works better under a/ux*/
00239             
00240             bigstring path;
00241             
00242             if (!filespectopath (&fs1, path))
00243                 return (false);
00244             
00245             folderfrompath (path, path);
00246             
00247             if (!pathtofilespec (path, &fs1))
00248                 return (false);
00249             
00250             goto gotfs1;
00251             }
00252         }
00253     else {
00254         
00255         if (fs1.parID == 1) { /*it's a volume*/
00256             
00257             err = FindFolder(fs1.vRefNum, kDesktopFolderType, false, &fs1.vRefNum, &fs1.parID);
00258             
00259             if (err != noErr)
00260                 return err;
00261             }
00262         }
00263     
00264     err = FSMakeFSSpec(fs1.vRefNum, fs1.parID, "\p", &fs1);
00265     
00266     if (err != noErr)
00267         return err;
00268     
00269     gotfs1:
00270     
00271     err = NewAliasMinimal(&fs1, &a1);
00272     
00273     if (err != noErr)
00274         return err;
00275     
00276     hs1 = GetHandleSize((Handle) a1);
00277     hs2 = GetHandleSize((Handle) a2);
00278     
00279     MoveHHi((Handle) a1); HLock((Handle) a1);
00280     MoveHHi((Handle) a2); HLock((Handle) a2);
00281     
00282     er.what = kHighLevelEvent;              /* PHLE fills this in, but we do it just to be clear. */
00283     er.message = kAEFinderEvents;           /* this is the event class */
00284     *(long *)&er.where = kAEOpenSelection;  /* this is the event type - see Card 131 */
00285     er.when = TickCount();                  /* this also gets filled in, but... */
00286     er.modifiers = 0;                       /* doesn't matter */
00287     
00288     message = NewHandle (24 + hs1 + 28 + hs2);
00289     
00290     /*
00291     normally you'd use Apple Events manager calls to pack up a message and
00292     send it.  I do things this way only because I can't be sure the frontmost
00293     app has initialized that manager.
00294     */
00295     
00296     if (message) {
00297         register long *filler = (void *)*message;
00298         
00299         *filler++ = 'aevt';
00300         *filler++ = 0x00010001;
00301         *filler++ = ';;;;';
00302         *filler++ = '----';
00303         *filler++ = 'alis';
00304         *filler++ = hs1;
00305         BlockMove(*a1, filler, hs1); filler = (long *)(hs1 + (long) filler);
00306         *filler++ = 'fsel';
00307         *filler++ = 'list';
00308         *filler++ = hs2 + 16;
00309         *filler++ = 1;
00310         *filler++ = 0;
00311         *filler++ = 'alis';
00312         *filler++ = hs2;
00313         BlockMove(*a2, filler, hs2);
00314         };
00315     
00316     DisposeHandle((Handle) a1);
00317     DisposeHandle((Handle) a2);
00318     
00319     if (!message)
00320         return (memFullErr);
00321     
00322     /*
00323     MFDispatch(0x40);
00324     */
00325     HLock(message);
00326     
00327     err = PostHighLevelEvent(&er, &FinderNumber, 237,
00328                              *message, GetHandleSize(message),
00329                              receiverIDisPSN);
00330     
00331     /*
00332     MFDispatch(0x41);
00333     */
00334     
00335     if ((pb.dirInfo.ioFlAttrib & ioDirMask) || pb.hFileInfo.ioFlFndrInfo.fdType == 'cdev') {
00336         SetFrontProcess(&FinderNumber);
00337         };
00338     
00339     DisposeHandle(message);
00340     #endif
00341         
00342     
00343     return (err);
00344     } /*System7Open*/
00345     

Generated on Wed May 31 18:19:46 2006 for frontierkernel 10.1.10a by  doxygen 1.4.6