blob: 8fdbc23acba6a8f80177e490dcdffff9fc843b76 [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
Jack Jansen6ba34aa2001-01-11 23:03:56 +0000290#if !TARGET_API_MAC_CARBON
Jack Jansena39f1b01997-05-23 15:35:14 +0000291/*
292** Replacement routines for the PLstr... functions so we don't need
Jack Jansen6ba34aa2001-01-11 23:03:56 +0000293** StdCLib.
Jack Jansena39f1b01997-05-23 15:35:14 +0000294*/
Jack Jansen8bb573e1999-12-12 21:37:14 +0000295pascal void
Jack Jansen9ae898b2000-07-11 21:16:03 +0000296PLstrcpy(unsigned char *to, unsigned char *fr)
Jack Jansena39f1b01997-05-23 15:35:14 +0000297{
298 memcpy(to, fr, fr[0]+1);
299}
300
Jack Jansen8bb573e1999-12-12 21:37:14 +0000301pascal int
Jack Jansen9ae898b2000-07-11 21:16:03 +0000302PLstrcmp(unsigned char *s1, unsigned char *s2)
Jack Jansena39f1b01997-05-23 15:35:14 +0000303{
304 int res;
305 int l = s1[0] < s2[0] ? s1[0] : s2[0];
306
307 res = memcmp(s1+1, s2+1, l);
308 if ( res != 0 )
309 return res;
310
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000311 if ( s1[0] < s2[0] )
Jack Jansena39f1b01997-05-23 15:35:14 +0000312 return -1;
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000313 else if ( s1[0] > s2[0] )
Jack Jansena39f1b01997-05-23 15:35:14 +0000314 return 1;
315 else
316 return 0;
317}
318
Jack Jansen8bb573e1999-12-12 21:37:14 +0000319pascal unsigned char *
Jack Jansen9ae898b2000-07-11 21:16:03 +0000320PLstrrchr(unsigned char *str, unsigned char chr)
Jack Jansena39f1b01997-05-23 15:35:14 +0000321{
322 unsigned char *ptr = 0;
323 unsigned char *p;
324
325 for(p=str+1; p<str+str[0]; p++)
326 if ( *p == chr )
327 ptr = p;
328 return ptr;
329}
330
Jack Jansen6ba34aa2001-01-11 23:03:56 +0000331#endif /* !TARGET_API_MAC_CARBON */
Jack Jansena39f1b01997-05-23 15:35:14 +0000332#endif /* USE_GUSI */
Jack Jansen378815c1996-03-06 16:21:34 +0000333
Jack Jansen819f1771995-08-14 12:35:10 +0000334
Jack Jansen5f653091995-01-18 13:53:49 +0000335/* Convert C to Pascal string. Returns pointer to static buffer. */
336unsigned char *
337Pstring(char *str)
338{
339 static Str255 buf;
340 int len;
341
342 len = strlen(str);
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000343 if (len > 255)
344 len = 255;
Jack Jansen5f653091995-01-18 13:53:49 +0000345 buf[0] = (unsigned char)len;
346 strncpy((char *)buf+1, str, len);
347 return buf;
348}
349
Jack Jansen91faef82001-01-09 22:24:56 +0000350#if !TARGET_API_MAC_CARBON
Jack Jansen5afad832000-12-12 22:12:14 +0000351void
352c2pstrcpy(unsigned char *dst, const char *src)
353{
354 int len;
355
356 len = strlen(src);
357 if ( len > 255 ) len = 255;
358 strncpy((char *)dst+1, src, len);
359 dst[0] = len;
360}
Jack Jansen6ba34aa2001-01-11 23:03:56 +0000361#endif /* !TARGET_API_MAC_CARBON */
Jack Jansen5afad832000-12-12 22:12:14 +0000362
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000363/* Like strerror() but for Mac OS error numbers */
364char *PyMac_StrError(int err)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000365{
366 static char buf[256];
367 Handle h;
368 char *str;
369
370 h = GetResource('Estr', err);
371 if ( h ) {
372 HLock(h);
373 str = (char *)*h;
374 memcpy(buf, str+1, (unsigned char)str[0]);
Guido van Rossumcc9bc8f1995-02-13 16:17:03 +0000375 buf[(unsigned char)str[0]] = '\0';
Jack Jansenf93c72a1994-12-14 14:07:50 +0000376 HUnlock(h);
377 ReleaseResource(h);
378 } else {
379 sprintf(buf, "Mac OS error code %d", err);
380 }
381 return buf;
382}
383
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000384/* Exception object shared by all Mac specific modules for Mac OS errors */
385PyObject *PyMac_OSErrException;
386
387/* Initialize and return PyMac_OSErrException */
388PyObject *
389PyMac_GetOSErrException()
390{
391 if (PyMac_OSErrException == NULL)
392 PyMac_OSErrException = PyString_FromString("Mac OS Error");
393 return PyMac_OSErrException;
394}
395
Jack Jansenf93c72a1994-12-14 14:07:50 +0000396/* Set a MAC-specific error from errno, and return NULL; return None if no error */
397PyObject *
Guido van Rossumfffb8bb1995-01-12 12:37:24 +0000398PyErr_Mac(PyObject *eobj, int err)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000399{
400 char *msg;
401 PyObject *v;
Jack Jansenf93c72a1994-12-14 14:07:50 +0000402
Guido van Rossum8f691791995-01-18 23:57:26 +0000403 if (err == 0 && !PyErr_Occurred()) {
Jack Jansenf93c72a1994-12-14 14:07:50 +0000404 Py_INCREF(Py_None);
405 return Py_None;
406 }
Guido van Rossum8f691791995-01-18 23:57:26 +0000407 if (err == -1 && PyErr_Occurred())
408 return NULL;
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000409 msg = PyMac_StrError(err);
Jack Jansenf93c72a1994-12-14 14:07:50 +0000410 v = Py_BuildValue("(is)", err, msg);
411 PyErr_SetObject(eobj, v);
412 Py_DECREF(v);
413 return NULL;
414}
415
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000416/* Call PyErr_Mac with PyMac_OSErrException */
417PyObject *
418PyMac_Error(OSErr err)
419{
420 return PyErr_Mac(PyMac_GetOSErrException(), err);
421}
422
Jack Jansen1ed95291996-07-22 15:25:10 +0000423#ifdef USE_STACKCHECK
424/* Check for stack overflow */
425int
426PyOS_CheckStack()
427{
Jack Jansen14a91712000-08-25 21:57:23 +0000428 char here;
429 static char *sentinel = 0;
Jack Jansen53bafd92000-09-08 22:05:48 +0000430 static PyThreadState *thread_for_sentinel = 0;
Jack Jansen1ed95291996-07-22 15:25:10 +0000431
Jack Jansen14a91712000-08-25 21:57:23 +0000432 if ( sentinel == 0 ) {
433 sentinel = &here - StackSpace() + MINIMUM_STACK_SIZE;
434 }
Jack Jansen53bafd92000-09-08 22:05:48 +0000435 if ( thread_for_sentinel == 0 ) {
436 thread_for_sentinel = PyThreadState_Get();
437 }
438 if ( &here < sentinel ) {
439 if (thread_for_sentinel == PyThreadState_Get()) {
440 return -1;
441#if 0
442 } else {
443 /* Else we are unsure... */
444 fprintf(stderr, "Stackcheck in other thread (was %x now %x)\n", thread_for_sentinel,PyThreadState_Get());
445#endif
446 }
447 }
Jack Jansen1ed95291996-07-22 15:25:10 +0000448 return 0;
449}
450#endif /* USE_STACKCHECK */
451
Jack Jansenee23d6e1995-01-27 14:43:25 +0000452/* The catcher routine (which may not be used for all compilers) */
453static RETSIGTYPE
454intcatcher(sig)
455 int sig;
456{
457 interrupted = 1;
458 signal(SIGINT, intcatcher);
459}
460
461void
462PyOS_InitInterrupts()
463{
464 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
465 signal(SIGINT, intcatcher);
466}
467
Jack Jansena8441de1997-08-08 14:57:37 +0000468void
469PyOS_FiniInterrupts()
470{
471}
472
Jack Jansenee23d6e1995-01-27 14:43:25 +0000473/*
474** This routine scans the event queue looking for cmd-.
475** This is the only way to get an interrupt under THINK (since it
476** doesn't do SIGINT handling), but is also used under MW, when
477** the full-fledged event loop is disabled. This way, we can at least
478** interrupt a runaway python program.
479*/
480static void
481scan_event_queue(flush)
482 int flush;
483{
Jack Jansen74a1e632000-07-14 22:37:27 +0000484#if TARGET_API_MAC_CARBON
Jack Jansend7b68022001-01-12 23:42:28 +0000485 if ( CheckEventQueueForUserCancel() )
486 interrupted = 1;
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000487#else
Jack Jansenee23d6e1995-01-27 14:43:25 +0000488 register EvQElPtr q;
489
Jack Jansenefaada71998-02-20 16:03:15 +0000490 q = (EvQElPtr) LMGetEventQueue()->qHead;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000491
492 for (; q; q = (EvQElPtr)q->qLink) {
493 if (q->evtQWhat == keyDown &&
494 (char)q->evtQMessage == '.' &&
495 (q->evtQModifiers & cmdKey) != 0) {
496 if ( flush )
497 FlushEvents(keyDownMask, 0);
498 interrupted = 1;
499 break;
500 }
501 }
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000502#endif
Jack Jansenee23d6e1995-01-27 14:43:25 +0000503}
504
505int
Jack Jansen36ed5061997-06-20 16:18:15 +0000506PyErr_CheckSignals()
Jack Jansenee23d6e1995-01-27 14:43:25 +0000507{
Jack Jansene3ae0df1997-06-03 15:28:29 +0000508 if (schedparams.enabled) {
509 if ( (unsigned long)LMGetTicks() > schedparams.next_check ) {
Jack Jansen36ed5061997-06-20 16:18:15 +0000510 if ( PyMac_Yield() < 0)
511 return -1;
Jack Jansene3ae0df1997-06-03 15:28:29 +0000512 schedparams.next_check = (unsigned long)LMGetTicks()
513 + schedparams.check_interval;
514 if (interrupted) {
Jack Jansencaa7c461997-06-12 10:49:13 +0000515 scan_event_queue(1); /* Eat events up to cmd-. */
Jack Jansene3ae0df1997-06-03 15:28:29 +0000516 interrupted = 0;
Jack Jansen36ed5061997-06-20 16:18:15 +0000517 PyErr_SetNone(PyExc_KeyboardInterrupt);
518 return -1;
Jack Jansene3ae0df1997-06-03 15:28:29 +0000519 }
520 }
Jack Jansenee23d6e1995-01-27 14:43:25 +0000521 }
522 return 0;
523}
524
Jack Jansen36ed5061997-06-20 16:18:15 +0000525int
526PyOS_InterruptOccurred()
527{
528 scan_event_queue(1);
529 return interrupted;
530}
Jack Jansenee23d6e1995-01-27 14:43:25 +0000531/* Check whether we are in the foreground */
Jack Jansen9ae898b2000-07-11 21:16:03 +0000532static int
533PyMac_InForeground(void)
Jack Jansenee23d6e1995-01-27 14:43:25 +0000534{
535 static ProcessSerialNumber ours;
536 static inited;
537 ProcessSerialNumber curfg;
538 Boolean eq;
539
Jack Jansene3ae0df1997-06-03 15:28:29 +0000540 if ( inited == 0 ) {
Jack Jansenee23d6e1995-01-27 14:43:25 +0000541 (void)GetCurrentProcess(&ours);
Jack Jansene3ae0df1997-06-03 15:28:29 +0000542 inited = 1;
543 }
Jack Jansenee23d6e1995-01-27 14:43:25 +0000544 if ( GetFrontProcess(&curfg) < 0 )
545 eq = 1;
546 else if ( SameProcess(&ours, &curfg, &eq) < 0 )
547 eq = 1;
548 return (int)eq;
549
550}
551
Jack Jansen36ed5061997-06-20 16:18:15 +0000552int
553PyMac_SetEventHandler(PyObject *evh)
554{
555 if ( evh && python_event_handler ) {
556 PyErr_SetString(PyExc_RuntimeError, "Python event handler already set");
557 return 0;
558 }
559 if ( python_event_handler )
560 Py_DECREF(python_event_handler);
561 if ( evh )
562 Py_INCREF(evh);
563 python_event_handler = evh;
564 return 1;
565}
566
Jack Jansenf93c72a1994-12-14 14:07:50 +0000567/*
Jack Jansena76382a1995-02-02 14:25:56 +0000568** Handle an event, either one found in the mainloop eventhandler or
569** one passed back from the python program.
570*/
571void
Jack Jansen36ed5061997-06-20 16:18:15 +0000572PyMac_HandleEventIntern(evp)
Jack Jansena76382a1995-02-02 14:25:56 +0000573 EventRecord *evp;
574{
Jack Jansen74a1e632000-07-14 22:37:27 +0000575#if !TARGET_API_MAC_CARBON
Jack Jansen0c968871997-08-26 13:20:34 +0000576 if ( evp->what == mouseDown ) {
577 WindowPtr wp;
578
579 if ( FindWindow(evp->where, &wp) == inSysWindow ) {
580 SystemClick(evp, wp);
581 return;
582 }
583 }
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000584#endif
Jack Jansena76382a1995-02-02 14:25:56 +0000585#ifdef __MWERKS__
Jack Jansen38e97661995-11-10 14:53:00 +0000586 {
587 int siouxdidit;
588
589 /* If SIOUX wants it we're done */
590 siouxdidit = SIOUXHandleOneEvent(evp);
591 if ( siouxdidit )
592 return;
593 }
Jack Jansena76382a1995-02-02 14:25:56 +0000594#else
Jack Jansen0c968871997-08-26 13:20:34 +0000595 /* Other compilers are just unlucky... */
Jack Jansena76382a1995-02-02 14:25:56 +0000596#endif /* !__MWERKS__ */
Jack Jansen36ed5061997-06-20 16:18:15 +0000597}
598
599/*
600** Handle an event, either through HandleEvent or by passing it to the Python
601** event handler.
602*/
603int
604PyMac_HandleEvent(evp)
605 EventRecord *evp;
606{
607 PyObject *rv;
608
609 if ( python_event_handler ) {
610 rv = PyObject_CallFunction(python_event_handler, "(O&)",
611 PyMac_BuildEventRecord, evp);
612 if ( rv )
613 Py_DECREF(rv);
614 else
615 return -1; /* Propagate exception */
616 } else {
617 PyMac_HandleEventIntern(evp);
618 }
619 return 0;
Jack Jansena76382a1995-02-02 14:25:56 +0000620}
621
622/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000623** Yield the CPU to other tasks without processing events.
Jack Jansene8e8ae01995-01-26 16:36:45 +0000624*/
Jack Jansen2d1306b2000-04-07 09:10:49 +0000625int
Jack Jansene3ae0df1997-06-03 15:28:29 +0000626PyMac_DoYield(int maxsleep, int maycallpython)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000627{
628 EventRecord ev;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000629 int gotone;
Jack Jansene3ae0df1997-06-03 15:28:29 +0000630 long latest_time_ready;
Jack Jansen36ed5061997-06-20 16:18:15 +0000631 static int in_here = 0;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000632
Jack Jansen36ed5061997-06-20 16:18:15 +0000633 in_here++;
Jack Jansene3ae0df1997-06-03 15:28:29 +0000634 /*
635 ** First check for interrupts, if wanted.
636 ** This sets a flag that will be picked up at an appropriate
637 ** moment in the mainloop.
638 */
639 if (schedparams.check_interrupt)
Jack Jansenee23d6e1995-01-27 14:43:25 +0000640 scan_event_queue(0);
Jack Jansene3ae0df1997-06-03 15:28:29 +0000641
642 /* XXXX Implementing an idle routine goes here */
Jack Jansene8e8ae01995-01-26 16:36:45 +0000643
Jack Jansene3ae0df1997-06-03 15:28:29 +0000644 /*
645 ** Check which of the eventloop cases we have:
646 ** - process events
647 ** - don't process events but do yield
648 ** - do neither
649 */
Jack Jansen36ed5061997-06-20 16:18:15 +0000650 if( in_here > 1 || !schedparams.process_events ||
651 (python_event_handler && !maycallpython) ) {
Jack Jansen74a1e632000-07-14 22:37:27 +0000652#if !TARGET_API_MAC_CARBON
Jack Jansene3ae0df1997-06-03 15:28:29 +0000653 if ( maxsleep >= 0 ) {
Jack Jansene8e8ae01995-01-26 16:36:45 +0000654 SystemTask();
Jack Jansene3ae0df1997-06-03 15:28:29 +0000655 }
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000656#endif
Jack Jansene3ae0df1997-06-03 15:28:29 +0000657 } else {
658 latest_time_ready = LMGetTicks() + maxsleep;
Jack Jansen2d1306b2000-04-07 09:10:49 +0000659 do {
Jack Jansen0c968871997-08-26 13:20:34 +0000660 /* XXXX Hack by Jack.
661 ** In time.sleep() you can click to another application
662 ** once only. If you come back to Python you cannot get away
663 ** again.
664 **/
Jack Jansen36ed5061997-06-20 16:18:15 +0000665 gotone = WaitNextEvent(schedparams.process_events, &ev, maxsleep, NULL);
Jack Jansene3ae0df1997-06-03 15:28:29 +0000666 /* Get out quickly if nothing interesting is happening */
667 if ( !gotone || ev.what == nullEvent )
668 break;
Jack Jansen36ed5061997-06-20 16:18:15 +0000669 if ( PyMac_HandleEvent(&ev) < 0 ) {
670 in_here--;
671 return -1;
672 }
Jack Jansene3ae0df1997-06-03 15:28:29 +0000673 maxsleep = latest_time_ready - LMGetTicks();
Jack Jansen2d1306b2000-04-07 09:10:49 +0000674 } while ( maxsleep > 0 );
Jack Jansenf93c72a1994-12-14 14:07:50 +0000675 }
Jack Jansen36ed5061997-06-20 16:18:15 +0000676 in_here--;
677 return 0;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000678}
679
680/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000681** Process events and/or yield the CPU to other tasks if opportune
Jack Jansene8e8ae01995-01-26 16:36:45 +0000682*/
Jack Jansen36ed5061997-06-20 16:18:15 +0000683int
Jack Jansene8e8ae01995-01-26 16:36:45 +0000684PyMac_Yield() {
Jack Jansene3ae0df1997-06-03 15:28:29 +0000685 unsigned long maxsleep;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000686
Jack Jansene3ae0df1997-06-03 15:28:29 +0000687 if( PyMac_InForeground() )
688 maxsleep = 0;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000689 else
Jack Jansene3ae0df1997-06-03 15:28:29 +0000690 maxsleep = schedparams.bg_yield;
691
Jack Jansen36ed5061997-06-20 16:18:15 +0000692 return PyMac_DoYield(maxsleep, 1);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000693}
694
695/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000696** Return current scheduler parameters
Jack Jansene8e8ae01995-01-26 16:36:45 +0000697*/
Jack Jansene3ae0df1997-06-03 15:28:29 +0000698void
699PyMac_GetSchedParams(PyMacSchedParams *sp)
Jack Jansene8e8ae01995-01-26 16:36:45 +0000700{
Jack Jansene3ae0df1997-06-03 15:28:29 +0000701 sp->check_interrupt = schedparams.check_interrupt;
702 sp->process_events = schedparams.process_events;
703 sp->besocial = schedparams.besocial;
704 sp->check_interval = schedparams.check_interval / 60.0;
705 sp->bg_yield = schedparams.bg_yield / 60.0;
Jack Jansenf93c72a1994-12-14 14:07:50 +0000706}
Jack Jansenf6865f71996-09-04 15:24:59 +0000707
Jack Jansen74162f31995-02-15 22:58:33 +0000708/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000709** Set current scheduler parameters
710*/
711void
712PyMac_SetSchedParams(PyMacSchedParams *sp)
713{
714 schedparams.check_interrupt = sp->check_interrupt;
715 schedparams.process_events = sp->process_events;
716 schedparams.besocial = sp->besocial;
717 schedparams.check_interval = (unsigned long)(sp->check_interval*60);
718 schedparams.bg_yield = (unsigned long)(sp->bg_yield*60);
719 if ( schedparams.check_interrupt || schedparams.process_events ||
720 schedparams.besocial )
721 schedparams.enabled = 1;
722 else
723 schedparams.enabled = 0;
724 schedparams.next_check = 0; /* Check immedeately */
725}
Jack Jansencaa7c461997-06-12 10:49:13 +0000726
Jack Jansene3ae0df1997-06-03 15:28:29 +0000727/*
Jack Jansen3469e991996-09-06 00:30:45 +0000728** Install our menu bar.
729*/
730void
731PyMac_InitMenuBar()
732{
Jack Jansen3469e991996-09-06 00:30:45 +0000733 MenuHandle applemenu;
734
Jack Jansencaa7c461997-06-12 10:49:13 +0000735 if ( (sioux_mbar=GetMenuBar()) == NULL ) {
736 /* Sioux menu not installed yet. Do so */
737 SIOUXSetupMenus();
738 if ( (sioux_mbar=GetMenuBar()) == NULL )
739 return;
740 }
Jack Jansen08c3be31997-04-08 15:27:00 +0000741 if ( (applemenu=GetMenuHandle(SIOUX_APPLEID)) == NULL ) return;
Jack Jansen3469e991996-09-06 00:30:45 +0000742 SetMenuItemText(applemenu, 1, "\pAbout Python...");
743}
744
745/*
Jack Jansencaa7c461997-06-12 10:49:13 +0000746** Restore sioux menu bar
747*/
748void
749PyMac_RestoreMenuBar()
750{
Jack Janseneda78631997-06-12 15:29:46 +0000751 if ( sioux_mbar ) {
Jack Jansencaa7c461997-06-12 10:49:13 +0000752 SetMenuBar(sioux_mbar);
Jack Janseneda78631997-06-12 15:29:46 +0000753 DrawMenuBar();
Jack Jansenefaada71998-02-20 16:03:15 +0000754 } else
755 PyMac_InitMenuBar();
Jack Jansencaa7c461997-06-12 10:49:13 +0000756}
757
758
759/*
Jack Jansen3469e991996-09-06 00:30:45 +0000760** Our replacement about box
761*/
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000762
763#include "patchlevel.h"
764
Jack Jansen3469e991996-09-06 00:30:45 +0000765void
766SIOUXDoAboutBox(void)
767{
768 DialogPtr theDialog;
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000769 WindowPtr theWindow;
Jack Jansen3469e991996-09-06 00:30:45 +0000770 short item;
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000771 short fontID;
Jack Jansen3469e991996-09-06 00:30:45 +0000772
773 if( (theDialog = GetNewDialog(ABOUT_ID, NULL, (WindowPtr)-1)) == NULL )
774 return;
Jack Jansend617c571996-09-22 22:14:30 +0000775 theWindow = GetDialogWindow(theDialog);
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000776 SetPortWindowPort(theWindow);
777 GetFNum("\pPython-Sans", &fontID);
778 if (fontID == 0)
779 fontID = kFontIDGeneva;
780 TextFont(fontID);
781 TextSize(9);
782 ParamText(Pstring(PATCHLEVEL), "\p", "\p", "\p");
Jack Jansend617c571996-09-22 22:14:30 +0000783 ShowWindow(theWindow);
Jack Jansen3469e991996-09-06 00:30:45 +0000784 ModalDialog(NULL, &item);
785 DisposeDialog(theDialog);
786}
787
Jack Janseneda78631997-06-12 15:29:46 +0000788#if 0
789int
790PyMac_FileExists(char *name)
791{
792 FSSpec fss;
793
794 if ( FSMakeFSSpec(0, 0, Pstring(name), &fss) == noErr )
795 return 1;
796 return 0;
797}
798#endif
799
800/*
Jack Jansen3ec804a1995-02-20 15:56:10 +0000801** Helper routine for GetDirectory
802*/
Guido van Rossum24a45e31995-02-20 23:45:53 +0000803static pascal short
Jack Jansen819f1771995-08-14 12:35:10 +0000804myhook_proc(short item, DialogPtr theDialog, struct hook_args *dataptr)
Jack Jansen3ec804a1995-02-20 15:56:10 +0000805{
Jack Jansen819f1771995-08-14 12:35:10 +0000806 if ( item == sfHookFirstCall && dataptr->prompt) {
807 Handle prompth;
808 short type;
809 Rect rect;
810
811 GetDialogItem(theDialog, PROMPT_ITEM, &type, &prompth, &rect);
812 if ( prompth )
813 SetDialogItemText(prompth, (unsigned char *)dataptr->prompt);
814 } else
Jack Jansen3ec804a1995-02-20 15:56:10 +0000815 if ( item == SELECTCUR_ITEM ) {
816 item = sfItemCancelButton;
Jack Jansen819f1771995-08-14 12:35:10 +0000817 dataptr->selectcur_hit = 1;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000818 }
819 return item;
820}
Jack Jansen74a1e632000-07-14 22:37:27 +0000821#if !TARGET_API_MAC_CARBON
Jack Jansen3ec804a1995-02-20 15:56:10 +0000822/*
823** Ask the user for a directory. I still can't understand
824** why Apple doesn't provide a standard solution for this...
825*/
826int
Jack Jansen819f1771995-08-14 12:35:10 +0000827PyMac_GetDirectory(dirfss, prompt)
Jack Jansen3ec804a1995-02-20 15:56:10 +0000828 FSSpec *dirfss;
Jack Jansen819f1771995-08-14 12:35:10 +0000829 char *prompt;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000830{
831 static SFTypeList list = {'fldr', 0, 0, 0};
832 static Point where = {-1, -1};
Jack Jansen3ec804a1995-02-20 15:56:10 +0000833 StandardFileReply reply;
Jack Jansen819f1771995-08-14 12:35:10 +0000834 struct hook_args hook_args;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000835
836 if ( !upp_inited ) {
837 myhook_upp = NewDlgHookYDProc(myhook_proc);
838 upp_inited = 1;
839 }
Jack Jansen819f1771995-08-14 12:35:10 +0000840 if ( prompt && *prompt )
841 hook_args.prompt = (char *)Pstring(prompt);
842 else
843 hook_args.prompt = NULL;
844 hook_args.selectcur_hit = 0;
Guido van Rossum24a45e31995-02-20 23:45:53 +0000845 CustomGetFile((FileFilterYDUPP)0, 1, list, &reply, GETDIR_ID, where, myhook_upp,
Jack Jansen819f1771995-08-14 12:35:10 +0000846 NULL, NULL, NULL, (void *)&hook_args);
Jack Jansen3ec804a1995-02-20 15:56:10 +0000847
848 reply.sfFile.name[0] = 0;
849 if( FSMakeFSSpec(reply.sfFile.vRefNum, reply.sfFile.parID, reply.sfFile.name, dirfss) )
850 return 0;
Jack Jansen819f1771995-08-14 12:35:10 +0000851 return hook_args.selectcur_hit;
852}
853
854/*
855** Slightly extended StandardGetFile: accepts a prompt */
856void PyMac_PromptGetFile(short numTypes, ConstSFTypeListPtr typeList,
857 StandardFileReply *reply, char *prompt)
858{
859 static Point where = {-1, -1};
860 struct hook_args hook_args;
861
862 if ( !upp_inited ) {
863 myhook_upp = NewDlgHookYDProc(myhook_proc);
864 upp_inited = 1;
865 }
866 if ( prompt && *prompt )
867 hook_args.prompt = (char *)Pstring(prompt);
868 else
869 hook_args.prompt = NULL;
870 hook_args.selectcur_hit = 0;
871 CustomGetFile((FileFilterYDUPP)0, numTypes, typeList, reply, GETFILEPROMPT_ID, where,
872 myhook_upp, NULL, NULL, NULL, (void *)&hook_args);
Jack Jansen3ec804a1995-02-20 15:56:10 +0000873}
Jack Jansenbb7e2132000-07-14 22:15:24 +0000874#endif /* TARGET_API_MAC_CARBON */
Jack Jansen5f653091995-01-18 13:53:49 +0000875
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000876/* Convert a 4-char string object argument to an OSType value */
Jack Jansen5f653091995-01-18 13:53:49 +0000877int
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000878PyMac_GetOSType(PyObject *v, OSType *pr)
Jack Jansen5f653091995-01-18 13:53:49 +0000879{
880 if (!PyString_Check(v) || PyString_Size(v) != 4) {
881 PyErr_SetString(PyExc_TypeError,
882 "OSType arg must be string of 4 chars");
883 return 0;
884 }
885 memcpy((char *)pr, PyString_AsString(v), 4);
886 return 1;
887}
888
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000889/* Convert an OSType value to a 4-char string object */
890PyObject *
891PyMac_BuildOSType(OSType t)
892{
893 return PyString_FromStringAndSize((char *)&t, 4);
894}
895
Jack Jansend1f06311996-08-01 15:23:54 +0000896/* Convert an NumVersion value to a 4-element tuple */
897PyObject *
898PyMac_BuildNumVersion(NumVersion t)
899{
900 return Py_BuildValue("(hhhh)", t.majorRev, t.minorAndBugRev, t.stage, t.nonRelRev);
901}
902
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000903
904/* Convert a Python string object to a Str255 */
Jack Jansen5f653091995-01-18 13:53:49 +0000905int
Guido van Rossum8f691791995-01-18 23:57:26 +0000906PyMac_GetStr255(PyObject *v, Str255 pbuf)
Jack Jansen5f653091995-01-18 13:53:49 +0000907{
908 int len;
909 if (!PyString_Check(v) || (len = PyString_Size(v)) > 255) {
910 PyErr_SetString(PyExc_TypeError,
911 "Str255 arg must be string of at most 255 chars");
912 return 0;
913 }
914 pbuf[0] = len;
915 memcpy((char *)(pbuf+1), PyString_AsString(v), len);
916 return 1;
917}
918
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000919/* Convert a Str255 to a Python string object */
920PyObject *
921PyMac_BuildStr255(Str255 s)
922{
Jack Jansenb734ade1999-12-17 17:15:50 +0000923 if ( s == NULL ) {
924 PyErr_SetString(PyExc_SystemError, "Str255 pointer is NULL");
925 return NULL;
926 }
927 return PyString_FromStringAndSize((char *)&s[1], (int)s[0]);
928}
929
930PyObject *
931PyMac_BuildOptStr255(Str255 s)
932{
933 if ( s == NULL ) {
934 Py_INCREF(Py_None);
935 return Py_None;
936 }
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000937 return PyString_FromStringAndSize((char *)&s[1], (int)s[0]);
938}
939
940
Jack Jansen5f653091995-01-18 13:53:49 +0000941/*
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000942** Convert a Python object to an FSSpec.
943** The object may either be a full pathname or a triple
944** (vrefnum, dirid, path).
Jack Jansen5f653091995-01-18 13:53:49 +0000945** NOTE: This routine will fail on pre-sys7 machines.
946** The caller is responsible for not calling this routine
947** in those cases (which is fine, since everyone calling
948** this is probably sys7 dependent anyway).
949*/
950int
Guido van Rossum8f691791995-01-18 23:57:26 +0000951PyMac_GetFSSpec(PyObject *v, FSSpec *fs)
Jack Jansen5f653091995-01-18 13:53:49 +0000952{
953 Str255 path;
954 short refnum;
955 long parid;
956 OSErr err;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000957 FSSpec *fs2;
Jack Jansen5f653091995-01-18 13:53:49 +0000958
Jack Jansene8e8ae01995-01-26 16:36:45 +0000959 /* first check whether it already is an FSSpec */
960 fs2 = mfs_GetFSSpecFSSpec(v);
961 if ( fs2 ) {
Jack Jansen3ec804a1995-02-20 15:56:10 +0000962 (void)FSMakeFSSpec(fs2->vRefNum, fs2->parID, fs2->name, fs);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000963 return 1;
964 }
Jack Jansen5f653091995-01-18 13:53:49 +0000965 if ( PyString_Check(v) ) {
966 /* It's a pathname */
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000967 if( !PyArg_Parse(v, "O&", PyMac_GetStr255, &path) )
Jack Jansen5f653091995-01-18 13:53:49 +0000968 return 0;
Jack Jansen378815c1996-03-06 16:21:34 +0000969 refnum = 0; /* XXXX Should get CurWD here?? */
Jack Jansen5f653091995-01-18 13:53:49 +0000970 parid = 0;
971 } else {
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000972 if( !PyArg_Parse(v, "(hlO&); FSSpec should be fullpath or (vrefnum,dirid,path)",
973 &refnum, &parid, PyMac_GetStr255, &path)) {
Jack Jansen5f653091995-01-18 13:53:49 +0000974 return 0;
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000975 }
Jack Jansen5f653091995-01-18 13:53:49 +0000976 }
977 err = FSMakeFSSpec(refnum, parid, path, fs);
978 if ( err && err != fnfErr ) {
Jack Jansen3d757542000-01-24 09:56:06 +0000979 PyMac_Error(err);
Jack Jansen5f653091995-01-18 13:53:49 +0000980 return 0;
981 }
982 return 1;
983}
984
Jack Jansen8bb573e1999-12-12 21:37:14 +0000985/* Convert FSSpec to PyObject */
986PyObject *PyMac_BuildFSSpec(FSSpec *v)
987{
988 return newmfssobject(v);
989}
Guido van Rossum8f691791995-01-18 23:57:26 +0000990
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000991/* Convert a Python object to a Rect.
Guido van Rossum5279ec61995-01-26 22:56:59 +0000992 The object must be a (left, top, right, bottom) tuple.
993 (This differs from the order in the struct but is consistent with
994 the arguments to SetRect(), and also with STDWIN). */
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000995int
996PyMac_GetRect(PyObject *v, Rect *r)
Guido van Rossum8f691791995-01-18 23:57:26 +0000997{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000998 return PyArg_Parse(v, "(hhhh)", &r->left, &r->top, &r->right, &r->bottom);
Guido van Rossum8f691791995-01-18 23:57:26 +0000999}
Guido van Rossumb3404661995-01-22 18:36:13 +00001000
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001001/* Convert a Rect to a Python object */
Guido van Rossumb3404661995-01-22 18:36:13 +00001002PyObject *
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001003PyMac_BuildRect(Rect *r)
Guido van Rossumb3404661995-01-22 18:36:13 +00001004{
Guido van Rossum5279ec61995-01-26 22:56:59 +00001005 return Py_BuildValue("(hhhh)", r->left, r->top, r->right, r->bottom);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001006}
1007
1008
1009/* Convert a Python object to a Point.
Guido van Rossum5279ec61995-01-26 22:56:59 +00001010 The object must be a (h, v) tuple.
1011 (This differs from the order in the struct but is consistent with
1012 the arguments to SetPoint(), and also with STDWIN). */
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001013int
1014PyMac_GetPoint(PyObject *v, Point *p)
1015{
Guido van Rossum5279ec61995-01-26 22:56:59 +00001016 return PyArg_Parse(v, "(hh)", &p->h, &p->v);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001017}
1018
1019/* Convert a Point to a Python object */
1020PyObject *
1021PyMac_BuildPoint(Point p)
1022{
Guido van Rossum5279ec61995-01-26 22:56:59 +00001023 return Py_BuildValue("(hh)", p.h, p.v);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001024}
1025
1026
1027/* Convert a Python object to an EventRecord.
1028 The object must be a (what, message, when, (v, h), modifiers) tuple. */
1029int
1030PyMac_GetEventRecord(PyObject *v, EventRecord *e)
1031{
1032 return PyArg_Parse(v, "(hll(hh)h)",
1033 &e->what,
1034 &e->message,
1035 &e->when,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001036 &e->where.h,
Guido van Rossum5279ec61995-01-26 22:56:59 +00001037 &e->where.v,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001038 &e->modifiers);
1039}
1040
1041/* Convert a Rect to an EventRecord object */
1042PyObject *
1043PyMac_BuildEventRecord(EventRecord *e)
1044{
1045 return Py_BuildValue("(hll(hh)h)",
1046 e->what,
1047 e->message,
1048 e->when,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001049 e->where.h,
Guido van Rossum5279ec61995-01-26 22:56:59 +00001050 e->where.v,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001051 e->modifiers);
Guido van Rossumb3404661995-01-22 18:36:13 +00001052}
Jack Jansenfa4d5d01995-11-15 15:19:29 +00001053
1054/* Convert Python object to Fixed */
1055int
1056PyMac_GetFixed(PyObject *v, Fixed *f)
1057{
1058 double d;
1059
1060 if( !PyArg_Parse(v, "d", &d))
1061 return 0;
1062 *f = (Fixed)(d * 0x10000);
Jack Jansen31dd5c01996-05-31 13:01:39 +00001063 return 1;
Jack Jansenfa4d5d01995-11-15 15:19:29 +00001064}
1065
1066/* Convert a Point to a Python object */
1067PyObject *
1068PyMac_BuildFixed(Fixed f)
1069{
1070 double d;
1071
1072 d = f;
1073 d = d / 0x10000;
1074 return Py_BuildValue("d", d);
1075}
1076
Jack Jansend58cd631998-04-21 15:24:39 +00001077/* Convert wide to/from Python int or (hi, lo) tuple. XXXX Should use Python longs */
1078int
1079PyMac_Getwide(PyObject *v, wide *rv)
1080{
1081 if (PyInt_Check(v)) {
1082 rv->hi = 0;
1083 rv->lo = PyInt_AsLong(v);
1084 if( rv->lo & 0x80000000 )
1085 rv->hi = -1;
1086 return 1;
1087 }
1088 return PyArg_Parse(v, "(ll)", &rv->hi, &rv->lo);
1089}
1090
1091
1092PyObject *
Jack Jansenbbf4be21998-04-23 13:20:17 +00001093PyMac_Buildwide(wide *w)
Jack Jansend58cd631998-04-21 15:24:39 +00001094{
Jack Jansenbbf4be21998-04-23 13:20:17 +00001095 if ( (w->hi == 0 && (w->lo & 0x80000000) == 0) ||
1096 (w->hi == -1 && (w->lo & 0x80000000) ) )
1097 return PyInt_FromLong(w->lo);
1098 return Py_BuildValue("(ll)", w->hi, w->lo);
Jack Jansend58cd631998-04-21 15:24:39 +00001099}