blob: 112604ee02850898565cc9b6ca6465085131e1f6 [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
Jack Jansenbf05d4c1996-08-19 15:11:45 +000025#ifdef __CFM68K__
26/* cfm68k InterfaceLib exports GetEventQueue, but Events.h doesn't know this
27** and defines it as GetEvQHdr (which is correct for PPC). This fix is for
28** CW9, check that the workaround is still needed for the next release.
29*/
30#define GetEvQHdr GetEventQueue
31#endif /* __CFM68K__ */
32
33#include <Events.h>
34
35#ifdef __CFM68K__
36#undef GetEventQueue
37#endif /* __CFM68K__ */
38
Jack Jansenf93c72a1994-12-14 14:07:50 +000039#include "Python.h"
Guido van Rossumbecdbec1995-02-14 01:27:24 +000040
Jack Jansenf93c72a1994-12-14 14:07:50 +000041#include "macglue.h"
Jack Jansen74162f31995-02-15 22:58:33 +000042#include "marshal.h"
43#include "import.h"
Jack Jansenf93c72a1994-12-14 14:07:50 +000044
Jack Jansen819f1771995-08-14 12:35:10 +000045#include "pythonresources.h"
46
Jack Jansenf93c72a1994-12-14 14:07:50 +000047#include <OSUtils.h> /* for Set(Current)A5 */
Jack Jansene8e8ae01995-01-26 16:36:45 +000048#include <Files.h>
Jack Jansen8cd2b721995-02-13 11:33:28 +000049#include <StandardFile.h>
Jack Jansenf93c72a1994-12-14 14:07:50 +000050#include <Resources.h>
51#include <Memory.h>
Jack Jansenf93c72a1994-12-14 14:07:50 +000052#include <Windows.h>
53#include <Desk.h>
Jack Jansene8e8ae01995-01-26 16:36:45 +000054#include <Traps.h>
Jack Jansenee23d6e1995-01-27 14:43:25 +000055#include <Processes.h>
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +000056#include <Fonts.h>
57#include <Menus.h>
Jack Jansen08305501995-06-18 20:03:40 +000058#include <TextUtils.h>
Guido van Rossumcc0d8791995-01-30 08:57:13 +000059#ifdef THINK_C
60#include <OSEvents.h> /* For EvQElPtr */
61#endif
Jack Jansen16df2aa1995-02-27 16:17:28 +000062#ifdef __MWERKS__
63#include <SIOUX.h>
64#endif
Jack Jansen911ad6b1996-03-05 16:56:24 +000065#ifdef USE_GUSI
66#include <TFileSpec.h> /* For Path2FSSpec */
Jack Jansen378815c1996-03-06 16:21:34 +000067#include <LowMem.h> /* For SetSFCurDir, etc */
Jack Jansen911ad6b1996-03-05 16:56:24 +000068#endif
Jack Jansenee23d6e1995-01-27 14:43:25 +000069
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +000070#ifndef HAVE_UNIVERSAL_HEADERS
71#define GetResourceSizeOnDisk(x) SizeResource(x)
Guido van Rossum24a45e31995-02-20 23:45:53 +000072typedef DlgHookYDProcPtr DlgHookYDUPP;
73#define NewDlgHookYDProc(userRoutine) ((DlgHookYDUPP) (userRoutine))
74typedef FileFilterYDProcPtr FileFilterYDUPP;
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +000075#endif
76
Jack Jansenee23d6e1995-01-27 14:43:25 +000077#include <signal.h>
Jack Jansen74162f31995-02-15 22:58:33 +000078#include <stdio.h>
Jack Jansene8e8ae01995-01-26 16:36:45 +000079
Jack Jansenee23d6e1995-01-27 14:43:25 +000080/*
Jack Jansend1f06311996-08-01 15:23:54 +000081** When less than this amount of stackspace is left we
82** raise a MemoryError.
83*/
84#ifndef MINIMUM_STACK_SIZE
85#ifdef __powerc
86#define MINIMUM_STACK_SIZE 8192
87#else
88#define MINIMUM_STACK_SIZE 4096
89#endif
90#endif
91
92/*
Jack Jansen16df2aa1995-02-27 16:17:28 +000093** We have to be careful, since we can't handle
Jack Jansenee23d6e1995-01-27 14:43:25 +000094** things like updates (and they'll keep coming back if we don't
Jack Jansen16df2aa1995-02-27 16:17:28 +000095** handle them). Note that we don't know who has windows open, so
96** even handing updates off to SIOUX under MW isn't going to work.
Jack Jansenee23d6e1995-01-27 14:43:25 +000097*/
98#define MAINLOOP_EVENTMASK (mDownMask|keyDownMask|osMask)
Jack Jansene8e8ae01995-01-26 16:36:45 +000099
100#include <signal.h>
Jack Jansenf93c72a1994-12-14 14:07:50 +0000101
Guido van Rossumb3404661995-01-22 18:36:13 +0000102/* XXX We should include Errors.h here, but it has a name conflict
Jack Jansen5f653091995-01-18 13:53:49 +0000103** with the python errors.h. */
104#define fnfErr -43
105
Jack Jansene8e8ae01995-01-26 16:36:45 +0000106/* Declared in macfsmodule.c: */
107extern FSSpec *mfs_GetFSSpecFSSpec();
108
Jack Jansenee23d6e1995-01-27 14:43:25 +0000109/* Interrupt code variables: */
110static int interrupted; /* Set to true when cmd-. seen */
111static RETSIGTYPE intcatcher Py_PROTO((int));
112
Jack Jansene8e8ae01995-01-26 16:36:45 +0000113/*
114** We attempt to be a good citizen by giving up the CPU periodically.
115** When in the foreground we do this less often and for shorter periods
116** than when in the background. At this time we also check for events and
Jack Jansenee23d6e1995-01-27 14:43:25 +0000117** pass them off to SIOUX, if compiling with mwerks.
Jack Jansene8e8ae01995-01-26 16:36:45 +0000118** The counts here are in ticks of 1/60th second.
119** XXXX The initial values here are not based on anything.
120** FG-python gives up the cpu for 1/60th 5 times per second,
121** BG-python for .2 second 10 times per second.
122*/
123static long interval_fg = 12;
124static long interval_bg = 6;
125static long yield_fg = 1;
126static long yield_bg = 12;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000127static long lastyield;
128static int in_foreground;
129
Guido van Rossume7134aa1995-02-26 10:20:53 +0000130/*
131** When > 0, do full scanning for events (program is not event aware)
132** when == 0, only scan for Command-period
133** when < 0, don't do any event scanning
134*/
135int PyMac_DoYieldEnabled = 1;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000136
Jack Jansen819f1771995-08-14 12:35:10 +0000137/*
138** Some stuff for our GetDirectory and PromptGetFile routines
139*/
140struct hook_args {
141 int selectcur_hit; /* Set to true when "select current" selected */
142 char *prompt; /* The prompt */
143};
144static DlgHookYDUPP myhook_upp;
145static int upp_inited = 0;
146
Jack Jansen378815c1996-03-06 16:21:34 +0000147#ifdef USE_GUSI
148/*
149** GUSI (1.6.0 and earlier, at the least) do not set the MacOS idea of
150** the working directory. Hence, we call this routine after each call
151** to chdir() to rectify things.
152*/
153void
154PyMac_FixGUSIcd()
155{
156 WDPBRec pb;
157 FSSpec curdirfss;
158
159 if ( Path2FSSpec(":x", &curdirfss) != noErr )
160 return;
161
162 /* Set MacOS "working directory" */
163 pb.ioNamePtr= "\p";
164 pb.ioVRefNum= curdirfss.vRefNum;
165 pb.ioWDDirID= curdirfss.parID;
166 if (PBHSetVol(&pb, 0) != noErr)
167 return;
Jack Jansen378815c1996-03-06 16:21:34 +0000168}
Jack Jansen7ac70af1996-08-19 11:01:05 +0000169
170#ifdef __CFM68K__
Jack Jansencfadbd41996-08-19 11:36:25 +0000171void SpinCursor(short x) { /* Dummy */ }
172#endif /* __CFM68K */
173
Jack Jansen378815c1996-03-06 16:21:34 +0000174#endif
175
Jack Jansen819f1771995-08-14 12:35:10 +0000176
Jack Jansen5f653091995-01-18 13:53:49 +0000177/* Convert C to Pascal string. Returns pointer to static buffer. */
178unsigned char *
179Pstring(char *str)
180{
181 static Str255 buf;
182 int len;
183
184 len = strlen(str);
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000185 if (len > 255)
186 len = 255;
Jack Jansen5f653091995-01-18 13:53:49 +0000187 buf[0] = (unsigned char)len;
188 strncpy((char *)buf+1, str, len);
189 return buf;
190}
191
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000192/* Like strerror() but for Mac OS error numbers */
193char *PyMac_StrError(int err)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000194{
195 static char buf[256];
196 Handle h;
197 char *str;
198
199 h = GetResource('Estr', err);
200 if ( h ) {
201 HLock(h);
202 str = (char *)*h;
203 memcpy(buf, str+1, (unsigned char)str[0]);
Guido van Rossumcc9bc8f1995-02-13 16:17:03 +0000204 buf[(unsigned char)str[0]] = '\0';
Jack Jansenf93c72a1994-12-14 14:07:50 +0000205 HUnlock(h);
206 ReleaseResource(h);
207 } else {
208 sprintf(buf, "Mac OS error code %d", err);
209 }
210 return buf;
211}
212
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000213/* Exception object shared by all Mac specific modules for Mac OS errors */
214PyObject *PyMac_OSErrException;
215
216/* Initialize and return PyMac_OSErrException */
217PyObject *
218PyMac_GetOSErrException()
219{
220 if (PyMac_OSErrException == NULL)
221 PyMac_OSErrException = PyString_FromString("Mac OS Error");
222 return PyMac_OSErrException;
223}
224
Jack Jansenf93c72a1994-12-14 14:07:50 +0000225/* Set a MAC-specific error from errno, and return NULL; return None if no error */
226PyObject *
Guido van Rossumfffb8bb1995-01-12 12:37:24 +0000227PyErr_Mac(PyObject *eobj, int err)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000228{
229 char *msg;
230 PyObject *v;
Jack Jansenf93c72a1994-12-14 14:07:50 +0000231
Guido van Rossum8f691791995-01-18 23:57:26 +0000232 if (err == 0 && !PyErr_Occurred()) {
Jack Jansenf93c72a1994-12-14 14:07:50 +0000233 Py_INCREF(Py_None);
234 return Py_None;
235 }
Guido van Rossum8f691791995-01-18 23:57:26 +0000236 if (err == -1 && PyErr_Occurred())
237 return NULL;
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000238 msg = PyMac_StrError(err);
Jack Jansenf93c72a1994-12-14 14:07:50 +0000239 v = Py_BuildValue("(is)", err, msg);
240 PyErr_SetObject(eobj, v);
241 Py_DECREF(v);
242 return NULL;
243}
244
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000245/* Call PyErr_Mac with PyMac_OSErrException */
246PyObject *
247PyMac_Error(OSErr err)
248{
249 return PyErr_Mac(PyMac_GetOSErrException(), err);
250}
251
Jack Jansen1ed95291996-07-22 15:25:10 +0000252#ifdef USE_STACKCHECK
253/* Check for stack overflow */
254int
255PyOS_CheckStack()
256{
257 long left;
258
259 left = StackSpace();
Jack Jansend1f06311996-08-01 15:23:54 +0000260 if ( left < MINIMUM_STACK_SIZE )
Jack Jansen1ed95291996-07-22 15:25:10 +0000261 return -1;
262 return 0;
263}
264#endif /* USE_STACKCHECK */
265
Jack Jansenee23d6e1995-01-27 14:43:25 +0000266/* The catcher routine (which may not be used for all compilers) */
267static RETSIGTYPE
268intcatcher(sig)
269 int sig;
270{
271 interrupted = 1;
272 signal(SIGINT, intcatcher);
273}
274
275void
276PyOS_InitInterrupts()
277{
278 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
279 signal(SIGINT, intcatcher);
280}
281
282/*
283** This routine scans the event queue looking for cmd-.
284** This is the only way to get an interrupt under THINK (since it
285** doesn't do SIGINT handling), but is also used under MW, when
286** the full-fledged event loop is disabled. This way, we can at least
287** interrupt a runaway python program.
288*/
289static void
290scan_event_queue(flush)
291 int flush;
292{
293 register EvQElPtr q;
294
Jack Jansencfadbd41996-08-19 11:36:25 +0000295 q = (EvQElPtr) GetEventQueue()->qHead;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000296
297 for (; q; q = (EvQElPtr)q->qLink) {
298 if (q->evtQWhat == keyDown &&
299 (char)q->evtQMessage == '.' &&
300 (q->evtQModifiers & cmdKey) != 0) {
301 if ( flush )
302 FlushEvents(keyDownMask, 0);
303 interrupted = 1;
304 break;
305 }
306 }
307}
308
309int
310PyOS_InterruptOccurred()
311{
Guido van Rossume7134aa1995-02-26 10:20:53 +0000312 if (PyMac_DoYieldEnabled < 0)
313 return 0;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000314#ifdef THINK_C
315 scan_event_queue(1);
316#endif
317 PyMac_Yield();
318 if (interrupted) {
319 interrupted = 0;
320 return 1;
321 }
322 return 0;
323}
324
325/* intrpeek() is like intrcheck(), but it doesn't flush the events. The
326** idea is that you call intrpeek() somewhere in a busy-wait loop, and return
327** None as soon as it returns 1. The mainloop will then pick up the cmd-. soon
328** thereafter.
329*/
330static int
331intrpeek()
332{
333#ifdef THINK_C
334 scan_event_queue(0);
335#endif
336 return interrupted;
337}
338
339/* Check whether we are in the foreground */
340int
341PyMac_InForeground()
342{
343 static ProcessSerialNumber ours;
344 static inited;
345 ProcessSerialNumber curfg;
346 Boolean eq;
347
348 if ( inited == 0 )
349 (void)GetCurrentProcess(&ours);
350 inited = 1;
351 if ( GetFrontProcess(&curfg) < 0 )
352 eq = 1;
353 else if ( SameProcess(&ours, &curfg, &eq) < 0 )
354 eq = 1;
355 return (int)eq;
356
357}
358
Jack Jansenf93c72a1994-12-14 14:07:50 +0000359/*
Jack Jansene8e8ae01995-01-26 16:36:45 +0000360** Set yield timeouts
Jack Jansenf93c72a1994-12-14 14:07:50 +0000361*/
Jack Jansene8e8ae01995-01-26 16:36:45 +0000362void
363PyMac_SetYield(long fgi, long fgy, long bgi, long bgy)
364{
365 interval_fg = fgi;
366 yield_fg = fgy;
367 interval_bg = bgi;
368 yield_bg = bgy;
369}
370
371/*
Jack Jansena76382a1995-02-02 14:25:56 +0000372** Handle an event, either one found in the mainloop eventhandler or
373** one passed back from the python program.
374*/
375void
376PyMac_HandleEvent(evp)
377 EventRecord *evp;
378{
Jack Jansena76382a1995-02-02 14:25:56 +0000379
380#ifdef __MWERKS__
Jack Jansen38e97661995-11-10 14:53:00 +0000381 {
382 int siouxdidit;
383
384 /* If SIOUX wants it we're done */
385 siouxdidit = SIOUXHandleOneEvent(evp);
386 if ( siouxdidit )
387 return;
388 }
Jack Jansena76382a1995-02-02 14:25:56 +0000389#else
390 /* Other compilers are just unlucky: we only weed out clicks in other applications */
391 if ( evp->what == mouseDown ) {
Jack Jansen847e89e1995-08-31 13:57:40 +0000392 WindowPtr wp;
393
Jack Jansen38e97661995-11-10 14:53:00 +0000394 if ( FindWindow(evp->where, &wp) == inSysWindow ) {
Jack Jansena76382a1995-02-02 14:25:56 +0000395 SystemClick(evp, wp);
Jack Jansen38e97661995-11-10 14:53:00 +0000396 return;
397 }
Jack Jansena76382a1995-02-02 14:25:56 +0000398 }
399#endif /* !__MWERKS__ */
400}
401
402/*
Jack Jansene8e8ae01995-01-26 16:36:45 +0000403** Yield the CPU to other tasks.
404*/
Jack Jansencfadbd41996-08-19 11:36:25 +0000405static void
Jack Jansene8e8ae01995-01-26 16:36:45 +0000406PyMac_DoYield()
Jack Jansenf93c72a1994-12-14 14:07:50 +0000407{
408 EventRecord ev;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000409 long yield;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000410 static int no_waitnextevent = -1;
411 int gotone;
412
413 if ( no_waitnextevent < 0 ) {
414 no_waitnextevent = (NGetTrapAddress(_WaitNextEvent, ToolTrap) ==
415 NGetTrapAddress(_Unimplemented, ToolTrap));
416 }
Jack Jansenf93c72a1994-12-14 14:07:50 +0000417
Jack Jansenbf05d4c1996-08-19 15:11:45 +0000418 if ( PyMac_DoYieldEnabled >= 0) {
Jack Jansenee23d6e1995-01-27 14:43:25 +0000419#ifndef THINK_C
420 /* Under think this has been done before in intrcheck() or intrpeek() */
421 scan_event_queue(0);
422#endif
Jack Jansene8e8ae01995-01-26 16:36:45 +0000423 return;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000424 }
Jack Jansene8e8ae01995-01-26 16:36:45 +0000425
Jack Jansenee23d6e1995-01-27 14:43:25 +0000426 in_foreground = PyMac_InForeground();
427 if ( in_foreground )
Jack Jansene8e8ae01995-01-26 16:36:45 +0000428 yield = yield_fg;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000429 else
430 yield = yield_bg;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000431 while ( 1 ) {
432 if ( no_waitnextevent ) {
433 SystemTask();
Jack Jansenee23d6e1995-01-27 14:43:25 +0000434 gotone = GetNextEvent(MAINLOOP_EVENTMASK, &ev);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000435 } else {
Jack Jansenee23d6e1995-01-27 14:43:25 +0000436 gotone = WaitNextEvent(MAINLOOP_EVENTMASK, &ev, yield, NULL);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000437 }
438 /* Get out quickly if nothing interesting is happening */
439 if ( !gotone || ev.what == nullEvent )
440 break;
Jack Jansena76382a1995-02-02 14:25:56 +0000441 PyMac_HandleEvent(&ev);
Jack Jansenf93c72a1994-12-14 14:07:50 +0000442 }
Jack Jansene8e8ae01995-01-26 16:36:45 +0000443 lastyield = TickCount();
444}
445
446/*
447** Yield the CPU to other tasks if opportune
448*/
449void
450PyMac_Yield() {
451 long iv;
452
Jack Jansenee23d6e1995-01-27 14:43:25 +0000453 if ( in_foreground )
Jack Jansene8e8ae01995-01-26 16:36:45 +0000454 iv = interval_fg;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000455 else
456 iv = interval_bg;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000457 if ( TickCount() > lastyield + iv )
458 PyMac_DoYield();
459}
460
461/*
462** Idle routine for busy-wait loops.
463** Gives up CPU, handles events and returns true if an interrupt is pending
464** (but not actually handled yet).
465*/
466int
467PyMac_Idle()
468{
469 PyMac_DoYield();
470 return intrpeek();
Jack Jansenf93c72a1994-12-14 14:07:50 +0000471}
Jack Jansen74162f31995-02-15 22:58:33 +0000472/*
473** Returns true if the argument has a resource fork, and it contains
474** a 'PYC ' resource of the correct name
475*/
476int
477PyMac_FindResourceModule(module, filename)
478char *module;
479char *filename;
480{
481 FSSpec fss;
482 FInfo finfo;
483 short oldrh, filerh;
484 int ok;
485 Handle h;
486
487 if ( FSMakeFSSpec(0, 0, Pstring(filename), &fss) != noErr )
488 return 0; /* It doesn't exist */
489 if ( FSpGetFInfo(&fss, &finfo) != noErr )
490 return 0; /* shouldn't happen, I guess */
Jack Jansen74162f31995-02-15 22:58:33 +0000491 oldrh = CurResFile();
492 filerh = FSpOpenResFile(&fss, fsRdPerm);
493 if ( filerh == -1 )
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000494 return 0;
Jack Jansen74162f31995-02-15 22:58:33 +0000495 UseResFile(filerh);
496 SetResLoad(0);
497 h = Get1NamedResource('PYC ', Pstring(module));
498 SetResLoad(1);
499 ok = (h != NULL);
500 CloseResFile(filerh);
501 UseResFile(oldrh);
502 return ok;
503}
504
505/*
506** Load the specified module from a resource
507*/
508PyObject *
509PyMac_LoadResourceModule(module, filename)
510char *module;
511char *filename;
512{
513 FSSpec fss;
514 FInfo finfo;
515 short oldrh, filerh;
Jack Jansen74162f31995-02-15 22:58:33 +0000516 Handle h;
517 OSErr err;
518 PyObject *m, *co;
519 long num, size;
520
521 if ( (err=FSMakeFSSpec(0, 0, Pstring(filename), &fss)) != noErr )
522 goto error;
523 if ( (err=FSpGetFInfo(&fss, &finfo)) != noErr )
524 goto error;
Jack Jansen74162f31995-02-15 22:58:33 +0000525 oldrh = CurResFile();
526 filerh = FSpOpenResFile(&fss, fsRdPerm);
527 if ( filerh == -1 ) {
528 err = ResError();
529 goto error;
530 }
531 UseResFile(filerh);
532 h = Get1NamedResource('PYC ', Pstring(module));
533 if ( h == NULL ) {
534 err = ResError();
535 goto error;
536 }
537 HLock(h);
538 /*
539 ** XXXX The next few lines are intimately tied to the format of pyc
540 ** files. I'm not sure whether this code should be here or in import.c -- Jack
541 */
542 size = GetHandleSize(h);
543 if ( size < 8 ) {
544 PyErr_SetString(PyExc_ImportError, "Resource too small");
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000545 co = NULL;
Jack Jansen74162f31995-02-15 22:58:33 +0000546 } else {
547 num = (*h)[0] & 0xff;
548 num = num | (((*h)[1] & 0xff) << 8);
549 num = num | (((*h)[2] & 0xff) << 16);
550 num = num | (((*h)[3] & 0xff) << 24);
551 if ( num != PyImport_GetMagicNumber() ) {
552 PyErr_SetString(PyExc_ImportError, "Bad MAGIC in resource");
553 co = NULL;
554 } else {
555 co = PyMarshal_ReadObjectFromString((*h)+8, size-8);
556 }
557 }
558 HUnlock(h);
559 CloseResFile(filerh);
560 UseResFile(oldrh);
561 if ( co ) {
562 m = PyImport_ExecCodeModule(module, co);
563 Py_DECREF(co);
564 } else {
565 m = NULL;
566 }
567 return m;
568error:
569 {
570 char buf[512];
571
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000572 sprintf(buf, "%s: %s", filename, PyMac_StrError(err));
Jack Jansen74162f31995-02-15 22:58:33 +0000573 PyErr_SetString(PyExc_ImportError, buf);
574 return NULL;
575 }
576}
Guido van Rossum24a45e31995-02-20 23:45:53 +0000577
Jack Jansen3ec804a1995-02-20 15:56:10 +0000578/*
579** Helper routine for GetDirectory
580*/
Guido van Rossum24a45e31995-02-20 23:45:53 +0000581static pascal short
Jack Jansen819f1771995-08-14 12:35:10 +0000582myhook_proc(short item, DialogPtr theDialog, struct hook_args *dataptr)
Jack Jansen3ec804a1995-02-20 15:56:10 +0000583{
Jack Jansen819f1771995-08-14 12:35:10 +0000584 if ( item == sfHookFirstCall && dataptr->prompt) {
585 Handle prompth;
586 short type;
587 Rect rect;
588
589 GetDialogItem(theDialog, PROMPT_ITEM, &type, &prompth, &rect);
590 if ( prompth )
591 SetDialogItemText(prompth, (unsigned char *)dataptr->prompt);
592 } else
Jack Jansen3ec804a1995-02-20 15:56:10 +0000593 if ( item == SELECTCUR_ITEM ) {
594 item = sfItemCancelButton;
Jack Jansen819f1771995-08-14 12:35:10 +0000595 dataptr->selectcur_hit = 1;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000596 }
597 return item;
598}
599
600/*
601** Ask the user for a directory. I still can't understand
602** why Apple doesn't provide a standard solution for this...
603*/
604int
Jack Jansen819f1771995-08-14 12:35:10 +0000605PyMac_GetDirectory(dirfss, prompt)
Jack Jansen3ec804a1995-02-20 15:56:10 +0000606 FSSpec *dirfss;
Jack Jansen819f1771995-08-14 12:35:10 +0000607 char *prompt;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000608{
609 static SFTypeList list = {'fldr', 0, 0, 0};
610 static Point where = {-1, -1};
Jack Jansen3ec804a1995-02-20 15:56:10 +0000611 StandardFileReply reply;
Jack Jansen819f1771995-08-14 12:35:10 +0000612 struct hook_args hook_args;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000613
614 if ( !upp_inited ) {
615 myhook_upp = NewDlgHookYDProc(myhook_proc);
616 upp_inited = 1;
617 }
Jack Jansen819f1771995-08-14 12:35:10 +0000618 if ( prompt && *prompt )
619 hook_args.prompt = (char *)Pstring(prompt);
620 else
621 hook_args.prompt = NULL;
622 hook_args.selectcur_hit = 0;
Guido van Rossum24a45e31995-02-20 23:45:53 +0000623 CustomGetFile((FileFilterYDUPP)0, 1, list, &reply, GETDIR_ID, where, myhook_upp,
Jack Jansen819f1771995-08-14 12:35:10 +0000624 NULL, NULL, NULL, (void *)&hook_args);
Jack Jansen3ec804a1995-02-20 15:56:10 +0000625
626 reply.sfFile.name[0] = 0;
627 if( FSMakeFSSpec(reply.sfFile.vRefNum, reply.sfFile.parID, reply.sfFile.name, dirfss) )
628 return 0;
Jack Jansen819f1771995-08-14 12:35:10 +0000629 return hook_args.selectcur_hit;
630}
631
632/*
633** Slightly extended StandardGetFile: accepts a prompt */
634void PyMac_PromptGetFile(short numTypes, ConstSFTypeListPtr typeList,
635 StandardFileReply *reply, char *prompt)
636{
637 static Point where = {-1, -1};
638 struct hook_args hook_args;
639
640 if ( !upp_inited ) {
641 myhook_upp = NewDlgHookYDProc(myhook_proc);
642 upp_inited = 1;
643 }
644 if ( prompt && *prompt )
645 hook_args.prompt = (char *)Pstring(prompt);
646 else
647 hook_args.prompt = NULL;
648 hook_args.selectcur_hit = 0;
649 CustomGetFile((FileFilterYDUPP)0, numTypes, typeList, reply, GETFILEPROMPT_ID, where,
650 myhook_upp, NULL, NULL, NULL, (void *)&hook_args);
Jack Jansen3ec804a1995-02-20 15:56:10 +0000651}
Jack Jansen5f653091995-01-18 13:53:49 +0000652
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000653/* Convert a 4-char string object argument to an OSType value */
Jack Jansen5f653091995-01-18 13:53:49 +0000654int
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000655PyMac_GetOSType(PyObject *v, OSType *pr)
Jack Jansen5f653091995-01-18 13:53:49 +0000656{
657 if (!PyString_Check(v) || PyString_Size(v) != 4) {
658 PyErr_SetString(PyExc_TypeError,
659 "OSType arg must be string of 4 chars");
660 return 0;
661 }
662 memcpy((char *)pr, PyString_AsString(v), 4);
663 return 1;
664}
665
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000666/* Convert an OSType value to a 4-char string object */
667PyObject *
668PyMac_BuildOSType(OSType t)
669{
670 return PyString_FromStringAndSize((char *)&t, 4);
671}
672
Jack Jansend1f06311996-08-01 15:23:54 +0000673/* Convert an NumVersion value to a 4-element tuple */
674PyObject *
675PyMac_BuildNumVersion(NumVersion t)
676{
677 return Py_BuildValue("(hhhh)", t.majorRev, t.minorAndBugRev, t.stage, t.nonRelRev);
678}
679
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000680
681/* Convert a Python string object to a Str255 */
Jack Jansen5f653091995-01-18 13:53:49 +0000682int
Guido van Rossum8f691791995-01-18 23:57:26 +0000683PyMac_GetStr255(PyObject *v, Str255 pbuf)
Jack Jansen5f653091995-01-18 13:53:49 +0000684{
685 int len;
686 if (!PyString_Check(v) || (len = PyString_Size(v)) > 255) {
687 PyErr_SetString(PyExc_TypeError,
688 "Str255 arg must be string of at most 255 chars");
689 return 0;
690 }
691 pbuf[0] = len;
692 memcpy((char *)(pbuf+1), PyString_AsString(v), len);
693 return 1;
694}
695
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000696/* Convert a Str255 to a Python string object */
697PyObject *
698PyMac_BuildStr255(Str255 s)
699{
700 return PyString_FromStringAndSize((char *)&s[1], (int)s[0]);
701}
702
703
Jack Jansen5f653091995-01-18 13:53:49 +0000704/*
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000705** Convert a Python object to an FSSpec.
706** The object may either be a full pathname or a triple
707** (vrefnum, dirid, path).
Jack Jansen5f653091995-01-18 13:53:49 +0000708** NOTE: This routine will fail on pre-sys7 machines.
709** The caller is responsible for not calling this routine
710** in those cases (which is fine, since everyone calling
711** this is probably sys7 dependent anyway).
712*/
713int
Guido van Rossum8f691791995-01-18 23:57:26 +0000714PyMac_GetFSSpec(PyObject *v, FSSpec *fs)
Jack Jansen5f653091995-01-18 13:53:49 +0000715{
716 Str255 path;
717 short refnum;
718 long parid;
719 OSErr err;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000720 FSSpec *fs2;
Jack Jansen5f653091995-01-18 13:53:49 +0000721
Jack Jansene8e8ae01995-01-26 16:36:45 +0000722 /* first check whether it already is an FSSpec */
723 fs2 = mfs_GetFSSpecFSSpec(v);
724 if ( fs2 ) {
Jack Jansen3ec804a1995-02-20 15:56:10 +0000725 (void)FSMakeFSSpec(fs2->vRefNum, fs2->parID, fs2->name, fs);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000726 return 1;
727 }
Jack Jansen5f653091995-01-18 13:53:49 +0000728 if ( PyString_Check(v) ) {
729 /* It's a pathname */
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000730 if( !PyArg_Parse(v, "O&", PyMac_GetStr255, &path) )
Jack Jansen5f653091995-01-18 13:53:49 +0000731 return 0;
Jack Jansen378815c1996-03-06 16:21:34 +0000732 refnum = 0; /* XXXX Should get CurWD here?? */
Jack Jansen5f653091995-01-18 13:53:49 +0000733 parid = 0;
734 } else {
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000735 if( !PyArg_Parse(v, "(hlO&); FSSpec should be fullpath or (vrefnum,dirid,path)",
736 &refnum, &parid, PyMac_GetStr255, &path)) {
Jack Jansen5f653091995-01-18 13:53:49 +0000737 return 0;
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000738 }
Jack Jansen5f653091995-01-18 13:53:49 +0000739 }
740 err = FSMakeFSSpec(refnum, parid, path, fs);
741 if ( err && err != fnfErr ) {
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000742 PyErr_Mac(PyExc_ValueError, err);
Jack Jansen5f653091995-01-18 13:53:49 +0000743 return 0;
744 }
745 return 1;
746}
747
Guido van Rossum8f691791995-01-18 23:57:26 +0000748
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000749/* Convert a Python object to a Rect.
Guido van Rossum5279ec61995-01-26 22:56:59 +0000750 The object must be a (left, top, right, bottom) tuple.
751 (This differs from the order in the struct but is consistent with
752 the arguments to SetRect(), and also with STDWIN). */
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000753int
754PyMac_GetRect(PyObject *v, Rect *r)
Guido van Rossum8f691791995-01-18 23:57:26 +0000755{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000756 return PyArg_Parse(v, "(hhhh)", &r->left, &r->top, &r->right, &r->bottom);
Guido van Rossum8f691791995-01-18 23:57:26 +0000757}
Guido van Rossumb3404661995-01-22 18:36:13 +0000758
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000759/* Convert a Rect to a Python object */
Guido van Rossumb3404661995-01-22 18:36:13 +0000760PyObject *
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000761PyMac_BuildRect(Rect *r)
Guido van Rossumb3404661995-01-22 18:36:13 +0000762{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000763 return Py_BuildValue("(hhhh)", r->left, r->top, r->right, r->bottom);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000764}
765
766
767/* Convert a Python object to a Point.
Guido van Rossum5279ec61995-01-26 22:56:59 +0000768 The object must be a (h, v) tuple.
769 (This differs from the order in the struct but is consistent with
770 the arguments to SetPoint(), and also with STDWIN). */
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000771int
772PyMac_GetPoint(PyObject *v, Point *p)
773{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000774 return PyArg_Parse(v, "(hh)", &p->h, &p->v);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000775}
776
777/* Convert a Point to a Python object */
778PyObject *
779PyMac_BuildPoint(Point p)
780{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000781 return Py_BuildValue("(hh)", p.h, p.v);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000782}
783
784
785/* Convert a Python object to an EventRecord.
786 The object must be a (what, message, when, (v, h), modifiers) tuple. */
787int
788PyMac_GetEventRecord(PyObject *v, EventRecord *e)
789{
790 return PyArg_Parse(v, "(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);
797}
798
799/* Convert a Rect to an EventRecord object */
800PyObject *
801PyMac_BuildEventRecord(EventRecord *e)
802{
803 return Py_BuildValue("(hll(hh)h)",
804 e->what,
805 e->message,
806 e->when,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000807 e->where.h,
Guido van Rossum5279ec61995-01-26 22:56:59 +0000808 e->where.v,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000809 e->modifiers);
Guido van Rossumb3404661995-01-22 18:36:13 +0000810}
Jack Jansenfa4d5d01995-11-15 15:19:29 +0000811
812/* Convert Python object to Fixed */
813int
814PyMac_GetFixed(PyObject *v, Fixed *f)
815{
816 double d;
817
818 if( !PyArg_Parse(v, "d", &d))
819 return 0;
820 *f = (Fixed)(d * 0x10000);
Jack Jansen31dd5c01996-05-31 13:01:39 +0000821 return 1;
Jack Jansenfa4d5d01995-11-15 15:19:29 +0000822}
823
824/* Convert a Point to a Python object */
825PyObject *
826PyMac_BuildFixed(Fixed f)
827{
828 double d;
829
830 d = f;
831 d = d / 0x10000;
832 return Py_BuildValue("d", d);
833}
834