blob: e0ecb8eeaae15a64632a84c422eda3b597970016 [file] [log] [blame]
Guido van Rossumdbfb2821995-02-19 15:51:30 +00001/***********************************************************
2Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3The Netherlands.
4
5 All Rights Reserved
6
7Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
9provided that the above copyright notice appear in all copies and that
10both that copyright notice and this permission notice appear in
11supporting documentation, and that the names of Stichting Mathematisch
12Centrum or CWI not be used in advertising or publicity pertaining to
13distribution of the software without specific, written prior permission.
14
15STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22
23******************************************************************/
24
25/* Construct argc and argv for main() by using Apple Events */
26/* From Jack's implementation for STDWIN */
27
28#include <stdlib.h>
29
30#ifndef SystemSevenOrLater
31#define SystemSevenOrLater 1
32#endif
33
34#include <Types.h>
35#include <Files.h>
36#include <Events.h>
37#include <Memory.h>
38#include <Processes.h>
39#include <Errors.h>
40#include <AppleEvents.h>
41#include <AEObjects.h>
42#include <Desk.h>
43#include <Fonts.h>
Guido van Rossum6fc5aec1995-02-19 23:32:59 +000044#include <TextEdit.h>
45#include <Menus.h>
46#include <Dialogs.h>
47#include <Windows.h>
Guido van Rossumdbfb2821995-02-19 15:51:30 +000048
49#ifdef GENERATINGCFM /* Defined to 0 or 1 in Universal headers */
50#define HAVE_UNIVERSAL_HEADERS
51#endif
52
Jack Jansenf74f63a1995-06-27 13:18:14 +000053#ifdef SYMANTEC__CFM68K__
Guido van Rossumdbfb2821995-02-19 15:51:30 +000054#pragma lib_export on
55#endif
56
57#ifndef HAVE_UNIVERSAL_HEADERS
58#define NewAEEventHandlerProc(x) (x)
59#define AEEventHandlerUPP EventHandlerProcPtr
60#endif
61
62static int arg_count;
63static char *arg_vector[256];
64
Jack Jansen178652b1995-10-12 10:22:57 +000065/* Duplicate a string to the heap. We also export this since it isn't standard
66** and others use it
67*/
Guido van Rossumdbfb2821995-02-19 15:51:30 +000068
Jack Jansen178652b1995-10-12 10:22:57 +000069char *
Guido van Rossumdbfb2821995-02-19 15:51:30 +000070strdup(char *src)
71{
72 char *dst = malloc(strlen(src) + 1);
73 if (dst)
74 strcpy(dst, src);
75 return dst;
76}
77
78/* Return FSSpec of current application */
79
Jack Jansen41fa7ea1995-08-31 13:59:36 +000080OSErr
81PyMac_process_location(FSSpec *applicationSpec)
Guido van Rossumdbfb2821995-02-19 15:51:30 +000082{
83 ProcessSerialNumber currentPSN;
84 ProcessInfoRec info;
85
86 currentPSN.highLongOfPSN = 0;
87 currentPSN.lowLongOfPSN = kCurrentProcess;
88 info.processInfoLength = sizeof(ProcessInfoRec);
89 info.processName = NULL;
90 info.processAppSpec = applicationSpec;
91 return GetProcessInformation(&currentPSN, &info);
92}
93
94/* Given an FSSpec, return the FSSpec of the parent folder */
95
96static OSErr
97get_folder_parent (FSSpec * fss, FSSpec * parent)
98{
99 CInfoPBRec rec;
100 short err;
101
102 * parent = * fss;
103 rec.hFileInfo.ioNamePtr = parent->name;
104 rec.hFileInfo.ioVRefNum = parent->vRefNum;
105 rec.hFileInfo.ioDirID = parent->parID;
106 rec.hFileInfo.ioFDirIndex = -1;
107 rec.hFileInfo.ioFVersNum = 0;
108 if (err = PBGetCatInfoSync (& rec))
109 return err;
110 parent->parID = rec.dirInfo.ioDrParID;
111/* parent->name[0] = 0; */
112 return 0;
113}
114
115/* Given an FSSpec return a full, colon-separated pathname */
116
117static OSErr
118get_full_path (FSSpec *fss, char *buf)
119{
120 short err;
121 FSSpec fss_parent, fss_current;
122 char tmpbuf[256];
123 int plen;
124
125 fss_current = *fss;
126 plen = fss_current.name[0];
127 memcpy(buf, &fss_current.name[1], plen);
128 buf[plen] = 0;
129 while (fss_current.parID > 1) {
130 /* Get parent folder name */
131 if (err = get_folder_parent(&fss_current, &fss_parent))
132 return err;
133 fss_current = fss_parent;
134 /* Prepend path component just found to buf */
135 plen = fss_current.name[0];
136 if (strlen(buf) + plen + 1 > 256) {
137 /* Oops... Not enough space (shouldn't happen) */
138 *buf = 0;
139 return -1;
140 }
141 memcpy(tmpbuf, &fss_current.name[1], plen);
142 tmpbuf[plen] = ':';
143 strcpy(&tmpbuf[plen+1], buf);
144 strcpy(buf, tmpbuf);
145 }
146 return 0;
147}
148
149/* Return the full program name */
150
151static char *
152get_application_name()
153{
154 static char appname[256];
155 FSSpec appspec;
Guido van Rossumdbfb2821995-02-19 15:51:30 +0000156
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000157 if (PyMac_process_location(&appspec))
Guido van Rossumdbfb2821995-02-19 15:51:30 +0000158 return NULL;
159 if (get_full_path(&appspec, appname))
160 return NULL;
161 return appname;
162}
163
164/* Check that there aren't any args remaining in the event */
165
166static OSErr
167get_missing_params(AppleEvent *theAppleEvent)
168{
169 DescType theType;
170 Size actualSize;
171 OSErr err;
172
173 err = AEGetAttributePtr(theAppleEvent, keyMissedKeywordAttr, typeWildCard,
174 &theType, nil, 0, &actualSize);
175 if (err == errAEDescNotFound)
176 return noErr;
177 else
178 return errAEEventNotHandled;
179}
180
181static int got_one; /* Flag that we can stop getting events */
182
183/* Handle the Print or Quit events (by failing) */
184
185static pascal OSErr
186handle_not(AppleEvent *theAppleEvent, AppleEvent *reply, long refCon)
187{
188 #pragma unused (reply, refCon)
189 got_one = 1;
190 return errAEEventNotHandled;
191}
192
193/* Handle the Open Application event (by ignoring it) */
194
195static pascal OSErr
196handle_open_app(AppleEvent *theAppleEvent, AppleEvent *reply, long refCon)
197{
198 #pragma unused (reply, refCon)
Jack Jansendbe75ae1995-11-10 14:54:16 +0000199#if 0
200 /* Test by Jack: would removing this facilitate debugging? */
Guido van Rossumdbfb2821995-02-19 15:51:30 +0000201 got_one = 1;
Jack Jansendbe75ae1995-11-10 14:54:16 +0000202#endif
Guido van Rossumdbfb2821995-02-19 15:51:30 +0000203 return get_missing_params(theAppleEvent);
204}
205
206/* Handle the Open Document event, by adding an argument */
207
208static pascal OSErr
209handle_open_doc(AppleEvent *theAppleEvent, AppleEvent *reply, long refCon)
210{
211 #pragma unused (reply, refCon)
212 OSErr err;
213 AEDescList doclist;
214 AEKeyword keywd;
215 DescType rttype;
216 long i, ndocs, size;
217 FSSpec fss;
218 char path[256];
219
220 got_one = 1;
221 if (err = AEGetParamDesc(theAppleEvent,
222 keyDirectObject, typeAEList, &doclist))
223 return err;
224 if (err = get_missing_params(theAppleEvent))
225 return err;
226 if (err = AECountItems(&doclist, &ndocs))
227 return err;
228 for(i = 1; i <= ndocs; i++) {
229 err = AEGetNthPtr(&doclist, i, typeFSS,
230 &keywd, &rttype, &fss, sizeof(fss), &size);
231 if (err)
232 break;
233 get_full_path(&fss, path);
234 arg_vector[arg_count++] = strdup(path);
235 }
236 return err;
237}
238
239/* Install standard core event handlers */
Jack Jansencc456fb1995-07-29 13:50:59 +0000240AEEventHandlerUPP open_doc_upp;
241AEEventHandlerUPP open_app_upp;
242AEEventHandlerUPP not_upp;
Guido van Rossumdbfb2821995-02-19 15:51:30 +0000243
244static void
245set_ae_handlers()
246{
Jack Jansencc456fb1995-07-29 13:50:59 +0000247 open_doc_upp = NewAEEventHandlerProc(handle_open_doc);
248 open_app_upp = NewAEEventHandlerProc(handle_open_app);
249 not_upp = NewAEEventHandlerProc(handle_not);
250
Guido van Rossumdbfb2821995-02-19 15:51:30 +0000251 AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
Jack Jansencc456fb1995-07-29 13:50:59 +0000252 open_app_upp, 0L, false);
Guido van Rossumdbfb2821995-02-19 15:51:30 +0000253 AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
Jack Jansencc456fb1995-07-29 13:50:59 +0000254 open_doc_upp, 0L, false);
Guido van Rossumdbfb2821995-02-19 15:51:30 +0000255 AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
Jack Jansencc456fb1995-07-29 13:50:59 +0000256 not_upp, 0L, false);
Guido van Rossumdbfb2821995-02-19 15:51:30 +0000257 AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
Jack Jansencc456fb1995-07-29 13:50:59 +0000258 not_upp, 0L, false);
Guido van Rossumdbfb2821995-02-19 15:51:30 +0000259}
260
261/* Uninstall standard core event handlers */
262
263static void
264reset_ae_handlers()
265{
266 AERemoveEventHandler(kCoreEventClass, kAEOpenApplication,
Jack Jansencc456fb1995-07-29 13:50:59 +0000267 open_app_upp, false);
Guido van Rossumdbfb2821995-02-19 15:51:30 +0000268 AERemoveEventHandler(kCoreEventClass, kAEOpenDocuments,
Jack Jansencc456fb1995-07-29 13:50:59 +0000269 open_doc_upp, false);
Guido van Rossumdbfb2821995-02-19 15:51:30 +0000270 AERemoveEventHandler(kCoreEventClass, kAEPrintDocuments,
Jack Jansencc456fb1995-07-29 13:50:59 +0000271 not_upp, false);
Guido van Rossumdbfb2821995-02-19 15:51:30 +0000272 AERemoveEventHandler(kCoreEventClass, kAEQuitApplication,
Jack Jansencc456fb1995-07-29 13:50:59 +0000273 not_upp, false);
Guido van Rossumdbfb2821995-02-19 15:51:30 +0000274}
275
276/* Wait for events until a core event has been handled */
277
278static void
279event_loop()
280{
281 EventRecord event;
282 int n;
283 int ok;
284
285 got_one = 0;
286 for (n = 0; n < 100 && !got_one; n++) {
287 SystemTask();
288 ok = GetNextEvent(everyEvent, &event);
289 if (ok && event.what == kHighLevelEvent) {
290 AEProcessAppleEvent(&event);
291 }
292 }
293}
294
Guido van Rossumdbfb2821995-02-19 15:51:30 +0000295/* Get the argv vector, return argc */
296
297int
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000298PyMac_GetArgv(pargv, noevents)
Guido van Rossumdbfb2821995-02-19 15:51:30 +0000299 char ***pargv;
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000300 int noevents;
Guido van Rossumdbfb2821995-02-19 15:51:30 +0000301{
Guido van Rossumdbfb2821995-02-19 15:51:30 +0000302
303 arg_count = 0;
304 arg_vector[arg_count++] = strdup(get_application_name());
305
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000306 if( !noevents ) {
307 set_ae_handlers();
308 event_loop();
309 reset_ae_handlers();
310 }
Guido van Rossumdbfb2821995-02-19 15:51:30 +0000311
312 arg_vector[arg_count] = NULL;
313
314 *pargv = arg_vector;
315 return arg_count;
316}