blob: 6fc1e99222d0c3dc82ac359e1ce61b751f4dd790 [file] [log] [blame]
Guido van Rossumb3404661995-01-22 18:36:13 +00001/***********************************************************
Jack Jansen42218ce1997-01-31 16:15:11 +00002Copyright 1991-1997 by Stichting Mathematisch Centrum, Amsterdam,
Guido van Rossumb3404661995-01-22 18:36:13 +00003The 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 Jansenf6865f71996-09-04 15:24:59 +000068#include <GUSI.h>
Jack Jansen911ad6b1996-03-05 16:56:24 +000069#endif
Jack Jansenee23d6e1995-01-27 14:43:25 +000070
Jack Jansen3469e991996-09-06 00:30:45 +000071/* The ID of the Sioux apple menu */
72#define SIOUX_APPLEID 32000
73
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +000074#ifndef HAVE_UNIVERSAL_HEADERS
75#define GetResourceSizeOnDisk(x) SizeResource(x)
Guido van Rossum24a45e31995-02-20 23:45:53 +000076typedef DlgHookYDProcPtr DlgHookYDUPP;
77#define NewDlgHookYDProc(userRoutine) ((DlgHookYDUPP) (userRoutine))
78typedef FileFilterYDProcPtr FileFilterYDUPP;
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +000079#endif
80
Jack Jansenee23d6e1995-01-27 14:43:25 +000081#include <signal.h>
Jack Jansen74162f31995-02-15 22:58:33 +000082#include <stdio.h>
Jack Jansene8e8ae01995-01-26 16:36:45 +000083
Jack Jansenee23d6e1995-01-27 14:43:25 +000084/*
Jack Jansend1f06311996-08-01 15:23:54 +000085** When less than this amount of stackspace is left we
86** raise a MemoryError.
87*/
88#ifndef MINIMUM_STACK_SIZE
89#ifdef __powerc
90#define MINIMUM_STACK_SIZE 8192
91#else
92#define MINIMUM_STACK_SIZE 4096
93#endif
94#endif
95
96/*
Jack Jansen16df2aa1995-02-27 16:17:28 +000097** We have to be careful, since we can't handle
Jack Jansenee23d6e1995-01-27 14:43:25 +000098** things like updates (and they'll keep coming back if we don't
Jack Jansen16df2aa1995-02-27 16:17:28 +000099** handle them). Note that we don't know who has windows open, so
100** even handing updates off to SIOUX under MW isn't going to work.
Jack Jansenee23d6e1995-01-27 14:43:25 +0000101*/
102#define MAINLOOP_EVENTMASK (mDownMask|keyDownMask|osMask)
Jack Jansene8e8ae01995-01-26 16:36:45 +0000103
104#include <signal.h>
Jack Jansenf93c72a1994-12-14 14:07:50 +0000105
Guido van Rossumb3404661995-01-22 18:36:13 +0000106/* XXX We should include Errors.h here, but it has a name conflict
Jack Jansen5f653091995-01-18 13:53:49 +0000107** with the python errors.h. */
108#define fnfErr -43
109
Jack Jansene8e8ae01995-01-26 16:36:45 +0000110/* Declared in macfsmodule.c: */
111extern FSSpec *mfs_GetFSSpecFSSpec();
112
Jack Jansenee23d6e1995-01-27 14:43:25 +0000113/* Interrupt code variables: */
114static int interrupted; /* Set to true when cmd-. seen */
115static RETSIGTYPE intcatcher Py_PROTO((int));
116
Jack Jansenf6865f71996-09-04 15:24:59 +0000117static void PyMac_DoYield Py_PROTO((int));
118
Jack Jansene8e8ae01995-01-26 16:36:45 +0000119/*
120** We attempt to be a good citizen by giving up the CPU periodically.
121** When in the foreground we do this less often and for shorter periods
122** than when in the background. At this time we also check for events and
Jack Jansenee23d6e1995-01-27 14:43:25 +0000123** pass them off to SIOUX, if compiling with mwerks.
Jack Jansene8e8ae01995-01-26 16:36:45 +0000124** The counts here are in ticks of 1/60th second.
125** XXXX The initial values here are not based on anything.
126** FG-python gives up the cpu for 1/60th 5 times per second,
127** BG-python for .2 second 10 times per second.
128*/
129static long interval_fg = 12;
130static long interval_bg = 6;
131static long yield_fg = 1;
Jack Jansend617c571996-09-22 22:14:30 +0000132static long yield_bg = 2;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000133static long lastyield;
134static int in_foreground;
135
Guido van Rossume7134aa1995-02-26 10:20:53 +0000136/*
137** When > 0, do full scanning for events (program is not event aware)
138** when == 0, only scan for Command-period
139** when < 0, don't do any event scanning
140*/
141int PyMac_DoYieldEnabled = 1;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000142
Jack Jansen819f1771995-08-14 12:35:10 +0000143/*
Jack Jansenf6865f71996-09-04 15:24:59 +0000144** Workaround for sioux/gusi combo: set when we are exiting
145*/
146int PyMac_ConsoleIsDead;
147
148/*
Jack Jansen819f1771995-08-14 12:35:10 +0000149** Some stuff for our GetDirectory and PromptGetFile routines
150*/
151struct hook_args {
152 int selectcur_hit; /* Set to true when "select current" selected */
153 char *prompt; /* The prompt */
154};
155static DlgHookYDUPP myhook_upp;
156static int upp_inited = 0;
157
Jack Jansen378815c1996-03-06 16:21:34 +0000158#ifdef USE_GUSI
159/*
160** GUSI (1.6.0 and earlier, at the least) do not set the MacOS idea of
161** the working directory. Hence, we call this routine after each call
162** to chdir() to rectify things.
163*/
164void
165PyMac_FixGUSIcd()
166{
167 WDPBRec pb;
168 FSSpec curdirfss;
169
170 if ( Path2FSSpec(":x", &curdirfss) != noErr )
171 return;
172
173 /* Set MacOS "working directory" */
174 pb.ioNamePtr= "\p";
175 pb.ioVRefNum= curdirfss.vRefNum;
176 pb.ioWDDirID= curdirfss.parID;
177 if (PBHSetVol(&pb, 0) != noErr)
178 return;
Jack Jansen378815c1996-03-06 16:21:34 +0000179}
Jack Jansen7ac70af1996-08-19 11:01:05 +0000180
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000181/*
182** SpinCursor (needed by GUSI) drags in heaps of stuff, so we
183** provide a dummy here.
184*/
Jack Jansencfadbd41996-08-19 11:36:25 +0000185void SpinCursor(short x) { /* Dummy */ }
Jack Jansencfadbd41996-08-19 11:36:25 +0000186
Jack Jansenf6865f71996-09-04 15:24:59 +0000187/*
188** Replacement GUSI Spin function
189*/
190static int
191PyMac_GUSISpin(spin_msg msg, long arg)
192{
193 static Boolean inForeground = true;
Jack Jansenf6865f71996-09-04 15:24:59 +0000194 int maysleep;
195
196 if (PyMac_ConsoleIsDead) return 0;
197#if 0
198 if (inForeground)
199 SpinCursor(msg == SP_AUTO_SPIN ? short(arg) : 1);
200#endif
201
202 if (interrupted) return -1;
203
204 if ( msg == SP_AUTO_SPIN || ((msg==SP_SLEEP||msg==SP_SELECT) && arg <= yield_fg))
205 maysleep = 0;
206 else
207 maysleep = 0;
208
209 PyMac_DoYield(maysleep);
210
211 return 0;
212}
213
214void
215PyMac_SetGUSISpin() {
216 GUSISetHook(GUSI_SpinHook, (GUSIHook)PyMac_GUSISpin);
217}
218
Jack Jansen378815c1996-03-06 16:21:34 +0000219#endif
220
Jack Jansen819f1771995-08-14 12:35:10 +0000221
Jack Jansen5f653091995-01-18 13:53:49 +0000222/* Convert C to Pascal string. Returns pointer to static buffer. */
223unsigned char *
224Pstring(char *str)
225{
226 static Str255 buf;
227 int len;
228
229 len = strlen(str);
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000230 if (len > 255)
231 len = 255;
Jack Jansen5f653091995-01-18 13:53:49 +0000232 buf[0] = (unsigned char)len;
233 strncpy((char *)buf+1, str, len);
234 return buf;
235}
236
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000237/* Like strerror() but for Mac OS error numbers */
238char *PyMac_StrError(int err)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000239{
240 static char buf[256];
241 Handle h;
242 char *str;
243
244 h = GetResource('Estr', err);
245 if ( h ) {
246 HLock(h);
247 str = (char *)*h;
248 memcpy(buf, str+1, (unsigned char)str[0]);
Guido van Rossumcc9bc8f1995-02-13 16:17:03 +0000249 buf[(unsigned char)str[0]] = '\0';
Jack Jansenf93c72a1994-12-14 14:07:50 +0000250 HUnlock(h);
251 ReleaseResource(h);
252 } else {
253 sprintf(buf, "Mac OS error code %d", err);
254 }
255 return buf;
256}
257
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000258/* Exception object shared by all Mac specific modules for Mac OS errors */
259PyObject *PyMac_OSErrException;
260
261/* Initialize and return PyMac_OSErrException */
262PyObject *
263PyMac_GetOSErrException()
264{
265 if (PyMac_OSErrException == NULL)
266 PyMac_OSErrException = PyString_FromString("Mac OS Error");
267 return PyMac_OSErrException;
268}
269
Jack Jansenf93c72a1994-12-14 14:07:50 +0000270/* Set a MAC-specific error from errno, and return NULL; return None if no error */
271PyObject *
Guido van Rossumfffb8bb1995-01-12 12:37:24 +0000272PyErr_Mac(PyObject *eobj, int err)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000273{
274 char *msg;
275 PyObject *v;
Jack Jansenf93c72a1994-12-14 14:07:50 +0000276
Guido van Rossum8f691791995-01-18 23:57:26 +0000277 if (err == 0 && !PyErr_Occurred()) {
Jack Jansenf93c72a1994-12-14 14:07:50 +0000278 Py_INCREF(Py_None);
279 return Py_None;
280 }
Guido van Rossum8f691791995-01-18 23:57:26 +0000281 if (err == -1 && PyErr_Occurred())
282 return NULL;
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000283 msg = PyMac_StrError(err);
Jack Jansenf93c72a1994-12-14 14:07:50 +0000284 v = Py_BuildValue("(is)", err, msg);
285 PyErr_SetObject(eobj, v);
286 Py_DECREF(v);
287 return NULL;
288}
289
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000290/* Call PyErr_Mac with PyMac_OSErrException */
291PyObject *
292PyMac_Error(OSErr err)
293{
294 return PyErr_Mac(PyMac_GetOSErrException(), err);
295}
296
Jack Jansen1ed95291996-07-22 15:25:10 +0000297#ifdef USE_STACKCHECK
298/* Check for stack overflow */
299int
300PyOS_CheckStack()
301{
302 long left;
303
304 left = StackSpace();
Jack Jansend1f06311996-08-01 15:23:54 +0000305 if ( left < MINIMUM_STACK_SIZE )
Jack Jansen1ed95291996-07-22 15:25:10 +0000306 return -1;
307 return 0;
308}
309#endif /* USE_STACKCHECK */
310
Jack Jansenee23d6e1995-01-27 14:43:25 +0000311/* The catcher routine (which may not be used for all compilers) */
312static RETSIGTYPE
313intcatcher(sig)
314 int sig;
315{
316 interrupted = 1;
317 signal(SIGINT, intcatcher);
318}
319
320void
321PyOS_InitInterrupts()
322{
323 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
324 signal(SIGINT, intcatcher);
325}
326
327/*
328** This routine scans the event queue looking for cmd-.
329** This is the only way to get an interrupt under THINK (since it
330** doesn't do SIGINT handling), but is also used under MW, when
331** the full-fledged event loop is disabled. This way, we can at least
332** interrupt a runaway python program.
333*/
334static void
335scan_event_queue(flush)
336 int flush;
337{
338 register EvQElPtr q;
339
Jack Jansencfadbd41996-08-19 11:36:25 +0000340 q = (EvQElPtr) GetEventQueue()->qHead;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000341
342 for (; q; q = (EvQElPtr)q->qLink) {
343 if (q->evtQWhat == keyDown &&
344 (char)q->evtQMessage == '.' &&
345 (q->evtQModifiers & cmdKey) != 0) {
346 if ( flush )
347 FlushEvents(keyDownMask, 0);
348 interrupted = 1;
349 break;
350 }
351 }
352}
353
Jack Jansen7e944041997-02-20 15:23:18 +0000354#define TICKCOUNT 6
355
Jack Jansenee23d6e1995-01-27 14:43:25 +0000356int
357PyOS_InterruptOccurred()
358{
Jack Jansen7e944041997-02-20 15:23:18 +0000359 static unsigned long nextticktime;
360 unsigned long curticktime;
361
Guido van Rossume7134aa1995-02-26 10:20:53 +0000362 if (PyMac_DoYieldEnabled < 0)
363 return 0;
Jack Jansen7e944041997-02-20 15:23:18 +0000364 curticktime = (unsigned long)LMGetTicks();
365 if ( curticktime < nextticktime )
366 return 0;
367 nextticktime = curticktime + TICKCOUNT;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000368#ifdef THINK_C
369 scan_event_queue(1);
370#endif
371 PyMac_Yield();
372 if (interrupted) {
373 interrupted = 0;
374 return 1;
375 }
376 return 0;
377}
378
379/* intrpeek() is like intrcheck(), but it doesn't flush the events. The
380** idea is that you call intrpeek() somewhere in a busy-wait loop, and return
381** None as soon as it returns 1. The mainloop will then pick up the cmd-. soon
382** thereafter.
383*/
384static int
385intrpeek()
386{
387#ifdef THINK_C
388 scan_event_queue(0);
389#endif
390 return interrupted;
391}
392
393/* Check whether we are in the foreground */
394int
395PyMac_InForeground()
396{
397 static ProcessSerialNumber ours;
398 static inited;
399 ProcessSerialNumber curfg;
400 Boolean eq;
401
402 if ( inited == 0 )
403 (void)GetCurrentProcess(&ours);
404 inited = 1;
405 if ( GetFrontProcess(&curfg) < 0 )
406 eq = 1;
407 else if ( SameProcess(&ours, &curfg, &eq) < 0 )
408 eq = 1;
409 return (int)eq;
410
411}
412
Jack Jansenf93c72a1994-12-14 14:07:50 +0000413/*
Jack Jansene8e8ae01995-01-26 16:36:45 +0000414** Set yield timeouts
Jack Jansenf93c72a1994-12-14 14:07:50 +0000415*/
Jack Jansene8e8ae01995-01-26 16:36:45 +0000416void
417PyMac_SetYield(long fgi, long fgy, long bgi, long bgy)
418{
419 interval_fg = fgi;
420 yield_fg = fgy;
421 interval_bg = bgi;
422 yield_bg = bgy;
423}
424
425/*
Jack Jansena76382a1995-02-02 14:25:56 +0000426** Handle an event, either one found in the mainloop eventhandler or
427** one passed back from the python program.
428*/
429void
430PyMac_HandleEvent(evp)
431 EventRecord *evp;
432{
Jack Jansena76382a1995-02-02 14:25:56 +0000433
434#ifdef __MWERKS__
Jack Jansen38e97661995-11-10 14:53:00 +0000435 {
436 int siouxdidit;
437
438 /* If SIOUX wants it we're done */
439 siouxdidit = SIOUXHandleOneEvent(evp);
440 if ( siouxdidit )
441 return;
442 }
Jack Jansena76382a1995-02-02 14:25:56 +0000443#else
444 /* Other compilers are just unlucky: we only weed out clicks in other applications */
445 if ( evp->what == mouseDown ) {
Jack Jansen847e89e1995-08-31 13:57:40 +0000446 WindowPtr wp;
447
Jack Jansen38e97661995-11-10 14:53:00 +0000448 if ( FindWindow(evp->where, &wp) == inSysWindow ) {
Jack Jansena76382a1995-02-02 14:25:56 +0000449 SystemClick(evp, wp);
Jack Jansen38e97661995-11-10 14:53:00 +0000450 return;
451 }
Jack Jansena76382a1995-02-02 14:25:56 +0000452 }
453#endif /* !__MWERKS__ */
454}
455
456/*
Jack Jansene8e8ae01995-01-26 16:36:45 +0000457** Yield the CPU to other tasks.
458*/
Jack Jansencfadbd41996-08-19 11:36:25 +0000459static void
Jack Jansenf6865f71996-09-04 15:24:59 +0000460PyMac_DoYield(int maysleep)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000461{
462 EventRecord ev;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000463 long yield;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000464 static int no_waitnextevent = -1;
465 int gotone;
466
467 if ( no_waitnextevent < 0 ) {
468 no_waitnextevent = (NGetTrapAddress(_WaitNextEvent, ToolTrap) ==
469 NGetTrapAddress(_Unimplemented, ToolTrap));
470 }
Jack Jansenf93c72a1994-12-14 14:07:50 +0000471
Jack Jansenf6865f71996-09-04 15:24:59 +0000472 lastyield = TickCount();
Jack Jansenee23d6e1995-01-27 14:43:25 +0000473#ifndef THINK_C
Jack Jansenf6865f71996-09-04 15:24:59 +0000474 /* Under think this has been done before in intrcheck() or intrpeek() */
475 if (PyMac_DoYieldEnabled >= 0)
Jack Jansenee23d6e1995-01-27 14:43:25 +0000476 scan_event_queue(0);
477#endif
Jack Jansenf6865f71996-09-04 15:24:59 +0000478 if (PyMac_DoYieldEnabled == 0)
Jack Jansene8e8ae01995-01-26 16:36:45 +0000479 return;
480
Jack Jansenee23d6e1995-01-27 14:43:25 +0000481 in_foreground = PyMac_InForeground();
Jack Jansenf6865f71996-09-04 15:24:59 +0000482 if ( maysleep ) {
483 if ( in_foreground )
484 yield = yield_fg;
485 else
486 yield = yield_bg;
487 } else {
488 yield = 0;
489 }
490
Jack Jansene8e8ae01995-01-26 16:36:45 +0000491 while ( 1 ) {
492 if ( no_waitnextevent ) {
493 SystemTask();
Jack Jansenee23d6e1995-01-27 14:43:25 +0000494 gotone = GetNextEvent(MAINLOOP_EVENTMASK, &ev);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000495 } else {
Jack Jansenee23d6e1995-01-27 14:43:25 +0000496 gotone = WaitNextEvent(MAINLOOP_EVENTMASK, &ev, yield, NULL);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000497 }
498 /* Get out quickly if nothing interesting is happening */
499 if ( !gotone || ev.what == nullEvent )
500 break;
Jack Jansena76382a1995-02-02 14:25:56 +0000501 PyMac_HandleEvent(&ev);
Jack Jansenf93c72a1994-12-14 14:07:50 +0000502 }
Jack Jansene8e8ae01995-01-26 16:36:45 +0000503}
504
505/*
506** Yield the CPU to other tasks if opportune
507*/
508void
509PyMac_Yield() {
510 long iv;
511
Jack Jansenee23d6e1995-01-27 14:43:25 +0000512 if ( in_foreground )
Jack Jansene8e8ae01995-01-26 16:36:45 +0000513 iv = interval_fg;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000514 else
515 iv = interval_bg;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000516 if ( TickCount() > lastyield + iv )
Jack Jansenf6865f71996-09-04 15:24:59 +0000517 PyMac_DoYield(1);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000518}
519
Jack Jansenf6865f71996-09-04 15:24:59 +0000520#ifdef USE_MACTCP
Jack Jansene8e8ae01995-01-26 16:36:45 +0000521/*
522** Idle routine for busy-wait loops.
523** Gives up CPU, handles events and returns true if an interrupt is pending
524** (but not actually handled yet).
525*/
526int
527PyMac_Idle()
528{
Jack Jansenf6865f71996-09-04 15:24:59 +0000529 PyMac_DoYield(1);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000530 return intrpeek();
Jack Jansenf93c72a1994-12-14 14:07:50 +0000531}
Jack Jansenf6865f71996-09-04 15:24:59 +0000532#endif
533
Jack Jansen74162f31995-02-15 22:58:33 +0000534/*
Jack Jansen3469e991996-09-06 00:30:45 +0000535** Install our menu bar.
536*/
537void
538PyMac_InitMenuBar()
539{
540 Handle bar;
541 MenuHandle applemenu;
542
543 if ( (bar=GetMenuBar()) == NULL ) return;
544 if ( (applemenu=GetMHandle(SIOUX_APPLEID)) == NULL ) return;
545 SetMenuItemText(applemenu, 1, "\pAbout Python...");
546}
547
548/*
549** Our replacement about box
550*/
551void
552SIOUXDoAboutBox(void)
553{
554 DialogPtr theDialog;
Jack Jansend617c571996-09-22 22:14:30 +0000555 WindowRef theWindow;
556 CGrafPtr thePort;
Jack Jansen3469e991996-09-06 00:30:45 +0000557 short item;
Jack Jansend617c571996-09-22 22:14:30 +0000558 short xpos, ypos, width, height, swidth, sheight;
Jack Jansen3469e991996-09-06 00:30:45 +0000559
560 if( (theDialog = GetNewDialog(ABOUT_ID, NULL, (WindowPtr)-1)) == NULL )
561 return;
Jack Jansend617c571996-09-22 22:14:30 +0000562 theWindow = GetDialogWindow(theDialog);
563 thePort = GetWindowPort(theWindow);
564 width = thePort->portRect.right - thePort->portRect.left;
565 height = thePort->portRect.bottom - thePort->portRect.top;
566 swidth = qd.screenBits.bounds.right - qd.screenBits.bounds.left;
567 sheight = qd.screenBits.bounds.bottom - qd.screenBits.bounds.top - LMGetMBarHeight();
568 xpos = (swidth-width)/2;
Jack Jansen0e06e7e1996-09-23 15:51:06 +0000569 ypos = (sheight-height)/5 + LMGetMBarHeight();
Jack Jansend617c571996-09-22 22:14:30 +0000570 MoveWindow(theWindow, xpos, ypos, 0);
571 ShowWindow(theWindow);
Jack Jansen3469e991996-09-06 00:30:45 +0000572 ModalDialog(NULL, &item);
573 DisposeDialog(theDialog);
574}
575
576/*
Jack Jansen74162f31995-02-15 22:58:33 +0000577** Returns true if the argument has a resource fork, and it contains
578** a 'PYC ' resource of the correct name
579*/
580int
581PyMac_FindResourceModule(module, filename)
582char *module;
583char *filename;
584{
585 FSSpec fss;
586 FInfo finfo;
587 short oldrh, filerh;
588 int ok;
589 Handle h;
590
Jack Jansen8096daa1996-11-09 18:43:44 +0000591 if ( strcmp(filename, PyMac_ApplicationPath) == 0 ) {
592 /*
593 ** Special case: the application itself. Use a shortcut to
594 ** forestall opening and closing the application numerous times
595 ** (which is dead slow when running from CDROM)
596 */
597 oldrh = CurResFile();
598 UseResFile(PyMac_AppRefNum);
599 filerh = -1;
600 } else {
601 if ( FSMakeFSSpec(0, 0, Pstring(filename), &fss) != noErr )
602 return 0; /* It doesn't exist */
603 if ( FSpGetFInfo(&fss, &finfo) != noErr )
604 return 0; /* shouldn't happen, I guess */
605 oldrh = CurResFile();
606 filerh = FSpOpenResFile(&fss, fsRdPerm);
607 if ( filerh == -1 )
608 return 0;
609 UseResFile(filerh);
610 }
Jack Jansen74162f31995-02-15 22:58:33 +0000611 SetResLoad(0);
612 h = Get1NamedResource('PYC ', Pstring(module));
613 SetResLoad(1);
614 ok = (h != NULL);
Jack Jansen8096daa1996-11-09 18:43:44 +0000615 if ( filerh != -1 )
616 CloseResFile(filerh);
Jack Jansen74162f31995-02-15 22:58:33 +0000617 UseResFile(oldrh);
618 return ok;
619}
620
621/*
622** Load the specified module from a resource
623*/
624PyObject *
625PyMac_LoadResourceModule(module, filename)
626char *module;
627char *filename;
628{
629 FSSpec fss;
630 FInfo finfo;
631 short oldrh, filerh;
Jack Jansen74162f31995-02-15 22:58:33 +0000632 Handle h;
633 OSErr err;
634 PyObject *m, *co;
635 long num, size;
636
Jack Jansen8096daa1996-11-09 18:43:44 +0000637 if ( strcmp(filename, PyMac_ApplicationPath) == 0 ) {
638 /*
639 ** Special case: the application itself. Use a shortcut to
640 ** forestall opening and closing the application numerous times
641 ** (which is dead slow when running from CDROM)
642 */
643 oldrh = CurResFile();
644 UseResFile(PyMac_AppRefNum);
645 filerh = -1;
646 } else {
647 if ( (err=FSMakeFSSpec(0, 0, Pstring(filename), &fss)) != noErr )
648 goto error;
649 if ( (err=FSpGetFInfo(&fss, &finfo)) != noErr )
650 goto error;
651 oldrh = CurResFile();
652 filerh = FSpOpenResFile(&fss, fsRdPerm);
653 if ( filerh == -1 ) {
654 err = ResError();
655 goto error;
656 }
657 UseResFile(filerh);
Jack Jansen74162f31995-02-15 22:58:33 +0000658 }
Jack Jansen74162f31995-02-15 22:58:33 +0000659 h = Get1NamedResource('PYC ', Pstring(module));
660 if ( h == NULL ) {
661 err = ResError();
662 goto error;
663 }
664 HLock(h);
665 /*
666 ** XXXX The next few lines are intimately tied to the format of pyc
667 ** files. I'm not sure whether this code should be here or in import.c -- Jack
668 */
669 size = GetHandleSize(h);
670 if ( size < 8 ) {
671 PyErr_SetString(PyExc_ImportError, "Resource too small");
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000672 co = NULL;
Jack Jansen74162f31995-02-15 22:58:33 +0000673 } else {
674 num = (*h)[0] & 0xff;
675 num = num | (((*h)[1] & 0xff) << 8);
676 num = num | (((*h)[2] & 0xff) << 16);
677 num = num | (((*h)[3] & 0xff) << 24);
678 if ( num != PyImport_GetMagicNumber() ) {
679 PyErr_SetString(PyExc_ImportError, "Bad MAGIC in resource");
680 co = NULL;
681 } else {
682 co = PyMarshal_ReadObjectFromString((*h)+8, size-8);
683 }
684 }
685 HUnlock(h);
Jack Jansen8096daa1996-11-09 18:43:44 +0000686 if ( filerh != -1 )
687 CloseResFile(filerh);
Jack Jansen74162f31995-02-15 22:58:33 +0000688 UseResFile(oldrh);
689 if ( co ) {
690 m = PyImport_ExecCodeModule(module, co);
691 Py_DECREF(co);
692 } else {
693 m = NULL;
694 }
695 return m;
696error:
697 {
698 char buf[512];
699
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000700 sprintf(buf, "%s: %s", filename, PyMac_StrError(err));
Jack Jansen74162f31995-02-15 22:58:33 +0000701 PyErr_SetString(PyExc_ImportError, buf);
702 return NULL;
703 }
704}
Guido van Rossum24a45e31995-02-20 23:45:53 +0000705
Jack Jansen3ec804a1995-02-20 15:56:10 +0000706/*
707** Helper routine for GetDirectory
708*/
Guido van Rossum24a45e31995-02-20 23:45:53 +0000709static pascal short
Jack Jansen819f1771995-08-14 12:35:10 +0000710myhook_proc(short item, DialogPtr theDialog, struct hook_args *dataptr)
Jack Jansen3ec804a1995-02-20 15:56:10 +0000711{
Jack Jansen819f1771995-08-14 12:35:10 +0000712 if ( item == sfHookFirstCall && dataptr->prompt) {
713 Handle prompth;
714 short type;
715 Rect rect;
716
717 GetDialogItem(theDialog, PROMPT_ITEM, &type, &prompth, &rect);
718 if ( prompth )
719 SetDialogItemText(prompth, (unsigned char *)dataptr->prompt);
720 } else
Jack Jansen3ec804a1995-02-20 15:56:10 +0000721 if ( item == SELECTCUR_ITEM ) {
722 item = sfItemCancelButton;
Jack Jansen819f1771995-08-14 12:35:10 +0000723 dataptr->selectcur_hit = 1;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000724 }
725 return item;
726}
727
728/*
729** Ask the user for a directory. I still can't understand
730** why Apple doesn't provide a standard solution for this...
731*/
732int
Jack Jansen819f1771995-08-14 12:35:10 +0000733PyMac_GetDirectory(dirfss, prompt)
Jack Jansen3ec804a1995-02-20 15:56:10 +0000734 FSSpec *dirfss;
Jack Jansen819f1771995-08-14 12:35:10 +0000735 char *prompt;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000736{
737 static SFTypeList list = {'fldr', 0, 0, 0};
738 static Point where = {-1, -1};
Jack Jansen3ec804a1995-02-20 15:56:10 +0000739 StandardFileReply reply;
Jack Jansen819f1771995-08-14 12:35:10 +0000740 struct hook_args hook_args;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000741
742 if ( !upp_inited ) {
743 myhook_upp = NewDlgHookYDProc(myhook_proc);
744 upp_inited = 1;
745 }
Jack Jansen819f1771995-08-14 12:35:10 +0000746 if ( prompt && *prompt )
747 hook_args.prompt = (char *)Pstring(prompt);
748 else
749 hook_args.prompt = NULL;
750 hook_args.selectcur_hit = 0;
Guido van Rossum24a45e31995-02-20 23:45:53 +0000751 CustomGetFile((FileFilterYDUPP)0, 1, list, &reply, GETDIR_ID, where, myhook_upp,
Jack Jansen819f1771995-08-14 12:35:10 +0000752 NULL, NULL, NULL, (void *)&hook_args);
Jack Jansen3ec804a1995-02-20 15:56:10 +0000753
754 reply.sfFile.name[0] = 0;
755 if( FSMakeFSSpec(reply.sfFile.vRefNum, reply.sfFile.parID, reply.sfFile.name, dirfss) )
756 return 0;
Jack Jansen819f1771995-08-14 12:35:10 +0000757 return hook_args.selectcur_hit;
758}
759
760/*
761** Slightly extended StandardGetFile: accepts a prompt */
762void PyMac_PromptGetFile(short numTypes, ConstSFTypeListPtr typeList,
763 StandardFileReply *reply, char *prompt)
764{
765 static Point where = {-1, -1};
766 struct hook_args hook_args;
767
768 if ( !upp_inited ) {
769 myhook_upp = NewDlgHookYDProc(myhook_proc);
770 upp_inited = 1;
771 }
772 if ( prompt && *prompt )
773 hook_args.prompt = (char *)Pstring(prompt);
774 else
775 hook_args.prompt = NULL;
776 hook_args.selectcur_hit = 0;
777 CustomGetFile((FileFilterYDUPP)0, numTypes, typeList, reply, GETFILEPROMPT_ID, where,
778 myhook_upp, NULL, NULL, NULL, (void *)&hook_args);
Jack Jansen3ec804a1995-02-20 15:56:10 +0000779}
Jack Jansen5f653091995-01-18 13:53:49 +0000780
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000781/* Convert a 4-char string object argument to an OSType value */
Jack Jansen5f653091995-01-18 13:53:49 +0000782int
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000783PyMac_GetOSType(PyObject *v, OSType *pr)
Jack Jansen5f653091995-01-18 13:53:49 +0000784{
785 if (!PyString_Check(v) || PyString_Size(v) != 4) {
786 PyErr_SetString(PyExc_TypeError,
787 "OSType arg must be string of 4 chars");
788 return 0;
789 }
790 memcpy((char *)pr, PyString_AsString(v), 4);
791 return 1;
792}
793
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000794/* Convert an OSType value to a 4-char string object */
795PyObject *
796PyMac_BuildOSType(OSType t)
797{
798 return PyString_FromStringAndSize((char *)&t, 4);
799}
800
Jack Jansend1f06311996-08-01 15:23:54 +0000801/* Convert an NumVersion value to a 4-element tuple */
802PyObject *
803PyMac_BuildNumVersion(NumVersion t)
804{
805 return Py_BuildValue("(hhhh)", t.majorRev, t.minorAndBugRev, t.stage, t.nonRelRev);
806}
807
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000808
809/* Convert a Python string object to a Str255 */
Jack Jansen5f653091995-01-18 13:53:49 +0000810int
Guido van Rossum8f691791995-01-18 23:57:26 +0000811PyMac_GetStr255(PyObject *v, Str255 pbuf)
Jack Jansen5f653091995-01-18 13:53:49 +0000812{
813 int len;
814 if (!PyString_Check(v) || (len = PyString_Size(v)) > 255) {
815 PyErr_SetString(PyExc_TypeError,
816 "Str255 arg must be string of at most 255 chars");
817 return 0;
818 }
819 pbuf[0] = len;
820 memcpy((char *)(pbuf+1), PyString_AsString(v), len);
821 return 1;
822}
823
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000824/* Convert a Str255 to a Python string object */
825PyObject *
826PyMac_BuildStr255(Str255 s)
827{
828 return PyString_FromStringAndSize((char *)&s[1], (int)s[0]);
829}
830
831
Jack Jansen5f653091995-01-18 13:53:49 +0000832/*
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000833** Convert a Python object to an FSSpec.
834** The object may either be a full pathname or a triple
835** (vrefnum, dirid, path).
Jack Jansen5f653091995-01-18 13:53:49 +0000836** NOTE: This routine will fail on pre-sys7 machines.
837** The caller is responsible for not calling this routine
838** in those cases (which is fine, since everyone calling
839** this is probably sys7 dependent anyway).
840*/
841int
Guido van Rossum8f691791995-01-18 23:57:26 +0000842PyMac_GetFSSpec(PyObject *v, FSSpec *fs)
Jack Jansen5f653091995-01-18 13:53:49 +0000843{
844 Str255 path;
845 short refnum;
846 long parid;
847 OSErr err;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000848 FSSpec *fs2;
Jack Jansen5f653091995-01-18 13:53:49 +0000849
Jack Jansene8e8ae01995-01-26 16:36:45 +0000850 /* first check whether it already is an FSSpec */
851 fs2 = mfs_GetFSSpecFSSpec(v);
852 if ( fs2 ) {
Jack Jansen3ec804a1995-02-20 15:56:10 +0000853 (void)FSMakeFSSpec(fs2->vRefNum, fs2->parID, fs2->name, fs);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000854 return 1;
855 }
Jack Jansen5f653091995-01-18 13:53:49 +0000856 if ( PyString_Check(v) ) {
857 /* It's a pathname */
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000858 if( !PyArg_Parse(v, "O&", PyMac_GetStr255, &path) )
Jack Jansen5f653091995-01-18 13:53:49 +0000859 return 0;
Jack Jansen378815c1996-03-06 16:21:34 +0000860 refnum = 0; /* XXXX Should get CurWD here?? */
Jack Jansen5f653091995-01-18 13:53:49 +0000861 parid = 0;
862 } else {
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000863 if( !PyArg_Parse(v, "(hlO&); FSSpec should be fullpath or (vrefnum,dirid,path)",
864 &refnum, &parid, PyMac_GetStr255, &path)) {
Jack Jansen5f653091995-01-18 13:53:49 +0000865 return 0;
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000866 }
Jack Jansen5f653091995-01-18 13:53:49 +0000867 }
868 err = FSMakeFSSpec(refnum, parid, path, fs);
869 if ( err && err != fnfErr ) {
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000870 PyErr_Mac(PyExc_ValueError, err);
Jack Jansen5f653091995-01-18 13:53:49 +0000871 return 0;
872 }
873 return 1;
874}
875
Guido van Rossum8f691791995-01-18 23:57:26 +0000876
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000877/* Convert a Python object to a Rect.
Guido van Rossum5279ec61995-01-26 22:56:59 +0000878 The object must be a (left, top, right, bottom) tuple.
879 (This differs from the order in the struct but is consistent with
880 the arguments to SetRect(), and also with STDWIN). */
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000881int
882PyMac_GetRect(PyObject *v, Rect *r)
Guido van Rossum8f691791995-01-18 23:57:26 +0000883{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000884 return PyArg_Parse(v, "(hhhh)", &r->left, &r->top, &r->right, &r->bottom);
Guido van Rossum8f691791995-01-18 23:57:26 +0000885}
Guido van Rossumb3404661995-01-22 18:36:13 +0000886
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000887/* Convert a Rect to a Python object */
Guido van Rossumb3404661995-01-22 18:36:13 +0000888PyObject *
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000889PyMac_BuildRect(Rect *r)
Guido van Rossumb3404661995-01-22 18:36:13 +0000890{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000891 return Py_BuildValue("(hhhh)", r->left, r->top, r->right, r->bottom);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000892}
893
894
895/* Convert a Python object to a Point.
Guido van Rossum5279ec61995-01-26 22:56:59 +0000896 The object must be a (h, v) tuple.
897 (This differs from the order in the struct but is consistent with
898 the arguments to SetPoint(), and also with STDWIN). */
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000899int
900PyMac_GetPoint(PyObject *v, Point *p)
901{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000902 return PyArg_Parse(v, "(hh)", &p->h, &p->v);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000903}
904
905/* Convert a Point to a Python object */
906PyObject *
907PyMac_BuildPoint(Point p)
908{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000909 return Py_BuildValue("(hh)", p.h, p.v);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000910}
911
912
913/* Convert a Python object to an EventRecord.
914 The object must be a (what, message, when, (v, h), modifiers) tuple. */
915int
916PyMac_GetEventRecord(PyObject *v, EventRecord *e)
917{
918 return PyArg_Parse(v, "(hll(hh)h)",
919 &e->what,
920 &e->message,
921 &e->when,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000922 &e->where.h,
Guido van Rossum5279ec61995-01-26 22:56:59 +0000923 &e->where.v,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000924 &e->modifiers);
925}
926
927/* Convert a Rect to an EventRecord object */
928PyObject *
929PyMac_BuildEventRecord(EventRecord *e)
930{
931 return Py_BuildValue("(hll(hh)h)",
932 e->what,
933 e->message,
934 e->when,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000935 e->where.h,
Guido van Rossum5279ec61995-01-26 22:56:59 +0000936 e->where.v,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000937 e->modifiers);
Guido van Rossumb3404661995-01-22 18:36:13 +0000938}
Jack Jansenfa4d5d01995-11-15 15:19:29 +0000939
940/* Convert Python object to Fixed */
941int
942PyMac_GetFixed(PyObject *v, Fixed *f)
943{
944 double d;
945
946 if( !PyArg_Parse(v, "d", &d))
947 return 0;
948 *f = (Fixed)(d * 0x10000);
Jack Jansen31dd5c01996-05-31 13:01:39 +0000949 return 1;
Jack Jansenfa4d5d01995-11-15 15:19:29 +0000950}
951
952/* Convert a Point to a Python object */
953PyObject *
954PyMac_BuildFixed(Fixed f)
955{
956 double d;
957
958 d = f;
959 d = d / 0x10000;
960 return Py_BuildValue("d", d);
961}
962