Version:
~ [ 10.0 ] ~
** Warning: Cannot open xref database.
1
2 /* $Id: filelaunch.c,v 1.4 2005/01/11 22:48:05 andreradke Exp $ */
3
4 /******************************************************************************
5
6 UserLand Frontier(tm) -- High performance Web content management,
7 object database, system-level and Internet scripting environment,
8 including source code editing and debugging.
9
10 Copyright (C) 1992-2004 UserLand Software, Inc.
11
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
16
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25
26 ******************************************************************************/
27
28 #include "frontier.h"
29 #include "standard.h"
30
31 #include "file.h"
32 #include "filesystem7.h"
33 #include "ops.h"
34
35
36
37 #define kAEFinderEvents 'FNDR'
38 #define kAEShowClipboard 'shcl'
39 #define kAEPutAway 'sput'
40 #define keyAEFinderSelection 'fsel'
41 #define kAEDrag 'drag'
42 #define keyAEFinderMisc 'fmsc'
43 #define kAEEmptyTrash 'empt'
44 #define kAEOpenSelection 'sope'
45 #define kAEPrintSelection 'spri'
46
47 #if TARGET_API_MAC_CARBON == 1
48 #else
49 static ProcessSerialNumber FinderNumber;
50 //Code change by Timothy Paustian Wednesday, June 21, 2000 4:04:43 PM
51 //in Carbon you have to use high level apple events. Since what we are trying
52 //to do is launch an application, lets try that.
53 static OSErr GetFinderPort(void) {
54
55 IPCListPortsPBRec ipc;
56 PPCPortRec port;
57 LocationNameRec where;
58 short i;
59 short err;
60 long first4;
61 PortInfoRec FinderPort;
62
63 if (FinderNumber.lowLongOfPSN || FinderNumber.highLongOfPSN) {
64 err = GetPortNameFromProcessSerialNumber(&FinderPort.name, &FinderNumber);
65 if (err == noErr) return noErr;
66 };
67
68 for (i = 0; ; i++) {
69 ipc.ioCompletion = 0;
70 ipc.startIndex = i;
71 ipc.requestCount = 1;
72 ipc.portName = &port;
73 port.nameScript = 0;
74 port.name[0] = 1;
75 port.name[1] = '=';
76 port.portKindSelector = ppcByString;
77 port.u.portTypeStr[0] = 1;
78 port.u.portTypeStr[1] = '=';
79 ipc.locationName = &where;
80 where.locationKindSelector = ppcNoLocation;
81 ipc.bufferPtr = &FinderPort;
82
83 err = IPCListPortsSync(&ipc);
84 if (err != noErr) return err;
85 if (ipc.actualCount != 1) return -1;
86 BlockMove(&FinderPort.name.u.portTypeStr[1], &first4, 4);
87 if (first4 != 'MACS') continue;
88 GetProcessSerialNumberFromPortName(&FinderPort.name, &FinderNumber);
89 return 0;
90 };
91
92 }
93 #endif
94
95 /*
96 the MFDispatch calls are only needed if you want to make the request
97 anonymously. Normally you don't have to do this. I do it because I
98 don't want the Finder sending replies back to the frontmost app.
99 */
100
101 pascal short MFDispatch(short number) ONEWORDINLINE (0xA88F);
102
103 short System7Open (FSSpec fs2) {
104
105 /*
106 3/12/92 dmb: commented out MFDispatch calls, seeking A/UX compatibility
107
108 6/1/92 dmb: added return (err) at end of function
109
110 8/20/92 dmb: special case for a/ux
111 */
112
113 #if TARGET_API_MAC_CARBON == 1
114 //Code change by Timothy Paustian Wednesday, June 21, 2000 4:06:47 PM
115 //Maybe I'm nuts, but I think I can do this very easily.
116 //2/25/2001 Tim P No I can't this needs to be an apple event
117 //I need to send an apple event to have the thing opened
118 //The below code works. It is a total rip off of the example code in apples
119 //Finder launch example. http://developer.apple.com/samplecode/Sample_Code/Interapplication_Comm/FinderLaunch.htm
120 //I have pretty much left it as is. We could clean it up by not creating a targetList, But
121 //I am leaving the ability in there in case it's wante later
122 OSErr err;
123 AppleEvent theAEvent, theReply;
124 AEAddressDesc fndrAddress;
125 AEDescList targetListDesc;
126 OSType fndrCreator;
127 Boolean wasChanged;
128 AliasHandle targetAlias;
129 long index;
130 long nTargets = 1;
131 FSSpec targets[1];
132 FSSpec *targetList;
133 targets[0] = fs2;
134 targetList = targets;
135 /* verify parameters */
136 if ((nTargets == 0) || (targetList == NULL)) return paramErr;
137
138 /* set up locals */
139 AECreateDesc(typeNull, NULL, 0, &theAEvent);
140 AECreateDesc(typeNull, NULL, 0, &fndrAddress);
141 AECreateDesc(typeNull, NULL, 0, &theReply);
142 AECreateDesc(typeNull, NULL, 0, &targetListDesc);
143 targetAlias = NULL;
144 fndrCreator = 'MACS';
145
146 /* create an open documents event targeting the finder */
147 err = AECreateDesc(typeApplSignature, (Ptr) &fndrCreator,
148 sizeof(fndrCreator), &fndrAddress);
149 if (err != noErr) goto bail;
150 err = AECreateAppleEvent(kCoreEventClass, kAEOpenDocuments,
151 &fndrAddress, kAutoGenerateReturnID,
152 kAnyTransactionID, &theAEvent);
153 if (err != noErr) goto bail;
154
155 /* create the list of files to open */
156 err = AECreateList(NULL, 0, false, &targetListDesc);
157 if (err != noErr) goto bail;
158 for ( index=0; index < nTargets; index++) {
159 if (targetAlias == NULL)
160 err = NewAlias(NULL, (targetList + index), &targetAlias);
161 else err = UpdateAlias(NULL, (targetList + index), targetAlias, &wasChanged);
162 if (err != noErr) goto bail;
163 HLock((Handle) targetAlias);
164 err = AEPutPtr(&targetListDesc, (index + 1), typeAlias, *targetAlias, GetHandleSize((Handle) targetAlias));
165 HUnlock((Handle) targetAlias);
166 if (err != noErr) goto bail;
167 }
168
169 /* add the file list to the apple event */
170 err = AEPutParamDesc(&theAEvent, keyDirectObject, &targetListDesc);
171 if (err != noErr) goto bail;
172
173 /* send the event to the Finder */
174 err = AESend(&theAEvent, &theReply, kAENoReply,
175 kAENormalPriority, kAEDefaultTimeout, NULL, NULL);
176
177 /* clean up and leave */
178 bail:
179 if (targetAlias != NULL) DisposeHandle((Handle) targetAlias);
180 AEDisposeDesc(&targetListDesc);
181 AEDisposeDesc(&theAEvent);
182 AEDisposeDesc(&fndrAddress);
183 AEDisposeDesc(&theReply);
184 return err;
185
186 #else
187
188 static EventRecord er;
189 short err;
190 AliasHandle a1 = 0, a2 = 0;
191 long hs1, hs2;
192 FSSpec fs1;
193 Handle message;
194 CInfoPBRec pb;
195 long version;
196
197 err = GetFinderPort();
198
199 if (err != noErr)
200 return err;
201
202 /*
203 err = FSMakeFSSpec(vRefNum, dirID, name, &fs2);
204 if (err != noErr)
205 return err;
206 */
207
208 /* get some catalog information, which we will use later. */
209 pb.dirInfo.ioCompletion=0;
210 pb.dirInfo.ioNamePtr = fs2.name;
211 pb.dirInfo.ioVRefNum = fs2.vRefNum;
212 pb.dirInfo.ioFDirIndex = 0;
213 pb.dirInfo.ioDrDirID = fs2.parID;
214
215 err = PBGetCatInfoSync(&pb);
216
217 if (err != noErr)
218 return err;
219
220 err = NewAliasMinimal(&fs2, &a2);
221
222 if (err != noErr)
223 return err;
224
225 fs1 = fs2;
226
227 if (gestalt (gestaltAUXVersion, &version)) { /*running under A/UX; cover bugs*/
228
229 if (fs1.parID == 1) { /*it's a volume*/
230
231 fs1.vRefNum = -1; /*a/ux wants to see the root as the parent*/
232 }
233 else { /*not a volume: path parsing works better under a/ux*/
234
235 bigstring path;
236
237 if (!filespectopath (&fs1, path))
238 return (false);
239
240 folderfrompath (path, path);
241
242 if (!pathtofilespec (path, &fs1))
243 return (false);
244
245 goto gotfs1;
246 }
247 }
248 else {
249
250 if (fs1.parID == 1) { /*it's a volume*/
251
252 err = FindFolder(fs1.vRefNum, kDesktopFolderType, false, &fs1.vRefNum, &fs1.parID);
253
254 if (err != noErr)
255 return err;
256 }
257 }
258
259 err = FSMakeFSSpec(fs1.vRefNum, fs1.parID, "\p", &fs1);
260
261 if (err != noErr)
262 return err;
263
264 gotfs1:
265
266 err = NewAliasMinimal(&fs1, &a1);
267
268 if (err != noErr)
269 return err;
270
271 hs1 = GetHandleSize((Handle) a1);
272 hs2 = GetHandleSize((Handle) a2);
273
274 MoveHHi((Handle) a1); HLock((Handle) a1);
275 MoveHHi((Handle) a2); HLock((Handle) a2);
276
277 er.what = kHighLevelEvent; /* PHLE fills this in, but we do it just to be clear. */
278 er.message = kAEFinderEvents; /* this is the event class */
279 *(long *)&er.where = kAEOpenSelection; /* this is the event type - see Card 131 */
280 er.when = TickCount(); /* this also gets filled in, but... */
281 er.modifiers = 0; /* doesn't matter */
282
283 message = NewHandle (24 + hs1 + 28 + hs2);
284
285 /*
286 normally you'd use Apple Events manager calls to pack up a message and
287 send it. I do things this way only because I can't be sure the frontmost
288 app has initialized that manager.
289 */
290
291 if (message) {
292 register long *filler = (void *)*message;
293
294 *filler++ = 'aevt';
295 *filler++ = 0x00010001;
296 *filler++ = ';;;;';
297 *filler++ = '----';
298 *filler++ = 'alis';
299 *filler++ = hs1;
300 BlockMove(*a1, filler, hs1); filler = (long *)(hs1 + (long) filler);
301 *filler++ = 'fsel';
302 *filler++ = 'list';
303 *filler++ = hs2 + 16;
304 *filler++ = 1;
305 *filler++ = 0;
306 *filler++ = 'alis';
307 *filler++ = hs2;
308 BlockMove(*a2, filler, hs2);
309 };
310
311 DisposeHandle((Handle) a1);
312 DisposeHandle((Handle) a2);
313
314 if (!message)
315 return (memFullErr);
316
317 /*
318 MFDispatch(0x40);
319 */
320 HLock(message);
321
322 err = PostHighLevelEvent(&er, &FinderNumber, 237,
323 *message, GetHandleSize(message),
324 receiverIDisPSN);
325
326 /*
327 MFDispatch(0x41);
328 */
329
330 if ((pb.dirInfo.ioFlAttrib & ioDirMask) || pb.hFileInfo.ioFlFndrInfo.fdType == 'cdev') {
331 SetFrontProcess(&FinderNumber);
332 };
333
334 DisposeHandle(message);
335 #endif
336
337
338 return (err);
339 } /*System7Open*/
340
341
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.