blob: e79a64aa29eecf3bb9afeac48e5b6e1f25bf363f [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
Jack Jansenbb6d83a2000-06-02 21:27:11 +000035#ifdef TARGET_API_MAC_CARBON
36/* Unfortunately this call is probably slower... */
37#define LMGetTicks() TickCount()
38#endif
39
Jack Jansenbf05d4c1996-08-19 15:11:45 +000040#ifdef __CFM68K__
41#undef GetEventQueue
42#endif /* __CFM68K__ */
43
Jack Jansenf93c72a1994-12-14 14:07:50 +000044#include "Python.h"
Guido van Rossumbecdbec1995-02-14 01:27:24 +000045
Jack Jansenf93c72a1994-12-14 14:07:50 +000046#include "macglue.h"
Jack Jansen74162f31995-02-15 22:58:33 +000047#include "marshal.h"
48#include "import.h"
Jack Janseneda78631997-06-12 15:29:46 +000049#include "importdl.h"
Jack Jansenf93c72a1994-12-14 14:07:50 +000050
Jack Jansen819f1771995-08-14 12:35:10 +000051#include "pythonresources.h"
52
Jack Jansenf93c72a1994-12-14 14:07:50 +000053#include <OSUtils.h> /* for Set(Current)A5 */
Jack Jansene8e8ae01995-01-26 16:36:45 +000054#include <Files.h>
Jack Jansen8cd2b721995-02-13 11:33:28 +000055#include <StandardFile.h>
Jack Jansenf93c72a1994-12-14 14:07:50 +000056#include <Resources.h>
57#include <Memory.h>
Jack Jansenf93c72a1994-12-14 14:07:50 +000058#include <Windows.h>
Jack Jansene8e8ae01995-01-26 16:36:45 +000059#include <Traps.h>
Jack Jansenee23d6e1995-01-27 14:43:25 +000060#include <Processes.h>
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +000061#include <Fonts.h>
62#include <Menus.h>
Jack Jansen08305501995-06-18 20:03:40 +000063#include <TextUtils.h>
Guido van Rossumcc0d8791995-01-30 08:57:13 +000064#ifdef THINK_C
65#include <OSEvents.h> /* For EvQElPtr */
66#endif
Jack Jansen16df2aa1995-02-27 16:17:28 +000067#ifdef __MWERKS__
68#include <SIOUX.h>
69#endif
Jack Jansen2d1306b2000-04-07 09:10:49 +000070#ifdef USE_GUSI1
Jack Jansen911ad6b1996-03-05 16:56:24 +000071#include <TFileSpec.h> /* For Path2FSSpec */
Jack Jansenf6865f71996-09-04 15:24:59 +000072#include <GUSI.h>
Jack Jansen911ad6b1996-03-05 16:56:24 +000073#endif
Jack Jansen2d1306b2000-04-07 09:10:49 +000074#include <LowMem.h>
Jack Jansenee23d6e1995-01-27 14:43:25 +000075
Jack Jansen3469e991996-09-06 00:30:45 +000076/* The ID of the Sioux apple menu */
77#define SIOUX_APPLEID 32000
78
Jack Jansenee23d6e1995-01-27 14:43:25 +000079#include <signal.h>
Jack Jansen74162f31995-02-15 22:58:33 +000080#include <stdio.h>
Jack Jansene8e8ae01995-01-26 16:36:45 +000081
Jack Jansenee23d6e1995-01-27 14:43:25 +000082/*
Jack Jansend1f06311996-08-01 15:23:54 +000083** When less than this amount of stackspace is left we
84** raise a MemoryError.
85*/
86#ifndef MINIMUM_STACK_SIZE
87#ifdef __powerc
88#define MINIMUM_STACK_SIZE 8192
89#else
90#define MINIMUM_STACK_SIZE 4096
91#endif
92#endif
93
94/*
Jack Jansen16df2aa1995-02-27 16:17:28 +000095** We have to be careful, since we can't handle
Jack Jansenee23d6e1995-01-27 14:43:25 +000096** things like updates (and they'll keep coming back if we don't
Jack Jansen16df2aa1995-02-27 16:17:28 +000097** handle them). Note that we don't know who has windows open, so
98** even handing updates off to SIOUX under MW isn't going to work.
Jack Jansenee23d6e1995-01-27 14:43:25 +000099*/
Jack Jansen0c968871997-08-26 13:20:34 +0000100#define MAINLOOP_EVENTMASK (mDownMask|keyDownMask|osMask|activMask)
Jack Jansene8e8ae01995-01-26 16:36:45 +0000101
102#include <signal.h>
Jack Jansenf93c72a1994-12-14 14:07:50 +0000103
Guido van Rossumb3404661995-01-22 18:36:13 +0000104/* XXX We should include Errors.h here, but it has a name conflict
Jack Jansen5f653091995-01-18 13:53:49 +0000105** with the python errors.h. */
106#define fnfErr -43
107
Jack Jansene8e8ae01995-01-26 16:36:45 +0000108/* Declared in macfsmodule.c: */
109extern FSSpec *mfs_GetFSSpecFSSpec();
Jack Jansen8bb573e1999-12-12 21:37:14 +0000110extern PyObject *newmfssobject Py_PROTO((FSSpec *));
Jack Jansene8e8ae01995-01-26 16:36:45 +0000111
Jack Jansenee23d6e1995-01-27 14:43:25 +0000112/* Interrupt code variables: */
113static int interrupted; /* Set to true when cmd-. seen */
114static RETSIGTYPE intcatcher Py_PROTO((int));
115
Jack Jansen36ed5061997-06-20 16:18:15 +0000116static int PyMac_Yield Py_PROTO((void));
Jack Jansenf6865f71996-09-04 15:24:59 +0000117
Jack Jansene8e8ae01995-01-26 16:36:45 +0000118/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000119** These are the real scheduling parameters that control what we check
120** in the event loop, and how often we check. The values are initialized
121** from pyMac_SchedParamStruct.
122*/
123
124struct real_sched_param_struct {
125 int check_interrupt; /* if true check for command-dot */
126 int process_events; /* if nonzero enable evt processing, this mask */
127 int besocial; /* if nonzero be a little social with CPU */
128 unsigned long check_interval; /* how often to check, in ticks */
129 unsigned long bg_yield; /* yield so long when in background */
130 /* these are computed from previous and clock and such */
131 int enabled; /* check_interrupt OR process_event OR yield */
132 unsigned long next_check; /* when to check/yield next, in ticks */
133};
134
135static struct real_sched_param_struct schedparams =
136 { 1, MAINLOOP_EVENTMASK, 1, 15, 15, 1, 0};
137
Jack Jansen819f1771995-08-14 12:35:10 +0000138/*
Jack Jansenf6865f71996-09-04 15:24:59 +0000139** Workaround for sioux/gusi combo: set when we are exiting
140*/
141int PyMac_ConsoleIsDead;
142
143/*
Jack Jansencaa7c461997-06-12 10:49:13 +0000144** Sioux menu bar, saved early so we can restore it
145*/
146static Handle sioux_mbar;
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};
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000155#ifdef TARGET_API_MAC_CARBON
156/* The StandardFile hooks don't exist in Carbon. This breaks GetDirectory,
157** but the macfsn code will replace it by a NavServices version anyway.
158*/
159#define myhook_upp NULL
160#else
Jack Jansen819f1771995-08-14 12:35:10 +0000161static DlgHookYDUPP myhook_upp;
162static int upp_inited = 0;
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000163#endif
Jack Jansen819f1771995-08-14 12:35:10 +0000164
Jack Jansen36ed5061997-06-20 16:18:15 +0000165/*
166** The python-code event handler
167*/
168static PyObject *python_event_handler;
169
Jack Jansen8f5725a1999-12-07 23:08:10 +0000170/*
171** Set to true if we're appearance-compliant
172*/
173int PyMac_AppearanceCompliant;
174
Jack Jansen2d1306b2000-04-07 09:10:49 +0000175#ifdef USE_GUSI1
Jack Jansen378815c1996-03-06 16:21:34 +0000176/*
177** GUSI (1.6.0 and earlier, at the least) do not set the MacOS idea of
178** the working directory. Hence, we call this routine after each call
179** to chdir() to rectify things.
180*/
181void
182PyMac_FixGUSIcd()
183{
184 WDPBRec pb;
185 FSSpec curdirfss;
186
187 if ( Path2FSSpec(":x", &curdirfss) != noErr )
188 return;
189
190 /* Set MacOS "working directory" */
191 pb.ioNamePtr= "\p";
192 pb.ioVRefNum= curdirfss.vRefNum;
193 pb.ioWDDirID= curdirfss.parID;
Jack Jansen08c3be31997-04-08 15:27:00 +0000194 if (PBHSetVolSync(&pb) != noErr)
Jack Jansen378815c1996-03-06 16:21:34 +0000195 return;
Jack Jansen378815c1996-03-06 16:21:34 +0000196}
Jack Jansen2d1306b2000-04-07 09:10:49 +0000197#endif
Jack Jansen7ac70af1996-08-19 11:01:05 +0000198
Jack Jansen2d1306b2000-04-07 09:10:49 +0000199#ifdef USE_GUSI
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000200/*
201** SpinCursor (needed by GUSI) drags in heaps of stuff, so we
202** provide a dummy here.
203*/
Jack Jansencfadbd41996-08-19 11:36:25 +0000204void SpinCursor(short x) { /* Dummy */ }
Jack Jansenefaada71998-02-20 16:03:15 +0000205void RotateCursor(short x) { /* Dummy */ }
Jack Jansencfadbd41996-08-19 11:36:25 +0000206
Jack Jansenf6865f71996-09-04 15:24:59 +0000207/*
208** Replacement GUSI Spin function
209*/
Jack Jansen2d1306b2000-04-07 09:10:49 +0000210#ifdef USE_GUSI1
Jack Jansenf6865f71996-09-04 15:24:59 +0000211static int
212PyMac_GUSISpin(spin_msg msg, long arg)
213{
Jack Jansene3ae0df1997-06-03 15:28:29 +0000214 static Boolean inForeground = true;
215 int maxsleep = 6; /* 6 ticks is "normal" sleeptime */
Jack Jansenf6865f71996-09-04 15:24:59 +0000216
217 if (PyMac_ConsoleIsDead) return 0;
218#if 0
219 if (inForeground)
220 SpinCursor(msg == SP_AUTO_SPIN ? short(arg) : 1);
221#endif
222
223 if (interrupted) return -1;
224
Jack Jansene3ae0df1997-06-03 15:28:29 +0000225 if ( msg == SP_AUTO_SPIN )
226 maxsleep = 0;
227 if ( msg==SP_SLEEP||msg==SP_SELECT )
228 maxsleep = arg;
Jack Jansenf6865f71996-09-04 15:24:59 +0000229
Jack Jansene3ae0df1997-06-03 15:28:29 +0000230 PyMac_DoYield(maxsleep, 0); /* XXXX or is it safe to call python here? */
Jack Jansenf6865f71996-09-04 15:24:59 +0000231
232 return 0;
233}
234
235void
236PyMac_SetGUSISpin() {
237 GUSISetHook(GUSI_SpinHook, (GUSIHook)PyMac_GUSISpin);
238}
Jack Jansen2d1306b2000-04-07 09:10:49 +0000239#endif
Jack Jansenf6865f71996-09-04 15:24:59 +0000240
Jack Jansena39f1b01997-05-23 15:35:14 +0000241/* Called at exit() time thru atexit(), to stop event processing */
242void
243PyMac_StopGUSISpin() {
244 PyMac_ConsoleIsDead = 1;
245}
246
247/*
248** Replacement routines for the PLstr... functions so we don't need
249** StdCLib. Moreover, that implementation is broken under cfm68k...
250*/
Jack Jansen8bb573e1999-12-12 21:37:14 +0000251pascal void
Jack Jansena39f1b01997-05-23 15:35:14 +0000252PLstrcpy(to, fr)
253 unsigned char *to, *fr;
254{
255 memcpy(to, fr, fr[0]+1);
256}
257
Jack Jansen8bb573e1999-12-12 21:37:14 +0000258pascal int
Jack Jansena39f1b01997-05-23 15:35:14 +0000259PLstrcmp(s1, s2)
260 unsigned char *s1, *s2;
261{
262 int res;
263 int l = s1[0] < s2[0] ? s1[0] : s2[0];
264
265 res = memcmp(s1+1, s2+1, l);
266 if ( res != 0 )
267 return res;
268
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000269 if ( s1[0] < s2[0] )
Jack Jansena39f1b01997-05-23 15:35:14 +0000270 return -1;
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000271 else if ( s1[0] > s2[0] )
Jack Jansena39f1b01997-05-23 15:35:14 +0000272 return 1;
273 else
274 return 0;
275}
276
Jack Jansen8bb573e1999-12-12 21:37:14 +0000277pascal unsigned char *
Jack Jansena39f1b01997-05-23 15:35:14 +0000278PLstrrchr(str, chr)
279 unsigned char *str;
280 unsigned char chr;
281{
282 unsigned char *ptr = 0;
283 unsigned char *p;
284
285 for(p=str+1; p<str+str[0]; p++)
286 if ( *p == chr )
287 ptr = p;
288 return ptr;
289}
290
291#endif /* USE_GUSI */
Jack Jansen378815c1996-03-06 16:21:34 +0000292
Jack Jansen819f1771995-08-14 12:35:10 +0000293
Jack Jansen5f653091995-01-18 13:53:49 +0000294/* Convert C to Pascal string. Returns pointer to static buffer. */
295unsigned char *
296Pstring(char *str)
297{
298 static Str255 buf;
299 int len;
300
301 len = strlen(str);
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000302 if (len > 255)
303 len = 255;
Jack Jansen5f653091995-01-18 13:53:49 +0000304 buf[0] = (unsigned char)len;
305 strncpy((char *)buf+1, str, len);
306 return buf;
307}
308
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000309/* Like strerror() but for Mac OS error numbers */
310char *PyMac_StrError(int err)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000311{
312 static char buf[256];
313 Handle h;
314 char *str;
315
316 h = GetResource('Estr', err);
317 if ( h ) {
318 HLock(h);
319 str = (char *)*h;
320 memcpy(buf, str+1, (unsigned char)str[0]);
Guido van Rossumcc9bc8f1995-02-13 16:17:03 +0000321 buf[(unsigned char)str[0]] = '\0';
Jack Jansenf93c72a1994-12-14 14:07:50 +0000322 HUnlock(h);
323 ReleaseResource(h);
324 } else {
325 sprintf(buf, "Mac OS error code %d", err);
326 }
327 return buf;
328}
329
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000330/* Exception object shared by all Mac specific modules for Mac OS errors */
331PyObject *PyMac_OSErrException;
332
333/* Initialize and return PyMac_OSErrException */
334PyObject *
335PyMac_GetOSErrException()
336{
337 if (PyMac_OSErrException == NULL)
338 PyMac_OSErrException = PyString_FromString("Mac OS Error");
339 return PyMac_OSErrException;
340}
341
Jack Jansenf93c72a1994-12-14 14:07:50 +0000342/* Set a MAC-specific error from errno, and return NULL; return None if no error */
343PyObject *
Guido van Rossumfffb8bb1995-01-12 12:37:24 +0000344PyErr_Mac(PyObject *eobj, int err)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000345{
346 char *msg;
347 PyObject *v;
Jack Jansenf93c72a1994-12-14 14:07:50 +0000348
Guido van Rossum8f691791995-01-18 23:57:26 +0000349 if (err == 0 && !PyErr_Occurred()) {
Jack Jansenf93c72a1994-12-14 14:07:50 +0000350 Py_INCREF(Py_None);
351 return Py_None;
352 }
Guido van Rossum8f691791995-01-18 23:57:26 +0000353 if (err == -1 && PyErr_Occurred())
354 return NULL;
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000355 msg = PyMac_StrError(err);
Jack Jansenf93c72a1994-12-14 14:07:50 +0000356 v = Py_BuildValue("(is)", err, msg);
357 PyErr_SetObject(eobj, v);
358 Py_DECREF(v);
359 return NULL;
360}
361
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000362/* Call PyErr_Mac with PyMac_OSErrException */
363PyObject *
364PyMac_Error(OSErr err)
365{
366 return PyErr_Mac(PyMac_GetOSErrException(), err);
367}
368
Jack Jansen1ed95291996-07-22 15:25:10 +0000369#ifdef USE_STACKCHECK
370/* Check for stack overflow */
371int
372PyOS_CheckStack()
373{
374 long left;
375
376 left = StackSpace();
Jack Jansend1f06311996-08-01 15:23:54 +0000377 if ( left < MINIMUM_STACK_SIZE )
Jack Jansen1ed95291996-07-22 15:25:10 +0000378 return -1;
379 return 0;
380}
381#endif /* USE_STACKCHECK */
382
Jack Jansenee23d6e1995-01-27 14:43:25 +0000383/* The catcher routine (which may not be used for all compilers) */
384static RETSIGTYPE
385intcatcher(sig)
386 int sig;
387{
388 interrupted = 1;
389 signal(SIGINT, intcatcher);
390}
391
392void
393PyOS_InitInterrupts()
394{
395 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
396 signal(SIGINT, intcatcher);
397}
398
Jack Jansena8441de1997-08-08 14:57:37 +0000399void
400PyOS_FiniInterrupts()
401{
402}
403
Jack Jansenee23d6e1995-01-27 14:43:25 +0000404/*
405** This routine scans the event queue looking for cmd-.
406** This is the only way to get an interrupt under THINK (since it
407** doesn't do SIGINT handling), but is also used under MW, when
408** the full-fledged event loop is disabled. This way, we can at least
409** interrupt a runaway python program.
410*/
411static void
412scan_event_queue(flush)
413 int flush;
414{
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000415#ifdef TARGET_API_MAC_CARBON
416 /* CARBONXXXX To be implemented */
417 return;
418#else
Jack Jansenee23d6e1995-01-27 14:43:25 +0000419 register EvQElPtr q;
420
Jack Jansenefaada71998-02-20 16:03:15 +0000421 q = (EvQElPtr) LMGetEventQueue()->qHead;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000422
423 for (; q; q = (EvQElPtr)q->qLink) {
424 if (q->evtQWhat == keyDown &&
425 (char)q->evtQMessage == '.' &&
426 (q->evtQModifiers & cmdKey) != 0) {
427 if ( flush )
428 FlushEvents(keyDownMask, 0);
429 interrupted = 1;
430 break;
431 }
432 }
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000433#endif
Jack Jansenee23d6e1995-01-27 14:43:25 +0000434}
435
436int
Jack Jansen36ed5061997-06-20 16:18:15 +0000437PyErr_CheckSignals()
Jack Jansenee23d6e1995-01-27 14:43:25 +0000438{
Jack Jansene3ae0df1997-06-03 15:28:29 +0000439 if (schedparams.enabled) {
440 if ( (unsigned long)LMGetTicks() > schedparams.next_check ) {
Jack Jansen36ed5061997-06-20 16:18:15 +0000441 if ( PyMac_Yield() < 0)
442 return -1;
Jack Jansene3ae0df1997-06-03 15:28:29 +0000443 schedparams.next_check = (unsigned long)LMGetTicks()
444 + schedparams.check_interval;
445 if (interrupted) {
Jack Jansencaa7c461997-06-12 10:49:13 +0000446 scan_event_queue(1); /* Eat events up to cmd-. */
Jack Jansene3ae0df1997-06-03 15:28:29 +0000447 interrupted = 0;
Jack Jansen36ed5061997-06-20 16:18:15 +0000448 PyErr_SetNone(PyExc_KeyboardInterrupt);
449 return -1;
Jack Jansene3ae0df1997-06-03 15:28:29 +0000450 }
451 }
Jack Jansenee23d6e1995-01-27 14:43:25 +0000452 }
453 return 0;
454}
455
Jack Jansen36ed5061997-06-20 16:18:15 +0000456int
457PyOS_InterruptOccurred()
458{
459 scan_event_queue(1);
460 return interrupted;
461}
Jack Jansenee23d6e1995-01-27 14:43:25 +0000462/* Check whether we are in the foreground */
463int
464PyMac_InForeground()
465{
466 static ProcessSerialNumber ours;
467 static inited;
468 ProcessSerialNumber curfg;
469 Boolean eq;
470
Jack Jansene3ae0df1997-06-03 15:28:29 +0000471 if ( inited == 0 ) {
Jack Jansenee23d6e1995-01-27 14:43:25 +0000472 (void)GetCurrentProcess(&ours);
Jack Jansene3ae0df1997-06-03 15:28:29 +0000473 inited = 1;
474 }
Jack Jansenee23d6e1995-01-27 14:43:25 +0000475 if ( GetFrontProcess(&curfg) < 0 )
476 eq = 1;
477 else if ( SameProcess(&ours, &curfg, &eq) < 0 )
478 eq = 1;
479 return (int)eq;
480
481}
482
Jack Jansen36ed5061997-06-20 16:18:15 +0000483int
484PyMac_SetEventHandler(PyObject *evh)
485{
486 if ( evh && python_event_handler ) {
487 PyErr_SetString(PyExc_RuntimeError, "Python event handler already set");
488 return 0;
489 }
490 if ( python_event_handler )
491 Py_DECREF(python_event_handler);
492 if ( evh )
493 Py_INCREF(evh);
494 python_event_handler = evh;
495 return 1;
496}
497
Jack Jansenf93c72a1994-12-14 14:07:50 +0000498/*
Jack Jansena76382a1995-02-02 14:25:56 +0000499** Handle an event, either one found in the mainloop eventhandler or
500** one passed back from the python program.
501*/
502void
Jack Jansen36ed5061997-06-20 16:18:15 +0000503PyMac_HandleEventIntern(evp)
Jack Jansena76382a1995-02-02 14:25:56 +0000504 EventRecord *evp;
505{
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000506#ifndef TARGET_API_MAC_CARBON
Jack Jansen0c968871997-08-26 13:20:34 +0000507 if ( evp->what == mouseDown ) {
508 WindowPtr wp;
509
510 if ( FindWindow(evp->where, &wp) == inSysWindow ) {
511 SystemClick(evp, wp);
512 return;
513 }
514 }
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000515#endif
Jack Jansena76382a1995-02-02 14:25:56 +0000516#ifdef __MWERKS__
Jack Jansen38e97661995-11-10 14:53:00 +0000517 {
518 int siouxdidit;
519
520 /* If SIOUX wants it we're done */
521 siouxdidit = SIOUXHandleOneEvent(evp);
522 if ( siouxdidit )
523 return;
524 }
Jack Jansena76382a1995-02-02 14:25:56 +0000525#else
Jack Jansen0c968871997-08-26 13:20:34 +0000526 /* Other compilers are just unlucky... */
Jack Jansena76382a1995-02-02 14:25:56 +0000527#endif /* !__MWERKS__ */
Jack Jansen36ed5061997-06-20 16:18:15 +0000528}
529
530/*
531** Handle an event, either through HandleEvent or by passing it to the Python
532** event handler.
533*/
534int
535PyMac_HandleEvent(evp)
536 EventRecord *evp;
537{
538 PyObject *rv;
539
540 if ( python_event_handler ) {
541 rv = PyObject_CallFunction(python_event_handler, "(O&)",
542 PyMac_BuildEventRecord, evp);
543 if ( rv )
544 Py_DECREF(rv);
545 else
546 return -1; /* Propagate exception */
547 } else {
548 PyMac_HandleEventIntern(evp);
549 }
550 return 0;
Jack Jansena76382a1995-02-02 14:25:56 +0000551}
552
553/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000554** Yield the CPU to other tasks without processing events.
Jack Jansene8e8ae01995-01-26 16:36:45 +0000555*/
Jack Jansen2d1306b2000-04-07 09:10:49 +0000556int
Jack Jansene3ae0df1997-06-03 15:28:29 +0000557PyMac_DoYield(int maxsleep, int maycallpython)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000558{
559 EventRecord ev;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000560 int gotone;
Jack Jansene3ae0df1997-06-03 15:28:29 +0000561 long latest_time_ready;
Jack Jansen36ed5061997-06-20 16:18:15 +0000562 static int in_here = 0;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000563
Jack Jansen36ed5061997-06-20 16:18:15 +0000564 in_here++;
Jack Jansene3ae0df1997-06-03 15:28:29 +0000565 /*
566 ** First check for interrupts, if wanted.
567 ** This sets a flag that will be picked up at an appropriate
568 ** moment in the mainloop.
569 */
570 if (schedparams.check_interrupt)
Jack Jansenee23d6e1995-01-27 14:43:25 +0000571 scan_event_queue(0);
Jack Jansene3ae0df1997-06-03 15:28:29 +0000572
573 /* XXXX Implementing an idle routine goes here */
Jack Jansene8e8ae01995-01-26 16:36:45 +0000574
Jack Jansene3ae0df1997-06-03 15:28:29 +0000575 /*
576 ** Check which of the eventloop cases we have:
577 ** - process events
578 ** - don't process events but do yield
579 ** - do neither
580 */
Jack Jansen36ed5061997-06-20 16:18:15 +0000581 if( in_here > 1 || !schedparams.process_events ||
582 (python_event_handler && !maycallpython) ) {
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000583#ifndef TARGET_API_MAC_CARBON
Jack Jansene3ae0df1997-06-03 15:28:29 +0000584 if ( maxsleep >= 0 ) {
Jack Jansene8e8ae01995-01-26 16:36:45 +0000585 SystemTask();
Jack Jansene3ae0df1997-06-03 15:28:29 +0000586 }
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000587#endif
Jack Jansene3ae0df1997-06-03 15:28:29 +0000588 } else {
589 latest_time_ready = LMGetTicks() + maxsleep;
Jack Jansen2d1306b2000-04-07 09:10:49 +0000590 do {
Jack Jansen0c968871997-08-26 13:20:34 +0000591 /* XXXX Hack by Jack.
592 ** In time.sleep() you can click to another application
593 ** once only. If you come back to Python you cannot get away
594 ** again.
595 **/
Jack Jansen36ed5061997-06-20 16:18:15 +0000596 gotone = WaitNextEvent(schedparams.process_events, &ev, maxsleep, NULL);
Jack Jansene3ae0df1997-06-03 15:28:29 +0000597 /* Get out quickly if nothing interesting is happening */
598 if ( !gotone || ev.what == nullEvent )
599 break;
Jack Jansen36ed5061997-06-20 16:18:15 +0000600 if ( PyMac_HandleEvent(&ev) < 0 ) {
601 in_here--;
602 return -1;
603 }
Jack Jansene3ae0df1997-06-03 15:28:29 +0000604 maxsleep = latest_time_ready - LMGetTicks();
Jack Jansen2d1306b2000-04-07 09:10:49 +0000605 } while ( maxsleep > 0 );
Jack Jansenf93c72a1994-12-14 14:07:50 +0000606 }
Jack Jansen36ed5061997-06-20 16:18:15 +0000607 in_here--;
608 return 0;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000609}
610
611/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000612** Process events and/or yield the CPU to other tasks if opportune
Jack Jansene8e8ae01995-01-26 16:36:45 +0000613*/
Jack Jansen36ed5061997-06-20 16:18:15 +0000614int
Jack Jansene8e8ae01995-01-26 16:36:45 +0000615PyMac_Yield() {
Jack Jansene3ae0df1997-06-03 15:28:29 +0000616 unsigned long maxsleep;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000617
Jack Jansene3ae0df1997-06-03 15:28:29 +0000618 if( PyMac_InForeground() )
619 maxsleep = 0;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000620 else
Jack Jansene3ae0df1997-06-03 15:28:29 +0000621 maxsleep = schedparams.bg_yield;
622
Jack Jansen36ed5061997-06-20 16:18:15 +0000623 return PyMac_DoYield(maxsleep, 1);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000624}
625
626/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000627** Return current scheduler parameters
Jack Jansene8e8ae01995-01-26 16:36:45 +0000628*/
Jack Jansene3ae0df1997-06-03 15:28:29 +0000629void
630PyMac_GetSchedParams(PyMacSchedParams *sp)
Jack Jansene8e8ae01995-01-26 16:36:45 +0000631{
Jack Jansene3ae0df1997-06-03 15:28:29 +0000632 sp->check_interrupt = schedparams.check_interrupt;
633 sp->process_events = schedparams.process_events;
634 sp->besocial = schedparams.besocial;
635 sp->check_interval = schedparams.check_interval / 60.0;
636 sp->bg_yield = schedparams.bg_yield / 60.0;
Jack Jansenf93c72a1994-12-14 14:07:50 +0000637}
Jack Jansenf6865f71996-09-04 15:24:59 +0000638
Jack Jansen74162f31995-02-15 22:58:33 +0000639/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000640** Set current scheduler parameters
641*/
642void
643PyMac_SetSchedParams(PyMacSchedParams *sp)
644{
645 schedparams.check_interrupt = sp->check_interrupt;
646 schedparams.process_events = sp->process_events;
647 schedparams.besocial = sp->besocial;
648 schedparams.check_interval = (unsigned long)(sp->check_interval*60);
649 schedparams.bg_yield = (unsigned long)(sp->bg_yield*60);
650 if ( schedparams.check_interrupt || schedparams.process_events ||
651 schedparams.besocial )
652 schedparams.enabled = 1;
653 else
654 schedparams.enabled = 0;
655 schedparams.next_check = 0; /* Check immedeately */
656}
Jack Jansencaa7c461997-06-12 10:49:13 +0000657
Jack Jansene3ae0df1997-06-03 15:28:29 +0000658/*
Jack Jansen3469e991996-09-06 00:30:45 +0000659** Install our menu bar.
660*/
661void
662PyMac_InitMenuBar()
663{
Jack Jansen3469e991996-09-06 00:30:45 +0000664 MenuHandle applemenu;
665
Jack Jansencaa7c461997-06-12 10:49:13 +0000666 if ( (sioux_mbar=GetMenuBar()) == NULL ) {
667 /* Sioux menu not installed yet. Do so */
668 SIOUXSetupMenus();
669 if ( (sioux_mbar=GetMenuBar()) == NULL )
670 return;
671 }
Jack Jansen08c3be31997-04-08 15:27:00 +0000672 if ( (applemenu=GetMenuHandle(SIOUX_APPLEID)) == NULL ) return;
Jack Jansen3469e991996-09-06 00:30:45 +0000673 SetMenuItemText(applemenu, 1, "\pAbout Python...");
674}
675
676/*
Jack Jansencaa7c461997-06-12 10:49:13 +0000677** Restore sioux menu bar
678*/
679void
680PyMac_RestoreMenuBar()
681{
Jack Janseneda78631997-06-12 15:29:46 +0000682 if ( sioux_mbar ) {
Jack Jansencaa7c461997-06-12 10:49:13 +0000683 SetMenuBar(sioux_mbar);
Jack Janseneda78631997-06-12 15:29:46 +0000684 DrawMenuBar();
Jack Jansenefaada71998-02-20 16:03:15 +0000685 } else
686 PyMac_InitMenuBar();
Jack Jansencaa7c461997-06-12 10:49:13 +0000687}
688
689
690/*
Jack Jansen3469e991996-09-06 00:30:45 +0000691** Our replacement about box
692*/
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000693
694#include "patchlevel.h"
695
Jack Jansen3469e991996-09-06 00:30:45 +0000696void
697SIOUXDoAboutBox(void)
698{
699 DialogPtr theDialog;
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000700 WindowPtr theWindow;
Jack Jansen3469e991996-09-06 00:30:45 +0000701 short item;
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000702 short fontID;
Jack Jansen3469e991996-09-06 00:30:45 +0000703
704 if( (theDialog = GetNewDialog(ABOUT_ID, NULL, (WindowPtr)-1)) == NULL )
705 return;
Jack Jansend617c571996-09-22 22:14:30 +0000706 theWindow = GetDialogWindow(theDialog);
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000707 SetPortWindowPort(theWindow);
708 GetFNum("\pPython-Sans", &fontID);
709 if (fontID == 0)
710 fontID = kFontIDGeneva;
711 TextFont(fontID);
712 TextSize(9);
713 ParamText(Pstring(PATCHLEVEL), "\p", "\p", "\p");
Jack Jansend617c571996-09-22 22:14:30 +0000714 ShowWindow(theWindow);
Jack Jansen3469e991996-09-06 00:30:45 +0000715 ModalDialog(NULL, &item);
716 DisposeDialog(theDialog);
717}
718
Jack Janseneda78631997-06-12 15:29:46 +0000719#if 0
720int
721PyMac_FileExists(char *name)
722{
723 FSSpec fss;
724
725 if ( FSMakeFSSpec(0, 0, Pstring(name), &fss) == noErr )
726 return 1;
727 return 0;
728}
729#endif
730
731/*
Jack Jansen3ec804a1995-02-20 15:56:10 +0000732** Helper routine for GetDirectory
733*/
Guido van Rossum24a45e31995-02-20 23:45:53 +0000734static pascal short
Jack Jansen819f1771995-08-14 12:35:10 +0000735myhook_proc(short item, DialogPtr theDialog, struct hook_args *dataptr)
Jack Jansen3ec804a1995-02-20 15:56:10 +0000736{
Jack Jansen819f1771995-08-14 12:35:10 +0000737 if ( item == sfHookFirstCall && dataptr->prompt) {
738 Handle prompth;
739 short type;
740 Rect rect;
741
742 GetDialogItem(theDialog, PROMPT_ITEM, &type, &prompth, &rect);
743 if ( prompth )
744 SetDialogItemText(prompth, (unsigned char *)dataptr->prompt);
745 } else
Jack Jansen3ec804a1995-02-20 15:56:10 +0000746 if ( item == SELECTCUR_ITEM ) {
747 item = sfItemCancelButton;
Jack Jansen819f1771995-08-14 12:35:10 +0000748 dataptr->selectcur_hit = 1;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000749 }
750 return item;
751}
752
753/*
754** Ask the user for a directory. I still can't understand
755** why Apple doesn't provide a standard solution for this...
756*/
757int
Jack Jansen819f1771995-08-14 12:35:10 +0000758PyMac_GetDirectory(dirfss, prompt)
Jack Jansen3ec804a1995-02-20 15:56:10 +0000759 FSSpec *dirfss;
Jack Jansen819f1771995-08-14 12:35:10 +0000760 char *prompt;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000761{
762 static SFTypeList list = {'fldr', 0, 0, 0};
763 static Point where = {-1, -1};
Jack Jansen3ec804a1995-02-20 15:56:10 +0000764 StandardFileReply reply;
Jack Jansen819f1771995-08-14 12:35:10 +0000765 struct hook_args hook_args;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000766
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000767#ifndef TARGET_API_MAC_CARBON
Jack Jansen3ec804a1995-02-20 15:56:10 +0000768 if ( !upp_inited ) {
769 myhook_upp = NewDlgHookYDProc(myhook_proc);
770 upp_inited = 1;
771 }
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000772#endif
Jack Jansen819f1771995-08-14 12:35:10 +0000773 if ( prompt && *prompt )
774 hook_args.prompt = (char *)Pstring(prompt);
775 else
776 hook_args.prompt = NULL;
777 hook_args.selectcur_hit = 0;
Guido van Rossum24a45e31995-02-20 23:45:53 +0000778 CustomGetFile((FileFilterYDUPP)0, 1, list, &reply, GETDIR_ID, where, myhook_upp,
Jack Jansen819f1771995-08-14 12:35:10 +0000779 NULL, NULL, NULL, (void *)&hook_args);
Jack Jansen3ec804a1995-02-20 15:56:10 +0000780
781 reply.sfFile.name[0] = 0;
782 if( FSMakeFSSpec(reply.sfFile.vRefNum, reply.sfFile.parID, reply.sfFile.name, dirfss) )
783 return 0;
Jack Jansen819f1771995-08-14 12:35:10 +0000784 return hook_args.selectcur_hit;
785}
786
787/*
788** Slightly extended StandardGetFile: accepts a prompt */
789void PyMac_PromptGetFile(short numTypes, ConstSFTypeListPtr typeList,
790 StandardFileReply *reply, char *prompt)
791{
792 static Point where = {-1, -1};
793 struct hook_args hook_args;
794
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000795#ifndef TARGET_API_MAC_CARBON
Jack Jansen819f1771995-08-14 12:35:10 +0000796 if ( !upp_inited ) {
797 myhook_upp = NewDlgHookYDProc(myhook_proc);
798 upp_inited = 1;
799 }
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000800#endif
Jack Jansen819f1771995-08-14 12:35:10 +0000801 if ( prompt && *prompt )
802 hook_args.prompt = (char *)Pstring(prompt);
803 else
804 hook_args.prompt = NULL;
805 hook_args.selectcur_hit = 0;
806 CustomGetFile((FileFilterYDUPP)0, numTypes, typeList, reply, GETFILEPROMPT_ID, where,
807 myhook_upp, NULL, NULL, NULL, (void *)&hook_args);
Jack Jansen3ec804a1995-02-20 15:56:10 +0000808}
Jack Jansen5f653091995-01-18 13:53:49 +0000809
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000810/* Convert a 4-char string object argument to an OSType value */
Jack Jansen5f653091995-01-18 13:53:49 +0000811int
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000812PyMac_GetOSType(PyObject *v, OSType *pr)
Jack Jansen5f653091995-01-18 13:53:49 +0000813{
814 if (!PyString_Check(v) || PyString_Size(v) != 4) {
815 PyErr_SetString(PyExc_TypeError,
816 "OSType arg must be string of 4 chars");
817 return 0;
818 }
819 memcpy((char *)pr, PyString_AsString(v), 4);
820 return 1;
821}
822
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000823/* Convert an OSType value to a 4-char string object */
824PyObject *
825PyMac_BuildOSType(OSType t)
826{
827 return PyString_FromStringAndSize((char *)&t, 4);
828}
829
Jack Jansend1f06311996-08-01 15:23:54 +0000830/* Convert an NumVersion value to a 4-element tuple */
831PyObject *
832PyMac_BuildNumVersion(NumVersion t)
833{
834 return Py_BuildValue("(hhhh)", t.majorRev, t.minorAndBugRev, t.stage, t.nonRelRev);
835}
836
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000837
838/* Convert a Python string object to a Str255 */
Jack Jansen5f653091995-01-18 13:53:49 +0000839int
Guido van Rossum8f691791995-01-18 23:57:26 +0000840PyMac_GetStr255(PyObject *v, Str255 pbuf)
Jack Jansen5f653091995-01-18 13:53:49 +0000841{
842 int len;
843 if (!PyString_Check(v) || (len = PyString_Size(v)) > 255) {
844 PyErr_SetString(PyExc_TypeError,
845 "Str255 arg must be string of at most 255 chars");
846 return 0;
847 }
848 pbuf[0] = len;
849 memcpy((char *)(pbuf+1), PyString_AsString(v), len);
850 return 1;
851}
852
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000853/* Convert a Str255 to a Python string object */
854PyObject *
855PyMac_BuildStr255(Str255 s)
856{
Jack Jansenb734ade1999-12-17 17:15:50 +0000857 if ( s == NULL ) {
858 PyErr_SetString(PyExc_SystemError, "Str255 pointer is NULL");
859 return NULL;
860 }
861 return PyString_FromStringAndSize((char *)&s[1], (int)s[0]);
862}
863
864PyObject *
865PyMac_BuildOptStr255(Str255 s)
866{
867 if ( s == NULL ) {
868 Py_INCREF(Py_None);
869 return Py_None;
870 }
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000871 return PyString_FromStringAndSize((char *)&s[1], (int)s[0]);
872}
873
874
Jack Jansen5f653091995-01-18 13:53:49 +0000875/*
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000876** Convert a Python object to an FSSpec.
877** The object may either be a full pathname or a triple
878** (vrefnum, dirid, path).
Jack Jansen5f653091995-01-18 13:53:49 +0000879** NOTE: This routine will fail on pre-sys7 machines.
880** The caller is responsible for not calling this routine
881** in those cases (which is fine, since everyone calling
882** this is probably sys7 dependent anyway).
883*/
884int
Guido van Rossum8f691791995-01-18 23:57:26 +0000885PyMac_GetFSSpec(PyObject *v, FSSpec *fs)
Jack Jansen5f653091995-01-18 13:53:49 +0000886{
887 Str255 path;
888 short refnum;
889 long parid;
890 OSErr err;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000891 FSSpec *fs2;
Jack Jansen5f653091995-01-18 13:53:49 +0000892
Jack Jansene8e8ae01995-01-26 16:36:45 +0000893 /* first check whether it already is an FSSpec */
894 fs2 = mfs_GetFSSpecFSSpec(v);
895 if ( fs2 ) {
Jack Jansen3ec804a1995-02-20 15:56:10 +0000896 (void)FSMakeFSSpec(fs2->vRefNum, fs2->parID, fs2->name, fs);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000897 return 1;
898 }
Jack Jansen5f653091995-01-18 13:53:49 +0000899 if ( PyString_Check(v) ) {
900 /* It's a pathname */
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000901 if( !PyArg_Parse(v, "O&", PyMac_GetStr255, &path) )
Jack Jansen5f653091995-01-18 13:53:49 +0000902 return 0;
Jack Jansen378815c1996-03-06 16:21:34 +0000903 refnum = 0; /* XXXX Should get CurWD here?? */
Jack Jansen5f653091995-01-18 13:53:49 +0000904 parid = 0;
905 } else {
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000906 if( !PyArg_Parse(v, "(hlO&); FSSpec should be fullpath or (vrefnum,dirid,path)",
907 &refnum, &parid, PyMac_GetStr255, &path)) {
Jack Jansen5f653091995-01-18 13:53:49 +0000908 return 0;
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000909 }
Jack Jansen5f653091995-01-18 13:53:49 +0000910 }
911 err = FSMakeFSSpec(refnum, parid, path, fs);
912 if ( err && err != fnfErr ) {
Jack Jansen3d757542000-01-24 09:56:06 +0000913 PyMac_Error(err);
Jack Jansen5f653091995-01-18 13:53:49 +0000914 return 0;
915 }
916 return 1;
917}
918
Jack Jansen8bb573e1999-12-12 21:37:14 +0000919/* Convert FSSpec to PyObject */
920PyObject *PyMac_BuildFSSpec(FSSpec *v)
921{
922 return newmfssobject(v);
923}
Guido van Rossum8f691791995-01-18 23:57:26 +0000924
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000925/* Convert a Python object to a Rect.
Guido van Rossum5279ec61995-01-26 22:56:59 +0000926 The object must be a (left, top, right, bottom) tuple.
927 (This differs from the order in the struct but is consistent with
928 the arguments to SetRect(), and also with STDWIN). */
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000929int
930PyMac_GetRect(PyObject *v, Rect *r)
Guido van Rossum8f691791995-01-18 23:57:26 +0000931{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000932 return PyArg_Parse(v, "(hhhh)", &r->left, &r->top, &r->right, &r->bottom);
Guido van Rossum8f691791995-01-18 23:57:26 +0000933}
Guido van Rossumb3404661995-01-22 18:36:13 +0000934
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000935/* Convert a Rect to a Python object */
Guido van Rossumb3404661995-01-22 18:36:13 +0000936PyObject *
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000937PyMac_BuildRect(Rect *r)
Guido van Rossumb3404661995-01-22 18:36:13 +0000938{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000939 return Py_BuildValue("(hhhh)", r->left, r->top, r->right, r->bottom);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000940}
941
942
943/* Convert a Python object to a Point.
Guido van Rossum5279ec61995-01-26 22:56:59 +0000944 The object must be a (h, v) tuple.
945 (This differs from the order in the struct but is consistent with
946 the arguments to SetPoint(), and also with STDWIN). */
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000947int
948PyMac_GetPoint(PyObject *v, Point *p)
949{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000950 return PyArg_Parse(v, "(hh)", &p->h, &p->v);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000951}
952
953/* Convert a Point to a Python object */
954PyObject *
955PyMac_BuildPoint(Point p)
956{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000957 return Py_BuildValue("(hh)", p.h, p.v);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000958}
959
960
961/* Convert a Python object to an EventRecord.
962 The object must be a (what, message, when, (v, h), modifiers) tuple. */
963int
964PyMac_GetEventRecord(PyObject *v, EventRecord *e)
965{
966 return PyArg_Parse(v, "(hll(hh)h)",
967 &e->what,
968 &e->message,
969 &e->when,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000970 &e->where.h,
Guido van Rossum5279ec61995-01-26 22:56:59 +0000971 &e->where.v,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000972 &e->modifiers);
973}
974
975/* Convert a Rect to an EventRecord object */
976PyObject *
977PyMac_BuildEventRecord(EventRecord *e)
978{
979 return Py_BuildValue("(hll(hh)h)",
980 e->what,
981 e->message,
982 e->when,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000983 e->where.h,
Guido van Rossum5279ec61995-01-26 22:56:59 +0000984 e->where.v,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000985 e->modifiers);
Guido van Rossumb3404661995-01-22 18:36:13 +0000986}
Jack Jansenfa4d5d01995-11-15 15:19:29 +0000987
988/* Convert Python object to Fixed */
989int
990PyMac_GetFixed(PyObject *v, Fixed *f)
991{
992 double d;
993
994 if( !PyArg_Parse(v, "d", &d))
995 return 0;
996 *f = (Fixed)(d * 0x10000);
Jack Jansen31dd5c01996-05-31 13:01:39 +0000997 return 1;
Jack Jansenfa4d5d01995-11-15 15:19:29 +0000998}
999
1000/* Convert a Point to a Python object */
1001PyObject *
1002PyMac_BuildFixed(Fixed f)
1003{
1004 double d;
1005
1006 d = f;
1007 d = d / 0x10000;
1008 return Py_BuildValue("d", d);
1009}
1010
Jack Jansend58cd631998-04-21 15:24:39 +00001011/* Convert wide to/from Python int or (hi, lo) tuple. XXXX Should use Python longs */
1012int
1013PyMac_Getwide(PyObject *v, wide *rv)
1014{
1015 if (PyInt_Check(v)) {
1016 rv->hi = 0;
1017 rv->lo = PyInt_AsLong(v);
1018 if( rv->lo & 0x80000000 )
1019 rv->hi = -1;
1020 return 1;
1021 }
1022 return PyArg_Parse(v, "(ll)", &rv->hi, &rv->lo);
1023}
1024
1025
1026PyObject *
Jack Jansenbbf4be21998-04-23 13:20:17 +00001027PyMac_Buildwide(wide *w)
Jack Jansend58cd631998-04-21 15:24:39 +00001028{
Jack Jansenbbf4be21998-04-23 13:20:17 +00001029 if ( (w->hi == 0 && (w->lo & 0x80000000) == 0) ||
1030 (w->hi == -1 && (w->lo & 0x80000000) ) )
1031 return PyInt_FromLong(w->lo);
1032 return Py_BuildValue("(ll)", w->hi, w->lo);
Jack Jansend58cd631998-04-21 15:24:39 +00001033}