blob: 46493d3c7e4f966e98997f1c9b4b31c211b8346b [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 Janseneda78631997-06-12 15:29:46 +000044#include "importdl.h"
Jack Jansenf93c72a1994-12-14 14:07:50 +000045
Jack Jansen819f1771995-08-14 12:35:10 +000046#include "pythonresources.h"
47
Jack Jansenf93c72a1994-12-14 14:07:50 +000048#include <OSUtils.h> /* for Set(Current)A5 */
Jack Jansene8e8ae01995-01-26 16:36:45 +000049#include <Files.h>
Jack Jansen8cd2b721995-02-13 11:33:28 +000050#include <StandardFile.h>
Jack Jansenf93c72a1994-12-14 14:07:50 +000051#include <Resources.h>
52#include <Memory.h>
Jack Jansenf93c72a1994-12-14 14:07:50 +000053#include <Windows.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
Jack Jansenee23d6e1995-01-27 14:43:25 +000074#include <signal.h>
Jack Jansen74162f31995-02-15 22:58:33 +000075#include <stdio.h>
Jack Jansene8e8ae01995-01-26 16:36:45 +000076
Jack Jansenee23d6e1995-01-27 14:43:25 +000077/*
Jack Jansend1f06311996-08-01 15:23:54 +000078** When less than this amount of stackspace is left we
79** raise a MemoryError.
80*/
81#ifndef MINIMUM_STACK_SIZE
82#ifdef __powerc
83#define MINIMUM_STACK_SIZE 8192
84#else
85#define MINIMUM_STACK_SIZE 4096
86#endif
87#endif
88
89/*
Jack Jansen16df2aa1995-02-27 16:17:28 +000090** We have to be careful, since we can't handle
Jack Jansenee23d6e1995-01-27 14:43:25 +000091** things like updates (and they'll keep coming back if we don't
Jack Jansen16df2aa1995-02-27 16:17:28 +000092** handle them). Note that we don't know who has windows open, so
93** even handing updates off to SIOUX under MW isn't going to work.
Jack Jansenee23d6e1995-01-27 14:43:25 +000094*/
Jack Jansen0c968871997-08-26 13:20:34 +000095#define MAINLOOP_EVENTMASK (mDownMask|keyDownMask|osMask|activMask)
Jack Jansene8e8ae01995-01-26 16:36:45 +000096
97#include <signal.h>
Jack Jansenf93c72a1994-12-14 14:07:50 +000098
Guido van Rossumb3404661995-01-22 18:36:13 +000099/* XXX We should include Errors.h here, but it has a name conflict
Jack Jansen5f653091995-01-18 13:53:49 +0000100** with the python errors.h. */
101#define fnfErr -43
102
Jack Jansene8e8ae01995-01-26 16:36:45 +0000103/* Declared in macfsmodule.c: */
104extern FSSpec *mfs_GetFSSpecFSSpec();
Jack Jansen8bb573e1999-12-12 21:37:14 +0000105extern PyObject *newmfssobject Py_PROTO((FSSpec *));
Jack Jansene8e8ae01995-01-26 16:36:45 +0000106
Jack Jansenee23d6e1995-01-27 14:43:25 +0000107/* Interrupt code variables: */
108static int interrupted; /* Set to true when cmd-. seen */
109static RETSIGTYPE intcatcher Py_PROTO((int));
110
Jack Jansen36ed5061997-06-20 16:18:15 +0000111static int PyMac_DoYield Py_PROTO((int, int));
112static int PyMac_Yield Py_PROTO((void));
Jack Jansenf6865f71996-09-04 15:24:59 +0000113
Jack Jansene8e8ae01995-01-26 16:36:45 +0000114/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000115** These are the real scheduling parameters that control what we check
116** in the event loop, and how often we check. The values are initialized
117** from pyMac_SchedParamStruct.
118*/
119
120struct real_sched_param_struct {
121 int check_interrupt; /* if true check for command-dot */
122 int process_events; /* if nonzero enable evt processing, this mask */
123 int besocial; /* if nonzero be a little social with CPU */
124 unsigned long check_interval; /* how often to check, in ticks */
125 unsigned long bg_yield; /* yield so long when in background */
126 /* these are computed from previous and clock and such */
127 int enabled; /* check_interrupt OR process_event OR yield */
128 unsigned long next_check; /* when to check/yield next, in ticks */
129};
130
131static struct real_sched_param_struct schedparams =
132 { 1, MAINLOOP_EVENTMASK, 1, 15, 15, 1, 0};
133
Jack Jansen819f1771995-08-14 12:35:10 +0000134/*
Jack Jansenf6865f71996-09-04 15:24:59 +0000135** Workaround for sioux/gusi combo: set when we are exiting
136*/
137int PyMac_ConsoleIsDead;
138
139/*
Jack Jansencaa7c461997-06-12 10:49:13 +0000140** Sioux menu bar, saved early so we can restore it
141*/
142static Handle sioux_mbar;
143
144/*
Jack Jansen819f1771995-08-14 12:35:10 +0000145** Some stuff for our GetDirectory and PromptGetFile routines
146*/
147struct hook_args {
148 int selectcur_hit; /* Set to true when "select current" selected */
149 char *prompt; /* The prompt */
150};
151static DlgHookYDUPP myhook_upp;
152static int upp_inited = 0;
153
Jack Jansen36ed5061997-06-20 16:18:15 +0000154/*
155** The python-code event handler
156*/
157static PyObject *python_event_handler;
158
Jack Jansen8f5725a1999-12-07 23:08:10 +0000159/*
160** Set to true if we're appearance-compliant
161*/
162int PyMac_AppearanceCompliant;
163
Jack Jansen378815c1996-03-06 16:21:34 +0000164#ifdef USE_GUSI
165/*
166** GUSI (1.6.0 and earlier, at the least) do not set the MacOS idea of
167** the working directory. Hence, we call this routine after each call
168** to chdir() to rectify things.
169*/
170void
171PyMac_FixGUSIcd()
172{
173 WDPBRec pb;
174 FSSpec curdirfss;
175
176 if ( Path2FSSpec(":x", &curdirfss) != noErr )
177 return;
178
179 /* Set MacOS "working directory" */
180 pb.ioNamePtr= "\p";
181 pb.ioVRefNum= curdirfss.vRefNum;
182 pb.ioWDDirID= curdirfss.parID;
Jack Jansen08c3be31997-04-08 15:27:00 +0000183 if (PBHSetVolSync(&pb) != noErr)
Jack Jansen378815c1996-03-06 16:21:34 +0000184 return;
Jack Jansen378815c1996-03-06 16:21:34 +0000185}
Jack Jansen7ac70af1996-08-19 11:01:05 +0000186
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000187/*
188** SpinCursor (needed by GUSI) drags in heaps of stuff, so we
189** provide a dummy here.
190*/
Jack Jansencfadbd41996-08-19 11:36:25 +0000191void SpinCursor(short x) { /* Dummy */ }
Jack Jansenefaada71998-02-20 16:03:15 +0000192void RotateCursor(short x) { /* Dummy */ }
Jack Jansencfadbd41996-08-19 11:36:25 +0000193
Jack Jansenf6865f71996-09-04 15:24:59 +0000194/*
195** Replacement GUSI Spin function
196*/
197static int
198PyMac_GUSISpin(spin_msg msg, long arg)
199{
Jack Jansene3ae0df1997-06-03 15:28:29 +0000200 static Boolean inForeground = true;
201 int maxsleep = 6; /* 6 ticks is "normal" sleeptime */
Jack Jansenf6865f71996-09-04 15:24:59 +0000202
203 if (PyMac_ConsoleIsDead) return 0;
204#if 0
205 if (inForeground)
206 SpinCursor(msg == SP_AUTO_SPIN ? short(arg) : 1);
207#endif
208
209 if (interrupted) return -1;
210
Jack Jansene3ae0df1997-06-03 15:28:29 +0000211 if ( msg == SP_AUTO_SPIN )
212 maxsleep = 0;
213 if ( msg==SP_SLEEP||msg==SP_SELECT )
214 maxsleep = arg;
Jack Jansenf6865f71996-09-04 15:24:59 +0000215
Jack Jansene3ae0df1997-06-03 15:28:29 +0000216 PyMac_DoYield(maxsleep, 0); /* XXXX or is it safe to call python here? */
Jack Jansenf6865f71996-09-04 15:24:59 +0000217
218 return 0;
219}
220
221void
222PyMac_SetGUSISpin() {
223 GUSISetHook(GUSI_SpinHook, (GUSIHook)PyMac_GUSISpin);
224}
225
Jack Jansena39f1b01997-05-23 15:35:14 +0000226/* Called at exit() time thru atexit(), to stop event processing */
227void
228PyMac_StopGUSISpin() {
229 PyMac_ConsoleIsDead = 1;
230}
231
232/*
233** Replacement routines for the PLstr... functions so we don't need
234** StdCLib. Moreover, that implementation is broken under cfm68k...
235*/
Jack Jansen8bb573e1999-12-12 21:37:14 +0000236pascal void
Jack Jansena39f1b01997-05-23 15:35:14 +0000237PLstrcpy(to, fr)
238 unsigned char *to, *fr;
239{
240 memcpy(to, fr, fr[0]+1);
241}
242
Jack Jansen8bb573e1999-12-12 21:37:14 +0000243pascal int
Jack Jansena39f1b01997-05-23 15:35:14 +0000244PLstrcmp(s1, s2)
245 unsigned char *s1, *s2;
246{
247 int res;
248 int l = s1[0] < s2[0] ? s1[0] : s2[0];
249
250 res = memcmp(s1+1, s2+1, l);
251 if ( res != 0 )
252 return res;
253
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000254 if ( s1[0] < s2[0] )
Jack Jansena39f1b01997-05-23 15:35:14 +0000255 return -1;
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000256 else if ( s1[0] > s2[0] )
Jack Jansena39f1b01997-05-23 15:35:14 +0000257 return 1;
258 else
259 return 0;
260}
261
Jack Jansen8bb573e1999-12-12 21:37:14 +0000262pascal unsigned char *
Jack Jansena39f1b01997-05-23 15:35:14 +0000263PLstrrchr(str, chr)
264 unsigned char *str;
265 unsigned char chr;
266{
267 unsigned char *ptr = 0;
268 unsigned char *p;
269
270 for(p=str+1; p<str+str[0]; p++)
271 if ( *p == chr )
272 ptr = p;
273 return ptr;
274}
275
276#endif /* USE_GUSI */
Jack Jansen378815c1996-03-06 16:21:34 +0000277
Jack Jansen819f1771995-08-14 12:35:10 +0000278
Jack Jansen5f653091995-01-18 13:53:49 +0000279/* Convert C to Pascal string. Returns pointer to static buffer. */
280unsigned char *
281Pstring(char *str)
282{
283 static Str255 buf;
284 int len;
285
286 len = strlen(str);
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000287 if (len > 255)
288 len = 255;
Jack Jansen5f653091995-01-18 13:53:49 +0000289 buf[0] = (unsigned char)len;
290 strncpy((char *)buf+1, str, len);
291 return buf;
292}
293
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000294/* Like strerror() but for Mac OS error numbers */
295char *PyMac_StrError(int err)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000296{
297 static char buf[256];
298 Handle h;
299 char *str;
300
301 h = GetResource('Estr', err);
302 if ( h ) {
303 HLock(h);
304 str = (char *)*h;
305 memcpy(buf, str+1, (unsigned char)str[0]);
Guido van Rossumcc9bc8f1995-02-13 16:17:03 +0000306 buf[(unsigned char)str[0]] = '\0';
Jack Jansenf93c72a1994-12-14 14:07:50 +0000307 HUnlock(h);
308 ReleaseResource(h);
309 } else {
310 sprintf(buf, "Mac OS error code %d", err);
311 }
312 return buf;
313}
314
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000315/* Exception object shared by all Mac specific modules for Mac OS errors */
316PyObject *PyMac_OSErrException;
317
318/* Initialize and return PyMac_OSErrException */
319PyObject *
320PyMac_GetOSErrException()
321{
322 if (PyMac_OSErrException == NULL)
323 PyMac_OSErrException = PyString_FromString("Mac OS Error");
324 return PyMac_OSErrException;
325}
326
Jack Jansenf93c72a1994-12-14 14:07:50 +0000327/* Set a MAC-specific error from errno, and return NULL; return None if no error */
328PyObject *
Guido van Rossumfffb8bb1995-01-12 12:37:24 +0000329PyErr_Mac(PyObject *eobj, int err)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000330{
331 char *msg;
332 PyObject *v;
Jack Jansenf93c72a1994-12-14 14:07:50 +0000333
Guido van Rossum8f691791995-01-18 23:57:26 +0000334 if (err == 0 && !PyErr_Occurred()) {
Jack Jansenf93c72a1994-12-14 14:07:50 +0000335 Py_INCREF(Py_None);
336 return Py_None;
337 }
Guido van Rossum8f691791995-01-18 23:57:26 +0000338 if (err == -1 && PyErr_Occurred())
339 return NULL;
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000340 msg = PyMac_StrError(err);
Jack Jansenf93c72a1994-12-14 14:07:50 +0000341 v = Py_BuildValue("(is)", err, msg);
342 PyErr_SetObject(eobj, v);
343 Py_DECREF(v);
344 return NULL;
345}
346
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000347/* Call PyErr_Mac with PyMac_OSErrException */
348PyObject *
349PyMac_Error(OSErr err)
350{
351 return PyErr_Mac(PyMac_GetOSErrException(), err);
352}
353
Jack Jansen1ed95291996-07-22 15:25:10 +0000354#ifdef USE_STACKCHECK
355/* Check for stack overflow */
356int
357PyOS_CheckStack()
358{
359 long left;
360
361 left = StackSpace();
Jack Jansend1f06311996-08-01 15:23:54 +0000362 if ( left < MINIMUM_STACK_SIZE )
Jack Jansen1ed95291996-07-22 15:25:10 +0000363 return -1;
364 return 0;
365}
366#endif /* USE_STACKCHECK */
367
Jack Jansenee23d6e1995-01-27 14:43:25 +0000368/* The catcher routine (which may not be used for all compilers) */
369static RETSIGTYPE
370intcatcher(sig)
371 int sig;
372{
373 interrupted = 1;
374 signal(SIGINT, intcatcher);
375}
376
377void
378PyOS_InitInterrupts()
379{
380 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
381 signal(SIGINT, intcatcher);
382}
383
Jack Jansena8441de1997-08-08 14:57:37 +0000384void
385PyOS_FiniInterrupts()
386{
387}
388
Jack Jansenee23d6e1995-01-27 14:43:25 +0000389/*
390** This routine scans the event queue looking for cmd-.
391** This is the only way to get an interrupt under THINK (since it
392** doesn't do SIGINT handling), but is also used under MW, when
393** the full-fledged event loop is disabled. This way, we can at least
394** interrupt a runaway python program.
395*/
396static void
397scan_event_queue(flush)
398 int flush;
399{
400 register EvQElPtr q;
401
Jack Jansenefaada71998-02-20 16:03:15 +0000402 q = (EvQElPtr) LMGetEventQueue()->qHead;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000403
404 for (; q; q = (EvQElPtr)q->qLink) {
405 if (q->evtQWhat == keyDown &&
406 (char)q->evtQMessage == '.' &&
407 (q->evtQModifiers & cmdKey) != 0) {
408 if ( flush )
409 FlushEvents(keyDownMask, 0);
410 interrupted = 1;
411 break;
412 }
413 }
414}
415
416int
Jack Jansen36ed5061997-06-20 16:18:15 +0000417PyErr_CheckSignals()
Jack Jansenee23d6e1995-01-27 14:43:25 +0000418{
Jack Jansene3ae0df1997-06-03 15:28:29 +0000419 if (schedparams.enabled) {
420 if ( (unsigned long)LMGetTicks() > schedparams.next_check ) {
Jack Jansen36ed5061997-06-20 16:18:15 +0000421 if ( PyMac_Yield() < 0)
422 return -1;
Jack Jansene3ae0df1997-06-03 15:28:29 +0000423 schedparams.next_check = (unsigned long)LMGetTicks()
424 + schedparams.check_interval;
425 if (interrupted) {
Jack Jansencaa7c461997-06-12 10:49:13 +0000426 scan_event_queue(1); /* Eat events up to cmd-. */
Jack Jansene3ae0df1997-06-03 15:28:29 +0000427 interrupted = 0;
Jack Jansen36ed5061997-06-20 16:18:15 +0000428 PyErr_SetNone(PyExc_KeyboardInterrupt);
429 return -1;
Jack Jansene3ae0df1997-06-03 15:28:29 +0000430 }
431 }
Jack Jansenee23d6e1995-01-27 14:43:25 +0000432 }
433 return 0;
434}
435
Jack Jansen36ed5061997-06-20 16:18:15 +0000436int
437PyOS_InterruptOccurred()
438{
439 scan_event_queue(1);
440 return interrupted;
441}
Jack Jansenee23d6e1995-01-27 14:43:25 +0000442/* Check whether we are in the foreground */
443int
444PyMac_InForeground()
445{
446 static ProcessSerialNumber ours;
447 static inited;
448 ProcessSerialNumber curfg;
449 Boolean eq;
450
Jack Jansene3ae0df1997-06-03 15:28:29 +0000451 if ( inited == 0 ) {
Jack Jansenee23d6e1995-01-27 14:43:25 +0000452 (void)GetCurrentProcess(&ours);
Jack Jansene3ae0df1997-06-03 15:28:29 +0000453 inited = 1;
454 }
Jack Jansenee23d6e1995-01-27 14:43:25 +0000455 if ( GetFrontProcess(&curfg) < 0 )
456 eq = 1;
457 else if ( SameProcess(&ours, &curfg, &eq) < 0 )
458 eq = 1;
459 return (int)eq;
460
461}
462
Jack Jansen36ed5061997-06-20 16:18:15 +0000463int
464PyMac_SetEventHandler(PyObject *evh)
465{
466 if ( evh && python_event_handler ) {
467 PyErr_SetString(PyExc_RuntimeError, "Python event handler already set");
468 return 0;
469 }
470 if ( python_event_handler )
471 Py_DECREF(python_event_handler);
472 if ( evh )
473 Py_INCREF(evh);
474 python_event_handler = evh;
475 return 1;
476}
477
Jack Jansenf93c72a1994-12-14 14:07:50 +0000478/*
Jack Jansena76382a1995-02-02 14:25:56 +0000479** Handle an event, either one found in the mainloop eventhandler or
480** one passed back from the python program.
481*/
482void
Jack Jansen36ed5061997-06-20 16:18:15 +0000483PyMac_HandleEventIntern(evp)
Jack Jansena76382a1995-02-02 14:25:56 +0000484 EventRecord *evp;
485{
Jack Jansen0c968871997-08-26 13:20:34 +0000486 if ( evp->what == mouseDown ) {
487 WindowPtr wp;
488
489 if ( FindWindow(evp->where, &wp) == inSysWindow ) {
490 SystemClick(evp, wp);
491 return;
492 }
493 }
Jack Jansena76382a1995-02-02 14:25:56 +0000494#ifdef __MWERKS__
Jack Jansen38e97661995-11-10 14:53:00 +0000495 {
496 int siouxdidit;
497
498 /* If SIOUX wants it we're done */
499 siouxdidit = SIOUXHandleOneEvent(evp);
500 if ( siouxdidit )
501 return;
502 }
Jack Jansena76382a1995-02-02 14:25:56 +0000503#else
Jack Jansen0c968871997-08-26 13:20:34 +0000504 /* Other compilers are just unlucky... */
Jack Jansena76382a1995-02-02 14:25:56 +0000505#endif /* !__MWERKS__ */
Jack Jansen36ed5061997-06-20 16:18:15 +0000506}
507
508/*
509** Handle an event, either through HandleEvent or by passing it to the Python
510** event handler.
511*/
512int
513PyMac_HandleEvent(evp)
514 EventRecord *evp;
515{
516 PyObject *rv;
517
518 if ( python_event_handler ) {
519 rv = PyObject_CallFunction(python_event_handler, "(O&)",
520 PyMac_BuildEventRecord, evp);
521 if ( rv )
522 Py_DECREF(rv);
523 else
524 return -1; /* Propagate exception */
525 } else {
526 PyMac_HandleEventIntern(evp);
527 }
528 return 0;
Jack Jansena76382a1995-02-02 14:25:56 +0000529}
530
531/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000532** Yield the CPU to other tasks without processing events.
Jack Jansene8e8ae01995-01-26 16:36:45 +0000533*/
Jack Jansen36ed5061997-06-20 16:18:15 +0000534static int
Jack Jansene3ae0df1997-06-03 15:28:29 +0000535PyMac_DoYield(int maxsleep, int maycallpython)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000536{
537 EventRecord ev;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000538 int gotone;
Jack Jansene3ae0df1997-06-03 15:28:29 +0000539 long latest_time_ready;
Jack Jansen36ed5061997-06-20 16:18:15 +0000540 static int in_here = 0;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000541
Jack Jansen36ed5061997-06-20 16:18:15 +0000542 in_here++;
Jack Jansene3ae0df1997-06-03 15:28:29 +0000543 /*
544 ** First check for interrupts, if wanted.
545 ** This sets a flag that will be picked up at an appropriate
546 ** moment in the mainloop.
547 */
548 if (schedparams.check_interrupt)
Jack Jansenee23d6e1995-01-27 14:43:25 +0000549 scan_event_queue(0);
Jack Jansene3ae0df1997-06-03 15:28:29 +0000550
551 /* XXXX Implementing an idle routine goes here */
Jack Jansene8e8ae01995-01-26 16:36:45 +0000552
Jack Jansene3ae0df1997-06-03 15:28:29 +0000553 /*
554 ** Check which of the eventloop cases we have:
555 ** - process events
556 ** - don't process events but do yield
557 ** - do neither
558 */
Jack Jansen36ed5061997-06-20 16:18:15 +0000559 if( in_here > 1 || !schedparams.process_events ||
560 (python_event_handler && !maycallpython) ) {
Jack Jansene3ae0df1997-06-03 15:28:29 +0000561 if ( maxsleep >= 0 ) {
Jack Jansene8e8ae01995-01-26 16:36:45 +0000562 SystemTask();
Jack Jansene3ae0df1997-06-03 15:28:29 +0000563 }
564 } else {
565 latest_time_ready = LMGetTicks() + maxsleep;
566 while ( maxsleep >= 0 ) {
Jack Jansen0c968871997-08-26 13:20:34 +0000567 /* XXXX Hack by Jack.
568 ** In time.sleep() you can click to another application
569 ** once only. If you come back to Python you cannot get away
570 ** again.
571 **/
Jack Jansen36ed5061997-06-20 16:18:15 +0000572 gotone = WaitNextEvent(schedparams.process_events, &ev, maxsleep, NULL);
Jack Jansene3ae0df1997-06-03 15:28:29 +0000573 /* Get out quickly if nothing interesting is happening */
574 if ( !gotone || ev.what == nullEvent )
575 break;
Jack Jansen36ed5061997-06-20 16:18:15 +0000576 if ( PyMac_HandleEvent(&ev) < 0 ) {
577 in_here--;
578 return -1;
579 }
Jack Jansene3ae0df1997-06-03 15:28:29 +0000580 maxsleep = latest_time_ready - LMGetTicks();
581 }
Jack Jansenf93c72a1994-12-14 14:07:50 +0000582 }
Jack Jansen36ed5061997-06-20 16:18:15 +0000583 in_here--;
584 return 0;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000585}
586
587/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000588** Process events and/or yield the CPU to other tasks if opportune
Jack Jansene8e8ae01995-01-26 16:36:45 +0000589*/
Jack Jansen36ed5061997-06-20 16:18:15 +0000590int
Jack Jansene8e8ae01995-01-26 16:36:45 +0000591PyMac_Yield() {
Jack Jansene3ae0df1997-06-03 15:28:29 +0000592 unsigned long maxsleep;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000593
Jack Jansene3ae0df1997-06-03 15:28:29 +0000594 if( PyMac_InForeground() )
595 maxsleep = 0;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000596 else
Jack Jansene3ae0df1997-06-03 15:28:29 +0000597 maxsleep = schedparams.bg_yield;
598
Jack Jansen36ed5061997-06-20 16:18:15 +0000599 return PyMac_DoYield(maxsleep, 1);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000600}
601
602/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000603** Return current scheduler parameters
Jack Jansene8e8ae01995-01-26 16:36:45 +0000604*/
Jack Jansene3ae0df1997-06-03 15:28:29 +0000605void
606PyMac_GetSchedParams(PyMacSchedParams *sp)
Jack Jansene8e8ae01995-01-26 16:36:45 +0000607{
Jack Jansene3ae0df1997-06-03 15:28:29 +0000608 sp->check_interrupt = schedparams.check_interrupt;
609 sp->process_events = schedparams.process_events;
610 sp->besocial = schedparams.besocial;
611 sp->check_interval = schedparams.check_interval / 60.0;
612 sp->bg_yield = schedparams.bg_yield / 60.0;
Jack Jansenf93c72a1994-12-14 14:07:50 +0000613}
Jack Jansenf6865f71996-09-04 15:24:59 +0000614
Jack Jansen74162f31995-02-15 22:58:33 +0000615/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000616** Set current scheduler parameters
617*/
618void
619PyMac_SetSchedParams(PyMacSchedParams *sp)
620{
621 schedparams.check_interrupt = sp->check_interrupt;
622 schedparams.process_events = sp->process_events;
623 schedparams.besocial = sp->besocial;
624 schedparams.check_interval = (unsigned long)(sp->check_interval*60);
625 schedparams.bg_yield = (unsigned long)(sp->bg_yield*60);
626 if ( schedparams.check_interrupt || schedparams.process_events ||
627 schedparams.besocial )
628 schedparams.enabled = 1;
629 else
630 schedparams.enabled = 0;
631 schedparams.next_check = 0; /* Check immedeately */
632}
Jack Jansencaa7c461997-06-12 10:49:13 +0000633
Jack Jansene3ae0df1997-06-03 15:28:29 +0000634/*
Jack Jansen3469e991996-09-06 00:30:45 +0000635** Install our menu bar.
636*/
637void
638PyMac_InitMenuBar()
639{
Jack Jansen3469e991996-09-06 00:30:45 +0000640 MenuHandle applemenu;
641
Jack Jansencaa7c461997-06-12 10:49:13 +0000642 if ( (sioux_mbar=GetMenuBar()) == NULL ) {
643 /* Sioux menu not installed yet. Do so */
644 SIOUXSetupMenus();
645 if ( (sioux_mbar=GetMenuBar()) == NULL )
646 return;
647 }
Jack Jansen08c3be31997-04-08 15:27:00 +0000648 if ( (applemenu=GetMenuHandle(SIOUX_APPLEID)) == NULL ) return;
Jack Jansen3469e991996-09-06 00:30:45 +0000649 SetMenuItemText(applemenu, 1, "\pAbout Python...");
650}
651
652/*
Jack Jansencaa7c461997-06-12 10:49:13 +0000653** Restore sioux menu bar
654*/
655void
656PyMac_RestoreMenuBar()
657{
Jack Janseneda78631997-06-12 15:29:46 +0000658 if ( sioux_mbar ) {
Jack Jansencaa7c461997-06-12 10:49:13 +0000659 SetMenuBar(sioux_mbar);
Jack Janseneda78631997-06-12 15:29:46 +0000660 DrawMenuBar();
Jack Jansenefaada71998-02-20 16:03:15 +0000661 } else
662 PyMac_InitMenuBar();
Jack Jansencaa7c461997-06-12 10:49:13 +0000663}
664
665
666/*
Jack Jansen3469e991996-09-06 00:30:45 +0000667** Our replacement about box
668*/
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000669
670#include "patchlevel.h"
671
Jack Jansen3469e991996-09-06 00:30:45 +0000672void
673SIOUXDoAboutBox(void)
674{
675 DialogPtr theDialog;
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000676 WindowPtr theWindow;
Jack Jansen3469e991996-09-06 00:30:45 +0000677 short item;
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000678 short fontID;
Jack Jansen3469e991996-09-06 00:30:45 +0000679
680 if( (theDialog = GetNewDialog(ABOUT_ID, NULL, (WindowPtr)-1)) == NULL )
681 return;
Jack Jansend617c571996-09-22 22:14:30 +0000682 theWindow = GetDialogWindow(theDialog);
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000683 SetPortWindowPort(theWindow);
684 GetFNum("\pPython-Sans", &fontID);
685 if (fontID == 0)
686 fontID = kFontIDGeneva;
687 TextFont(fontID);
688 TextSize(9);
689 ParamText(Pstring(PATCHLEVEL), "\p", "\p", "\p");
Jack Jansend617c571996-09-22 22:14:30 +0000690 ShowWindow(theWindow);
Jack Jansen3469e991996-09-06 00:30:45 +0000691 ModalDialog(NULL, &item);
692 DisposeDialog(theDialog);
693}
694
Jack Janseneda78631997-06-12 15:29:46 +0000695#if 0
696int
697PyMac_FileExists(char *name)
698{
699 FSSpec fss;
700
701 if ( FSMakeFSSpec(0, 0, Pstring(name), &fss) == noErr )
702 return 1;
703 return 0;
704}
705#endif
706
707/*
Jack Jansen3ec804a1995-02-20 15:56:10 +0000708** Helper routine for GetDirectory
709*/
Guido van Rossum24a45e31995-02-20 23:45:53 +0000710static pascal short
Jack Jansen819f1771995-08-14 12:35:10 +0000711myhook_proc(short item, DialogPtr theDialog, struct hook_args *dataptr)
Jack Jansen3ec804a1995-02-20 15:56:10 +0000712{
Jack Jansen819f1771995-08-14 12:35:10 +0000713 if ( item == sfHookFirstCall && dataptr->prompt) {
714 Handle prompth;
715 short type;
716 Rect rect;
717
718 GetDialogItem(theDialog, PROMPT_ITEM, &type, &prompth, &rect);
719 if ( prompth )
720 SetDialogItemText(prompth, (unsigned char *)dataptr->prompt);
721 } else
Jack Jansen3ec804a1995-02-20 15:56:10 +0000722 if ( item == SELECTCUR_ITEM ) {
723 item = sfItemCancelButton;
Jack Jansen819f1771995-08-14 12:35:10 +0000724 dataptr->selectcur_hit = 1;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000725 }
726 return item;
727}
728
729/*
730** Ask the user for a directory. I still can't understand
731** why Apple doesn't provide a standard solution for this...
732*/
733int
Jack Jansen819f1771995-08-14 12:35:10 +0000734PyMac_GetDirectory(dirfss, prompt)
Jack Jansen3ec804a1995-02-20 15:56:10 +0000735 FSSpec *dirfss;
Jack Jansen819f1771995-08-14 12:35:10 +0000736 char *prompt;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000737{
738 static SFTypeList list = {'fldr', 0, 0, 0};
739 static Point where = {-1, -1};
Jack Jansen3ec804a1995-02-20 15:56:10 +0000740 StandardFileReply reply;
Jack Jansen819f1771995-08-14 12:35:10 +0000741 struct hook_args hook_args;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000742
743 if ( !upp_inited ) {
744 myhook_upp = NewDlgHookYDProc(myhook_proc);
745 upp_inited = 1;
746 }
Jack Jansen819f1771995-08-14 12:35:10 +0000747 if ( prompt && *prompt )
748 hook_args.prompt = (char *)Pstring(prompt);
749 else
750 hook_args.prompt = NULL;
751 hook_args.selectcur_hit = 0;
Guido van Rossum24a45e31995-02-20 23:45:53 +0000752 CustomGetFile((FileFilterYDUPP)0, 1, list, &reply, GETDIR_ID, where, myhook_upp,
Jack Jansen819f1771995-08-14 12:35:10 +0000753 NULL, NULL, NULL, (void *)&hook_args);
Jack Jansen3ec804a1995-02-20 15:56:10 +0000754
755 reply.sfFile.name[0] = 0;
756 if( FSMakeFSSpec(reply.sfFile.vRefNum, reply.sfFile.parID, reply.sfFile.name, dirfss) )
757 return 0;
Jack Jansen819f1771995-08-14 12:35:10 +0000758 return hook_args.selectcur_hit;
759}
760
761/*
762** Slightly extended StandardGetFile: accepts a prompt */
763void PyMac_PromptGetFile(short numTypes, ConstSFTypeListPtr typeList,
764 StandardFileReply *reply, char *prompt)
765{
766 static Point where = {-1, -1};
767 struct hook_args hook_args;
768
769 if ( !upp_inited ) {
770 myhook_upp = NewDlgHookYDProc(myhook_proc);
771 upp_inited = 1;
772 }
773 if ( prompt && *prompt )
774 hook_args.prompt = (char *)Pstring(prompt);
775 else
776 hook_args.prompt = NULL;
777 hook_args.selectcur_hit = 0;
778 CustomGetFile((FileFilterYDUPP)0, numTypes, typeList, reply, GETFILEPROMPT_ID, where,
779 myhook_upp, NULL, NULL, NULL, (void *)&hook_args);
Jack Jansen3ec804a1995-02-20 15:56:10 +0000780}
Jack Jansen5f653091995-01-18 13:53:49 +0000781
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000782/* Convert a 4-char string object argument to an OSType value */
Jack Jansen5f653091995-01-18 13:53:49 +0000783int
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000784PyMac_GetOSType(PyObject *v, OSType *pr)
Jack Jansen5f653091995-01-18 13:53:49 +0000785{
786 if (!PyString_Check(v) || PyString_Size(v) != 4) {
787 PyErr_SetString(PyExc_TypeError,
788 "OSType arg must be string of 4 chars");
789 return 0;
790 }
791 memcpy((char *)pr, PyString_AsString(v), 4);
792 return 1;
793}
794
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000795/* Convert an OSType value to a 4-char string object */
796PyObject *
797PyMac_BuildOSType(OSType t)
798{
799 return PyString_FromStringAndSize((char *)&t, 4);
800}
801
Jack Jansend1f06311996-08-01 15:23:54 +0000802/* Convert an NumVersion value to a 4-element tuple */
803PyObject *
804PyMac_BuildNumVersion(NumVersion t)
805{
806 return Py_BuildValue("(hhhh)", t.majorRev, t.minorAndBugRev, t.stage, t.nonRelRev);
807}
808
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000809
810/* Convert a Python string object to a Str255 */
Jack Jansen5f653091995-01-18 13:53:49 +0000811int
Guido van Rossum8f691791995-01-18 23:57:26 +0000812PyMac_GetStr255(PyObject *v, Str255 pbuf)
Jack Jansen5f653091995-01-18 13:53:49 +0000813{
814 int len;
815 if (!PyString_Check(v) || (len = PyString_Size(v)) > 255) {
816 PyErr_SetString(PyExc_TypeError,
817 "Str255 arg must be string of at most 255 chars");
818 return 0;
819 }
820 pbuf[0] = len;
821 memcpy((char *)(pbuf+1), PyString_AsString(v), len);
822 return 1;
823}
824
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000825/* Convert a Str255 to a Python string object */
826PyObject *
827PyMac_BuildStr255(Str255 s)
828{
Jack Jansenb734ade1999-12-17 17:15:50 +0000829 if ( s == NULL ) {
830 PyErr_SetString(PyExc_SystemError, "Str255 pointer is NULL");
831 return NULL;
832 }
833 return PyString_FromStringAndSize((char *)&s[1], (int)s[0]);
834}
835
836PyObject *
837PyMac_BuildOptStr255(Str255 s)
838{
839 if ( s == NULL ) {
840 Py_INCREF(Py_None);
841 return Py_None;
842 }
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000843 return PyString_FromStringAndSize((char *)&s[1], (int)s[0]);
844}
845
846
Jack Jansen5f653091995-01-18 13:53:49 +0000847/*
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000848** Convert a Python object to an FSSpec.
849** The object may either be a full pathname or a triple
850** (vrefnum, dirid, path).
Jack Jansen5f653091995-01-18 13:53:49 +0000851** NOTE: This routine will fail on pre-sys7 machines.
852** The caller is responsible for not calling this routine
853** in those cases (which is fine, since everyone calling
854** this is probably sys7 dependent anyway).
855*/
856int
Guido van Rossum8f691791995-01-18 23:57:26 +0000857PyMac_GetFSSpec(PyObject *v, FSSpec *fs)
Jack Jansen5f653091995-01-18 13:53:49 +0000858{
859 Str255 path;
860 short refnum;
861 long parid;
862 OSErr err;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000863 FSSpec *fs2;
Jack Jansen5f653091995-01-18 13:53:49 +0000864
Jack Jansene8e8ae01995-01-26 16:36:45 +0000865 /* first check whether it already is an FSSpec */
866 fs2 = mfs_GetFSSpecFSSpec(v);
867 if ( fs2 ) {
Jack Jansen3ec804a1995-02-20 15:56:10 +0000868 (void)FSMakeFSSpec(fs2->vRefNum, fs2->parID, fs2->name, fs);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000869 return 1;
870 }
Jack Jansen5f653091995-01-18 13:53:49 +0000871 if ( PyString_Check(v) ) {
872 /* It's a pathname */
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000873 if( !PyArg_Parse(v, "O&", PyMac_GetStr255, &path) )
Jack Jansen5f653091995-01-18 13:53:49 +0000874 return 0;
Jack Jansen378815c1996-03-06 16:21:34 +0000875 refnum = 0; /* XXXX Should get CurWD here?? */
Jack Jansen5f653091995-01-18 13:53:49 +0000876 parid = 0;
877 } else {
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000878 if( !PyArg_Parse(v, "(hlO&); FSSpec should be fullpath or (vrefnum,dirid,path)",
879 &refnum, &parid, PyMac_GetStr255, &path)) {
Jack Jansen5f653091995-01-18 13:53:49 +0000880 return 0;
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000881 }
Jack Jansen5f653091995-01-18 13:53:49 +0000882 }
883 err = FSMakeFSSpec(refnum, parid, path, fs);
884 if ( err && err != fnfErr ) {
Jack Jansen3d757542000-01-24 09:56:06 +0000885 PyMac_Error(err);
Jack Jansen5f653091995-01-18 13:53:49 +0000886 return 0;
887 }
888 return 1;
889}
890
Jack Jansen8bb573e1999-12-12 21:37:14 +0000891/* Convert FSSpec to PyObject */
892PyObject *PyMac_BuildFSSpec(FSSpec *v)
893{
894 return newmfssobject(v);
895}
Guido van Rossum8f691791995-01-18 23:57:26 +0000896
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000897/* Convert a Python object to a Rect.
Guido van Rossum5279ec61995-01-26 22:56:59 +0000898 The object must be a (left, top, right, bottom) tuple.
899 (This differs from the order in the struct but is consistent with
900 the arguments to SetRect(), and also with STDWIN). */
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000901int
902PyMac_GetRect(PyObject *v, Rect *r)
Guido van Rossum8f691791995-01-18 23:57:26 +0000903{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000904 return PyArg_Parse(v, "(hhhh)", &r->left, &r->top, &r->right, &r->bottom);
Guido van Rossum8f691791995-01-18 23:57:26 +0000905}
Guido van Rossumb3404661995-01-22 18:36:13 +0000906
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000907/* Convert a Rect to a Python object */
Guido van Rossumb3404661995-01-22 18:36:13 +0000908PyObject *
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000909PyMac_BuildRect(Rect *r)
Guido van Rossumb3404661995-01-22 18:36:13 +0000910{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000911 return Py_BuildValue("(hhhh)", r->left, r->top, r->right, r->bottom);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000912}
913
914
915/* Convert a Python object to a Point.
Guido van Rossum5279ec61995-01-26 22:56:59 +0000916 The object must be a (h, v) tuple.
917 (This differs from the order in the struct but is consistent with
918 the arguments to SetPoint(), and also with STDWIN). */
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000919int
920PyMac_GetPoint(PyObject *v, Point *p)
921{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000922 return PyArg_Parse(v, "(hh)", &p->h, &p->v);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000923}
924
925/* Convert a Point to a Python object */
926PyObject *
927PyMac_BuildPoint(Point p)
928{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000929 return Py_BuildValue("(hh)", p.h, p.v);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000930}
931
932
933/* Convert a Python object to an EventRecord.
934 The object must be a (what, message, when, (v, h), modifiers) tuple. */
935int
936PyMac_GetEventRecord(PyObject *v, EventRecord *e)
937{
938 return PyArg_Parse(v, "(hll(hh)h)",
939 &e->what,
940 &e->message,
941 &e->when,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000942 &e->where.h,
Guido van Rossum5279ec61995-01-26 22:56:59 +0000943 &e->where.v,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000944 &e->modifiers);
945}
946
947/* Convert a Rect to an EventRecord object */
948PyObject *
949PyMac_BuildEventRecord(EventRecord *e)
950{
951 return Py_BuildValue("(hll(hh)h)",
952 e->what,
953 e->message,
954 e->when,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000955 e->where.h,
Guido van Rossum5279ec61995-01-26 22:56:59 +0000956 e->where.v,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000957 e->modifiers);
Guido van Rossumb3404661995-01-22 18:36:13 +0000958}
Jack Jansenfa4d5d01995-11-15 15:19:29 +0000959
960/* Convert Python object to Fixed */
961int
962PyMac_GetFixed(PyObject *v, Fixed *f)
963{
964 double d;
965
966 if( !PyArg_Parse(v, "d", &d))
967 return 0;
968 *f = (Fixed)(d * 0x10000);
Jack Jansen31dd5c01996-05-31 13:01:39 +0000969 return 1;
Jack Jansenfa4d5d01995-11-15 15:19:29 +0000970}
971
972/* Convert a Point to a Python object */
973PyObject *
974PyMac_BuildFixed(Fixed f)
975{
976 double d;
977
978 d = f;
979 d = d / 0x10000;
980 return Py_BuildValue("d", d);
981}
982
Jack Jansend58cd631998-04-21 15:24:39 +0000983/* Convert wide to/from Python int or (hi, lo) tuple. XXXX Should use Python longs */
984int
985PyMac_Getwide(PyObject *v, wide *rv)
986{
987 if (PyInt_Check(v)) {
988 rv->hi = 0;
989 rv->lo = PyInt_AsLong(v);
990 if( rv->lo & 0x80000000 )
991 rv->hi = -1;
992 return 1;
993 }
994 return PyArg_Parse(v, "(ll)", &rv->hi, &rv->lo);
995}
996
997
998PyObject *
Jack Jansenbbf4be21998-04-23 13:20:17 +0000999PyMac_Buildwide(wide *w)
Jack Jansend58cd631998-04-21 15:24:39 +00001000{
Jack Jansenbbf4be21998-04-23 13:20:17 +00001001 if ( (w->hi == 0 && (w->lo & 0x80000000) == 0) ||
1002 (w->hi == -1 && (w->lo & 0x80000000) ) )
1003 return PyInt_FromLong(w->lo);
1004 return Py_BuildValue("(ll)", w->hi, w->lo);
Jack Jansend58cd631998-04-21 15:24:39 +00001005}