blob: ded0ad1e19106e6533fa3383b6c5493ec7d31f94 [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 Jansen5afad832000-12-12 22:12:14 +0000348void
349c2pstrcpy(unsigned char *dst, const char *src)
350{
351 int len;
352
353 len = strlen(src);
354 if ( len > 255 ) len = 255;
355 strncpy((char *)dst+1, src, len);
356 dst[0] = len;
357}
358
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000359/* Like strerror() but for Mac OS error numbers */
360char *PyMac_StrError(int err)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000361{
362 static char buf[256];
363 Handle h;
364 char *str;
365
366 h = GetResource('Estr', err);
367 if ( h ) {
368 HLock(h);
369 str = (char *)*h;
370 memcpy(buf, str+1, (unsigned char)str[0]);
Guido van Rossumcc9bc8f1995-02-13 16:17:03 +0000371 buf[(unsigned char)str[0]] = '\0';
Jack Jansenf93c72a1994-12-14 14:07:50 +0000372 HUnlock(h);
373 ReleaseResource(h);
374 } else {
375 sprintf(buf, "Mac OS error code %d", err);
376 }
377 return buf;
378}
379
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000380/* Exception object shared by all Mac specific modules for Mac OS errors */
381PyObject *PyMac_OSErrException;
382
383/* Initialize and return PyMac_OSErrException */
384PyObject *
385PyMac_GetOSErrException()
386{
387 if (PyMac_OSErrException == NULL)
388 PyMac_OSErrException = PyString_FromString("Mac OS Error");
389 return PyMac_OSErrException;
390}
391
Jack Jansenf93c72a1994-12-14 14:07:50 +0000392/* Set a MAC-specific error from errno, and return NULL; return None if no error */
393PyObject *
Guido van Rossumfffb8bb1995-01-12 12:37:24 +0000394PyErr_Mac(PyObject *eobj, int err)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000395{
396 char *msg;
397 PyObject *v;
Jack Jansenf93c72a1994-12-14 14:07:50 +0000398
Guido van Rossum8f691791995-01-18 23:57:26 +0000399 if (err == 0 && !PyErr_Occurred()) {
Jack Jansenf93c72a1994-12-14 14:07:50 +0000400 Py_INCREF(Py_None);
401 return Py_None;
402 }
Guido van Rossum8f691791995-01-18 23:57:26 +0000403 if (err == -1 && PyErr_Occurred())
404 return NULL;
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000405 msg = PyMac_StrError(err);
Jack Jansenf93c72a1994-12-14 14:07:50 +0000406 v = Py_BuildValue("(is)", err, msg);
407 PyErr_SetObject(eobj, v);
408 Py_DECREF(v);
409 return NULL;
410}
411
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000412/* Call PyErr_Mac with PyMac_OSErrException */
413PyObject *
414PyMac_Error(OSErr err)
415{
416 return PyErr_Mac(PyMac_GetOSErrException(), err);
417}
418
Jack Jansen1ed95291996-07-22 15:25:10 +0000419#ifdef USE_STACKCHECK
420/* Check for stack overflow */
421int
422PyOS_CheckStack()
423{
Jack Jansen14a91712000-08-25 21:57:23 +0000424 char here;
425 static char *sentinel = 0;
Jack Jansen53bafd92000-09-08 22:05:48 +0000426 static PyThreadState *thread_for_sentinel = 0;
Jack Jansen1ed95291996-07-22 15:25:10 +0000427
Jack Jansen14a91712000-08-25 21:57:23 +0000428 if ( sentinel == 0 ) {
429 sentinel = &here - StackSpace() + MINIMUM_STACK_SIZE;
430 }
Jack Jansen53bafd92000-09-08 22:05:48 +0000431 if ( thread_for_sentinel == 0 ) {
432 thread_for_sentinel = PyThreadState_Get();
433 }
434 if ( &here < sentinel ) {
435 if (thread_for_sentinel == PyThreadState_Get()) {
436 return -1;
437#if 0
438 } else {
439 /* Else we are unsure... */
440 fprintf(stderr, "Stackcheck in other thread (was %x now %x)\n", thread_for_sentinel,PyThreadState_Get());
441#endif
442 }
443 }
Jack Jansen1ed95291996-07-22 15:25:10 +0000444 return 0;
445}
446#endif /* USE_STACKCHECK */
447
Jack Jansenee23d6e1995-01-27 14:43:25 +0000448/* The catcher routine (which may not be used for all compilers) */
449static RETSIGTYPE
450intcatcher(sig)
451 int sig;
452{
453 interrupted = 1;
454 signal(SIGINT, intcatcher);
455}
456
457void
458PyOS_InitInterrupts()
459{
460 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
461 signal(SIGINT, intcatcher);
462}
463
Jack Jansena8441de1997-08-08 14:57:37 +0000464void
465PyOS_FiniInterrupts()
466{
467}
468
Jack Jansenee23d6e1995-01-27 14:43:25 +0000469/*
470** This routine scans the event queue looking for cmd-.
471** This is the only way to get an interrupt under THINK (since it
472** doesn't do SIGINT handling), but is also used under MW, when
473** the full-fledged event loop is disabled. This way, we can at least
474** interrupt a runaway python program.
475*/
476static void
477scan_event_queue(flush)
478 int flush;
479{
Jack Jansen74a1e632000-07-14 22:37:27 +0000480#if TARGET_API_MAC_CARBON
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000481 /* CARBONXXXX To be implemented */
482 return;
483#else
Jack Jansenee23d6e1995-01-27 14:43:25 +0000484 register EvQElPtr q;
485
Jack Jansenefaada71998-02-20 16:03:15 +0000486 q = (EvQElPtr) LMGetEventQueue()->qHead;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000487
488 for (; q; q = (EvQElPtr)q->qLink) {
489 if (q->evtQWhat == keyDown &&
490 (char)q->evtQMessage == '.' &&
491 (q->evtQModifiers & cmdKey) != 0) {
492 if ( flush )
493 FlushEvents(keyDownMask, 0);
494 interrupted = 1;
495 break;
496 }
497 }
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000498#endif
Jack Jansenee23d6e1995-01-27 14:43:25 +0000499}
500
501int
Jack Jansen36ed5061997-06-20 16:18:15 +0000502PyErr_CheckSignals()
Jack Jansenee23d6e1995-01-27 14:43:25 +0000503{
Jack Jansene3ae0df1997-06-03 15:28:29 +0000504 if (schedparams.enabled) {
505 if ( (unsigned long)LMGetTicks() > schedparams.next_check ) {
Jack Jansen36ed5061997-06-20 16:18:15 +0000506 if ( PyMac_Yield() < 0)
507 return -1;
Jack Jansene3ae0df1997-06-03 15:28:29 +0000508 schedparams.next_check = (unsigned long)LMGetTicks()
509 + schedparams.check_interval;
510 if (interrupted) {
Jack Jansencaa7c461997-06-12 10:49:13 +0000511 scan_event_queue(1); /* Eat events up to cmd-. */
Jack Jansene3ae0df1997-06-03 15:28:29 +0000512 interrupted = 0;
Jack Jansen36ed5061997-06-20 16:18:15 +0000513 PyErr_SetNone(PyExc_KeyboardInterrupt);
514 return -1;
Jack Jansene3ae0df1997-06-03 15:28:29 +0000515 }
516 }
Jack Jansenee23d6e1995-01-27 14:43:25 +0000517 }
518 return 0;
519}
520
Jack Jansen36ed5061997-06-20 16:18:15 +0000521int
522PyOS_InterruptOccurred()
523{
524 scan_event_queue(1);
525 return interrupted;
526}
Jack Jansenee23d6e1995-01-27 14:43:25 +0000527/* Check whether we are in the foreground */
Jack Jansen9ae898b2000-07-11 21:16:03 +0000528static int
529PyMac_InForeground(void)
Jack Jansenee23d6e1995-01-27 14:43:25 +0000530{
531 static ProcessSerialNumber ours;
532 static inited;
533 ProcessSerialNumber curfg;
534 Boolean eq;
535
Jack Jansene3ae0df1997-06-03 15:28:29 +0000536 if ( inited == 0 ) {
Jack Jansenee23d6e1995-01-27 14:43:25 +0000537 (void)GetCurrentProcess(&ours);
Jack Jansene3ae0df1997-06-03 15:28:29 +0000538 inited = 1;
539 }
Jack Jansenee23d6e1995-01-27 14:43:25 +0000540 if ( GetFrontProcess(&curfg) < 0 )
541 eq = 1;
542 else if ( SameProcess(&ours, &curfg, &eq) < 0 )
543 eq = 1;
544 return (int)eq;
545
546}
547
Jack Jansen36ed5061997-06-20 16:18:15 +0000548int
549PyMac_SetEventHandler(PyObject *evh)
550{
551 if ( evh && python_event_handler ) {
552 PyErr_SetString(PyExc_RuntimeError, "Python event handler already set");
553 return 0;
554 }
555 if ( python_event_handler )
556 Py_DECREF(python_event_handler);
557 if ( evh )
558 Py_INCREF(evh);
559 python_event_handler = evh;
560 return 1;
561}
562
Jack Jansenf93c72a1994-12-14 14:07:50 +0000563/*
Jack Jansena76382a1995-02-02 14:25:56 +0000564** Handle an event, either one found in the mainloop eventhandler or
565** one passed back from the python program.
566*/
567void
Jack Jansen36ed5061997-06-20 16:18:15 +0000568PyMac_HandleEventIntern(evp)
Jack Jansena76382a1995-02-02 14:25:56 +0000569 EventRecord *evp;
570{
Jack Jansen74a1e632000-07-14 22:37:27 +0000571#if !TARGET_API_MAC_CARBON
Jack Jansen0c968871997-08-26 13:20:34 +0000572 if ( evp->what == mouseDown ) {
573 WindowPtr wp;
574
575 if ( FindWindow(evp->where, &wp) == inSysWindow ) {
576 SystemClick(evp, wp);
577 return;
578 }
579 }
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000580#endif
Jack Jansena76382a1995-02-02 14:25:56 +0000581#ifdef __MWERKS__
Jack Jansen38e97661995-11-10 14:53:00 +0000582 {
583 int siouxdidit;
584
585 /* If SIOUX wants it we're done */
586 siouxdidit = SIOUXHandleOneEvent(evp);
587 if ( siouxdidit )
588 return;
589 }
Jack Jansena76382a1995-02-02 14:25:56 +0000590#else
Jack Jansen0c968871997-08-26 13:20:34 +0000591 /* Other compilers are just unlucky... */
Jack Jansena76382a1995-02-02 14:25:56 +0000592#endif /* !__MWERKS__ */
Jack Jansen36ed5061997-06-20 16:18:15 +0000593}
594
595/*
596** Handle an event, either through HandleEvent or by passing it to the Python
597** event handler.
598*/
599int
600PyMac_HandleEvent(evp)
601 EventRecord *evp;
602{
603 PyObject *rv;
604
605 if ( python_event_handler ) {
606 rv = PyObject_CallFunction(python_event_handler, "(O&)",
607 PyMac_BuildEventRecord, evp);
608 if ( rv )
609 Py_DECREF(rv);
610 else
611 return -1; /* Propagate exception */
612 } else {
613 PyMac_HandleEventIntern(evp);
614 }
615 return 0;
Jack Jansena76382a1995-02-02 14:25:56 +0000616}
617
618/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000619** Yield the CPU to other tasks without processing events.
Jack Jansene8e8ae01995-01-26 16:36:45 +0000620*/
Jack Jansen2d1306b2000-04-07 09:10:49 +0000621int
Jack Jansene3ae0df1997-06-03 15:28:29 +0000622PyMac_DoYield(int maxsleep, int maycallpython)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000623{
624 EventRecord ev;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000625 int gotone;
Jack Jansene3ae0df1997-06-03 15:28:29 +0000626 long latest_time_ready;
Jack Jansen36ed5061997-06-20 16:18:15 +0000627 static int in_here = 0;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000628
Jack Jansen36ed5061997-06-20 16:18:15 +0000629 in_here++;
Jack Jansene3ae0df1997-06-03 15:28:29 +0000630 /*
631 ** First check for interrupts, if wanted.
632 ** This sets a flag that will be picked up at an appropriate
633 ** moment in the mainloop.
634 */
635 if (schedparams.check_interrupt)
Jack Jansenee23d6e1995-01-27 14:43:25 +0000636 scan_event_queue(0);
Jack Jansene3ae0df1997-06-03 15:28:29 +0000637
638 /* XXXX Implementing an idle routine goes here */
Jack Jansene8e8ae01995-01-26 16:36:45 +0000639
Jack Jansene3ae0df1997-06-03 15:28:29 +0000640 /*
641 ** Check which of the eventloop cases we have:
642 ** - process events
643 ** - don't process events but do yield
644 ** - do neither
645 */
Jack Jansen36ed5061997-06-20 16:18:15 +0000646 if( in_here > 1 || !schedparams.process_events ||
647 (python_event_handler && !maycallpython) ) {
Jack Jansen74a1e632000-07-14 22:37:27 +0000648#if !TARGET_API_MAC_CARBON
Jack Jansene3ae0df1997-06-03 15:28:29 +0000649 if ( maxsleep >= 0 ) {
Jack Jansene8e8ae01995-01-26 16:36:45 +0000650 SystemTask();
Jack Jansene3ae0df1997-06-03 15:28:29 +0000651 }
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000652#endif
Jack Jansene3ae0df1997-06-03 15:28:29 +0000653 } else {
654 latest_time_ready = LMGetTicks() + maxsleep;
Jack Jansen2d1306b2000-04-07 09:10:49 +0000655 do {
Jack Jansen0c968871997-08-26 13:20:34 +0000656 /* XXXX Hack by Jack.
657 ** In time.sleep() you can click to another application
658 ** once only. If you come back to Python you cannot get away
659 ** again.
660 **/
Jack Jansen36ed5061997-06-20 16:18:15 +0000661 gotone = WaitNextEvent(schedparams.process_events, &ev, maxsleep, NULL);
Jack Jansene3ae0df1997-06-03 15:28:29 +0000662 /* Get out quickly if nothing interesting is happening */
663 if ( !gotone || ev.what == nullEvent )
664 break;
Jack Jansen36ed5061997-06-20 16:18:15 +0000665 if ( PyMac_HandleEvent(&ev) < 0 ) {
666 in_here--;
667 return -1;
668 }
Jack Jansene3ae0df1997-06-03 15:28:29 +0000669 maxsleep = latest_time_ready - LMGetTicks();
Jack Jansen2d1306b2000-04-07 09:10:49 +0000670 } while ( maxsleep > 0 );
Jack Jansenf93c72a1994-12-14 14:07:50 +0000671 }
Jack Jansen36ed5061997-06-20 16:18:15 +0000672 in_here--;
673 return 0;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000674}
675
676/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000677** Process events and/or yield the CPU to other tasks if opportune
Jack Jansene8e8ae01995-01-26 16:36:45 +0000678*/
Jack Jansen36ed5061997-06-20 16:18:15 +0000679int
Jack Jansene8e8ae01995-01-26 16:36:45 +0000680PyMac_Yield() {
Jack Jansene3ae0df1997-06-03 15:28:29 +0000681 unsigned long maxsleep;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000682
Jack Jansene3ae0df1997-06-03 15:28:29 +0000683 if( PyMac_InForeground() )
684 maxsleep = 0;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000685 else
Jack Jansene3ae0df1997-06-03 15:28:29 +0000686 maxsleep = schedparams.bg_yield;
687
Jack Jansen36ed5061997-06-20 16:18:15 +0000688 return PyMac_DoYield(maxsleep, 1);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000689}
690
691/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000692** Return current scheduler parameters
Jack Jansene8e8ae01995-01-26 16:36:45 +0000693*/
Jack Jansene3ae0df1997-06-03 15:28:29 +0000694void
695PyMac_GetSchedParams(PyMacSchedParams *sp)
Jack Jansene8e8ae01995-01-26 16:36:45 +0000696{
Jack Jansene3ae0df1997-06-03 15:28:29 +0000697 sp->check_interrupt = schedparams.check_interrupt;
698 sp->process_events = schedparams.process_events;
699 sp->besocial = schedparams.besocial;
700 sp->check_interval = schedparams.check_interval / 60.0;
701 sp->bg_yield = schedparams.bg_yield / 60.0;
Jack Jansenf93c72a1994-12-14 14:07:50 +0000702}
Jack Jansenf6865f71996-09-04 15:24:59 +0000703
Jack Jansen74162f31995-02-15 22:58:33 +0000704/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000705** Set current scheduler parameters
706*/
707void
708PyMac_SetSchedParams(PyMacSchedParams *sp)
709{
710 schedparams.check_interrupt = sp->check_interrupt;
711 schedparams.process_events = sp->process_events;
712 schedparams.besocial = sp->besocial;
713 schedparams.check_interval = (unsigned long)(sp->check_interval*60);
714 schedparams.bg_yield = (unsigned long)(sp->bg_yield*60);
715 if ( schedparams.check_interrupt || schedparams.process_events ||
716 schedparams.besocial )
717 schedparams.enabled = 1;
718 else
719 schedparams.enabled = 0;
720 schedparams.next_check = 0; /* Check immedeately */
721}
Jack Jansencaa7c461997-06-12 10:49:13 +0000722
Jack Jansene3ae0df1997-06-03 15:28:29 +0000723/*
Jack Jansen3469e991996-09-06 00:30:45 +0000724** Install our menu bar.
725*/
726void
727PyMac_InitMenuBar()
728{
Jack Jansen3469e991996-09-06 00:30:45 +0000729 MenuHandle applemenu;
730
Jack Jansencaa7c461997-06-12 10:49:13 +0000731 if ( (sioux_mbar=GetMenuBar()) == NULL ) {
732 /* Sioux menu not installed yet. Do so */
733 SIOUXSetupMenus();
734 if ( (sioux_mbar=GetMenuBar()) == NULL )
735 return;
736 }
Jack Jansen08c3be31997-04-08 15:27:00 +0000737 if ( (applemenu=GetMenuHandle(SIOUX_APPLEID)) == NULL ) return;
Jack Jansen3469e991996-09-06 00:30:45 +0000738 SetMenuItemText(applemenu, 1, "\pAbout Python...");
739}
740
741/*
Jack Jansencaa7c461997-06-12 10:49:13 +0000742** Restore sioux menu bar
743*/
744void
745PyMac_RestoreMenuBar()
746{
Jack Janseneda78631997-06-12 15:29:46 +0000747 if ( sioux_mbar ) {
Jack Jansencaa7c461997-06-12 10:49:13 +0000748 SetMenuBar(sioux_mbar);
Jack Janseneda78631997-06-12 15:29:46 +0000749 DrawMenuBar();
Jack Jansenefaada71998-02-20 16:03:15 +0000750 } else
751 PyMac_InitMenuBar();
Jack Jansencaa7c461997-06-12 10:49:13 +0000752}
753
754
755/*
Jack Jansen3469e991996-09-06 00:30:45 +0000756** Our replacement about box
757*/
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000758
759#include "patchlevel.h"
760
Jack Jansen3469e991996-09-06 00:30:45 +0000761void
762SIOUXDoAboutBox(void)
763{
764 DialogPtr theDialog;
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000765 WindowPtr theWindow;
Jack Jansen3469e991996-09-06 00:30:45 +0000766 short item;
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000767 short fontID;
Jack Jansen3469e991996-09-06 00:30:45 +0000768
769 if( (theDialog = GetNewDialog(ABOUT_ID, NULL, (WindowPtr)-1)) == NULL )
770 return;
Jack Jansend617c571996-09-22 22:14:30 +0000771 theWindow = GetDialogWindow(theDialog);
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000772 SetPortWindowPort(theWindow);
773 GetFNum("\pPython-Sans", &fontID);
774 if (fontID == 0)
775 fontID = kFontIDGeneva;
776 TextFont(fontID);
777 TextSize(9);
778 ParamText(Pstring(PATCHLEVEL), "\p", "\p", "\p");
Jack Jansend617c571996-09-22 22:14:30 +0000779 ShowWindow(theWindow);
Jack Jansen3469e991996-09-06 00:30:45 +0000780 ModalDialog(NULL, &item);
781 DisposeDialog(theDialog);
782}
783
Jack Janseneda78631997-06-12 15:29:46 +0000784#if 0
785int
786PyMac_FileExists(char *name)
787{
788 FSSpec fss;
789
790 if ( FSMakeFSSpec(0, 0, Pstring(name), &fss) == noErr )
791 return 1;
792 return 0;
793}
794#endif
795
796/*
Jack Jansen3ec804a1995-02-20 15:56:10 +0000797** Helper routine for GetDirectory
798*/
Guido van Rossum24a45e31995-02-20 23:45:53 +0000799static pascal short
Jack Jansen819f1771995-08-14 12:35:10 +0000800myhook_proc(short item, DialogPtr theDialog, struct hook_args *dataptr)
Jack Jansen3ec804a1995-02-20 15:56:10 +0000801{
Jack Jansen819f1771995-08-14 12:35:10 +0000802 if ( item == sfHookFirstCall && dataptr->prompt) {
803 Handle prompth;
804 short type;
805 Rect rect;
806
807 GetDialogItem(theDialog, PROMPT_ITEM, &type, &prompth, &rect);
808 if ( prompth )
809 SetDialogItemText(prompth, (unsigned char *)dataptr->prompt);
810 } else
Jack Jansen3ec804a1995-02-20 15:56:10 +0000811 if ( item == SELECTCUR_ITEM ) {
812 item = sfItemCancelButton;
Jack Jansen819f1771995-08-14 12:35:10 +0000813 dataptr->selectcur_hit = 1;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000814 }
815 return item;
816}
Jack Jansen74a1e632000-07-14 22:37:27 +0000817#if !TARGET_API_MAC_CARBON
Jack Jansen3ec804a1995-02-20 15:56:10 +0000818/*
819** Ask the user for a directory. I still can't understand
820** why Apple doesn't provide a standard solution for this...
821*/
822int
Jack Jansen819f1771995-08-14 12:35:10 +0000823PyMac_GetDirectory(dirfss, prompt)
Jack Jansen3ec804a1995-02-20 15:56:10 +0000824 FSSpec *dirfss;
Jack Jansen819f1771995-08-14 12:35:10 +0000825 char *prompt;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000826{
827 static SFTypeList list = {'fldr', 0, 0, 0};
828 static Point where = {-1, -1};
Jack Jansen3ec804a1995-02-20 15:56:10 +0000829 StandardFileReply reply;
Jack Jansen819f1771995-08-14 12:35:10 +0000830 struct hook_args hook_args;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000831
832 if ( !upp_inited ) {
833 myhook_upp = NewDlgHookYDProc(myhook_proc);
834 upp_inited = 1;
835 }
Jack Jansen819f1771995-08-14 12:35:10 +0000836 if ( prompt && *prompt )
837 hook_args.prompt = (char *)Pstring(prompt);
838 else
839 hook_args.prompt = NULL;
840 hook_args.selectcur_hit = 0;
Guido van Rossum24a45e31995-02-20 23:45:53 +0000841 CustomGetFile((FileFilterYDUPP)0, 1, list, &reply, GETDIR_ID, where, myhook_upp,
Jack Jansen819f1771995-08-14 12:35:10 +0000842 NULL, NULL, NULL, (void *)&hook_args);
Jack Jansen3ec804a1995-02-20 15:56:10 +0000843
844 reply.sfFile.name[0] = 0;
845 if( FSMakeFSSpec(reply.sfFile.vRefNum, reply.sfFile.parID, reply.sfFile.name, dirfss) )
846 return 0;
Jack Jansen819f1771995-08-14 12:35:10 +0000847 return hook_args.selectcur_hit;
848}
849
850/*
851** Slightly extended StandardGetFile: accepts a prompt */
852void PyMac_PromptGetFile(short numTypes, ConstSFTypeListPtr typeList,
853 StandardFileReply *reply, char *prompt)
854{
855 static Point where = {-1, -1};
856 struct hook_args hook_args;
857
858 if ( !upp_inited ) {
859 myhook_upp = NewDlgHookYDProc(myhook_proc);
860 upp_inited = 1;
861 }
862 if ( prompt && *prompt )
863 hook_args.prompt = (char *)Pstring(prompt);
864 else
865 hook_args.prompt = NULL;
866 hook_args.selectcur_hit = 0;
867 CustomGetFile((FileFilterYDUPP)0, numTypes, typeList, reply, GETFILEPROMPT_ID, where,
868 myhook_upp, NULL, NULL, NULL, (void *)&hook_args);
Jack Jansen3ec804a1995-02-20 15:56:10 +0000869}
Jack Jansenbb7e2132000-07-14 22:15:24 +0000870#endif /* TARGET_API_MAC_CARBON */
Jack Jansen5f653091995-01-18 13:53:49 +0000871
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000872/* Convert a 4-char string object argument to an OSType value */
Jack Jansen5f653091995-01-18 13:53:49 +0000873int
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000874PyMac_GetOSType(PyObject *v, OSType *pr)
Jack Jansen5f653091995-01-18 13:53:49 +0000875{
876 if (!PyString_Check(v) || PyString_Size(v) != 4) {
877 PyErr_SetString(PyExc_TypeError,
878 "OSType arg must be string of 4 chars");
879 return 0;
880 }
881 memcpy((char *)pr, PyString_AsString(v), 4);
882 return 1;
883}
884
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000885/* Convert an OSType value to a 4-char string object */
886PyObject *
887PyMac_BuildOSType(OSType t)
888{
889 return PyString_FromStringAndSize((char *)&t, 4);
890}
891
Jack Jansend1f06311996-08-01 15:23:54 +0000892/* Convert an NumVersion value to a 4-element tuple */
893PyObject *
894PyMac_BuildNumVersion(NumVersion t)
895{
896 return Py_BuildValue("(hhhh)", t.majorRev, t.minorAndBugRev, t.stage, t.nonRelRev);
897}
898
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000899
900/* Convert a Python string object to a Str255 */
Jack Jansen5f653091995-01-18 13:53:49 +0000901int
Guido van Rossum8f691791995-01-18 23:57:26 +0000902PyMac_GetStr255(PyObject *v, Str255 pbuf)
Jack Jansen5f653091995-01-18 13:53:49 +0000903{
904 int len;
905 if (!PyString_Check(v) || (len = PyString_Size(v)) > 255) {
906 PyErr_SetString(PyExc_TypeError,
907 "Str255 arg must be string of at most 255 chars");
908 return 0;
909 }
910 pbuf[0] = len;
911 memcpy((char *)(pbuf+1), PyString_AsString(v), len);
912 return 1;
913}
914
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000915/* Convert a Str255 to a Python string object */
916PyObject *
917PyMac_BuildStr255(Str255 s)
918{
Jack Jansenb734ade1999-12-17 17:15:50 +0000919 if ( s == NULL ) {
920 PyErr_SetString(PyExc_SystemError, "Str255 pointer is NULL");
921 return NULL;
922 }
923 return PyString_FromStringAndSize((char *)&s[1], (int)s[0]);
924}
925
926PyObject *
927PyMac_BuildOptStr255(Str255 s)
928{
929 if ( s == NULL ) {
930 Py_INCREF(Py_None);
931 return Py_None;
932 }
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000933 return PyString_FromStringAndSize((char *)&s[1], (int)s[0]);
934}
935
936
Jack Jansen5f653091995-01-18 13:53:49 +0000937/*
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000938** Convert a Python object to an FSSpec.
939** The object may either be a full pathname or a triple
940** (vrefnum, dirid, path).
Jack Jansen5f653091995-01-18 13:53:49 +0000941** NOTE: This routine will fail on pre-sys7 machines.
942** The caller is responsible for not calling this routine
943** in those cases (which is fine, since everyone calling
944** this is probably sys7 dependent anyway).
945*/
946int
Guido van Rossum8f691791995-01-18 23:57:26 +0000947PyMac_GetFSSpec(PyObject *v, FSSpec *fs)
Jack Jansen5f653091995-01-18 13:53:49 +0000948{
949 Str255 path;
950 short refnum;
951 long parid;
952 OSErr err;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000953 FSSpec *fs2;
Jack Jansen5f653091995-01-18 13:53:49 +0000954
Jack Jansene8e8ae01995-01-26 16:36:45 +0000955 /* first check whether it already is an FSSpec */
956 fs2 = mfs_GetFSSpecFSSpec(v);
957 if ( fs2 ) {
Jack Jansen3ec804a1995-02-20 15:56:10 +0000958 (void)FSMakeFSSpec(fs2->vRefNum, fs2->parID, fs2->name, fs);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000959 return 1;
960 }
Jack Jansen5f653091995-01-18 13:53:49 +0000961 if ( PyString_Check(v) ) {
962 /* It's a pathname */
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000963 if( !PyArg_Parse(v, "O&", PyMac_GetStr255, &path) )
Jack Jansen5f653091995-01-18 13:53:49 +0000964 return 0;
Jack Jansen378815c1996-03-06 16:21:34 +0000965 refnum = 0; /* XXXX Should get CurWD here?? */
Jack Jansen5f653091995-01-18 13:53:49 +0000966 parid = 0;
967 } else {
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000968 if( !PyArg_Parse(v, "(hlO&); FSSpec should be fullpath or (vrefnum,dirid,path)",
969 &refnum, &parid, PyMac_GetStr255, &path)) {
Jack Jansen5f653091995-01-18 13:53:49 +0000970 return 0;
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000971 }
Jack Jansen5f653091995-01-18 13:53:49 +0000972 }
973 err = FSMakeFSSpec(refnum, parid, path, fs);
974 if ( err && err != fnfErr ) {
Jack Jansen3d757542000-01-24 09:56:06 +0000975 PyMac_Error(err);
Jack Jansen5f653091995-01-18 13:53:49 +0000976 return 0;
977 }
978 return 1;
979}
980
Jack Jansen8bb573e1999-12-12 21:37:14 +0000981/* Convert FSSpec to PyObject */
982PyObject *PyMac_BuildFSSpec(FSSpec *v)
983{
984 return newmfssobject(v);
985}
Guido van Rossum8f691791995-01-18 23:57:26 +0000986
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000987/* Convert a Python object to a Rect.
Guido van Rossum5279ec61995-01-26 22:56:59 +0000988 The object must be a (left, top, right, bottom) tuple.
989 (This differs from the order in the struct but is consistent with
990 the arguments to SetRect(), and also with STDWIN). */
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000991int
992PyMac_GetRect(PyObject *v, Rect *r)
Guido van Rossum8f691791995-01-18 23:57:26 +0000993{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000994 return PyArg_Parse(v, "(hhhh)", &r->left, &r->top, &r->right, &r->bottom);
Guido van Rossum8f691791995-01-18 23:57:26 +0000995}
Guido van Rossumb3404661995-01-22 18:36:13 +0000996
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000997/* Convert a Rect to a Python object */
Guido van Rossumb3404661995-01-22 18:36:13 +0000998PyObject *
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000999PyMac_BuildRect(Rect *r)
Guido van Rossumb3404661995-01-22 18:36:13 +00001000{
Guido van Rossum5279ec61995-01-26 22:56:59 +00001001 return Py_BuildValue("(hhhh)", r->left, r->top, r->right, r->bottom);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001002}
1003
1004
1005/* Convert a Python object to a Point.
Guido van Rossum5279ec61995-01-26 22:56:59 +00001006 The object must be a (h, v) tuple.
1007 (This differs from the order in the struct but is consistent with
1008 the arguments to SetPoint(), and also with STDWIN). */
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001009int
1010PyMac_GetPoint(PyObject *v, Point *p)
1011{
Guido van Rossum5279ec61995-01-26 22:56:59 +00001012 return PyArg_Parse(v, "(hh)", &p->h, &p->v);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001013}
1014
1015/* Convert a Point to a Python object */
1016PyObject *
1017PyMac_BuildPoint(Point p)
1018{
Guido van Rossum5279ec61995-01-26 22:56:59 +00001019 return Py_BuildValue("(hh)", p.h, p.v);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001020}
1021
1022
1023/* Convert a Python object to an EventRecord.
1024 The object must be a (what, message, when, (v, h), modifiers) tuple. */
1025int
1026PyMac_GetEventRecord(PyObject *v, EventRecord *e)
1027{
1028 return PyArg_Parse(v, "(hll(hh)h)",
1029 &e->what,
1030 &e->message,
1031 &e->when,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001032 &e->where.h,
Guido van Rossum5279ec61995-01-26 22:56:59 +00001033 &e->where.v,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001034 &e->modifiers);
1035}
1036
1037/* Convert a Rect to an EventRecord object */
1038PyObject *
1039PyMac_BuildEventRecord(EventRecord *e)
1040{
1041 return Py_BuildValue("(hll(hh)h)",
1042 e->what,
1043 e->message,
1044 e->when,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001045 e->where.h,
Guido van Rossum5279ec61995-01-26 22:56:59 +00001046 e->where.v,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001047 e->modifiers);
Guido van Rossumb3404661995-01-22 18:36:13 +00001048}
Jack Jansenfa4d5d01995-11-15 15:19:29 +00001049
1050/* Convert Python object to Fixed */
1051int
1052PyMac_GetFixed(PyObject *v, Fixed *f)
1053{
1054 double d;
1055
1056 if( !PyArg_Parse(v, "d", &d))
1057 return 0;
1058 *f = (Fixed)(d * 0x10000);
Jack Jansen31dd5c01996-05-31 13:01:39 +00001059 return 1;
Jack Jansenfa4d5d01995-11-15 15:19:29 +00001060}
1061
1062/* Convert a Point to a Python object */
1063PyObject *
1064PyMac_BuildFixed(Fixed f)
1065{
1066 double d;
1067
1068 d = f;
1069 d = d / 0x10000;
1070 return Py_BuildValue("d", d);
1071}
1072
Jack Jansend58cd631998-04-21 15:24:39 +00001073/* Convert wide to/from Python int or (hi, lo) tuple. XXXX Should use Python longs */
1074int
1075PyMac_Getwide(PyObject *v, wide *rv)
1076{
1077 if (PyInt_Check(v)) {
1078 rv->hi = 0;
1079 rv->lo = PyInt_AsLong(v);
1080 if( rv->lo & 0x80000000 )
1081 rv->hi = -1;
1082 return 1;
1083 }
1084 return PyArg_Parse(v, "(ll)", &rv->hi, &rv->lo);
1085}
1086
1087
1088PyObject *
Jack Jansenbbf4be21998-04-23 13:20:17 +00001089PyMac_Buildwide(wide *w)
Jack Jansend58cd631998-04-21 15:24:39 +00001090{
Jack Jansenbbf4be21998-04-23 13:20:17 +00001091 if ( (w->hi == 0 && (w->lo & 0x80000000) == 0) ||
1092 (w->hi == -1 && (w->lo & 0x80000000) ) )
1093 return PyInt_FromLong(w->lo);
1094 return Py_BuildValue("(ll)", w->hi, w->lo);
Jack Jansend58cd631998-04-21 15:24:39 +00001095}