blob: 5f2e637718e1d3c3232840e906dd2c939231e5bd [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
65/* Duplicate a string to the heap */
66
67static char *
68strdup(char *src)
69{
70 char *dst = malloc(strlen(src) + 1);
71 if (dst)
72 strcpy(dst, src);
73 return dst;
74}
75
76/* Return FSSpec of current application */
77
78static OSErr
79current_process_location(FSSpec *applicationSpec)
80{
81 ProcessSerialNumber currentPSN;
82 ProcessInfoRec info;
83
84 currentPSN.highLongOfPSN = 0;
85 currentPSN.lowLongOfPSN = kCurrentProcess;
86 info.processInfoLength = sizeof(ProcessInfoRec);
87 info.processName = NULL;
88 info.processAppSpec = applicationSpec;
89 return GetProcessInformation(&currentPSN, &info);
90}
91
92/* Given an FSSpec, return the FSSpec of the parent folder */
93
94static OSErr
95get_folder_parent (FSSpec * fss, FSSpec * parent)
96{
97 CInfoPBRec rec;
98 short err;
99
100 * parent = * fss;
101 rec.hFileInfo.ioNamePtr = parent->name;
102 rec.hFileInfo.ioVRefNum = parent->vRefNum;
103 rec.hFileInfo.ioDirID = parent->parID;
104 rec.hFileInfo.ioFDirIndex = -1;
105 rec.hFileInfo.ioFVersNum = 0;
106 if (err = PBGetCatInfoSync (& rec))
107 return err;
108 parent->parID = rec.dirInfo.ioDrParID;
109/* parent->name[0] = 0; */
110 return 0;
111}
112
113/* Given an FSSpec return a full, colon-separated pathname */
114
115static OSErr
116get_full_path (FSSpec *fss, char *buf)
117{
118 short err;
119 FSSpec fss_parent, fss_current;
120 char tmpbuf[256];
121 int plen;
122
Jack Jansenf74f63a1995-06-27 13:18:14 +0000123#if defined(__MWERKS__) && defined(__CFM68K__)
124 return -1; /* get_folder_parent doesn't work */
125#endif
Guido van Rossumdbfb2821995-02-19 15:51:30 +0000126 fss_current = *fss;
127 plen = fss_current.name[0];
128 memcpy(buf, &fss_current.name[1], plen);
129 buf[plen] = 0;
130 while (fss_current.parID > 1) {
131 /* Get parent folder name */
132 if (err = get_folder_parent(&fss_current, &fss_parent))
133 return err;
134 fss_current = fss_parent;
135 /* Prepend path component just found to buf */
136 plen = fss_current.name[0];
137 if (strlen(buf) + plen + 1 > 256) {
138 /* Oops... Not enough space (shouldn't happen) */
139 *buf = 0;
140 return -1;
141 }
142 memcpy(tmpbuf, &fss_current.name[1], plen);
143 tmpbuf[plen] = ':';
144 strcpy(&tmpbuf[plen+1], buf);
145 strcpy(buf, tmpbuf);
146 }
147 return 0;
148}
149
150/* Return the full program name */
151
152static char *
153get_application_name()
154{
155 static char appname[256];
156 FSSpec appspec;
Guido van Rossumdbfb2821995-02-19 15:51:30 +0000157
158 if (current_process_location(&appspec))
159 return NULL;
160 if (get_full_path(&appspec, appname))
161 return NULL;
162 return appname;
163}
164
165/* Check that there aren't any args remaining in the event */
166
167static OSErr
168get_missing_params(AppleEvent *theAppleEvent)
169{
170 DescType theType;
171 Size actualSize;
172 OSErr err;
173
174 err = AEGetAttributePtr(theAppleEvent, keyMissedKeywordAttr, typeWildCard,
175 &theType, nil, 0, &actualSize);
176 if (err == errAEDescNotFound)
177 return noErr;
178 else
179 return errAEEventNotHandled;
180}
181
182static int got_one; /* Flag that we can stop getting events */
183
184/* Handle the Print or Quit events (by failing) */
185
186static pascal OSErr
187handle_not(AppleEvent *theAppleEvent, AppleEvent *reply, long refCon)
188{
189 #pragma unused (reply, refCon)
190 got_one = 1;
191 return errAEEventNotHandled;
192}
193
194/* Handle the Open Application event (by ignoring it) */
195
196static pascal OSErr
197handle_open_app(AppleEvent *theAppleEvent, AppleEvent *reply, long refCon)
198{
199 #pragma unused (reply, refCon)
200 got_one = 1;
201 return get_missing_params(theAppleEvent);
202}
203
204/* Handle the Open Document event, by adding an argument */
205
206static pascal OSErr
207handle_open_doc(AppleEvent *theAppleEvent, AppleEvent *reply, long refCon)
208{
209 #pragma unused (reply, refCon)
210 OSErr err;
211 AEDescList doclist;
212 AEKeyword keywd;
213 DescType rttype;
214 long i, ndocs, size;
215 FSSpec fss;
216 char path[256];
217
218 got_one = 1;
219 if (err = AEGetParamDesc(theAppleEvent,
220 keyDirectObject, typeAEList, &doclist))
221 return err;
222 if (err = get_missing_params(theAppleEvent))
223 return err;
224 if (err = AECountItems(&doclist, &ndocs))
225 return err;
226 for(i = 1; i <= ndocs; i++) {
227 err = AEGetNthPtr(&doclist, i, typeFSS,
228 &keywd, &rttype, &fss, sizeof(fss), &size);
229 if (err)
230 break;
231 get_full_path(&fss, path);
232 arg_vector[arg_count++] = strdup(path);
233 }
234 return err;
235}
236
237/* Install standard core event handlers */
238
239static void
240set_ae_handlers()
241{
242 AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
243 NewAEEventHandlerProc(handle_open_app), 0L, false);
244 AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
245 NewAEEventHandlerProc(handle_open_doc), 0L, false);
246 AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
247 NewAEEventHandlerProc(handle_not), 0L, false);
248 AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
249 NewAEEventHandlerProc(handle_not), 0L, false);
250}
251
252/* Uninstall standard core event handlers */
253
254static void
255reset_ae_handlers()
256{
257 AERemoveEventHandler(kCoreEventClass, kAEOpenApplication,
258 NewAEEventHandlerProc(handle_open_app), false);
259 AERemoveEventHandler(kCoreEventClass, kAEOpenDocuments,
260 NewAEEventHandlerProc(handle_open_doc), false);
261 AERemoveEventHandler(kCoreEventClass, kAEPrintDocuments,
262 NewAEEventHandlerProc(handle_not), false);
263 AERemoveEventHandler(kCoreEventClass, kAEQuitApplication,
264 NewAEEventHandlerProc(handle_not), false);
265}
266
267/* Wait for events until a core event has been handled */
268
269static void
270event_loop()
271{
272 EventRecord event;
273 int n;
274 int ok;
275
276 got_one = 0;
277 for (n = 0; n < 100 && !got_one; n++) {
278 SystemTask();
279 ok = GetNextEvent(everyEvent, &event);
280 if (ok && event.what == kHighLevelEvent) {
281 AEProcessAppleEvent(&event);
282 }
283 }
284}
285
286/* Initialize the Mac toolbox world */
287
288static void
289init_mac_world()
290{
Guido van Rossum6fc5aec1995-02-19 23:32:59 +0000291#ifdef THINK_C
292 printf("\n");
293#else
Guido van Rossumdbfb2821995-02-19 15:51:30 +0000294 MaxApplZone();
295 InitGraf(&qd.thePort);
296 InitFonts();
297 InitWindows();
298 TEInit();
299 InitDialogs((long)0);
300 InitMenus();
301 InitCursor();
Guido van Rossum6fc5aec1995-02-19 23:32:59 +0000302#endif
Guido van Rossumdbfb2821995-02-19 15:51:30 +0000303}
304/* Get the argv vector, return argc */
305
306int
307PyMac_GetArgv(pargv)
308 char ***pargv;
309{
310 init_mac_world();
311
312 arg_count = 0;
313 arg_vector[arg_count++] = strdup(get_application_name());
314
315 set_ae_handlers();
316 event_loop();
317 reset_ae_handlers();
318
319 arg_vector[arg_count] = NULL;
320
321 *pargv = arg_vector;
322 return arg_count;
323}