blob: 0763eaa3c2bf66dfd27b0ec2b8042585eb0e1e5a [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 Jansen74a1e632000-07-14 22:37:27 +000035#if TARGET_API_MAC_CARBON
Jack Jansenbb6d83a2000-06-02 21:27:11 +000036/* 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>
Jack Jansen9ae898b2000-07-11 21:16:03 +000066extern void SIOUXSetupMenus(void);
67extern void SIOUXDoAboutBox(void);
Jack Jansen16df2aa1995-02-27 16:17:28 +000068#endif
Jack Jansen9ae898b2000-07-11 21:16:03 +000069#ifdef USE_GUSI
70/* Functions we redefine because they're in obscure libraries */
71extern void SpinCursor(short x);
72extern void RotateCursor(short x);
73extern pascal void PLstrcpy(unsigned char *, unsigned char *);
74extern pascal int PLstrcmp(unsigned char *, unsigned char *);
75extern pascal unsigned char *PLstrrchr(unsigned char *, unsigned char);
76
77#endif
78
Jack Jansen2d1306b2000-04-07 09:10:49 +000079#ifdef USE_GUSI1
Jack Jansen911ad6b1996-03-05 16:56:24 +000080#include <TFileSpec.h> /* For Path2FSSpec */
Jack Jansenf6865f71996-09-04 15:24:59 +000081#include <GUSI.h>
Jack Jansen911ad6b1996-03-05 16:56:24 +000082#endif
Jack Jansen2d1306b2000-04-07 09:10:49 +000083#include <LowMem.h>
Jack Jansenee23d6e1995-01-27 14:43:25 +000084
Jack Jansen3469e991996-09-06 00:30:45 +000085/* The ID of the Sioux apple menu */
86#define SIOUX_APPLEID 32000
87
Jack Jansenee23d6e1995-01-27 14:43:25 +000088#include <signal.h>
Jack Jansen74162f31995-02-15 22:58:33 +000089#include <stdio.h>
Jack Jansene8e8ae01995-01-26 16:36:45 +000090
Jack Jansenee23d6e1995-01-27 14:43:25 +000091/*
Jack Jansend1f06311996-08-01 15:23:54 +000092** When less than this amount of stackspace is left we
93** raise a MemoryError.
94*/
95#ifndef MINIMUM_STACK_SIZE
96#ifdef __powerc
97#define MINIMUM_STACK_SIZE 8192
98#else
99#define MINIMUM_STACK_SIZE 4096
100#endif
101#endif
102
103/*
Jack Jansen16df2aa1995-02-27 16:17:28 +0000104** We have to be careful, since we can't handle
Jack Jansenee23d6e1995-01-27 14:43:25 +0000105** things like updates (and they'll keep coming back if we don't
Jack Jansen16df2aa1995-02-27 16:17:28 +0000106** handle them). Note that we don't know who has windows open, so
107** even handing updates off to SIOUX under MW isn't going to work.
Jack Jansenee23d6e1995-01-27 14:43:25 +0000108*/
Jack Jansen0c968871997-08-26 13:20:34 +0000109#define MAINLOOP_EVENTMASK (mDownMask|keyDownMask|osMask|activMask)
Jack Jansene8e8ae01995-01-26 16:36:45 +0000110
111#include <signal.h>
Jack Jansenf93c72a1994-12-14 14:07:50 +0000112
Guido van Rossumb3404661995-01-22 18:36:13 +0000113/* XXX We should include Errors.h here, but it has a name conflict
Jack Jansen5f653091995-01-18 13:53:49 +0000114** with the python errors.h. */
115#define fnfErr -43
116
Jack Jansene8e8ae01995-01-26 16:36:45 +0000117/* Declared in macfsmodule.c: */
Jack Jansen9ae898b2000-07-11 21:16:03 +0000118extern FSSpec *mfs_GetFSSpecFSSpec(PyObject *);
Jack Jansend88296d2000-07-11 19:51:05 +0000119extern PyObject *newmfssobject(FSSpec *);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000120
Jack Jansenee23d6e1995-01-27 14:43:25 +0000121/* Interrupt code variables: */
122static int interrupted; /* Set to true when cmd-. seen */
Jack Jansend88296d2000-07-11 19:51:05 +0000123static RETSIGTYPE intcatcher(int);
Jack Jansenee23d6e1995-01-27 14:43:25 +0000124
Jack Jansend88296d2000-07-11 19:51:05 +0000125static int PyMac_Yield(void);
Jack Jansenf6865f71996-09-04 15:24:59 +0000126
Jack Jansene8e8ae01995-01-26 16:36:45 +0000127/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000128** These are the real scheduling parameters that control what we check
129** in the event loop, and how often we check. The values are initialized
130** from pyMac_SchedParamStruct.
131*/
132
133struct real_sched_param_struct {
134 int check_interrupt; /* if true check for command-dot */
135 int process_events; /* if nonzero enable evt processing, this mask */
136 int besocial; /* if nonzero be a little social with CPU */
137 unsigned long check_interval; /* how often to check, in ticks */
138 unsigned long bg_yield; /* yield so long when in background */
139 /* these are computed from previous and clock and such */
140 int enabled; /* check_interrupt OR process_event OR yield */
141 unsigned long next_check; /* when to check/yield next, in ticks */
142};
143
144static struct real_sched_param_struct schedparams =
145 { 1, MAINLOOP_EVENTMASK, 1, 15, 15, 1, 0};
146
Jack Jansen819f1771995-08-14 12:35:10 +0000147/*
Jack Jansenf6865f71996-09-04 15:24:59 +0000148** Workaround for sioux/gusi combo: set when we are exiting
149*/
150int PyMac_ConsoleIsDead;
151
152/*
Jack Jansencaa7c461997-06-12 10:49:13 +0000153** Sioux menu bar, saved early so we can restore it
154*/
155static Handle sioux_mbar;
156
157/*
Jack Jansen819f1771995-08-14 12:35:10 +0000158** Some stuff for our GetDirectory and PromptGetFile routines
159*/
160struct hook_args {
161 int selectcur_hit; /* Set to true when "select current" selected */
162 char *prompt; /* The prompt */
163};
Jack Jansen74a1e632000-07-14 22:37:27 +0000164#if TARGET_API_MAC_CARBON
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000165/* The StandardFile hooks don't exist in Carbon. This breaks GetDirectory,
166** but the macfsn code will replace it by a NavServices version anyway.
167*/
168#define myhook_upp NULL
169#else
Jack Jansen819f1771995-08-14 12:35:10 +0000170static DlgHookYDUPP myhook_upp;
171static int upp_inited = 0;
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000172#endif
Jack Jansen819f1771995-08-14 12:35:10 +0000173
Jack Jansen36ed5061997-06-20 16:18:15 +0000174/*
175** The python-code event handler
176*/
177static PyObject *python_event_handler;
178
Jack Jansen8f5725a1999-12-07 23:08:10 +0000179/*
180** Set to true if we're appearance-compliant
181*/
182int PyMac_AppearanceCompliant;
183
Jack Jansen1f9f2f42000-07-24 19:50:16 +0000184/*
185** Find out what the current script is.
186** Donated by Fredrik Lund.
187*/
188char *PyMac_getscript()
189{
190 int font, script, lang;
191 font = 0;
192 font = GetSysFont();
193 script = FontToScript(font);
194 switch (script) {
195 case smRoman:
196 lang = GetScriptVariable(script, smScriptLang);
197 if (lang == langIcelandic)
198 return "mac-iceland";
199 else if (lang == langTurkish)
200 return "mac-turkish";
201 else if (lang == langGreek)
202 return "mac-greek";
203 else
204 return "mac-roman";
205 break;
206 case smJapanese:
207 return "mac-japan";
208 case smGreek:
209 return "mac-greek";
210 case smCyrillic:
211 return "mac-cyrillic";
212 default:
213 return "mac-roman"; /* better than nothing */
214 }
215}
216
217
Jack Jansen2d1306b2000-04-07 09:10:49 +0000218#ifdef USE_GUSI1
Jack Jansen378815c1996-03-06 16:21:34 +0000219/*
220** GUSI (1.6.0 and earlier, at the least) do not set the MacOS idea of
221** the working directory. Hence, we call this routine after each call
222** to chdir() to rectify things.
223*/
224void
225PyMac_FixGUSIcd()
226{
227 WDPBRec pb;
228 FSSpec curdirfss;
229
230 if ( Path2FSSpec(":x", &curdirfss) != noErr )
231 return;
232
233 /* Set MacOS "working directory" */
234 pb.ioNamePtr= "\p";
235 pb.ioVRefNum= curdirfss.vRefNum;
236 pb.ioWDDirID= curdirfss.parID;
Jack Jansen08c3be31997-04-08 15:27:00 +0000237 if (PBHSetVolSync(&pb) != noErr)
Jack Jansen378815c1996-03-06 16:21:34 +0000238 return;
Jack Jansen378815c1996-03-06 16:21:34 +0000239}
Jack Jansen2d1306b2000-04-07 09:10:49 +0000240#endif
Jack Jansen7ac70af1996-08-19 11:01:05 +0000241
Jack Jansen2d1306b2000-04-07 09:10:49 +0000242#ifdef USE_GUSI
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000243/*
244** SpinCursor (needed by GUSI) drags in heaps of stuff, so we
245** provide a dummy here.
246*/
Jack Jansencfadbd41996-08-19 11:36:25 +0000247void SpinCursor(short x) { /* Dummy */ }
Jack Jansenefaada71998-02-20 16:03:15 +0000248void RotateCursor(short x) { /* Dummy */ }
Jack Jansencfadbd41996-08-19 11:36:25 +0000249
Jack Jansenf6865f71996-09-04 15:24:59 +0000250/*
251** Replacement GUSI Spin function
252*/
Jack Jansen2d1306b2000-04-07 09:10:49 +0000253#ifdef USE_GUSI1
Jack Jansenf6865f71996-09-04 15:24:59 +0000254static int
255PyMac_GUSISpin(spin_msg msg, long arg)
256{
Jack Jansene3ae0df1997-06-03 15:28:29 +0000257 static Boolean inForeground = true;
258 int maxsleep = 6; /* 6 ticks is "normal" sleeptime */
Jack Jansenf6865f71996-09-04 15:24:59 +0000259
260 if (PyMac_ConsoleIsDead) return 0;
261#if 0
262 if (inForeground)
263 SpinCursor(msg == SP_AUTO_SPIN ? short(arg) : 1);
264#endif
265
266 if (interrupted) return -1;
267
Jack Jansene3ae0df1997-06-03 15:28:29 +0000268 if ( msg == SP_AUTO_SPIN )
269 maxsleep = 0;
270 if ( msg==SP_SLEEP||msg==SP_SELECT )
271 maxsleep = arg;
Jack Jansenf6865f71996-09-04 15:24:59 +0000272
Jack Jansene3ae0df1997-06-03 15:28:29 +0000273 PyMac_DoYield(maxsleep, 0); /* XXXX or is it safe to call python here? */
Jack Jansenf6865f71996-09-04 15:24:59 +0000274
275 return 0;
276}
277
278void
279PyMac_SetGUSISpin() {
280 GUSISetHook(GUSI_SpinHook, (GUSIHook)PyMac_GUSISpin);
281}
Jack Jansen2d1306b2000-04-07 09:10:49 +0000282#endif
Jack Jansenf6865f71996-09-04 15:24:59 +0000283
Jack Jansena39f1b01997-05-23 15:35:14 +0000284/* Called at exit() time thru atexit(), to stop event processing */
285void
286PyMac_StopGUSISpin() {
287 PyMac_ConsoleIsDead = 1;
288}
289
290/*
291** Replacement routines for the PLstr... functions so we don't need
292** StdCLib. Moreover, that implementation is broken under cfm68k...
293*/
Jack Jansen8bb573e1999-12-12 21:37:14 +0000294pascal void
Jack Jansen9ae898b2000-07-11 21:16:03 +0000295PLstrcpy(unsigned char *to, unsigned char *fr)
Jack Jansena39f1b01997-05-23 15:35:14 +0000296{
297 memcpy(to, fr, fr[0]+1);
298}
299
Jack Jansen8bb573e1999-12-12 21:37:14 +0000300pascal int
Jack Jansen9ae898b2000-07-11 21:16:03 +0000301PLstrcmp(unsigned char *s1, unsigned char *s2)
Jack Jansena39f1b01997-05-23 15:35:14 +0000302{
303 int res;
304 int l = s1[0] < s2[0] ? s1[0] : s2[0];
305
306 res = memcmp(s1+1, s2+1, l);
307 if ( res != 0 )
308 return res;
309
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000310 if ( s1[0] < s2[0] )
Jack Jansena39f1b01997-05-23 15:35:14 +0000311 return -1;
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000312 else if ( s1[0] > s2[0] )
Jack Jansena39f1b01997-05-23 15:35:14 +0000313 return 1;
314 else
315 return 0;
316}
317
Jack Jansen8bb573e1999-12-12 21:37:14 +0000318pascal unsigned char *
Jack Jansen9ae898b2000-07-11 21:16:03 +0000319PLstrrchr(unsigned char *str, unsigned char chr)
Jack Jansena39f1b01997-05-23 15:35:14 +0000320{
321 unsigned char *ptr = 0;
322 unsigned char *p;
323
324 for(p=str+1; p<str+str[0]; p++)
325 if ( *p == chr )
326 ptr = p;
327 return ptr;
328}
329
330#endif /* USE_GUSI */
Jack Jansen378815c1996-03-06 16:21:34 +0000331
Jack Jansen819f1771995-08-14 12:35:10 +0000332
Jack Jansen5f653091995-01-18 13:53:49 +0000333/* Convert C to Pascal string. Returns pointer to static buffer. */
334unsigned char *
335Pstring(char *str)
336{
337 static Str255 buf;
338 int len;
339
340 len = strlen(str);
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000341 if (len > 255)
342 len = 255;
Jack Jansen5f653091995-01-18 13:53:49 +0000343 buf[0] = (unsigned char)len;
344 strncpy((char *)buf+1, str, len);
345 return buf;
346}
347
Jack Jansen91faef82001-01-09 22:24:56 +0000348#if !TARGET_API_MAC_CARBON
Jack Jansen5afad832000-12-12 22:12:14 +0000349void
350c2pstrcpy(unsigned char *dst, const char *src)
351{
352 int len;
353
354 len = strlen(src);
355 if ( len > 255 ) len = 255;
356 strncpy((char *)dst+1, src, len);
357 dst[0] = len;
358}
Jack Jansen91faef82001-01-09 22:24:56 +0000359#endif
Jack Jansen5afad832000-12-12 22:12:14 +0000360
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000361/* Like strerror() but for Mac OS error numbers */
362char *PyMac_StrError(int err)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000363{
364 static char buf[256];
365 Handle h;
366 char *str;
367
368 h = GetResource('Estr', err);
369 if ( h ) {
370 HLock(h);
371 str = (char *)*h;
372 memcpy(buf, str+1, (unsigned char)str[0]);
Guido van Rossumcc9bc8f1995-02-13 16:17:03 +0000373 buf[(unsigned char)str[0]] = '\0';
Jack Jansenf93c72a1994-12-14 14:07:50 +0000374 HUnlock(h);
375 ReleaseResource(h);
376 } else {
377 sprintf(buf, "Mac OS error code %d", err);
378 }
379 return buf;
380}
381
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000382/* Exception object shared by all Mac specific modules for Mac OS errors */
383PyObject *PyMac_OSErrException;
384
385/* Initialize and return PyMac_OSErrException */
386PyObject *
387PyMac_GetOSErrException()
388{
389 if (PyMac_OSErrException == NULL)
390 PyMac_OSErrException = PyString_FromString("Mac OS Error");
391 return PyMac_OSErrException;
392}
393
Jack Jansenf93c72a1994-12-14 14:07:50 +0000394/* Set a MAC-specific error from errno, and return NULL; return None if no error */
395PyObject *
Guido van Rossumfffb8bb1995-01-12 12:37:24 +0000396PyErr_Mac(PyObject *eobj, int err)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000397{
398 char *msg;
399 PyObject *v;
Jack Jansenf93c72a1994-12-14 14:07:50 +0000400
Guido van Rossum8f691791995-01-18 23:57:26 +0000401 if (err == 0 && !PyErr_Occurred()) {
Jack Jansenf93c72a1994-12-14 14:07:50 +0000402 Py_INCREF(Py_None);
403 return Py_None;
404 }
Guido van Rossum8f691791995-01-18 23:57:26 +0000405 if (err == -1 && PyErr_Occurred())
406 return NULL;
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000407 msg = PyMac_StrError(err);
Jack Jansenf93c72a1994-12-14 14:07:50 +0000408 v = Py_BuildValue("(is)", err, msg);
409 PyErr_SetObject(eobj, v);
410 Py_DECREF(v);
411 return NULL;
412}
413
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000414/* Call PyErr_Mac with PyMac_OSErrException */
415PyObject *
416PyMac_Error(OSErr err)
417{
418 return PyErr_Mac(PyMac_GetOSErrException(), err);
419}
420
Jack Jansen1ed95291996-07-22 15:25:10 +0000421#ifdef USE_STACKCHECK
422/* Check for stack overflow */
423int
424PyOS_CheckStack()
425{
Jack Jansen14a91712000-08-25 21:57:23 +0000426 char here;
427 static char *sentinel = 0;
Jack Jansen53bafd92000-09-08 22:05:48 +0000428 static PyThreadState *thread_for_sentinel = 0;
Jack Jansen1ed95291996-07-22 15:25:10 +0000429
Jack Jansen14a91712000-08-25 21:57:23 +0000430 if ( sentinel == 0 ) {
431 sentinel = &here - StackSpace() + MINIMUM_STACK_SIZE;
432 }
Jack Jansen53bafd92000-09-08 22:05:48 +0000433 if ( thread_for_sentinel == 0 ) {
434 thread_for_sentinel = PyThreadState_Get();
435 }
436 if ( &here < sentinel ) {
437 if (thread_for_sentinel == PyThreadState_Get()) {
438 return -1;
439#if 0
440 } else {
441 /* Else we are unsure... */
442 fprintf(stderr, "Stackcheck in other thread (was %x now %x)\n", thread_for_sentinel,PyThreadState_Get());
443#endif
444 }
445 }
Jack Jansen1ed95291996-07-22 15:25:10 +0000446 return 0;
447}
448#endif /* USE_STACKCHECK */
449
Jack Jansenee23d6e1995-01-27 14:43:25 +0000450/* The catcher routine (which may not be used for all compilers) */
451static RETSIGTYPE
452intcatcher(sig)
453 int sig;
454{
455 interrupted = 1;
456 signal(SIGINT, intcatcher);
457}
458
459void
460PyOS_InitInterrupts()
461{
462 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
463 signal(SIGINT, intcatcher);
464}
465
Jack Jansena8441de1997-08-08 14:57:37 +0000466void
467PyOS_FiniInterrupts()
468{
469}
470
Jack Jansenee23d6e1995-01-27 14:43:25 +0000471/*
472** This routine scans the event queue looking for cmd-.
473** This is the only way to get an interrupt under THINK (since it
474** doesn't do SIGINT handling), but is also used under MW, when
475** the full-fledged event loop is disabled. This way, we can at least
476** interrupt a runaway python program.
477*/
478static void
479scan_event_queue(flush)
480 int flush;
481{
Jack Jansen74a1e632000-07-14 22:37:27 +0000482#if TARGET_API_MAC_CARBON
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000483 /* CARBONXXXX To be implemented */
484 return;
485#else
Jack Jansenee23d6e1995-01-27 14:43:25 +0000486 register EvQElPtr q;
487
Jack Jansenefaada71998-02-20 16:03:15 +0000488 q = (EvQElPtr) LMGetEventQueue()->qHead;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000489
490 for (; q; q = (EvQElPtr)q->qLink) {
491 if (q->evtQWhat == keyDown &&
492 (char)q->evtQMessage == '.' &&
493 (q->evtQModifiers & cmdKey) != 0) {
494 if ( flush )
495 FlushEvents(keyDownMask, 0);
496 interrupted = 1;
497 break;
498 }
499 }
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000500#endif
Jack Jansenee23d6e1995-01-27 14:43:25 +0000501}
502
503int
Jack Jansen36ed5061997-06-20 16:18:15 +0000504PyErr_CheckSignals()
Jack Jansenee23d6e1995-01-27 14:43:25 +0000505{
Jack Jansene3ae0df1997-06-03 15:28:29 +0000506 if (schedparams.enabled) {
507 if ( (unsigned long)LMGetTicks() > schedparams.next_check ) {
Jack Jansen36ed5061997-06-20 16:18:15 +0000508 if ( PyMac_Yield() < 0)
509 return -1;
Jack Jansene3ae0df1997-06-03 15:28:29 +0000510 schedparams.next_check = (unsigned long)LMGetTicks()
511 + schedparams.check_interval;
512 if (interrupted) {
Jack Jansencaa7c461997-06-12 10:49:13 +0000513 scan_event_queue(1); /* Eat events up to cmd-. */
Jack Jansene3ae0df1997-06-03 15:28:29 +0000514 interrupted = 0;
Jack Jansen36ed5061997-06-20 16:18:15 +0000515 PyErr_SetNone(PyExc_KeyboardInterrupt);
516 return -1;
Jack Jansene3ae0df1997-06-03 15:28:29 +0000517 }
518 }
Jack Jansenee23d6e1995-01-27 14:43:25 +0000519 }
520 return 0;
521}
522
Jack Jansen36ed5061997-06-20 16:18:15 +0000523int
524PyOS_InterruptOccurred()
525{
526 scan_event_queue(1);
527 return interrupted;
528}
Jack Jansenee23d6e1995-01-27 14:43:25 +0000529/* Check whether we are in the foreground */
Jack Jansen9ae898b2000-07-11 21:16:03 +0000530static int
531PyMac_InForeground(void)
Jack Jansenee23d6e1995-01-27 14:43:25 +0000532{
533 static ProcessSerialNumber ours;
534 static inited;
535 ProcessSerialNumber curfg;
536 Boolean eq;
537
Jack Jansene3ae0df1997-06-03 15:28:29 +0000538 if ( inited == 0 ) {
Jack Jansenee23d6e1995-01-27 14:43:25 +0000539 (void)GetCurrentProcess(&ours);
Jack Jansene3ae0df1997-06-03 15:28:29 +0000540 inited = 1;
541 }
Jack Jansenee23d6e1995-01-27 14:43:25 +0000542 if ( GetFrontProcess(&curfg) < 0 )
543 eq = 1;
544 else if ( SameProcess(&ours, &curfg, &eq) < 0 )
545 eq = 1;
546 return (int)eq;
547
548}
549
Jack Jansen36ed5061997-06-20 16:18:15 +0000550int
551PyMac_SetEventHandler(PyObject *evh)
552{
553 if ( evh && python_event_handler ) {
554 PyErr_SetString(PyExc_RuntimeError, "Python event handler already set");
555 return 0;
556 }
557 if ( python_event_handler )
558 Py_DECREF(python_event_handler);
559 if ( evh )
560 Py_INCREF(evh);
561 python_event_handler = evh;
562 return 1;
563}
564
Jack Jansenf93c72a1994-12-14 14:07:50 +0000565/*
Jack Jansena76382a1995-02-02 14:25:56 +0000566** Handle an event, either one found in the mainloop eventhandler or
567** one passed back from the python program.
568*/
569void
Jack Jansen36ed5061997-06-20 16:18:15 +0000570PyMac_HandleEventIntern(evp)
Jack Jansena76382a1995-02-02 14:25:56 +0000571 EventRecord *evp;
572{
Jack Jansen74a1e632000-07-14 22:37:27 +0000573#if !TARGET_API_MAC_CARBON
Jack Jansen0c968871997-08-26 13:20:34 +0000574 if ( evp->what == mouseDown ) {
575 WindowPtr wp;
576
577 if ( FindWindow(evp->where, &wp) == inSysWindow ) {
578 SystemClick(evp, wp);
579 return;
580 }
581 }
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000582#endif
Jack Jansena76382a1995-02-02 14:25:56 +0000583#ifdef __MWERKS__
Jack Jansen38e97661995-11-10 14:53:00 +0000584 {
585 int siouxdidit;
586
587 /* If SIOUX wants it we're done */
588 siouxdidit = SIOUXHandleOneEvent(evp);
589 if ( siouxdidit )
590 return;
591 }
Jack Jansena76382a1995-02-02 14:25:56 +0000592#else
Jack Jansen0c968871997-08-26 13:20:34 +0000593 /* Other compilers are just unlucky... */
Jack Jansena76382a1995-02-02 14:25:56 +0000594#endif /* !__MWERKS__ */
Jack Jansen36ed5061997-06-20 16:18:15 +0000595}
596
597/*
598** Handle an event, either through HandleEvent or by passing it to the Python
599** event handler.
600*/
601int
602PyMac_HandleEvent(evp)
603 EventRecord *evp;
604{
605 PyObject *rv;
606
607 if ( python_event_handler ) {
608 rv = PyObject_CallFunction(python_event_handler, "(O&)",
609 PyMac_BuildEventRecord, evp);
610 if ( rv )
611 Py_DECREF(rv);
612 else
613 return -1; /* Propagate exception */
614 } else {
615 PyMac_HandleEventIntern(evp);
616 }
617 return 0;
Jack Jansena76382a1995-02-02 14:25:56 +0000618}
619
620/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000621** Yield the CPU to other tasks without processing events.
Jack Jansene8e8ae01995-01-26 16:36:45 +0000622*/
Jack Jansen2d1306b2000-04-07 09:10:49 +0000623int
Jack Jansene3ae0df1997-06-03 15:28:29 +0000624PyMac_DoYield(int maxsleep, int maycallpython)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000625{
626 EventRecord ev;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000627 int gotone;
Jack Jansene3ae0df1997-06-03 15:28:29 +0000628 long latest_time_ready;
Jack Jansen36ed5061997-06-20 16:18:15 +0000629 static int in_here = 0;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000630
Jack Jansen36ed5061997-06-20 16:18:15 +0000631 in_here++;
Jack Jansene3ae0df1997-06-03 15:28:29 +0000632 /*
633 ** First check for interrupts, if wanted.
634 ** This sets a flag that will be picked up at an appropriate
635 ** moment in the mainloop.
636 */
637 if (schedparams.check_interrupt)
Jack Jansenee23d6e1995-01-27 14:43:25 +0000638 scan_event_queue(0);
Jack Jansene3ae0df1997-06-03 15:28:29 +0000639
640 /* XXXX Implementing an idle routine goes here */
Jack Jansene8e8ae01995-01-26 16:36:45 +0000641
Jack Jansene3ae0df1997-06-03 15:28:29 +0000642 /*
643 ** Check which of the eventloop cases we have:
644 ** - process events
645 ** - don't process events but do yield
646 ** - do neither
647 */
Jack Jansen36ed5061997-06-20 16:18:15 +0000648 if( in_here > 1 || !schedparams.process_events ||
649 (python_event_handler && !maycallpython) ) {
Jack Jansen74a1e632000-07-14 22:37:27 +0000650#if !TARGET_API_MAC_CARBON
Jack Jansene3ae0df1997-06-03 15:28:29 +0000651 if ( maxsleep >= 0 ) {
Jack Jansene8e8ae01995-01-26 16:36:45 +0000652 SystemTask();
Jack Jansene3ae0df1997-06-03 15:28:29 +0000653 }
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000654#endif
Jack Jansene3ae0df1997-06-03 15:28:29 +0000655 } else {
656 latest_time_ready = LMGetTicks() + maxsleep;
Jack Jansen2d1306b2000-04-07 09:10:49 +0000657 do {
Jack Jansen0c968871997-08-26 13:20:34 +0000658 /* XXXX Hack by Jack.
659 ** In time.sleep() you can click to another application
660 ** once only. If you come back to Python you cannot get away
661 ** again.
662 **/
Jack Jansen36ed5061997-06-20 16:18:15 +0000663 gotone = WaitNextEvent(schedparams.process_events, &ev, maxsleep, NULL);
Jack Jansene3ae0df1997-06-03 15:28:29 +0000664 /* Get out quickly if nothing interesting is happening */
665 if ( !gotone || ev.what == nullEvent )
666 break;
Jack Jansen36ed5061997-06-20 16:18:15 +0000667 if ( PyMac_HandleEvent(&ev) < 0 ) {
668 in_here--;
669 return -1;
670 }
Jack Jansene3ae0df1997-06-03 15:28:29 +0000671 maxsleep = latest_time_ready - LMGetTicks();
Jack Jansen2d1306b2000-04-07 09:10:49 +0000672 } while ( maxsleep > 0 );
Jack Jansenf93c72a1994-12-14 14:07:50 +0000673 }
Jack Jansen36ed5061997-06-20 16:18:15 +0000674 in_here--;
675 return 0;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000676}
677
678/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000679** Process events and/or yield the CPU to other tasks if opportune
Jack Jansene8e8ae01995-01-26 16:36:45 +0000680*/
Jack Jansen36ed5061997-06-20 16:18:15 +0000681int
Jack Jansene8e8ae01995-01-26 16:36:45 +0000682PyMac_Yield() {
Jack Jansene3ae0df1997-06-03 15:28:29 +0000683 unsigned long maxsleep;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000684
Jack Jansene3ae0df1997-06-03 15:28:29 +0000685 if( PyMac_InForeground() )
686 maxsleep = 0;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000687 else
Jack Jansene3ae0df1997-06-03 15:28:29 +0000688 maxsleep = schedparams.bg_yield;
689
Jack Jansen36ed5061997-06-20 16:18:15 +0000690 return PyMac_DoYield(maxsleep, 1);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000691}
692
693/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000694** Return current scheduler parameters
Jack Jansene8e8ae01995-01-26 16:36:45 +0000695*/
Jack Jansene3ae0df1997-06-03 15:28:29 +0000696void
697PyMac_GetSchedParams(PyMacSchedParams *sp)
Jack Jansene8e8ae01995-01-26 16:36:45 +0000698{
Jack Jansene3ae0df1997-06-03 15:28:29 +0000699 sp->check_interrupt = schedparams.check_interrupt;
700 sp->process_events = schedparams.process_events;
701 sp->besocial = schedparams.besocial;
702 sp->check_interval = schedparams.check_interval / 60.0;
703 sp->bg_yield = schedparams.bg_yield / 60.0;
Jack Jansenf93c72a1994-12-14 14:07:50 +0000704}
Jack Jansenf6865f71996-09-04 15:24:59 +0000705
Jack Jansen74162f31995-02-15 22:58:33 +0000706/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000707** Set current scheduler parameters
708*/
709void
710PyMac_SetSchedParams(PyMacSchedParams *sp)
711{
712 schedparams.check_interrupt = sp->check_interrupt;
713 schedparams.process_events = sp->process_events;
714 schedparams.besocial = sp->besocial;
715 schedparams.check_interval = (unsigned long)(sp->check_interval*60);
716 schedparams.bg_yield = (unsigned long)(sp->bg_yield*60);
717 if ( schedparams.check_interrupt || schedparams.process_events ||
718 schedparams.besocial )
719 schedparams.enabled = 1;
720 else
721 schedparams.enabled = 0;
722 schedparams.next_check = 0; /* Check immedeately */
723}
Jack Jansencaa7c461997-06-12 10:49:13 +0000724
Jack Jansene3ae0df1997-06-03 15:28:29 +0000725/*
Jack Jansen3469e991996-09-06 00:30:45 +0000726** Install our menu bar.
727*/
728void
729PyMac_InitMenuBar()
730{
Jack Jansen3469e991996-09-06 00:30:45 +0000731 MenuHandle applemenu;
732
Jack Jansencaa7c461997-06-12 10:49:13 +0000733 if ( (sioux_mbar=GetMenuBar()) == NULL ) {
734 /* Sioux menu not installed yet. Do so */
735 SIOUXSetupMenus();
736 if ( (sioux_mbar=GetMenuBar()) == NULL )
737 return;
738 }
Jack Jansen08c3be31997-04-08 15:27:00 +0000739 if ( (applemenu=GetMenuHandle(SIOUX_APPLEID)) == NULL ) return;
Jack Jansen3469e991996-09-06 00:30:45 +0000740 SetMenuItemText(applemenu, 1, "\pAbout Python...");
741}
742
743/*
Jack Jansencaa7c461997-06-12 10:49:13 +0000744** Restore sioux menu bar
745*/
746void
747PyMac_RestoreMenuBar()
748{
Jack Janseneda78631997-06-12 15:29:46 +0000749 if ( sioux_mbar ) {
Jack Jansencaa7c461997-06-12 10:49:13 +0000750 SetMenuBar(sioux_mbar);
Jack Janseneda78631997-06-12 15:29:46 +0000751 DrawMenuBar();
Jack Jansenefaada71998-02-20 16:03:15 +0000752 } else
753 PyMac_InitMenuBar();
Jack Jansencaa7c461997-06-12 10:49:13 +0000754}
755
756
757/*
Jack Jansen3469e991996-09-06 00:30:45 +0000758** Our replacement about box
759*/
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000760
761#include "patchlevel.h"
762
Jack Jansen3469e991996-09-06 00:30:45 +0000763void
764SIOUXDoAboutBox(void)
765{
766 DialogPtr theDialog;
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000767 WindowPtr theWindow;
Jack Jansen3469e991996-09-06 00:30:45 +0000768 short item;
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000769 short fontID;
Jack Jansen3469e991996-09-06 00:30:45 +0000770
771 if( (theDialog = GetNewDialog(ABOUT_ID, NULL, (WindowPtr)-1)) == NULL )
772 return;
Jack Jansend617c571996-09-22 22:14:30 +0000773 theWindow = GetDialogWindow(theDialog);
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000774 SetPortWindowPort(theWindow);
775 GetFNum("\pPython-Sans", &fontID);
776 if (fontID == 0)
777 fontID = kFontIDGeneva;
778 TextFont(fontID);
779 TextSize(9);
780 ParamText(Pstring(PATCHLEVEL), "\p", "\p", "\p");
Jack Jansend617c571996-09-22 22:14:30 +0000781 ShowWindow(theWindow);
Jack Jansen3469e991996-09-06 00:30:45 +0000782 ModalDialog(NULL, &item);
783 DisposeDialog(theDialog);
784}
785
Jack Janseneda78631997-06-12 15:29:46 +0000786#if 0
787int
788PyMac_FileExists(char *name)
789{
790 FSSpec fss;
791
792 if ( FSMakeFSSpec(0, 0, Pstring(name), &fss) == noErr )
793 return 1;
794 return 0;
795}
796#endif
797
798/*
Jack Jansen3ec804a1995-02-20 15:56:10 +0000799** Helper routine for GetDirectory
800*/
Guido van Rossum24a45e31995-02-20 23:45:53 +0000801static pascal short
Jack Jansen819f1771995-08-14 12:35:10 +0000802myhook_proc(short item, DialogPtr theDialog, struct hook_args *dataptr)
Jack Jansen3ec804a1995-02-20 15:56:10 +0000803{
Jack Jansen819f1771995-08-14 12:35:10 +0000804 if ( item == sfHookFirstCall && dataptr->prompt) {
805 Handle prompth;
806 short type;
807 Rect rect;
808
809 GetDialogItem(theDialog, PROMPT_ITEM, &type, &prompth, &rect);
810 if ( prompth )
811 SetDialogItemText(prompth, (unsigned char *)dataptr->prompt);
812 } else
Jack Jansen3ec804a1995-02-20 15:56:10 +0000813 if ( item == SELECTCUR_ITEM ) {
814 item = sfItemCancelButton;
Jack Jansen819f1771995-08-14 12:35:10 +0000815 dataptr->selectcur_hit = 1;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000816 }
817 return item;
818}
Jack Jansen74a1e632000-07-14 22:37:27 +0000819#if !TARGET_API_MAC_CARBON
Jack Jansen3ec804a1995-02-20 15:56:10 +0000820/*
821** Ask the user for a directory. I still can't understand
822** why Apple doesn't provide a standard solution for this...
823*/
824int
Jack Jansen819f1771995-08-14 12:35:10 +0000825PyMac_GetDirectory(dirfss, prompt)
Jack Jansen3ec804a1995-02-20 15:56:10 +0000826 FSSpec *dirfss;
Jack Jansen819f1771995-08-14 12:35:10 +0000827 char *prompt;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000828{
829 static SFTypeList list = {'fldr', 0, 0, 0};
830 static Point where = {-1, -1};
Jack Jansen3ec804a1995-02-20 15:56:10 +0000831 StandardFileReply reply;
Jack Jansen819f1771995-08-14 12:35:10 +0000832 struct hook_args hook_args;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000833
834 if ( !upp_inited ) {
835 myhook_upp = NewDlgHookYDProc(myhook_proc);
836 upp_inited = 1;
837 }
Jack Jansen819f1771995-08-14 12:35:10 +0000838 if ( prompt && *prompt )
839 hook_args.prompt = (char *)Pstring(prompt);
840 else
841 hook_args.prompt = NULL;
842 hook_args.selectcur_hit = 0;
Guido van Rossum24a45e31995-02-20 23:45:53 +0000843 CustomGetFile((FileFilterYDUPP)0, 1, list, &reply, GETDIR_ID, where, myhook_upp,
Jack Jansen819f1771995-08-14 12:35:10 +0000844 NULL, NULL, NULL, (void *)&hook_args);
Jack Jansen3ec804a1995-02-20 15:56:10 +0000845
846 reply.sfFile.name[0] = 0;
847 if( FSMakeFSSpec(reply.sfFile.vRefNum, reply.sfFile.parID, reply.sfFile.name, dirfss) )
848 return 0;
Jack Jansen819f1771995-08-14 12:35:10 +0000849 return hook_args.selectcur_hit;
850}
851
852/*
853** Slightly extended StandardGetFile: accepts a prompt */
854void PyMac_PromptGetFile(short numTypes, ConstSFTypeListPtr typeList,
855 StandardFileReply *reply, char *prompt)
856{
857 static Point where = {-1, -1};
858 struct hook_args hook_args;
859
860 if ( !upp_inited ) {
861 myhook_upp = NewDlgHookYDProc(myhook_proc);
862 upp_inited = 1;
863 }
864 if ( prompt && *prompt )
865 hook_args.prompt = (char *)Pstring(prompt);
866 else
867 hook_args.prompt = NULL;
868 hook_args.selectcur_hit = 0;
869 CustomGetFile((FileFilterYDUPP)0, numTypes, typeList, reply, GETFILEPROMPT_ID, where,
870 myhook_upp, NULL, NULL, NULL, (void *)&hook_args);
Jack Jansen3ec804a1995-02-20 15:56:10 +0000871}
Jack Jansenbb7e2132000-07-14 22:15:24 +0000872#endif /* TARGET_API_MAC_CARBON */
Jack Jansen5f653091995-01-18 13:53:49 +0000873
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000874/* Convert a 4-char string object argument to an OSType value */
Jack Jansen5f653091995-01-18 13:53:49 +0000875int
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000876PyMac_GetOSType(PyObject *v, OSType *pr)
Jack Jansen5f653091995-01-18 13:53:49 +0000877{
878 if (!PyString_Check(v) || PyString_Size(v) != 4) {
879 PyErr_SetString(PyExc_TypeError,
880 "OSType arg must be string of 4 chars");
881 return 0;
882 }
883 memcpy((char *)pr, PyString_AsString(v), 4);
884 return 1;
885}
886
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000887/* Convert an OSType value to a 4-char string object */
888PyObject *
889PyMac_BuildOSType(OSType t)
890{
891 return PyString_FromStringAndSize((char *)&t, 4);
892}
893
Jack Jansend1f06311996-08-01 15:23:54 +0000894/* Convert an NumVersion value to a 4-element tuple */
895PyObject *
896PyMac_BuildNumVersion(NumVersion t)
897{
898 return Py_BuildValue("(hhhh)", t.majorRev, t.minorAndBugRev, t.stage, t.nonRelRev);
899}
900
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000901
902/* Convert a Python string object to a Str255 */
Jack Jansen5f653091995-01-18 13:53:49 +0000903int
Guido van Rossum8f691791995-01-18 23:57:26 +0000904PyMac_GetStr255(PyObject *v, Str255 pbuf)
Jack Jansen5f653091995-01-18 13:53:49 +0000905{
906 int len;
907 if (!PyString_Check(v) || (len = PyString_Size(v)) > 255) {
908 PyErr_SetString(PyExc_TypeError,
909 "Str255 arg must be string of at most 255 chars");
910 return 0;
911 }
912 pbuf[0] = len;
913 memcpy((char *)(pbuf+1), PyString_AsString(v), len);
914 return 1;
915}
916
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000917/* Convert a Str255 to a Python string object */
918PyObject *
919PyMac_BuildStr255(Str255 s)
920{
Jack Jansenb734ade1999-12-17 17:15:50 +0000921 if ( s == NULL ) {
922 PyErr_SetString(PyExc_SystemError, "Str255 pointer is NULL");
923 return NULL;
924 }
925 return PyString_FromStringAndSize((char *)&s[1], (int)s[0]);
926}
927
928PyObject *
929PyMac_BuildOptStr255(Str255 s)
930{
931 if ( s == NULL ) {
932 Py_INCREF(Py_None);
933 return Py_None;
934 }
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000935 return PyString_FromStringAndSize((char *)&s[1], (int)s[0]);
936}
937
938
Jack Jansen5f653091995-01-18 13:53:49 +0000939/*
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000940** Convert a Python object to an FSSpec.
941** The object may either be a full pathname or a triple
942** (vrefnum, dirid, path).
Jack Jansen5f653091995-01-18 13:53:49 +0000943** NOTE: This routine will fail on pre-sys7 machines.
944** The caller is responsible for not calling this routine
945** in those cases (which is fine, since everyone calling
946** this is probably sys7 dependent anyway).
947*/
948int
Guido van Rossum8f691791995-01-18 23:57:26 +0000949PyMac_GetFSSpec(PyObject *v, FSSpec *fs)
Jack Jansen5f653091995-01-18 13:53:49 +0000950{
951 Str255 path;
952 short refnum;
953 long parid;
954 OSErr err;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000955 FSSpec *fs2;
Jack Jansen5f653091995-01-18 13:53:49 +0000956
Jack Jansene8e8ae01995-01-26 16:36:45 +0000957 /* first check whether it already is an FSSpec */
958 fs2 = mfs_GetFSSpecFSSpec(v);
959 if ( fs2 ) {
Jack Jansen3ec804a1995-02-20 15:56:10 +0000960 (void)FSMakeFSSpec(fs2->vRefNum, fs2->parID, fs2->name, fs);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000961 return 1;
962 }
Jack Jansen5f653091995-01-18 13:53:49 +0000963 if ( PyString_Check(v) ) {
964 /* It's a pathname */
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000965 if( !PyArg_Parse(v, "O&", PyMac_GetStr255, &path) )
Jack Jansen5f653091995-01-18 13:53:49 +0000966 return 0;
Jack Jansen378815c1996-03-06 16:21:34 +0000967 refnum = 0; /* XXXX Should get CurWD here?? */
Jack Jansen5f653091995-01-18 13:53:49 +0000968 parid = 0;
969 } else {
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000970 if( !PyArg_Parse(v, "(hlO&); FSSpec should be fullpath or (vrefnum,dirid,path)",
971 &refnum, &parid, PyMac_GetStr255, &path)) {
Jack Jansen5f653091995-01-18 13:53:49 +0000972 return 0;
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000973 }
Jack Jansen5f653091995-01-18 13:53:49 +0000974 }
975 err = FSMakeFSSpec(refnum, parid, path, fs);
976 if ( err && err != fnfErr ) {
Jack Jansen3d757542000-01-24 09:56:06 +0000977 PyMac_Error(err);
Jack Jansen5f653091995-01-18 13:53:49 +0000978 return 0;
979 }
980 return 1;
981}
982
Jack Jansen8bb573e1999-12-12 21:37:14 +0000983/* Convert FSSpec to PyObject */
984PyObject *PyMac_BuildFSSpec(FSSpec *v)
985{
986 return newmfssobject(v);
987}
Guido van Rossum8f691791995-01-18 23:57:26 +0000988
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000989/* Convert a Python object to a Rect.
Guido van Rossum5279ec61995-01-26 22:56:59 +0000990 The object must be a (left, top, right, bottom) tuple.
991 (This differs from the order in the struct but is consistent with
992 the arguments to SetRect(), and also with STDWIN). */
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000993int
994PyMac_GetRect(PyObject *v, Rect *r)
Guido van Rossum8f691791995-01-18 23:57:26 +0000995{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000996 return PyArg_Parse(v, "(hhhh)", &r->left, &r->top, &r->right, &r->bottom);
Guido van Rossum8f691791995-01-18 23:57:26 +0000997}
Guido van Rossumb3404661995-01-22 18:36:13 +0000998
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000999/* Convert a Rect to a Python object */
Guido van Rossumb3404661995-01-22 18:36:13 +00001000PyObject *
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001001PyMac_BuildRect(Rect *r)
Guido van Rossumb3404661995-01-22 18:36:13 +00001002{
Guido van Rossum5279ec61995-01-26 22:56:59 +00001003 return Py_BuildValue("(hhhh)", r->left, r->top, r->right, r->bottom);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001004}
1005
1006
1007/* Convert a Python object to a Point.
Guido van Rossum5279ec61995-01-26 22:56:59 +00001008 The object must be a (h, v) tuple.
1009 (This differs from the order in the struct but is consistent with
1010 the arguments to SetPoint(), and also with STDWIN). */
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001011int
1012PyMac_GetPoint(PyObject *v, Point *p)
1013{
Guido van Rossum5279ec61995-01-26 22:56:59 +00001014 return PyArg_Parse(v, "(hh)", &p->h, &p->v);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001015}
1016
1017/* Convert a Point to a Python object */
1018PyObject *
1019PyMac_BuildPoint(Point p)
1020{
Guido van Rossum5279ec61995-01-26 22:56:59 +00001021 return Py_BuildValue("(hh)", p.h, p.v);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001022}
1023
1024
1025/* Convert a Python object to an EventRecord.
1026 The object must be a (what, message, when, (v, h), modifiers) tuple. */
1027int
1028PyMac_GetEventRecord(PyObject *v, EventRecord *e)
1029{
1030 return PyArg_Parse(v, "(hll(hh)h)",
1031 &e->what,
1032 &e->message,
1033 &e->when,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001034 &e->where.h,
Guido van Rossum5279ec61995-01-26 22:56:59 +00001035 &e->where.v,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001036 &e->modifiers);
1037}
1038
1039/* Convert a Rect to an EventRecord object */
1040PyObject *
1041PyMac_BuildEventRecord(EventRecord *e)
1042{
1043 return Py_BuildValue("(hll(hh)h)",
1044 e->what,
1045 e->message,
1046 e->when,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001047 e->where.h,
Guido van Rossum5279ec61995-01-26 22:56:59 +00001048 e->where.v,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001049 e->modifiers);
Guido van Rossumb3404661995-01-22 18:36:13 +00001050}
Jack Jansenfa4d5d01995-11-15 15:19:29 +00001051
1052/* Convert Python object to Fixed */
1053int
1054PyMac_GetFixed(PyObject *v, Fixed *f)
1055{
1056 double d;
1057
1058 if( !PyArg_Parse(v, "d", &d))
1059 return 0;
1060 *f = (Fixed)(d * 0x10000);
Jack Jansen31dd5c01996-05-31 13:01:39 +00001061 return 1;
Jack Jansenfa4d5d01995-11-15 15:19:29 +00001062}
1063
1064/* Convert a Point to a Python object */
1065PyObject *
1066PyMac_BuildFixed(Fixed f)
1067{
1068 double d;
1069
1070 d = f;
1071 d = d / 0x10000;
1072 return Py_BuildValue("d", d);
1073}
1074
Jack Jansend58cd631998-04-21 15:24:39 +00001075/* Convert wide to/from Python int or (hi, lo) tuple. XXXX Should use Python longs */
1076int
1077PyMac_Getwide(PyObject *v, wide *rv)
1078{
1079 if (PyInt_Check(v)) {
1080 rv->hi = 0;
1081 rv->lo = PyInt_AsLong(v);
1082 if( rv->lo & 0x80000000 )
1083 rv->hi = -1;
1084 return 1;
1085 }
1086 return PyArg_Parse(v, "(ll)", &rv->hi, &rv->lo);
1087}
1088
1089
1090PyObject *
Jack Jansenbbf4be21998-04-23 13:20:17 +00001091PyMac_Buildwide(wide *w)
Jack Jansend58cd631998-04-21 15:24:39 +00001092{
Jack Jansenbbf4be21998-04-23 13:20:17 +00001093 if ( (w->hi == 0 && (w->lo & 0x80000000) == 0) ||
1094 (w->hi == -1 && (w->lo & 0x80000000) ) )
1095 return PyInt_FromLong(w->lo);
1096 return Py_BuildValue("(ll)", w->hi, w->lo);
Jack Jansend58cd631998-04-21 15:24:39 +00001097}