blob: e6739b532b5ac97c7afd96a6ee1de677b8d30737 [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}
156#endif
157
Jack Jansen819f1771995-08-14 12:35:10 +0000158
Jack Jansen5f653091995-01-18 13:53:49 +0000159/* Convert C to Pascal string. Returns pointer to static buffer. */
160unsigned char *
161Pstring(char *str)
162{
163 static Str255 buf;
164 int len;
165
166 len = strlen(str);
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000167 if (len > 255)
168 len = 255;
Jack Jansen5f653091995-01-18 13:53:49 +0000169 buf[0] = (unsigned char)len;
170 strncpy((char *)buf+1, str, len);
171 return buf;
172}
173
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000174/* Like strerror() but for Mac OS error numbers */
175char *PyMac_StrError(int err)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000176{
177 static char buf[256];
178 Handle h;
179 char *str;
180
181 h = GetResource('Estr', err);
182 if ( h ) {
183 HLock(h);
184 str = (char *)*h;
185 memcpy(buf, str+1, (unsigned char)str[0]);
Guido van Rossumcc9bc8f1995-02-13 16:17:03 +0000186 buf[(unsigned char)str[0]] = '\0';
Jack Jansenf93c72a1994-12-14 14:07:50 +0000187 HUnlock(h);
188 ReleaseResource(h);
189 } else {
190 sprintf(buf, "Mac OS error code %d", err);
191 }
192 return buf;
193}
194
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000195/* Exception object shared by all Mac specific modules for Mac OS errors */
196PyObject *PyMac_OSErrException;
197
198/* Initialize and return PyMac_OSErrException */
199PyObject *
200PyMac_GetOSErrException()
201{
202 if (PyMac_OSErrException == NULL)
203 PyMac_OSErrException = PyString_FromString("Mac OS Error");
204 return PyMac_OSErrException;
205}
206
Jack Jansenf93c72a1994-12-14 14:07:50 +0000207/* Set a MAC-specific error from errno, and return NULL; return None if no error */
208PyObject *
Guido van Rossumfffb8bb1995-01-12 12:37:24 +0000209PyErr_Mac(PyObject *eobj, int err)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000210{
211 char *msg;
212 PyObject *v;
Jack Jansenf93c72a1994-12-14 14:07:50 +0000213
Guido van Rossum8f691791995-01-18 23:57:26 +0000214 if (err == 0 && !PyErr_Occurred()) {
Jack Jansenf93c72a1994-12-14 14:07:50 +0000215 Py_INCREF(Py_None);
216 return Py_None;
217 }
Guido van Rossum8f691791995-01-18 23:57:26 +0000218 if (err == -1 && PyErr_Occurred())
219 return NULL;
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000220 msg = PyMac_StrError(err);
Jack Jansenf93c72a1994-12-14 14:07:50 +0000221 v = Py_BuildValue("(is)", err, msg);
222 PyErr_SetObject(eobj, v);
223 Py_DECREF(v);
224 return NULL;
225}
226
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000227/* Call PyErr_Mac with PyMac_OSErrException */
228PyObject *
229PyMac_Error(OSErr err)
230{
231 return PyErr_Mac(PyMac_GetOSErrException(), err);
232}
233
Jack Jansen1ed95291996-07-22 15:25:10 +0000234#ifdef USE_STACKCHECK
235/* Check for stack overflow */
236int
237PyOS_CheckStack()
238{
239 long left;
240
241 left = StackSpace();
Jack Jansend1f06311996-08-01 15:23:54 +0000242 if ( left < MINIMUM_STACK_SIZE )
Jack Jansen1ed95291996-07-22 15:25:10 +0000243 return -1;
244 return 0;
245}
246#endif /* USE_STACKCHECK */
247
Jack Jansenee23d6e1995-01-27 14:43:25 +0000248/* The catcher routine (which may not be used for all compilers) */
249static RETSIGTYPE
250intcatcher(sig)
251 int sig;
252{
253 interrupted = 1;
254 signal(SIGINT, intcatcher);
255}
256
257void
258PyOS_InitInterrupts()
259{
260 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
261 signal(SIGINT, intcatcher);
262}
263
264/*
265** This routine scans the event queue looking for cmd-.
266** This is the only way to get an interrupt under THINK (since it
267** doesn't do SIGINT handling), but is also used under MW, when
268** the full-fledged event loop is disabled. This way, we can at least
269** interrupt a runaway python program.
270*/
271static void
272scan_event_queue(flush)
273 int flush;
274{
Jack Jansenf74f63a1995-06-27 13:18:14 +0000275#if defined(__MWERKS__) && defined(__CFM68K__)
276 return; /* No GetEvQHdr yet */
277#else
Jack Jansenee23d6e1995-01-27 14:43:25 +0000278 register EvQElPtr q;
279
280 q = (EvQElPtr) GetEvQHdr()->qHead;
281
282 for (; q; q = (EvQElPtr)q->qLink) {
283 if (q->evtQWhat == keyDown &&
284 (char)q->evtQMessage == '.' &&
285 (q->evtQModifiers & cmdKey) != 0) {
286 if ( flush )
287 FlushEvents(keyDownMask, 0);
288 interrupted = 1;
289 break;
290 }
291 }
Jack Jansenf74f63a1995-06-27 13:18:14 +0000292#endif
Jack Jansenee23d6e1995-01-27 14:43:25 +0000293}
294
295int
296PyOS_InterruptOccurred()
297{
Guido van Rossume7134aa1995-02-26 10:20:53 +0000298 if (PyMac_DoYieldEnabled < 0)
299 return 0;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000300#ifdef THINK_C
301 scan_event_queue(1);
302#endif
303 PyMac_Yield();
304 if (interrupted) {
305 interrupted = 0;
306 return 1;
307 }
308 return 0;
309}
310
311/* intrpeek() is like intrcheck(), but it doesn't flush the events. The
312** idea is that you call intrpeek() somewhere in a busy-wait loop, and return
313** None as soon as it returns 1. The mainloop will then pick up the cmd-. soon
314** thereafter.
315*/
316static int
317intrpeek()
318{
319#ifdef THINK_C
320 scan_event_queue(0);
321#endif
322 return interrupted;
323}
324
325/* Check whether we are in the foreground */
326int
327PyMac_InForeground()
328{
329 static ProcessSerialNumber ours;
330 static inited;
331 ProcessSerialNumber curfg;
332 Boolean eq;
333
334 if ( inited == 0 )
335 (void)GetCurrentProcess(&ours);
336 inited = 1;
337 if ( GetFrontProcess(&curfg) < 0 )
338 eq = 1;
339 else if ( SameProcess(&ours, &curfg, &eq) < 0 )
340 eq = 1;
341 return (int)eq;
342
343}
344
Jack Jansenf93c72a1994-12-14 14:07:50 +0000345/*
Jack Jansene8e8ae01995-01-26 16:36:45 +0000346** Set yield timeouts
Jack Jansenf93c72a1994-12-14 14:07:50 +0000347*/
Jack Jansene8e8ae01995-01-26 16:36:45 +0000348void
349PyMac_SetYield(long fgi, long fgy, long bgi, long bgy)
350{
351 interval_fg = fgi;
352 yield_fg = fgy;
353 interval_bg = bgi;
354 yield_bg = bgy;
355}
356
357/*
Jack Jansena76382a1995-02-02 14:25:56 +0000358** Handle an event, either one found in the mainloop eventhandler or
359** one passed back from the python program.
360*/
361void
362PyMac_HandleEvent(evp)
363 EventRecord *evp;
364{
Jack Jansena76382a1995-02-02 14:25:56 +0000365
366#ifdef __MWERKS__
Jack Jansen38e97661995-11-10 14:53:00 +0000367 {
368 int siouxdidit;
369
370 /* If SIOUX wants it we're done */
371 siouxdidit = SIOUXHandleOneEvent(evp);
372 if ( siouxdidit )
373 return;
374 }
Jack Jansena76382a1995-02-02 14:25:56 +0000375#else
376 /* Other compilers are just unlucky: we only weed out clicks in other applications */
377 if ( evp->what == mouseDown ) {
Jack Jansen847e89e1995-08-31 13:57:40 +0000378 WindowPtr wp;
379
Jack Jansen38e97661995-11-10 14:53:00 +0000380 if ( FindWindow(evp->where, &wp) == inSysWindow ) {
Jack Jansena76382a1995-02-02 14:25:56 +0000381 SystemClick(evp, wp);
Jack Jansen38e97661995-11-10 14:53:00 +0000382 return;
383 }
Jack Jansena76382a1995-02-02 14:25:56 +0000384 }
385#endif /* !__MWERKS__ */
386}
387
388/*
Jack Jansene8e8ae01995-01-26 16:36:45 +0000389** Yield the CPU to other tasks.
390*/
391static
392PyMac_DoYield()
Jack Jansenf93c72a1994-12-14 14:07:50 +0000393{
394 EventRecord ev;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000395 long yield;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000396 static int no_waitnextevent = -1;
397 int gotone;
398
399 if ( no_waitnextevent < 0 ) {
400 no_waitnextevent = (NGetTrapAddress(_WaitNextEvent, ToolTrap) ==
401 NGetTrapAddress(_Unimplemented, ToolTrap));
402 }
Jack Jansenf93c72a1994-12-14 14:07:50 +0000403
Jack Jansenee23d6e1995-01-27 14:43:25 +0000404 if ( !PyMac_DoYieldEnabled ) {
405#ifndef THINK_C
406 /* Under think this has been done before in intrcheck() or intrpeek() */
407 scan_event_queue(0);
408#endif
Jack Jansene8e8ae01995-01-26 16:36:45 +0000409 return;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000410 }
Jack Jansene8e8ae01995-01-26 16:36:45 +0000411
Jack Jansenee23d6e1995-01-27 14:43:25 +0000412 in_foreground = PyMac_InForeground();
413 if ( in_foreground )
Jack Jansene8e8ae01995-01-26 16:36:45 +0000414 yield = yield_fg;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000415 else
416 yield = yield_bg;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000417 while ( 1 ) {
418 if ( no_waitnextevent ) {
419 SystemTask();
Jack Jansenee23d6e1995-01-27 14:43:25 +0000420 gotone = GetNextEvent(MAINLOOP_EVENTMASK, &ev);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000421 } else {
Jack Jansenee23d6e1995-01-27 14:43:25 +0000422 gotone = WaitNextEvent(MAINLOOP_EVENTMASK, &ev, yield, NULL);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000423 }
424 /* Get out quickly if nothing interesting is happening */
425 if ( !gotone || ev.what == nullEvent )
426 break;
Jack Jansena76382a1995-02-02 14:25:56 +0000427 PyMac_HandleEvent(&ev);
Jack Jansenf93c72a1994-12-14 14:07:50 +0000428 }
Jack Jansene8e8ae01995-01-26 16:36:45 +0000429 lastyield = TickCount();
430}
431
432/*
433** Yield the CPU to other tasks if opportune
434*/
435void
436PyMac_Yield() {
437 long iv;
438
Jack Jansenee23d6e1995-01-27 14:43:25 +0000439 if ( in_foreground )
Jack Jansene8e8ae01995-01-26 16:36:45 +0000440 iv = interval_fg;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000441 else
442 iv = interval_bg;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000443 if ( TickCount() > lastyield + iv )
444 PyMac_DoYield();
445}
446
447/*
448** Idle routine for busy-wait loops.
449** Gives up CPU, handles events and returns true if an interrupt is pending
450** (but not actually handled yet).
451*/
452int
453PyMac_Idle()
454{
455 PyMac_DoYield();
456 return intrpeek();
Jack Jansenf93c72a1994-12-14 14:07:50 +0000457}
Jack Jansen74162f31995-02-15 22:58:33 +0000458/*
459** Returns true if the argument has a resource fork, and it contains
460** a 'PYC ' resource of the correct name
461*/
462int
463PyMac_FindResourceModule(module, filename)
464char *module;
465char *filename;
466{
467 FSSpec fss;
468 FInfo finfo;
469 short oldrh, filerh;
470 int ok;
471 Handle h;
472
473 if ( FSMakeFSSpec(0, 0, Pstring(filename), &fss) != noErr )
474 return 0; /* It doesn't exist */
475 if ( FSpGetFInfo(&fss, &finfo) != noErr )
476 return 0; /* shouldn't happen, I guess */
Jack Jansen74162f31995-02-15 22:58:33 +0000477 oldrh = CurResFile();
478 filerh = FSpOpenResFile(&fss, fsRdPerm);
479 if ( filerh == -1 )
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000480 return 0;
Jack Jansen74162f31995-02-15 22:58:33 +0000481 UseResFile(filerh);
482 SetResLoad(0);
483 h = Get1NamedResource('PYC ', Pstring(module));
484 SetResLoad(1);
485 ok = (h != NULL);
486 CloseResFile(filerh);
487 UseResFile(oldrh);
488 return ok;
489}
490
491/*
492** Load the specified module from a resource
493*/
494PyObject *
495PyMac_LoadResourceModule(module, filename)
496char *module;
497char *filename;
498{
499 FSSpec fss;
500 FInfo finfo;
501 short oldrh, filerh;
Jack Jansen74162f31995-02-15 22:58:33 +0000502 Handle h;
503 OSErr err;
504 PyObject *m, *co;
505 long num, size;
506
507 if ( (err=FSMakeFSSpec(0, 0, Pstring(filename), &fss)) != noErr )
508 goto error;
509 if ( (err=FSpGetFInfo(&fss, &finfo)) != noErr )
510 goto error;
Jack Jansen74162f31995-02-15 22:58:33 +0000511 oldrh = CurResFile();
512 filerh = FSpOpenResFile(&fss, fsRdPerm);
513 if ( filerh == -1 ) {
514 err = ResError();
515 goto error;
516 }
517 UseResFile(filerh);
518 h = Get1NamedResource('PYC ', Pstring(module));
519 if ( h == NULL ) {
520 err = ResError();
521 goto error;
522 }
523 HLock(h);
524 /*
525 ** XXXX The next few lines are intimately tied to the format of pyc
526 ** files. I'm not sure whether this code should be here or in import.c -- Jack
527 */
528 size = GetHandleSize(h);
529 if ( size < 8 ) {
530 PyErr_SetString(PyExc_ImportError, "Resource too small");
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000531 co = NULL;
Jack Jansen74162f31995-02-15 22:58:33 +0000532 } else {
533 num = (*h)[0] & 0xff;
534 num = num | (((*h)[1] & 0xff) << 8);
535 num = num | (((*h)[2] & 0xff) << 16);
536 num = num | (((*h)[3] & 0xff) << 24);
537 if ( num != PyImport_GetMagicNumber() ) {
538 PyErr_SetString(PyExc_ImportError, "Bad MAGIC in resource");
539 co = NULL;
540 } else {
541 co = PyMarshal_ReadObjectFromString((*h)+8, size-8);
542 }
543 }
544 HUnlock(h);
545 CloseResFile(filerh);
546 UseResFile(oldrh);
547 if ( co ) {
548 m = PyImport_ExecCodeModule(module, co);
549 Py_DECREF(co);
550 } else {
551 m = NULL;
552 }
553 return m;
554error:
555 {
556 char buf[512];
557
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000558 sprintf(buf, "%s: %s", filename, PyMac_StrError(err));
Jack Jansen74162f31995-02-15 22:58:33 +0000559 PyErr_SetString(PyExc_ImportError, buf);
560 return NULL;
561 }
562}
Guido van Rossum24a45e31995-02-20 23:45:53 +0000563
Jack Jansen3ec804a1995-02-20 15:56:10 +0000564/*
565** Helper routine for GetDirectory
566*/
Guido van Rossum24a45e31995-02-20 23:45:53 +0000567static pascal short
Jack Jansen819f1771995-08-14 12:35:10 +0000568myhook_proc(short item, DialogPtr theDialog, struct hook_args *dataptr)
Jack Jansen3ec804a1995-02-20 15:56:10 +0000569{
Jack Jansen819f1771995-08-14 12:35:10 +0000570 if ( item == sfHookFirstCall && dataptr->prompt) {
571 Handle prompth;
572 short type;
573 Rect rect;
574
575 GetDialogItem(theDialog, PROMPT_ITEM, &type, &prompth, &rect);
576 if ( prompth )
577 SetDialogItemText(prompth, (unsigned char *)dataptr->prompt);
578 } else
Jack Jansen3ec804a1995-02-20 15:56:10 +0000579 if ( item == SELECTCUR_ITEM ) {
580 item = sfItemCancelButton;
Jack Jansen819f1771995-08-14 12:35:10 +0000581 dataptr->selectcur_hit = 1;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000582 }
583 return item;
584}
585
586/*
587** Ask the user for a directory. I still can't understand
588** why Apple doesn't provide a standard solution for this...
589*/
590int
Jack Jansen819f1771995-08-14 12:35:10 +0000591PyMac_GetDirectory(dirfss, prompt)
Jack Jansen3ec804a1995-02-20 15:56:10 +0000592 FSSpec *dirfss;
Jack Jansen819f1771995-08-14 12:35:10 +0000593 char *prompt;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000594{
595 static SFTypeList list = {'fldr', 0, 0, 0};
596 static Point where = {-1, -1};
Jack Jansen3ec804a1995-02-20 15:56:10 +0000597 StandardFileReply reply;
Jack Jansen819f1771995-08-14 12:35:10 +0000598 struct hook_args hook_args;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000599
600 if ( !upp_inited ) {
601 myhook_upp = NewDlgHookYDProc(myhook_proc);
602 upp_inited = 1;
603 }
Jack Jansen819f1771995-08-14 12:35:10 +0000604 if ( prompt && *prompt )
605 hook_args.prompt = (char *)Pstring(prompt);
606 else
607 hook_args.prompt = NULL;
608 hook_args.selectcur_hit = 0;
Guido van Rossum24a45e31995-02-20 23:45:53 +0000609 CustomGetFile((FileFilterYDUPP)0, 1, list, &reply, GETDIR_ID, where, myhook_upp,
Jack Jansen819f1771995-08-14 12:35:10 +0000610 NULL, NULL, NULL, (void *)&hook_args);
Jack Jansen3ec804a1995-02-20 15:56:10 +0000611
612 reply.sfFile.name[0] = 0;
613 if( FSMakeFSSpec(reply.sfFile.vRefNum, reply.sfFile.parID, reply.sfFile.name, dirfss) )
614 return 0;
Jack Jansen819f1771995-08-14 12:35:10 +0000615 return hook_args.selectcur_hit;
616}
617
618/*
619** Slightly extended StandardGetFile: accepts a prompt */
620void PyMac_PromptGetFile(short numTypes, ConstSFTypeListPtr typeList,
621 StandardFileReply *reply, char *prompt)
622{
623 static Point where = {-1, -1};
624 struct hook_args hook_args;
625
626 if ( !upp_inited ) {
627 myhook_upp = NewDlgHookYDProc(myhook_proc);
628 upp_inited = 1;
629 }
630 if ( prompt && *prompt )
631 hook_args.prompt = (char *)Pstring(prompt);
632 else
633 hook_args.prompt = NULL;
634 hook_args.selectcur_hit = 0;
635 CustomGetFile((FileFilterYDUPP)0, numTypes, typeList, reply, GETFILEPROMPT_ID, where,
636 myhook_upp, NULL, NULL, NULL, (void *)&hook_args);
Jack Jansen3ec804a1995-02-20 15:56:10 +0000637}
Jack Jansen5f653091995-01-18 13:53:49 +0000638
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000639/* Convert a 4-char string object argument to an OSType value */
Jack Jansen5f653091995-01-18 13:53:49 +0000640int
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000641PyMac_GetOSType(PyObject *v, OSType *pr)
Jack Jansen5f653091995-01-18 13:53:49 +0000642{
643 if (!PyString_Check(v) || PyString_Size(v) != 4) {
644 PyErr_SetString(PyExc_TypeError,
645 "OSType arg must be string of 4 chars");
646 return 0;
647 }
648 memcpy((char *)pr, PyString_AsString(v), 4);
649 return 1;
650}
651
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000652/* Convert an OSType value to a 4-char string object */
653PyObject *
654PyMac_BuildOSType(OSType t)
655{
656 return PyString_FromStringAndSize((char *)&t, 4);
657}
658
Jack Jansend1f06311996-08-01 15:23:54 +0000659/* Convert an NumVersion value to a 4-element tuple */
660PyObject *
661PyMac_BuildNumVersion(NumVersion t)
662{
663 return Py_BuildValue("(hhhh)", t.majorRev, t.minorAndBugRev, t.stage, t.nonRelRev);
664}
665
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000666
667/* Convert a Python string object to a Str255 */
Jack Jansen5f653091995-01-18 13:53:49 +0000668int
Guido van Rossum8f691791995-01-18 23:57:26 +0000669PyMac_GetStr255(PyObject *v, Str255 pbuf)
Jack Jansen5f653091995-01-18 13:53:49 +0000670{
671 int len;
672 if (!PyString_Check(v) || (len = PyString_Size(v)) > 255) {
673 PyErr_SetString(PyExc_TypeError,
674 "Str255 arg must be string of at most 255 chars");
675 return 0;
676 }
677 pbuf[0] = len;
678 memcpy((char *)(pbuf+1), PyString_AsString(v), len);
679 return 1;
680}
681
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000682/* Convert a Str255 to a Python string object */
683PyObject *
684PyMac_BuildStr255(Str255 s)
685{
686 return PyString_FromStringAndSize((char *)&s[1], (int)s[0]);
687}
688
689
Jack Jansen5f653091995-01-18 13:53:49 +0000690/*
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000691** Convert a Python object to an FSSpec.
692** The object may either be a full pathname or a triple
693** (vrefnum, dirid, path).
Jack Jansen5f653091995-01-18 13:53:49 +0000694** NOTE: This routine will fail on pre-sys7 machines.
695** The caller is responsible for not calling this routine
696** in those cases (which is fine, since everyone calling
697** this is probably sys7 dependent anyway).
698*/
699int
Guido van Rossum8f691791995-01-18 23:57:26 +0000700PyMac_GetFSSpec(PyObject *v, FSSpec *fs)
Jack Jansen5f653091995-01-18 13:53:49 +0000701{
702 Str255 path;
703 short refnum;
704 long parid;
705 OSErr err;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000706 FSSpec *fs2;
Jack Jansen5f653091995-01-18 13:53:49 +0000707
Jack Jansene8e8ae01995-01-26 16:36:45 +0000708 /* first check whether it already is an FSSpec */
709 fs2 = mfs_GetFSSpecFSSpec(v);
710 if ( fs2 ) {
Jack Jansen3ec804a1995-02-20 15:56:10 +0000711 (void)FSMakeFSSpec(fs2->vRefNum, fs2->parID, fs2->name, fs);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000712 return 1;
713 }
Jack Jansen5f653091995-01-18 13:53:49 +0000714 if ( PyString_Check(v) ) {
715 /* It's a pathname */
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000716 if( !PyArg_Parse(v, "O&", PyMac_GetStr255, &path) )
Jack Jansen5f653091995-01-18 13:53:49 +0000717 return 0;
Jack Jansen378815c1996-03-06 16:21:34 +0000718 refnum = 0; /* XXXX Should get CurWD here?? */
Jack Jansen5f653091995-01-18 13:53:49 +0000719 parid = 0;
720 } else {
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000721 if( !PyArg_Parse(v, "(hlO&); FSSpec should be fullpath or (vrefnum,dirid,path)",
722 &refnum, &parid, PyMac_GetStr255, &path)) {
Jack Jansen5f653091995-01-18 13:53:49 +0000723 return 0;
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000724 }
Jack Jansen5f653091995-01-18 13:53:49 +0000725 }
726 err = FSMakeFSSpec(refnum, parid, path, fs);
727 if ( err && err != fnfErr ) {
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000728 PyErr_Mac(PyExc_ValueError, err);
Jack Jansen5f653091995-01-18 13:53:49 +0000729 return 0;
730 }
731 return 1;
732}
733
Guido van Rossum8f691791995-01-18 23:57:26 +0000734
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000735/* Convert a Python object to a Rect.
Guido van Rossum5279ec61995-01-26 22:56:59 +0000736 The object must be a (left, top, right, bottom) tuple.
737 (This differs from the order in the struct but is consistent with
738 the arguments to SetRect(), and also with STDWIN). */
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000739int
740PyMac_GetRect(PyObject *v, Rect *r)
Guido van Rossum8f691791995-01-18 23:57:26 +0000741{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000742 return PyArg_Parse(v, "(hhhh)", &r->left, &r->top, &r->right, &r->bottom);
Guido van Rossum8f691791995-01-18 23:57:26 +0000743}
Guido van Rossumb3404661995-01-22 18:36:13 +0000744
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000745/* Convert a Rect to a Python object */
Guido van Rossumb3404661995-01-22 18:36:13 +0000746PyObject *
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000747PyMac_BuildRect(Rect *r)
Guido van Rossumb3404661995-01-22 18:36:13 +0000748{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000749 return Py_BuildValue("(hhhh)", r->left, r->top, r->right, r->bottom);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000750}
751
752
753/* Convert a Python object to a Point.
Guido van Rossum5279ec61995-01-26 22:56:59 +0000754 The object must be a (h, v) tuple.
755 (This differs from the order in the struct but is consistent with
756 the arguments to SetPoint(), and also with STDWIN). */
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000757int
758PyMac_GetPoint(PyObject *v, Point *p)
759{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000760 return PyArg_Parse(v, "(hh)", &p->h, &p->v);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000761}
762
763/* Convert a Point to a Python object */
764PyObject *
765PyMac_BuildPoint(Point p)
766{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000767 return Py_BuildValue("(hh)", p.h, p.v);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000768}
769
770
771/* Convert a Python object to an EventRecord.
772 The object must be a (what, message, when, (v, h), modifiers) tuple. */
773int
774PyMac_GetEventRecord(PyObject *v, EventRecord *e)
775{
776 return PyArg_Parse(v, "(hll(hh)h)",
777 &e->what,
778 &e->message,
779 &e->when,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000780 &e->where.h,
Guido van Rossum5279ec61995-01-26 22:56:59 +0000781 &e->where.v,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000782 &e->modifiers);
783}
784
785/* Convert a Rect to an EventRecord object */
786PyObject *
787PyMac_BuildEventRecord(EventRecord *e)
788{
789 return Py_BuildValue("(hll(hh)h)",
790 e->what,
791 e->message,
792 e->when,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000793 e->where.h,
Guido van Rossum5279ec61995-01-26 22:56:59 +0000794 e->where.v,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000795 e->modifiers);
Guido van Rossumb3404661995-01-22 18:36:13 +0000796}
Jack Jansenfa4d5d01995-11-15 15:19:29 +0000797
798/* Convert Python object to Fixed */
799int
800PyMac_GetFixed(PyObject *v, Fixed *f)
801{
802 double d;
803
804 if( !PyArg_Parse(v, "d", &d))
805 return 0;
806 *f = (Fixed)(d * 0x10000);
Jack Jansen31dd5c01996-05-31 13:01:39 +0000807 return 1;
Jack Jansenfa4d5d01995-11-15 15:19:29 +0000808}
809
810/* Convert a Point to a Python object */
811PyObject *
812PyMac_BuildFixed(Fixed f)
813{
814 double d;
815
816 d = f;
817 d = d / 0x10000;
818 return Py_BuildValue("d", d);
819}
820