blob: 17bbff00ede1f7dc574b9e8ee9a846c8811c5550 [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 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;
132static long yield_bg = 12;
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
181#ifdef __CFM68K__
Jack Jansencfadbd41996-08-19 11:36:25 +0000182void SpinCursor(short x) { /* Dummy */ }
183#endif /* __CFM68K */
184
Jack Jansenf6865f71996-09-04 15:24:59 +0000185/*
186** Replacement GUSI Spin function
187*/
188static int
189PyMac_GUSISpin(spin_msg msg, long arg)
190{
191 static Boolean inForeground = true;
Jack Jansenf6865f71996-09-04 15:24:59 +0000192 int maysleep;
193
194 if (PyMac_ConsoleIsDead) return 0;
195#if 0
196 if (inForeground)
197 SpinCursor(msg == SP_AUTO_SPIN ? short(arg) : 1);
198#endif
199
200 if (interrupted) return -1;
201
202 if ( msg == SP_AUTO_SPIN || ((msg==SP_SLEEP||msg==SP_SELECT) && arg <= yield_fg))
203 maysleep = 0;
204 else
205 maysleep = 0;
206
207 PyMac_DoYield(maysleep);
208
209 return 0;
210}
211
212void
213PyMac_SetGUSISpin() {
214 GUSISetHook(GUSI_SpinHook, (GUSIHook)PyMac_GUSISpin);
215}
216
Jack Jansen378815c1996-03-06 16:21:34 +0000217#endif
218
Jack Jansen819f1771995-08-14 12:35:10 +0000219
Jack Jansen5f653091995-01-18 13:53:49 +0000220/* Convert C to Pascal string. Returns pointer to static buffer. */
221unsigned char *
222Pstring(char *str)
223{
224 static Str255 buf;
225 int len;
226
227 len = strlen(str);
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000228 if (len > 255)
229 len = 255;
Jack Jansen5f653091995-01-18 13:53:49 +0000230 buf[0] = (unsigned char)len;
231 strncpy((char *)buf+1, str, len);
232 return buf;
233}
234
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000235/* Like strerror() but for Mac OS error numbers */
236char *PyMac_StrError(int err)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000237{
238 static char buf[256];
239 Handle h;
240 char *str;
241
242 h = GetResource('Estr', err);
243 if ( h ) {
244 HLock(h);
245 str = (char *)*h;
246 memcpy(buf, str+1, (unsigned char)str[0]);
Guido van Rossumcc9bc8f1995-02-13 16:17:03 +0000247 buf[(unsigned char)str[0]] = '\0';
Jack Jansenf93c72a1994-12-14 14:07:50 +0000248 HUnlock(h);
249 ReleaseResource(h);
250 } else {
251 sprintf(buf, "Mac OS error code %d", err);
252 }
253 return buf;
254}
255
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000256/* Exception object shared by all Mac specific modules for Mac OS errors */
257PyObject *PyMac_OSErrException;
258
259/* Initialize and return PyMac_OSErrException */
260PyObject *
261PyMac_GetOSErrException()
262{
263 if (PyMac_OSErrException == NULL)
264 PyMac_OSErrException = PyString_FromString("Mac OS Error");
265 return PyMac_OSErrException;
266}
267
Jack Jansenf93c72a1994-12-14 14:07:50 +0000268/* Set a MAC-specific error from errno, and return NULL; return None if no error */
269PyObject *
Guido van Rossumfffb8bb1995-01-12 12:37:24 +0000270PyErr_Mac(PyObject *eobj, int err)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000271{
272 char *msg;
273 PyObject *v;
Jack Jansenf93c72a1994-12-14 14:07:50 +0000274
Guido van Rossum8f691791995-01-18 23:57:26 +0000275 if (err == 0 && !PyErr_Occurred()) {
Jack Jansenf93c72a1994-12-14 14:07:50 +0000276 Py_INCREF(Py_None);
277 return Py_None;
278 }
Guido van Rossum8f691791995-01-18 23:57:26 +0000279 if (err == -1 && PyErr_Occurred())
280 return NULL;
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000281 msg = PyMac_StrError(err);
Jack Jansenf93c72a1994-12-14 14:07:50 +0000282 v = Py_BuildValue("(is)", err, msg);
283 PyErr_SetObject(eobj, v);
284 Py_DECREF(v);
285 return NULL;
286}
287
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000288/* Call PyErr_Mac with PyMac_OSErrException */
289PyObject *
290PyMac_Error(OSErr err)
291{
292 return PyErr_Mac(PyMac_GetOSErrException(), err);
293}
294
Jack Jansen1ed95291996-07-22 15:25:10 +0000295#ifdef USE_STACKCHECK
296/* Check for stack overflow */
297int
298PyOS_CheckStack()
299{
300 long left;
301
302 left = StackSpace();
Jack Jansend1f06311996-08-01 15:23:54 +0000303 if ( left < MINIMUM_STACK_SIZE )
Jack Jansen1ed95291996-07-22 15:25:10 +0000304 return -1;
305 return 0;
306}
307#endif /* USE_STACKCHECK */
308
Jack Jansenee23d6e1995-01-27 14:43:25 +0000309/* The catcher routine (which may not be used for all compilers) */
310static RETSIGTYPE
311intcatcher(sig)
312 int sig;
313{
314 interrupted = 1;
315 signal(SIGINT, intcatcher);
316}
317
318void
319PyOS_InitInterrupts()
320{
321 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
322 signal(SIGINT, intcatcher);
323}
324
325/*
326** This routine scans the event queue looking for cmd-.
327** This is the only way to get an interrupt under THINK (since it
328** doesn't do SIGINT handling), but is also used under MW, when
329** the full-fledged event loop is disabled. This way, we can at least
330** interrupt a runaway python program.
331*/
332static void
333scan_event_queue(flush)
334 int flush;
335{
336 register EvQElPtr q;
337
Jack Jansencfadbd41996-08-19 11:36:25 +0000338 q = (EvQElPtr) GetEventQueue()->qHead;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000339
340 for (; q; q = (EvQElPtr)q->qLink) {
341 if (q->evtQWhat == keyDown &&
342 (char)q->evtQMessage == '.' &&
343 (q->evtQModifiers & cmdKey) != 0) {
344 if ( flush )
345 FlushEvents(keyDownMask, 0);
346 interrupted = 1;
347 break;
348 }
349 }
350}
351
352int
353PyOS_InterruptOccurred()
354{
Guido van Rossume7134aa1995-02-26 10:20:53 +0000355 if (PyMac_DoYieldEnabled < 0)
356 return 0;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000357#ifdef THINK_C
358 scan_event_queue(1);
359#endif
360 PyMac_Yield();
361 if (interrupted) {
362 interrupted = 0;
363 return 1;
364 }
365 return 0;
366}
367
368/* intrpeek() is like intrcheck(), but it doesn't flush the events. The
369** idea is that you call intrpeek() somewhere in a busy-wait loop, and return
370** None as soon as it returns 1. The mainloop will then pick up the cmd-. soon
371** thereafter.
372*/
373static int
374intrpeek()
375{
376#ifdef THINK_C
377 scan_event_queue(0);
378#endif
379 return interrupted;
380}
381
382/* Check whether we are in the foreground */
383int
384PyMac_InForeground()
385{
386 static ProcessSerialNumber ours;
387 static inited;
388 ProcessSerialNumber curfg;
389 Boolean eq;
390
391 if ( inited == 0 )
392 (void)GetCurrentProcess(&ours);
393 inited = 1;
394 if ( GetFrontProcess(&curfg) < 0 )
395 eq = 1;
396 else if ( SameProcess(&ours, &curfg, &eq) < 0 )
397 eq = 1;
398 return (int)eq;
399
400}
401
Jack Jansenf93c72a1994-12-14 14:07:50 +0000402/*
Jack Jansene8e8ae01995-01-26 16:36:45 +0000403** Set yield timeouts
Jack Jansenf93c72a1994-12-14 14:07:50 +0000404*/
Jack Jansene8e8ae01995-01-26 16:36:45 +0000405void
406PyMac_SetYield(long fgi, long fgy, long bgi, long bgy)
407{
408 interval_fg = fgi;
409 yield_fg = fgy;
410 interval_bg = bgi;
411 yield_bg = bgy;
412}
413
414/*
Jack Jansena76382a1995-02-02 14:25:56 +0000415** Handle an event, either one found in the mainloop eventhandler or
416** one passed back from the python program.
417*/
418void
419PyMac_HandleEvent(evp)
420 EventRecord *evp;
421{
Jack Jansena76382a1995-02-02 14:25:56 +0000422
423#ifdef __MWERKS__
Jack Jansen38e97661995-11-10 14:53:00 +0000424 {
425 int siouxdidit;
426
427 /* If SIOUX wants it we're done */
428 siouxdidit = SIOUXHandleOneEvent(evp);
429 if ( siouxdidit )
430 return;
431 }
Jack Jansena76382a1995-02-02 14:25:56 +0000432#else
433 /* Other compilers are just unlucky: we only weed out clicks in other applications */
434 if ( evp->what == mouseDown ) {
Jack Jansen847e89e1995-08-31 13:57:40 +0000435 WindowPtr wp;
436
Jack Jansen38e97661995-11-10 14:53:00 +0000437 if ( FindWindow(evp->where, &wp) == inSysWindow ) {
Jack Jansena76382a1995-02-02 14:25:56 +0000438 SystemClick(evp, wp);
Jack Jansen38e97661995-11-10 14:53:00 +0000439 return;
440 }
Jack Jansena76382a1995-02-02 14:25:56 +0000441 }
442#endif /* !__MWERKS__ */
443}
444
445/*
Jack Jansene8e8ae01995-01-26 16:36:45 +0000446** Yield the CPU to other tasks.
447*/
Jack Jansencfadbd41996-08-19 11:36:25 +0000448static void
Jack Jansenf6865f71996-09-04 15:24:59 +0000449PyMac_DoYield(int maysleep)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000450{
451 EventRecord ev;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000452 long yield;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000453 static int no_waitnextevent = -1;
454 int gotone;
455
456 if ( no_waitnextevent < 0 ) {
457 no_waitnextevent = (NGetTrapAddress(_WaitNextEvent, ToolTrap) ==
458 NGetTrapAddress(_Unimplemented, ToolTrap));
459 }
Jack Jansenf93c72a1994-12-14 14:07:50 +0000460
Jack Jansenf6865f71996-09-04 15:24:59 +0000461 lastyield = TickCount();
Jack Jansenee23d6e1995-01-27 14:43:25 +0000462#ifndef THINK_C
Jack Jansenf6865f71996-09-04 15:24:59 +0000463 /* Under think this has been done before in intrcheck() or intrpeek() */
464 if (PyMac_DoYieldEnabled >= 0)
Jack Jansenee23d6e1995-01-27 14:43:25 +0000465 scan_event_queue(0);
466#endif
Jack Jansenf6865f71996-09-04 15:24:59 +0000467 if (PyMac_DoYieldEnabled == 0)
Jack Jansene8e8ae01995-01-26 16:36:45 +0000468 return;
469
Jack Jansenee23d6e1995-01-27 14:43:25 +0000470 in_foreground = PyMac_InForeground();
Jack Jansenf6865f71996-09-04 15:24:59 +0000471 if ( maysleep ) {
472 if ( in_foreground )
473 yield = yield_fg;
474 else
475 yield = yield_bg;
476 } else {
477 yield = 0;
478 }
479
Jack Jansene8e8ae01995-01-26 16:36:45 +0000480 while ( 1 ) {
481 if ( no_waitnextevent ) {
482 SystemTask();
Jack Jansenee23d6e1995-01-27 14:43:25 +0000483 gotone = GetNextEvent(MAINLOOP_EVENTMASK, &ev);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000484 } else {
Jack Jansenee23d6e1995-01-27 14:43:25 +0000485 gotone = WaitNextEvent(MAINLOOP_EVENTMASK, &ev, yield, NULL);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000486 }
487 /* Get out quickly if nothing interesting is happening */
488 if ( !gotone || ev.what == nullEvent )
489 break;
Jack Jansena76382a1995-02-02 14:25:56 +0000490 PyMac_HandleEvent(&ev);
Jack Jansenf93c72a1994-12-14 14:07:50 +0000491 }
Jack Jansene8e8ae01995-01-26 16:36:45 +0000492}
493
494/*
495** Yield the CPU to other tasks if opportune
496*/
497void
498PyMac_Yield() {
499 long iv;
500
Jack Jansenee23d6e1995-01-27 14:43:25 +0000501 if ( in_foreground )
Jack Jansene8e8ae01995-01-26 16:36:45 +0000502 iv = interval_fg;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000503 else
504 iv = interval_bg;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000505 if ( TickCount() > lastyield + iv )
Jack Jansenf6865f71996-09-04 15:24:59 +0000506 PyMac_DoYield(1);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000507}
508
Jack Jansenf6865f71996-09-04 15:24:59 +0000509#ifdef USE_MACTCP
Jack Jansene8e8ae01995-01-26 16:36:45 +0000510/*
511** Idle routine for busy-wait loops.
512** Gives up CPU, handles events and returns true if an interrupt is pending
513** (but not actually handled yet).
514*/
515int
516PyMac_Idle()
517{
Jack Jansenf6865f71996-09-04 15:24:59 +0000518 PyMac_DoYield(1);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000519 return intrpeek();
Jack Jansenf93c72a1994-12-14 14:07:50 +0000520}
Jack Jansenf6865f71996-09-04 15:24:59 +0000521#endif
522
Jack Jansen74162f31995-02-15 22:58:33 +0000523/*
Jack Jansen3469e991996-09-06 00:30:45 +0000524** Install our menu bar.
525*/
526void
527PyMac_InitMenuBar()
528{
529 Handle bar;
530 MenuHandle applemenu;
531
532 if ( (bar=GetMenuBar()) == NULL ) return;
533 if ( (applemenu=GetMHandle(SIOUX_APPLEID)) == NULL ) return;
534 SetMenuItemText(applemenu, 1, "\pAbout Python...");
535}
536
537/*
538** Our replacement about box
539*/
540void
541SIOUXDoAboutBox(void)
542{
543 DialogPtr theDialog;
544 short item;
545
546 if( (theDialog = GetNewDialog(ABOUT_ID, NULL, (WindowPtr)-1)) == NULL )
547 return;
548 ModalDialog(NULL, &item);
549 DisposeDialog(theDialog);
550}
551
552/*
Jack Jansen74162f31995-02-15 22:58:33 +0000553** Returns true if the argument has a resource fork, and it contains
554** a 'PYC ' resource of the correct name
555*/
556int
557PyMac_FindResourceModule(module, filename)
558char *module;
559char *filename;
560{
561 FSSpec fss;
562 FInfo finfo;
563 short oldrh, filerh;
564 int ok;
565 Handle h;
566
567 if ( FSMakeFSSpec(0, 0, Pstring(filename), &fss) != noErr )
568 return 0; /* It doesn't exist */
569 if ( FSpGetFInfo(&fss, &finfo) != noErr )
570 return 0; /* shouldn't happen, I guess */
Jack Jansen74162f31995-02-15 22:58:33 +0000571 oldrh = CurResFile();
572 filerh = FSpOpenResFile(&fss, fsRdPerm);
573 if ( filerh == -1 )
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000574 return 0;
Jack Jansen74162f31995-02-15 22:58:33 +0000575 UseResFile(filerh);
576 SetResLoad(0);
577 h = Get1NamedResource('PYC ', Pstring(module));
578 SetResLoad(1);
579 ok = (h != NULL);
580 CloseResFile(filerh);
581 UseResFile(oldrh);
582 return ok;
583}
584
585/*
586** Load the specified module from a resource
587*/
588PyObject *
589PyMac_LoadResourceModule(module, filename)
590char *module;
591char *filename;
592{
593 FSSpec fss;
594 FInfo finfo;
595 short oldrh, filerh;
Jack Jansen74162f31995-02-15 22:58:33 +0000596 Handle h;
597 OSErr err;
598 PyObject *m, *co;
599 long num, size;
600
601 if ( (err=FSMakeFSSpec(0, 0, Pstring(filename), &fss)) != noErr )
602 goto error;
603 if ( (err=FSpGetFInfo(&fss, &finfo)) != noErr )
604 goto error;
Jack Jansen74162f31995-02-15 22:58:33 +0000605 oldrh = CurResFile();
606 filerh = FSpOpenResFile(&fss, fsRdPerm);
607 if ( filerh == -1 ) {
608 err = ResError();
609 goto error;
610 }
611 UseResFile(filerh);
612 h = Get1NamedResource('PYC ', Pstring(module));
613 if ( h == NULL ) {
614 err = ResError();
615 goto error;
616 }
617 HLock(h);
618 /*
619 ** XXXX The next few lines are intimately tied to the format of pyc
620 ** files. I'm not sure whether this code should be here or in import.c -- Jack
621 */
622 size = GetHandleSize(h);
623 if ( size < 8 ) {
624 PyErr_SetString(PyExc_ImportError, "Resource too small");
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000625 co = NULL;
Jack Jansen74162f31995-02-15 22:58:33 +0000626 } else {
627 num = (*h)[0] & 0xff;
628 num = num | (((*h)[1] & 0xff) << 8);
629 num = num | (((*h)[2] & 0xff) << 16);
630 num = num | (((*h)[3] & 0xff) << 24);
631 if ( num != PyImport_GetMagicNumber() ) {
632 PyErr_SetString(PyExc_ImportError, "Bad MAGIC in resource");
633 co = NULL;
634 } else {
635 co = PyMarshal_ReadObjectFromString((*h)+8, size-8);
636 }
637 }
638 HUnlock(h);
639 CloseResFile(filerh);
640 UseResFile(oldrh);
641 if ( co ) {
642 m = PyImport_ExecCodeModule(module, co);
643 Py_DECREF(co);
644 } else {
645 m = NULL;
646 }
647 return m;
648error:
649 {
650 char buf[512];
651
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000652 sprintf(buf, "%s: %s", filename, PyMac_StrError(err));
Jack Jansen74162f31995-02-15 22:58:33 +0000653 PyErr_SetString(PyExc_ImportError, buf);
654 return NULL;
655 }
656}
Guido van Rossum24a45e31995-02-20 23:45:53 +0000657
Jack Jansen3ec804a1995-02-20 15:56:10 +0000658/*
659** Helper routine for GetDirectory
660*/
Guido van Rossum24a45e31995-02-20 23:45:53 +0000661static pascal short
Jack Jansen819f1771995-08-14 12:35:10 +0000662myhook_proc(short item, DialogPtr theDialog, struct hook_args *dataptr)
Jack Jansen3ec804a1995-02-20 15:56:10 +0000663{
Jack Jansen819f1771995-08-14 12:35:10 +0000664 if ( item == sfHookFirstCall && dataptr->prompt) {
665 Handle prompth;
666 short type;
667 Rect rect;
668
669 GetDialogItem(theDialog, PROMPT_ITEM, &type, &prompth, &rect);
670 if ( prompth )
671 SetDialogItemText(prompth, (unsigned char *)dataptr->prompt);
672 } else
Jack Jansen3ec804a1995-02-20 15:56:10 +0000673 if ( item == SELECTCUR_ITEM ) {
674 item = sfItemCancelButton;
Jack Jansen819f1771995-08-14 12:35:10 +0000675 dataptr->selectcur_hit = 1;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000676 }
677 return item;
678}
679
680/*
681** Ask the user for a directory. I still can't understand
682** why Apple doesn't provide a standard solution for this...
683*/
684int
Jack Jansen819f1771995-08-14 12:35:10 +0000685PyMac_GetDirectory(dirfss, prompt)
Jack Jansen3ec804a1995-02-20 15:56:10 +0000686 FSSpec *dirfss;
Jack Jansen819f1771995-08-14 12:35:10 +0000687 char *prompt;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000688{
689 static SFTypeList list = {'fldr', 0, 0, 0};
690 static Point where = {-1, -1};
Jack Jansen3ec804a1995-02-20 15:56:10 +0000691 StandardFileReply reply;
Jack Jansen819f1771995-08-14 12:35:10 +0000692 struct hook_args hook_args;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000693
694 if ( !upp_inited ) {
695 myhook_upp = NewDlgHookYDProc(myhook_proc);
696 upp_inited = 1;
697 }
Jack Jansen819f1771995-08-14 12:35:10 +0000698 if ( prompt && *prompt )
699 hook_args.prompt = (char *)Pstring(prompt);
700 else
701 hook_args.prompt = NULL;
702 hook_args.selectcur_hit = 0;
Guido van Rossum24a45e31995-02-20 23:45:53 +0000703 CustomGetFile((FileFilterYDUPP)0, 1, list, &reply, GETDIR_ID, where, myhook_upp,
Jack Jansen819f1771995-08-14 12:35:10 +0000704 NULL, NULL, NULL, (void *)&hook_args);
Jack Jansen3ec804a1995-02-20 15:56:10 +0000705
706 reply.sfFile.name[0] = 0;
707 if( FSMakeFSSpec(reply.sfFile.vRefNum, reply.sfFile.parID, reply.sfFile.name, dirfss) )
708 return 0;
Jack Jansen819f1771995-08-14 12:35:10 +0000709 return hook_args.selectcur_hit;
710}
711
712/*
713** Slightly extended StandardGetFile: accepts a prompt */
714void PyMac_PromptGetFile(short numTypes, ConstSFTypeListPtr typeList,
715 StandardFileReply *reply, char *prompt)
716{
717 static Point where = {-1, -1};
718 struct hook_args hook_args;
719
720 if ( !upp_inited ) {
721 myhook_upp = NewDlgHookYDProc(myhook_proc);
722 upp_inited = 1;
723 }
724 if ( prompt && *prompt )
725 hook_args.prompt = (char *)Pstring(prompt);
726 else
727 hook_args.prompt = NULL;
728 hook_args.selectcur_hit = 0;
729 CustomGetFile((FileFilterYDUPP)0, numTypes, typeList, reply, GETFILEPROMPT_ID, where,
730 myhook_upp, NULL, NULL, NULL, (void *)&hook_args);
Jack Jansen3ec804a1995-02-20 15:56:10 +0000731}
Jack Jansen5f653091995-01-18 13:53:49 +0000732
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000733/* Convert a 4-char string object argument to an OSType value */
Jack Jansen5f653091995-01-18 13:53:49 +0000734int
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000735PyMac_GetOSType(PyObject *v, OSType *pr)
Jack Jansen5f653091995-01-18 13:53:49 +0000736{
737 if (!PyString_Check(v) || PyString_Size(v) != 4) {
738 PyErr_SetString(PyExc_TypeError,
739 "OSType arg must be string of 4 chars");
740 return 0;
741 }
742 memcpy((char *)pr, PyString_AsString(v), 4);
743 return 1;
744}
745
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000746/* Convert an OSType value to a 4-char string object */
747PyObject *
748PyMac_BuildOSType(OSType t)
749{
750 return PyString_FromStringAndSize((char *)&t, 4);
751}
752
Jack Jansend1f06311996-08-01 15:23:54 +0000753/* Convert an NumVersion value to a 4-element tuple */
754PyObject *
755PyMac_BuildNumVersion(NumVersion t)
756{
757 return Py_BuildValue("(hhhh)", t.majorRev, t.minorAndBugRev, t.stage, t.nonRelRev);
758}
759
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000760
761/* Convert a Python string object to a Str255 */
Jack Jansen5f653091995-01-18 13:53:49 +0000762int
Guido van Rossum8f691791995-01-18 23:57:26 +0000763PyMac_GetStr255(PyObject *v, Str255 pbuf)
Jack Jansen5f653091995-01-18 13:53:49 +0000764{
765 int len;
766 if (!PyString_Check(v) || (len = PyString_Size(v)) > 255) {
767 PyErr_SetString(PyExc_TypeError,
768 "Str255 arg must be string of at most 255 chars");
769 return 0;
770 }
771 pbuf[0] = len;
772 memcpy((char *)(pbuf+1), PyString_AsString(v), len);
773 return 1;
774}
775
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000776/* Convert a Str255 to a Python string object */
777PyObject *
778PyMac_BuildStr255(Str255 s)
779{
780 return PyString_FromStringAndSize((char *)&s[1], (int)s[0]);
781}
782
783
Jack Jansen5f653091995-01-18 13:53:49 +0000784/*
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000785** Convert a Python object to an FSSpec.
786** The object may either be a full pathname or a triple
787** (vrefnum, dirid, path).
Jack Jansen5f653091995-01-18 13:53:49 +0000788** NOTE: This routine will fail on pre-sys7 machines.
789** The caller is responsible for not calling this routine
790** in those cases (which is fine, since everyone calling
791** this is probably sys7 dependent anyway).
792*/
793int
Guido van Rossum8f691791995-01-18 23:57:26 +0000794PyMac_GetFSSpec(PyObject *v, FSSpec *fs)
Jack Jansen5f653091995-01-18 13:53:49 +0000795{
796 Str255 path;
797 short refnum;
798 long parid;
799 OSErr err;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000800 FSSpec *fs2;
Jack Jansen5f653091995-01-18 13:53:49 +0000801
Jack Jansene8e8ae01995-01-26 16:36:45 +0000802 /* first check whether it already is an FSSpec */
803 fs2 = mfs_GetFSSpecFSSpec(v);
804 if ( fs2 ) {
Jack Jansen3ec804a1995-02-20 15:56:10 +0000805 (void)FSMakeFSSpec(fs2->vRefNum, fs2->parID, fs2->name, fs);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000806 return 1;
807 }
Jack Jansen5f653091995-01-18 13:53:49 +0000808 if ( PyString_Check(v) ) {
809 /* It's a pathname */
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000810 if( !PyArg_Parse(v, "O&", PyMac_GetStr255, &path) )
Jack Jansen5f653091995-01-18 13:53:49 +0000811 return 0;
Jack Jansen378815c1996-03-06 16:21:34 +0000812 refnum = 0; /* XXXX Should get CurWD here?? */
Jack Jansen5f653091995-01-18 13:53:49 +0000813 parid = 0;
814 } else {
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000815 if( !PyArg_Parse(v, "(hlO&); FSSpec should be fullpath or (vrefnum,dirid,path)",
816 &refnum, &parid, PyMac_GetStr255, &path)) {
Jack Jansen5f653091995-01-18 13:53:49 +0000817 return 0;
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000818 }
Jack Jansen5f653091995-01-18 13:53:49 +0000819 }
820 err = FSMakeFSSpec(refnum, parid, path, fs);
821 if ( err && err != fnfErr ) {
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000822 PyErr_Mac(PyExc_ValueError, err);
Jack Jansen5f653091995-01-18 13:53:49 +0000823 return 0;
824 }
825 return 1;
826}
827
Guido van Rossum8f691791995-01-18 23:57:26 +0000828
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000829/* Convert a Python object to a Rect.
Guido van Rossum5279ec61995-01-26 22:56:59 +0000830 The object must be a (left, top, right, bottom) tuple.
831 (This differs from the order in the struct but is consistent with
832 the arguments to SetRect(), and also with STDWIN). */
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000833int
834PyMac_GetRect(PyObject *v, Rect *r)
Guido van Rossum8f691791995-01-18 23:57:26 +0000835{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000836 return PyArg_Parse(v, "(hhhh)", &r->left, &r->top, &r->right, &r->bottom);
Guido van Rossum8f691791995-01-18 23:57:26 +0000837}
Guido van Rossumb3404661995-01-22 18:36:13 +0000838
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000839/* Convert a Rect to a Python object */
Guido van Rossumb3404661995-01-22 18:36:13 +0000840PyObject *
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000841PyMac_BuildRect(Rect *r)
Guido van Rossumb3404661995-01-22 18:36:13 +0000842{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000843 return Py_BuildValue("(hhhh)", r->left, r->top, r->right, r->bottom);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000844}
845
846
847/* Convert a Python object to a Point.
Guido van Rossum5279ec61995-01-26 22:56:59 +0000848 The object must be a (h, v) tuple.
849 (This differs from the order in the struct but is consistent with
850 the arguments to SetPoint(), and also with STDWIN). */
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000851int
852PyMac_GetPoint(PyObject *v, Point *p)
853{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000854 return PyArg_Parse(v, "(hh)", &p->h, &p->v);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000855}
856
857/* Convert a Point to a Python object */
858PyObject *
859PyMac_BuildPoint(Point p)
860{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000861 return Py_BuildValue("(hh)", p.h, p.v);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000862}
863
864
865/* Convert a Python object to an EventRecord.
866 The object must be a (what, message, when, (v, h), modifiers) tuple. */
867int
868PyMac_GetEventRecord(PyObject *v, EventRecord *e)
869{
870 return PyArg_Parse(v, "(hll(hh)h)",
871 &e->what,
872 &e->message,
873 &e->when,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000874 &e->where.h,
Guido van Rossum5279ec61995-01-26 22:56:59 +0000875 &e->where.v,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000876 &e->modifiers);
877}
878
879/* Convert a Rect to an EventRecord object */
880PyObject *
881PyMac_BuildEventRecord(EventRecord *e)
882{
883 return Py_BuildValue("(hll(hh)h)",
884 e->what,
885 e->message,
886 e->when,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000887 e->where.h,
Guido van Rossum5279ec61995-01-26 22:56:59 +0000888 e->where.v,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000889 e->modifiers);
Guido van Rossumb3404661995-01-22 18:36:13 +0000890}
Jack Jansenfa4d5d01995-11-15 15:19:29 +0000891
892/* Convert Python object to Fixed */
893int
894PyMac_GetFixed(PyObject *v, Fixed *f)
895{
896 double d;
897
898 if( !PyArg_Parse(v, "d", &d))
899 return 0;
900 *f = (Fixed)(d * 0x10000);
Jack Jansen31dd5c01996-05-31 13:01:39 +0000901 return 1;
Jack Jansenfa4d5d01995-11-15 15:19:29 +0000902}
903
904/* Convert a Point to a Python object */
905PyObject *
906PyMac_BuildFixed(Fixed f)
907{
908 double d;
909
910 d = f;
911 d = d / 0x10000;
912 return Py_BuildValue("d", d);
913}
914