blob: 1266b59c469d71ebd3c6f56151f56729a5a4d0e4 [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>
Jack Jansen16df2aa1995-02-27 16:17:28 +000064#ifdef __MWERKS__
65#include <SIOUX.h>
66#endif
Jack Jansen2d1306b2000-04-07 09:10:49 +000067#ifdef USE_GUSI1
Jack Jansen911ad6b1996-03-05 16:56:24 +000068#include <TFileSpec.h> /* For Path2FSSpec */
Jack Jansenf6865f71996-09-04 15:24:59 +000069#include <GUSI.h>
Jack Jansen911ad6b1996-03-05 16:56:24 +000070#endif
Jack Jansen2d1306b2000-04-07 09:10:49 +000071#include <LowMem.h>
Jack Jansenee23d6e1995-01-27 14:43:25 +000072
Jack Jansen3469e991996-09-06 00:30:45 +000073/* The ID of the Sioux apple menu */
74#define SIOUX_APPLEID 32000
75
Jack Jansenee23d6e1995-01-27 14:43:25 +000076#include <signal.h>
Jack Jansen74162f31995-02-15 22:58:33 +000077#include <stdio.h>
Jack Jansene8e8ae01995-01-26 16:36:45 +000078
Jack Jansenee23d6e1995-01-27 14:43:25 +000079/*
Jack Jansend1f06311996-08-01 15:23:54 +000080** When less than this amount of stackspace is left we
81** raise a MemoryError.
82*/
83#ifndef MINIMUM_STACK_SIZE
84#ifdef __powerc
85#define MINIMUM_STACK_SIZE 8192
86#else
87#define MINIMUM_STACK_SIZE 4096
88#endif
89#endif
90
91/*
Jack Jansen16df2aa1995-02-27 16:17:28 +000092** We have to be careful, since we can't handle
Jack Jansenee23d6e1995-01-27 14:43:25 +000093** things like updates (and they'll keep coming back if we don't
Jack Jansen16df2aa1995-02-27 16:17:28 +000094** handle them). Note that we don't know who has windows open, so
95** even handing updates off to SIOUX under MW isn't going to work.
Jack Jansenee23d6e1995-01-27 14:43:25 +000096*/
Jack Jansen0c968871997-08-26 13:20:34 +000097#define MAINLOOP_EVENTMASK (mDownMask|keyDownMask|osMask|activMask)
Jack Jansene8e8ae01995-01-26 16:36:45 +000098
99#include <signal.h>
Jack Jansenf93c72a1994-12-14 14:07:50 +0000100
Guido van Rossumb3404661995-01-22 18:36:13 +0000101/* XXX We should include Errors.h here, but it has a name conflict
Jack Jansen5f653091995-01-18 13:53:49 +0000102** with the python errors.h. */
103#define fnfErr -43
104
Jack Jansene8e8ae01995-01-26 16:36:45 +0000105/* Declared in macfsmodule.c: */
106extern FSSpec *mfs_GetFSSpecFSSpec();
Jack Jansend88296d2000-07-11 19:51:05 +0000107extern PyObject *newmfssobject(FSSpec *);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000108
Jack Jansenee23d6e1995-01-27 14:43:25 +0000109/* Interrupt code variables: */
110static int interrupted; /* Set to true when cmd-. seen */
Jack Jansend88296d2000-07-11 19:51:05 +0000111static RETSIGTYPE intcatcher(int);
Jack Jansenee23d6e1995-01-27 14:43:25 +0000112
Jack Jansend88296d2000-07-11 19:51:05 +0000113static int PyMac_Yield(void);
Jack Jansenf6865f71996-09-04 15:24:59 +0000114
Jack Jansene8e8ae01995-01-26 16:36:45 +0000115/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000116** These are the real scheduling parameters that control what we check
117** in the event loop, and how often we check. The values are initialized
118** from pyMac_SchedParamStruct.
119*/
120
121struct real_sched_param_struct {
122 int check_interrupt; /* if true check for command-dot */
123 int process_events; /* if nonzero enable evt processing, this mask */
124 int besocial; /* if nonzero be a little social with CPU */
125 unsigned long check_interval; /* how often to check, in ticks */
126 unsigned long bg_yield; /* yield so long when in background */
127 /* these are computed from previous and clock and such */
128 int enabled; /* check_interrupt OR process_event OR yield */
129 unsigned long next_check; /* when to check/yield next, in ticks */
130};
131
132static struct real_sched_param_struct schedparams =
133 { 1, MAINLOOP_EVENTMASK, 1, 15, 15, 1, 0};
134
Jack Jansen819f1771995-08-14 12:35:10 +0000135/*
Jack Jansenf6865f71996-09-04 15:24:59 +0000136** Workaround for sioux/gusi combo: set when we are exiting
137*/
138int PyMac_ConsoleIsDead;
139
140/*
Jack Jansencaa7c461997-06-12 10:49:13 +0000141** Sioux menu bar, saved early so we can restore it
142*/
143static Handle sioux_mbar;
144
145/*
Jack Jansen819f1771995-08-14 12:35:10 +0000146** Some stuff for our GetDirectory and PromptGetFile routines
147*/
148struct hook_args {
149 int selectcur_hit; /* Set to true when "select current" selected */
150 char *prompt; /* The prompt */
151};
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000152#ifdef TARGET_API_MAC_CARBON
153/* The StandardFile hooks don't exist in Carbon. This breaks GetDirectory,
154** but the macfsn code will replace it by a NavServices version anyway.
155*/
156#define myhook_upp NULL
157#else
Jack Jansen819f1771995-08-14 12:35:10 +0000158static DlgHookYDUPP myhook_upp;
159static int upp_inited = 0;
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000160#endif
Jack Jansen819f1771995-08-14 12:35:10 +0000161
Jack Jansen36ed5061997-06-20 16:18:15 +0000162/*
163** The python-code event handler
164*/
165static PyObject *python_event_handler;
166
Jack Jansen8f5725a1999-12-07 23:08:10 +0000167/*
168** Set to true if we're appearance-compliant
169*/
170int PyMac_AppearanceCompliant;
171
Jack Jansen2d1306b2000-04-07 09:10:49 +0000172#ifdef USE_GUSI1
Jack Jansen378815c1996-03-06 16:21:34 +0000173/*
174** GUSI (1.6.0 and earlier, at the least) do not set the MacOS idea of
175** the working directory. Hence, we call this routine after each call
176** to chdir() to rectify things.
177*/
178void
179PyMac_FixGUSIcd()
180{
181 WDPBRec pb;
182 FSSpec curdirfss;
183
184 if ( Path2FSSpec(":x", &curdirfss) != noErr )
185 return;
186
187 /* Set MacOS "working directory" */
188 pb.ioNamePtr= "\p";
189 pb.ioVRefNum= curdirfss.vRefNum;
190 pb.ioWDDirID= curdirfss.parID;
Jack Jansen08c3be31997-04-08 15:27:00 +0000191 if (PBHSetVolSync(&pb) != noErr)
Jack Jansen378815c1996-03-06 16:21:34 +0000192 return;
Jack Jansen378815c1996-03-06 16:21:34 +0000193}
Jack Jansen2d1306b2000-04-07 09:10:49 +0000194#endif
Jack Jansen7ac70af1996-08-19 11:01:05 +0000195
Jack Jansen2d1306b2000-04-07 09:10:49 +0000196#ifdef USE_GUSI
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000197/*
198** SpinCursor (needed by GUSI) drags in heaps of stuff, so we
199** provide a dummy here.
200*/
Jack Jansencfadbd41996-08-19 11:36:25 +0000201void SpinCursor(short x) { /* Dummy */ }
Jack Jansenefaada71998-02-20 16:03:15 +0000202void RotateCursor(short x) { /* Dummy */ }
Jack Jansencfadbd41996-08-19 11:36:25 +0000203
Jack Jansenf6865f71996-09-04 15:24:59 +0000204/*
205** Replacement GUSI Spin function
206*/
Jack Jansen2d1306b2000-04-07 09:10:49 +0000207#ifdef USE_GUSI1
Jack Jansenf6865f71996-09-04 15:24:59 +0000208static int
209PyMac_GUSISpin(spin_msg msg, long arg)
210{
Jack Jansene3ae0df1997-06-03 15:28:29 +0000211 static Boolean inForeground = true;
212 int maxsleep = 6; /* 6 ticks is "normal" sleeptime */
Jack Jansenf6865f71996-09-04 15:24:59 +0000213
214 if (PyMac_ConsoleIsDead) return 0;
215#if 0
216 if (inForeground)
217 SpinCursor(msg == SP_AUTO_SPIN ? short(arg) : 1);
218#endif
219
220 if (interrupted) return -1;
221
Jack Jansene3ae0df1997-06-03 15:28:29 +0000222 if ( msg == SP_AUTO_SPIN )
223 maxsleep = 0;
224 if ( msg==SP_SLEEP||msg==SP_SELECT )
225 maxsleep = arg;
Jack Jansenf6865f71996-09-04 15:24:59 +0000226
Jack Jansene3ae0df1997-06-03 15:28:29 +0000227 PyMac_DoYield(maxsleep, 0); /* XXXX or is it safe to call python here? */
Jack Jansenf6865f71996-09-04 15:24:59 +0000228
229 return 0;
230}
231
232void
233PyMac_SetGUSISpin() {
234 GUSISetHook(GUSI_SpinHook, (GUSIHook)PyMac_GUSISpin);
235}
Jack Jansen2d1306b2000-04-07 09:10:49 +0000236#endif
Jack Jansenf6865f71996-09-04 15:24:59 +0000237
Jack Jansena39f1b01997-05-23 15:35:14 +0000238/* Called at exit() time thru atexit(), to stop event processing */
239void
240PyMac_StopGUSISpin() {
241 PyMac_ConsoleIsDead = 1;
242}
243
244/*
245** Replacement routines for the PLstr... functions so we don't need
246** StdCLib. Moreover, that implementation is broken under cfm68k...
247*/
Jack Jansen8bb573e1999-12-12 21:37:14 +0000248pascal void
Jack Jansena39f1b01997-05-23 15:35:14 +0000249PLstrcpy(to, fr)
250 unsigned char *to, *fr;
251{
252 memcpy(to, fr, fr[0]+1);
253}
254
Jack Jansen8bb573e1999-12-12 21:37:14 +0000255pascal int
Jack Jansena39f1b01997-05-23 15:35:14 +0000256PLstrcmp(s1, s2)
257 unsigned char *s1, *s2;
258{
259 int res;
260 int l = s1[0] < s2[0] ? s1[0] : s2[0];
261
262 res = memcmp(s1+1, s2+1, l);
263 if ( res != 0 )
264 return res;
265
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000266 if ( s1[0] < s2[0] )
Jack Jansena39f1b01997-05-23 15:35:14 +0000267 return -1;
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000268 else if ( s1[0] > s2[0] )
Jack Jansena39f1b01997-05-23 15:35:14 +0000269 return 1;
270 else
271 return 0;
272}
273
Jack Jansen8bb573e1999-12-12 21:37:14 +0000274pascal unsigned char *
Jack Jansena39f1b01997-05-23 15:35:14 +0000275PLstrrchr(str, chr)
276 unsigned char *str;
277 unsigned char chr;
278{
279 unsigned char *ptr = 0;
280 unsigned char *p;
281
282 for(p=str+1; p<str+str[0]; p++)
283 if ( *p == chr )
284 ptr = p;
285 return ptr;
286}
287
288#endif /* USE_GUSI */
Jack Jansen378815c1996-03-06 16:21:34 +0000289
Jack Jansen819f1771995-08-14 12:35:10 +0000290
Jack Jansen5f653091995-01-18 13:53:49 +0000291/* Convert C to Pascal string. Returns pointer to static buffer. */
292unsigned char *
293Pstring(char *str)
294{
295 static Str255 buf;
296 int len;
297
298 len = strlen(str);
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000299 if (len > 255)
300 len = 255;
Jack Jansen5f653091995-01-18 13:53:49 +0000301 buf[0] = (unsigned char)len;
302 strncpy((char *)buf+1, str, len);
303 return buf;
304}
305
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000306/* Like strerror() but for Mac OS error numbers */
307char *PyMac_StrError(int err)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000308{
309 static char buf[256];
310 Handle h;
311 char *str;
312
313 h = GetResource('Estr', err);
314 if ( h ) {
315 HLock(h);
316 str = (char *)*h;
317 memcpy(buf, str+1, (unsigned char)str[0]);
Guido van Rossumcc9bc8f1995-02-13 16:17:03 +0000318 buf[(unsigned char)str[0]] = '\0';
Jack Jansenf93c72a1994-12-14 14:07:50 +0000319 HUnlock(h);
320 ReleaseResource(h);
321 } else {
322 sprintf(buf, "Mac OS error code %d", err);
323 }
324 return buf;
325}
326
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000327/* Exception object shared by all Mac specific modules for Mac OS errors */
328PyObject *PyMac_OSErrException;
329
330/* Initialize and return PyMac_OSErrException */
331PyObject *
332PyMac_GetOSErrException()
333{
334 if (PyMac_OSErrException == NULL)
335 PyMac_OSErrException = PyString_FromString("Mac OS Error");
336 return PyMac_OSErrException;
337}
338
Jack Jansenf93c72a1994-12-14 14:07:50 +0000339/* Set a MAC-specific error from errno, and return NULL; return None if no error */
340PyObject *
Guido van Rossumfffb8bb1995-01-12 12:37:24 +0000341PyErr_Mac(PyObject *eobj, int err)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000342{
343 char *msg;
344 PyObject *v;
Jack Jansenf93c72a1994-12-14 14:07:50 +0000345
Guido van Rossum8f691791995-01-18 23:57:26 +0000346 if (err == 0 && !PyErr_Occurred()) {
Jack Jansenf93c72a1994-12-14 14:07:50 +0000347 Py_INCREF(Py_None);
348 return Py_None;
349 }
Guido van Rossum8f691791995-01-18 23:57:26 +0000350 if (err == -1 && PyErr_Occurred())
351 return NULL;
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000352 msg = PyMac_StrError(err);
Jack Jansenf93c72a1994-12-14 14:07:50 +0000353 v = Py_BuildValue("(is)", err, msg);
354 PyErr_SetObject(eobj, v);
355 Py_DECREF(v);
356 return NULL;
357}
358
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000359/* Call PyErr_Mac with PyMac_OSErrException */
360PyObject *
361PyMac_Error(OSErr err)
362{
363 return PyErr_Mac(PyMac_GetOSErrException(), err);
364}
365
Jack Jansen1ed95291996-07-22 15:25:10 +0000366#ifdef USE_STACKCHECK
367/* Check for stack overflow */
368int
369PyOS_CheckStack()
370{
371 long left;
372
373 left = StackSpace();
Jack Jansend1f06311996-08-01 15:23:54 +0000374 if ( left < MINIMUM_STACK_SIZE )
Jack Jansen1ed95291996-07-22 15:25:10 +0000375 return -1;
376 return 0;
377}
378#endif /* USE_STACKCHECK */
379
Jack Jansenee23d6e1995-01-27 14:43:25 +0000380/* The catcher routine (which may not be used for all compilers) */
381static RETSIGTYPE
382intcatcher(sig)
383 int sig;
384{
385 interrupted = 1;
386 signal(SIGINT, intcatcher);
387}
388
389void
390PyOS_InitInterrupts()
391{
392 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
393 signal(SIGINT, intcatcher);
394}
395
Jack Jansena8441de1997-08-08 14:57:37 +0000396void
397PyOS_FiniInterrupts()
398{
399}
400
Jack Jansenee23d6e1995-01-27 14:43:25 +0000401/*
402** This routine scans the event queue looking for cmd-.
403** This is the only way to get an interrupt under THINK (since it
404** doesn't do SIGINT handling), but is also used under MW, when
405** the full-fledged event loop is disabled. This way, we can at least
406** interrupt a runaway python program.
407*/
408static void
409scan_event_queue(flush)
410 int flush;
411{
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000412#ifdef TARGET_API_MAC_CARBON
413 /* CARBONXXXX To be implemented */
414 return;
415#else
Jack Jansenee23d6e1995-01-27 14:43:25 +0000416 register EvQElPtr q;
417
Jack Jansenefaada71998-02-20 16:03:15 +0000418 q = (EvQElPtr) LMGetEventQueue()->qHead;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000419
420 for (; q; q = (EvQElPtr)q->qLink) {
421 if (q->evtQWhat == keyDown &&
422 (char)q->evtQMessage == '.' &&
423 (q->evtQModifiers & cmdKey) != 0) {
424 if ( flush )
425 FlushEvents(keyDownMask, 0);
426 interrupted = 1;
427 break;
428 }
429 }
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000430#endif
Jack Jansenee23d6e1995-01-27 14:43:25 +0000431}
432
433int
Jack Jansen36ed5061997-06-20 16:18:15 +0000434PyErr_CheckSignals()
Jack Jansenee23d6e1995-01-27 14:43:25 +0000435{
Jack Jansene3ae0df1997-06-03 15:28:29 +0000436 if (schedparams.enabled) {
437 if ( (unsigned long)LMGetTicks() > schedparams.next_check ) {
Jack Jansen36ed5061997-06-20 16:18:15 +0000438 if ( PyMac_Yield() < 0)
439 return -1;
Jack Jansene3ae0df1997-06-03 15:28:29 +0000440 schedparams.next_check = (unsigned long)LMGetTicks()
441 + schedparams.check_interval;
442 if (interrupted) {
Jack Jansencaa7c461997-06-12 10:49:13 +0000443 scan_event_queue(1); /* Eat events up to cmd-. */
Jack Jansene3ae0df1997-06-03 15:28:29 +0000444 interrupted = 0;
Jack Jansen36ed5061997-06-20 16:18:15 +0000445 PyErr_SetNone(PyExc_KeyboardInterrupt);
446 return -1;
Jack Jansene3ae0df1997-06-03 15:28:29 +0000447 }
448 }
Jack Jansenee23d6e1995-01-27 14:43:25 +0000449 }
450 return 0;
451}
452
Jack Jansen36ed5061997-06-20 16:18:15 +0000453int
454PyOS_InterruptOccurred()
455{
456 scan_event_queue(1);
457 return interrupted;
458}
Jack Jansenee23d6e1995-01-27 14:43:25 +0000459/* Check whether we are in the foreground */
460int
461PyMac_InForeground()
462{
463 static ProcessSerialNumber ours;
464 static inited;
465 ProcessSerialNumber curfg;
466 Boolean eq;
467
Jack Jansene3ae0df1997-06-03 15:28:29 +0000468 if ( inited == 0 ) {
Jack Jansenee23d6e1995-01-27 14:43:25 +0000469 (void)GetCurrentProcess(&ours);
Jack Jansene3ae0df1997-06-03 15:28:29 +0000470 inited = 1;
471 }
Jack Jansenee23d6e1995-01-27 14:43:25 +0000472 if ( GetFrontProcess(&curfg) < 0 )
473 eq = 1;
474 else if ( SameProcess(&ours, &curfg, &eq) < 0 )
475 eq = 1;
476 return (int)eq;
477
478}
479
Jack Jansen36ed5061997-06-20 16:18:15 +0000480int
481PyMac_SetEventHandler(PyObject *evh)
482{
483 if ( evh && python_event_handler ) {
484 PyErr_SetString(PyExc_RuntimeError, "Python event handler already set");
485 return 0;
486 }
487 if ( python_event_handler )
488 Py_DECREF(python_event_handler);
489 if ( evh )
490 Py_INCREF(evh);
491 python_event_handler = evh;
492 return 1;
493}
494
Jack Jansenf93c72a1994-12-14 14:07:50 +0000495/*
Jack Jansena76382a1995-02-02 14:25:56 +0000496** Handle an event, either one found in the mainloop eventhandler or
497** one passed back from the python program.
498*/
499void
Jack Jansen36ed5061997-06-20 16:18:15 +0000500PyMac_HandleEventIntern(evp)
Jack Jansena76382a1995-02-02 14:25:56 +0000501 EventRecord *evp;
502{
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000503#ifndef TARGET_API_MAC_CARBON
Jack Jansen0c968871997-08-26 13:20:34 +0000504 if ( evp->what == mouseDown ) {
505 WindowPtr wp;
506
507 if ( FindWindow(evp->where, &wp) == inSysWindow ) {
508 SystemClick(evp, wp);
509 return;
510 }
511 }
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000512#endif
Jack Jansena76382a1995-02-02 14:25:56 +0000513#ifdef __MWERKS__
Jack Jansen38e97661995-11-10 14:53:00 +0000514 {
515 int siouxdidit;
516
517 /* If SIOUX wants it we're done */
518 siouxdidit = SIOUXHandleOneEvent(evp);
519 if ( siouxdidit )
520 return;
521 }
Jack Jansena76382a1995-02-02 14:25:56 +0000522#else
Jack Jansen0c968871997-08-26 13:20:34 +0000523 /* Other compilers are just unlucky... */
Jack Jansena76382a1995-02-02 14:25:56 +0000524#endif /* !__MWERKS__ */
Jack Jansen36ed5061997-06-20 16:18:15 +0000525}
526
527/*
528** Handle an event, either through HandleEvent or by passing it to the Python
529** event handler.
530*/
531int
532PyMac_HandleEvent(evp)
533 EventRecord *evp;
534{
535 PyObject *rv;
536
537 if ( python_event_handler ) {
538 rv = PyObject_CallFunction(python_event_handler, "(O&)",
539 PyMac_BuildEventRecord, evp);
540 if ( rv )
541 Py_DECREF(rv);
542 else
543 return -1; /* Propagate exception */
544 } else {
545 PyMac_HandleEventIntern(evp);
546 }
547 return 0;
Jack Jansena76382a1995-02-02 14:25:56 +0000548}
549
550/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000551** Yield the CPU to other tasks without processing events.
Jack Jansene8e8ae01995-01-26 16:36:45 +0000552*/
Jack Jansen2d1306b2000-04-07 09:10:49 +0000553int
Jack Jansene3ae0df1997-06-03 15:28:29 +0000554PyMac_DoYield(int maxsleep, int maycallpython)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000555{
556 EventRecord ev;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000557 int gotone;
Jack Jansene3ae0df1997-06-03 15:28:29 +0000558 long latest_time_ready;
Jack Jansen36ed5061997-06-20 16:18:15 +0000559 static int in_here = 0;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000560
Jack Jansen36ed5061997-06-20 16:18:15 +0000561 in_here++;
Jack Jansene3ae0df1997-06-03 15:28:29 +0000562 /*
563 ** First check for interrupts, if wanted.
564 ** This sets a flag that will be picked up at an appropriate
565 ** moment in the mainloop.
566 */
567 if (schedparams.check_interrupt)
Jack Jansenee23d6e1995-01-27 14:43:25 +0000568 scan_event_queue(0);
Jack Jansene3ae0df1997-06-03 15:28:29 +0000569
570 /* XXXX Implementing an idle routine goes here */
Jack Jansene8e8ae01995-01-26 16:36:45 +0000571
Jack Jansene3ae0df1997-06-03 15:28:29 +0000572 /*
573 ** Check which of the eventloop cases we have:
574 ** - process events
575 ** - don't process events but do yield
576 ** - do neither
577 */
Jack Jansen36ed5061997-06-20 16:18:15 +0000578 if( in_here > 1 || !schedparams.process_events ||
579 (python_event_handler && !maycallpython) ) {
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000580#ifndef TARGET_API_MAC_CARBON
Jack Jansene3ae0df1997-06-03 15:28:29 +0000581 if ( maxsleep >= 0 ) {
Jack Jansene8e8ae01995-01-26 16:36:45 +0000582 SystemTask();
Jack Jansene3ae0df1997-06-03 15:28:29 +0000583 }
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000584#endif
Jack Jansene3ae0df1997-06-03 15:28:29 +0000585 } else {
586 latest_time_ready = LMGetTicks() + maxsleep;
Jack Jansen2d1306b2000-04-07 09:10:49 +0000587 do {
Jack Jansen0c968871997-08-26 13:20:34 +0000588 /* XXXX Hack by Jack.
589 ** In time.sleep() you can click to another application
590 ** once only. If you come back to Python you cannot get away
591 ** again.
592 **/
Jack Jansen36ed5061997-06-20 16:18:15 +0000593 gotone = WaitNextEvent(schedparams.process_events, &ev, maxsleep, NULL);
Jack Jansene3ae0df1997-06-03 15:28:29 +0000594 /* Get out quickly if nothing interesting is happening */
595 if ( !gotone || ev.what == nullEvent )
596 break;
Jack Jansen36ed5061997-06-20 16:18:15 +0000597 if ( PyMac_HandleEvent(&ev) < 0 ) {
598 in_here--;
599 return -1;
600 }
Jack Jansene3ae0df1997-06-03 15:28:29 +0000601 maxsleep = latest_time_ready - LMGetTicks();
Jack Jansen2d1306b2000-04-07 09:10:49 +0000602 } while ( maxsleep > 0 );
Jack Jansenf93c72a1994-12-14 14:07:50 +0000603 }
Jack Jansen36ed5061997-06-20 16:18:15 +0000604 in_here--;
605 return 0;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000606}
607
608/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000609** Process events and/or yield the CPU to other tasks if opportune
Jack Jansene8e8ae01995-01-26 16:36:45 +0000610*/
Jack Jansen36ed5061997-06-20 16:18:15 +0000611int
Jack Jansene8e8ae01995-01-26 16:36:45 +0000612PyMac_Yield() {
Jack Jansene3ae0df1997-06-03 15:28:29 +0000613 unsigned long maxsleep;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000614
Jack Jansene3ae0df1997-06-03 15:28:29 +0000615 if( PyMac_InForeground() )
616 maxsleep = 0;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000617 else
Jack Jansene3ae0df1997-06-03 15:28:29 +0000618 maxsleep = schedparams.bg_yield;
619
Jack Jansen36ed5061997-06-20 16:18:15 +0000620 return PyMac_DoYield(maxsleep, 1);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000621}
622
623/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000624** Return current scheduler parameters
Jack Jansene8e8ae01995-01-26 16:36:45 +0000625*/
Jack Jansene3ae0df1997-06-03 15:28:29 +0000626void
627PyMac_GetSchedParams(PyMacSchedParams *sp)
Jack Jansene8e8ae01995-01-26 16:36:45 +0000628{
Jack Jansene3ae0df1997-06-03 15:28:29 +0000629 sp->check_interrupt = schedparams.check_interrupt;
630 sp->process_events = schedparams.process_events;
631 sp->besocial = schedparams.besocial;
632 sp->check_interval = schedparams.check_interval / 60.0;
633 sp->bg_yield = schedparams.bg_yield / 60.0;
Jack Jansenf93c72a1994-12-14 14:07:50 +0000634}
Jack Jansenf6865f71996-09-04 15:24:59 +0000635
Jack Jansen74162f31995-02-15 22:58:33 +0000636/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000637** Set current scheduler parameters
638*/
639void
640PyMac_SetSchedParams(PyMacSchedParams *sp)
641{
642 schedparams.check_interrupt = sp->check_interrupt;
643 schedparams.process_events = sp->process_events;
644 schedparams.besocial = sp->besocial;
645 schedparams.check_interval = (unsigned long)(sp->check_interval*60);
646 schedparams.bg_yield = (unsigned long)(sp->bg_yield*60);
647 if ( schedparams.check_interrupt || schedparams.process_events ||
648 schedparams.besocial )
649 schedparams.enabled = 1;
650 else
651 schedparams.enabled = 0;
652 schedparams.next_check = 0; /* Check immedeately */
653}
Jack Jansencaa7c461997-06-12 10:49:13 +0000654
Jack Jansene3ae0df1997-06-03 15:28:29 +0000655/*
Jack Jansen3469e991996-09-06 00:30:45 +0000656** Install our menu bar.
657*/
658void
659PyMac_InitMenuBar()
660{
Jack Jansen3469e991996-09-06 00:30:45 +0000661 MenuHandle applemenu;
662
Jack Jansencaa7c461997-06-12 10:49:13 +0000663 if ( (sioux_mbar=GetMenuBar()) == NULL ) {
664 /* Sioux menu not installed yet. Do so */
665 SIOUXSetupMenus();
666 if ( (sioux_mbar=GetMenuBar()) == NULL )
667 return;
668 }
Jack Jansen08c3be31997-04-08 15:27:00 +0000669 if ( (applemenu=GetMenuHandle(SIOUX_APPLEID)) == NULL ) return;
Jack Jansen3469e991996-09-06 00:30:45 +0000670 SetMenuItemText(applemenu, 1, "\pAbout Python...");
671}
672
673/*
Jack Jansencaa7c461997-06-12 10:49:13 +0000674** Restore sioux menu bar
675*/
676void
677PyMac_RestoreMenuBar()
678{
Jack Janseneda78631997-06-12 15:29:46 +0000679 if ( sioux_mbar ) {
Jack Jansencaa7c461997-06-12 10:49:13 +0000680 SetMenuBar(sioux_mbar);
Jack Janseneda78631997-06-12 15:29:46 +0000681 DrawMenuBar();
Jack Jansenefaada71998-02-20 16:03:15 +0000682 } else
683 PyMac_InitMenuBar();
Jack Jansencaa7c461997-06-12 10:49:13 +0000684}
685
686
687/*
Jack Jansen3469e991996-09-06 00:30:45 +0000688** Our replacement about box
689*/
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000690
691#include "patchlevel.h"
692
Jack Jansen3469e991996-09-06 00:30:45 +0000693void
694SIOUXDoAboutBox(void)
695{
696 DialogPtr theDialog;
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000697 WindowPtr theWindow;
Jack Jansen3469e991996-09-06 00:30:45 +0000698 short item;
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000699 short fontID;
Jack Jansen3469e991996-09-06 00:30:45 +0000700
701 if( (theDialog = GetNewDialog(ABOUT_ID, NULL, (WindowPtr)-1)) == NULL )
702 return;
Jack Jansend617c571996-09-22 22:14:30 +0000703 theWindow = GetDialogWindow(theDialog);
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000704 SetPortWindowPort(theWindow);
705 GetFNum("\pPython-Sans", &fontID);
706 if (fontID == 0)
707 fontID = kFontIDGeneva;
708 TextFont(fontID);
709 TextSize(9);
710 ParamText(Pstring(PATCHLEVEL), "\p", "\p", "\p");
Jack Jansend617c571996-09-22 22:14:30 +0000711 ShowWindow(theWindow);
Jack Jansen3469e991996-09-06 00:30:45 +0000712 ModalDialog(NULL, &item);
713 DisposeDialog(theDialog);
714}
715
Jack Janseneda78631997-06-12 15:29:46 +0000716#if 0
717int
718PyMac_FileExists(char *name)
719{
720 FSSpec fss;
721
722 if ( FSMakeFSSpec(0, 0, Pstring(name), &fss) == noErr )
723 return 1;
724 return 0;
725}
726#endif
727
728/*
Jack Jansen3ec804a1995-02-20 15:56:10 +0000729** Helper routine for GetDirectory
730*/
Guido van Rossum24a45e31995-02-20 23:45:53 +0000731static pascal short
Jack Jansen819f1771995-08-14 12:35:10 +0000732myhook_proc(short item, DialogPtr theDialog, struct hook_args *dataptr)
Jack Jansen3ec804a1995-02-20 15:56:10 +0000733{
Jack Jansen819f1771995-08-14 12:35:10 +0000734 if ( item == sfHookFirstCall && dataptr->prompt) {
735 Handle prompth;
736 short type;
737 Rect rect;
738
739 GetDialogItem(theDialog, PROMPT_ITEM, &type, &prompth, &rect);
740 if ( prompth )
741 SetDialogItemText(prompth, (unsigned char *)dataptr->prompt);
742 } else
Jack Jansen3ec804a1995-02-20 15:56:10 +0000743 if ( item == SELECTCUR_ITEM ) {
744 item = sfItemCancelButton;
Jack Jansen819f1771995-08-14 12:35:10 +0000745 dataptr->selectcur_hit = 1;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000746 }
747 return item;
748}
749
750/*
751** Ask the user for a directory. I still can't understand
752** why Apple doesn't provide a standard solution for this...
753*/
754int
Jack Jansen819f1771995-08-14 12:35:10 +0000755PyMac_GetDirectory(dirfss, prompt)
Jack Jansen3ec804a1995-02-20 15:56:10 +0000756 FSSpec *dirfss;
Jack Jansen819f1771995-08-14 12:35:10 +0000757 char *prompt;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000758{
759 static SFTypeList list = {'fldr', 0, 0, 0};
760 static Point where = {-1, -1};
Jack Jansen3ec804a1995-02-20 15:56:10 +0000761 StandardFileReply reply;
Jack Jansen819f1771995-08-14 12:35:10 +0000762 struct hook_args hook_args;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000763
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000764#ifndef TARGET_API_MAC_CARBON
Jack Jansen3ec804a1995-02-20 15:56:10 +0000765 if ( !upp_inited ) {
766 myhook_upp = NewDlgHookYDProc(myhook_proc);
767 upp_inited = 1;
768 }
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000769#endif
Jack Jansen819f1771995-08-14 12:35:10 +0000770 if ( prompt && *prompt )
771 hook_args.prompt = (char *)Pstring(prompt);
772 else
773 hook_args.prompt = NULL;
774 hook_args.selectcur_hit = 0;
Guido van Rossum24a45e31995-02-20 23:45:53 +0000775 CustomGetFile((FileFilterYDUPP)0, 1, list, &reply, GETDIR_ID, where, myhook_upp,
Jack Jansen819f1771995-08-14 12:35:10 +0000776 NULL, NULL, NULL, (void *)&hook_args);
Jack Jansen3ec804a1995-02-20 15:56:10 +0000777
778 reply.sfFile.name[0] = 0;
779 if( FSMakeFSSpec(reply.sfFile.vRefNum, reply.sfFile.parID, reply.sfFile.name, dirfss) )
780 return 0;
Jack Jansen819f1771995-08-14 12:35:10 +0000781 return hook_args.selectcur_hit;
782}
783
784/*
785** Slightly extended StandardGetFile: accepts a prompt */
786void PyMac_PromptGetFile(short numTypes, ConstSFTypeListPtr typeList,
787 StandardFileReply *reply, char *prompt)
788{
789 static Point where = {-1, -1};
790 struct hook_args hook_args;
791
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000792#ifndef TARGET_API_MAC_CARBON
Jack Jansen819f1771995-08-14 12:35:10 +0000793 if ( !upp_inited ) {
794 myhook_upp = NewDlgHookYDProc(myhook_proc);
795 upp_inited = 1;
796 }
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000797#endif
Jack Jansen819f1771995-08-14 12:35:10 +0000798 if ( prompt && *prompt )
799 hook_args.prompt = (char *)Pstring(prompt);
800 else
801 hook_args.prompt = NULL;
802 hook_args.selectcur_hit = 0;
803 CustomGetFile((FileFilterYDUPP)0, numTypes, typeList, reply, GETFILEPROMPT_ID, where,
804 myhook_upp, NULL, NULL, NULL, (void *)&hook_args);
Jack Jansen3ec804a1995-02-20 15:56:10 +0000805}
Jack Jansen5f653091995-01-18 13:53:49 +0000806
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000807/* Convert a 4-char string object argument to an OSType value */
Jack Jansen5f653091995-01-18 13:53:49 +0000808int
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000809PyMac_GetOSType(PyObject *v, OSType *pr)
Jack Jansen5f653091995-01-18 13:53:49 +0000810{
811 if (!PyString_Check(v) || PyString_Size(v) != 4) {
812 PyErr_SetString(PyExc_TypeError,
813 "OSType arg must be string of 4 chars");
814 return 0;
815 }
816 memcpy((char *)pr, PyString_AsString(v), 4);
817 return 1;
818}
819
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000820/* Convert an OSType value to a 4-char string object */
821PyObject *
822PyMac_BuildOSType(OSType t)
823{
824 return PyString_FromStringAndSize((char *)&t, 4);
825}
826
Jack Jansend1f06311996-08-01 15:23:54 +0000827/* Convert an NumVersion value to a 4-element tuple */
828PyObject *
829PyMac_BuildNumVersion(NumVersion t)
830{
831 return Py_BuildValue("(hhhh)", t.majorRev, t.minorAndBugRev, t.stage, t.nonRelRev);
832}
833
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000834
835/* Convert a Python string object to a Str255 */
Jack Jansen5f653091995-01-18 13:53:49 +0000836int
Guido van Rossum8f691791995-01-18 23:57:26 +0000837PyMac_GetStr255(PyObject *v, Str255 pbuf)
Jack Jansen5f653091995-01-18 13:53:49 +0000838{
839 int len;
840 if (!PyString_Check(v) || (len = PyString_Size(v)) > 255) {
841 PyErr_SetString(PyExc_TypeError,
842 "Str255 arg must be string of at most 255 chars");
843 return 0;
844 }
845 pbuf[0] = len;
846 memcpy((char *)(pbuf+1), PyString_AsString(v), len);
847 return 1;
848}
849
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000850/* Convert a Str255 to a Python string object */
851PyObject *
852PyMac_BuildStr255(Str255 s)
853{
Jack Jansenb734ade1999-12-17 17:15:50 +0000854 if ( s == NULL ) {
855 PyErr_SetString(PyExc_SystemError, "Str255 pointer is NULL");
856 return NULL;
857 }
858 return PyString_FromStringAndSize((char *)&s[1], (int)s[0]);
859}
860
861PyObject *
862PyMac_BuildOptStr255(Str255 s)
863{
864 if ( s == NULL ) {
865 Py_INCREF(Py_None);
866 return Py_None;
867 }
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000868 return PyString_FromStringAndSize((char *)&s[1], (int)s[0]);
869}
870
871
Jack Jansen5f653091995-01-18 13:53:49 +0000872/*
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000873** Convert a Python object to an FSSpec.
874** The object may either be a full pathname or a triple
875** (vrefnum, dirid, path).
Jack Jansen5f653091995-01-18 13:53:49 +0000876** NOTE: This routine will fail on pre-sys7 machines.
877** The caller is responsible for not calling this routine
878** in those cases (which is fine, since everyone calling
879** this is probably sys7 dependent anyway).
880*/
881int
Guido van Rossum8f691791995-01-18 23:57:26 +0000882PyMac_GetFSSpec(PyObject *v, FSSpec *fs)
Jack Jansen5f653091995-01-18 13:53:49 +0000883{
884 Str255 path;
885 short refnum;
886 long parid;
887 OSErr err;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000888 FSSpec *fs2;
Jack Jansen5f653091995-01-18 13:53:49 +0000889
Jack Jansene8e8ae01995-01-26 16:36:45 +0000890 /* first check whether it already is an FSSpec */
891 fs2 = mfs_GetFSSpecFSSpec(v);
892 if ( fs2 ) {
Jack Jansen3ec804a1995-02-20 15:56:10 +0000893 (void)FSMakeFSSpec(fs2->vRefNum, fs2->parID, fs2->name, fs);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000894 return 1;
895 }
Jack Jansen5f653091995-01-18 13:53:49 +0000896 if ( PyString_Check(v) ) {
897 /* It's a pathname */
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000898 if( !PyArg_Parse(v, "O&", PyMac_GetStr255, &path) )
Jack Jansen5f653091995-01-18 13:53:49 +0000899 return 0;
Jack Jansen378815c1996-03-06 16:21:34 +0000900 refnum = 0; /* XXXX Should get CurWD here?? */
Jack Jansen5f653091995-01-18 13:53:49 +0000901 parid = 0;
902 } else {
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000903 if( !PyArg_Parse(v, "(hlO&); FSSpec should be fullpath or (vrefnum,dirid,path)",
904 &refnum, &parid, PyMac_GetStr255, &path)) {
Jack Jansen5f653091995-01-18 13:53:49 +0000905 return 0;
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000906 }
Jack Jansen5f653091995-01-18 13:53:49 +0000907 }
908 err = FSMakeFSSpec(refnum, parid, path, fs);
909 if ( err && err != fnfErr ) {
Jack Jansen3d757542000-01-24 09:56:06 +0000910 PyMac_Error(err);
Jack Jansen5f653091995-01-18 13:53:49 +0000911 return 0;
912 }
913 return 1;
914}
915
Jack Jansen8bb573e1999-12-12 21:37:14 +0000916/* Convert FSSpec to PyObject */
917PyObject *PyMac_BuildFSSpec(FSSpec *v)
918{
919 return newmfssobject(v);
920}
Guido van Rossum8f691791995-01-18 23:57:26 +0000921
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000922/* Convert a Python object to a Rect.
Guido van Rossum5279ec61995-01-26 22:56:59 +0000923 The object must be a (left, top, right, bottom) tuple.
924 (This differs from the order in the struct but is consistent with
925 the arguments to SetRect(), and also with STDWIN). */
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000926int
927PyMac_GetRect(PyObject *v, Rect *r)
Guido van Rossum8f691791995-01-18 23:57:26 +0000928{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000929 return PyArg_Parse(v, "(hhhh)", &r->left, &r->top, &r->right, &r->bottom);
Guido van Rossum8f691791995-01-18 23:57:26 +0000930}
Guido van Rossumb3404661995-01-22 18:36:13 +0000931
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000932/* Convert a Rect to a Python object */
Guido van Rossumb3404661995-01-22 18:36:13 +0000933PyObject *
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000934PyMac_BuildRect(Rect *r)
Guido van Rossumb3404661995-01-22 18:36:13 +0000935{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000936 return Py_BuildValue("(hhhh)", r->left, r->top, r->right, r->bottom);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000937}
938
939
940/* Convert a Python object to a Point.
Guido van Rossum5279ec61995-01-26 22:56:59 +0000941 The object must be a (h, v) tuple.
942 (This differs from the order in the struct but is consistent with
943 the arguments to SetPoint(), and also with STDWIN). */
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000944int
945PyMac_GetPoint(PyObject *v, Point *p)
946{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000947 return PyArg_Parse(v, "(hh)", &p->h, &p->v);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000948}
949
950/* Convert a Point to a Python object */
951PyObject *
952PyMac_BuildPoint(Point p)
953{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000954 return Py_BuildValue("(hh)", p.h, p.v);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000955}
956
957
958/* Convert a Python object to an EventRecord.
959 The object must be a (what, message, when, (v, h), modifiers) tuple. */
960int
961PyMac_GetEventRecord(PyObject *v, EventRecord *e)
962{
963 return PyArg_Parse(v, "(hll(hh)h)",
964 &e->what,
965 &e->message,
966 &e->when,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000967 &e->where.h,
Guido van Rossum5279ec61995-01-26 22:56:59 +0000968 &e->where.v,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000969 &e->modifiers);
970}
971
972/* Convert a Rect to an EventRecord object */
973PyObject *
974PyMac_BuildEventRecord(EventRecord *e)
975{
976 return Py_BuildValue("(hll(hh)h)",
977 e->what,
978 e->message,
979 e->when,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000980 e->where.h,
Guido van Rossum5279ec61995-01-26 22:56:59 +0000981 e->where.v,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000982 e->modifiers);
Guido van Rossumb3404661995-01-22 18:36:13 +0000983}
Jack Jansenfa4d5d01995-11-15 15:19:29 +0000984
985/* Convert Python object to Fixed */
986int
987PyMac_GetFixed(PyObject *v, Fixed *f)
988{
989 double d;
990
991 if( !PyArg_Parse(v, "d", &d))
992 return 0;
993 *f = (Fixed)(d * 0x10000);
Jack Jansen31dd5c01996-05-31 13:01:39 +0000994 return 1;
Jack Jansenfa4d5d01995-11-15 15:19:29 +0000995}
996
997/* Convert a Point to a Python object */
998PyObject *
999PyMac_BuildFixed(Fixed f)
1000{
1001 double d;
1002
1003 d = f;
1004 d = d / 0x10000;
1005 return Py_BuildValue("d", d);
1006}
1007
Jack Jansend58cd631998-04-21 15:24:39 +00001008/* Convert wide to/from Python int or (hi, lo) tuple. XXXX Should use Python longs */
1009int
1010PyMac_Getwide(PyObject *v, wide *rv)
1011{
1012 if (PyInt_Check(v)) {
1013 rv->hi = 0;
1014 rv->lo = PyInt_AsLong(v);
1015 if( rv->lo & 0x80000000 )
1016 rv->hi = -1;
1017 return 1;
1018 }
1019 return PyArg_Parse(v, "(ll)", &rv->hi, &rv->lo);
1020}
1021
1022
1023PyObject *
Jack Jansenbbf4be21998-04-23 13:20:17 +00001024PyMac_Buildwide(wide *w)
Jack Jansend58cd631998-04-21 15:24:39 +00001025{
Jack Jansenbbf4be21998-04-23 13:20:17 +00001026 if ( (w->hi == 0 && (w->lo & 0x80000000) == 0) ||
1027 (w->hi == -1 && (w->lo & 0x80000000) ) )
1028 return PyInt_FromLong(w->lo);
1029 return Py_BuildValue("(ll)", w->hi, w->lo);
Jack Jansend58cd631998-04-21 15:24:39 +00001030}