blob: fd0ddfbb1f6316d73362ce54457bfd1cad901bff [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 Jansen2d1306b2000-04-07 09:10:49 +000065#ifdef USE_GUSI1
Jack Jansen911ad6b1996-03-05 16:56:24 +000066#include <TFileSpec.h> /* For Path2FSSpec */
Jack Jansenf6865f71996-09-04 15:24:59 +000067#include <GUSI.h>
Jack Jansen911ad6b1996-03-05 16:56:24 +000068#endif
Jack Jansen2d1306b2000-04-07 09:10:49 +000069#include <LowMem.h>
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_Yield Py_PROTO((void));
Jack Jansenf6865f71996-09-04 15:24:59 +0000112
Jack Jansene8e8ae01995-01-26 16:36:45 +0000113/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000114** These are the real scheduling parameters that control what we check
115** in the event loop, and how often we check. The values are initialized
116** from pyMac_SchedParamStruct.
117*/
118
119struct real_sched_param_struct {
120 int check_interrupt; /* if true check for command-dot */
121 int process_events; /* if nonzero enable evt processing, this mask */
122 int besocial; /* if nonzero be a little social with CPU */
123 unsigned long check_interval; /* how often to check, in ticks */
124 unsigned long bg_yield; /* yield so long when in background */
125 /* these are computed from previous and clock and such */
126 int enabled; /* check_interrupt OR process_event OR yield */
127 unsigned long next_check; /* when to check/yield next, in ticks */
128};
129
130static struct real_sched_param_struct schedparams =
131 { 1, MAINLOOP_EVENTMASK, 1, 15, 15, 1, 0};
132
Jack Jansen819f1771995-08-14 12:35:10 +0000133/*
Jack Jansenf6865f71996-09-04 15:24:59 +0000134** Workaround for sioux/gusi combo: set when we are exiting
135*/
136int PyMac_ConsoleIsDead;
137
138/*
Jack Jansencaa7c461997-06-12 10:49:13 +0000139** Sioux menu bar, saved early so we can restore it
140*/
141static Handle sioux_mbar;
142
143/*
Jack Jansen819f1771995-08-14 12:35:10 +0000144** Some stuff for our GetDirectory and PromptGetFile routines
145*/
146struct hook_args {
147 int selectcur_hit; /* Set to true when "select current" selected */
148 char *prompt; /* The prompt */
149};
150static DlgHookYDUPP myhook_upp;
151static int upp_inited = 0;
152
Jack Jansen36ed5061997-06-20 16:18:15 +0000153/*
154** The python-code event handler
155*/
156static PyObject *python_event_handler;
157
Jack Jansen8f5725a1999-12-07 23:08:10 +0000158/*
159** Set to true if we're appearance-compliant
160*/
161int PyMac_AppearanceCompliant;
162
Jack Jansen2d1306b2000-04-07 09:10:49 +0000163#ifdef USE_GUSI1
Jack Jansen378815c1996-03-06 16:21:34 +0000164/*
165** GUSI (1.6.0 and earlier, at the least) do not set the MacOS idea of
166** the working directory. Hence, we call this routine after each call
167** to chdir() to rectify things.
168*/
169void
170PyMac_FixGUSIcd()
171{
172 WDPBRec pb;
173 FSSpec curdirfss;
174
175 if ( Path2FSSpec(":x", &curdirfss) != noErr )
176 return;
177
178 /* Set MacOS "working directory" */
179 pb.ioNamePtr= "\p";
180 pb.ioVRefNum= curdirfss.vRefNum;
181 pb.ioWDDirID= curdirfss.parID;
Jack Jansen08c3be31997-04-08 15:27:00 +0000182 if (PBHSetVolSync(&pb) != noErr)
Jack Jansen378815c1996-03-06 16:21:34 +0000183 return;
Jack Jansen378815c1996-03-06 16:21:34 +0000184}
Jack Jansen2d1306b2000-04-07 09:10:49 +0000185#endif
Jack Jansen7ac70af1996-08-19 11:01:05 +0000186
Jack Jansen2d1306b2000-04-07 09:10:49 +0000187#ifdef USE_GUSI
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000188/*
189** SpinCursor (needed by GUSI) drags in heaps of stuff, so we
190** provide a dummy here.
191*/
Jack Jansencfadbd41996-08-19 11:36:25 +0000192void SpinCursor(short x) { /* Dummy */ }
Jack Jansenefaada71998-02-20 16:03:15 +0000193void RotateCursor(short x) { /* Dummy */ }
Jack Jansencfadbd41996-08-19 11:36:25 +0000194
Jack Jansenf6865f71996-09-04 15:24:59 +0000195/*
196** Replacement GUSI Spin function
197*/
Jack Jansen2d1306b2000-04-07 09:10:49 +0000198#ifdef USE_GUSI1
Jack Jansenf6865f71996-09-04 15:24:59 +0000199static int
200PyMac_GUSISpin(spin_msg msg, long arg)
201{
Jack Jansene3ae0df1997-06-03 15:28:29 +0000202 static Boolean inForeground = true;
203 int maxsleep = 6; /* 6 ticks is "normal" sleeptime */
Jack Jansenf6865f71996-09-04 15:24:59 +0000204
205 if (PyMac_ConsoleIsDead) return 0;
206#if 0
207 if (inForeground)
208 SpinCursor(msg == SP_AUTO_SPIN ? short(arg) : 1);
209#endif
210
211 if (interrupted) return -1;
212
Jack Jansene3ae0df1997-06-03 15:28:29 +0000213 if ( msg == SP_AUTO_SPIN )
214 maxsleep = 0;
215 if ( msg==SP_SLEEP||msg==SP_SELECT )
216 maxsleep = arg;
Jack Jansenf6865f71996-09-04 15:24:59 +0000217
Jack Jansene3ae0df1997-06-03 15:28:29 +0000218 PyMac_DoYield(maxsleep, 0); /* XXXX or is it safe to call python here? */
Jack Jansenf6865f71996-09-04 15:24:59 +0000219
220 return 0;
221}
222
223void
224PyMac_SetGUSISpin() {
225 GUSISetHook(GUSI_SpinHook, (GUSIHook)PyMac_GUSISpin);
226}
Jack Jansen2d1306b2000-04-07 09:10:49 +0000227#endif
Jack Jansenf6865f71996-09-04 15:24:59 +0000228
Jack Jansena39f1b01997-05-23 15:35:14 +0000229/* Called at exit() time thru atexit(), to stop event processing */
230void
231PyMac_StopGUSISpin() {
232 PyMac_ConsoleIsDead = 1;
233}
234
235/*
236** Replacement routines for the PLstr... functions so we don't need
237** StdCLib. Moreover, that implementation is broken under cfm68k...
238*/
Jack Jansen8bb573e1999-12-12 21:37:14 +0000239pascal void
Jack Jansena39f1b01997-05-23 15:35:14 +0000240PLstrcpy(to, fr)
241 unsigned char *to, *fr;
242{
243 memcpy(to, fr, fr[0]+1);
244}
245
Jack Jansen8bb573e1999-12-12 21:37:14 +0000246pascal int
Jack Jansena39f1b01997-05-23 15:35:14 +0000247PLstrcmp(s1, s2)
248 unsigned char *s1, *s2;
249{
250 int res;
251 int l = s1[0] < s2[0] ? s1[0] : s2[0];
252
253 res = memcmp(s1+1, s2+1, l);
254 if ( res != 0 )
255 return res;
256
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000257 if ( s1[0] < s2[0] )
Jack Jansena39f1b01997-05-23 15:35:14 +0000258 return -1;
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000259 else if ( s1[0] > s2[0] )
Jack Jansena39f1b01997-05-23 15:35:14 +0000260 return 1;
261 else
262 return 0;
263}
264
Jack Jansen8bb573e1999-12-12 21:37:14 +0000265pascal unsigned char *
Jack Jansena39f1b01997-05-23 15:35:14 +0000266PLstrrchr(str, chr)
267 unsigned char *str;
268 unsigned char chr;
269{
270 unsigned char *ptr = 0;
271 unsigned char *p;
272
273 for(p=str+1; p<str+str[0]; p++)
274 if ( *p == chr )
275 ptr = p;
276 return ptr;
277}
278
279#endif /* USE_GUSI */
Jack Jansen378815c1996-03-06 16:21:34 +0000280
Jack Jansen819f1771995-08-14 12:35:10 +0000281
Jack Jansen5f653091995-01-18 13:53:49 +0000282/* Convert C to Pascal string. Returns pointer to static buffer. */
283unsigned char *
284Pstring(char *str)
285{
286 static Str255 buf;
287 int len;
288
289 len = strlen(str);
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000290 if (len > 255)
291 len = 255;
Jack Jansen5f653091995-01-18 13:53:49 +0000292 buf[0] = (unsigned char)len;
293 strncpy((char *)buf+1, str, len);
294 return buf;
295}
296
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000297/* Like strerror() but for Mac OS error numbers */
298char *PyMac_StrError(int err)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000299{
300 static char buf[256];
301 Handle h;
302 char *str;
303
304 h = GetResource('Estr', err);
305 if ( h ) {
306 HLock(h);
307 str = (char *)*h;
308 memcpy(buf, str+1, (unsigned char)str[0]);
Guido van Rossumcc9bc8f1995-02-13 16:17:03 +0000309 buf[(unsigned char)str[0]] = '\0';
Jack Jansenf93c72a1994-12-14 14:07:50 +0000310 HUnlock(h);
311 ReleaseResource(h);
312 } else {
313 sprintf(buf, "Mac OS error code %d", err);
314 }
315 return buf;
316}
317
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000318/* Exception object shared by all Mac specific modules for Mac OS errors */
319PyObject *PyMac_OSErrException;
320
321/* Initialize and return PyMac_OSErrException */
322PyObject *
323PyMac_GetOSErrException()
324{
325 if (PyMac_OSErrException == NULL)
326 PyMac_OSErrException = PyString_FromString("Mac OS Error");
327 return PyMac_OSErrException;
328}
329
Jack Jansenf93c72a1994-12-14 14:07:50 +0000330/* Set a MAC-specific error from errno, and return NULL; return None if no error */
331PyObject *
Guido van Rossumfffb8bb1995-01-12 12:37:24 +0000332PyErr_Mac(PyObject *eobj, int err)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000333{
334 char *msg;
335 PyObject *v;
Jack Jansenf93c72a1994-12-14 14:07:50 +0000336
Guido van Rossum8f691791995-01-18 23:57:26 +0000337 if (err == 0 && !PyErr_Occurred()) {
Jack Jansenf93c72a1994-12-14 14:07:50 +0000338 Py_INCREF(Py_None);
339 return Py_None;
340 }
Guido van Rossum8f691791995-01-18 23:57:26 +0000341 if (err == -1 && PyErr_Occurred())
342 return NULL;
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000343 msg = PyMac_StrError(err);
Jack Jansenf93c72a1994-12-14 14:07:50 +0000344 v = Py_BuildValue("(is)", err, msg);
345 PyErr_SetObject(eobj, v);
346 Py_DECREF(v);
347 return NULL;
348}
349
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000350/* Call PyErr_Mac with PyMac_OSErrException */
351PyObject *
352PyMac_Error(OSErr err)
353{
354 return PyErr_Mac(PyMac_GetOSErrException(), err);
355}
356
Jack Jansen1ed95291996-07-22 15:25:10 +0000357#ifdef USE_STACKCHECK
358/* Check for stack overflow */
359int
360PyOS_CheckStack()
361{
362 long left;
363
364 left = StackSpace();
Jack Jansend1f06311996-08-01 15:23:54 +0000365 if ( left < MINIMUM_STACK_SIZE )
Jack Jansen1ed95291996-07-22 15:25:10 +0000366 return -1;
367 return 0;
368}
369#endif /* USE_STACKCHECK */
370
Jack Jansenee23d6e1995-01-27 14:43:25 +0000371/* The catcher routine (which may not be used for all compilers) */
372static RETSIGTYPE
373intcatcher(sig)
374 int sig;
375{
376 interrupted = 1;
377 signal(SIGINT, intcatcher);
378}
379
380void
381PyOS_InitInterrupts()
382{
383 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
384 signal(SIGINT, intcatcher);
385}
386
Jack Jansena8441de1997-08-08 14:57:37 +0000387void
388PyOS_FiniInterrupts()
389{
390}
391
Jack Jansenee23d6e1995-01-27 14:43:25 +0000392/*
393** This routine scans the event queue looking for cmd-.
394** This is the only way to get an interrupt under THINK (since it
395** doesn't do SIGINT handling), but is also used under MW, when
396** the full-fledged event loop is disabled. This way, we can at least
397** interrupt a runaway python program.
398*/
399static void
400scan_event_queue(flush)
401 int flush;
402{
403 register EvQElPtr q;
404
Jack Jansenefaada71998-02-20 16:03:15 +0000405 q = (EvQElPtr) LMGetEventQueue()->qHead;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000406
407 for (; q; q = (EvQElPtr)q->qLink) {
408 if (q->evtQWhat == keyDown &&
409 (char)q->evtQMessage == '.' &&
410 (q->evtQModifiers & cmdKey) != 0) {
411 if ( flush )
412 FlushEvents(keyDownMask, 0);
413 interrupted = 1;
414 break;
415 }
416 }
417}
418
419int
Jack Jansen36ed5061997-06-20 16:18:15 +0000420PyErr_CheckSignals()
Jack Jansenee23d6e1995-01-27 14:43:25 +0000421{
Jack Jansene3ae0df1997-06-03 15:28:29 +0000422 if (schedparams.enabled) {
423 if ( (unsigned long)LMGetTicks() > schedparams.next_check ) {
Jack Jansen36ed5061997-06-20 16:18:15 +0000424 if ( PyMac_Yield() < 0)
425 return -1;
Jack Jansene3ae0df1997-06-03 15:28:29 +0000426 schedparams.next_check = (unsigned long)LMGetTicks()
427 + schedparams.check_interval;
428 if (interrupted) {
Jack Jansencaa7c461997-06-12 10:49:13 +0000429 scan_event_queue(1); /* Eat events up to cmd-. */
Jack Jansene3ae0df1997-06-03 15:28:29 +0000430 interrupted = 0;
Jack Jansen36ed5061997-06-20 16:18:15 +0000431 PyErr_SetNone(PyExc_KeyboardInterrupt);
432 return -1;
Jack Jansene3ae0df1997-06-03 15:28:29 +0000433 }
434 }
Jack Jansenee23d6e1995-01-27 14:43:25 +0000435 }
436 return 0;
437}
438
Jack Jansen36ed5061997-06-20 16:18:15 +0000439int
440PyOS_InterruptOccurred()
441{
442 scan_event_queue(1);
443 return interrupted;
444}
Jack Jansenee23d6e1995-01-27 14:43:25 +0000445/* Check whether we are in the foreground */
446int
447PyMac_InForeground()
448{
449 static ProcessSerialNumber ours;
450 static inited;
451 ProcessSerialNumber curfg;
452 Boolean eq;
453
Jack Jansene3ae0df1997-06-03 15:28:29 +0000454 if ( inited == 0 ) {
Jack Jansenee23d6e1995-01-27 14:43:25 +0000455 (void)GetCurrentProcess(&ours);
Jack Jansene3ae0df1997-06-03 15:28:29 +0000456 inited = 1;
457 }
Jack Jansenee23d6e1995-01-27 14:43:25 +0000458 if ( GetFrontProcess(&curfg) < 0 )
459 eq = 1;
460 else if ( SameProcess(&ours, &curfg, &eq) < 0 )
461 eq = 1;
462 return (int)eq;
463
464}
465
Jack Jansen36ed5061997-06-20 16:18:15 +0000466int
467PyMac_SetEventHandler(PyObject *evh)
468{
469 if ( evh && python_event_handler ) {
470 PyErr_SetString(PyExc_RuntimeError, "Python event handler already set");
471 return 0;
472 }
473 if ( python_event_handler )
474 Py_DECREF(python_event_handler);
475 if ( evh )
476 Py_INCREF(evh);
477 python_event_handler = evh;
478 return 1;
479}
480
Jack Jansenf93c72a1994-12-14 14:07:50 +0000481/*
Jack Jansena76382a1995-02-02 14:25:56 +0000482** Handle an event, either one found in the mainloop eventhandler or
483** one passed back from the python program.
484*/
485void
Jack Jansen36ed5061997-06-20 16:18:15 +0000486PyMac_HandleEventIntern(evp)
Jack Jansena76382a1995-02-02 14:25:56 +0000487 EventRecord *evp;
488{
Jack Jansen0c968871997-08-26 13:20:34 +0000489 if ( evp->what == mouseDown ) {
490 WindowPtr wp;
491
492 if ( FindWindow(evp->where, &wp) == inSysWindow ) {
493 SystemClick(evp, wp);
494 return;
495 }
496 }
Jack Jansena76382a1995-02-02 14:25:56 +0000497#ifdef __MWERKS__
Jack Jansen38e97661995-11-10 14:53:00 +0000498 {
499 int siouxdidit;
500
501 /* If SIOUX wants it we're done */
502 siouxdidit = SIOUXHandleOneEvent(evp);
503 if ( siouxdidit )
504 return;
505 }
Jack Jansena76382a1995-02-02 14:25:56 +0000506#else
Jack Jansen0c968871997-08-26 13:20:34 +0000507 /* Other compilers are just unlucky... */
Jack Jansena76382a1995-02-02 14:25:56 +0000508#endif /* !__MWERKS__ */
Jack Jansen36ed5061997-06-20 16:18:15 +0000509}
510
511/*
512** Handle an event, either through HandleEvent or by passing it to the Python
513** event handler.
514*/
515int
516PyMac_HandleEvent(evp)
517 EventRecord *evp;
518{
519 PyObject *rv;
520
521 if ( python_event_handler ) {
522 rv = PyObject_CallFunction(python_event_handler, "(O&)",
523 PyMac_BuildEventRecord, evp);
524 if ( rv )
525 Py_DECREF(rv);
526 else
527 return -1; /* Propagate exception */
528 } else {
529 PyMac_HandleEventIntern(evp);
530 }
531 return 0;
Jack Jansena76382a1995-02-02 14:25:56 +0000532}
533
534/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000535** Yield the CPU to other tasks without processing events.
Jack Jansene8e8ae01995-01-26 16:36:45 +0000536*/
Jack Jansen2d1306b2000-04-07 09:10:49 +0000537int
Jack Jansene3ae0df1997-06-03 15:28:29 +0000538PyMac_DoYield(int maxsleep, int maycallpython)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000539{
540 EventRecord ev;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000541 int gotone;
Jack Jansene3ae0df1997-06-03 15:28:29 +0000542 long latest_time_ready;
Jack Jansen36ed5061997-06-20 16:18:15 +0000543 static int in_here = 0;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000544
Jack Jansen36ed5061997-06-20 16:18:15 +0000545 in_here++;
Jack Jansene3ae0df1997-06-03 15:28:29 +0000546 /*
547 ** First check for interrupts, if wanted.
548 ** This sets a flag that will be picked up at an appropriate
549 ** moment in the mainloop.
550 */
551 if (schedparams.check_interrupt)
Jack Jansenee23d6e1995-01-27 14:43:25 +0000552 scan_event_queue(0);
Jack Jansene3ae0df1997-06-03 15:28:29 +0000553
554 /* XXXX Implementing an idle routine goes here */
Jack Jansene8e8ae01995-01-26 16:36:45 +0000555
Jack Jansene3ae0df1997-06-03 15:28:29 +0000556 /*
557 ** Check which of the eventloop cases we have:
558 ** - process events
559 ** - don't process events but do yield
560 ** - do neither
561 */
Jack Jansen36ed5061997-06-20 16:18:15 +0000562 if( in_here > 1 || !schedparams.process_events ||
563 (python_event_handler && !maycallpython) ) {
Jack Jansene3ae0df1997-06-03 15:28:29 +0000564 if ( maxsleep >= 0 ) {
Jack Jansene8e8ae01995-01-26 16:36:45 +0000565 SystemTask();
Jack Jansene3ae0df1997-06-03 15:28:29 +0000566 }
567 } else {
568 latest_time_ready = LMGetTicks() + maxsleep;
Jack Jansen2d1306b2000-04-07 09:10:49 +0000569 do {
Jack Jansen0c968871997-08-26 13:20:34 +0000570 /* XXXX Hack by Jack.
571 ** In time.sleep() you can click to another application
572 ** once only. If you come back to Python you cannot get away
573 ** again.
574 **/
Jack Jansen36ed5061997-06-20 16:18:15 +0000575 gotone = WaitNextEvent(schedparams.process_events, &ev, maxsleep, NULL);
Jack Jansene3ae0df1997-06-03 15:28:29 +0000576 /* Get out quickly if nothing interesting is happening */
577 if ( !gotone || ev.what == nullEvent )
578 break;
Jack Jansen36ed5061997-06-20 16:18:15 +0000579 if ( PyMac_HandleEvent(&ev) < 0 ) {
580 in_here--;
581 return -1;
582 }
Jack Jansene3ae0df1997-06-03 15:28:29 +0000583 maxsleep = latest_time_ready - LMGetTicks();
Jack Jansen2d1306b2000-04-07 09:10:49 +0000584 } while ( maxsleep > 0 );
Jack Jansenf93c72a1994-12-14 14:07:50 +0000585 }
Jack Jansen36ed5061997-06-20 16:18:15 +0000586 in_here--;
587 return 0;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000588}
589
590/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000591** Process events and/or yield the CPU to other tasks if opportune
Jack Jansene8e8ae01995-01-26 16:36:45 +0000592*/
Jack Jansen36ed5061997-06-20 16:18:15 +0000593int
Jack Jansene8e8ae01995-01-26 16:36:45 +0000594PyMac_Yield() {
Jack Jansene3ae0df1997-06-03 15:28:29 +0000595 unsigned long maxsleep;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000596
Jack Jansene3ae0df1997-06-03 15:28:29 +0000597 if( PyMac_InForeground() )
598 maxsleep = 0;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000599 else
Jack Jansene3ae0df1997-06-03 15:28:29 +0000600 maxsleep = schedparams.bg_yield;
601
Jack Jansen36ed5061997-06-20 16:18:15 +0000602 return PyMac_DoYield(maxsleep, 1);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000603}
604
605/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000606** Return current scheduler parameters
Jack Jansene8e8ae01995-01-26 16:36:45 +0000607*/
Jack Jansene3ae0df1997-06-03 15:28:29 +0000608void
609PyMac_GetSchedParams(PyMacSchedParams *sp)
Jack Jansene8e8ae01995-01-26 16:36:45 +0000610{
Jack Jansene3ae0df1997-06-03 15:28:29 +0000611 sp->check_interrupt = schedparams.check_interrupt;
612 sp->process_events = schedparams.process_events;
613 sp->besocial = schedparams.besocial;
614 sp->check_interval = schedparams.check_interval / 60.0;
615 sp->bg_yield = schedparams.bg_yield / 60.0;
Jack Jansenf93c72a1994-12-14 14:07:50 +0000616}
Jack Jansenf6865f71996-09-04 15:24:59 +0000617
Jack Jansen74162f31995-02-15 22:58:33 +0000618/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000619** Set current scheduler parameters
620*/
621void
622PyMac_SetSchedParams(PyMacSchedParams *sp)
623{
624 schedparams.check_interrupt = sp->check_interrupt;
625 schedparams.process_events = sp->process_events;
626 schedparams.besocial = sp->besocial;
627 schedparams.check_interval = (unsigned long)(sp->check_interval*60);
628 schedparams.bg_yield = (unsigned long)(sp->bg_yield*60);
629 if ( schedparams.check_interrupt || schedparams.process_events ||
630 schedparams.besocial )
631 schedparams.enabled = 1;
632 else
633 schedparams.enabled = 0;
634 schedparams.next_check = 0; /* Check immedeately */
635}
Jack Jansencaa7c461997-06-12 10:49:13 +0000636
Jack Jansene3ae0df1997-06-03 15:28:29 +0000637/*
Jack Jansen3469e991996-09-06 00:30:45 +0000638** Install our menu bar.
639*/
640void
641PyMac_InitMenuBar()
642{
Jack Jansen3469e991996-09-06 00:30:45 +0000643 MenuHandle applemenu;
644
Jack Jansencaa7c461997-06-12 10:49:13 +0000645 if ( (sioux_mbar=GetMenuBar()) == NULL ) {
646 /* Sioux menu not installed yet. Do so */
647 SIOUXSetupMenus();
648 if ( (sioux_mbar=GetMenuBar()) == NULL )
649 return;
650 }
Jack Jansen08c3be31997-04-08 15:27:00 +0000651 if ( (applemenu=GetMenuHandle(SIOUX_APPLEID)) == NULL ) return;
Jack Jansen3469e991996-09-06 00:30:45 +0000652 SetMenuItemText(applemenu, 1, "\pAbout Python...");
653}
654
655/*
Jack Jansencaa7c461997-06-12 10:49:13 +0000656** Restore sioux menu bar
657*/
658void
659PyMac_RestoreMenuBar()
660{
Jack Janseneda78631997-06-12 15:29:46 +0000661 if ( sioux_mbar ) {
Jack Jansencaa7c461997-06-12 10:49:13 +0000662 SetMenuBar(sioux_mbar);
Jack Janseneda78631997-06-12 15:29:46 +0000663 DrawMenuBar();
Jack Jansenefaada71998-02-20 16:03:15 +0000664 } else
665 PyMac_InitMenuBar();
Jack Jansencaa7c461997-06-12 10:49:13 +0000666}
667
668
669/*
Jack Jansen3469e991996-09-06 00:30:45 +0000670** Our replacement about box
671*/
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000672
673#include "patchlevel.h"
674
Jack Jansen3469e991996-09-06 00:30:45 +0000675void
676SIOUXDoAboutBox(void)
677{
678 DialogPtr theDialog;
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000679 WindowPtr theWindow;
Jack Jansen3469e991996-09-06 00:30:45 +0000680 short item;
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000681 short fontID;
Jack Jansen3469e991996-09-06 00:30:45 +0000682
683 if( (theDialog = GetNewDialog(ABOUT_ID, NULL, (WindowPtr)-1)) == NULL )
684 return;
Jack Jansend617c571996-09-22 22:14:30 +0000685 theWindow = GetDialogWindow(theDialog);
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000686 SetPortWindowPort(theWindow);
687 GetFNum("\pPython-Sans", &fontID);
688 if (fontID == 0)
689 fontID = kFontIDGeneva;
690 TextFont(fontID);
691 TextSize(9);
692 ParamText(Pstring(PATCHLEVEL), "\p", "\p", "\p");
Jack Jansend617c571996-09-22 22:14:30 +0000693 ShowWindow(theWindow);
Jack Jansen3469e991996-09-06 00:30:45 +0000694 ModalDialog(NULL, &item);
695 DisposeDialog(theDialog);
696}
697
Jack Janseneda78631997-06-12 15:29:46 +0000698#if 0
699int
700PyMac_FileExists(char *name)
701{
702 FSSpec fss;
703
704 if ( FSMakeFSSpec(0, 0, Pstring(name), &fss) == noErr )
705 return 1;
706 return 0;
707}
708#endif
709
710/*
Jack Jansen3ec804a1995-02-20 15:56:10 +0000711** Helper routine for GetDirectory
712*/
Guido van Rossum24a45e31995-02-20 23:45:53 +0000713static pascal short
Jack Jansen819f1771995-08-14 12:35:10 +0000714myhook_proc(short item, DialogPtr theDialog, struct hook_args *dataptr)
Jack Jansen3ec804a1995-02-20 15:56:10 +0000715{
Jack Jansen819f1771995-08-14 12:35:10 +0000716 if ( item == sfHookFirstCall && dataptr->prompt) {
717 Handle prompth;
718 short type;
719 Rect rect;
720
721 GetDialogItem(theDialog, PROMPT_ITEM, &type, &prompth, &rect);
722 if ( prompth )
723 SetDialogItemText(prompth, (unsigned char *)dataptr->prompt);
724 } else
Jack Jansen3ec804a1995-02-20 15:56:10 +0000725 if ( item == SELECTCUR_ITEM ) {
726 item = sfItemCancelButton;
Jack Jansen819f1771995-08-14 12:35:10 +0000727 dataptr->selectcur_hit = 1;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000728 }
729 return item;
730}
731
732/*
733** Ask the user for a directory. I still can't understand
734** why Apple doesn't provide a standard solution for this...
735*/
736int
Jack Jansen819f1771995-08-14 12:35:10 +0000737PyMac_GetDirectory(dirfss, prompt)
Jack Jansen3ec804a1995-02-20 15:56:10 +0000738 FSSpec *dirfss;
Jack Jansen819f1771995-08-14 12:35:10 +0000739 char *prompt;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000740{
741 static SFTypeList list = {'fldr', 0, 0, 0};
742 static Point where = {-1, -1};
Jack Jansen3ec804a1995-02-20 15:56:10 +0000743 StandardFileReply reply;
Jack Jansen819f1771995-08-14 12:35:10 +0000744 struct hook_args hook_args;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000745
746 if ( !upp_inited ) {
747 myhook_upp = NewDlgHookYDProc(myhook_proc);
748 upp_inited = 1;
749 }
Jack Jansen819f1771995-08-14 12:35:10 +0000750 if ( prompt && *prompt )
751 hook_args.prompt = (char *)Pstring(prompt);
752 else
753 hook_args.prompt = NULL;
754 hook_args.selectcur_hit = 0;
Guido van Rossum24a45e31995-02-20 23:45:53 +0000755 CustomGetFile((FileFilterYDUPP)0, 1, list, &reply, GETDIR_ID, where, myhook_upp,
Jack Jansen819f1771995-08-14 12:35:10 +0000756 NULL, NULL, NULL, (void *)&hook_args);
Jack Jansen3ec804a1995-02-20 15:56:10 +0000757
758 reply.sfFile.name[0] = 0;
759 if( FSMakeFSSpec(reply.sfFile.vRefNum, reply.sfFile.parID, reply.sfFile.name, dirfss) )
760 return 0;
Jack Jansen819f1771995-08-14 12:35:10 +0000761 return hook_args.selectcur_hit;
762}
763
764/*
765** Slightly extended StandardGetFile: accepts a prompt */
766void PyMac_PromptGetFile(short numTypes, ConstSFTypeListPtr typeList,
767 StandardFileReply *reply, char *prompt)
768{
769 static Point where = {-1, -1};
770 struct hook_args hook_args;
771
772 if ( !upp_inited ) {
773 myhook_upp = NewDlgHookYDProc(myhook_proc);
774 upp_inited = 1;
775 }
776 if ( prompt && *prompt )
777 hook_args.prompt = (char *)Pstring(prompt);
778 else
779 hook_args.prompt = NULL;
780 hook_args.selectcur_hit = 0;
781 CustomGetFile((FileFilterYDUPP)0, numTypes, typeList, reply, GETFILEPROMPT_ID, where,
782 myhook_upp, NULL, NULL, NULL, (void *)&hook_args);
Jack Jansen3ec804a1995-02-20 15:56:10 +0000783}
Jack Jansen5f653091995-01-18 13:53:49 +0000784
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000785/* Convert a 4-char string object argument to an OSType value */
Jack Jansen5f653091995-01-18 13:53:49 +0000786int
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000787PyMac_GetOSType(PyObject *v, OSType *pr)
Jack Jansen5f653091995-01-18 13:53:49 +0000788{
789 if (!PyString_Check(v) || PyString_Size(v) != 4) {
790 PyErr_SetString(PyExc_TypeError,
791 "OSType arg must be string of 4 chars");
792 return 0;
793 }
794 memcpy((char *)pr, PyString_AsString(v), 4);
795 return 1;
796}
797
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000798/* Convert an OSType value to a 4-char string object */
799PyObject *
800PyMac_BuildOSType(OSType t)
801{
802 return PyString_FromStringAndSize((char *)&t, 4);
803}
804
Jack Jansend1f06311996-08-01 15:23:54 +0000805/* Convert an NumVersion value to a 4-element tuple */
806PyObject *
807PyMac_BuildNumVersion(NumVersion t)
808{
809 return Py_BuildValue("(hhhh)", t.majorRev, t.minorAndBugRev, t.stage, t.nonRelRev);
810}
811
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000812
813/* Convert a Python string object to a Str255 */
Jack Jansen5f653091995-01-18 13:53:49 +0000814int
Guido van Rossum8f691791995-01-18 23:57:26 +0000815PyMac_GetStr255(PyObject *v, Str255 pbuf)
Jack Jansen5f653091995-01-18 13:53:49 +0000816{
817 int len;
818 if (!PyString_Check(v) || (len = PyString_Size(v)) > 255) {
819 PyErr_SetString(PyExc_TypeError,
820 "Str255 arg must be string of at most 255 chars");
821 return 0;
822 }
823 pbuf[0] = len;
824 memcpy((char *)(pbuf+1), PyString_AsString(v), len);
825 return 1;
826}
827
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000828/* Convert a Str255 to a Python string object */
829PyObject *
830PyMac_BuildStr255(Str255 s)
831{
Jack Jansenb734ade1999-12-17 17:15:50 +0000832 if ( s == NULL ) {
833 PyErr_SetString(PyExc_SystemError, "Str255 pointer is NULL");
834 return NULL;
835 }
836 return PyString_FromStringAndSize((char *)&s[1], (int)s[0]);
837}
838
839PyObject *
840PyMac_BuildOptStr255(Str255 s)
841{
842 if ( s == NULL ) {
843 Py_INCREF(Py_None);
844 return Py_None;
845 }
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000846 return PyString_FromStringAndSize((char *)&s[1], (int)s[0]);
847}
848
849
Jack Jansen5f653091995-01-18 13:53:49 +0000850/*
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000851** Convert a Python object to an FSSpec.
852** The object may either be a full pathname or a triple
853** (vrefnum, dirid, path).
Jack Jansen5f653091995-01-18 13:53:49 +0000854** NOTE: This routine will fail on pre-sys7 machines.
855** The caller is responsible for not calling this routine
856** in those cases (which is fine, since everyone calling
857** this is probably sys7 dependent anyway).
858*/
859int
Guido van Rossum8f691791995-01-18 23:57:26 +0000860PyMac_GetFSSpec(PyObject *v, FSSpec *fs)
Jack Jansen5f653091995-01-18 13:53:49 +0000861{
862 Str255 path;
863 short refnum;
864 long parid;
865 OSErr err;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000866 FSSpec *fs2;
Jack Jansen5f653091995-01-18 13:53:49 +0000867
Jack Jansene8e8ae01995-01-26 16:36:45 +0000868 /* first check whether it already is an FSSpec */
869 fs2 = mfs_GetFSSpecFSSpec(v);
870 if ( fs2 ) {
Jack Jansen3ec804a1995-02-20 15:56:10 +0000871 (void)FSMakeFSSpec(fs2->vRefNum, fs2->parID, fs2->name, fs);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000872 return 1;
873 }
Jack Jansen5f653091995-01-18 13:53:49 +0000874 if ( PyString_Check(v) ) {
875 /* It's a pathname */
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000876 if( !PyArg_Parse(v, "O&", PyMac_GetStr255, &path) )
Jack Jansen5f653091995-01-18 13:53:49 +0000877 return 0;
Jack Jansen378815c1996-03-06 16:21:34 +0000878 refnum = 0; /* XXXX Should get CurWD here?? */
Jack Jansen5f653091995-01-18 13:53:49 +0000879 parid = 0;
880 } else {
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000881 if( !PyArg_Parse(v, "(hlO&); FSSpec should be fullpath or (vrefnum,dirid,path)",
882 &refnum, &parid, PyMac_GetStr255, &path)) {
Jack Jansen5f653091995-01-18 13:53:49 +0000883 return 0;
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000884 }
Jack Jansen5f653091995-01-18 13:53:49 +0000885 }
886 err = FSMakeFSSpec(refnum, parid, path, fs);
887 if ( err && err != fnfErr ) {
Jack Jansen3d757542000-01-24 09:56:06 +0000888 PyMac_Error(err);
Jack Jansen5f653091995-01-18 13:53:49 +0000889 return 0;
890 }
891 return 1;
892}
893
Jack Jansen8bb573e1999-12-12 21:37:14 +0000894/* Convert FSSpec to PyObject */
895PyObject *PyMac_BuildFSSpec(FSSpec *v)
896{
897 return newmfssobject(v);
898}
Guido van Rossum8f691791995-01-18 23:57:26 +0000899
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000900/* Convert a Python object to a Rect.
Guido van Rossum5279ec61995-01-26 22:56:59 +0000901 The object must be a (left, top, right, bottom) tuple.
902 (This differs from the order in the struct but is consistent with
903 the arguments to SetRect(), and also with STDWIN). */
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000904int
905PyMac_GetRect(PyObject *v, Rect *r)
Guido van Rossum8f691791995-01-18 23:57:26 +0000906{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000907 return PyArg_Parse(v, "(hhhh)", &r->left, &r->top, &r->right, &r->bottom);
Guido van Rossum8f691791995-01-18 23:57:26 +0000908}
Guido van Rossumb3404661995-01-22 18:36:13 +0000909
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000910/* Convert a Rect to a Python object */
Guido van Rossumb3404661995-01-22 18:36:13 +0000911PyObject *
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000912PyMac_BuildRect(Rect *r)
Guido van Rossumb3404661995-01-22 18:36:13 +0000913{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000914 return Py_BuildValue("(hhhh)", r->left, r->top, r->right, r->bottom);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000915}
916
917
918/* Convert a Python object to a Point.
Guido van Rossum5279ec61995-01-26 22:56:59 +0000919 The object must be a (h, v) tuple.
920 (This differs from the order in the struct but is consistent with
921 the arguments to SetPoint(), and also with STDWIN). */
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000922int
923PyMac_GetPoint(PyObject *v, Point *p)
924{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000925 return PyArg_Parse(v, "(hh)", &p->h, &p->v);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000926}
927
928/* Convert a Point to a Python object */
929PyObject *
930PyMac_BuildPoint(Point p)
931{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000932 return Py_BuildValue("(hh)", p.h, p.v);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000933}
934
935
936/* Convert a Python object to an EventRecord.
937 The object must be a (what, message, when, (v, h), modifiers) tuple. */
938int
939PyMac_GetEventRecord(PyObject *v, EventRecord *e)
940{
941 return PyArg_Parse(v, "(hll(hh)h)",
942 &e->what,
943 &e->message,
944 &e->when,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000945 &e->where.h,
Guido van Rossum5279ec61995-01-26 22:56:59 +0000946 &e->where.v,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000947 &e->modifiers);
948}
949
950/* Convert a Rect to an EventRecord object */
951PyObject *
952PyMac_BuildEventRecord(EventRecord *e)
953{
954 return Py_BuildValue("(hll(hh)h)",
955 e->what,
956 e->message,
957 e->when,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000958 e->where.h,
Guido van Rossum5279ec61995-01-26 22:56:59 +0000959 e->where.v,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000960 e->modifiers);
Guido van Rossumb3404661995-01-22 18:36:13 +0000961}
Jack Jansenfa4d5d01995-11-15 15:19:29 +0000962
963/* Convert Python object to Fixed */
964int
965PyMac_GetFixed(PyObject *v, Fixed *f)
966{
967 double d;
968
969 if( !PyArg_Parse(v, "d", &d))
970 return 0;
971 *f = (Fixed)(d * 0x10000);
Jack Jansen31dd5c01996-05-31 13:01:39 +0000972 return 1;
Jack Jansenfa4d5d01995-11-15 15:19:29 +0000973}
974
975/* Convert a Point to a Python object */
976PyObject *
977PyMac_BuildFixed(Fixed f)
978{
979 double d;
980
981 d = f;
982 d = d / 0x10000;
983 return Py_BuildValue("d", d);
984}
985
Jack Jansend58cd631998-04-21 15:24:39 +0000986/* Convert wide to/from Python int or (hi, lo) tuple. XXXX Should use Python longs */
987int
988PyMac_Getwide(PyObject *v, wide *rv)
989{
990 if (PyInt_Check(v)) {
991 rv->hi = 0;
992 rv->lo = PyInt_AsLong(v);
993 if( rv->lo & 0x80000000 )
994 rv->hi = -1;
995 return 1;
996 }
997 return PyArg_Parse(v, "(ll)", &rv->hi, &rv->lo);
998}
999
1000
1001PyObject *
Jack Jansenbbf4be21998-04-23 13:20:17 +00001002PyMac_Buildwide(wide *w)
Jack Jansend58cd631998-04-21 15:24:39 +00001003{
Jack Jansenbbf4be21998-04-23 13:20:17 +00001004 if ( (w->hi == 0 && (w->lo & 0x80000000) == 0) ||
1005 (w->hi == -1 && (w->lo & 0x80000000) ) )
1006 return PyInt_FromLong(w->lo);
1007 return Py_BuildValue("(ll)", w->hi, w->lo);
Jack Jansend58cd631998-04-21 15:24:39 +00001008}