blob: 9df41fbf1e84cb359cf5e7223123f4dcc1b88294 [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
Jack Jansen741e0372001-05-19 12:55:57 +0000235/* Given an FSSpec, return the FSSpec of the parent folder */
236
237static OSErr
238get_folder_parent (FSSpec * fss, FSSpec * parent)
239{
240 CInfoPBRec rec;
241 short err;
242
243 * parent = * fss;
244 rec.hFileInfo.ioNamePtr = parent->name;
245 rec.hFileInfo.ioVRefNum = parent->vRefNum;
246 rec.hFileInfo.ioDirID = parent->parID;
247 rec.hFileInfo.ioFDirIndex = -1;
248 rec.hFileInfo.ioFVersNum = 0;
249 if (err = PBGetCatInfoSync (& rec))
250 return err;
251 parent->parID = rec.dirInfo.ioDrParID;
252/* parent->name[0] = 0; */
253 return 0;
254}
255
256/* Given an FSSpec return a full, colon-separated pathname */
257
258OSErr
259PyMac_GetFullPath (FSSpec *fss, char *buf)
260{
261 short err;
262 FSSpec fss_parent, fss_current;
263 char tmpbuf[1024];
264 int plen;
265
266 fss_current = *fss;
267 plen = fss_current.name[0];
268 memcpy(buf, &fss_current.name[1], plen);
269 buf[plen] = 0;
270 /* Special case for disk names */
271 if ( fss_current.parID <= 1 ) {
272 buf[plen++] = ':';
273 buf[plen] = 0;
274 return 0;
275 }
276 while (fss_current.parID > 1) {
277 /* Get parent folder name */
278 if (err = get_folder_parent(&fss_current, &fss_parent))
279 return err;
280 fss_current = fss_parent;
281 /* Prepend path component just found to buf */
282 plen = fss_current.name[0];
283 if (strlen(buf) + plen + 1 > 1024) {
284 /* Oops... Not enough space (shouldn't happen) */
285 *buf = 0;
286 return -1;
287 }
288 memcpy(tmpbuf, &fss_current.name[1], plen);
289 tmpbuf[plen] = ':';
290 strcpy(&tmpbuf[plen+1], buf);
291 strcpy(buf, tmpbuf);
292 }
293 return 0;
294}
Jack Jansen1f9f2f42000-07-24 19:50:16 +0000295
Jack Jansen2d1306b2000-04-07 09:10:49 +0000296#ifdef USE_GUSI1
Jack Jansen378815c1996-03-06 16:21:34 +0000297/*
298** GUSI (1.6.0 and earlier, at the least) do not set the MacOS idea of
299** the working directory. Hence, we call this routine after each call
300** to chdir() to rectify things.
301*/
302void
303PyMac_FixGUSIcd()
304{
305 WDPBRec pb;
306 FSSpec curdirfss;
307
308 if ( Path2FSSpec(":x", &curdirfss) != noErr )
309 return;
310
311 /* Set MacOS "working directory" */
312 pb.ioNamePtr= "\p";
313 pb.ioVRefNum= curdirfss.vRefNum;
314 pb.ioWDDirID= curdirfss.parID;
Jack Jansen08c3be31997-04-08 15:27:00 +0000315 if (PBHSetVolSync(&pb) != noErr)
Jack Jansen378815c1996-03-06 16:21:34 +0000316 return;
Jack Jansen378815c1996-03-06 16:21:34 +0000317}
Jack Jansen2d1306b2000-04-07 09:10:49 +0000318#endif
Jack Jansen7ac70af1996-08-19 11:01:05 +0000319
Jack Jansen2d1306b2000-04-07 09:10:49 +0000320#ifdef USE_GUSI
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000321/*
322** SpinCursor (needed by GUSI) drags in heaps of stuff, so we
323** provide a dummy here.
324*/
Jack Jansencfadbd41996-08-19 11:36:25 +0000325void SpinCursor(short x) { /* Dummy */ }
Jack Jansenefaada71998-02-20 16:03:15 +0000326void RotateCursor(short x) { /* Dummy */ }
Jack Jansencfadbd41996-08-19 11:36:25 +0000327
Jack Jansenf6865f71996-09-04 15:24:59 +0000328/*
329** Replacement GUSI Spin function
330*/
Jack Jansen2d1306b2000-04-07 09:10:49 +0000331#ifdef USE_GUSI1
Jack Jansenf6865f71996-09-04 15:24:59 +0000332static int
333PyMac_GUSISpin(spin_msg msg, long arg)
334{
Jack Jansene3ae0df1997-06-03 15:28:29 +0000335 static Boolean inForeground = true;
336 int maxsleep = 6; /* 6 ticks is "normal" sleeptime */
Jack Jansenf6865f71996-09-04 15:24:59 +0000337
338 if (PyMac_ConsoleIsDead) return 0;
339#if 0
340 if (inForeground)
341 SpinCursor(msg == SP_AUTO_SPIN ? short(arg) : 1);
342#endif
343
344 if (interrupted) return -1;
345
Jack Jansene3ae0df1997-06-03 15:28:29 +0000346 if ( msg == SP_AUTO_SPIN )
347 maxsleep = 0;
348 if ( msg==SP_SLEEP||msg==SP_SELECT )
349 maxsleep = arg;
Jack Jansenf6865f71996-09-04 15:24:59 +0000350
Jack Jansene3ae0df1997-06-03 15:28:29 +0000351 PyMac_DoYield(maxsleep, 0); /* XXXX or is it safe to call python here? */
Jack Jansenf6865f71996-09-04 15:24:59 +0000352
353 return 0;
354}
355
356void
357PyMac_SetGUSISpin() {
358 GUSISetHook(GUSI_SpinHook, (GUSIHook)PyMac_GUSISpin);
359}
Jack Jansen2d1306b2000-04-07 09:10:49 +0000360#endif
Jack Jansenf6865f71996-09-04 15:24:59 +0000361
Jack Jansena39f1b01997-05-23 15:35:14 +0000362/* Called at exit() time thru atexit(), to stop event processing */
363void
364PyMac_StopGUSISpin() {
365 PyMac_ConsoleIsDead = 1;
366}
367
Jack Jansen6e68a7e2001-05-12 21:31:34 +0000368#if TARGET_API_MAC_OS8
Jack Jansena39f1b01997-05-23 15:35:14 +0000369/*
370** Replacement routines for the PLstr... functions so we don't need
Jack Jansen6ba34aa2001-01-11 23:03:56 +0000371** StdCLib.
Jack Jansena39f1b01997-05-23 15:35:14 +0000372*/
Jack Jansen8bb573e1999-12-12 21:37:14 +0000373pascal void
Jack Jansen9ae898b2000-07-11 21:16:03 +0000374PLstrcpy(unsigned char *to, unsigned char *fr)
Jack Jansena39f1b01997-05-23 15:35:14 +0000375{
376 memcpy(to, fr, fr[0]+1);
377}
378
Jack Jansen8bb573e1999-12-12 21:37:14 +0000379pascal int
Jack Jansen9ae898b2000-07-11 21:16:03 +0000380PLstrcmp(unsigned char *s1, unsigned char *s2)
Jack Jansena39f1b01997-05-23 15:35:14 +0000381{
382 int res;
383 int l = s1[0] < s2[0] ? s1[0] : s2[0];
384
385 res = memcmp(s1+1, s2+1, l);
386 if ( res != 0 )
387 return res;
388
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000389 if ( s1[0] < s2[0] )
Jack Jansena39f1b01997-05-23 15:35:14 +0000390 return -1;
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000391 else if ( s1[0] > s2[0] )
Jack Jansena39f1b01997-05-23 15:35:14 +0000392 return 1;
393 else
394 return 0;
395}
396
Jack Jansen8bb573e1999-12-12 21:37:14 +0000397pascal unsigned char *
Jack Jansen9ae898b2000-07-11 21:16:03 +0000398PLstrrchr(unsigned char *str, unsigned char chr)
Jack Jansena39f1b01997-05-23 15:35:14 +0000399{
400 unsigned char *ptr = 0;
401 unsigned char *p;
402
403 for(p=str+1; p<str+str[0]; p++)
404 if ( *p == chr )
405 ptr = p;
406 return ptr;
407}
408
Jack Jansen6e68a7e2001-05-12 21:31:34 +0000409#endif /* TARGET_API_MAC_OS8 */
Jack Jansena39f1b01997-05-23 15:35:14 +0000410#endif /* USE_GUSI */
Jack Jansen378815c1996-03-06 16:21:34 +0000411
Jack Jansen819f1771995-08-14 12:35:10 +0000412
Jack Jansen5f653091995-01-18 13:53:49 +0000413/* Convert C to Pascal string. Returns pointer to static buffer. */
414unsigned char *
415Pstring(char *str)
416{
417 static Str255 buf;
418 int len;
419
420 len = strlen(str);
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000421 if (len > 255)
422 len = 255;
Jack Jansen5f653091995-01-18 13:53:49 +0000423 buf[0] = (unsigned char)len;
424 strncpy((char *)buf+1, str, len);
425 return buf;
426}
427
Jack Jansen6e68a7e2001-05-12 21:31:34 +0000428#if TARGET_API_MAC_OS8
Jack Jansen5afad832000-12-12 22:12:14 +0000429void
430c2pstrcpy(unsigned char *dst, const char *src)
431{
432 int len;
433
434 len = strlen(src);
435 if ( len > 255 ) len = 255;
436 strncpy((char *)dst+1, src, len);
437 dst[0] = len;
438}
Jack Jansen6e68a7e2001-05-12 21:31:34 +0000439#endif /* TARGET_API_MAC_OS8 */
Jack Jansen5afad832000-12-12 22:12:14 +0000440
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000441/* Like strerror() but for Mac OS error numbers */
442char *PyMac_StrError(int err)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000443{
444 static char buf[256];
445 Handle h;
446 char *str;
447
448 h = GetResource('Estr', err);
449 if ( h ) {
450 HLock(h);
451 str = (char *)*h;
452 memcpy(buf, str+1, (unsigned char)str[0]);
Guido van Rossumcc9bc8f1995-02-13 16:17:03 +0000453 buf[(unsigned char)str[0]] = '\0';
Jack Jansenf93c72a1994-12-14 14:07:50 +0000454 HUnlock(h);
455 ReleaseResource(h);
456 } else {
457 sprintf(buf, "Mac OS error code %d", err);
458 }
459 return buf;
460}
461
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000462/* Exception object shared by all Mac specific modules for Mac OS errors */
463PyObject *PyMac_OSErrException;
464
465/* Initialize and return PyMac_OSErrException */
466PyObject *
467PyMac_GetOSErrException()
468{
469 if (PyMac_OSErrException == NULL)
470 PyMac_OSErrException = PyString_FromString("Mac OS Error");
471 return PyMac_OSErrException;
472}
473
Jack Jansenf93c72a1994-12-14 14:07:50 +0000474/* Set a MAC-specific error from errno, and return NULL; return None if no error */
475PyObject *
Guido van Rossumfffb8bb1995-01-12 12:37:24 +0000476PyErr_Mac(PyObject *eobj, int err)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000477{
478 char *msg;
479 PyObject *v;
Jack Jansenf93c72a1994-12-14 14:07:50 +0000480
Guido van Rossum8f691791995-01-18 23:57:26 +0000481 if (err == 0 && !PyErr_Occurred()) {
Jack Jansenf93c72a1994-12-14 14:07:50 +0000482 Py_INCREF(Py_None);
483 return Py_None;
484 }
Guido van Rossum8f691791995-01-18 23:57:26 +0000485 if (err == -1 && PyErr_Occurred())
486 return NULL;
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000487 msg = PyMac_StrError(err);
Jack Jansenf93c72a1994-12-14 14:07:50 +0000488 v = Py_BuildValue("(is)", err, msg);
489 PyErr_SetObject(eobj, v);
490 Py_DECREF(v);
491 return NULL;
492}
493
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000494/* Call PyErr_Mac with PyMac_OSErrException */
495PyObject *
496PyMac_Error(OSErr err)
497{
498 return PyErr_Mac(PyMac_GetOSErrException(), err);
499}
500
Jack Jansen1ed95291996-07-22 15:25:10 +0000501#ifdef USE_STACKCHECK
502/* Check for stack overflow */
503int
504PyOS_CheckStack()
505{
Jack Jansen14a91712000-08-25 21:57:23 +0000506 char here;
507 static char *sentinel = 0;
Jack Jansen53bafd92000-09-08 22:05:48 +0000508 static PyThreadState *thread_for_sentinel = 0;
Jack Jansen1ed95291996-07-22 15:25:10 +0000509
Jack Jansen340eb882001-02-02 22:40:28 +0000510 if ( sentinel == 0 ) {
511 unsigned long stackspace = StackSpace();
512
513#ifdef MAXIMUM_STACK_SIZE
514 /* See the comment at the definition */
515 if ( stackspace > MAXIMUM_STACK_SIZE )
516 stackspace = MAXIMUM_STACK_SIZE;
517#endif
518 sentinel = &here - stackspace + MINIMUM_STACK_SIZE;
Jack Jansen14a91712000-08-25 21:57:23 +0000519 }
Jack Jansen53bafd92000-09-08 22:05:48 +0000520 if ( thread_for_sentinel == 0 ) {
521 thread_for_sentinel = PyThreadState_Get();
522 }
523 if ( &here < sentinel ) {
524 if (thread_for_sentinel == PyThreadState_Get()) {
525 return -1;
526#if 0
527 } else {
528 /* Else we are unsure... */
529 fprintf(stderr, "Stackcheck in other thread (was %x now %x)\n", thread_for_sentinel,PyThreadState_Get());
530#endif
531 }
532 }
Jack Jansen1ed95291996-07-22 15:25:10 +0000533 return 0;
534}
535#endif /* USE_STACKCHECK */
536
Jack Jansen0194ad52001-05-12 22:46:35 +0000537#if !TARGET_API_MAC_OSX
Jack Jansenee23d6e1995-01-27 14:43:25 +0000538/* The catcher routine (which may not be used for all compilers) */
539static RETSIGTYPE
540intcatcher(sig)
541 int sig;
542{
543 interrupted = 1;
544 signal(SIGINT, intcatcher);
545}
546
547void
548PyOS_InitInterrupts()
549{
550 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
551 signal(SIGINT, intcatcher);
552}
553
Jack Jansena8441de1997-08-08 14:57:37 +0000554void
555PyOS_FiniInterrupts()
556{
557}
558
Jack Jansenee23d6e1995-01-27 14:43:25 +0000559/*
560** This routine scans the event queue looking for cmd-.
561** This is the only way to get an interrupt under THINK (since it
562** doesn't do SIGINT handling), but is also used under MW, when
563** the full-fledged event loop is disabled. This way, we can at least
564** interrupt a runaway python program.
565*/
566static void
567scan_event_queue(flush)
568 int flush;
569{
Jack Jansen6e68a7e2001-05-12 21:31:34 +0000570#if !TARGET_API_MAC_OS8
Jack Jansend7b68022001-01-12 23:42:28 +0000571 if ( CheckEventQueueForUserCancel() )
572 interrupted = 1;
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000573#else
Jack Jansenee23d6e1995-01-27 14:43:25 +0000574 register EvQElPtr q;
575
Jack Jansenefaada71998-02-20 16:03:15 +0000576 q = (EvQElPtr) LMGetEventQueue()->qHead;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000577
578 for (; q; q = (EvQElPtr)q->qLink) {
579 if (q->evtQWhat == keyDown &&
580 (char)q->evtQMessage == '.' &&
581 (q->evtQModifiers & cmdKey) != 0) {
582 if ( flush )
583 FlushEvents(keyDownMask, 0);
584 interrupted = 1;
585 break;
586 }
587 }
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000588#endif
Jack Jansenee23d6e1995-01-27 14:43:25 +0000589}
590
591int
Jack Jansen36ed5061997-06-20 16:18:15 +0000592PyErr_CheckSignals()
Jack Jansenee23d6e1995-01-27 14:43:25 +0000593{
Jack Jansene3ae0df1997-06-03 15:28:29 +0000594 if (schedparams.enabled) {
595 if ( (unsigned long)LMGetTicks() > schedparams.next_check ) {
Jack Jansen36ed5061997-06-20 16:18:15 +0000596 if ( PyMac_Yield() < 0)
597 return -1;
Jack Jansene3ae0df1997-06-03 15:28:29 +0000598 schedparams.next_check = (unsigned long)LMGetTicks()
599 + schedparams.check_interval;
600 if (interrupted) {
Jack Jansencaa7c461997-06-12 10:49:13 +0000601 scan_event_queue(1); /* Eat events up to cmd-. */
Jack Jansene3ae0df1997-06-03 15:28:29 +0000602 interrupted = 0;
Jack Jansen36ed5061997-06-20 16:18:15 +0000603 PyErr_SetNone(PyExc_KeyboardInterrupt);
604 return -1;
Jack Jansene3ae0df1997-06-03 15:28:29 +0000605 }
606 }
Jack Jansenee23d6e1995-01-27 14:43:25 +0000607 }
608 return 0;
609}
610
Jack Jansen36ed5061997-06-20 16:18:15 +0000611int
612PyOS_InterruptOccurred()
613{
614 scan_event_queue(1);
615 return interrupted;
616}
Jack Jansen0194ad52001-05-12 22:46:35 +0000617
Jack Jansenee23d6e1995-01-27 14:43:25 +0000618/* Check whether we are in the foreground */
Jack Jansen9ae898b2000-07-11 21:16:03 +0000619static int
620PyMac_InForeground(void)
Jack Jansenee23d6e1995-01-27 14:43:25 +0000621{
622 static ProcessSerialNumber ours;
623 static inited;
624 ProcessSerialNumber curfg;
625 Boolean eq;
626
Jack Jansene3ae0df1997-06-03 15:28:29 +0000627 if ( inited == 0 ) {
Jack Jansenee23d6e1995-01-27 14:43:25 +0000628 (void)GetCurrentProcess(&ours);
Jack Jansene3ae0df1997-06-03 15:28:29 +0000629 inited = 1;
630 }
Jack Jansenee23d6e1995-01-27 14:43:25 +0000631 if ( GetFrontProcess(&curfg) < 0 )
632 eq = 1;
633 else if ( SameProcess(&ours, &curfg, &eq) < 0 )
634 eq = 1;
635 return (int)eq;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000636}
Jack Jansen0194ad52001-05-12 22:46:35 +0000637#endif
Jack Jansenee23d6e1995-01-27 14:43:25 +0000638
Jack Jansen36ed5061997-06-20 16:18:15 +0000639int
640PyMac_SetEventHandler(PyObject *evh)
641{
642 if ( evh && python_event_handler ) {
643 PyErr_SetString(PyExc_RuntimeError, "Python event handler already set");
644 return 0;
645 }
646 if ( python_event_handler )
647 Py_DECREF(python_event_handler);
648 if ( evh )
649 Py_INCREF(evh);
650 python_event_handler = evh;
651 return 1;
652}
653
Jack Jansenf93c72a1994-12-14 14:07:50 +0000654/*
Jack Jansena76382a1995-02-02 14:25:56 +0000655** Handle an event, either one found in the mainloop eventhandler or
656** one passed back from the python program.
657*/
658void
Jack Jansen36ed5061997-06-20 16:18:15 +0000659PyMac_HandleEventIntern(evp)
Jack Jansena76382a1995-02-02 14:25:56 +0000660 EventRecord *evp;
661{
Jack Jansen6e68a7e2001-05-12 21:31:34 +0000662#if TARGET_API_MAC_OS8
Jack Jansen0c968871997-08-26 13:20:34 +0000663 if ( evp->what == mouseDown ) {
664 WindowPtr wp;
665
666 if ( FindWindow(evp->where, &wp) == inSysWindow ) {
667 SystemClick(evp, wp);
668 return;
669 }
670 }
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000671#endif
Jack Jansena76382a1995-02-02 14:25:56 +0000672#ifdef __MWERKS__
Jack Jansen38e97661995-11-10 14:53:00 +0000673 {
674 int siouxdidit;
675
676 /* If SIOUX wants it we're done */
677 siouxdidit = SIOUXHandleOneEvent(evp);
678 if ( siouxdidit )
679 return;
680 }
Jack Jansena76382a1995-02-02 14:25:56 +0000681#else
Jack Jansen0c968871997-08-26 13:20:34 +0000682 /* Other compilers are just unlucky... */
Jack Jansena76382a1995-02-02 14:25:56 +0000683#endif /* !__MWERKS__ */
Jack Jansen36ed5061997-06-20 16:18:15 +0000684}
685
686/*
687** Handle an event, either through HandleEvent or by passing it to the Python
688** event handler.
689*/
690int
691PyMac_HandleEvent(evp)
692 EventRecord *evp;
693{
694 PyObject *rv;
695
696 if ( python_event_handler ) {
697 rv = PyObject_CallFunction(python_event_handler, "(O&)",
698 PyMac_BuildEventRecord, evp);
699 if ( rv )
700 Py_DECREF(rv);
701 else
702 return -1; /* Propagate exception */
703 } else {
704 PyMac_HandleEventIntern(evp);
705 }
706 return 0;
Jack Jansena76382a1995-02-02 14:25:56 +0000707}
708
Jack Jansen0194ad52001-05-12 22:46:35 +0000709#if !TARGET_API_MAC_OSX
Jack Jansena76382a1995-02-02 14:25:56 +0000710/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000711** Yield the CPU to other tasks without processing events.
Jack Jansene8e8ae01995-01-26 16:36:45 +0000712*/
Jack Jansen2d1306b2000-04-07 09:10:49 +0000713int
Jack Jansene3ae0df1997-06-03 15:28:29 +0000714PyMac_DoYield(int maxsleep, int maycallpython)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000715{
716 EventRecord ev;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000717 int gotone;
Jack Jansene3ae0df1997-06-03 15:28:29 +0000718 long latest_time_ready;
Jack Jansen36ed5061997-06-20 16:18:15 +0000719 static int in_here = 0;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000720
Jack Jansen36ed5061997-06-20 16:18:15 +0000721 in_here++;
Jack Jansene3ae0df1997-06-03 15:28:29 +0000722 /*
723 ** First check for interrupts, if wanted.
724 ** This sets a flag that will be picked up at an appropriate
725 ** moment in the mainloop.
726 */
727 if (schedparams.check_interrupt)
Jack Jansenee23d6e1995-01-27 14:43:25 +0000728 scan_event_queue(0);
Jack Jansene3ae0df1997-06-03 15:28:29 +0000729
730 /* XXXX Implementing an idle routine goes here */
Jack Jansene8e8ae01995-01-26 16:36:45 +0000731
Jack Jansene3ae0df1997-06-03 15:28:29 +0000732 /*
733 ** Check which of the eventloop cases we have:
734 ** - process events
735 ** - don't process events but do yield
736 ** - do neither
737 */
Jack Jansen36ed5061997-06-20 16:18:15 +0000738 if( in_here > 1 || !schedparams.process_events ||
739 (python_event_handler && !maycallpython) ) {
Jack Jansene3ae0df1997-06-03 15:28:29 +0000740 if ( maxsleep >= 0 ) {
Jack Jansen6e68a7e2001-05-12 21:31:34 +0000741#if TARGET_API_MAC_OS8
Jack Jansene8e8ae01995-01-26 16:36:45 +0000742 SystemTask();
Jack Jansen15f1c082001-04-25 22:07:27 +0000743#else
744 int xxx = 0;
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000745#endif
Jack Jansen15f1c082001-04-25 22:07:27 +0000746 }
Jack Jansene3ae0df1997-06-03 15:28:29 +0000747 } else {
748 latest_time_ready = LMGetTicks() + maxsleep;
Jack Jansen2d1306b2000-04-07 09:10:49 +0000749 do {
Jack Jansen0c968871997-08-26 13:20:34 +0000750 /* XXXX Hack by Jack.
751 ** In time.sleep() you can click to another application
752 ** once only. If you come back to Python you cannot get away
753 ** again.
754 **/
Jack Jansen36ed5061997-06-20 16:18:15 +0000755 gotone = WaitNextEvent(schedparams.process_events, &ev, maxsleep, NULL);
Jack Jansene3ae0df1997-06-03 15:28:29 +0000756 /* Get out quickly if nothing interesting is happening */
757 if ( !gotone || ev.what == nullEvent )
758 break;
Jack Jansen36ed5061997-06-20 16:18:15 +0000759 if ( PyMac_HandleEvent(&ev) < 0 ) {
760 in_here--;
761 return -1;
762 }
Jack Jansene3ae0df1997-06-03 15:28:29 +0000763 maxsleep = latest_time_ready - LMGetTicks();
Jack Jansen2d1306b2000-04-07 09:10:49 +0000764 } while ( maxsleep > 0 );
Jack Jansenf93c72a1994-12-14 14:07:50 +0000765 }
Jack Jansen36ed5061997-06-20 16:18:15 +0000766 in_here--;
767 return 0;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000768}
769
770/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000771** Process events and/or yield the CPU to other tasks if opportune
Jack Jansene8e8ae01995-01-26 16:36:45 +0000772*/
Jack Jansen36ed5061997-06-20 16:18:15 +0000773int
Jack Jansene8e8ae01995-01-26 16:36:45 +0000774PyMac_Yield() {
Jack Jansene3ae0df1997-06-03 15:28:29 +0000775 unsigned long maxsleep;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000776
Jack Jansene3ae0df1997-06-03 15:28:29 +0000777 if( PyMac_InForeground() )
778 maxsleep = 0;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000779 else
Jack Jansene3ae0df1997-06-03 15:28:29 +0000780 maxsleep = schedparams.bg_yield;
781
Jack Jansen36ed5061997-06-20 16:18:15 +0000782 return PyMac_DoYield(maxsleep, 1);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000783}
784
785/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000786** Return current scheduler parameters
Jack Jansene8e8ae01995-01-26 16:36:45 +0000787*/
Jack Jansene3ae0df1997-06-03 15:28:29 +0000788void
789PyMac_GetSchedParams(PyMacSchedParams *sp)
Jack Jansene8e8ae01995-01-26 16:36:45 +0000790{
Jack Jansene3ae0df1997-06-03 15:28:29 +0000791 sp->check_interrupt = schedparams.check_interrupt;
792 sp->process_events = schedparams.process_events;
793 sp->besocial = schedparams.besocial;
794 sp->check_interval = schedparams.check_interval / 60.0;
795 sp->bg_yield = schedparams.bg_yield / 60.0;
Jack Jansenf93c72a1994-12-14 14:07:50 +0000796}
Jack Jansenf6865f71996-09-04 15:24:59 +0000797
Jack Jansen74162f31995-02-15 22:58:33 +0000798/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000799** Set current scheduler parameters
800*/
801void
802PyMac_SetSchedParams(PyMacSchedParams *sp)
803{
804 schedparams.check_interrupt = sp->check_interrupt;
805 schedparams.process_events = sp->process_events;
806 schedparams.besocial = sp->besocial;
807 schedparams.check_interval = (unsigned long)(sp->check_interval*60);
808 schedparams.bg_yield = (unsigned long)(sp->bg_yield*60);
809 if ( schedparams.check_interrupt || schedparams.process_events ||
810 schedparams.besocial )
811 schedparams.enabled = 1;
812 else
813 schedparams.enabled = 0;
814 schedparams.next_check = 0; /* Check immedeately */
815}
Jack Jansencaa7c461997-06-12 10:49:13 +0000816
Jack Jansene3ae0df1997-06-03 15:28:29 +0000817/*
Jack Jansen3469e991996-09-06 00:30:45 +0000818** Install our menu bar.
819*/
820void
821PyMac_InitMenuBar()
822{
Jack Jansen3469e991996-09-06 00:30:45 +0000823 MenuHandle applemenu;
824
Jack Jansen15f1c082001-04-25 22:07:27 +0000825 if ( sioux_mbar ) return;
Jack Jansencaa7c461997-06-12 10:49:13 +0000826 if ( (sioux_mbar=GetMenuBar()) == NULL ) {
827 /* Sioux menu not installed yet. Do so */
828 SIOUXSetupMenus();
829 if ( (sioux_mbar=GetMenuBar()) == NULL )
830 return;
831 }
Jack Jansen08c3be31997-04-08 15:27:00 +0000832 if ( (applemenu=GetMenuHandle(SIOUX_APPLEID)) == NULL ) return;
Jack Jansen3469e991996-09-06 00:30:45 +0000833 SetMenuItemText(applemenu, 1, "\pAbout Python...");
834}
835
836/*
Jack Jansencaa7c461997-06-12 10:49:13 +0000837** Restore sioux menu bar
838*/
839void
840PyMac_RestoreMenuBar()
841{
Jack Jansen15f1c082001-04-25 22:07:27 +0000842#if 1
Jack Jansen657ba272001-02-17 22:02:07 +0000843 /* This doesn't seem to work anymore? Or only for Carbon? */
844 MenuBarHandle curmenubar;
845
846 curmenubar = GetMenuBar();
Jack Janseneda78631997-06-12 15:29:46 +0000847 if ( sioux_mbar ) {
Jack Jansencaa7c461997-06-12 10:49:13 +0000848 SetMenuBar(sioux_mbar);
Jack Janseneda78631997-06-12 15:29:46 +0000849 DrawMenuBar();
Jack Jansen657ba272001-02-17 22:02:07 +0000850 } else {
Jack Jansenefaada71998-02-20 16:03:15 +0000851 PyMac_InitMenuBar();
Jack Jansen657ba272001-02-17 22:02:07 +0000852 DrawMenuBar();
853 }
854#endif
Jack Jansencaa7c461997-06-12 10:49:13 +0000855}
856
Jack Jansen15f1c082001-04-25 22:07:27 +0000857void
858PyMac_RaiseConsoleWindow()
859{
860 /* Note: this is a hack. SIOUXTextWindow is SIOUX's internal structure
861 ** and we happen to know that the first entry is the window pointer.
862 */
863 extern WindowRef *SIOUXTextWindow;
864
865 if ( SIOUXTextWindow == NULL || *SIOUXTextWindow == NULL )
866 return;
867 if ( FrontWindow() != *SIOUXTextWindow )
868 BringToFront(*SIOUXTextWindow);
869}
Jack Jansencaa7c461997-06-12 10:49:13 +0000870
871/*
Jack Jansen3469e991996-09-06 00:30:45 +0000872** Our replacement about box
873*/
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000874
875#include "patchlevel.h"
876
Jack Jansen3469e991996-09-06 00:30:45 +0000877void
878SIOUXDoAboutBox(void)
879{
880 DialogPtr theDialog;
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000881 WindowPtr theWindow;
Jack Jansen3469e991996-09-06 00:30:45 +0000882 short item;
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000883 short fontID;
Jack Jansen3469e991996-09-06 00:30:45 +0000884
885 if( (theDialog = GetNewDialog(ABOUT_ID, NULL, (WindowPtr)-1)) == NULL )
886 return;
Jack Jansend617c571996-09-22 22:14:30 +0000887 theWindow = GetDialogWindow(theDialog);
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000888 SetPortWindowPort(theWindow);
889 GetFNum("\pPython-Sans", &fontID);
890 if (fontID == 0)
891 fontID = kFontIDGeneva;
892 TextFont(fontID);
893 TextSize(9);
894 ParamText(Pstring(PATCHLEVEL), "\p", "\p", "\p");
Jack Jansend617c571996-09-22 22:14:30 +0000895 ShowWindow(theWindow);
Jack Jansen3469e991996-09-06 00:30:45 +0000896 ModalDialog(NULL, &item);
897 DisposeDialog(theDialog);
898}
899
Jack Jansen0194ad52001-05-12 22:46:35 +0000900#endif /* !TARGET_API_MAC_OSX */
Jack Janseneda78631997-06-12 15:29:46 +0000901
Jack Jansen0194ad52001-05-12 22:46:35 +0000902#if TARGET_API_MAC_OS8
Jack Janseneda78631997-06-12 15:29:46 +0000903/*
Jack Jansen3ec804a1995-02-20 15:56:10 +0000904** Helper routine for GetDirectory
905*/
Guido van Rossum24a45e31995-02-20 23:45:53 +0000906static pascal short
Jack Jansen819f1771995-08-14 12:35:10 +0000907myhook_proc(short item, DialogPtr theDialog, struct hook_args *dataptr)
Jack Jansen3ec804a1995-02-20 15:56:10 +0000908{
Jack Jansen819f1771995-08-14 12:35:10 +0000909 if ( item == sfHookFirstCall && dataptr->prompt) {
910 Handle prompth;
911 short type;
912 Rect rect;
913
914 GetDialogItem(theDialog, PROMPT_ITEM, &type, &prompth, &rect);
915 if ( prompth )
916 SetDialogItemText(prompth, (unsigned char *)dataptr->prompt);
917 } else
Jack Jansen3ec804a1995-02-20 15:56:10 +0000918 if ( item == SELECTCUR_ITEM ) {
919 item = sfItemCancelButton;
Jack Jansen819f1771995-08-14 12:35:10 +0000920 dataptr->selectcur_hit = 1;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000921 }
922 return item;
923}
Jack Jansen0194ad52001-05-12 22:46:35 +0000924
Jack Jansen3ec804a1995-02-20 15:56:10 +0000925/*
926** Ask the user for a directory. I still can't understand
927** why Apple doesn't provide a standard solution for this...
928*/
929int
Jack Jansen819f1771995-08-14 12:35:10 +0000930PyMac_GetDirectory(dirfss, prompt)
Jack Jansen3ec804a1995-02-20 15:56:10 +0000931 FSSpec *dirfss;
Jack Jansen819f1771995-08-14 12:35:10 +0000932 char *prompt;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000933{
934 static SFTypeList list = {'fldr', 0, 0, 0};
935 static Point where = {-1, -1};
Jack Jansen3ec804a1995-02-20 15:56:10 +0000936 StandardFileReply reply;
Jack Jansen819f1771995-08-14 12:35:10 +0000937 struct hook_args hook_args;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000938
939 if ( !upp_inited ) {
940 myhook_upp = NewDlgHookYDProc(myhook_proc);
941 upp_inited = 1;
942 }
Jack Jansen819f1771995-08-14 12:35:10 +0000943 if ( prompt && *prompt )
944 hook_args.prompt = (char *)Pstring(prompt);
945 else
946 hook_args.prompt = NULL;
947 hook_args.selectcur_hit = 0;
Guido van Rossum24a45e31995-02-20 23:45:53 +0000948 CustomGetFile((FileFilterYDUPP)0, 1, list, &reply, GETDIR_ID, where, myhook_upp,
Jack Jansen819f1771995-08-14 12:35:10 +0000949 NULL, NULL, NULL, (void *)&hook_args);
Jack Jansen3ec804a1995-02-20 15:56:10 +0000950
951 reply.sfFile.name[0] = 0;
952 if( FSMakeFSSpec(reply.sfFile.vRefNum, reply.sfFile.parID, reply.sfFile.name, dirfss) )
953 return 0;
Jack Jansen819f1771995-08-14 12:35:10 +0000954 return hook_args.selectcur_hit;
955}
956
957/*
958** Slightly extended StandardGetFile: accepts a prompt */
959void PyMac_PromptGetFile(short numTypes, ConstSFTypeListPtr typeList,
960 StandardFileReply *reply, char *prompt)
961{
962 static Point where = {-1, -1};
963 struct hook_args hook_args;
964
965 if ( !upp_inited ) {
966 myhook_upp = NewDlgHookYDProc(myhook_proc);
967 upp_inited = 1;
968 }
969 if ( prompt && *prompt )
970 hook_args.prompt = (char *)Pstring(prompt);
971 else
972 hook_args.prompt = NULL;
973 hook_args.selectcur_hit = 0;
974 CustomGetFile((FileFilterYDUPP)0, numTypes, typeList, reply, GETFILEPROMPT_ID, where,
975 myhook_upp, NULL, NULL, NULL, (void *)&hook_args);
Jack Jansen3ec804a1995-02-20 15:56:10 +0000976}
Jack Jansen6e68a7e2001-05-12 21:31:34 +0000977#endif /* TARGET_API_MAC_OS8 */
Jack Jansen5f653091995-01-18 13:53:49 +0000978
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000979/* Convert a 4-char string object argument to an OSType value */
Jack Jansen5f653091995-01-18 13:53:49 +0000980int
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000981PyMac_GetOSType(PyObject *v, OSType *pr)
Jack Jansen5f653091995-01-18 13:53:49 +0000982{
983 if (!PyString_Check(v) || PyString_Size(v) != 4) {
984 PyErr_SetString(PyExc_TypeError,
985 "OSType arg must be string of 4 chars");
986 return 0;
987 }
988 memcpy((char *)pr, PyString_AsString(v), 4);
989 return 1;
990}
991
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000992/* Convert an OSType value to a 4-char string object */
993PyObject *
994PyMac_BuildOSType(OSType t)
995{
996 return PyString_FromStringAndSize((char *)&t, 4);
997}
998
Jack Jansend1f06311996-08-01 15:23:54 +0000999/* Convert an NumVersion value to a 4-element tuple */
1000PyObject *
1001PyMac_BuildNumVersion(NumVersion t)
1002{
1003 return Py_BuildValue("(hhhh)", t.majorRev, t.minorAndBugRev, t.stage, t.nonRelRev);
1004}
1005
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001006
1007/* Convert a Python string object to a Str255 */
Jack Jansen5f653091995-01-18 13:53:49 +00001008int
Guido van Rossum8f691791995-01-18 23:57:26 +00001009PyMac_GetStr255(PyObject *v, Str255 pbuf)
Jack Jansen5f653091995-01-18 13:53:49 +00001010{
1011 int len;
1012 if (!PyString_Check(v) || (len = PyString_Size(v)) > 255) {
1013 PyErr_SetString(PyExc_TypeError,
1014 "Str255 arg must be string of at most 255 chars");
1015 return 0;
1016 }
1017 pbuf[0] = len;
1018 memcpy((char *)(pbuf+1), PyString_AsString(v), len);
1019 return 1;
1020}
1021
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001022/* Convert a Str255 to a Python string object */
1023PyObject *
1024PyMac_BuildStr255(Str255 s)
1025{
Jack Jansenb734ade1999-12-17 17:15:50 +00001026 if ( s == NULL ) {
1027 PyErr_SetString(PyExc_SystemError, "Str255 pointer is NULL");
1028 return NULL;
1029 }
1030 return PyString_FromStringAndSize((char *)&s[1], (int)s[0]);
1031}
1032
1033PyObject *
1034PyMac_BuildOptStr255(Str255 s)
1035{
1036 if ( s == NULL ) {
1037 Py_INCREF(Py_None);
1038 return Py_None;
1039 }
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001040 return PyString_FromStringAndSize((char *)&s[1], (int)s[0]);
1041}
1042
1043
Jack Jansen5f653091995-01-18 13:53:49 +00001044/*
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001045** Convert a Python object to an FSSpec.
1046** The object may either be a full pathname or a triple
1047** (vrefnum, dirid, path).
Jack Jansen5f653091995-01-18 13:53:49 +00001048** NOTE: This routine will fail on pre-sys7 machines.
1049** The caller is responsible for not calling this routine
1050** in those cases (which is fine, since everyone calling
1051** this is probably sys7 dependent anyway).
1052*/
1053int
Guido van Rossum8f691791995-01-18 23:57:26 +00001054PyMac_GetFSSpec(PyObject *v, FSSpec *fs)
Jack Jansen5f653091995-01-18 13:53:49 +00001055{
1056 Str255 path;
1057 short refnum;
1058 long parid;
1059 OSErr err;
Jack Jansene8e8ae01995-01-26 16:36:45 +00001060 FSSpec *fs2;
Jack Jansen5f653091995-01-18 13:53:49 +00001061
Jack Jansen0194ad52001-05-12 22:46:35 +00001062#if !TARGET_API_MAC_OSX
1063 /* XXX This #if is temporary */
Jack Jansene8e8ae01995-01-26 16:36:45 +00001064 /* first check whether it already is an FSSpec */
1065 fs2 = mfs_GetFSSpecFSSpec(v);
1066 if ( fs2 ) {
Jack Jansen3ec804a1995-02-20 15:56:10 +00001067 (void)FSMakeFSSpec(fs2->vRefNum, fs2->parID, fs2->name, fs);
Jack Jansene8e8ae01995-01-26 16:36:45 +00001068 return 1;
1069 }
Jack Jansen0194ad52001-05-12 22:46:35 +00001070#endif
Jack Jansen5f653091995-01-18 13:53:49 +00001071 if ( PyString_Check(v) ) {
1072 /* It's a pathname */
Guido van Rossum9aa3d131995-01-21 13:46:04 +00001073 if( !PyArg_Parse(v, "O&", PyMac_GetStr255, &path) )
Jack Jansen5f653091995-01-18 13:53:49 +00001074 return 0;
Jack Jansen378815c1996-03-06 16:21:34 +00001075 refnum = 0; /* XXXX Should get CurWD here?? */
Jack Jansen5f653091995-01-18 13:53:49 +00001076 parid = 0;
1077 } else {
Guido van Rossum9aa3d131995-01-21 13:46:04 +00001078 if( !PyArg_Parse(v, "(hlO&); FSSpec should be fullpath or (vrefnum,dirid,path)",
1079 &refnum, &parid, PyMac_GetStr255, &path)) {
Jack Jansen5f653091995-01-18 13:53:49 +00001080 return 0;
Guido van Rossum9aa3d131995-01-21 13:46:04 +00001081 }
Jack Jansen5f653091995-01-18 13:53:49 +00001082 }
1083 err = FSMakeFSSpec(refnum, parid, path, fs);
1084 if ( err && err != fnfErr ) {
Jack Jansen3d757542000-01-24 09:56:06 +00001085 PyMac_Error(err);
Jack Jansen5f653091995-01-18 13:53:49 +00001086 return 0;
1087 }
1088 return 1;
1089}
1090
Jack Jansen8bb573e1999-12-12 21:37:14 +00001091/* Convert FSSpec to PyObject */
1092PyObject *PyMac_BuildFSSpec(FSSpec *v)
1093{
Jack Jansen0194ad52001-05-12 22:46:35 +00001094#if TARGET_API_MAC_OSX
1095 PyErr_SetString(PyExc_NotImplementedError, "FSSpec not yet done for OSX");
1096 return NULL;
1097#else
Jack Jansen8bb573e1999-12-12 21:37:14 +00001098 return newmfssobject(v);
Jack Jansen0194ad52001-05-12 22:46:35 +00001099#endif
Jack Jansen8bb573e1999-12-12 21:37:14 +00001100}
Guido van Rossum8f691791995-01-18 23:57:26 +00001101
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001102/* Convert a Python object to a Rect.
Guido van Rossum5279ec61995-01-26 22:56:59 +00001103 The object must be a (left, top, right, bottom) tuple.
1104 (This differs from the order in the struct but is consistent with
1105 the arguments to SetRect(), and also with STDWIN). */
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001106int
1107PyMac_GetRect(PyObject *v, Rect *r)
Guido van Rossum8f691791995-01-18 23:57:26 +00001108{
Guido van Rossum5279ec61995-01-26 22:56:59 +00001109 return PyArg_Parse(v, "(hhhh)", &r->left, &r->top, &r->right, &r->bottom);
Guido van Rossum8f691791995-01-18 23:57:26 +00001110}
Guido van Rossumb3404661995-01-22 18:36:13 +00001111
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001112/* Convert a Rect to a Python object */
Guido van Rossumb3404661995-01-22 18:36:13 +00001113PyObject *
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001114PyMac_BuildRect(Rect *r)
Guido van Rossumb3404661995-01-22 18:36:13 +00001115{
Guido van Rossum5279ec61995-01-26 22:56:59 +00001116 return Py_BuildValue("(hhhh)", r->left, r->top, r->right, r->bottom);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001117}
1118
1119
1120/* Convert a Python object to a Point.
Guido van Rossum5279ec61995-01-26 22:56:59 +00001121 The object must be a (h, v) tuple.
1122 (This differs from the order in the struct but is consistent with
1123 the arguments to SetPoint(), and also with STDWIN). */
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001124int
1125PyMac_GetPoint(PyObject *v, Point *p)
1126{
Guido van Rossum5279ec61995-01-26 22:56:59 +00001127 return PyArg_Parse(v, "(hh)", &p->h, &p->v);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001128}
1129
1130/* Convert a Point to a Python object */
1131PyObject *
1132PyMac_BuildPoint(Point p)
1133{
Guido van Rossum5279ec61995-01-26 22:56:59 +00001134 return Py_BuildValue("(hh)", p.h, p.v);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001135}
1136
1137
1138/* Convert a Python object to an EventRecord.
1139 The object must be a (what, message, when, (v, h), modifiers) tuple. */
1140int
1141PyMac_GetEventRecord(PyObject *v, EventRecord *e)
1142{
1143 return PyArg_Parse(v, "(hll(hh)h)",
1144 &e->what,
1145 &e->message,
1146 &e->when,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001147 &e->where.h,
Guido van Rossum5279ec61995-01-26 22:56:59 +00001148 &e->where.v,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001149 &e->modifiers);
1150}
1151
1152/* Convert a Rect to an EventRecord object */
1153PyObject *
1154PyMac_BuildEventRecord(EventRecord *e)
1155{
1156 return Py_BuildValue("(hll(hh)h)",
1157 e->what,
1158 e->message,
1159 e->when,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001160 e->where.h,
Guido van Rossum5279ec61995-01-26 22:56:59 +00001161 e->where.v,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001162 e->modifiers);
Guido van Rossumb3404661995-01-22 18:36:13 +00001163}
Jack Jansenfa4d5d01995-11-15 15:19:29 +00001164
1165/* Convert Python object to Fixed */
1166int
1167PyMac_GetFixed(PyObject *v, Fixed *f)
1168{
1169 double d;
1170
1171 if( !PyArg_Parse(v, "d", &d))
1172 return 0;
1173 *f = (Fixed)(d * 0x10000);
Jack Jansen31dd5c01996-05-31 13:01:39 +00001174 return 1;
Jack Jansenfa4d5d01995-11-15 15:19:29 +00001175}
1176
1177/* Convert a Point to a Python object */
1178PyObject *
1179PyMac_BuildFixed(Fixed f)
1180{
1181 double d;
1182
1183 d = f;
1184 d = d / 0x10000;
1185 return Py_BuildValue("d", d);
1186}
1187
Jack Jansend58cd631998-04-21 15:24:39 +00001188/* Convert wide to/from Python int or (hi, lo) tuple. XXXX Should use Python longs */
1189int
1190PyMac_Getwide(PyObject *v, wide *rv)
1191{
1192 if (PyInt_Check(v)) {
1193 rv->hi = 0;
1194 rv->lo = PyInt_AsLong(v);
1195 if( rv->lo & 0x80000000 )
1196 rv->hi = -1;
1197 return 1;
1198 }
1199 return PyArg_Parse(v, "(ll)", &rv->hi, &rv->lo);
1200}
1201
1202
1203PyObject *
Jack Jansenbbf4be21998-04-23 13:20:17 +00001204PyMac_Buildwide(wide *w)
Jack Jansend58cd631998-04-21 15:24:39 +00001205{
Jack Jansenbbf4be21998-04-23 13:20:17 +00001206 if ( (w->hi == 0 && (w->lo & 0x80000000) == 0) ||
1207 (w->hi == -1 && (w->lo & 0x80000000) ) )
1208 return PyInt_FromLong(w->lo);
1209 return Py_BuildValue("(ll)", w->hi, w->lo);
Jack Jansend58cd631998-04-21 15:24:39 +00001210}
Jack Jansen8bb1dc12001-05-19 12:31:09 +00001211
1212#ifdef USE_TOOLBOX_OBJECT_GLUE
1213/*
1214** Glue together the toolbox objects.
1215**
1216** Because toolbox modules interdepend on each other, they use each others
1217** object types, on MacOSX/MachO this leads to the situation that they
1218** cannot be dynamically loaded (or they would all have to be lumped into
1219** a single .so, but this would be bad for extensibility).
1220**
1221** This file defines wrappers for all the _New and _Convert functions,
1222** which are the Py_BuildValue and PyArg_ParseTuple helpers. The wrappers
1223** check an indirection function pointer, and if it isn't filled in yet
1224** they import the appropriate module, whose init routine should fill in
1225** the pointer.
1226*/
1227
1228#define GLUE_NEW(object, routinename, module) \
1229PyObject *(*PyMacGluePtr_##routinename)(object); \
1230\
1231PyObject *routinename(object cobj) { \
1232 if (!PyMacGluePtr_##routinename) { \
1233 if (!PyImport_ImportModule(module)) return NULL; \
1234 if (!PyMacGluePtr_##routinename) { \
1235 PyErr_SetString(PyExc_ImportError, "Module did not provide routine: " module ": " #routinename); \
1236 return NULL; \
1237 } \
1238 } \
1239 return (*PyMacGluePtr_##routinename)(cobj); \
1240}
1241
1242#define GLUE_CONVERT(object, routinename, module) \
1243int (*PyMacGluePtr_##routinename)(PyObject *, object *); \
1244\
1245int routinename(PyObject *pyobj, object *cobj) { \
1246 if (!PyMacGluePtr_##routinename) { \
1247 if (!PyImport_ImportModule(module)) return NULL; \
1248 if (!PyMacGluePtr_##routinename) { \
1249 PyErr_SetString(PyExc_ImportError, "Module did not provide routine: " module ": " #routinename); \
1250 return NULL; \
1251 } \
1252 } \
1253 return (*PyMacGluePtr_##routinename)(pyobj, cobj); \
1254}
1255
1256GLUE_NEW(AppleEvent *, AEDesc_New, "AE") /* XXXX Why by address? */
1257GLUE_CONVERT(AppleEvent, AEDesc_Convert, "AE")
1258
1259GLUE_NEW(Component, CmpObj_New, "Cm")
1260GLUE_CONVERT(Component, CmpObj_Convert, "Cm")
1261GLUE_NEW(ComponentInstance, CmpInstObj_New, "Cm")
1262GLUE_CONVERT(ComponentInstance, CmpInstObj_Convert, "Cm")
1263
1264GLUE_NEW(ControlHandle, CtlObj_New, "Ctl")
1265GLUE_CONVERT(ControlHandle, CtlObj_Convert, "Ctl")
1266
1267GLUE_NEW(DialogPtr, DlgObj_New, "Dlg")
1268GLUE_CONVERT(DialogPtr, DlgObj_Convert, "Dlg")
1269GLUE_NEW(DialogPtr, DlgObj_WhichDialog, "Dlg")
1270
1271GLUE_NEW(DragReference, DragObj_New, "Drag")
1272GLUE_CONVERT(DragReference, DragObj_Convert, "Drag")
1273
1274GLUE_NEW(ListHandle, ListObj_New, "List")
1275GLUE_CONVERT(ListHandle, ListObj_Convert, "List")
1276
1277GLUE_NEW(MenuHandle, MenuObj_New, "Menu")
1278GLUE_CONVERT(MenuHandle, MenuObj_Convert, "Menu")
1279
1280GLUE_NEW(GrafPtr, GrafObj_New, "Qd")
1281GLUE_CONVERT(GrafPtr, GrafObj_Convert, "Qd")
1282GLUE_NEW(BitMapPtr, BMObj_New, "Qd")
1283GLUE_CONVERT(BitMapPtr, BMObj_Convert, "Qd")
1284GLUE_NEW(RGBColor *, QdRGB_New, "Qd") /* XXXX Why? */
1285GLUE_CONVERT(RGBColor, QdRGB_Convert, "Qd")
1286
1287GLUE_NEW(GWorldPtr, GWorldObj_New, "Qdoffs")
1288GLUE_CONVERT(GWorldPtr, GWorldObj_Convert, "Qdoffs")
1289
1290GLUE_NEW(Track, TrackObj_New, "Qt")
1291GLUE_CONVERT(Track, TrackObj_Convert, "Qt")
1292GLUE_NEW(Movie, MovieObj_New, "Qt")
1293GLUE_CONVERT(Movie, MovieObj_Convert, "Qt")
1294GLUE_NEW(MovieController, MovieCtlObj_New, "Qt")
1295GLUE_CONVERT(MovieController, MovieCtlObj_Convert, "Qt")
1296GLUE_NEW(TimeBase, TimeBaseObj_New, "Qt")
1297GLUE_CONVERT(TimeBase, TimeBaseObj_Convert, "Qt")
1298GLUE_NEW(UserData, UserDataObj_New, "Qt")
1299GLUE_CONVERT(UserData, UserDataObj_Convert, "Qt")
1300GLUE_NEW(Media, MediaObj_New, "Qt")
1301GLUE_CONVERT(Media, MediaObj_Convert, "Qt")
1302
1303GLUE_NEW(Handle, ResObj_New, "Res")
1304GLUE_CONVERT(Handle, ResObj_Convert, "Res")
1305GLUE_NEW(Handle, OptResObj_New, "Res")
1306GLUE_CONVERT(Handle, OptResObj_Convert, "Res")
1307
1308GLUE_NEW(TEHandle, TEObj_New, "TE")
1309GLUE_CONVERT(TEHandle, TEObj_Convert, "TE")
1310
1311GLUE_NEW(WindowPtr, WinObj_New, "Win")
1312GLUE_CONVERT(WindowPtr, WinObj_Convert, "Win")
1313GLUE_NEW(WindowPtr, WinObj_WhichWindow, "Win")
1314
1315#endif /* USE_TOOLBOX_OBJECT_GLUE */