blob: bf5e3487b4444fa494e56f9adfe3aef92e4532e0 [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
Jack Jansenf93c72a1994-12-14 14:07:50 +000026#include "Python.h"
Guido van Rossumbecdbec1995-02-14 01:27:24 +000027
Jack Jansenf93c72a1994-12-14 14:07:50 +000028#include "macglue.h"
Jack Jansen74162f31995-02-15 22:58:33 +000029#include "marshal.h"
30#include "import.h"
Jack Janseneda78631997-06-12 15:29:46 +000031#include "importdl.h"
Jack Jansen8bb1dc12001-05-19 12:31:09 +000032#include "pymactoolbox.h"
Jack Jansenf93c72a1994-12-14 14:07:50 +000033
Jack Jansen819f1771995-08-14 12:35:10 +000034#include "pythonresources.h"
35
Jack Jansen0194ad52001-05-12 22:46:35 +000036#ifdef WITHOUT_FRAMEWORKS
Jack Jansenf93c72a1994-12-14 14:07:50 +000037#include <OSUtils.h> /* for Set(Current)A5 */
Jack Jansene8e8ae01995-01-26 16:36:45 +000038#include <Files.h>
Jack Jansen8cd2b721995-02-13 11:33:28 +000039#include <StandardFile.h>
Jack Jansenf93c72a1994-12-14 14:07:50 +000040#include <Resources.h>
41#include <Memory.h>
Jack Jansenf93c72a1994-12-14 14:07:50 +000042#include <Windows.h>
Jack Jansene8e8ae01995-01-26 16:36:45 +000043#include <Traps.h>
Jack Jansenee23d6e1995-01-27 14:43:25 +000044#include <Processes.h>
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +000045#include <Fonts.h>
46#include <Menus.h>
Jack Jansen08305501995-06-18 20:03:40 +000047#include <TextUtils.h>
Jack Jansen0194ad52001-05-12 22:46:35 +000048#include <LowMem.h>
49#ifdef __CFM68K__
50/* cfm68k InterfaceLib exports GetEventQueue, but Events.h doesn't know this
51** and defines it as GetEvQHdr (which is correct for PPC). This fix is for
52** CW9, check that the workaround is still needed for the next release.
53*/
54#define GetEvQHdr GetEventQueue
55#endif /* __CFM68K__ */
56
57#include <Events.h>
58
59#ifdef __CFM68K__
60#undef GetEventQueue
61#endif /* __CFM68K__ */
62#else
63#include <Carbon/Carbon.h>
64#endif
65
66#if !TARGET_API_MAC_OS8
67/* Unfortunately this call is probably slower... */
68#define LMGetTicks() TickCount()
69#endif
70
Jack Jansen16df2aa1995-02-27 16:17:28 +000071#ifdef __MWERKS__
72#include <SIOUX.h>
Jack Jansen9ae898b2000-07-11 21:16:03 +000073extern void SIOUXSetupMenus(void);
74extern void SIOUXDoAboutBox(void);
Jack Jansen16df2aa1995-02-27 16:17:28 +000075#endif
Jack Jansen9ae898b2000-07-11 21:16:03 +000076#ifdef USE_GUSI
77/* Functions we redefine because they're in obscure libraries */
78extern void SpinCursor(short x);
79extern void RotateCursor(short x);
80extern pascal void PLstrcpy(unsigned char *, unsigned char *);
81extern pascal int PLstrcmp(unsigned char *, unsigned char *);
82extern pascal unsigned char *PLstrrchr(unsigned char *, unsigned char);
83
84#endif
85
Jack Jansen2d1306b2000-04-07 09:10:49 +000086#ifdef USE_GUSI1
Jack Jansen911ad6b1996-03-05 16:56:24 +000087#include <TFileSpec.h> /* For Path2FSSpec */
Jack Jansenf6865f71996-09-04 15:24:59 +000088#include <GUSI.h>
Jack Jansen911ad6b1996-03-05 16:56:24 +000089#endif
Jack Jansenee23d6e1995-01-27 14:43:25 +000090
Jack Jansen3469e991996-09-06 00:30:45 +000091/* The ID of the Sioux apple menu */
92#define SIOUX_APPLEID 32000
93
Jack Jansenee23d6e1995-01-27 14:43:25 +000094#include <signal.h>
Jack Jansen74162f31995-02-15 22:58:33 +000095#include <stdio.h>
Jack Jansene8e8ae01995-01-26 16:36:45 +000096
Jack Jansenee23d6e1995-01-27 14:43:25 +000097/*
Jack Jansend1f06311996-08-01 15:23:54 +000098** When less than this amount of stackspace is left we
99** raise a MemoryError.
100*/
101#ifndef MINIMUM_STACK_SIZE
102#ifdef __powerc
103#define MINIMUM_STACK_SIZE 8192
104#else
105#define MINIMUM_STACK_SIZE 4096
106#endif
107#endif
108
Jack Jansen340eb882001-02-02 22:40:28 +0000109#if TARGET_API_MAC_CARBON
110/*
111** On MacOSX StackSpace() lies: it gives the distance from heap end to stack pointer,
112** but the stack cannot grow that far due to rlimit values. We cannot get at this value
113** from Carbon, so we set a maximum to the stack here that is based on the default
114** stack limit of 512K.
115*/
116#define MAXIMUM_STACK_SIZE (256*1024)
117#endif
118
Jack Jansend1f06311996-08-01 15:23:54 +0000119/*
Jack Jansen16df2aa1995-02-27 16:17:28 +0000120** We have to be careful, since we can't handle
Jack Jansenee23d6e1995-01-27 14:43:25 +0000121** things like updates (and they'll keep coming back if we don't
Jack Jansen16df2aa1995-02-27 16:17:28 +0000122** handle them). Note that we don't know who has windows open, so
123** even handing updates off to SIOUX under MW isn't going to work.
Jack Jansenee23d6e1995-01-27 14:43:25 +0000124*/
Jack Jansen0c968871997-08-26 13:20:34 +0000125#define MAINLOOP_EVENTMASK (mDownMask|keyDownMask|osMask|activMask)
Jack Jansene8e8ae01995-01-26 16:36:45 +0000126
127#include <signal.h>
Jack Jansenf93c72a1994-12-14 14:07:50 +0000128
Guido van Rossumb3404661995-01-22 18:36:13 +0000129/* XXX We should include Errors.h here, but it has a name conflict
Jack Jansen5f653091995-01-18 13:53:49 +0000130** with the python errors.h. */
131#define fnfErr -43
132
Jack Jansene8e8ae01995-01-26 16:36:45 +0000133/* Declared in macfsmodule.c: */
Jack Jansen9ae898b2000-07-11 21:16:03 +0000134extern FSSpec *mfs_GetFSSpecFSSpec(PyObject *);
Jack Jansend88296d2000-07-11 19:51:05 +0000135extern PyObject *newmfssobject(FSSpec *);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000136
Jack Jansenee23d6e1995-01-27 14:43:25 +0000137/* Interrupt code variables: */
138static int interrupted; /* Set to true when cmd-. seen */
Jack Jansend88296d2000-07-11 19:51:05 +0000139static RETSIGTYPE intcatcher(int);
Jack Jansenee23d6e1995-01-27 14:43:25 +0000140
Jack Jansen0194ad52001-05-12 22:46:35 +0000141#if !TARGET_API_MAC_OSX
Jack Jansend88296d2000-07-11 19:51:05 +0000142static int PyMac_Yield(void);
Jack Jansen0194ad52001-05-12 22:46:35 +0000143#endif
Jack Jansenf6865f71996-09-04 15:24:59 +0000144
Jack Jansene8e8ae01995-01-26 16:36:45 +0000145/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000146** These are the real scheduling parameters that control what we check
147** in the event loop, and how often we check. The values are initialized
148** from pyMac_SchedParamStruct.
149*/
150
151struct real_sched_param_struct {
152 int check_interrupt; /* if true check for command-dot */
153 int process_events; /* if nonzero enable evt processing, this mask */
154 int besocial; /* if nonzero be a little social with CPU */
155 unsigned long check_interval; /* how often to check, in ticks */
156 unsigned long bg_yield; /* yield so long when in background */
157 /* these are computed from previous and clock and such */
158 int enabled; /* check_interrupt OR process_event OR yield */
159 unsigned long next_check; /* when to check/yield next, in ticks */
160};
161
162static struct real_sched_param_struct schedparams =
163 { 1, MAINLOOP_EVENTMASK, 1, 15, 15, 1, 0};
164
Jack Jansen819f1771995-08-14 12:35:10 +0000165/*
Jack Jansenf6865f71996-09-04 15:24:59 +0000166** Workaround for sioux/gusi combo: set when we are exiting
167*/
168int PyMac_ConsoleIsDead;
169
170/*
Jack Jansencaa7c461997-06-12 10:49:13 +0000171** Sioux menu bar, saved early so we can restore it
172*/
Jack Jansen657ba272001-02-17 22:02:07 +0000173static MenuBarHandle sioux_mbar;
Jack Jansencaa7c461997-06-12 10:49:13 +0000174
175/*
Jack Jansen819f1771995-08-14 12:35:10 +0000176** Some stuff for our GetDirectory and PromptGetFile routines
177*/
178struct hook_args {
179 int selectcur_hit; /* Set to true when "select current" selected */
180 char *prompt; /* The prompt */
181};
Jack Jansen6e68a7e2001-05-12 21:31:34 +0000182#if !TARGET_API_MAC_OS8
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000183/* The StandardFile hooks don't exist in Carbon. This breaks GetDirectory,
184** but the macfsn code will replace it by a NavServices version anyway.
185*/
186#define myhook_upp NULL
187#else
Jack Jansen819f1771995-08-14 12:35:10 +0000188static DlgHookYDUPP myhook_upp;
189static int upp_inited = 0;
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000190#endif
Jack Jansen819f1771995-08-14 12:35:10 +0000191
Jack Jansen36ed5061997-06-20 16:18:15 +0000192/*
193** The python-code event handler
194*/
195static PyObject *python_event_handler;
196
Jack Jansen8f5725a1999-12-07 23:08:10 +0000197/*
198** Set to true if we're appearance-compliant
199*/
200int PyMac_AppearanceCompliant;
201
Jack Jansen1f9f2f42000-07-24 19:50:16 +0000202/*
203** Find out what the current script is.
204** Donated by Fredrik Lund.
205*/
206char *PyMac_getscript()
207{
208 int font, script, lang;
209 font = 0;
210 font = GetSysFont();
211 script = FontToScript(font);
212 switch (script) {
213 case smRoman:
214 lang = GetScriptVariable(script, smScriptLang);
215 if (lang == langIcelandic)
216 return "mac-iceland";
217 else if (lang == langTurkish)
218 return "mac-turkish";
219 else if (lang == langGreek)
220 return "mac-greek";
221 else
222 return "mac-roman";
223 break;
224 case smJapanese:
225 return "mac-japan";
226 case smGreek:
227 return "mac-greek";
228 case smCyrillic:
229 return "mac-cyrillic";
230 default:
231 return "mac-roman"; /* better than nothing */
232 }
233}
234
235
Jack Jansen2d1306b2000-04-07 09:10:49 +0000236#ifdef USE_GUSI1
Jack Jansen378815c1996-03-06 16:21:34 +0000237/*
238** GUSI (1.6.0 and earlier, at the least) do not set the MacOS idea of
239** the working directory. Hence, we call this routine after each call
240** to chdir() to rectify things.
241*/
242void
243PyMac_FixGUSIcd()
244{
245 WDPBRec pb;
246 FSSpec curdirfss;
247
248 if ( Path2FSSpec(":x", &curdirfss) != noErr )
249 return;
250
251 /* Set MacOS "working directory" */
252 pb.ioNamePtr= "\p";
253 pb.ioVRefNum= curdirfss.vRefNum;
254 pb.ioWDDirID= curdirfss.parID;
Jack Jansen08c3be31997-04-08 15:27:00 +0000255 if (PBHSetVolSync(&pb) != noErr)
Jack Jansen378815c1996-03-06 16:21:34 +0000256 return;
Jack Jansen378815c1996-03-06 16:21:34 +0000257}
Jack Jansen2d1306b2000-04-07 09:10:49 +0000258#endif
Jack Jansen7ac70af1996-08-19 11:01:05 +0000259
Jack Jansen2d1306b2000-04-07 09:10:49 +0000260#ifdef USE_GUSI
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000261/*
262** SpinCursor (needed by GUSI) drags in heaps of stuff, so we
263** provide a dummy here.
264*/
Jack Jansencfadbd41996-08-19 11:36:25 +0000265void SpinCursor(short x) { /* Dummy */ }
Jack Jansenefaada71998-02-20 16:03:15 +0000266void RotateCursor(short x) { /* Dummy */ }
Jack Jansencfadbd41996-08-19 11:36:25 +0000267
Jack Jansenf6865f71996-09-04 15:24:59 +0000268/*
269** Replacement GUSI Spin function
270*/
Jack Jansen2d1306b2000-04-07 09:10:49 +0000271#ifdef USE_GUSI1
Jack Jansenf6865f71996-09-04 15:24:59 +0000272static int
273PyMac_GUSISpin(spin_msg msg, long arg)
274{
Jack Jansene3ae0df1997-06-03 15:28:29 +0000275 static Boolean inForeground = true;
276 int maxsleep = 6; /* 6 ticks is "normal" sleeptime */
Jack Jansenf6865f71996-09-04 15:24:59 +0000277
278 if (PyMac_ConsoleIsDead) return 0;
279#if 0
280 if (inForeground)
281 SpinCursor(msg == SP_AUTO_SPIN ? short(arg) : 1);
282#endif
283
284 if (interrupted) return -1;
285
Jack Jansene3ae0df1997-06-03 15:28:29 +0000286 if ( msg == SP_AUTO_SPIN )
287 maxsleep = 0;
288 if ( msg==SP_SLEEP||msg==SP_SELECT )
289 maxsleep = arg;
Jack Jansenf6865f71996-09-04 15:24:59 +0000290
Jack Jansene3ae0df1997-06-03 15:28:29 +0000291 PyMac_DoYield(maxsleep, 0); /* XXXX or is it safe to call python here? */
Jack Jansenf6865f71996-09-04 15:24:59 +0000292
293 return 0;
294}
295
296void
297PyMac_SetGUSISpin() {
298 GUSISetHook(GUSI_SpinHook, (GUSIHook)PyMac_GUSISpin);
299}
Jack Jansen2d1306b2000-04-07 09:10:49 +0000300#endif
Jack Jansenf6865f71996-09-04 15:24:59 +0000301
Jack Jansena39f1b01997-05-23 15:35:14 +0000302/* Called at exit() time thru atexit(), to stop event processing */
303void
304PyMac_StopGUSISpin() {
305 PyMac_ConsoleIsDead = 1;
306}
307
Jack Jansen6e68a7e2001-05-12 21:31:34 +0000308#if TARGET_API_MAC_OS8
Jack Jansena39f1b01997-05-23 15:35:14 +0000309/*
310** Replacement routines for the PLstr... functions so we don't need
Jack Jansen6ba34aa2001-01-11 23:03:56 +0000311** StdCLib.
Jack Jansena39f1b01997-05-23 15:35:14 +0000312*/
Jack Jansen8bb573e1999-12-12 21:37:14 +0000313pascal void
Jack Jansen9ae898b2000-07-11 21:16:03 +0000314PLstrcpy(unsigned char *to, unsigned char *fr)
Jack Jansena39f1b01997-05-23 15:35:14 +0000315{
316 memcpy(to, fr, fr[0]+1);
317}
318
Jack Jansen8bb573e1999-12-12 21:37:14 +0000319pascal int
Jack Jansen9ae898b2000-07-11 21:16:03 +0000320PLstrcmp(unsigned char *s1, unsigned char *s2)
Jack Jansena39f1b01997-05-23 15:35:14 +0000321{
322 int res;
323 int l = s1[0] < s2[0] ? s1[0] : s2[0];
324
325 res = memcmp(s1+1, s2+1, l);
326 if ( res != 0 )
327 return res;
328
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000329 if ( s1[0] < s2[0] )
Jack Jansena39f1b01997-05-23 15:35:14 +0000330 return -1;
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000331 else if ( s1[0] > s2[0] )
Jack Jansena39f1b01997-05-23 15:35:14 +0000332 return 1;
333 else
334 return 0;
335}
336
Jack Jansen8bb573e1999-12-12 21:37:14 +0000337pascal unsigned char *
Jack Jansen9ae898b2000-07-11 21:16:03 +0000338PLstrrchr(unsigned char *str, unsigned char chr)
Jack Jansena39f1b01997-05-23 15:35:14 +0000339{
340 unsigned char *ptr = 0;
341 unsigned char *p;
342
343 for(p=str+1; p<str+str[0]; p++)
344 if ( *p == chr )
345 ptr = p;
346 return ptr;
347}
348
Jack Jansen6e68a7e2001-05-12 21:31:34 +0000349#endif /* TARGET_API_MAC_OS8 */
Jack Jansena39f1b01997-05-23 15:35:14 +0000350#endif /* USE_GUSI */
Jack Jansen378815c1996-03-06 16:21:34 +0000351
Jack Jansen819f1771995-08-14 12:35:10 +0000352
Jack Jansen5f653091995-01-18 13:53:49 +0000353/* Convert C to Pascal string. Returns pointer to static buffer. */
354unsigned char *
355Pstring(char *str)
356{
357 static Str255 buf;
358 int len;
359
360 len = strlen(str);
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000361 if (len > 255)
362 len = 255;
Jack Jansen5f653091995-01-18 13:53:49 +0000363 buf[0] = (unsigned char)len;
364 strncpy((char *)buf+1, str, len);
365 return buf;
366}
367
Jack Jansen6e68a7e2001-05-12 21:31:34 +0000368#if TARGET_API_MAC_OS8
Jack Jansen5afad832000-12-12 22:12:14 +0000369void
370c2pstrcpy(unsigned char *dst, const char *src)
371{
372 int len;
373
374 len = strlen(src);
375 if ( len > 255 ) len = 255;
376 strncpy((char *)dst+1, src, len);
377 dst[0] = len;
378}
Jack Jansen6e68a7e2001-05-12 21:31:34 +0000379#endif /* TARGET_API_MAC_OS8 */
Jack Jansen5afad832000-12-12 22:12:14 +0000380
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000381/* Like strerror() but for Mac OS error numbers */
382char *PyMac_StrError(int err)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000383{
384 static char buf[256];
385 Handle h;
386 char *str;
387
388 h = GetResource('Estr', err);
389 if ( h ) {
390 HLock(h);
391 str = (char *)*h;
392 memcpy(buf, str+1, (unsigned char)str[0]);
Guido van Rossumcc9bc8f1995-02-13 16:17:03 +0000393 buf[(unsigned char)str[0]] = '\0';
Jack Jansenf93c72a1994-12-14 14:07:50 +0000394 HUnlock(h);
395 ReleaseResource(h);
396 } else {
397 sprintf(buf, "Mac OS error code %d", err);
398 }
399 return buf;
400}
401
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000402/* Exception object shared by all Mac specific modules for Mac OS errors */
403PyObject *PyMac_OSErrException;
404
405/* Initialize and return PyMac_OSErrException */
406PyObject *
407PyMac_GetOSErrException()
408{
409 if (PyMac_OSErrException == NULL)
410 PyMac_OSErrException = PyString_FromString("Mac OS Error");
411 return PyMac_OSErrException;
412}
413
Jack Jansenf93c72a1994-12-14 14:07:50 +0000414/* Set a MAC-specific error from errno, and return NULL; return None if no error */
415PyObject *
Guido van Rossumfffb8bb1995-01-12 12:37:24 +0000416PyErr_Mac(PyObject *eobj, int err)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000417{
418 char *msg;
419 PyObject *v;
Jack Jansenf93c72a1994-12-14 14:07:50 +0000420
Guido van Rossum8f691791995-01-18 23:57:26 +0000421 if (err == 0 && !PyErr_Occurred()) {
Jack Jansenf93c72a1994-12-14 14:07:50 +0000422 Py_INCREF(Py_None);
423 return Py_None;
424 }
Guido van Rossum8f691791995-01-18 23:57:26 +0000425 if (err == -1 && PyErr_Occurred())
426 return NULL;
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000427 msg = PyMac_StrError(err);
Jack Jansenf93c72a1994-12-14 14:07:50 +0000428 v = Py_BuildValue("(is)", err, msg);
429 PyErr_SetObject(eobj, v);
430 Py_DECREF(v);
431 return NULL;
432}
433
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000434/* Call PyErr_Mac with PyMac_OSErrException */
435PyObject *
436PyMac_Error(OSErr err)
437{
438 return PyErr_Mac(PyMac_GetOSErrException(), err);
439}
440
Jack Jansen1ed95291996-07-22 15:25:10 +0000441#ifdef USE_STACKCHECK
442/* Check for stack overflow */
443int
444PyOS_CheckStack()
445{
Jack Jansen14a91712000-08-25 21:57:23 +0000446 char here;
447 static char *sentinel = 0;
Jack Jansen53bafd92000-09-08 22:05:48 +0000448 static PyThreadState *thread_for_sentinel = 0;
Jack Jansen1ed95291996-07-22 15:25:10 +0000449
Jack Jansen340eb882001-02-02 22:40:28 +0000450 if ( sentinel == 0 ) {
451 unsigned long stackspace = StackSpace();
452
453#ifdef MAXIMUM_STACK_SIZE
454 /* See the comment at the definition */
455 if ( stackspace > MAXIMUM_STACK_SIZE )
456 stackspace = MAXIMUM_STACK_SIZE;
457#endif
458 sentinel = &here - stackspace + MINIMUM_STACK_SIZE;
Jack Jansen14a91712000-08-25 21:57:23 +0000459 }
Jack Jansen53bafd92000-09-08 22:05:48 +0000460 if ( thread_for_sentinel == 0 ) {
461 thread_for_sentinel = PyThreadState_Get();
462 }
463 if ( &here < sentinel ) {
464 if (thread_for_sentinel == PyThreadState_Get()) {
465 return -1;
466#if 0
467 } else {
468 /* Else we are unsure... */
469 fprintf(stderr, "Stackcheck in other thread (was %x now %x)\n", thread_for_sentinel,PyThreadState_Get());
470#endif
471 }
472 }
Jack Jansen1ed95291996-07-22 15:25:10 +0000473 return 0;
474}
475#endif /* USE_STACKCHECK */
476
Jack Jansen0194ad52001-05-12 22:46:35 +0000477#if !TARGET_API_MAC_OSX
Jack Jansenee23d6e1995-01-27 14:43:25 +0000478/* The catcher routine (which may not be used for all compilers) */
479static RETSIGTYPE
480intcatcher(sig)
481 int sig;
482{
483 interrupted = 1;
484 signal(SIGINT, intcatcher);
485}
486
487void
488PyOS_InitInterrupts()
489{
490 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
491 signal(SIGINT, intcatcher);
492}
493
Jack Jansena8441de1997-08-08 14:57:37 +0000494void
495PyOS_FiniInterrupts()
496{
497}
498
Jack Jansenee23d6e1995-01-27 14:43:25 +0000499/*
500** This routine scans the event queue looking for cmd-.
501** This is the only way to get an interrupt under THINK (since it
502** doesn't do SIGINT handling), but is also used under MW, when
503** the full-fledged event loop is disabled. This way, we can at least
504** interrupt a runaway python program.
505*/
506static void
507scan_event_queue(flush)
508 int flush;
509{
Jack Jansen6e68a7e2001-05-12 21:31:34 +0000510#if !TARGET_API_MAC_OS8
Jack Jansend7b68022001-01-12 23:42:28 +0000511 if ( CheckEventQueueForUserCancel() )
512 interrupted = 1;
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000513#else
Jack Jansenee23d6e1995-01-27 14:43:25 +0000514 register EvQElPtr q;
515
Jack Jansenefaada71998-02-20 16:03:15 +0000516 q = (EvQElPtr) LMGetEventQueue()->qHead;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000517
518 for (; q; q = (EvQElPtr)q->qLink) {
519 if (q->evtQWhat == keyDown &&
520 (char)q->evtQMessage == '.' &&
521 (q->evtQModifiers & cmdKey) != 0) {
522 if ( flush )
523 FlushEvents(keyDownMask, 0);
524 interrupted = 1;
525 break;
526 }
527 }
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000528#endif
Jack Jansenee23d6e1995-01-27 14:43:25 +0000529}
530
531int
Jack Jansen36ed5061997-06-20 16:18:15 +0000532PyErr_CheckSignals()
Jack Jansenee23d6e1995-01-27 14:43:25 +0000533{
Jack Jansene3ae0df1997-06-03 15:28:29 +0000534 if (schedparams.enabled) {
535 if ( (unsigned long)LMGetTicks() > schedparams.next_check ) {
Jack Jansen36ed5061997-06-20 16:18:15 +0000536 if ( PyMac_Yield() < 0)
537 return -1;
Jack Jansene3ae0df1997-06-03 15:28:29 +0000538 schedparams.next_check = (unsigned long)LMGetTicks()
539 + schedparams.check_interval;
540 if (interrupted) {
Jack Jansencaa7c461997-06-12 10:49:13 +0000541 scan_event_queue(1); /* Eat events up to cmd-. */
Jack Jansene3ae0df1997-06-03 15:28:29 +0000542 interrupted = 0;
Jack Jansen36ed5061997-06-20 16:18:15 +0000543 PyErr_SetNone(PyExc_KeyboardInterrupt);
544 return -1;
Jack Jansene3ae0df1997-06-03 15:28:29 +0000545 }
546 }
Jack Jansenee23d6e1995-01-27 14:43:25 +0000547 }
548 return 0;
549}
550
Jack Jansen36ed5061997-06-20 16:18:15 +0000551int
552PyOS_InterruptOccurred()
553{
554 scan_event_queue(1);
555 return interrupted;
556}
Jack Jansen0194ad52001-05-12 22:46:35 +0000557
Jack Jansenee23d6e1995-01-27 14:43:25 +0000558/* Check whether we are in the foreground */
Jack Jansen9ae898b2000-07-11 21:16:03 +0000559static int
560PyMac_InForeground(void)
Jack Jansenee23d6e1995-01-27 14:43:25 +0000561{
562 static ProcessSerialNumber ours;
563 static inited;
564 ProcessSerialNumber curfg;
565 Boolean eq;
566
Jack Jansene3ae0df1997-06-03 15:28:29 +0000567 if ( inited == 0 ) {
Jack Jansenee23d6e1995-01-27 14:43:25 +0000568 (void)GetCurrentProcess(&ours);
Jack Jansene3ae0df1997-06-03 15:28:29 +0000569 inited = 1;
570 }
Jack Jansenee23d6e1995-01-27 14:43:25 +0000571 if ( GetFrontProcess(&curfg) < 0 )
572 eq = 1;
573 else if ( SameProcess(&ours, &curfg, &eq) < 0 )
574 eq = 1;
575 return (int)eq;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000576}
Jack Jansen0194ad52001-05-12 22:46:35 +0000577#endif
Jack Jansenee23d6e1995-01-27 14:43:25 +0000578
Jack Jansen36ed5061997-06-20 16:18:15 +0000579int
580PyMac_SetEventHandler(PyObject *evh)
581{
582 if ( evh && python_event_handler ) {
583 PyErr_SetString(PyExc_RuntimeError, "Python event handler already set");
584 return 0;
585 }
586 if ( python_event_handler )
587 Py_DECREF(python_event_handler);
588 if ( evh )
589 Py_INCREF(evh);
590 python_event_handler = evh;
591 return 1;
592}
593
Jack Jansenf93c72a1994-12-14 14:07:50 +0000594/*
Jack Jansena76382a1995-02-02 14:25:56 +0000595** Handle an event, either one found in the mainloop eventhandler or
596** one passed back from the python program.
597*/
598void
Jack Jansen36ed5061997-06-20 16:18:15 +0000599PyMac_HandleEventIntern(evp)
Jack Jansena76382a1995-02-02 14:25:56 +0000600 EventRecord *evp;
601{
Jack Jansen6e68a7e2001-05-12 21:31:34 +0000602#if TARGET_API_MAC_OS8
Jack Jansen0c968871997-08-26 13:20:34 +0000603 if ( evp->what == mouseDown ) {
604 WindowPtr wp;
605
606 if ( FindWindow(evp->where, &wp) == inSysWindow ) {
607 SystemClick(evp, wp);
608 return;
609 }
610 }
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000611#endif
Jack Jansena76382a1995-02-02 14:25:56 +0000612#ifdef __MWERKS__
Jack Jansen38e97661995-11-10 14:53:00 +0000613 {
614 int siouxdidit;
615
616 /* If SIOUX wants it we're done */
617 siouxdidit = SIOUXHandleOneEvent(evp);
618 if ( siouxdidit )
619 return;
620 }
Jack Jansena76382a1995-02-02 14:25:56 +0000621#else
Jack Jansen0c968871997-08-26 13:20:34 +0000622 /* Other compilers are just unlucky... */
Jack Jansena76382a1995-02-02 14:25:56 +0000623#endif /* !__MWERKS__ */
Jack Jansen36ed5061997-06-20 16:18:15 +0000624}
625
626/*
627** Handle an event, either through HandleEvent or by passing it to the Python
628** event handler.
629*/
630int
631PyMac_HandleEvent(evp)
632 EventRecord *evp;
633{
634 PyObject *rv;
635
636 if ( python_event_handler ) {
637 rv = PyObject_CallFunction(python_event_handler, "(O&)",
638 PyMac_BuildEventRecord, evp);
639 if ( rv )
640 Py_DECREF(rv);
641 else
642 return -1; /* Propagate exception */
643 } else {
644 PyMac_HandleEventIntern(evp);
645 }
646 return 0;
Jack Jansena76382a1995-02-02 14:25:56 +0000647}
648
Jack Jansen0194ad52001-05-12 22:46:35 +0000649#if !TARGET_API_MAC_OSX
Jack Jansena76382a1995-02-02 14:25:56 +0000650/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000651** Yield the CPU to other tasks without processing events.
Jack Jansene8e8ae01995-01-26 16:36:45 +0000652*/
Jack Jansen2d1306b2000-04-07 09:10:49 +0000653int
Jack Jansene3ae0df1997-06-03 15:28:29 +0000654PyMac_DoYield(int maxsleep, int maycallpython)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000655{
656 EventRecord ev;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000657 int gotone;
Jack Jansene3ae0df1997-06-03 15:28:29 +0000658 long latest_time_ready;
Jack Jansen36ed5061997-06-20 16:18:15 +0000659 static int in_here = 0;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000660
Jack Jansen36ed5061997-06-20 16:18:15 +0000661 in_here++;
Jack Jansene3ae0df1997-06-03 15:28:29 +0000662 /*
663 ** First check for interrupts, if wanted.
664 ** This sets a flag that will be picked up at an appropriate
665 ** moment in the mainloop.
666 */
667 if (schedparams.check_interrupt)
Jack Jansenee23d6e1995-01-27 14:43:25 +0000668 scan_event_queue(0);
Jack Jansene3ae0df1997-06-03 15:28:29 +0000669
670 /* XXXX Implementing an idle routine goes here */
Jack Jansene8e8ae01995-01-26 16:36:45 +0000671
Jack Jansene3ae0df1997-06-03 15:28:29 +0000672 /*
673 ** Check which of the eventloop cases we have:
674 ** - process events
675 ** - don't process events but do yield
676 ** - do neither
677 */
Jack Jansen36ed5061997-06-20 16:18:15 +0000678 if( in_here > 1 || !schedparams.process_events ||
679 (python_event_handler && !maycallpython) ) {
Jack Jansene3ae0df1997-06-03 15:28:29 +0000680 if ( maxsleep >= 0 ) {
Jack Jansen6e68a7e2001-05-12 21:31:34 +0000681#if TARGET_API_MAC_OS8
Jack Jansene8e8ae01995-01-26 16:36:45 +0000682 SystemTask();
Jack Jansen15f1c082001-04-25 22:07:27 +0000683#else
684 int xxx = 0;
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000685#endif
Jack Jansen15f1c082001-04-25 22:07:27 +0000686 }
Jack Jansene3ae0df1997-06-03 15:28:29 +0000687 } else {
688 latest_time_ready = LMGetTicks() + maxsleep;
Jack Jansen2d1306b2000-04-07 09:10:49 +0000689 do {
Jack Jansen0c968871997-08-26 13:20:34 +0000690 /* XXXX Hack by Jack.
691 ** In time.sleep() you can click to another application
692 ** once only. If you come back to Python you cannot get away
693 ** again.
694 **/
Jack Jansen36ed5061997-06-20 16:18:15 +0000695 gotone = WaitNextEvent(schedparams.process_events, &ev, maxsleep, NULL);
Jack Jansene3ae0df1997-06-03 15:28:29 +0000696 /* Get out quickly if nothing interesting is happening */
697 if ( !gotone || ev.what == nullEvent )
698 break;
Jack Jansen36ed5061997-06-20 16:18:15 +0000699 if ( PyMac_HandleEvent(&ev) < 0 ) {
700 in_here--;
701 return -1;
702 }
Jack Jansene3ae0df1997-06-03 15:28:29 +0000703 maxsleep = latest_time_ready - LMGetTicks();
Jack Jansen2d1306b2000-04-07 09:10:49 +0000704 } while ( maxsleep > 0 );
Jack Jansenf93c72a1994-12-14 14:07:50 +0000705 }
Jack Jansen36ed5061997-06-20 16:18:15 +0000706 in_here--;
707 return 0;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000708}
709
710/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000711** Process events and/or yield the CPU to other tasks if opportune
Jack Jansene8e8ae01995-01-26 16:36:45 +0000712*/
Jack Jansen36ed5061997-06-20 16:18:15 +0000713int
Jack Jansene8e8ae01995-01-26 16:36:45 +0000714PyMac_Yield() {
Jack Jansene3ae0df1997-06-03 15:28:29 +0000715 unsigned long maxsleep;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000716
Jack Jansene3ae0df1997-06-03 15:28:29 +0000717 if( PyMac_InForeground() )
718 maxsleep = 0;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000719 else
Jack Jansene3ae0df1997-06-03 15:28:29 +0000720 maxsleep = schedparams.bg_yield;
721
Jack Jansen36ed5061997-06-20 16:18:15 +0000722 return PyMac_DoYield(maxsleep, 1);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000723}
724
725/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000726** Return current scheduler parameters
Jack Jansene8e8ae01995-01-26 16:36:45 +0000727*/
Jack Jansene3ae0df1997-06-03 15:28:29 +0000728void
729PyMac_GetSchedParams(PyMacSchedParams *sp)
Jack Jansene8e8ae01995-01-26 16:36:45 +0000730{
Jack Jansene3ae0df1997-06-03 15:28:29 +0000731 sp->check_interrupt = schedparams.check_interrupt;
732 sp->process_events = schedparams.process_events;
733 sp->besocial = schedparams.besocial;
734 sp->check_interval = schedparams.check_interval / 60.0;
735 sp->bg_yield = schedparams.bg_yield / 60.0;
Jack Jansenf93c72a1994-12-14 14:07:50 +0000736}
Jack Jansenf6865f71996-09-04 15:24:59 +0000737
Jack Jansen74162f31995-02-15 22:58:33 +0000738/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000739** Set current scheduler parameters
740*/
741void
742PyMac_SetSchedParams(PyMacSchedParams *sp)
743{
744 schedparams.check_interrupt = sp->check_interrupt;
745 schedparams.process_events = sp->process_events;
746 schedparams.besocial = sp->besocial;
747 schedparams.check_interval = (unsigned long)(sp->check_interval*60);
748 schedparams.bg_yield = (unsigned long)(sp->bg_yield*60);
749 if ( schedparams.check_interrupt || schedparams.process_events ||
750 schedparams.besocial )
751 schedparams.enabled = 1;
752 else
753 schedparams.enabled = 0;
754 schedparams.next_check = 0; /* Check immedeately */
755}
Jack Jansencaa7c461997-06-12 10:49:13 +0000756
Jack Jansene3ae0df1997-06-03 15:28:29 +0000757/*
Jack Jansen3469e991996-09-06 00:30:45 +0000758** Install our menu bar.
759*/
760void
761PyMac_InitMenuBar()
762{
Jack Jansen3469e991996-09-06 00:30:45 +0000763 MenuHandle applemenu;
764
Jack Jansen15f1c082001-04-25 22:07:27 +0000765 if ( sioux_mbar ) return;
Jack Jansencaa7c461997-06-12 10:49:13 +0000766 if ( (sioux_mbar=GetMenuBar()) == NULL ) {
767 /* Sioux menu not installed yet. Do so */
768 SIOUXSetupMenus();
769 if ( (sioux_mbar=GetMenuBar()) == NULL )
770 return;
771 }
Jack Jansen08c3be31997-04-08 15:27:00 +0000772 if ( (applemenu=GetMenuHandle(SIOUX_APPLEID)) == NULL ) return;
Jack Jansen3469e991996-09-06 00:30:45 +0000773 SetMenuItemText(applemenu, 1, "\pAbout Python...");
774}
775
776/*
Jack Jansencaa7c461997-06-12 10:49:13 +0000777** Restore sioux menu bar
778*/
779void
780PyMac_RestoreMenuBar()
781{
Jack Jansen15f1c082001-04-25 22:07:27 +0000782#if 1
Jack Jansen657ba272001-02-17 22:02:07 +0000783 /* This doesn't seem to work anymore? Or only for Carbon? */
784 MenuBarHandle curmenubar;
785
786 curmenubar = GetMenuBar();
Jack Janseneda78631997-06-12 15:29:46 +0000787 if ( sioux_mbar ) {
Jack Jansencaa7c461997-06-12 10:49:13 +0000788 SetMenuBar(sioux_mbar);
Jack Janseneda78631997-06-12 15:29:46 +0000789 DrawMenuBar();
Jack Jansen657ba272001-02-17 22:02:07 +0000790 } else {
Jack Jansenefaada71998-02-20 16:03:15 +0000791 PyMac_InitMenuBar();
Jack Jansen657ba272001-02-17 22:02:07 +0000792 DrawMenuBar();
793 }
794#endif
Jack Jansencaa7c461997-06-12 10:49:13 +0000795}
796
Jack Jansen15f1c082001-04-25 22:07:27 +0000797void
798PyMac_RaiseConsoleWindow()
799{
800 /* Note: this is a hack. SIOUXTextWindow is SIOUX's internal structure
801 ** and we happen to know that the first entry is the window pointer.
802 */
803 extern WindowRef *SIOUXTextWindow;
804
805 if ( SIOUXTextWindow == NULL || *SIOUXTextWindow == NULL )
806 return;
807 if ( FrontWindow() != *SIOUXTextWindow )
808 BringToFront(*SIOUXTextWindow);
809}
Jack Jansencaa7c461997-06-12 10:49:13 +0000810
811/*
Jack Jansen3469e991996-09-06 00:30:45 +0000812** Our replacement about box
813*/
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000814
815#include "patchlevel.h"
816
Jack Jansen3469e991996-09-06 00:30:45 +0000817void
818SIOUXDoAboutBox(void)
819{
820 DialogPtr theDialog;
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000821 WindowPtr theWindow;
Jack Jansen3469e991996-09-06 00:30:45 +0000822 short item;
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000823 short fontID;
Jack Jansen3469e991996-09-06 00:30:45 +0000824
825 if( (theDialog = GetNewDialog(ABOUT_ID, NULL, (WindowPtr)-1)) == NULL )
826 return;
Jack Jansend617c571996-09-22 22:14:30 +0000827 theWindow = GetDialogWindow(theDialog);
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000828 SetPortWindowPort(theWindow);
829 GetFNum("\pPython-Sans", &fontID);
830 if (fontID == 0)
831 fontID = kFontIDGeneva;
832 TextFont(fontID);
833 TextSize(9);
834 ParamText(Pstring(PATCHLEVEL), "\p", "\p", "\p");
Jack Jansend617c571996-09-22 22:14:30 +0000835 ShowWindow(theWindow);
Jack Jansen3469e991996-09-06 00:30:45 +0000836 ModalDialog(NULL, &item);
837 DisposeDialog(theDialog);
838}
839
Jack Jansen0194ad52001-05-12 22:46:35 +0000840#endif /* !TARGET_API_MAC_OSX */
Jack Janseneda78631997-06-12 15:29:46 +0000841
Jack Jansen0194ad52001-05-12 22:46:35 +0000842#if TARGET_API_MAC_OS8
Jack Janseneda78631997-06-12 15:29:46 +0000843/*
Jack Jansen3ec804a1995-02-20 15:56:10 +0000844** Helper routine for GetDirectory
845*/
Guido van Rossum24a45e31995-02-20 23:45:53 +0000846static pascal short
Jack Jansen819f1771995-08-14 12:35:10 +0000847myhook_proc(short item, DialogPtr theDialog, struct hook_args *dataptr)
Jack Jansen3ec804a1995-02-20 15:56:10 +0000848{
Jack Jansen819f1771995-08-14 12:35:10 +0000849 if ( item == sfHookFirstCall && dataptr->prompt) {
850 Handle prompth;
851 short type;
852 Rect rect;
853
854 GetDialogItem(theDialog, PROMPT_ITEM, &type, &prompth, &rect);
855 if ( prompth )
856 SetDialogItemText(prompth, (unsigned char *)dataptr->prompt);
857 } else
Jack Jansen3ec804a1995-02-20 15:56:10 +0000858 if ( item == SELECTCUR_ITEM ) {
859 item = sfItemCancelButton;
Jack Jansen819f1771995-08-14 12:35:10 +0000860 dataptr->selectcur_hit = 1;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000861 }
862 return item;
863}
Jack Jansen0194ad52001-05-12 22:46:35 +0000864
Jack Jansen3ec804a1995-02-20 15:56:10 +0000865/*
866** Ask the user for a directory. I still can't understand
867** why Apple doesn't provide a standard solution for this...
868*/
869int
Jack Jansen819f1771995-08-14 12:35:10 +0000870PyMac_GetDirectory(dirfss, prompt)
Jack Jansen3ec804a1995-02-20 15:56:10 +0000871 FSSpec *dirfss;
Jack Jansen819f1771995-08-14 12:35:10 +0000872 char *prompt;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000873{
874 static SFTypeList list = {'fldr', 0, 0, 0};
875 static Point where = {-1, -1};
Jack Jansen3ec804a1995-02-20 15:56:10 +0000876 StandardFileReply reply;
Jack Jansen819f1771995-08-14 12:35:10 +0000877 struct hook_args hook_args;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000878
879 if ( !upp_inited ) {
880 myhook_upp = NewDlgHookYDProc(myhook_proc);
881 upp_inited = 1;
882 }
Jack Jansen819f1771995-08-14 12:35:10 +0000883 if ( prompt && *prompt )
884 hook_args.prompt = (char *)Pstring(prompt);
885 else
886 hook_args.prompt = NULL;
887 hook_args.selectcur_hit = 0;
Guido van Rossum24a45e31995-02-20 23:45:53 +0000888 CustomGetFile((FileFilterYDUPP)0, 1, list, &reply, GETDIR_ID, where, myhook_upp,
Jack Jansen819f1771995-08-14 12:35:10 +0000889 NULL, NULL, NULL, (void *)&hook_args);
Jack Jansen3ec804a1995-02-20 15:56:10 +0000890
891 reply.sfFile.name[0] = 0;
892 if( FSMakeFSSpec(reply.sfFile.vRefNum, reply.sfFile.parID, reply.sfFile.name, dirfss) )
893 return 0;
Jack Jansen819f1771995-08-14 12:35:10 +0000894 return hook_args.selectcur_hit;
895}
896
897/*
898** Slightly extended StandardGetFile: accepts a prompt */
899void PyMac_PromptGetFile(short numTypes, ConstSFTypeListPtr typeList,
900 StandardFileReply *reply, char *prompt)
901{
902 static Point where = {-1, -1};
903 struct hook_args hook_args;
904
905 if ( !upp_inited ) {
906 myhook_upp = NewDlgHookYDProc(myhook_proc);
907 upp_inited = 1;
908 }
909 if ( prompt && *prompt )
910 hook_args.prompt = (char *)Pstring(prompt);
911 else
912 hook_args.prompt = NULL;
913 hook_args.selectcur_hit = 0;
914 CustomGetFile((FileFilterYDUPP)0, numTypes, typeList, reply, GETFILEPROMPT_ID, where,
915 myhook_upp, NULL, NULL, NULL, (void *)&hook_args);
Jack Jansen3ec804a1995-02-20 15:56:10 +0000916}
Jack Jansen6e68a7e2001-05-12 21:31:34 +0000917#endif /* TARGET_API_MAC_OS8 */
Jack Jansen5f653091995-01-18 13:53:49 +0000918
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000919/* Convert a 4-char string object argument to an OSType value */
Jack Jansen5f653091995-01-18 13:53:49 +0000920int
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000921PyMac_GetOSType(PyObject *v, OSType *pr)
Jack Jansen5f653091995-01-18 13:53:49 +0000922{
923 if (!PyString_Check(v) || PyString_Size(v) != 4) {
924 PyErr_SetString(PyExc_TypeError,
925 "OSType arg must be string of 4 chars");
926 return 0;
927 }
928 memcpy((char *)pr, PyString_AsString(v), 4);
929 return 1;
930}
931
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000932/* Convert an OSType value to a 4-char string object */
933PyObject *
934PyMac_BuildOSType(OSType t)
935{
936 return PyString_FromStringAndSize((char *)&t, 4);
937}
938
Jack Jansend1f06311996-08-01 15:23:54 +0000939/* Convert an NumVersion value to a 4-element tuple */
940PyObject *
941PyMac_BuildNumVersion(NumVersion t)
942{
943 return Py_BuildValue("(hhhh)", t.majorRev, t.minorAndBugRev, t.stage, t.nonRelRev);
944}
945
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000946
947/* Convert a Python string object to a Str255 */
Jack Jansen5f653091995-01-18 13:53:49 +0000948int
Guido van Rossum8f691791995-01-18 23:57:26 +0000949PyMac_GetStr255(PyObject *v, Str255 pbuf)
Jack Jansen5f653091995-01-18 13:53:49 +0000950{
951 int len;
952 if (!PyString_Check(v) || (len = PyString_Size(v)) > 255) {
953 PyErr_SetString(PyExc_TypeError,
954 "Str255 arg must be string of at most 255 chars");
955 return 0;
956 }
957 pbuf[0] = len;
958 memcpy((char *)(pbuf+1), PyString_AsString(v), len);
959 return 1;
960}
961
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000962/* Convert a Str255 to a Python string object */
963PyObject *
964PyMac_BuildStr255(Str255 s)
965{
Jack Jansenb734ade1999-12-17 17:15:50 +0000966 if ( s == NULL ) {
967 PyErr_SetString(PyExc_SystemError, "Str255 pointer is NULL");
968 return NULL;
969 }
970 return PyString_FromStringAndSize((char *)&s[1], (int)s[0]);
971}
972
973PyObject *
974PyMac_BuildOptStr255(Str255 s)
975{
976 if ( s == NULL ) {
977 Py_INCREF(Py_None);
978 return Py_None;
979 }
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000980 return PyString_FromStringAndSize((char *)&s[1], (int)s[0]);
981}
982
983
Jack Jansen5f653091995-01-18 13:53:49 +0000984/*
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000985** Convert a Python object to an FSSpec.
986** The object may either be a full pathname or a triple
987** (vrefnum, dirid, path).
Jack Jansen5f653091995-01-18 13:53:49 +0000988** NOTE: This routine will fail on pre-sys7 machines.
989** The caller is responsible for not calling this routine
990** in those cases (which is fine, since everyone calling
991** this is probably sys7 dependent anyway).
992*/
993int
Guido van Rossum8f691791995-01-18 23:57:26 +0000994PyMac_GetFSSpec(PyObject *v, FSSpec *fs)
Jack Jansen5f653091995-01-18 13:53:49 +0000995{
996 Str255 path;
997 short refnum;
998 long parid;
999 OSErr err;
Jack Jansene8e8ae01995-01-26 16:36:45 +00001000 FSSpec *fs2;
Jack Jansen5f653091995-01-18 13:53:49 +00001001
Jack Jansen0194ad52001-05-12 22:46:35 +00001002#if !TARGET_API_MAC_OSX
1003 /* XXX This #if is temporary */
Jack Jansene8e8ae01995-01-26 16:36:45 +00001004 /* first check whether it already is an FSSpec */
1005 fs2 = mfs_GetFSSpecFSSpec(v);
1006 if ( fs2 ) {
Jack Jansen3ec804a1995-02-20 15:56:10 +00001007 (void)FSMakeFSSpec(fs2->vRefNum, fs2->parID, fs2->name, fs);
Jack Jansene8e8ae01995-01-26 16:36:45 +00001008 return 1;
1009 }
Jack Jansen0194ad52001-05-12 22:46:35 +00001010#endif
Jack Jansen5f653091995-01-18 13:53:49 +00001011 if ( PyString_Check(v) ) {
1012 /* It's a pathname */
Guido van Rossum9aa3d131995-01-21 13:46:04 +00001013 if( !PyArg_Parse(v, "O&", PyMac_GetStr255, &path) )
Jack Jansen5f653091995-01-18 13:53:49 +00001014 return 0;
Jack Jansen378815c1996-03-06 16:21:34 +00001015 refnum = 0; /* XXXX Should get CurWD here?? */
Jack Jansen5f653091995-01-18 13:53:49 +00001016 parid = 0;
1017 } else {
Guido van Rossum9aa3d131995-01-21 13:46:04 +00001018 if( !PyArg_Parse(v, "(hlO&); FSSpec should be fullpath or (vrefnum,dirid,path)",
1019 &refnum, &parid, PyMac_GetStr255, &path)) {
Jack Jansen5f653091995-01-18 13:53:49 +00001020 return 0;
Guido van Rossum9aa3d131995-01-21 13:46:04 +00001021 }
Jack Jansen5f653091995-01-18 13:53:49 +00001022 }
1023 err = FSMakeFSSpec(refnum, parid, path, fs);
1024 if ( err && err != fnfErr ) {
Jack Jansen3d757542000-01-24 09:56:06 +00001025 PyMac_Error(err);
Jack Jansen5f653091995-01-18 13:53:49 +00001026 return 0;
1027 }
1028 return 1;
1029}
1030
Jack Jansen8bb573e1999-12-12 21:37:14 +00001031/* Convert FSSpec to PyObject */
1032PyObject *PyMac_BuildFSSpec(FSSpec *v)
1033{
Jack Jansen0194ad52001-05-12 22:46:35 +00001034#if TARGET_API_MAC_OSX
1035 PyErr_SetString(PyExc_NotImplementedError, "FSSpec not yet done for OSX");
1036 return NULL;
1037#else
Jack Jansen8bb573e1999-12-12 21:37:14 +00001038 return newmfssobject(v);
Jack Jansen0194ad52001-05-12 22:46:35 +00001039#endif
Jack Jansen8bb573e1999-12-12 21:37:14 +00001040}
Guido van Rossum8f691791995-01-18 23:57:26 +00001041
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001042/* Convert a Python object to a Rect.
Guido van Rossum5279ec61995-01-26 22:56:59 +00001043 The object must be a (left, top, right, bottom) tuple.
1044 (This differs from the order in the struct but is consistent with
1045 the arguments to SetRect(), and also with STDWIN). */
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001046int
1047PyMac_GetRect(PyObject *v, Rect *r)
Guido van Rossum8f691791995-01-18 23:57:26 +00001048{
Guido van Rossum5279ec61995-01-26 22:56:59 +00001049 return PyArg_Parse(v, "(hhhh)", &r->left, &r->top, &r->right, &r->bottom);
Guido van Rossum8f691791995-01-18 23:57:26 +00001050}
Guido van Rossumb3404661995-01-22 18:36:13 +00001051
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001052/* Convert a Rect to a Python object */
Guido van Rossumb3404661995-01-22 18:36:13 +00001053PyObject *
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001054PyMac_BuildRect(Rect *r)
Guido van Rossumb3404661995-01-22 18:36:13 +00001055{
Guido van Rossum5279ec61995-01-26 22:56:59 +00001056 return Py_BuildValue("(hhhh)", r->left, r->top, r->right, r->bottom);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001057}
1058
1059
1060/* Convert a Python object to a Point.
Guido van Rossum5279ec61995-01-26 22:56:59 +00001061 The object must be a (h, v) tuple.
1062 (This differs from the order in the struct but is consistent with
1063 the arguments to SetPoint(), and also with STDWIN). */
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001064int
1065PyMac_GetPoint(PyObject *v, Point *p)
1066{
Guido van Rossum5279ec61995-01-26 22:56:59 +00001067 return PyArg_Parse(v, "(hh)", &p->h, &p->v);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001068}
1069
1070/* Convert a Point to a Python object */
1071PyObject *
1072PyMac_BuildPoint(Point p)
1073{
Guido van Rossum5279ec61995-01-26 22:56:59 +00001074 return Py_BuildValue("(hh)", p.h, p.v);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001075}
1076
1077
1078/* Convert a Python object to an EventRecord.
1079 The object must be a (what, message, when, (v, h), modifiers) tuple. */
1080int
1081PyMac_GetEventRecord(PyObject *v, EventRecord *e)
1082{
1083 return PyArg_Parse(v, "(hll(hh)h)",
1084 &e->what,
1085 &e->message,
1086 &e->when,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001087 &e->where.h,
Guido van Rossum5279ec61995-01-26 22:56:59 +00001088 &e->where.v,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001089 &e->modifiers);
1090}
1091
1092/* Convert a Rect to an EventRecord object */
1093PyObject *
1094PyMac_BuildEventRecord(EventRecord *e)
1095{
1096 return Py_BuildValue("(hll(hh)h)",
1097 e->what,
1098 e->message,
1099 e->when,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001100 e->where.h,
Guido van Rossum5279ec61995-01-26 22:56:59 +00001101 e->where.v,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001102 e->modifiers);
Guido van Rossumb3404661995-01-22 18:36:13 +00001103}
Jack Jansenfa4d5d01995-11-15 15:19:29 +00001104
1105/* Convert Python object to Fixed */
1106int
1107PyMac_GetFixed(PyObject *v, Fixed *f)
1108{
1109 double d;
1110
1111 if( !PyArg_Parse(v, "d", &d))
1112 return 0;
1113 *f = (Fixed)(d * 0x10000);
Jack Jansen31dd5c01996-05-31 13:01:39 +00001114 return 1;
Jack Jansenfa4d5d01995-11-15 15:19:29 +00001115}
1116
1117/* Convert a Point to a Python object */
1118PyObject *
1119PyMac_BuildFixed(Fixed f)
1120{
1121 double d;
1122
1123 d = f;
1124 d = d / 0x10000;
1125 return Py_BuildValue("d", d);
1126}
1127
Jack Jansend58cd631998-04-21 15:24:39 +00001128/* Convert wide to/from Python int or (hi, lo) tuple. XXXX Should use Python longs */
1129int
1130PyMac_Getwide(PyObject *v, wide *rv)
1131{
1132 if (PyInt_Check(v)) {
1133 rv->hi = 0;
1134 rv->lo = PyInt_AsLong(v);
1135 if( rv->lo & 0x80000000 )
1136 rv->hi = -1;
1137 return 1;
1138 }
1139 return PyArg_Parse(v, "(ll)", &rv->hi, &rv->lo);
1140}
1141
1142
1143PyObject *
Jack Jansenbbf4be21998-04-23 13:20:17 +00001144PyMac_Buildwide(wide *w)
Jack Jansend58cd631998-04-21 15:24:39 +00001145{
Jack Jansenbbf4be21998-04-23 13:20:17 +00001146 if ( (w->hi == 0 && (w->lo & 0x80000000) == 0) ||
1147 (w->hi == -1 && (w->lo & 0x80000000) ) )
1148 return PyInt_FromLong(w->lo);
1149 return Py_BuildValue("(ll)", w->hi, w->lo);
Jack Jansend58cd631998-04-21 15:24:39 +00001150}
Jack Jansen8bb1dc12001-05-19 12:31:09 +00001151
1152#ifdef USE_TOOLBOX_OBJECT_GLUE
1153/*
1154** Glue together the toolbox objects.
1155**
1156** Because toolbox modules interdepend on each other, they use each others
1157** object types, on MacOSX/MachO this leads to the situation that they
1158** cannot be dynamically loaded (or they would all have to be lumped into
1159** a single .so, but this would be bad for extensibility).
1160**
1161** This file defines wrappers for all the _New and _Convert functions,
1162** which are the Py_BuildValue and PyArg_ParseTuple helpers. The wrappers
1163** check an indirection function pointer, and if it isn't filled in yet
1164** they import the appropriate module, whose init routine should fill in
1165** the pointer.
1166*/
1167
1168#define GLUE_NEW(object, routinename, module) \
1169PyObject *(*PyMacGluePtr_##routinename)(object); \
1170\
1171PyObject *routinename(object cobj) { \
1172 if (!PyMacGluePtr_##routinename) { \
1173 if (!PyImport_ImportModule(module)) return NULL; \
1174 if (!PyMacGluePtr_##routinename) { \
1175 PyErr_SetString(PyExc_ImportError, "Module did not provide routine: " module ": " #routinename); \
1176 return NULL; \
1177 } \
1178 } \
1179 return (*PyMacGluePtr_##routinename)(cobj); \
1180}
1181
1182#define GLUE_CONVERT(object, routinename, module) \
1183int (*PyMacGluePtr_##routinename)(PyObject *, object *); \
1184\
1185int routinename(PyObject *pyobj, object *cobj) { \
1186 if (!PyMacGluePtr_##routinename) { \
1187 if (!PyImport_ImportModule(module)) return NULL; \
1188 if (!PyMacGluePtr_##routinename) { \
1189 PyErr_SetString(PyExc_ImportError, "Module did not provide routine: " module ": " #routinename); \
1190 return NULL; \
1191 } \
1192 } \
1193 return (*PyMacGluePtr_##routinename)(pyobj, cobj); \
1194}
1195
1196GLUE_NEW(AppleEvent *, AEDesc_New, "AE") /* XXXX Why by address? */
1197GLUE_CONVERT(AppleEvent, AEDesc_Convert, "AE")
1198
1199GLUE_NEW(Component, CmpObj_New, "Cm")
1200GLUE_CONVERT(Component, CmpObj_Convert, "Cm")
1201GLUE_NEW(ComponentInstance, CmpInstObj_New, "Cm")
1202GLUE_CONVERT(ComponentInstance, CmpInstObj_Convert, "Cm")
1203
1204GLUE_NEW(ControlHandle, CtlObj_New, "Ctl")
1205GLUE_CONVERT(ControlHandle, CtlObj_Convert, "Ctl")
1206
1207GLUE_NEW(DialogPtr, DlgObj_New, "Dlg")
1208GLUE_CONVERT(DialogPtr, DlgObj_Convert, "Dlg")
1209GLUE_NEW(DialogPtr, DlgObj_WhichDialog, "Dlg")
1210
1211GLUE_NEW(DragReference, DragObj_New, "Drag")
1212GLUE_CONVERT(DragReference, DragObj_Convert, "Drag")
1213
1214GLUE_NEW(ListHandle, ListObj_New, "List")
1215GLUE_CONVERT(ListHandle, ListObj_Convert, "List")
1216
1217GLUE_NEW(MenuHandle, MenuObj_New, "Menu")
1218GLUE_CONVERT(MenuHandle, MenuObj_Convert, "Menu")
1219
1220GLUE_NEW(GrafPtr, GrafObj_New, "Qd")
1221GLUE_CONVERT(GrafPtr, GrafObj_Convert, "Qd")
1222GLUE_NEW(BitMapPtr, BMObj_New, "Qd")
1223GLUE_CONVERT(BitMapPtr, BMObj_Convert, "Qd")
1224GLUE_NEW(RGBColor *, QdRGB_New, "Qd") /* XXXX Why? */
1225GLUE_CONVERT(RGBColor, QdRGB_Convert, "Qd")
1226
1227GLUE_NEW(GWorldPtr, GWorldObj_New, "Qdoffs")
1228GLUE_CONVERT(GWorldPtr, GWorldObj_Convert, "Qdoffs")
1229
1230GLUE_NEW(Track, TrackObj_New, "Qt")
1231GLUE_CONVERT(Track, TrackObj_Convert, "Qt")
1232GLUE_NEW(Movie, MovieObj_New, "Qt")
1233GLUE_CONVERT(Movie, MovieObj_Convert, "Qt")
1234GLUE_NEW(MovieController, MovieCtlObj_New, "Qt")
1235GLUE_CONVERT(MovieController, MovieCtlObj_Convert, "Qt")
1236GLUE_NEW(TimeBase, TimeBaseObj_New, "Qt")
1237GLUE_CONVERT(TimeBase, TimeBaseObj_Convert, "Qt")
1238GLUE_NEW(UserData, UserDataObj_New, "Qt")
1239GLUE_CONVERT(UserData, UserDataObj_Convert, "Qt")
1240GLUE_NEW(Media, MediaObj_New, "Qt")
1241GLUE_CONVERT(Media, MediaObj_Convert, "Qt")
1242
1243GLUE_NEW(Handle, ResObj_New, "Res")
1244GLUE_CONVERT(Handle, ResObj_Convert, "Res")
1245GLUE_NEW(Handle, OptResObj_New, "Res")
1246GLUE_CONVERT(Handle, OptResObj_Convert, "Res")
1247
1248GLUE_NEW(TEHandle, TEObj_New, "TE")
1249GLUE_CONVERT(TEHandle, TEObj_Convert, "TE")
1250
1251GLUE_NEW(WindowPtr, WinObj_New, "Win")
1252GLUE_CONVERT(WindowPtr, WinObj_Convert, "Win")
1253GLUE_NEW(WindowPtr, WinObj_WhichWindow, "Win")
1254
1255#endif /* USE_TOOLBOX_OBJECT_GLUE */