blob: d2797e7d28660757e35e7906ae753b18e2cc313e [file] [log] [blame]
Guido van Rossumb3404661995-01-22 18:36:13 +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******************************************************************/
Jack Jansenf93c72a1994-12-14 14:07:50 +000024
25#include "Python.h"
Guido van Rossumbecdbec1995-02-14 01:27:24 +000026
Jack Jansenf93c72a1994-12-14 14:07:50 +000027#include "macglue.h"
Jack Jansen74162f31995-02-15 22:58:33 +000028#include "marshal.h"
29#include "import.h"
Jack Jansenf93c72a1994-12-14 14:07:50 +000030
31#include <OSUtils.h> /* for Set(Current)A5 */
Jack Jansene8e8ae01995-01-26 16:36:45 +000032#include <Files.h>
Jack Jansen8cd2b721995-02-13 11:33:28 +000033#include <Aliases.h>
Jack Jansen6cfab231995-02-13 22:46:00 +000034#include <Folders.h>
Jack Jansen8cd2b721995-02-13 11:33:28 +000035#include <StandardFile.h>
Jack Jansenf93c72a1994-12-14 14:07:50 +000036#include <Resources.h>
37#include <Memory.h>
38#include <Events.h>
39#include <Windows.h>
40#include <Desk.h>
Jack Jansene8e8ae01995-01-26 16:36:45 +000041#include <Traps.h>
Jack Jansenee23d6e1995-01-27 14:43:25 +000042#include <Processes.h>
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +000043#include <Fonts.h>
44#include <Menus.h>
Guido van Rossumcc0d8791995-01-30 08:57:13 +000045#ifdef THINK_C
46#include <OSEvents.h> /* For EvQElPtr */
47#endif
Jack Jansenee23d6e1995-01-27 14:43:25 +000048
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +000049#ifndef HAVE_UNIVERSAL_HEADERS
50#define GetResourceSizeOnDisk(x) SizeResource(x)
51#endif
52
Jack Jansenee23d6e1995-01-27 14:43:25 +000053#include <signal.h>
Jack Jansen74162f31995-02-15 22:58:33 +000054#include <stdio.h>
Jack Jansene8e8ae01995-01-26 16:36:45 +000055
Jack Jansen8cd2b721995-02-13 11:33:28 +000056#define NOPYTHON_ALERT 128
57#define YES_ITEM 1
58#define NO_ITEM 2
59#define CURWD_ITEM 3
60
Jack Jansene8e8ae01995-01-26 16:36:45 +000061#ifdef __MWERKS__
Jack Jansenee23d6e1995-01-27 14:43:25 +000062/*
63** With MW we can pass the event off to the console window, so
64** we might as well handle all events.
65*/
Jack Jansene8e8ae01995-01-26 16:36:45 +000066#include <SIOUX.h>
Jack Jansenee23d6e1995-01-27 14:43:25 +000067#define MAINLOOP_EVENTMASK everyEvent
68#else
69/*
70** For other compilers we're more careful, since we can't handle
71** things like updates (and they'll keep coming back if we don't
72** handle them)
73*/
74#define MAINLOOP_EVENTMASK (mDownMask|keyDownMask|osMask)
Jack Jansene8e8ae01995-01-26 16:36:45 +000075#endif /* __MWERKS__ */
76
77#include <signal.h>
Jack Jansenf93c72a1994-12-14 14:07:50 +000078
Guido van Rossumb3404661995-01-22 18:36:13 +000079/* XXX We should include Errors.h here, but it has a name conflict
Jack Jansen5f653091995-01-18 13:53:49 +000080** with the python errors.h. */
81#define fnfErr -43
82
Jack Jansene8e8ae01995-01-26 16:36:45 +000083/* Declared in macfsmodule.c: */
84extern FSSpec *mfs_GetFSSpecFSSpec();
85
Jack Jansenee23d6e1995-01-27 14:43:25 +000086/* Interrupt code variables: */
87static int interrupted; /* Set to true when cmd-. seen */
88static RETSIGTYPE intcatcher Py_PROTO((int));
89
Jack Jansene8e8ae01995-01-26 16:36:45 +000090/*
91** We attempt to be a good citizen by giving up the CPU periodically.
92** When in the foreground we do this less often and for shorter periods
93** than when in the background. At this time we also check for events and
Jack Jansenee23d6e1995-01-27 14:43:25 +000094** pass them off to SIOUX, if compiling with mwerks.
Jack Jansene8e8ae01995-01-26 16:36:45 +000095** The counts here are in ticks of 1/60th second.
96** XXXX The initial values here are not based on anything.
97** FG-python gives up the cpu for 1/60th 5 times per second,
98** BG-python for .2 second 10 times per second.
99*/
100static long interval_fg = 12;
101static long interval_bg = 6;
102static long yield_fg = 1;
103static long yield_bg = 12;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000104static long lastyield;
105static int in_foreground;
106
107int PyMac_DoYieldEnabled = 1; /* Don't do eventloop when false */
108
Jack Jansene8e8ae01995-01-26 16:36:45 +0000109
Jack Jansen5f653091995-01-18 13:53:49 +0000110/* Convert C to Pascal string. Returns pointer to static buffer. */
111unsigned char *
112Pstring(char *str)
113{
114 static Str255 buf;
115 int len;
116
117 len = strlen(str);
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000118 if (len > 255)
119 len = 255;
Jack Jansen5f653091995-01-18 13:53:49 +0000120 buf[0] = (unsigned char)len;
121 strncpy((char *)buf+1, str, len);
122 return buf;
123}
124
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000125/* Like strerror() but for Mac OS error numbers */
126char *PyMac_StrError(int err)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000127{
128 static char buf[256];
129 Handle h;
130 char *str;
131
132 h = GetResource('Estr', err);
133 if ( h ) {
134 HLock(h);
135 str = (char *)*h;
136 memcpy(buf, str+1, (unsigned char)str[0]);
Guido van Rossumcc9bc8f1995-02-13 16:17:03 +0000137 buf[(unsigned char)str[0]] = '\0';
Jack Jansenf93c72a1994-12-14 14:07:50 +0000138 HUnlock(h);
139 ReleaseResource(h);
140 } else {
141 sprintf(buf, "Mac OS error code %d", err);
142 }
143 return buf;
144}
145
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000146/* Exception object shared by all Mac specific modules for Mac OS errors */
147PyObject *PyMac_OSErrException;
148
149/* Initialize and return PyMac_OSErrException */
150PyObject *
151PyMac_GetOSErrException()
152{
153 if (PyMac_OSErrException == NULL)
154 PyMac_OSErrException = PyString_FromString("Mac OS Error");
155 return PyMac_OSErrException;
156}
157
Jack Jansenf93c72a1994-12-14 14:07:50 +0000158/* Set a MAC-specific error from errno, and return NULL; return None if no error */
159PyObject *
Guido van Rossumfffb8bb1995-01-12 12:37:24 +0000160PyErr_Mac(PyObject *eobj, int err)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000161{
162 char *msg;
163 PyObject *v;
Jack Jansenf93c72a1994-12-14 14:07:50 +0000164
Guido van Rossum8f691791995-01-18 23:57:26 +0000165 if (err == 0 && !PyErr_Occurred()) {
Jack Jansenf93c72a1994-12-14 14:07:50 +0000166 Py_INCREF(Py_None);
167 return Py_None;
168 }
Guido van Rossum8f691791995-01-18 23:57:26 +0000169 if (err == -1 && PyErr_Occurred())
170 return NULL;
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000171 msg = PyMac_StrError(err);
Jack Jansenf93c72a1994-12-14 14:07:50 +0000172 v = Py_BuildValue("(is)", err, msg);
173 PyErr_SetObject(eobj, v);
174 Py_DECREF(v);
175 return NULL;
176}
177
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000178/* Call PyErr_Mac with PyMac_OSErrException */
179PyObject *
180PyMac_Error(OSErr err)
181{
182 return PyErr_Mac(PyMac_GetOSErrException(), err);
183}
184
Jack Jansenee23d6e1995-01-27 14:43:25 +0000185/* The catcher routine (which may not be used for all compilers) */
186static RETSIGTYPE
187intcatcher(sig)
188 int sig;
189{
190 interrupted = 1;
191 signal(SIGINT, intcatcher);
192}
193
194void
195PyOS_InitInterrupts()
196{
197 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
198 signal(SIGINT, intcatcher);
199}
200
201/*
202** This routine scans the event queue looking for cmd-.
203** This is the only way to get an interrupt under THINK (since it
204** doesn't do SIGINT handling), but is also used under MW, when
205** the full-fledged event loop is disabled. This way, we can at least
206** interrupt a runaway python program.
207*/
208static void
209scan_event_queue(flush)
210 int flush;
211{
212 register EvQElPtr q;
213
214 q = (EvQElPtr) GetEvQHdr()->qHead;
215
216 for (; q; q = (EvQElPtr)q->qLink) {
217 if (q->evtQWhat == keyDown &&
218 (char)q->evtQMessage == '.' &&
219 (q->evtQModifiers & cmdKey) != 0) {
220 if ( flush )
221 FlushEvents(keyDownMask, 0);
222 interrupted = 1;
223 break;
224 }
225 }
226}
227
228int
229PyOS_InterruptOccurred()
230{
231#ifdef THINK_C
232 scan_event_queue(1);
233#endif
234 PyMac_Yield();
235 if (interrupted) {
236 interrupted = 0;
237 return 1;
238 }
239 return 0;
240}
241
242/* intrpeek() is like intrcheck(), but it doesn't flush the events. The
243** idea is that you call intrpeek() somewhere in a busy-wait loop, and return
244** None as soon as it returns 1. The mainloop will then pick up the cmd-. soon
245** thereafter.
246*/
247static int
248intrpeek()
249{
250#ifdef THINK_C
251 scan_event_queue(0);
252#endif
253 return interrupted;
254}
255
256/* Check whether we are in the foreground */
257int
258PyMac_InForeground()
259{
260 static ProcessSerialNumber ours;
261 static inited;
262 ProcessSerialNumber curfg;
263 Boolean eq;
264
265 if ( inited == 0 )
266 (void)GetCurrentProcess(&ours);
267 inited = 1;
268 if ( GetFrontProcess(&curfg) < 0 )
269 eq = 1;
270 else if ( SameProcess(&ours, &curfg, &eq) < 0 )
271 eq = 1;
272 return (int)eq;
273
274}
275
Jack Jansenf93c72a1994-12-14 14:07:50 +0000276/*
Jack Jansene8e8ae01995-01-26 16:36:45 +0000277** Set yield timeouts
Jack Jansenf93c72a1994-12-14 14:07:50 +0000278*/
Jack Jansene8e8ae01995-01-26 16:36:45 +0000279void
280PyMac_SetYield(long fgi, long fgy, long bgi, long bgy)
281{
282 interval_fg = fgi;
283 yield_fg = fgy;
284 interval_bg = bgi;
285 yield_bg = bgy;
286}
287
288/*
Jack Jansena76382a1995-02-02 14:25:56 +0000289** Handle an event, either one found in the mainloop eventhandler or
290** one passed back from the python program.
291*/
292void
293PyMac_HandleEvent(evp)
294 EventRecord *evp;
295{
296 WindowPtr wp;
297
298#ifdef __MWERKS__
299 /* If SIOUX wants it we're done */
300 (void)SIOUXHandleOneEvent(evp);
301#else
302 /* Other compilers are just unlucky: we only weed out clicks in other applications */
303 if ( evp->what == mouseDown ) {
304 if ( FindWindow(evp->where, &wp) == inSysWindow )
305 SystemClick(evp, wp);
306 }
307#endif /* !__MWERKS__ */
308}
309
310/*
Jack Jansene8e8ae01995-01-26 16:36:45 +0000311** Yield the CPU to other tasks.
312*/
313static
314PyMac_DoYield()
Jack Jansenf93c72a1994-12-14 14:07:50 +0000315{
316 EventRecord ev;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000317 long yield;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000318 static int no_waitnextevent = -1;
319 int gotone;
320
321 if ( no_waitnextevent < 0 ) {
322 no_waitnextevent = (NGetTrapAddress(_WaitNextEvent, ToolTrap) ==
323 NGetTrapAddress(_Unimplemented, ToolTrap));
324 }
Jack Jansenf93c72a1994-12-14 14:07:50 +0000325
Jack Jansenee23d6e1995-01-27 14:43:25 +0000326 if ( !PyMac_DoYieldEnabled ) {
327#ifndef THINK_C
328 /* Under think this has been done before in intrcheck() or intrpeek() */
329 scan_event_queue(0);
330#endif
Jack Jansene8e8ae01995-01-26 16:36:45 +0000331 return;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000332 }
Jack Jansene8e8ae01995-01-26 16:36:45 +0000333
Jack Jansenee23d6e1995-01-27 14:43:25 +0000334 in_foreground = PyMac_InForeground();
335 if ( in_foreground )
Jack Jansene8e8ae01995-01-26 16:36:45 +0000336 yield = yield_fg;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000337 else
338 yield = yield_bg;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000339 while ( 1 ) {
340 if ( no_waitnextevent ) {
341 SystemTask();
Jack Jansenee23d6e1995-01-27 14:43:25 +0000342 gotone = GetNextEvent(MAINLOOP_EVENTMASK, &ev);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000343 } else {
Jack Jansenee23d6e1995-01-27 14:43:25 +0000344 gotone = WaitNextEvent(MAINLOOP_EVENTMASK, &ev, yield, NULL);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000345 }
346 /* Get out quickly if nothing interesting is happening */
347 if ( !gotone || ev.what == nullEvent )
348 break;
Jack Jansena76382a1995-02-02 14:25:56 +0000349 PyMac_HandleEvent(&ev);
Jack Jansenf93c72a1994-12-14 14:07:50 +0000350 }
Jack Jansene8e8ae01995-01-26 16:36:45 +0000351 lastyield = TickCount();
352}
353
354/*
355** Yield the CPU to other tasks if opportune
356*/
357void
358PyMac_Yield() {
359 long iv;
360
Jack Jansenee23d6e1995-01-27 14:43:25 +0000361 if ( in_foreground )
Jack Jansene8e8ae01995-01-26 16:36:45 +0000362 iv = interval_fg;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000363 else
364 iv = interval_bg;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000365 if ( TickCount() > lastyield + iv )
366 PyMac_DoYield();
367}
368
369/*
370** Idle routine for busy-wait loops.
371** Gives up CPU, handles events and returns true if an interrupt is pending
372** (but not actually handled yet).
373*/
374int
375PyMac_Idle()
376{
377 PyMac_DoYield();
378 return intrpeek();
Jack Jansenf93c72a1994-12-14 14:07:50 +0000379}
380
Jack Jansen8cd2b721995-02-13 11:33:28 +0000381/*
382** Return the name of the Python directory
383*/
384char *
385PyMac_GetPythonDir()
386{
387 int item;
388 static char name[256];
389 AliasHandle handle;
390 FSSpec dirspec;
391 int ok = 0, exists = 0;
Jack Jansen6cfab231995-02-13 22:46:00 +0000392 Boolean modified = 0, cannotmodify = 0;
Jack Jansen8cd2b721995-02-13 11:33:28 +0000393 StandardFileReply sfreply;
Jack Jansen6cfab231995-02-13 22:46:00 +0000394 short oldrh, prefrh;
395 short prefdirRefNum;
396 long prefdirDirID;
Jack Jansen8cd2b721995-02-13 11:33:28 +0000397
Jack Jansen6cfab231995-02-13 22:46:00 +0000398 /*
399 ** Remember old resource file and try to open preferences file
400 ** in the preferences folder. If it doesn't exist we try to create
401 ** it. If anything fails here we limp on, but set cannotmodify so
402 ** we don't try to store things later on.
403 */
404 oldrh = CurResFile();
405 if ( FindFolder(kOnSystemDisk, 'pref', kDontCreateFolder, &prefdirRefNum,
406 &prefdirDirID) != noErr ) {
407 /* Something wrong with preferences folder */
408 cannotmodify = 1;
409 } else {
410 (void)FSMakeFSSpec(prefdirRefNum, prefdirDirID, "\pPython Preferences", &dirspec);
411 prefrh = FSpOpenResFile(&dirspec, fsRdWrShPerm);
412 if ( prefrh == -1 ) {
413 /* It doesn't exist. Try to create it */
Guido van Rossumbecdbec1995-02-14 01:27:24 +0000414 FSpCreateResFile(&dirspec, 'PYTH', 'pref', 0);
Jack Jansen6cfab231995-02-13 22:46:00 +0000415 prefrh = FSpOpenResFile(&dirspec, fsRdWrShPerm);
416 if ( prefrh == -1 ) {
417 cannotmodify = 1;
418 } else {
419 UseResFile(prefrh);
420 }
421 }
422 }
423 /* So, we've opened our preferences file, we hope. Look for the alias */
424 handle = (AliasHandle)Get1Resource('alis', 128);
Jack Jansen8cd2b721995-02-13 11:33:28 +0000425 if ( handle ) {
Jack Jansen6cfab231995-02-13 22:46:00 +0000426 /* It exists. Resolve it (possibly updating it) */
Jack Jansen8cd2b721995-02-13 11:33:28 +0000427 if ( ResolveAlias(NULL, handle, &dirspec, &modified) == noErr )
428 ok = 1;
429 exists = 1;
430 }
431 if ( !ok ) {
Jack Jansen6cfab231995-02-13 22:46:00 +0000432 /* No luck, so far. ask the user for help */
Jack Jansen8cd2b721995-02-13 11:33:28 +0000433 item = Alert(NOPYTHON_ALERT, NULL);
434 if ( item == YES_ITEM ) {
Jack Jansen6cfab231995-02-13 22:46:00 +0000435 /* The user wants to point us to a directory. Let her do so */
Jack Jansen8cd2b721995-02-13 11:33:28 +0000436 StandardGetFile(NULL, 0, NULL, &sfreply);
437 if ( sfreply.sfGood ) {
438 if ( sfreply.sfIsFolder ) {
439 dirspec = sfreply.sfFile;
440 ok = 1;
441 modified = 1;
442 } else {
443 /* User selected a file. Use folder containing it */
444 if (FSMakeFSSpec(sfreply.sfFile.vRefNum,
445 sfreply.sfFile.parID, "\p", &dirspec) == 0) {
446 ok = 1;
447 modified = 1;
448 }
449 }
450 }
451 } else if ( item == CURWD_ITEM ) {
Jack Jansen6cfab231995-02-13 22:46:00 +0000452 /* The user told us the current directory is fine. Build an FSSpec for it */
Jack Jansen8cd2b721995-02-13 11:33:28 +0000453 if ( getwd(name) ) {
454 if ( FSMakeFSSpec(0, 0, Pstring(name), &dirspec) == 0 ) {
455 ok = 1;
456 modified = 1;
457 }
458 }
459 }
460 }
Jack Jansen6cfab231995-02-13 22:46:00 +0000461 if ( ok && modified && !cannotmodify) {
462 /* We have a new, valid fsspec and we can update the preferences file. Do so. */
Jack Jansen8cd2b721995-02-13 11:33:28 +0000463 if ( !exists ) {
464 if (NewAlias(NULL, &dirspec, &handle) == 0 )
465 AddResource((Handle)handle, 'alis', 128, "\p");
466 } else {
467 ChangedResource((Handle)handle);
468 }
Jack Jansen6cfab231995-02-13 22:46:00 +0000469 UpdateResFile(prefrh);
Jack Jansen8cd2b721995-02-13 11:33:28 +0000470 }
Jack Jansen6cfab231995-02-13 22:46:00 +0000471 if ( !cannotmodify ) {
472 /* This means we have the resfile open. Close it. */
473 CloseResFile(prefrh);
474 }
475 /* Back to the old resource file */
476 UseResFile(oldrh);
477 /* Now turn the fsspec into a path to give back to our caller */
Jack Jansen8cd2b721995-02-13 11:33:28 +0000478 if ( ok ) {
479 ok = (nfullpath(&dirspec, name) == 0);
480 if ( ok ) strcat(name, ":");
481 }
482 if ( !ok ) {
483 /* If all fails, we return the current directory */
484 name[0] = 0;
485 (void)getwd(name);
486 }
487 return name;
488}
489
Jack Jansen74162f31995-02-15 22:58:33 +0000490/*
491** Returns true if the argument has a resource fork, and it contains
492** a 'PYC ' resource of the correct name
493*/
494int
495PyMac_FindResourceModule(module, filename)
496char *module;
497char *filename;
498{
499 FSSpec fss;
500 FInfo finfo;
501 short oldrh, filerh;
502 int ok;
503 Handle h;
504
505 if ( FSMakeFSSpec(0, 0, Pstring(filename), &fss) != noErr )
506 return 0; /* It doesn't exist */
507 if ( FSpGetFInfo(&fss, &finfo) != noErr )
508 return 0; /* shouldn't happen, I guess */
Jack Jansen74162f31995-02-15 22:58:33 +0000509 oldrh = CurResFile();
510 filerh = FSpOpenResFile(&fss, fsRdPerm);
511 if ( filerh == -1 )
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000512 return 0;
Jack Jansen74162f31995-02-15 22:58:33 +0000513 UseResFile(filerh);
514 SetResLoad(0);
515 h = Get1NamedResource('PYC ', Pstring(module));
516 SetResLoad(1);
517 ok = (h != NULL);
518 CloseResFile(filerh);
519 UseResFile(oldrh);
520 return ok;
521}
522
523/*
524** Load the specified module from a resource
525*/
526PyObject *
527PyMac_LoadResourceModule(module, filename)
528char *module;
529char *filename;
530{
531 FSSpec fss;
532 FInfo finfo;
533 short oldrh, filerh;
534 int ok;
535 Handle h;
536 OSErr err;
537 PyObject *m, *co;
538 long num, size;
539
540 if ( (err=FSMakeFSSpec(0, 0, Pstring(filename), &fss)) != noErr )
541 goto error;
542 if ( (err=FSpGetFInfo(&fss, &finfo)) != noErr )
543 goto error;
Jack Jansen74162f31995-02-15 22:58:33 +0000544 oldrh = CurResFile();
545 filerh = FSpOpenResFile(&fss, fsRdPerm);
546 if ( filerh == -1 ) {
547 err = ResError();
548 goto error;
549 }
550 UseResFile(filerh);
551 h = Get1NamedResource('PYC ', Pstring(module));
552 if ( h == NULL ) {
553 err = ResError();
554 goto error;
555 }
556 HLock(h);
557 /*
558 ** XXXX The next few lines are intimately tied to the format of pyc
559 ** files. I'm not sure whether this code should be here or in import.c -- Jack
560 */
561 size = GetHandleSize(h);
562 if ( size < 8 ) {
563 PyErr_SetString(PyExc_ImportError, "Resource too small");
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000564 co = NULL;
Jack Jansen74162f31995-02-15 22:58:33 +0000565 } else {
566 num = (*h)[0] & 0xff;
567 num = num | (((*h)[1] & 0xff) << 8);
568 num = num | (((*h)[2] & 0xff) << 16);
569 num = num | (((*h)[3] & 0xff) << 24);
570 if ( num != PyImport_GetMagicNumber() ) {
571 PyErr_SetString(PyExc_ImportError, "Bad MAGIC in resource");
572 co = NULL;
573 } else {
574 co = PyMarshal_ReadObjectFromString((*h)+8, size-8);
575 }
576 }
577 HUnlock(h);
578 CloseResFile(filerh);
579 UseResFile(oldrh);
580 if ( co ) {
581 m = PyImport_ExecCodeModule(module, co);
582 Py_DECREF(co);
583 } else {
584 m = NULL;
585 }
586 return m;
587error:
588 {
589 char buf[512];
590
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000591 sprintf(buf, "%s: %s", filename, PyMac_StrError(err));
Jack Jansen74162f31995-02-15 22:58:33 +0000592 PyErr_SetString(PyExc_ImportError, buf);
593 return NULL;
594 }
595}
Jack Jansen5f653091995-01-18 13:53:49 +0000596
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000597/* Convert a 4-char string object argument to an OSType value */
Jack Jansen5f653091995-01-18 13:53:49 +0000598int
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000599PyMac_GetOSType(PyObject *v, OSType *pr)
Jack Jansen5f653091995-01-18 13:53:49 +0000600{
601 if (!PyString_Check(v) || PyString_Size(v) != 4) {
602 PyErr_SetString(PyExc_TypeError,
603 "OSType arg must be string of 4 chars");
604 return 0;
605 }
606 memcpy((char *)pr, PyString_AsString(v), 4);
607 return 1;
608}
609
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000610/* Convert an OSType value to a 4-char string object */
611PyObject *
612PyMac_BuildOSType(OSType t)
613{
614 return PyString_FromStringAndSize((char *)&t, 4);
615}
616
617
618/* Convert a Python string object to a Str255 */
Jack Jansen5f653091995-01-18 13:53:49 +0000619int
Guido van Rossum8f691791995-01-18 23:57:26 +0000620PyMac_GetStr255(PyObject *v, Str255 pbuf)
Jack Jansen5f653091995-01-18 13:53:49 +0000621{
622 int len;
623 if (!PyString_Check(v) || (len = PyString_Size(v)) > 255) {
624 PyErr_SetString(PyExc_TypeError,
625 "Str255 arg must be string of at most 255 chars");
626 return 0;
627 }
628 pbuf[0] = len;
629 memcpy((char *)(pbuf+1), PyString_AsString(v), len);
630 return 1;
631}
632
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000633/* Convert a Str255 to a Python string object */
634PyObject *
635PyMac_BuildStr255(Str255 s)
636{
637 return PyString_FromStringAndSize((char *)&s[1], (int)s[0]);
638}
639
640
Jack Jansen5f653091995-01-18 13:53:49 +0000641/*
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000642** Convert a Python object to an FSSpec.
643** The object may either be a full pathname or a triple
644** (vrefnum, dirid, path).
Jack Jansen5f653091995-01-18 13:53:49 +0000645** NOTE: This routine will fail on pre-sys7 machines.
646** The caller is responsible for not calling this routine
647** in those cases (which is fine, since everyone calling
648** this is probably sys7 dependent anyway).
649*/
650int
Guido van Rossum8f691791995-01-18 23:57:26 +0000651PyMac_GetFSSpec(PyObject *v, FSSpec *fs)
Jack Jansen5f653091995-01-18 13:53:49 +0000652{
653 Str255 path;
654 short refnum;
655 long parid;
656 OSErr err;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000657 FSSpec *fs2;
Jack Jansen5f653091995-01-18 13:53:49 +0000658
Jack Jansene8e8ae01995-01-26 16:36:45 +0000659 /* first check whether it already is an FSSpec */
660 fs2 = mfs_GetFSSpecFSSpec(v);
661 if ( fs2 ) {
662 fs = fs2;
663 return 1;
664 }
Jack Jansen5f653091995-01-18 13:53:49 +0000665 if ( PyString_Check(v) ) {
666 /* It's a pathname */
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000667 if( !PyArg_Parse(v, "O&", PyMac_GetStr255, &path) )
Jack Jansen5f653091995-01-18 13:53:49 +0000668 return 0;
669 refnum = 0; /* XXXX Should get CurWD here... */
670 parid = 0;
671 } else {
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000672 if( !PyArg_Parse(v, "(hlO&); FSSpec should be fullpath or (vrefnum,dirid,path)",
673 &refnum, &parid, PyMac_GetStr255, &path)) {
Jack Jansen5f653091995-01-18 13:53:49 +0000674 return 0;
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000675 }
Jack Jansen5f653091995-01-18 13:53:49 +0000676 }
677 err = FSMakeFSSpec(refnum, parid, path, fs);
678 if ( err && err != fnfErr ) {
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000679 PyErr_Mac(PyExc_ValueError, err);
Jack Jansen5f653091995-01-18 13:53:49 +0000680 return 0;
681 }
682 return 1;
683}
684
Guido van Rossum8f691791995-01-18 23:57:26 +0000685
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000686
687/* Convert a Python object to a Rect.
Guido van Rossum5279ec61995-01-26 22:56:59 +0000688 The object must be a (left, top, right, bottom) tuple.
689 (This differs from the order in the struct but is consistent with
690 the arguments to SetRect(), and also with STDWIN). */
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000691int
692PyMac_GetRect(PyObject *v, Rect *r)
Guido van Rossum8f691791995-01-18 23:57:26 +0000693{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000694 return PyArg_Parse(v, "(hhhh)", &r->left, &r->top, &r->right, &r->bottom);
Guido van Rossum8f691791995-01-18 23:57:26 +0000695}
Guido van Rossumb3404661995-01-22 18:36:13 +0000696
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000697/* Convert a Rect to a Python object */
Guido van Rossumb3404661995-01-22 18:36:13 +0000698PyObject *
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000699PyMac_BuildRect(Rect *r)
Guido van Rossumb3404661995-01-22 18:36:13 +0000700{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000701 return Py_BuildValue("(hhhh)", r->left, r->top, r->right, r->bottom);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000702}
703
704
705/* Convert a Python object to a Point.
Guido van Rossum5279ec61995-01-26 22:56:59 +0000706 The object must be a (h, v) tuple.
707 (This differs from the order in the struct but is consistent with
708 the arguments to SetPoint(), and also with STDWIN). */
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000709int
710PyMac_GetPoint(PyObject *v, Point *p)
711{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000712 return PyArg_Parse(v, "(hh)", &p->h, &p->v);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000713}
714
715/* Convert a Point to a Python object */
716PyObject *
717PyMac_BuildPoint(Point p)
718{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000719 return Py_BuildValue("(hh)", p.h, p.v);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000720}
721
722
723/* Convert a Python object to an EventRecord.
724 The object must be a (what, message, when, (v, h), modifiers) tuple. */
725int
726PyMac_GetEventRecord(PyObject *v, EventRecord *e)
727{
728 return PyArg_Parse(v, "(hll(hh)h)",
729 &e->what,
730 &e->message,
731 &e->when,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000732 &e->where.h,
Guido van Rossum5279ec61995-01-26 22:56:59 +0000733 &e->where.v,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000734 &e->modifiers);
735}
736
737/* Convert a Rect to an EventRecord object */
738PyObject *
739PyMac_BuildEventRecord(EventRecord *e)
740{
741 return Py_BuildValue("(hll(hh)h)",
742 e->what,
743 e->message,
744 e->when,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000745 e->where.h,
Guido van Rossum5279ec61995-01-26 22:56:59 +0000746 e->where.v,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000747 e->modifiers);
Guido van Rossumb3404661995-01-22 18:36:13 +0000748}
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000749
750
Guido van Rossum8c89a6f1995-02-19 15:52:17 +0000751/* ---------- */
752/* Applet support */
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000753
Guido van Rossum8c89a6f1995-02-19 15:52:17 +0000754/* Run a compiled Python Python script from 'PYC ' resource __main__ */
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000755static int
756run_main_resource()
757{
758 Handle h;
759 long size;
760 PyObject *code;
761 PyObject *result;
762
763 h = GetNamedResource('PYC ', "\p__main__");
764 if (h == NULL) {
765 fprintf(stderr, "No 'PYC ' resource named __main__ found\n");
766 return 1;
767 }
768 size = GetResourceSizeOnDisk(h);
769 HLock(h);
770 code = PyMarshal_ReadObjectFromString(*h + 8, (int)(size - 8));
771 HUnlock(h);
772 ReleaseResource(h);
773 if (code == NULL) {
774 PyErr_Print();
775 return 1;
776 }
777 result = PyImport_ExecCodeModule("__main__", code);
778 Py_DECREF(code);
779 if (result == NULL) {
780 PyErr_Print();
781 return 1;
782 }
783 Py_DECREF(result);
784 return 0;
785}
786
Guido van Rossum8c89a6f1995-02-19 15:52:17 +0000787/* Initialization sequence for applets */
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000788void
789PyMac_InitApplet()
790{
Guido van Rossum8c89a6f1995-02-19 15:52:17 +0000791 int argc;
792 char **argv;
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000793
Guido van Rossum8c89a6f1995-02-19 15:52:17 +0000794 argc = PyMac_GetArgv(&argv);
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000795 Py_Initialize();
Guido van Rossum8c89a6f1995-02-19 15:52:17 +0000796 PySys_SetArgv(argc, argv);
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000797 run_main_resource();
798 fflush(stderr);
799 fflush(stdout);
800 /* XXX Should we bother to Py_Exit(sts)? */
801}