blob: c1d1e3edef08a1448934705c277611aa1524b7cf [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
Jack Jansen26ee1261996-11-09 18:45:18 +000049#include "Python.h"
50#include "macglue.h"
51
Guido van Rossumdbfb2821995-02-19 15:51:30 +000052#ifdef GENERATINGCFM /* Defined to 0 or 1 in Universal headers */
53#define HAVE_UNIVERSAL_HEADERS
54#endif
55
Jack Jansenf74f63a1995-06-27 13:18:14 +000056#ifdef SYMANTEC__CFM68K__
Guido van Rossumdbfb2821995-02-19 15:51:30 +000057#pragma lib_export on
58#endif
59
60#ifndef HAVE_UNIVERSAL_HEADERS
61#define NewAEEventHandlerProc(x) (x)
62#define AEEventHandlerUPP EventHandlerProcPtr
63#endif
64
65static int arg_count;
66static char *arg_vector[256];
Jack Jansen26ee1261996-11-09 18:45:18 +000067FSSpec PyMac_ApplicationFSSpec;
68char PyMac_ApplicationPath[256];
69static int applocation_inited;
Guido van Rossumdbfb2821995-02-19 15:51:30 +000070
Jack Jansen178652b1995-10-12 10:22:57 +000071/* Duplicate a string to the heap. We also export this since it isn't standard
72** and others use it
73*/
Guido van Rossumdbfb2821995-02-19 15:51:30 +000074
Jack Jansen178652b1995-10-12 10:22:57 +000075char *
Guido van Rossumdbfb2821995-02-19 15:51:30 +000076strdup(char *src)
77{
78 char *dst = malloc(strlen(src) + 1);
79 if (dst)
80 strcpy(dst, src);
81 return dst;
82}
83
Jack Jansen26ee1261996-11-09 18:45:18 +000084/* Initialize FSSpec and full name of current application */
Guido van Rossumdbfb2821995-02-19 15:51:30 +000085
Jack Jansen41fa7ea1995-08-31 13:59:36 +000086OSErr
Jack Jansen26ee1261996-11-09 18:45:18 +000087PyMac_init_process_location()
Guido van Rossumdbfb2821995-02-19 15:51:30 +000088{
89 ProcessSerialNumber currentPSN;
90 ProcessInfoRec info;
Jack Jansen26ee1261996-11-09 18:45:18 +000091 OSErr err;
Guido van Rossumdbfb2821995-02-19 15:51:30 +000092
Jack Jansen26ee1261996-11-09 18:45:18 +000093 if ( applocation_inited ) return 0;
Guido van Rossumdbfb2821995-02-19 15:51:30 +000094 currentPSN.highLongOfPSN = 0;
95 currentPSN.lowLongOfPSN = kCurrentProcess;
96 info.processInfoLength = sizeof(ProcessInfoRec);
97 info.processName = NULL;
Jack Jansen26ee1261996-11-09 18:45:18 +000098 info.processAppSpec = &PyMac_ApplicationFSSpec;
99 if ( err=GetProcessInformation(&currentPSN, &info))
100 return err;
101 if ( err=PyMac_GetFullPath(&PyMac_ApplicationFSSpec, PyMac_ApplicationPath) )
102 return err;
103 applocation_inited = 1;
104 return 0;
Guido van Rossumdbfb2821995-02-19 15:51:30 +0000105}
106
107/* Given an FSSpec, return the FSSpec of the parent folder */
108
109static OSErr
110get_folder_parent (FSSpec * fss, FSSpec * parent)
111{
112 CInfoPBRec rec;
113 short err;
114
115 * parent = * fss;
116 rec.hFileInfo.ioNamePtr = parent->name;
117 rec.hFileInfo.ioVRefNum = parent->vRefNum;
118 rec.hFileInfo.ioDirID = parent->parID;
119 rec.hFileInfo.ioFDirIndex = -1;
120 rec.hFileInfo.ioFVersNum = 0;
121 if (err = PBGetCatInfoSync (& rec))
122 return err;
123 parent->parID = rec.dirInfo.ioDrParID;
124/* parent->name[0] = 0; */
125 return 0;
126}
127
128/* Given an FSSpec return a full, colon-separated pathname */
129
Jack Jansen26ee1261996-11-09 18:45:18 +0000130OSErr
131PyMac_GetFullPath (FSSpec *fss, char *buf)
Guido van Rossumdbfb2821995-02-19 15:51:30 +0000132{
133 short err;
134 FSSpec fss_parent, fss_current;
135 char tmpbuf[256];
136 int plen;
137
138 fss_current = *fss;
139 plen = fss_current.name[0];
140 memcpy(buf, &fss_current.name[1], plen);
141 buf[plen] = 0;
142 while (fss_current.parID > 1) {
143 /* Get parent folder name */
144 if (err = get_folder_parent(&fss_current, &fss_parent))
145 return err;
146 fss_current = fss_parent;
147 /* Prepend path component just found to buf */
148 plen = fss_current.name[0];
149 if (strlen(buf) + plen + 1 > 256) {
150 /* Oops... Not enough space (shouldn't happen) */
151 *buf = 0;
152 return -1;
153 }
154 memcpy(tmpbuf, &fss_current.name[1], plen);
155 tmpbuf[plen] = ':';
156 strcpy(&tmpbuf[plen+1], buf);
157 strcpy(buf, tmpbuf);
158 }
159 return 0;
160}
161
Guido van Rossumdbfb2821995-02-19 15:51:30 +0000162/* Check that there aren't any args remaining in the event */
163
164static OSErr
165get_missing_params(AppleEvent *theAppleEvent)
166{
167 DescType theType;
168 Size actualSize;
169 OSErr err;
170
171 err = AEGetAttributePtr(theAppleEvent, keyMissedKeywordAttr, typeWildCard,
172 &theType, nil, 0, &actualSize);
173 if (err == errAEDescNotFound)
174 return noErr;
175 else
176 return errAEEventNotHandled;
177}
178
179static int got_one; /* Flag that we can stop getting events */
180
181/* Handle the Print or Quit events (by failing) */
182
183static pascal OSErr
184handle_not(AppleEvent *theAppleEvent, AppleEvent *reply, long refCon)
185{
186 #pragma unused (reply, refCon)
187 got_one = 1;
188 return errAEEventNotHandled;
189}
190
191/* Handle the Open Application event (by ignoring it) */
192
193static pascal OSErr
194handle_open_app(AppleEvent *theAppleEvent, AppleEvent *reply, long refCon)
195{
196 #pragma unused (reply, refCon)
Jack Jansendbe75ae1995-11-10 14:54:16 +0000197#if 0
198 /* Test by Jack: would removing this facilitate debugging? */
Guido van Rossumdbfb2821995-02-19 15:51:30 +0000199 got_one = 1;
Jack Jansendbe75ae1995-11-10 14:54:16 +0000200#endif
Guido van Rossumdbfb2821995-02-19 15:51:30 +0000201 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;
Jack Jansen26ee1261996-11-09 18:45:18 +0000231 PyMac_GetFullPath(&fss, path);
Guido van Rossumdbfb2821995-02-19 15:51:30 +0000232 arg_vector[arg_count++] = strdup(path);
233 }
234 return err;
235}
236
237/* Install standard core event handlers */
Jack Jansencc456fb1995-07-29 13:50:59 +0000238AEEventHandlerUPP open_doc_upp;
239AEEventHandlerUPP open_app_upp;
240AEEventHandlerUPP not_upp;
Guido van Rossumdbfb2821995-02-19 15:51:30 +0000241
242static void
243set_ae_handlers()
244{
Jack Jansencc456fb1995-07-29 13:50:59 +0000245 open_doc_upp = NewAEEventHandlerProc(handle_open_doc);
246 open_app_upp = NewAEEventHandlerProc(handle_open_app);
247 not_upp = NewAEEventHandlerProc(handle_not);
248
Guido van Rossumdbfb2821995-02-19 15:51:30 +0000249 AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
Jack Jansencc456fb1995-07-29 13:50:59 +0000250 open_app_upp, 0L, false);
Guido van Rossumdbfb2821995-02-19 15:51:30 +0000251 AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
Jack Jansencc456fb1995-07-29 13:50:59 +0000252 open_doc_upp, 0L, false);
Guido van Rossumdbfb2821995-02-19 15:51:30 +0000253 AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
Jack Jansencc456fb1995-07-29 13:50:59 +0000254 not_upp, 0L, false);
Guido van Rossumdbfb2821995-02-19 15:51:30 +0000255 AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
Jack Jansencc456fb1995-07-29 13:50:59 +0000256 not_upp, 0L, false);
Guido van Rossumdbfb2821995-02-19 15:51:30 +0000257}
258
259/* Uninstall standard core event handlers */
260
261static void
262reset_ae_handlers()
263{
264 AERemoveEventHandler(kCoreEventClass, kAEOpenApplication,
Jack Jansencc456fb1995-07-29 13:50:59 +0000265 open_app_upp, false);
Guido van Rossumdbfb2821995-02-19 15:51:30 +0000266 AERemoveEventHandler(kCoreEventClass, kAEOpenDocuments,
Jack Jansencc456fb1995-07-29 13:50:59 +0000267 open_doc_upp, false);
Guido van Rossumdbfb2821995-02-19 15:51:30 +0000268 AERemoveEventHandler(kCoreEventClass, kAEPrintDocuments,
Jack Jansencc456fb1995-07-29 13:50:59 +0000269 not_upp, false);
Guido van Rossumdbfb2821995-02-19 15:51:30 +0000270 AERemoveEventHandler(kCoreEventClass, kAEQuitApplication,
Jack Jansencc456fb1995-07-29 13:50:59 +0000271 not_upp, false);
Guido van Rossumdbfb2821995-02-19 15:51:30 +0000272}
273
274/* Wait for events until a core event has been handled */
275
276static void
277event_loop()
278{
279 EventRecord event;
280 int n;
281 int ok;
282
283 got_one = 0;
284 for (n = 0; n < 100 && !got_one; n++) {
285 SystemTask();
286 ok = GetNextEvent(everyEvent, &event);
287 if (ok && event.what == kHighLevelEvent) {
288 AEProcessAppleEvent(&event);
289 }
290 }
291}
292
Guido van Rossumdbfb2821995-02-19 15:51:30 +0000293/* Get the argv vector, return argc */
294
295int
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000296PyMac_GetArgv(pargv, noevents)
Guido van Rossumdbfb2821995-02-19 15:51:30 +0000297 char ***pargv;
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000298 int noevents;
Guido van Rossumdbfb2821995-02-19 15:51:30 +0000299{
Guido van Rossumdbfb2821995-02-19 15:51:30 +0000300
301 arg_count = 0;
Jack Jansen26ee1261996-11-09 18:45:18 +0000302 (void)PyMac_init_process_location();
303 arg_vector[arg_count++] = strdup(PyMac_ApplicationPath);
Guido van Rossumdbfb2821995-02-19 15:51:30 +0000304
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000305 if( !noevents ) {
306 set_ae_handlers();
307 event_loop();
308 reset_ae_handlers();
309 }
Guido van Rossumdbfb2821995-02-19 15:51:30 +0000310
311 arg_vector[arg_count] = NULL;
312
313 *pargv = arg_vector;
314 return arg_count;
315}