blob: 7af6e132df18f49caf5eacb3648e0c833ec609cb [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__
158/*
159** There is no SpinCursor for cfm68k.
160*/
161SpinCursor(dummy)
162int dummy;
163{
164}
165#endif
Jack Jansen378815c1996-03-06 16:21:34 +0000166#endif
167
Jack Jansen819f1771995-08-14 12:35:10 +0000168
Jack Jansen5f653091995-01-18 13:53:49 +0000169/* Convert C to Pascal string. Returns pointer to static buffer. */
170unsigned char *
171Pstring(char *str)
172{
173 static Str255 buf;
174 int len;
175
176 len = strlen(str);
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000177 if (len > 255)
178 len = 255;
Jack Jansen5f653091995-01-18 13:53:49 +0000179 buf[0] = (unsigned char)len;
180 strncpy((char *)buf+1, str, len);
181 return buf;
182}
183
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000184/* Like strerror() but for Mac OS error numbers */
185char *PyMac_StrError(int err)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000186{
187 static char buf[256];
188 Handle h;
189 char *str;
190
191 h = GetResource('Estr', err);
192 if ( h ) {
193 HLock(h);
194 str = (char *)*h;
195 memcpy(buf, str+1, (unsigned char)str[0]);
Guido van Rossumcc9bc8f1995-02-13 16:17:03 +0000196 buf[(unsigned char)str[0]] = '\0';
Jack Jansenf93c72a1994-12-14 14:07:50 +0000197 HUnlock(h);
198 ReleaseResource(h);
199 } else {
200 sprintf(buf, "Mac OS error code %d", err);
201 }
202 return buf;
203}
204
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000205/* Exception object shared by all Mac specific modules for Mac OS errors */
206PyObject *PyMac_OSErrException;
207
208/* Initialize and return PyMac_OSErrException */
209PyObject *
210PyMac_GetOSErrException()
211{
212 if (PyMac_OSErrException == NULL)
213 PyMac_OSErrException = PyString_FromString("Mac OS Error");
214 return PyMac_OSErrException;
215}
216
Jack Jansenf93c72a1994-12-14 14:07:50 +0000217/* Set a MAC-specific error from errno, and return NULL; return None if no error */
218PyObject *
Guido van Rossumfffb8bb1995-01-12 12:37:24 +0000219PyErr_Mac(PyObject *eobj, int err)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000220{
221 char *msg;
222 PyObject *v;
Jack Jansenf93c72a1994-12-14 14:07:50 +0000223
Guido van Rossum8f691791995-01-18 23:57:26 +0000224 if (err == 0 && !PyErr_Occurred()) {
Jack Jansenf93c72a1994-12-14 14:07:50 +0000225 Py_INCREF(Py_None);
226 return Py_None;
227 }
Guido van Rossum8f691791995-01-18 23:57:26 +0000228 if (err == -1 && PyErr_Occurred())
229 return NULL;
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000230 msg = PyMac_StrError(err);
Jack Jansenf93c72a1994-12-14 14:07:50 +0000231 v = Py_BuildValue("(is)", err, msg);
232 PyErr_SetObject(eobj, v);
233 Py_DECREF(v);
234 return NULL;
235}
236
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000237/* Call PyErr_Mac with PyMac_OSErrException */
238PyObject *
239PyMac_Error(OSErr err)
240{
241 return PyErr_Mac(PyMac_GetOSErrException(), err);
242}
243
Jack Jansen1ed95291996-07-22 15:25:10 +0000244#ifdef USE_STACKCHECK
245/* Check for stack overflow */
246int
247PyOS_CheckStack()
248{
249 long left;
250
251 left = StackSpace();
Jack Jansend1f06311996-08-01 15:23:54 +0000252 if ( left < MINIMUM_STACK_SIZE )
Jack Jansen1ed95291996-07-22 15:25:10 +0000253 return -1;
254 return 0;
255}
256#endif /* USE_STACKCHECK */
257
Jack Jansenee23d6e1995-01-27 14:43:25 +0000258/* The catcher routine (which may not be used for all compilers) */
259static RETSIGTYPE
260intcatcher(sig)
261 int sig;
262{
263 interrupted = 1;
264 signal(SIGINT, intcatcher);
265}
266
267void
268PyOS_InitInterrupts()
269{
270 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
271 signal(SIGINT, intcatcher);
272}
273
274/*
275** This routine scans the event queue looking for cmd-.
276** This is the only way to get an interrupt under THINK (since it
277** doesn't do SIGINT handling), but is also used under MW, when
278** the full-fledged event loop is disabled. This way, we can at least
279** interrupt a runaway python program.
280*/
281static void
282scan_event_queue(flush)
283 int flush;
284{
Jack Jansenf74f63a1995-06-27 13:18:14 +0000285#if defined(__MWERKS__) && defined(__CFM68K__)
286 return; /* No GetEvQHdr yet */
287#else
Jack Jansenee23d6e1995-01-27 14:43:25 +0000288 register EvQElPtr q;
289
290 q = (EvQElPtr) GetEvQHdr()->qHead;
291
292 for (; q; q = (EvQElPtr)q->qLink) {
293 if (q->evtQWhat == keyDown &&
294 (char)q->evtQMessage == '.' &&
295 (q->evtQModifiers & cmdKey) != 0) {
296 if ( flush )
297 FlushEvents(keyDownMask, 0);
298 interrupted = 1;
299 break;
300 }
301 }
Jack Jansenf74f63a1995-06-27 13:18:14 +0000302#endif
Jack Jansenee23d6e1995-01-27 14:43:25 +0000303}
304
305int
306PyOS_InterruptOccurred()
307{
Guido van Rossume7134aa1995-02-26 10:20:53 +0000308 if (PyMac_DoYieldEnabled < 0)
309 return 0;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000310#ifdef THINK_C
311 scan_event_queue(1);
312#endif
313 PyMac_Yield();
314 if (interrupted) {
315 interrupted = 0;
316 return 1;
317 }
318 return 0;
319}
320
321/* intrpeek() is like intrcheck(), but it doesn't flush the events. The
322** idea is that you call intrpeek() somewhere in a busy-wait loop, and return
323** None as soon as it returns 1. The mainloop will then pick up the cmd-. soon
324** thereafter.
325*/
326static int
327intrpeek()
328{
329#ifdef THINK_C
330 scan_event_queue(0);
331#endif
332 return interrupted;
333}
334
335/* Check whether we are in the foreground */
336int
337PyMac_InForeground()
338{
339 static ProcessSerialNumber ours;
340 static inited;
341 ProcessSerialNumber curfg;
342 Boolean eq;
343
344 if ( inited == 0 )
345 (void)GetCurrentProcess(&ours);
346 inited = 1;
347 if ( GetFrontProcess(&curfg) < 0 )
348 eq = 1;
349 else if ( SameProcess(&ours, &curfg, &eq) < 0 )
350 eq = 1;
351 return (int)eq;
352
353}
354
Jack Jansenf93c72a1994-12-14 14:07:50 +0000355/*
Jack Jansene8e8ae01995-01-26 16:36:45 +0000356** Set yield timeouts
Jack Jansenf93c72a1994-12-14 14:07:50 +0000357*/
Jack Jansene8e8ae01995-01-26 16:36:45 +0000358void
359PyMac_SetYield(long fgi, long fgy, long bgi, long bgy)
360{
361 interval_fg = fgi;
362 yield_fg = fgy;
363 interval_bg = bgi;
364 yield_bg = bgy;
365}
366
367/*
Jack Jansena76382a1995-02-02 14:25:56 +0000368** Handle an event, either one found in the mainloop eventhandler or
369** one passed back from the python program.
370*/
371void
372PyMac_HandleEvent(evp)
373 EventRecord *evp;
374{
Jack Jansena76382a1995-02-02 14:25:56 +0000375
376#ifdef __MWERKS__
Jack Jansen38e97661995-11-10 14:53:00 +0000377 {
378 int siouxdidit;
379
380 /* If SIOUX wants it we're done */
381 siouxdidit = SIOUXHandleOneEvent(evp);
382 if ( siouxdidit )
383 return;
384 }
Jack Jansena76382a1995-02-02 14:25:56 +0000385#else
386 /* Other compilers are just unlucky: we only weed out clicks in other applications */
387 if ( evp->what == mouseDown ) {
Jack Jansen847e89e1995-08-31 13:57:40 +0000388 WindowPtr wp;
389
Jack Jansen38e97661995-11-10 14:53:00 +0000390 if ( FindWindow(evp->where, &wp) == inSysWindow ) {
Jack Jansena76382a1995-02-02 14:25:56 +0000391 SystemClick(evp, wp);
Jack Jansen38e97661995-11-10 14:53:00 +0000392 return;
393 }
Jack Jansena76382a1995-02-02 14:25:56 +0000394 }
395#endif /* !__MWERKS__ */
396}
397
398/*
Jack Jansene8e8ae01995-01-26 16:36:45 +0000399** Yield the CPU to other tasks.
400*/
401static
402PyMac_DoYield()
Jack Jansenf93c72a1994-12-14 14:07:50 +0000403{
404 EventRecord ev;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000405 long yield;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000406 static int no_waitnextevent = -1;
407 int gotone;
408
409 if ( no_waitnextevent < 0 ) {
410 no_waitnextevent = (NGetTrapAddress(_WaitNextEvent, ToolTrap) ==
411 NGetTrapAddress(_Unimplemented, ToolTrap));
412 }
Jack Jansenf93c72a1994-12-14 14:07:50 +0000413
Jack Jansenee23d6e1995-01-27 14:43:25 +0000414 if ( !PyMac_DoYieldEnabled ) {
415#ifndef THINK_C
416 /* Under think this has been done before in intrcheck() or intrpeek() */
417 scan_event_queue(0);
418#endif
Jack Jansene8e8ae01995-01-26 16:36:45 +0000419 return;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000420 }
Jack Jansene8e8ae01995-01-26 16:36:45 +0000421
Jack Jansenee23d6e1995-01-27 14:43:25 +0000422 in_foreground = PyMac_InForeground();
423 if ( in_foreground )
Jack Jansene8e8ae01995-01-26 16:36:45 +0000424 yield = yield_fg;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000425 else
426 yield = yield_bg;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000427 while ( 1 ) {
428 if ( no_waitnextevent ) {
429 SystemTask();
Jack Jansenee23d6e1995-01-27 14:43:25 +0000430 gotone = GetNextEvent(MAINLOOP_EVENTMASK, &ev);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000431 } else {
Jack Jansenee23d6e1995-01-27 14:43:25 +0000432 gotone = WaitNextEvent(MAINLOOP_EVENTMASK, &ev, yield, NULL);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000433 }
434 /* Get out quickly if nothing interesting is happening */
435 if ( !gotone || ev.what == nullEvent )
436 break;
Jack Jansena76382a1995-02-02 14:25:56 +0000437 PyMac_HandleEvent(&ev);
Jack Jansenf93c72a1994-12-14 14:07:50 +0000438 }
Jack Jansene8e8ae01995-01-26 16:36:45 +0000439 lastyield = TickCount();
440}
441
442/*
443** Yield the CPU to other tasks if opportune
444*/
445void
446PyMac_Yield() {
447 long iv;
448
Jack Jansenee23d6e1995-01-27 14:43:25 +0000449 if ( in_foreground )
Jack Jansene8e8ae01995-01-26 16:36:45 +0000450 iv = interval_fg;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000451 else
452 iv = interval_bg;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000453 if ( TickCount() > lastyield + iv )
454 PyMac_DoYield();
455}
456
457/*
458** Idle routine for busy-wait loops.
459** Gives up CPU, handles events and returns true if an interrupt is pending
460** (but not actually handled yet).
461*/
462int
463PyMac_Idle()
464{
465 PyMac_DoYield();
466 return intrpeek();
Jack Jansenf93c72a1994-12-14 14:07:50 +0000467}
Jack Jansen74162f31995-02-15 22:58:33 +0000468/*
469** Returns true if the argument has a resource fork, and it contains
470** a 'PYC ' resource of the correct name
471*/
472int
473PyMac_FindResourceModule(module, filename)
474char *module;
475char *filename;
476{
477 FSSpec fss;
478 FInfo finfo;
479 short oldrh, filerh;
480 int ok;
481 Handle h;
482
483 if ( FSMakeFSSpec(0, 0, Pstring(filename), &fss) != noErr )
484 return 0; /* It doesn't exist */
485 if ( FSpGetFInfo(&fss, &finfo) != noErr )
486 return 0; /* shouldn't happen, I guess */
Jack Jansen74162f31995-02-15 22:58:33 +0000487 oldrh = CurResFile();
488 filerh = FSpOpenResFile(&fss, fsRdPerm);
489 if ( filerh == -1 )
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000490 return 0;
Jack Jansen74162f31995-02-15 22:58:33 +0000491 UseResFile(filerh);
492 SetResLoad(0);
493 h = Get1NamedResource('PYC ', Pstring(module));
494 SetResLoad(1);
495 ok = (h != NULL);
496 CloseResFile(filerh);
497 UseResFile(oldrh);
498 return ok;
499}
500
501/*
502** Load the specified module from a resource
503*/
504PyObject *
505PyMac_LoadResourceModule(module, filename)
506char *module;
507char *filename;
508{
509 FSSpec fss;
510 FInfo finfo;
511 short oldrh, filerh;
Jack Jansen74162f31995-02-15 22:58:33 +0000512 Handle h;
513 OSErr err;
514 PyObject *m, *co;
515 long num, size;
516
517 if ( (err=FSMakeFSSpec(0, 0, Pstring(filename), &fss)) != noErr )
518 goto error;
519 if ( (err=FSpGetFInfo(&fss, &finfo)) != noErr )
520 goto error;
Jack Jansen74162f31995-02-15 22:58:33 +0000521 oldrh = CurResFile();
522 filerh = FSpOpenResFile(&fss, fsRdPerm);
523 if ( filerh == -1 ) {
524 err = ResError();
525 goto error;
526 }
527 UseResFile(filerh);
528 h = Get1NamedResource('PYC ', Pstring(module));
529 if ( h == NULL ) {
530 err = ResError();
531 goto error;
532 }
533 HLock(h);
534 /*
535 ** XXXX The next few lines are intimately tied to the format of pyc
536 ** files. I'm not sure whether this code should be here or in import.c -- Jack
537 */
538 size = GetHandleSize(h);
539 if ( size < 8 ) {
540 PyErr_SetString(PyExc_ImportError, "Resource too small");
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000541 co = NULL;
Jack Jansen74162f31995-02-15 22:58:33 +0000542 } else {
543 num = (*h)[0] & 0xff;
544 num = num | (((*h)[1] & 0xff) << 8);
545 num = num | (((*h)[2] & 0xff) << 16);
546 num = num | (((*h)[3] & 0xff) << 24);
547 if ( num != PyImport_GetMagicNumber() ) {
548 PyErr_SetString(PyExc_ImportError, "Bad MAGIC in resource");
549 co = NULL;
550 } else {
551 co = PyMarshal_ReadObjectFromString((*h)+8, size-8);
552 }
553 }
554 HUnlock(h);
555 CloseResFile(filerh);
556 UseResFile(oldrh);
557 if ( co ) {
558 m = PyImport_ExecCodeModule(module, co);
559 Py_DECREF(co);
560 } else {
561 m = NULL;
562 }
563 return m;
564error:
565 {
566 char buf[512];
567
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000568 sprintf(buf, "%s: %s", filename, PyMac_StrError(err));
Jack Jansen74162f31995-02-15 22:58:33 +0000569 PyErr_SetString(PyExc_ImportError, buf);
570 return NULL;
571 }
572}
Guido van Rossum24a45e31995-02-20 23:45:53 +0000573
Jack Jansen3ec804a1995-02-20 15:56:10 +0000574/*
575** Helper routine for GetDirectory
576*/
Guido van Rossum24a45e31995-02-20 23:45:53 +0000577static pascal short
Jack Jansen819f1771995-08-14 12:35:10 +0000578myhook_proc(short item, DialogPtr theDialog, struct hook_args *dataptr)
Jack Jansen3ec804a1995-02-20 15:56:10 +0000579{
Jack Jansen819f1771995-08-14 12:35:10 +0000580 if ( item == sfHookFirstCall && dataptr->prompt) {
581 Handle prompth;
582 short type;
583 Rect rect;
584
585 GetDialogItem(theDialog, PROMPT_ITEM, &type, &prompth, &rect);
586 if ( prompth )
587 SetDialogItemText(prompth, (unsigned char *)dataptr->prompt);
588 } else
Jack Jansen3ec804a1995-02-20 15:56:10 +0000589 if ( item == SELECTCUR_ITEM ) {
590 item = sfItemCancelButton;
Jack Jansen819f1771995-08-14 12:35:10 +0000591 dataptr->selectcur_hit = 1;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000592 }
593 return item;
594}
595
596/*
597** Ask the user for a directory. I still can't understand
598** why Apple doesn't provide a standard solution for this...
599*/
600int
Jack Jansen819f1771995-08-14 12:35:10 +0000601PyMac_GetDirectory(dirfss, prompt)
Jack Jansen3ec804a1995-02-20 15:56:10 +0000602 FSSpec *dirfss;
Jack Jansen819f1771995-08-14 12:35:10 +0000603 char *prompt;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000604{
605 static SFTypeList list = {'fldr', 0, 0, 0};
606 static Point where = {-1, -1};
Jack Jansen3ec804a1995-02-20 15:56:10 +0000607 StandardFileReply reply;
Jack Jansen819f1771995-08-14 12:35:10 +0000608 struct hook_args hook_args;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000609
610 if ( !upp_inited ) {
611 myhook_upp = NewDlgHookYDProc(myhook_proc);
612 upp_inited = 1;
613 }
Jack Jansen819f1771995-08-14 12:35:10 +0000614 if ( prompt && *prompt )
615 hook_args.prompt = (char *)Pstring(prompt);
616 else
617 hook_args.prompt = NULL;
618 hook_args.selectcur_hit = 0;
Guido van Rossum24a45e31995-02-20 23:45:53 +0000619 CustomGetFile((FileFilterYDUPP)0, 1, list, &reply, GETDIR_ID, where, myhook_upp,
Jack Jansen819f1771995-08-14 12:35:10 +0000620 NULL, NULL, NULL, (void *)&hook_args);
Jack Jansen3ec804a1995-02-20 15:56:10 +0000621
622 reply.sfFile.name[0] = 0;
623 if( FSMakeFSSpec(reply.sfFile.vRefNum, reply.sfFile.parID, reply.sfFile.name, dirfss) )
624 return 0;
Jack Jansen819f1771995-08-14 12:35:10 +0000625 return hook_args.selectcur_hit;
626}
627
628/*
629** Slightly extended StandardGetFile: accepts a prompt */
630void PyMac_PromptGetFile(short numTypes, ConstSFTypeListPtr typeList,
631 StandardFileReply *reply, char *prompt)
632{
633 static Point where = {-1, -1};
634 struct hook_args hook_args;
635
636 if ( !upp_inited ) {
637 myhook_upp = NewDlgHookYDProc(myhook_proc);
638 upp_inited = 1;
639 }
640 if ( prompt && *prompt )
641 hook_args.prompt = (char *)Pstring(prompt);
642 else
643 hook_args.prompt = NULL;
644 hook_args.selectcur_hit = 0;
645 CustomGetFile((FileFilterYDUPP)0, numTypes, typeList, reply, GETFILEPROMPT_ID, where,
646 myhook_upp, NULL, NULL, NULL, (void *)&hook_args);
Jack Jansen3ec804a1995-02-20 15:56:10 +0000647}
Jack Jansen5f653091995-01-18 13:53:49 +0000648
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000649/* Convert a 4-char string object argument to an OSType value */
Jack Jansen5f653091995-01-18 13:53:49 +0000650int
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000651PyMac_GetOSType(PyObject *v, OSType *pr)
Jack Jansen5f653091995-01-18 13:53:49 +0000652{
653 if (!PyString_Check(v) || PyString_Size(v) != 4) {
654 PyErr_SetString(PyExc_TypeError,
655 "OSType arg must be string of 4 chars");
656 return 0;
657 }
658 memcpy((char *)pr, PyString_AsString(v), 4);
659 return 1;
660}
661
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000662/* Convert an OSType value to a 4-char string object */
663PyObject *
664PyMac_BuildOSType(OSType t)
665{
666 return PyString_FromStringAndSize((char *)&t, 4);
667}
668
Jack Jansend1f06311996-08-01 15:23:54 +0000669/* Convert an NumVersion value to a 4-element tuple */
670PyObject *
671PyMac_BuildNumVersion(NumVersion t)
672{
673 return Py_BuildValue("(hhhh)", t.majorRev, t.minorAndBugRev, t.stage, t.nonRelRev);
674}
675
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000676
677/* Convert a Python string object to a Str255 */
Jack Jansen5f653091995-01-18 13:53:49 +0000678int
Guido van Rossum8f691791995-01-18 23:57:26 +0000679PyMac_GetStr255(PyObject *v, Str255 pbuf)
Jack Jansen5f653091995-01-18 13:53:49 +0000680{
681 int len;
682 if (!PyString_Check(v) || (len = PyString_Size(v)) > 255) {
683 PyErr_SetString(PyExc_TypeError,
684 "Str255 arg must be string of at most 255 chars");
685 return 0;
686 }
687 pbuf[0] = len;
688 memcpy((char *)(pbuf+1), PyString_AsString(v), len);
689 return 1;
690}
691
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000692/* Convert a Str255 to a Python string object */
693PyObject *
694PyMac_BuildStr255(Str255 s)
695{
696 return PyString_FromStringAndSize((char *)&s[1], (int)s[0]);
697}
698
699
Jack Jansen5f653091995-01-18 13:53:49 +0000700/*
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000701** Convert a Python object to an FSSpec.
702** The object may either be a full pathname or a triple
703** (vrefnum, dirid, path).
Jack Jansen5f653091995-01-18 13:53:49 +0000704** NOTE: This routine will fail on pre-sys7 machines.
705** The caller is responsible for not calling this routine
706** in those cases (which is fine, since everyone calling
707** this is probably sys7 dependent anyway).
708*/
709int
Guido van Rossum8f691791995-01-18 23:57:26 +0000710PyMac_GetFSSpec(PyObject *v, FSSpec *fs)
Jack Jansen5f653091995-01-18 13:53:49 +0000711{
712 Str255 path;
713 short refnum;
714 long parid;
715 OSErr err;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000716 FSSpec *fs2;
Jack Jansen5f653091995-01-18 13:53:49 +0000717
Jack Jansene8e8ae01995-01-26 16:36:45 +0000718 /* first check whether it already is an FSSpec */
719 fs2 = mfs_GetFSSpecFSSpec(v);
720 if ( fs2 ) {
Jack Jansen3ec804a1995-02-20 15:56:10 +0000721 (void)FSMakeFSSpec(fs2->vRefNum, fs2->parID, fs2->name, fs);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000722 return 1;
723 }
Jack Jansen5f653091995-01-18 13:53:49 +0000724 if ( PyString_Check(v) ) {
725 /* It's a pathname */
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000726 if( !PyArg_Parse(v, "O&", PyMac_GetStr255, &path) )
Jack Jansen5f653091995-01-18 13:53:49 +0000727 return 0;
Jack Jansen378815c1996-03-06 16:21:34 +0000728 refnum = 0; /* XXXX Should get CurWD here?? */
Jack Jansen5f653091995-01-18 13:53:49 +0000729 parid = 0;
730 } else {
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000731 if( !PyArg_Parse(v, "(hlO&); FSSpec should be fullpath or (vrefnum,dirid,path)",
732 &refnum, &parid, PyMac_GetStr255, &path)) {
Jack Jansen5f653091995-01-18 13:53:49 +0000733 return 0;
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000734 }
Jack Jansen5f653091995-01-18 13:53:49 +0000735 }
736 err = FSMakeFSSpec(refnum, parid, path, fs);
737 if ( err && err != fnfErr ) {
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000738 PyErr_Mac(PyExc_ValueError, err);
Jack Jansen5f653091995-01-18 13:53:49 +0000739 return 0;
740 }
741 return 1;
742}
743
Guido van Rossum8f691791995-01-18 23:57:26 +0000744
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000745/* Convert a Python object to a Rect.
Guido van Rossum5279ec61995-01-26 22:56:59 +0000746 The object must be a (left, top, right, bottom) tuple.
747 (This differs from the order in the struct but is consistent with
748 the arguments to SetRect(), and also with STDWIN). */
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000749int
750PyMac_GetRect(PyObject *v, Rect *r)
Guido van Rossum8f691791995-01-18 23:57:26 +0000751{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000752 return PyArg_Parse(v, "(hhhh)", &r->left, &r->top, &r->right, &r->bottom);
Guido van Rossum8f691791995-01-18 23:57:26 +0000753}
Guido van Rossumb3404661995-01-22 18:36:13 +0000754
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000755/* Convert a Rect to a Python object */
Guido van Rossumb3404661995-01-22 18:36:13 +0000756PyObject *
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000757PyMac_BuildRect(Rect *r)
Guido van Rossumb3404661995-01-22 18:36:13 +0000758{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000759 return Py_BuildValue("(hhhh)", r->left, r->top, r->right, r->bottom);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000760}
761
762
763/* Convert a Python object to a Point.
Guido van Rossum5279ec61995-01-26 22:56:59 +0000764 The object must be a (h, v) tuple.
765 (This differs from the order in the struct but is consistent with
766 the arguments to SetPoint(), and also with STDWIN). */
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000767int
768PyMac_GetPoint(PyObject *v, Point *p)
769{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000770 return PyArg_Parse(v, "(hh)", &p->h, &p->v);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000771}
772
773/* Convert a Point to a Python object */
774PyObject *
775PyMac_BuildPoint(Point p)
776{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000777 return Py_BuildValue("(hh)", p.h, p.v);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000778}
779
780
781/* Convert a Python object to an EventRecord.
782 The object must be a (what, message, when, (v, h), modifiers) tuple. */
783int
784PyMac_GetEventRecord(PyObject *v, EventRecord *e)
785{
786 return PyArg_Parse(v, "(hll(hh)h)",
787 &e->what,
788 &e->message,
789 &e->when,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000790 &e->where.h,
Guido van Rossum5279ec61995-01-26 22:56:59 +0000791 &e->where.v,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000792 &e->modifiers);
793}
794
795/* Convert a Rect to an EventRecord object */
796PyObject *
797PyMac_BuildEventRecord(EventRecord *e)
798{
799 return Py_BuildValue("(hll(hh)h)",
800 e->what,
801 e->message,
802 e->when,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000803 e->where.h,
Guido van Rossum5279ec61995-01-26 22:56:59 +0000804 e->where.v,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000805 e->modifiers);
Guido van Rossumb3404661995-01-22 18:36:13 +0000806}
Jack Jansenfa4d5d01995-11-15 15:19:29 +0000807
808/* Convert Python object to Fixed */
809int
810PyMac_GetFixed(PyObject *v, Fixed *f)
811{
812 double d;
813
814 if( !PyArg_Parse(v, "d", &d))
815 return 0;
816 *f = (Fixed)(d * 0x10000);
Jack Jansen31dd5c01996-05-31 13:01:39 +0000817 return 1;
Jack Jansenfa4d5d01995-11-15 15:19:29 +0000818}
819
820/* Convert a Point to a Python object */
821PyObject *
822PyMac_BuildFixed(Fixed f)
823{
824 double d;
825
826 d = f;
827 d = d / 0x10000;
828 return Py_BuildValue("d", d);
829}
830