blob: 2c8951ad86ec87e53d07edec856f996fa0cdba33 [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
Jack Jansen819f1771995-08-14 12:35:10 +000031#include "pythonresources.h"
32
Jack Jansenf93c72a1994-12-14 14:07:50 +000033#include <OSUtils.h> /* for Set(Current)A5 */
Jack Jansene8e8ae01995-01-26 16:36:45 +000034#include <Files.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>
Jack Jansen08305501995-06-18 20:03:40 +000045#include <TextUtils.h>
Guido van Rossumcc0d8791995-01-30 08:57:13 +000046#ifdef THINK_C
47#include <OSEvents.h> /* For EvQElPtr */
48#endif
Jack Jansen16df2aa1995-02-27 16:17:28 +000049#ifdef __MWERKS__
50#include <SIOUX.h>
51#endif
Jack Jansen911ad6b1996-03-05 16:56:24 +000052#ifdef USE_GUSI
53#include <TFileSpec.h> /* For Path2FSSpec */
Jack Jansen378815c1996-03-06 16:21:34 +000054#include <LowMem.h> /* For SetSFCurDir, etc */
Jack Jansen911ad6b1996-03-05 16:56:24 +000055#endif
Jack Jansenee23d6e1995-01-27 14:43:25 +000056
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +000057#ifndef HAVE_UNIVERSAL_HEADERS
58#define GetResourceSizeOnDisk(x) SizeResource(x)
Guido van Rossum24a45e31995-02-20 23:45:53 +000059typedef DlgHookYDProcPtr DlgHookYDUPP;
60#define NewDlgHookYDProc(userRoutine) ((DlgHookYDUPP) (userRoutine))
61typedef FileFilterYDProcPtr FileFilterYDUPP;
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +000062#endif
63
Jack Jansenee23d6e1995-01-27 14:43:25 +000064#include <signal.h>
Jack Jansen74162f31995-02-15 22:58:33 +000065#include <stdio.h>
Jack Jansene8e8ae01995-01-26 16:36:45 +000066
Jack Jansenee23d6e1995-01-27 14:43:25 +000067/*
Jack Jansend1f06311996-08-01 15:23:54 +000068** When less than this amount of stackspace is left we
69** raise a MemoryError.
70*/
71#ifndef MINIMUM_STACK_SIZE
72#ifdef __powerc
73#define MINIMUM_STACK_SIZE 8192
74#else
75#define MINIMUM_STACK_SIZE 4096
76#endif
77#endif
78
79/*
Jack Jansen16df2aa1995-02-27 16:17:28 +000080** We have to be careful, since we can't handle
Jack Jansenee23d6e1995-01-27 14:43:25 +000081** things like updates (and they'll keep coming back if we don't
Jack Jansen16df2aa1995-02-27 16:17:28 +000082** handle them). Note that we don't know who has windows open, so
83** even handing updates off to SIOUX under MW isn't going to work.
Jack Jansenee23d6e1995-01-27 14:43:25 +000084*/
85#define MAINLOOP_EVENTMASK (mDownMask|keyDownMask|osMask)
Jack Jansene8e8ae01995-01-26 16:36:45 +000086
87#include <signal.h>
Jack Jansenf93c72a1994-12-14 14:07:50 +000088
Guido van Rossumb3404661995-01-22 18:36:13 +000089/* XXX We should include Errors.h here, but it has a name conflict
Jack Jansen5f653091995-01-18 13:53:49 +000090** with the python errors.h. */
91#define fnfErr -43
92
Jack Jansene8e8ae01995-01-26 16:36:45 +000093/* Declared in macfsmodule.c: */
94extern FSSpec *mfs_GetFSSpecFSSpec();
95
Jack Jansenee23d6e1995-01-27 14:43:25 +000096/* Interrupt code variables: */
97static int interrupted; /* Set to true when cmd-. seen */
98static RETSIGTYPE intcatcher Py_PROTO((int));
99
Jack Jansene8e8ae01995-01-26 16:36:45 +0000100/*
101** We attempt to be a good citizen by giving up the CPU periodically.
102** When in the foreground we do this less often and for shorter periods
103** than when in the background. At this time we also check for events and
Jack Jansenee23d6e1995-01-27 14:43:25 +0000104** pass them off to SIOUX, if compiling with mwerks.
Jack Jansene8e8ae01995-01-26 16:36:45 +0000105** The counts here are in ticks of 1/60th second.
106** XXXX The initial values here are not based on anything.
107** FG-python gives up the cpu for 1/60th 5 times per second,
108** BG-python for .2 second 10 times per second.
109*/
110static long interval_fg = 12;
111static long interval_bg = 6;
112static long yield_fg = 1;
113static long yield_bg = 12;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000114static long lastyield;
115static int in_foreground;
116
Guido van Rossume7134aa1995-02-26 10:20:53 +0000117/*
118** When > 0, do full scanning for events (program is not event aware)
119** when == 0, only scan for Command-period
120** when < 0, don't do any event scanning
121*/
122int PyMac_DoYieldEnabled = 1;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000123
Jack Jansen819f1771995-08-14 12:35:10 +0000124/*
125** Some stuff for our GetDirectory and PromptGetFile routines
126*/
127struct hook_args {
128 int selectcur_hit; /* Set to true when "select current" selected */
129 char *prompt; /* The prompt */
130};
131static DlgHookYDUPP myhook_upp;
132static int upp_inited = 0;
133
Jack Jansen378815c1996-03-06 16:21:34 +0000134#ifdef USE_GUSI
135/*
136** GUSI (1.6.0 and earlier, at the least) do not set the MacOS idea of
137** the working directory. Hence, we call this routine after each call
138** to chdir() to rectify things.
139*/
140void
141PyMac_FixGUSIcd()
142{
143 WDPBRec pb;
144 FSSpec curdirfss;
145
146 if ( Path2FSSpec(":x", &curdirfss) != noErr )
147 return;
148
149 /* Set MacOS "working directory" */
150 pb.ioNamePtr= "\p";
151 pb.ioVRefNum= curdirfss.vRefNum;
152 pb.ioWDDirID= curdirfss.parID;
153 if (PBHSetVol(&pb, 0) != noErr)
154 return;
Jack Jansen378815c1996-03-06 16:21:34 +0000155}
Jack Jansen7ac70af1996-08-19 11:01:05 +0000156
157#ifdef __CFM68K__
Jack Jansencfadbd41996-08-19 11:36:25 +0000158void SpinCursor(short x) { /* Dummy */ }
159#endif /* __CFM68K */
160
Jack Jansen378815c1996-03-06 16:21:34 +0000161#endif
162
Jack Jansen819f1771995-08-14 12:35:10 +0000163
Jack Jansen5f653091995-01-18 13:53:49 +0000164/* Convert C to Pascal string. Returns pointer to static buffer. */
165unsigned char *
166Pstring(char *str)
167{
168 static Str255 buf;
169 int len;
170
171 len = strlen(str);
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000172 if (len > 255)
173 len = 255;
Jack Jansen5f653091995-01-18 13:53:49 +0000174 buf[0] = (unsigned char)len;
175 strncpy((char *)buf+1, str, len);
176 return buf;
177}
178
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000179/* Like strerror() but for Mac OS error numbers */
180char *PyMac_StrError(int err)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000181{
182 static char buf[256];
183 Handle h;
184 char *str;
185
186 h = GetResource('Estr', err);
187 if ( h ) {
188 HLock(h);
189 str = (char *)*h;
190 memcpy(buf, str+1, (unsigned char)str[0]);
Guido van Rossumcc9bc8f1995-02-13 16:17:03 +0000191 buf[(unsigned char)str[0]] = '\0';
Jack Jansenf93c72a1994-12-14 14:07:50 +0000192 HUnlock(h);
193 ReleaseResource(h);
194 } else {
195 sprintf(buf, "Mac OS error code %d", err);
196 }
197 return buf;
198}
199
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000200/* Exception object shared by all Mac specific modules for Mac OS errors */
201PyObject *PyMac_OSErrException;
202
203/* Initialize and return PyMac_OSErrException */
204PyObject *
205PyMac_GetOSErrException()
206{
207 if (PyMac_OSErrException == NULL)
208 PyMac_OSErrException = PyString_FromString("Mac OS Error");
209 return PyMac_OSErrException;
210}
211
Jack Jansenf93c72a1994-12-14 14:07:50 +0000212/* Set a MAC-specific error from errno, and return NULL; return None if no error */
213PyObject *
Guido van Rossumfffb8bb1995-01-12 12:37:24 +0000214PyErr_Mac(PyObject *eobj, int err)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000215{
216 char *msg;
217 PyObject *v;
Jack Jansenf93c72a1994-12-14 14:07:50 +0000218
Guido van Rossum8f691791995-01-18 23:57:26 +0000219 if (err == 0 && !PyErr_Occurred()) {
Jack Jansenf93c72a1994-12-14 14:07:50 +0000220 Py_INCREF(Py_None);
221 return Py_None;
222 }
Guido van Rossum8f691791995-01-18 23:57:26 +0000223 if (err == -1 && PyErr_Occurred())
224 return NULL;
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000225 msg = PyMac_StrError(err);
Jack Jansenf93c72a1994-12-14 14:07:50 +0000226 v = Py_BuildValue("(is)", err, msg);
227 PyErr_SetObject(eobj, v);
228 Py_DECREF(v);
229 return NULL;
230}
231
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000232/* Call PyErr_Mac with PyMac_OSErrException */
233PyObject *
234PyMac_Error(OSErr err)
235{
236 return PyErr_Mac(PyMac_GetOSErrException(), err);
237}
238
Jack Jansen1ed95291996-07-22 15:25:10 +0000239#ifdef USE_STACKCHECK
240/* Check for stack overflow */
241int
242PyOS_CheckStack()
243{
244 long left;
245
246 left = StackSpace();
Jack Jansend1f06311996-08-01 15:23:54 +0000247 if ( left < MINIMUM_STACK_SIZE )
Jack Jansen1ed95291996-07-22 15:25:10 +0000248 return -1;
249 return 0;
250}
251#endif /* USE_STACKCHECK */
252
Jack Jansenee23d6e1995-01-27 14:43:25 +0000253/* The catcher routine (which may not be used for all compilers) */
254static RETSIGTYPE
255intcatcher(sig)
256 int sig;
257{
258 interrupted = 1;
259 signal(SIGINT, intcatcher);
260}
261
262void
263PyOS_InitInterrupts()
264{
265 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
266 signal(SIGINT, intcatcher);
267}
268
269/*
270** This routine scans the event queue looking for cmd-.
271** This is the only way to get an interrupt under THINK (since it
272** doesn't do SIGINT handling), but is also used under MW, when
273** the full-fledged event loop is disabled. This way, we can at least
274** interrupt a runaway python program.
275*/
276static void
277scan_event_queue(flush)
278 int flush;
279{
280 register EvQElPtr q;
281
Jack Jansencfadbd41996-08-19 11:36:25 +0000282 q = (EvQElPtr) GetEventQueue()->qHead;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000283
284 for (; q; q = (EvQElPtr)q->qLink) {
285 if (q->evtQWhat == keyDown &&
286 (char)q->evtQMessage == '.' &&
287 (q->evtQModifiers & cmdKey) != 0) {
288 if ( flush )
289 FlushEvents(keyDownMask, 0);
290 interrupted = 1;
291 break;
292 }
293 }
294}
295
296int
297PyOS_InterruptOccurred()
298{
Guido van Rossume7134aa1995-02-26 10:20:53 +0000299 if (PyMac_DoYieldEnabled < 0)
300 return 0;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000301#ifdef THINK_C
302 scan_event_queue(1);
303#endif
304 PyMac_Yield();
305 if (interrupted) {
306 interrupted = 0;
307 return 1;
308 }
309 return 0;
310}
311
312/* intrpeek() is like intrcheck(), but it doesn't flush the events. The
313** idea is that you call intrpeek() somewhere in a busy-wait loop, and return
314** None as soon as it returns 1. The mainloop will then pick up the cmd-. soon
315** thereafter.
316*/
317static int
318intrpeek()
319{
320#ifdef THINK_C
321 scan_event_queue(0);
322#endif
323 return interrupted;
324}
325
326/* Check whether we are in the foreground */
327int
328PyMac_InForeground()
329{
330 static ProcessSerialNumber ours;
331 static inited;
332 ProcessSerialNumber curfg;
333 Boolean eq;
334
335 if ( inited == 0 )
336 (void)GetCurrentProcess(&ours);
337 inited = 1;
338 if ( GetFrontProcess(&curfg) < 0 )
339 eq = 1;
340 else if ( SameProcess(&ours, &curfg, &eq) < 0 )
341 eq = 1;
342 return (int)eq;
343
344}
345
Jack Jansenf93c72a1994-12-14 14:07:50 +0000346/*
Jack Jansene8e8ae01995-01-26 16:36:45 +0000347** Set yield timeouts
Jack Jansenf93c72a1994-12-14 14:07:50 +0000348*/
Jack Jansene8e8ae01995-01-26 16:36:45 +0000349void
350PyMac_SetYield(long fgi, long fgy, long bgi, long bgy)
351{
352 interval_fg = fgi;
353 yield_fg = fgy;
354 interval_bg = bgi;
355 yield_bg = bgy;
356}
357
358/*
Jack Jansena76382a1995-02-02 14:25:56 +0000359** Handle an event, either one found in the mainloop eventhandler or
360** one passed back from the python program.
361*/
362void
363PyMac_HandleEvent(evp)
364 EventRecord *evp;
365{
Jack Jansena76382a1995-02-02 14:25:56 +0000366
367#ifdef __MWERKS__
Jack Jansen38e97661995-11-10 14:53:00 +0000368 {
369 int siouxdidit;
370
371 /* If SIOUX wants it we're done */
372 siouxdidit = SIOUXHandleOneEvent(evp);
373 if ( siouxdidit )
374 return;
375 }
Jack Jansena76382a1995-02-02 14:25:56 +0000376#else
377 /* Other compilers are just unlucky: we only weed out clicks in other applications */
378 if ( evp->what == mouseDown ) {
Jack Jansen847e89e1995-08-31 13:57:40 +0000379 WindowPtr wp;
380
Jack Jansen38e97661995-11-10 14:53:00 +0000381 if ( FindWindow(evp->where, &wp) == inSysWindow ) {
Jack Jansena76382a1995-02-02 14:25:56 +0000382 SystemClick(evp, wp);
Jack Jansen38e97661995-11-10 14:53:00 +0000383 return;
384 }
Jack Jansena76382a1995-02-02 14:25:56 +0000385 }
386#endif /* !__MWERKS__ */
387}
388
389/*
Jack Jansene8e8ae01995-01-26 16:36:45 +0000390** Yield the CPU to other tasks.
391*/
Jack Jansencfadbd41996-08-19 11:36:25 +0000392static void
Jack Jansene8e8ae01995-01-26 16:36:45 +0000393PyMac_DoYield()
Jack Jansenf93c72a1994-12-14 14:07:50 +0000394{
395 EventRecord ev;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000396 long yield;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000397 static int no_waitnextevent = -1;
398 int gotone;
399
400 if ( no_waitnextevent < 0 ) {
401 no_waitnextevent = (NGetTrapAddress(_WaitNextEvent, ToolTrap) ==
402 NGetTrapAddress(_Unimplemented, ToolTrap));
403 }
Jack Jansenf93c72a1994-12-14 14:07:50 +0000404
Jack Jansenee23d6e1995-01-27 14:43:25 +0000405 if ( !PyMac_DoYieldEnabled ) {
406#ifndef THINK_C
407 /* Under think this has been done before in intrcheck() or intrpeek() */
408 scan_event_queue(0);
409#endif
Jack Jansene8e8ae01995-01-26 16:36:45 +0000410 return;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000411 }
Jack Jansene8e8ae01995-01-26 16:36:45 +0000412
Jack Jansenee23d6e1995-01-27 14:43:25 +0000413 in_foreground = PyMac_InForeground();
414 if ( in_foreground )
Jack Jansene8e8ae01995-01-26 16:36:45 +0000415 yield = yield_fg;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000416 else
417 yield = yield_bg;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000418 while ( 1 ) {
419 if ( no_waitnextevent ) {
420 SystemTask();
Jack Jansenee23d6e1995-01-27 14:43:25 +0000421 gotone = GetNextEvent(MAINLOOP_EVENTMASK, &ev);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000422 } else {
Jack Jansenee23d6e1995-01-27 14:43:25 +0000423 gotone = WaitNextEvent(MAINLOOP_EVENTMASK, &ev, yield, NULL);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000424 }
425 /* Get out quickly if nothing interesting is happening */
426 if ( !gotone || ev.what == nullEvent )
427 break;
Jack Jansena76382a1995-02-02 14:25:56 +0000428 PyMac_HandleEvent(&ev);
Jack Jansenf93c72a1994-12-14 14:07:50 +0000429 }
Jack Jansene8e8ae01995-01-26 16:36:45 +0000430 lastyield = TickCount();
431}
432
433/*
434** Yield the CPU to other tasks if opportune
435*/
436void
437PyMac_Yield() {
438 long iv;
439
Jack Jansenee23d6e1995-01-27 14:43:25 +0000440 if ( in_foreground )
Jack Jansene8e8ae01995-01-26 16:36:45 +0000441 iv = interval_fg;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000442 else
443 iv = interval_bg;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000444 if ( TickCount() > lastyield + iv )
445 PyMac_DoYield();
446}
447
448/*
449** Idle routine for busy-wait loops.
450** Gives up CPU, handles events and returns true if an interrupt is pending
451** (but not actually handled yet).
452*/
453int
454PyMac_Idle()
455{
456 PyMac_DoYield();
457 return intrpeek();
Jack Jansenf93c72a1994-12-14 14:07:50 +0000458}
Jack Jansen74162f31995-02-15 22:58:33 +0000459/*
460** Returns true if the argument has a resource fork, and it contains
461** a 'PYC ' resource of the correct name
462*/
463int
464PyMac_FindResourceModule(module, filename)
465char *module;
466char *filename;
467{
468 FSSpec fss;
469 FInfo finfo;
470 short oldrh, filerh;
471 int ok;
472 Handle h;
473
474 if ( FSMakeFSSpec(0, 0, Pstring(filename), &fss) != noErr )
475 return 0; /* It doesn't exist */
476 if ( FSpGetFInfo(&fss, &finfo) != noErr )
477 return 0; /* shouldn't happen, I guess */
Jack Jansen74162f31995-02-15 22:58:33 +0000478 oldrh = CurResFile();
479 filerh = FSpOpenResFile(&fss, fsRdPerm);
480 if ( filerh == -1 )
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000481 return 0;
Jack Jansen74162f31995-02-15 22:58:33 +0000482 UseResFile(filerh);
483 SetResLoad(0);
484 h = Get1NamedResource('PYC ', Pstring(module));
485 SetResLoad(1);
486 ok = (h != NULL);
487 CloseResFile(filerh);
488 UseResFile(oldrh);
489 return ok;
490}
491
492/*
493** Load the specified module from a resource
494*/
495PyObject *
496PyMac_LoadResourceModule(module, filename)
497char *module;
498char *filename;
499{
500 FSSpec fss;
501 FInfo finfo;
502 short oldrh, filerh;
Jack Jansen74162f31995-02-15 22:58:33 +0000503 Handle h;
504 OSErr err;
505 PyObject *m, *co;
506 long num, size;
507
508 if ( (err=FSMakeFSSpec(0, 0, Pstring(filename), &fss)) != noErr )
509 goto error;
510 if ( (err=FSpGetFInfo(&fss, &finfo)) != noErr )
511 goto error;
Jack Jansen74162f31995-02-15 22:58:33 +0000512 oldrh = CurResFile();
513 filerh = FSpOpenResFile(&fss, fsRdPerm);
514 if ( filerh == -1 ) {
515 err = ResError();
516 goto error;
517 }
518 UseResFile(filerh);
519 h = Get1NamedResource('PYC ', Pstring(module));
520 if ( h == NULL ) {
521 err = ResError();
522 goto error;
523 }
524 HLock(h);
525 /*
526 ** XXXX The next few lines are intimately tied to the format of pyc
527 ** files. I'm not sure whether this code should be here or in import.c -- Jack
528 */
529 size = GetHandleSize(h);
530 if ( size < 8 ) {
531 PyErr_SetString(PyExc_ImportError, "Resource too small");
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000532 co = NULL;
Jack Jansen74162f31995-02-15 22:58:33 +0000533 } else {
534 num = (*h)[0] & 0xff;
535 num = num | (((*h)[1] & 0xff) << 8);
536 num = num | (((*h)[2] & 0xff) << 16);
537 num = num | (((*h)[3] & 0xff) << 24);
538 if ( num != PyImport_GetMagicNumber() ) {
539 PyErr_SetString(PyExc_ImportError, "Bad MAGIC in resource");
540 co = NULL;
541 } else {
542 co = PyMarshal_ReadObjectFromString((*h)+8, size-8);
543 }
544 }
545 HUnlock(h);
546 CloseResFile(filerh);
547 UseResFile(oldrh);
548 if ( co ) {
549 m = PyImport_ExecCodeModule(module, co);
550 Py_DECREF(co);
551 } else {
552 m = NULL;
553 }
554 return m;
555error:
556 {
557 char buf[512];
558
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000559 sprintf(buf, "%s: %s", filename, PyMac_StrError(err));
Jack Jansen74162f31995-02-15 22:58:33 +0000560 PyErr_SetString(PyExc_ImportError, buf);
561 return NULL;
562 }
563}
Guido van Rossum24a45e31995-02-20 23:45:53 +0000564
Jack Jansen3ec804a1995-02-20 15:56:10 +0000565/*
566** Helper routine for GetDirectory
567*/
Guido van Rossum24a45e31995-02-20 23:45:53 +0000568static pascal short
Jack Jansen819f1771995-08-14 12:35:10 +0000569myhook_proc(short item, DialogPtr theDialog, struct hook_args *dataptr)
Jack Jansen3ec804a1995-02-20 15:56:10 +0000570{
Jack Jansen819f1771995-08-14 12:35:10 +0000571 if ( item == sfHookFirstCall && dataptr->prompt) {
572 Handle prompth;
573 short type;
574 Rect rect;
575
576 GetDialogItem(theDialog, PROMPT_ITEM, &type, &prompth, &rect);
577 if ( prompth )
578 SetDialogItemText(prompth, (unsigned char *)dataptr->prompt);
579 } else
Jack Jansen3ec804a1995-02-20 15:56:10 +0000580 if ( item == SELECTCUR_ITEM ) {
581 item = sfItemCancelButton;
Jack Jansen819f1771995-08-14 12:35:10 +0000582 dataptr->selectcur_hit = 1;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000583 }
584 return item;
585}
586
587/*
588** Ask the user for a directory. I still can't understand
589** why Apple doesn't provide a standard solution for this...
590*/
591int
Jack Jansen819f1771995-08-14 12:35:10 +0000592PyMac_GetDirectory(dirfss, prompt)
Jack Jansen3ec804a1995-02-20 15:56:10 +0000593 FSSpec *dirfss;
Jack Jansen819f1771995-08-14 12:35:10 +0000594 char *prompt;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000595{
596 static SFTypeList list = {'fldr', 0, 0, 0};
597 static Point where = {-1, -1};
Jack Jansen3ec804a1995-02-20 15:56:10 +0000598 StandardFileReply reply;
Jack Jansen819f1771995-08-14 12:35:10 +0000599 struct hook_args hook_args;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000600
601 if ( !upp_inited ) {
602 myhook_upp = NewDlgHookYDProc(myhook_proc);
603 upp_inited = 1;
604 }
Jack Jansen819f1771995-08-14 12:35:10 +0000605 if ( prompt && *prompt )
606 hook_args.prompt = (char *)Pstring(prompt);
607 else
608 hook_args.prompt = NULL;
609 hook_args.selectcur_hit = 0;
Guido van Rossum24a45e31995-02-20 23:45:53 +0000610 CustomGetFile((FileFilterYDUPP)0, 1, list, &reply, GETDIR_ID, where, myhook_upp,
Jack Jansen819f1771995-08-14 12:35:10 +0000611 NULL, NULL, NULL, (void *)&hook_args);
Jack Jansen3ec804a1995-02-20 15:56:10 +0000612
613 reply.sfFile.name[0] = 0;
614 if( FSMakeFSSpec(reply.sfFile.vRefNum, reply.sfFile.parID, reply.sfFile.name, dirfss) )
615 return 0;
Jack Jansen819f1771995-08-14 12:35:10 +0000616 return hook_args.selectcur_hit;
617}
618
619/*
620** Slightly extended StandardGetFile: accepts a prompt */
621void PyMac_PromptGetFile(short numTypes, ConstSFTypeListPtr typeList,
622 StandardFileReply *reply, char *prompt)
623{
624 static Point where = {-1, -1};
625 struct hook_args hook_args;
626
627 if ( !upp_inited ) {
628 myhook_upp = NewDlgHookYDProc(myhook_proc);
629 upp_inited = 1;
630 }
631 if ( prompt && *prompt )
632 hook_args.prompt = (char *)Pstring(prompt);
633 else
634 hook_args.prompt = NULL;
635 hook_args.selectcur_hit = 0;
636 CustomGetFile((FileFilterYDUPP)0, numTypes, typeList, reply, GETFILEPROMPT_ID, where,
637 myhook_upp, NULL, NULL, NULL, (void *)&hook_args);
Jack Jansen3ec804a1995-02-20 15:56:10 +0000638}
Jack Jansen5f653091995-01-18 13:53:49 +0000639
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000640/* Convert a 4-char string object argument to an OSType value */
Jack Jansen5f653091995-01-18 13:53:49 +0000641int
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000642PyMac_GetOSType(PyObject *v, OSType *pr)
Jack Jansen5f653091995-01-18 13:53:49 +0000643{
644 if (!PyString_Check(v) || PyString_Size(v) != 4) {
645 PyErr_SetString(PyExc_TypeError,
646 "OSType arg must be string of 4 chars");
647 return 0;
648 }
649 memcpy((char *)pr, PyString_AsString(v), 4);
650 return 1;
651}
652
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000653/* Convert an OSType value to a 4-char string object */
654PyObject *
655PyMac_BuildOSType(OSType t)
656{
657 return PyString_FromStringAndSize((char *)&t, 4);
658}
659
Jack Jansend1f06311996-08-01 15:23:54 +0000660/* Convert an NumVersion value to a 4-element tuple */
661PyObject *
662PyMac_BuildNumVersion(NumVersion t)
663{
664 return Py_BuildValue("(hhhh)", t.majorRev, t.minorAndBugRev, t.stage, t.nonRelRev);
665}
666
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000667
668/* Convert a Python string object to a Str255 */
Jack Jansen5f653091995-01-18 13:53:49 +0000669int
Guido van Rossum8f691791995-01-18 23:57:26 +0000670PyMac_GetStr255(PyObject *v, Str255 pbuf)
Jack Jansen5f653091995-01-18 13:53:49 +0000671{
672 int len;
673 if (!PyString_Check(v) || (len = PyString_Size(v)) > 255) {
674 PyErr_SetString(PyExc_TypeError,
675 "Str255 arg must be string of at most 255 chars");
676 return 0;
677 }
678 pbuf[0] = len;
679 memcpy((char *)(pbuf+1), PyString_AsString(v), len);
680 return 1;
681}
682
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000683/* Convert a Str255 to a Python string object */
684PyObject *
685PyMac_BuildStr255(Str255 s)
686{
687 return PyString_FromStringAndSize((char *)&s[1], (int)s[0]);
688}
689
690
Jack Jansen5f653091995-01-18 13:53:49 +0000691/*
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000692** Convert a Python object to an FSSpec.
693** The object may either be a full pathname or a triple
694** (vrefnum, dirid, path).
Jack Jansen5f653091995-01-18 13:53:49 +0000695** NOTE: This routine will fail on pre-sys7 machines.
696** The caller is responsible for not calling this routine
697** in those cases (which is fine, since everyone calling
698** this is probably sys7 dependent anyway).
699*/
700int
Guido van Rossum8f691791995-01-18 23:57:26 +0000701PyMac_GetFSSpec(PyObject *v, FSSpec *fs)
Jack Jansen5f653091995-01-18 13:53:49 +0000702{
703 Str255 path;
704 short refnum;
705 long parid;
706 OSErr err;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000707 FSSpec *fs2;
Jack Jansen5f653091995-01-18 13:53:49 +0000708
Jack Jansene8e8ae01995-01-26 16:36:45 +0000709 /* first check whether it already is an FSSpec */
710 fs2 = mfs_GetFSSpecFSSpec(v);
711 if ( fs2 ) {
Jack Jansen3ec804a1995-02-20 15:56:10 +0000712 (void)FSMakeFSSpec(fs2->vRefNum, fs2->parID, fs2->name, fs);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000713 return 1;
714 }
Jack Jansen5f653091995-01-18 13:53:49 +0000715 if ( PyString_Check(v) ) {
716 /* It's a pathname */
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000717 if( !PyArg_Parse(v, "O&", PyMac_GetStr255, &path) )
Jack Jansen5f653091995-01-18 13:53:49 +0000718 return 0;
Jack Jansen378815c1996-03-06 16:21:34 +0000719 refnum = 0; /* XXXX Should get CurWD here?? */
Jack Jansen5f653091995-01-18 13:53:49 +0000720 parid = 0;
721 } else {
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000722 if( !PyArg_Parse(v, "(hlO&); FSSpec should be fullpath or (vrefnum,dirid,path)",
723 &refnum, &parid, PyMac_GetStr255, &path)) {
Jack Jansen5f653091995-01-18 13:53:49 +0000724 return 0;
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000725 }
Jack Jansen5f653091995-01-18 13:53:49 +0000726 }
727 err = FSMakeFSSpec(refnum, parid, path, fs);
728 if ( err && err != fnfErr ) {
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000729 PyErr_Mac(PyExc_ValueError, err);
Jack Jansen5f653091995-01-18 13:53:49 +0000730 return 0;
731 }
732 return 1;
733}
734
Guido van Rossum8f691791995-01-18 23:57:26 +0000735
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000736/* Convert a Python object to a Rect.
Guido van Rossum5279ec61995-01-26 22:56:59 +0000737 The object must be a (left, top, right, bottom) tuple.
738 (This differs from the order in the struct but is consistent with
739 the arguments to SetRect(), and also with STDWIN). */
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000740int
741PyMac_GetRect(PyObject *v, Rect *r)
Guido van Rossum8f691791995-01-18 23:57:26 +0000742{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000743 return PyArg_Parse(v, "(hhhh)", &r->left, &r->top, &r->right, &r->bottom);
Guido van Rossum8f691791995-01-18 23:57:26 +0000744}
Guido van Rossumb3404661995-01-22 18:36:13 +0000745
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000746/* Convert a Rect to a Python object */
Guido van Rossumb3404661995-01-22 18:36:13 +0000747PyObject *
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000748PyMac_BuildRect(Rect *r)
Guido van Rossumb3404661995-01-22 18:36:13 +0000749{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000750 return Py_BuildValue("(hhhh)", r->left, r->top, r->right, r->bottom);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000751}
752
753
754/* Convert a Python object to a Point.
Guido van Rossum5279ec61995-01-26 22:56:59 +0000755 The object must be a (h, v) tuple.
756 (This differs from the order in the struct but is consistent with
757 the arguments to SetPoint(), and also with STDWIN). */
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000758int
759PyMac_GetPoint(PyObject *v, Point *p)
760{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000761 return PyArg_Parse(v, "(hh)", &p->h, &p->v);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000762}
763
764/* Convert a Point to a Python object */
765PyObject *
766PyMac_BuildPoint(Point p)
767{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000768 return Py_BuildValue("(hh)", p.h, p.v);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000769}
770
771
772/* Convert a Python object to an EventRecord.
773 The object must be a (what, message, when, (v, h), modifiers) tuple. */
774int
775PyMac_GetEventRecord(PyObject *v, EventRecord *e)
776{
777 return PyArg_Parse(v, "(hll(hh)h)",
778 &e->what,
779 &e->message,
780 &e->when,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000781 &e->where.h,
Guido van Rossum5279ec61995-01-26 22:56:59 +0000782 &e->where.v,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000783 &e->modifiers);
784}
785
786/* Convert a Rect to an EventRecord object */
787PyObject *
788PyMac_BuildEventRecord(EventRecord *e)
789{
790 return Py_BuildValue("(hll(hh)h)",
791 e->what,
792 e->message,
793 e->when,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000794 e->where.h,
Guido van Rossum5279ec61995-01-26 22:56:59 +0000795 e->where.v,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000796 e->modifiers);
Guido van Rossumb3404661995-01-22 18:36:13 +0000797}
Jack Jansenfa4d5d01995-11-15 15:19:29 +0000798
799/* Convert Python object to Fixed */
800int
801PyMac_GetFixed(PyObject *v, Fixed *f)
802{
803 double d;
804
805 if( !PyArg_Parse(v, "d", &d))
806 return 0;
807 *f = (Fixed)(d * 0x10000);
Jack Jansen31dd5c01996-05-31 13:01:39 +0000808 return 1;
Jack Jansenfa4d5d01995-11-15 15:19:29 +0000809}
810
811/* Convert a Point to a Python object */
812PyObject *
813PyMac_BuildFixed(Fixed f)
814{
815 double d;
816
817 d = f;
818 d = d / 0x10000;
819 return Py_BuildValue("d", d);
820}
821