blob: 844ee42d5b2f2a29710b519827b2df362e6fb4c3 [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 Jansenf93c72a1994-12-14 14:07:50 +000032
Jack Jansen819f1771995-08-14 12:35:10 +000033#include "pythonresources.h"
34
Jack Jansen0194ad52001-05-12 22:46:35 +000035#ifdef WITHOUT_FRAMEWORKS
Jack Jansenf93c72a1994-12-14 14:07:50 +000036#include <OSUtils.h> /* for Set(Current)A5 */
Jack Jansene8e8ae01995-01-26 16:36:45 +000037#include <Files.h>
Jack Jansen8cd2b721995-02-13 11:33:28 +000038#include <StandardFile.h>
Jack Jansenf93c72a1994-12-14 14:07:50 +000039#include <Resources.h>
40#include <Memory.h>
Jack Jansenf93c72a1994-12-14 14:07:50 +000041#include <Windows.h>
Jack Jansene8e8ae01995-01-26 16:36:45 +000042#include <Traps.h>
Jack Jansenee23d6e1995-01-27 14:43:25 +000043#include <Processes.h>
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +000044#include <Fonts.h>
45#include <Menus.h>
Jack Jansen08305501995-06-18 20:03:40 +000046#include <TextUtils.h>
Jack Jansen0194ad52001-05-12 22:46:35 +000047#include <LowMem.h>
48#ifdef __CFM68K__
49/* cfm68k InterfaceLib exports GetEventQueue, but Events.h doesn't know this
50** and defines it as GetEvQHdr (which is correct for PPC). This fix is for
51** CW9, check that the workaround is still needed for the next release.
52*/
53#define GetEvQHdr GetEventQueue
54#endif /* __CFM68K__ */
55
56#include <Events.h>
57
58#ifdef __CFM68K__
59#undef GetEventQueue
60#endif /* __CFM68K__ */
61#else
62#include <Carbon/Carbon.h>
63#endif
64
65#if !TARGET_API_MAC_OS8
66/* Unfortunately this call is probably slower... */
67#define LMGetTicks() TickCount()
68#endif
69
Jack Jansen16df2aa1995-02-27 16:17:28 +000070#ifdef __MWERKS__
71#include <SIOUX.h>
Jack Jansen9ae898b2000-07-11 21:16:03 +000072extern void SIOUXSetupMenus(void);
73extern void SIOUXDoAboutBox(void);
Jack Jansen16df2aa1995-02-27 16:17:28 +000074#endif
Jack Jansen9ae898b2000-07-11 21:16:03 +000075#ifdef USE_GUSI
76/* Functions we redefine because they're in obscure libraries */
77extern void SpinCursor(short x);
78extern void RotateCursor(short x);
79extern pascal void PLstrcpy(unsigned char *, unsigned char *);
80extern pascal int PLstrcmp(unsigned char *, unsigned char *);
81extern pascal unsigned char *PLstrrchr(unsigned char *, unsigned char);
82
83#endif
84
Jack Jansen2d1306b2000-04-07 09:10:49 +000085#ifdef USE_GUSI1
Jack Jansen911ad6b1996-03-05 16:56:24 +000086#include <TFileSpec.h> /* For Path2FSSpec */
Jack Jansenf6865f71996-09-04 15:24:59 +000087#include <GUSI.h>
Jack Jansen911ad6b1996-03-05 16:56:24 +000088#endif
Jack Jansenee23d6e1995-01-27 14:43:25 +000089
Jack Jansen3469e991996-09-06 00:30:45 +000090/* The ID of the Sioux apple menu */
91#define SIOUX_APPLEID 32000
92
Jack Jansenee23d6e1995-01-27 14:43:25 +000093#include <signal.h>
Jack Jansen74162f31995-02-15 22:58:33 +000094#include <stdio.h>
Jack Jansene8e8ae01995-01-26 16:36:45 +000095
Jack Jansenee23d6e1995-01-27 14:43:25 +000096/*
Jack Jansend1f06311996-08-01 15:23:54 +000097** When less than this amount of stackspace is left we
98** raise a MemoryError.
99*/
100#ifndef MINIMUM_STACK_SIZE
101#ifdef __powerc
102#define MINIMUM_STACK_SIZE 8192
103#else
104#define MINIMUM_STACK_SIZE 4096
105#endif
106#endif
107
Jack Jansen340eb882001-02-02 22:40:28 +0000108#if TARGET_API_MAC_CARBON
109/*
110** On MacOSX StackSpace() lies: it gives the distance from heap end to stack pointer,
111** but the stack cannot grow that far due to rlimit values. We cannot get at this value
112** from Carbon, so we set a maximum to the stack here that is based on the default
113** stack limit of 512K.
114*/
115#define MAXIMUM_STACK_SIZE (256*1024)
116#endif
117
Jack Jansend1f06311996-08-01 15:23:54 +0000118/*
Jack Jansen16df2aa1995-02-27 16:17:28 +0000119** We have to be careful, since we can't handle
Jack Jansenee23d6e1995-01-27 14:43:25 +0000120** things like updates (and they'll keep coming back if we don't
Jack Jansen16df2aa1995-02-27 16:17:28 +0000121** handle them). Note that we don't know who has windows open, so
122** even handing updates off to SIOUX under MW isn't going to work.
Jack Jansenee23d6e1995-01-27 14:43:25 +0000123*/
Jack Jansen0c968871997-08-26 13:20:34 +0000124#define MAINLOOP_EVENTMASK (mDownMask|keyDownMask|osMask|activMask)
Jack Jansene8e8ae01995-01-26 16:36:45 +0000125
126#include <signal.h>
Jack Jansenf93c72a1994-12-14 14:07:50 +0000127
Guido van Rossumb3404661995-01-22 18:36:13 +0000128/* XXX We should include Errors.h here, but it has a name conflict
Jack Jansen5f653091995-01-18 13:53:49 +0000129** with the python errors.h. */
130#define fnfErr -43
131
Jack Jansene8e8ae01995-01-26 16:36:45 +0000132/* Declared in macfsmodule.c: */
Jack Jansen9ae898b2000-07-11 21:16:03 +0000133extern FSSpec *mfs_GetFSSpecFSSpec(PyObject *);
Jack Jansend88296d2000-07-11 19:51:05 +0000134extern PyObject *newmfssobject(FSSpec *);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000135
Jack Jansenee23d6e1995-01-27 14:43:25 +0000136/* Interrupt code variables: */
137static int interrupted; /* Set to true when cmd-. seen */
Jack Jansend88296d2000-07-11 19:51:05 +0000138static RETSIGTYPE intcatcher(int);
Jack Jansenee23d6e1995-01-27 14:43:25 +0000139
Jack Jansen0194ad52001-05-12 22:46:35 +0000140#if !TARGET_API_MAC_OSX
Jack Jansend88296d2000-07-11 19:51:05 +0000141static int PyMac_Yield(void);
Jack Jansen0194ad52001-05-12 22:46:35 +0000142#endif
Jack Jansenf6865f71996-09-04 15:24:59 +0000143
Jack Jansene8e8ae01995-01-26 16:36:45 +0000144/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000145** These are the real scheduling parameters that control what we check
146** in the event loop, and how often we check. The values are initialized
147** from pyMac_SchedParamStruct.
148*/
149
150struct real_sched_param_struct {
151 int check_interrupt; /* if true check for command-dot */
152 int process_events; /* if nonzero enable evt processing, this mask */
153 int besocial; /* if nonzero be a little social with CPU */
154 unsigned long check_interval; /* how often to check, in ticks */
155 unsigned long bg_yield; /* yield so long when in background */
156 /* these are computed from previous and clock and such */
157 int enabled; /* check_interrupt OR process_event OR yield */
158 unsigned long next_check; /* when to check/yield next, in ticks */
159};
160
161static struct real_sched_param_struct schedparams =
162 { 1, MAINLOOP_EVENTMASK, 1, 15, 15, 1, 0};
163
Jack Jansen819f1771995-08-14 12:35:10 +0000164/*
Jack Jansenf6865f71996-09-04 15:24:59 +0000165** Workaround for sioux/gusi combo: set when we are exiting
166*/
167int PyMac_ConsoleIsDead;
168
169/*
Jack Jansencaa7c461997-06-12 10:49:13 +0000170** Sioux menu bar, saved early so we can restore it
171*/
Jack Jansen657ba272001-02-17 22:02:07 +0000172static MenuBarHandle sioux_mbar;
Jack Jansencaa7c461997-06-12 10:49:13 +0000173
174/*
Jack Jansen819f1771995-08-14 12:35:10 +0000175** Some stuff for our GetDirectory and PromptGetFile routines
176*/
177struct hook_args {
178 int selectcur_hit; /* Set to true when "select current" selected */
179 char *prompt; /* The prompt */
180};
Jack Jansen6e68a7e2001-05-12 21:31:34 +0000181#if !TARGET_API_MAC_OS8
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000182/* The StandardFile hooks don't exist in Carbon. This breaks GetDirectory,
183** but the macfsn code will replace it by a NavServices version anyway.
184*/
185#define myhook_upp NULL
186#else
Jack Jansen819f1771995-08-14 12:35:10 +0000187static DlgHookYDUPP myhook_upp;
188static int upp_inited = 0;
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000189#endif
Jack Jansen819f1771995-08-14 12:35:10 +0000190
Jack Jansen36ed5061997-06-20 16:18:15 +0000191/*
192** The python-code event handler
193*/
194static PyObject *python_event_handler;
195
Jack Jansen8f5725a1999-12-07 23:08:10 +0000196/*
197** Set to true if we're appearance-compliant
198*/
199int PyMac_AppearanceCompliant;
200
Jack Jansen1f9f2f42000-07-24 19:50:16 +0000201/*
202** Find out what the current script is.
203** Donated by Fredrik Lund.
204*/
205char *PyMac_getscript()
206{
207 int font, script, lang;
208 font = 0;
209 font = GetSysFont();
210 script = FontToScript(font);
211 switch (script) {
212 case smRoman:
213 lang = GetScriptVariable(script, smScriptLang);
214 if (lang == langIcelandic)
215 return "mac-iceland";
216 else if (lang == langTurkish)
217 return "mac-turkish";
218 else if (lang == langGreek)
219 return "mac-greek";
220 else
221 return "mac-roman";
222 break;
223 case smJapanese:
224 return "mac-japan";
225 case smGreek:
226 return "mac-greek";
227 case smCyrillic:
228 return "mac-cyrillic";
229 default:
230 return "mac-roman"; /* better than nothing */
231 }
232}
233
234
Jack Jansen2d1306b2000-04-07 09:10:49 +0000235#ifdef USE_GUSI1
Jack Jansen378815c1996-03-06 16:21:34 +0000236/*
237** GUSI (1.6.0 and earlier, at the least) do not set the MacOS idea of
238** the working directory. Hence, we call this routine after each call
239** to chdir() to rectify things.
240*/
241void
242PyMac_FixGUSIcd()
243{
244 WDPBRec pb;
245 FSSpec curdirfss;
246
247 if ( Path2FSSpec(":x", &curdirfss) != noErr )
248 return;
249
250 /* Set MacOS "working directory" */
251 pb.ioNamePtr= "\p";
252 pb.ioVRefNum= curdirfss.vRefNum;
253 pb.ioWDDirID= curdirfss.parID;
Jack Jansen08c3be31997-04-08 15:27:00 +0000254 if (PBHSetVolSync(&pb) != noErr)
Jack Jansen378815c1996-03-06 16:21:34 +0000255 return;
Jack Jansen378815c1996-03-06 16:21:34 +0000256}
Jack Jansen2d1306b2000-04-07 09:10:49 +0000257#endif
Jack Jansen7ac70af1996-08-19 11:01:05 +0000258
Jack Jansen2d1306b2000-04-07 09:10:49 +0000259#ifdef USE_GUSI
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000260/*
261** SpinCursor (needed by GUSI) drags in heaps of stuff, so we
262** provide a dummy here.
263*/
Jack Jansencfadbd41996-08-19 11:36:25 +0000264void SpinCursor(short x) { /* Dummy */ }
Jack Jansenefaada71998-02-20 16:03:15 +0000265void RotateCursor(short x) { /* Dummy */ }
Jack Jansencfadbd41996-08-19 11:36:25 +0000266
Jack Jansenf6865f71996-09-04 15:24:59 +0000267/*
268** Replacement GUSI Spin function
269*/
Jack Jansen2d1306b2000-04-07 09:10:49 +0000270#ifdef USE_GUSI1
Jack Jansenf6865f71996-09-04 15:24:59 +0000271static int
272PyMac_GUSISpin(spin_msg msg, long arg)
273{
Jack Jansene3ae0df1997-06-03 15:28:29 +0000274 static Boolean inForeground = true;
275 int maxsleep = 6; /* 6 ticks is "normal" sleeptime */
Jack Jansenf6865f71996-09-04 15:24:59 +0000276
277 if (PyMac_ConsoleIsDead) return 0;
278#if 0
279 if (inForeground)
280 SpinCursor(msg == SP_AUTO_SPIN ? short(arg) : 1);
281#endif
282
283 if (interrupted) return -1;
284
Jack Jansene3ae0df1997-06-03 15:28:29 +0000285 if ( msg == SP_AUTO_SPIN )
286 maxsleep = 0;
287 if ( msg==SP_SLEEP||msg==SP_SELECT )
288 maxsleep = arg;
Jack Jansenf6865f71996-09-04 15:24:59 +0000289
Jack Jansene3ae0df1997-06-03 15:28:29 +0000290 PyMac_DoYield(maxsleep, 0); /* XXXX or is it safe to call python here? */
Jack Jansenf6865f71996-09-04 15:24:59 +0000291
292 return 0;
293}
294
295void
296PyMac_SetGUSISpin() {
297 GUSISetHook(GUSI_SpinHook, (GUSIHook)PyMac_GUSISpin);
298}
Jack Jansen2d1306b2000-04-07 09:10:49 +0000299#endif
Jack Jansenf6865f71996-09-04 15:24:59 +0000300
Jack Jansena39f1b01997-05-23 15:35:14 +0000301/* Called at exit() time thru atexit(), to stop event processing */
302void
303PyMac_StopGUSISpin() {
304 PyMac_ConsoleIsDead = 1;
305}
306
Jack Jansen6e68a7e2001-05-12 21:31:34 +0000307#if TARGET_API_MAC_OS8
Jack Jansena39f1b01997-05-23 15:35:14 +0000308/*
309** Replacement routines for the PLstr... functions so we don't need
Jack Jansen6ba34aa2001-01-11 23:03:56 +0000310** StdCLib.
Jack Jansena39f1b01997-05-23 15:35:14 +0000311*/
Jack Jansen8bb573e1999-12-12 21:37:14 +0000312pascal void
Jack Jansen9ae898b2000-07-11 21:16:03 +0000313PLstrcpy(unsigned char *to, unsigned char *fr)
Jack Jansena39f1b01997-05-23 15:35:14 +0000314{
315 memcpy(to, fr, fr[0]+1);
316}
317
Jack Jansen8bb573e1999-12-12 21:37:14 +0000318pascal int
Jack Jansen9ae898b2000-07-11 21:16:03 +0000319PLstrcmp(unsigned char *s1, unsigned char *s2)
Jack Jansena39f1b01997-05-23 15:35:14 +0000320{
321 int res;
322 int l = s1[0] < s2[0] ? s1[0] : s2[0];
323
324 res = memcmp(s1+1, s2+1, l);
325 if ( res != 0 )
326 return res;
327
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000328 if ( s1[0] < s2[0] )
Jack Jansena39f1b01997-05-23 15:35:14 +0000329 return -1;
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000330 else if ( s1[0] > s2[0] )
Jack Jansena39f1b01997-05-23 15:35:14 +0000331 return 1;
332 else
333 return 0;
334}
335
Jack Jansen8bb573e1999-12-12 21:37:14 +0000336pascal unsigned char *
Jack Jansen9ae898b2000-07-11 21:16:03 +0000337PLstrrchr(unsigned char *str, unsigned char chr)
Jack Jansena39f1b01997-05-23 15:35:14 +0000338{
339 unsigned char *ptr = 0;
340 unsigned char *p;
341
342 for(p=str+1; p<str+str[0]; p++)
343 if ( *p == chr )
344 ptr = p;
345 return ptr;
346}
347
Jack Jansen6e68a7e2001-05-12 21:31:34 +0000348#endif /* TARGET_API_MAC_OS8 */
Jack Jansena39f1b01997-05-23 15:35:14 +0000349#endif /* USE_GUSI */
Jack Jansen378815c1996-03-06 16:21:34 +0000350
Jack Jansen819f1771995-08-14 12:35:10 +0000351
Jack Jansen5f653091995-01-18 13:53:49 +0000352/* Convert C to Pascal string. Returns pointer to static buffer. */
353unsigned char *
354Pstring(char *str)
355{
356 static Str255 buf;
357 int len;
358
359 len = strlen(str);
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000360 if (len > 255)
361 len = 255;
Jack Jansen5f653091995-01-18 13:53:49 +0000362 buf[0] = (unsigned char)len;
363 strncpy((char *)buf+1, str, len);
364 return buf;
365}
366
Jack Jansen6e68a7e2001-05-12 21:31:34 +0000367#if TARGET_API_MAC_OS8
Jack Jansen5afad832000-12-12 22:12:14 +0000368void
369c2pstrcpy(unsigned char *dst, const char *src)
370{
371 int len;
372
373 len = strlen(src);
374 if ( len > 255 ) len = 255;
375 strncpy((char *)dst+1, src, len);
376 dst[0] = len;
377}
Jack Jansen6e68a7e2001-05-12 21:31:34 +0000378#endif /* TARGET_API_MAC_OS8 */
Jack Jansen5afad832000-12-12 22:12:14 +0000379
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000380/* Like strerror() but for Mac OS error numbers */
381char *PyMac_StrError(int err)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000382{
383 static char buf[256];
384 Handle h;
385 char *str;
386
387 h = GetResource('Estr', err);
388 if ( h ) {
389 HLock(h);
390 str = (char *)*h;
391 memcpy(buf, str+1, (unsigned char)str[0]);
Guido van Rossumcc9bc8f1995-02-13 16:17:03 +0000392 buf[(unsigned char)str[0]] = '\0';
Jack Jansenf93c72a1994-12-14 14:07:50 +0000393 HUnlock(h);
394 ReleaseResource(h);
395 } else {
396 sprintf(buf, "Mac OS error code %d", err);
397 }
398 return buf;
399}
400
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000401/* Exception object shared by all Mac specific modules for Mac OS errors */
402PyObject *PyMac_OSErrException;
403
404/* Initialize and return PyMac_OSErrException */
405PyObject *
406PyMac_GetOSErrException()
407{
408 if (PyMac_OSErrException == NULL)
409 PyMac_OSErrException = PyString_FromString("Mac OS Error");
410 return PyMac_OSErrException;
411}
412
Jack Jansenf93c72a1994-12-14 14:07:50 +0000413/* Set a MAC-specific error from errno, and return NULL; return None if no error */
414PyObject *
Guido van Rossumfffb8bb1995-01-12 12:37:24 +0000415PyErr_Mac(PyObject *eobj, int err)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000416{
417 char *msg;
418 PyObject *v;
Jack Jansenf93c72a1994-12-14 14:07:50 +0000419
Guido van Rossum8f691791995-01-18 23:57:26 +0000420 if (err == 0 && !PyErr_Occurred()) {
Jack Jansenf93c72a1994-12-14 14:07:50 +0000421 Py_INCREF(Py_None);
422 return Py_None;
423 }
Guido van Rossum8f691791995-01-18 23:57:26 +0000424 if (err == -1 && PyErr_Occurred())
425 return NULL;
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000426 msg = PyMac_StrError(err);
Jack Jansenf93c72a1994-12-14 14:07:50 +0000427 v = Py_BuildValue("(is)", err, msg);
428 PyErr_SetObject(eobj, v);
429 Py_DECREF(v);
430 return NULL;
431}
432
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000433/* Call PyErr_Mac with PyMac_OSErrException */
434PyObject *
435PyMac_Error(OSErr err)
436{
437 return PyErr_Mac(PyMac_GetOSErrException(), err);
438}
439
Jack Jansen1ed95291996-07-22 15:25:10 +0000440#ifdef USE_STACKCHECK
441/* Check for stack overflow */
442int
443PyOS_CheckStack()
444{
Jack Jansen14a91712000-08-25 21:57:23 +0000445 char here;
446 static char *sentinel = 0;
Jack Jansen53bafd92000-09-08 22:05:48 +0000447 static PyThreadState *thread_for_sentinel = 0;
Jack Jansen1ed95291996-07-22 15:25:10 +0000448
Jack Jansen340eb882001-02-02 22:40:28 +0000449 if ( sentinel == 0 ) {
450 unsigned long stackspace = StackSpace();
451
452#ifdef MAXIMUM_STACK_SIZE
453 /* See the comment at the definition */
454 if ( stackspace > MAXIMUM_STACK_SIZE )
455 stackspace = MAXIMUM_STACK_SIZE;
456#endif
457 sentinel = &here - stackspace + MINIMUM_STACK_SIZE;
Jack Jansen14a91712000-08-25 21:57:23 +0000458 }
Jack Jansen53bafd92000-09-08 22:05:48 +0000459 if ( thread_for_sentinel == 0 ) {
460 thread_for_sentinel = PyThreadState_Get();
461 }
462 if ( &here < sentinel ) {
463 if (thread_for_sentinel == PyThreadState_Get()) {
464 return -1;
465#if 0
466 } else {
467 /* Else we are unsure... */
468 fprintf(stderr, "Stackcheck in other thread (was %x now %x)\n", thread_for_sentinel,PyThreadState_Get());
469#endif
470 }
471 }
Jack Jansen1ed95291996-07-22 15:25:10 +0000472 return 0;
473}
474#endif /* USE_STACKCHECK */
475
Jack Jansen0194ad52001-05-12 22:46:35 +0000476#if !TARGET_API_MAC_OSX
Jack Jansenee23d6e1995-01-27 14:43:25 +0000477/* The catcher routine (which may not be used for all compilers) */
478static RETSIGTYPE
479intcatcher(sig)
480 int sig;
481{
482 interrupted = 1;
483 signal(SIGINT, intcatcher);
484}
485
486void
487PyOS_InitInterrupts()
488{
489 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
490 signal(SIGINT, intcatcher);
491}
492
Jack Jansena8441de1997-08-08 14:57:37 +0000493void
494PyOS_FiniInterrupts()
495{
496}
497
Jack Jansenee23d6e1995-01-27 14:43:25 +0000498/*
499** This routine scans the event queue looking for cmd-.
500** This is the only way to get an interrupt under THINK (since it
501** doesn't do SIGINT handling), but is also used under MW, when
502** the full-fledged event loop is disabled. This way, we can at least
503** interrupt a runaway python program.
504*/
505static void
506scan_event_queue(flush)
507 int flush;
508{
Jack Jansen6e68a7e2001-05-12 21:31:34 +0000509#if !TARGET_API_MAC_OS8
Jack Jansend7b68022001-01-12 23:42:28 +0000510 if ( CheckEventQueueForUserCancel() )
511 interrupted = 1;
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000512#else
Jack Jansenee23d6e1995-01-27 14:43:25 +0000513 register EvQElPtr q;
514
Jack Jansenefaada71998-02-20 16:03:15 +0000515 q = (EvQElPtr) LMGetEventQueue()->qHead;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000516
517 for (; q; q = (EvQElPtr)q->qLink) {
518 if (q->evtQWhat == keyDown &&
519 (char)q->evtQMessage == '.' &&
520 (q->evtQModifiers & cmdKey) != 0) {
521 if ( flush )
522 FlushEvents(keyDownMask, 0);
523 interrupted = 1;
524 break;
525 }
526 }
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000527#endif
Jack Jansenee23d6e1995-01-27 14:43:25 +0000528}
529
530int
Jack Jansen36ed5061997-06-20 16:18:15 +0000531PyErr_CheckSignals()
Jack Jansenee23d6e1995-01-27 14:43:25 +0000532{
Jack Jansene3ae0df1997-06-03 15:28:29 +0000533 if (schedparams.enabled) {
534 if ( (unsigned long)LMGetTicks() > schedparams.next_check ) {
Jack Jansen36ed5061997-06-20 16:18:15 +0000535 if ( PyMac_Yield() < 0)
536 return -1;
Jack Jansene3ae0df1997-06-03 15:28:29 +0000537 schedparams.next_check = (unsigned long)LMGetTicks()
538 + schedparams.check_interval;
539 if (interrupted) {
Jack Jansencaa7c461997-06-12 10:49:13 +0000540 scan_event_queue(1); /* Eat events up to cmd-. */
Jack Jansene3ae0df1997-06-03 15:28:29 +0000541 interrupted = 0;
Jack Jansen36ed5061997-06-20 16:18:15 +0000542 PyErr_SetNone(PyExc_KeyboardInterrupt);
543 return -1;
Jack Jansene3ae0df1997-06-03 15:28:29 +0000544 }
545 }
Jack Jansenee23d6e1995-01-27 14:43:25 +0000546 }
547 return 0;
548}
549
Jack Jansen36ed5061997-06-20 16:18:15 +0000550int
551PyOS_InterruptOccurred()
552{
553 scan_event_queue(1);
554 return interrupted;
555}
Jack Jansen0194ad52001-05-12 22:46:35 +0000556
Jack Jansenee23d6e1995-01-27 14:43:25 +0000557/* Check whether we are in the foreground */
Jack Jansen9ae898b2000-07-11 21:16:03 +0000558static int
559PyMac_InForeground(void)
Jack Jansenee23d6e1995-01-27 14:43:25 +0000560{
561 static ProcessSerialNumber ours;
562 static inited;
563 ProcessSerialNumber curfg;
564 Boolean eq;
565
Jack Jansene3ae0df1997-06-03 15:28:29 +0000566 if ( inited == 0 ) {
Jack Jansenee23d6e1995-01-27 14:43:25 +0000567 (void)GetCurrentProcess(&ours);
Jack Jansene3ae0df1997-06-03 15:28:29 +0000568 inited = 1;
569 }
Jack Jansenee23d6e1995-01-27 14:43:25 +0000570 if ( GetFrontProcess(&curfg) < 0 )
571 eq = 1;
572 else if ( SameProcess(&ours, &curfg, &eq) < 0 )
573 eq = 1;
574 return (int)eq;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000575}
Jack Jansen0194ad52001-05-12 22:46:35 +0000576#endif
Jack Jansenee23d6e1995-01-27 14:43:25 +0000577
Jack Jansen36ed5061997-06-20 16:18:15 +0000578int
579PyMac_SetEventHandler(PyObject *evh)
580{
581 if ( evh && python_event_handler ) {
582 PyErr_SetString(PyExc_RuntimeError, "Python event handler already set");
583 return 0;
584 }
585 if ( python_event_handler )
586 Py_DECREF(python_event_handler);
587 if ( evh )
588 Py_INCREF(evh);
589 python_event_handler = evh;
590 return 1;
591}
592
Jack Jansenf93c72a1994-12-14 14:07:50 +0000593/*
Jack Jansena76382a1995-02-02 14:25:56 +0000594** Handle an event, either one found in the mainloop eventhandler or
595** one passed back from the python program.
596*/
597void
Jack Jansen36ed5061997-06-20 16:18:15 +0000598PyMac_HandleEventIntern(evp)
Jack Jansena76382a1995-02-02 14:25:56 +0000599 EventRecord *evp;
600{
Jack Jansen6e68a7e2001-05-12 21:31:34 +0000601#if TARGET_API_MAC_OS8
Jack Jansen0c968871997-08-26 13:20:34 +0000602 if ( evp->what == mouseDown ) {
603 WindowPtr wp;
604
605 if ( FindWindow(evp->where, &wp) == inSysWindow ) {
606 SystemClick(evp, wp);
607 return;
608 }
609 }
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000610#endif
Jack Jansena76382a1995-02-02 14:25:56 +0000611#ifdef __MWERKS__
Jack Jansen38e97661995-11-10 14:53:00 +0000612 {
613 int siouxdidit;
614
615 /* If SIOUX wants it we're done */
616 siouxdidit = SIOUXHandleOneEvent(evp);
617 if ( siouxdidit )
618 return;
619 }
Jack Jansena76382a1995-02-02 14:25:56 +0000620#else
Jack Jansen0c968871997-08-26 13:20:34 +0000621 /* Other compilers are just unlucky... */
Jack Jansena76382a1995-02-02 14:25:56 +0000622#endif /* !__MWERKS__ */
Jack Jansen36ed5061997-06-20 16:18:15 +0000623}
624
625/*
626** Handle an event, either through HandleEvent or by passing it to the Python
627** event handler.
628*/
629int
630PyMac_HandleEvent(evp)
631 EventRecord *evp;
632{
633 PyObject *rv;
634
635 if ( python_event_handler ) {
636 rv = PyObject_CallFunction(python_event_handler, "(O&)",
637 PyMac_BuildEventRecord, evp);
638 if ( rv )
639 Py_DECREF(rv);
640 else
641 return -1; /* Propagate exception */
642 } else {
643 PyMac_HandleEventIntern(evp);
644 }
645 return 0;
Jack Jansena76382a1995-02-02 14:25:56 +0000646}
647
Jack Jansen0194ad52001-05-12 22:46:35 +0000648#if !TARGET_API_MAC_OSX
Jack Jansena76382a1995-02-02 14:25:56 +0000649/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000650** Yield the CPU to other tasks without processing events.
Jack Jansene8e8ae01995-01-26 16:36:45 +0000651*/
Jack Jansen2d1306b2000-04-07 09:10:49 +0000652int
Jack Jansene3ae0df1997-06-03 15:28:29 +0000653PyMac_DoYield(int maxsleep, int maycallpython)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000654{
655 EventRecord ev;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000656 int gotone;
Jack Jansene3ae0df1997-06-03 15:28:29 +0000657 long latest_time_ready;
Jack Jansen36ed5061997-06-20 16:18:15 +0000658 static int in_here = 0;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000659
Jack Jansen36ed5061997-06-20 16:18:15 +0000660 in_here++;
Jack Jansene3ae0df1997-06-03 15:28:29 +0000661 /*
662 ** First check for interrupts, if wanted.
663 ** This sets a flag that will be picked up at an appropriate
664 ** moment in the mainloop.
665 */
666 if (schedparams.check_interrupt)
Jack Jansenee23d6e1995-01-27 14:43:25 +0000667 scan_event_queue(0);
Jack Jansene3ae0df1997-06-03 15:28:29 +0000668
669 /* XXXX Implementing an idle routine goes here */
Jack Jansene8e8ae01995-01-26 16:36:45 +0000670
Jack Jansene3ae0df1997-06-03 15:28:29 +0000671 /*
672 ** Check which of the eventloop cases we have:
673 ** - process events
674 ** - don't process events but do yield
675 ** - do neither
676 */
Jack Jansen36ed5061997-06-20 16:18:15 +0000677 if( in_here > 1 || !schedparams.process_events ||
678 (python_event_handler && !maycallpython) ) {
Jack Jansene3ae0df1997-06-03 15:28:29 +0000679 if ( maxsleep >= 0 ) {
Jack Jansen6e68a7e2001-05-12 21:31:34 +0000680#if TARGET_API_MAC_OS8
Jack Jansene8e8ae01995-01-26 16:36:45 +0000681 SystemTask();
Jack Jansen15f1c082001-04-25 22:07:27 +0000682#else
683 int xxx = 0;
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000684#endif
Jack Jansen15f1c082001-04-25 22:07:27 +0000685 }
Jack Jansene3ae0df1997-06-03 15:28:29 +0000686 } else {
687 latest_time_ready = LMGetTicks() + maxsleep;
Jack Jansen2d1306b2000-04-07 09:10:49 +0000688 do {
Jack Jansen0c968871997-08-26 13:20:34 +0000689 /* XXXX Hack by Jack.
690 ** In time.sleep() you can click to another application
691 ** once only. If you come back to Python you cannot get away
692 ** again.
693 **/
Jack Jansen36ed5061997-06-20 16:18:15 +0000694 gotone = WaitNextEvent(schedparams.process_events, &ev, maxsleep, NULL);
Jack Jansene3ae0df1997-06-03 15:28:29 +0000695 /* Get out quickly if nothing interesting is happening */
696 if ( !gotone || ev.what == nullEvent )
697 break;
Jack Jansen36ed5061997-06-20 16:18:15 +0000698 if ( PyMac_HandleEvent(&ev) < 0 ) {
699 in_here--;
700 return -1;
701 }
Jack Jansene3ae0df1997-06-03 15:28:29 +0000702 maxsleep = latest_time_ready - LMGetTicks();
Jack Jansen2d1306b2000-04-07 09:10:49 +0000703 } while ( maxsleep > 0 );
Jack Jansenf93c72a1994-12-14 14:07:50 +0000704 }
Jack Jansen36ed5061997-06-20 16:18:15 +0000705 in_here--;
706 return 0;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000707}
708
709/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000710** Process events and/or yield the CPU to other tasks if opportune
Jack Jansene8e8ae01995-01-26 16:36:45 +0000711*/
Jack Jansen36ed5061997-06-20 16:18:15 +0000712int
Jack Jansene8e8ae01995-01-26 16:36:45 +0000713PyMac_Yield() {
Jack Jansene3ae0df1997-06-03 15:28:29 +0000714 unsigned long maxsleep;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000715
Jack Jansene3ae0df1997-06-03 15:28:29 +0000716 if( PyMac_InForeground() )
717 maxsleep = 0;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000718 else
Jack Jansene3ae0df1997-06-03 15:28:29 +0000719 maxsleep = schedparams.bg_yield;
720
Jack Jansen36ed5061997-06-20 16:18:15 +0000721 return PyMac_DoYield(maxsleep, 1);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000722}
723
724/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000725** Return current scheduler parameters
Jack Jansene8e8ae01995-01-26 16:36:45 +0000726*/
Jack Jansene3ae0df1997-06-03 15:28:29 +0000727void
728PyMac_GetSchedParams(PyMacSchedParams *sp)
Jack Jansene8e8ae01995-01-26 16:36:45 +0000729{
Jack Jansene3ae0df1997-06-03 15:28:29 +0000730 sp->check_interrupt = schedparams.check_interrupt;
731 sp->process_events = schedparams.process_events;
732 sp->besocial = schedparams.besocial;
733 sp->check_interval = schedparams.check_interval / 60.0;
734 sp->bg_yield = schedparams.bg_yield / 60.0;
Jack Jansenf93c72a1994-12-14 14:07:50 +0000735}
Jack Jansenf6865f71996-09-04 15:24:59 +0000736
Jack Jansen74162f31995-02-15 22:58:33 +0000737/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000738** Set current scheduler parameters
739*/
740void
741PyMac_SetSchedParams(PyMacSchedParams *sp)
742{
743 schedparams.check_interrupt = sp->check_interrupt;
744 schedparams.process_events = sp->process_events;
745 schedparams.besocial = sp->besocial;
746 schedparams.check_interval = (unsigned long)(sp->check_interval*60);
747 schedparams.bg_yield = (unsigned long)(sp->bg_yield*60);
748 if ( schedparams.check_interrupt || schedparams.process_events ||
749 schedparams.besocial )
750 schedparams.enabled = 1;
751 else
752 schedparams.enabled = 0;
753 schedparams.next_check = 0; /* Check immedeately */
754}
Jack Jansencaa7c461997-06-12 10:49:13 +0000755
Jack Jansene3ae0df1997-06-03 15:28:29 +0000756/*
Jack Jansen3469e991996-09-06 00:30:45 +0000757** Install our menu bar.
758*/
759void
760PyMac_InitMenuBar()
761{
Jack Jansen3469e991996-09-06 00:30:45 +0000762 MenuHandle applemenu;
763
Jack Jansen15f1c082001-04-25 22:07:27 +0000764 if ( sioux_mbar ) return;
Jack Jansencaa7c461997-06-12 10:49:13 +0000765 if ( (sioux_mbar=GetMenuBar()) == NULL ) {
766 /* Sioux menu not installed yet. Do so */
767 SIOUXSetupMenus();
768 if ( (sioux_mbar=GetMenuBar()) == NULL )
769 return;
770 }
Jack Jansen08c3be31997-04-08 15:27:00 +0000771 if ( (applemenu=GetMenuHandle(SIOUX_APPLEID)) == NULL ) return;
Jack Jansen3469e991996-09-06 00:30:45 +0000772 SetMenuItemText(applemenu, 1, "\pAbout Python...");
773}
774
775/*
Jack Jansencaa7c461997-06-12 10:49:13 +0000776** Restore sioux menu bar
777*/
778void
779PyMac_RestoreMenuBar()
780{
Jack Jansen15f1c082001-04-25 22:07:27 +0000781#if 1
Jack Jansen657ba272001-02-17 22:02:07 +0000782 /* This doesn't seem to work anymore? Or only for Carbon? */
783 MenuBarHandle curmenubar;
784
785 curmenubar = GetMenuBar();
Jack Janseneda78631997-06-12 15:29:46 +0000786 if ( sioux_mbar ) {
Jack Jansencaa7c461997-06-12 10:49:13 +0000787 SetMenuBar(sioux_mbar);
Jack Janseneda78631997-06-12 15:29:46 +0000788 DrawMenuBar();
Jack Jansen657ba272001-02-17 22:02:07 +0000789 } else {
Jack Jansenefaada71998-02-20 16:03:15 +0000790 PyMac_InitMenuBar();
Jack Jansen657ba272001-02-17 22:02:07 +0000791 DrawMenuBar();
792 }
793#endif
Jack Jansencaa7c461997-06-12 10:49:13 +0000794}
795
Jack Jansen15f1c082001-04-25 22:07:27 +0000796void
797PyMac_RaiseConsoleWindow()
798{
799 /* Note: this is a hack. SIOUXTextWindow is SIOUX's internal structure
800 ** and we happen to know that the first entry is the window pointer.
801 */
802 extern WindowRef *SIOUXTextWindow;
803
804 if ( SIOUXTextWindow == NULL || *SIOUXTextWindow == NULL )
805 return;
806 if ( FrontWindow() != *SIOUXTextWindow )
807 BringToFront(*SIOUXTextWindow);
808}
Jack Jansencaa7c461997-06-12 10:49:13 +0000809
810/*
Jack Jansen3469e991996-09-06 00:30:45 +0000811** Our replacement about box
812*/
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000813
814#include "patchlevel.h"
815
Jack Jansen3469e991996-09-06 00:30:45 +0000816void
817SIOUXDoAboutBox(void)
818{
819 DialogPtr theDialog;
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000820 WindowPtr theWindow;
Jack Jansen3469e991996-09-06 00:30:45 +0000821 short item;
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000822 short fontID;
Jack Jansen3469e991996-09-06 00:30:45 +0000823
824 if( (theDialog = GetNewDialog(ABOUT_ID, NULL, (WindowPtr)-1)) == NULL )
825 return;
Jack Jansend617c571996-09-22 22:14:30 +0000826 theWindow = GetDialogWindow(theDialog);
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000827 SetPortWindowPort(theWindow);
828 GetFNum("\pPython-Sans", &fontID);
829 if (fontID == 0)
830 fontID = kFontIDGeneva;
831 TextFont(fontID);
832 TextSize(9);
833 ParamText(Pstring(PATCHLEVEL), "\p", "\p", "\p");
Jack Jansend617c571996-09-22 22:14:30 +0000834 ShowWindow(theWindow);
Jack Jansen3469e991996-09-06 00:30:45 +0000835 ModalDialog(NULL, &item);
836 DisposeDialog(theDialog);
837}
838
Jack Jansen0194ad52001-05-12 22:46:35 +0000839#endif /* !TARGET_API_MAC_OSX */
Jack Janseneda78631997-06-12 15:29:46 +0000840
Jack Jansen0194ad52001-05-12 22:46:35 +0000841#if TARGET_API_MAC_OS8
Jack Janseneda78631997-06-12 15:29:46 +0000842/*
Jack Jansen3ec804a1995-02-20 15:56:10 +0000843** Helper routine for GetDirectory
844*/
Guido van Rossum24a45e31995-02-20 23:45:53 +0000845static pascal short
Jack Jansen819f1771995-08-14 12:35:10 +0000846myhook_proc(short item, DialogPtr theDialog, struct hook_args *dataptr)
Jack Jansen3ec804a1995-02-20 15:56:10 +0000847{
Jack Jansen819f1771995-08-14 12:35:10 +0000848 if ( item == sfHookFirstCall && dataptr->prompt) {
849 Handle prompth;
850 short type;
851 Rect rect;
852
853 GetDialogItem(theDialog, PROMPT_ITEM, &type, &prompth, &rect);
854 if ( prompth )
855 SetDialogItemText(prompth, (unsigned char *)dataptr->prompt);
856 } else
Jack Jansen3ec804a1995-02-20 15:56:10 +0000857 if ( item == SELECTCUR_ITEM ) {
858 item = sfItemCancelButton;
Jack Jansen819f1771995-08-14 12:35:10 +0000859 dataptr->selectcur_hit = 1;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000860 }
861 return item;
862}
Jack Jansen0194ad52001-05-12 22:46:35 +0000863
Jack Jansen3ec804a1995-02-20 15:56:10 +0000864/*
865** Ask the user for a directory. I still can't understand
866** why Apple doesn't provide a standard solution for this...
867*/
868int
Jack Jansen819f1771995-08-14 12:35:10 +0000869PyMac_GetDirectory(dirfss, prompt)
Jack Jansen3ec804a1995-02-20 15:56:10 +0000870 FSSpec *dirfss;
Jack Jansen819f1771995-08-14 12:35:10 +0000871 char *prompt;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000872{
873 static SFTypeList list = {'fldr', 0, 0, 0};
874 static Point where = {-1, -1};
Jack Jansen3ec804a1995-02-20 15:56:10 +0000875 StandardFileReply reply;
Jack Jansen819f1771995-08-14 12:35:10 +0000876 struct hook_args hook_args;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000877
878 if ( !upp_inited ) {
879 myhook_upp = NewDlgHookYDProc(myhook_proc);
880 upp_inited = 1;
881 }
Jack Jansen819f1771995-08-14 12:35:10 +0000882 if ( prompt && *prompt )
883 hook_args.prompt = (char *)Pstring(prompt);
884 else
885 hook_args.prompt = NULL;
886 hook_args.selectcur_hit = 0;
Guido van Rossum24a45e31995-02-20 23:45:53 +0000887 CustomGetFile((FileFilterYDUPP)0, 1, list, &reply, GETDIR_ID, where, myhook_upp,
Jack Jansen819f1771995-08-14 12:35:10 +0000888 NULL, NULL, NULL, (void *)&hook_args);
Jack Jansen3ec804a1995-02-20 15:56:10 +0000889
890 reply.sfFile.name[0] = 0;
891 if( FSMakeFSSpec(reply.sfFile.vRefNum, reply.sfFile.parID, reply.sfFile.name, dirfss) )
892 return 0;
Jack Jansen819f1771995-08-14 12:35:10 +0000893 return hook_args.selectcur_hit;
894}
895
896/*
897** Slightly extended StandardGetFile: accepts a prompt */
898void PyMac_PromptGetFile(short numTypes, ConstSFTypeListPtr typeList,
899 StandardFileReply *reply, char *prompt)
900{
901 static Point where = {-1, -1};
902 struct hook_args hook_args;
903
904 if ( !upp_inited ) {
905 myhook_upp = NewDlgHookYDProc(myhook_proc);
906 upp_inited = 1;
907 }
908 if ( prompt && *prompt )
909 hook_args.prompt = (char *)Pstring(prompt);
910 else
911 hook_args.prompt = NULL;
912 hook_args.selectcur_hit = 0;
913 CustomGetFile((FileFilterYDUPP)0, numTypes, typeList, reply, GETFILEPROMPT_ID, where,
914 myhook_upp, NULL, NULL, NULL, (void *)&hook_args);
Jack Jansen3ec804a1995-02-20 15:56:10 +0000915}
Jack Jansen6e68a7e2001-05-12 21:31:34 +0000916#endif /* TARGET_API_MAC_OS8 */
Jack Jansen5f653091995-01-18 13:53:49 +0000917
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000918/* Convert a 4-char string object argument to an OSType value */
Jack Jansen5f653091995-01-18 13:53:49 +0000919int
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000920PyMac_GetOSType(PyObject *v, OSType *pr)
Jack Jansen5f653091995-01-18 13:53:49 +0000921{
922 if (!PyString_Check(v) || PyString_Size(v) != 4) {
923 PyErr_SetString(PyExc_TypeError,
924 "OSType arg must be string of 4 chars");
925 return 0;
926 }
927 memcpy((char *)pr, PyString_AsString(v), 4);
928 return 1;
929}
930
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000931/* Convert an OSType value to a 4-char string object */
932PyObject *
933PyMac_BuildOSType(OSType t)
934{
935 return PyString_FromStringAndSize((char *)&t, 4);
936}
937
Jack Jansend1f06311996-08-01 15:23:54 +0000938/* Convert an NumVersion value to a 4-element tuple */
939PyObject *
940PyMac_BuildNumVersion(NumVersion t)
941{
942 return Py_BuildValue("(hhhh)", t.majorRev, t.minorAndBugRev, t.stage, t.nonRelRev);
943}
944
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000945
946/* Convert a Python string object to a Str255 */
Jack Jansen5f653091995-01-18 13:53:49 +0000947int
Guido van Rossum8f691791995-01-18 23:57:26 +0000948PyMac_GetStr255(PyObject *v, Str255 pbuf)
Jack Jansen5f653091995-01-18 13:53:49 +0000949{
950 int len;
951 if (!PyString_Check(v) || (len = PyString_Size(v)) > 255) {
952 PyErr_SetString(PyExc_TypeError,
953 "Str255 arg must be string of at most 255 chars");
954 return 0;
955 }
956 pbuf[0] = len;
957 memcpy((char *)(pbuf+1), PyString_AsString(v), len);
958 return 1;
959}
960
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000961/* Convert a Str255 to a Python string object */
962PyObject *
963PyMac_BuildStr255(Str255 s)
964{
Jack Jansenb734ade1999-12-17 17:15:50 +0000965 if ( s == NULL ) {
966 PyErr_SetString(PyExc_SystemError, "Str255 pointer is NULL");
967 return NULL;
968 }
969 return PyString_FromStringAndSize((char *)&s[1], (int)s[0]);
970}
971
972PyObject *
973PyMac_BuildOptStr255(Str255 s)
974{
975 if ( s == NULL ) {
976 Py_INCREF(Py_None);
977 return Py_None;
978 }
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000979 return PyString_FromStringAndSize((char *)&s[1], (int)s[0]);
980}
981
982
Jack Jansen5f653091995-01-18 13:53:49 +0000983/*
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000984** Convert a Python object to an FSSpec.
985** The object may either be a full pathname or a triple
986** (vrefnum, dirid, path).
Jack Jansen5f653091995-01-18 13:53:49 +0000987** NOTE: This routine will fail on pre-sys7 machines.
988** The caller is responsible for not calling this routine
989** in those cases (which is fine, since everyone calling
990** this is probably sys7 dependent anyway).
991*/
992int
Guido van Rossum8f691791995-01-18 23:57:26 +0000993PyMac_GetFSSpec(PyObject *v, FSSpec *fs)
Jack Jansen5f653091995-01-18 13:53:49 +0000994{
995 Str255 path;
996 short refnum;
997 long parid;
998 OSErr err;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000999 FSSpec *fs2;
Jack Jansen5f653091995-01-18 13:53:49 +00001000
Jack Jansen0194ad52001-05-12 22:46:35 +00001001#if !TARGET_API_MAC_OSX
1002 /* XXX This #if is temporary */
Jack Jansene8e8ae01995-01-26 16:36:45 +00001003 /* first check whether it already is an FSSpec */
1004 fs2 = mfs_GetFSSpecFSSpec(v);
1005 if ( fs2 ) {
Jack Jansen3ec804a1995-02-20 15:56:10 +00001006 (void)FSMakeFSSpec(fs2->vRefNum, fs2->parID, fs2->name, fs);
Jack Jansene8e8ae01995-01-26 16:36:45 +00001007 return 1;
1008 }
Jack Jansen0194ad52001-05-12 22:46:35 +00001009#endif
Jack Jansen5f653091995-01-18 13:53:49 +00001010 if ( PyString_Check(v) ) {
1011 /* It's a pathname */
Guido van Rossum9aa3d131995-01-21 13:46:04 +00001012 if( !PyArg_Parse(v, "O&", PyMac_GetStr255, &path) )
Jack Jansen5f653091995-01-18 13:53:49 +00001013 return 0;
Jack Jansen378815c1996-03-06 16:21:34 +00001014 refnum = 0; /* XXXX Should get CurWD here?? */
Jack Jansen5f653091995-01-18 13:53:49 +00001015 parid = 0;
1016 } else {
Guido van Rossum9aa3d131995-01-21 13:46:04 +00001017 if( !PyArg_Parse(v, "(hlO&); FSSpec should be fullpath or (vrefnum,dirid,path)",
1018 &refnum, &parid, PyMac_GetStr255, &path)) {
Jack Jansen5f653091995-01-18 13:53:49 +00001019 return 0;
Guido van Rossum9aa3d131995-01-21 13:46:04 +00001020 }
Jack Jansen5f653091995-01-18 13:53:49 +00001021 }
1022 err = FSMakeFSSpec(refnum, parid, path, fs);
1023 if ( err && err != fnfErr ) {
Jack Jansen3d757542000-01-24 09:56:06 +00001024 PyMac_Error(err);
Jack Jansen5f653091995-01-18 13:53:49 +00001025 return 0;
1026 }
1027 return 1;
1028}
1029
Jack Jansen8bb573e1999-12-12 21:37:14 +00001030/* Convert FSSpec to PyObject */
1031PyObject *PyMac_BuildFSSpec(FSSpec *v)
1032{
Jack Jansen0194ad52001-05-12 22:46:35 +00001033#if TARGET_API_MAC_OSX
1034 PyErr_SetString(PyExc_NotImplementedError, "FSSpec not yet done for OSX");
1035 return NULL;
1036#else
Jack Jansen8bb573e1999-12-12 21:37:14 +00001037 return newmfssobject(v);
Jack Jansen0194ad52001-05-12 22:46:35 +00001038#endif
Jack Jansen8bb573e1999-12-12 21:37:14 +00001039}
Guido van Rossum8f691791995-01-18 23:57:26 +00001040
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001041/* Convert a Python object to a Rect.
Guido van Rossum5279ec61995-01-26 22:56:59 +00001042 The object must be a (left, top, right, bottom) tuple.
1043 (This differs from the order in the struct but is consistent with
1044 the arguments to SetRect(), and also with STDWIN). */
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001045int
1046PyMac_GetRect(PyObject *v, Rect *r)
Guido van Rossum8f691791995-01-18 23:57:26 +00001047{
Guido van Rossum5279ec61995-01-26 22:56:59 +00001048 return PyArg_Parse(v, "(hhhh)", &r->left, &r->top, &r->right, &r->bottom);
Guido van Rossum8f691791995-01-18 23:57:26 +00001049}
Guido van Rossumb3404661995-01-22 18:36:13 +00001050
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001051/* Convert a Rect to a Python object */
Guido van Rossumb3404661995-01-22 18:36:13 +00001052PyObject *
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001053PyMac_BuildRect(Rect *r)
Guido van Rossumb3404661995-01-22 18:36:13 +00001054{
Guido van Rossum5279ec61995-01-26 22:56:59 +00001055 return Py_BuildValue("(hhhh)", r->left, r->top, r->right, r->bottom);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001056}
1057
1058
1059/* Convert a Python object to a Point.
Guido van Rossum5279ec61995-01-26 22:56:59 +00001060 The object must be a (h, v) tuple.
1061 (This differs from the order in the struct but is consistent with
1062 the arguments to SetPoint(), and also with STDWIN). */
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001063int
1064PyMac_GetPoint(PyObject *v, Point *p)
1065{
Guido van Rossum5279ec61995-01-26 22:56:59 +00001066 return PyArg_Parse(v, "(hh)", &p->h, &p->v);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001067}
1068
1069/* Convert a Point to a Python object */
1070PyObject *
1071PyMac_BuildPoint(Point p)
1072{
Guido van Rossum5279ec61995-01-26 22:56:59 +00001073 return Py_BuildValue("(hh)", p.h, p.v);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001074}
1075
1076
1077/* Convert a Python object to an EventRecord.
1078 The object must be a (what, message, when, (v, h), modifiers) tuple. */
1079int
1080PyMac_GetEventRecord(PyObject *v, EventRecord *e)
1081{
1082 return PyArg_Parse(v, "(hll(hh)h)",
1083 &e->what,
1084 &e->message,
1085 &e->when,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001086 &e->where.h,
Guido van Rossum5279ec61995-01-26 22:56:59 +00001087 &e->where.v,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001088 &e->modifiers);
1089}
1090
1091/* Convert a Rect to an EventRecord object */
1092PyObject *
1093PyMac_BuildEventRecord(EventRecord *e)
1094{
1095 return Py_BuildValue("(hll(hh)h)",
1096 e->what,
1097 e->message,
1098 e->when,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001099 e->where.h,
Guido van Rossum5279ec61995-01-26 22:56:59 +00001100 e->where.v,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001101 e->modifiers);
Guido van Rossumb3404661995-01-22 18:36:13 +00001102}
Jack Jansenfa4d5d01995-11-15 15:19:29 +00001103
1104/* Convert Python object to Fixed */
1105int
1106PyMac_GetFixed(PyObject *v, Fixed *f)
1107{
1108 double d;
1109
1110 if( !PyArg_Parse(v, "d", &d))
1111 return 0;
1112 *f = (Fixed)(d * 0x10000);
Jack Jansen31dd5c01996-05-31 13:01:39 +00001113 return 1;
Jack Jansenfa4d5d01995-11-15 15:19:29 +00001114}
1115
1116/* Convert a Point to a Python object */
1117PyObject *
1118PyMac_BuildFixed(Fixed f)
1119{
1120 double d;
1121
1122 d = f;
1123 d = d / 0x10000;
1124 return Py_BuildValue("d", d);
1125}
1126
Jack Jansend58cd631998-04-21 15:24:39 +00001127/* Convert wide to/from Python int or (hi, lo) tuple. XXXX Should use Python longs */
1128int
1129PyMac_Getwide(PyObject *v, wide *rv)
1130{
1131 if (PyInt_Check(v)) {
1132 rv->hi = 0;
1133 rv->lo = PyInt_AsLong(v);
1134 if( rv->lo & 0x80000000 )
1135 rv->hi = -1;
1136 return 1;
1137 }
1138 return PyArg_Parse(v, "(ll)", &rv->hi, &rv->lo);
1139}
1140
1141
1142PyObject *
Jack Jansenbbf4be21998-04-23 13:20:17 +00001143PyMac_Buildwide(wide *w)
Jack Jansend58cd631998-04-21 15:24:39 +00001144{
Jack Jansenbbf4be21998-04-23 13:20:17 +00001145 if ( (w->hi == 0 && (w->lo & 0x80000000) == 0) ||
1146 (w->hi == -1 && (w->lo & 0x80000000) ) )
1147 return PyInt_FromLong(w->lo);
1148 return Py_BuildValue("(ll)", w->hi, w->lo);
Jack Jansend58cd631998-04-21 15:24:39 +00001149}