blob: 052c1ee9158423a5722023c6f5f415aad9005564 [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;
unknownf428aef2001-07-04 22:36:27 +0000224#if 0
225 /* We don't have a codec for this, so don't return it */
Jack Jansen1f9f2f42000-07-24 19:50:16 +0000226 case smJapanese:
227 return "mac-japan";
unknownf428aef2001-07-04 22:36:27 +0000228#endif
Jack Jansen1f9f2f42000-07-24 19:50:16 +0000229 case smGreek:
230 return "mac-greek";
231 case smCyrillic:
232 return "mac-cyrillic";
233 default:
234 return "mac-roman"; /* better than nothing */
235 }
236}
237
Jack Jansen741e0372001-05-19 12:55:57 +0000238/* Given an FSSpec, return the FSSpec of the parent folder */
239
240static OSErr
241get_folder_parent (FSSpec * fss, FSSpec * parent)
242{
243 CInfoPBRec rec;
244 short err;
245
246 * parent = * fss;
247 rec.hFileInfo.ioNamePtr = parent->name;
248 rec.hFileInfo.ioVRefNum = parent->vRefNum;
249 rec.hFileInfo.ioDirID = parent->parID;
250 rec.hFileInfo.ioFDirIndex = -1;
251 rec.hFileInfo.ioFVersNum = 0;
252 if (err = PBGetCatInfoSync (& rec))
253 return err;
254 parent->parID = rec.dirInfo.ioDrParID;
255/* parent->name[0] = 0; */
256 return 0;
257}
258
259/* Given an FSSpec return a full, colon-separated pathname */
260
261OSErr
262PyMac_GetFullPath (FSSpec *fss, char *buf)
263{
264 short err;
265 FSSpec fss_parent, fss_current;
266 char tmpbuf[1024];
267 int plen;
268
269 fss_current = *fss;
270 plen = fss_current.name[0];
271 memcpy(buf, &fss_current.name[1], plen);
272 buf[plen] = 0;
273 /* Special case for disk names */
274 if ( fss_current.parID <= 1 ) {
275 buf[plen++] = ':';
276 buf[plen] = 0;
277 return 0;
278 }
279 while (fss_current.parID > 1) {
280 /* Get parent folder name */
281 if (err = get_folder_parent(&fss_current, &fss_parent))
282 return err;
283 fss_current = fss_parent;
284 /* Prepend path component just found to buf */
285 plen = fss_current.name[0];
286 if (strlen(buf) + plen + 1 > 1024) {
287 /* Oops... Not enough space (shouldn't happen) */
288 *buf = 0;
289 return -1;
290 }
291 memcpy(tmpbuf, &fss_current.name[1], plen);
292 tmpbuf[plen] = ':';
293 strcpy(&tmpbuf[plen+1], buf);
294 strcpy(buf, tmpbuf);
295 }
296 return 0;
297}
Jack Jansen1f9f2f42000-07-24 19:50:16 +0000298
Jack Jansen2d1306b2000-04-07 09:10:49 +0000299#ifdef USE_GUSI1
Jack Jansen378815c1996-03-06 16:21:34 +0000300/*
301** GUSI (1.6.0 and earlier, at the least) do not set the MacOS idea of
302** the working directory. Hence, we call this routine after each call
303** to chdir() to rectify things.
304*/
305void
306PyMac_FixGUSIcd()
307{
308 WDPBRec pb;
309 FSSpec curdirfss;
310
311 if ( Path2FSSpec(":x", &curdirfss) != noErr )
312 return;
313
314 /* Set MacOS "working directory" */
315 pb.ioNamePtr= "\p";
316 pb.ioVRefNum= curdirfss.vRefNum;
317 pb.ioWDDirID= curdirfss.parID;
Jack Jansen08c3be31997-04-08 15:27:00 +0000318 if (PBHSetVolSync(&pb) != noErr)
Jack Jansen378815c1996-03-06 16:21:34 +0000319 return;
Jack Jansen378815c1996-03-06 16:21:34 +0000320}
Jack Jansen2d1306b2000-04-07 09:10:49 +0000321#endif
Jack Jansen7ac70af1996-08-19 11:01:05 +0000322
Jack Jansen2d1306b2000-04-07 09:10:49 +0000323#ifdef USE_GUSI
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000324/*
325** SpinCursor (needed by GUSI) drags in heaps of stuff, so we
326** provide a dummy here.
327*/
Jack Jansencfadbd41996-08-19 11:36:25 +0000328void SpinCursor(short x) { /* Dummy */ }
Jack Jansenefaada71998-02-20 16:03:15 +0000329void RotateCursor(short x) { /* Dummy */ }
Jack Jansencfadbd41996-08-19 11:36:25 +0000330
Jack Jansenf6865f71996-09-04 15:24:59 +0000331/*
332** Replacement GUSI Spin function
333*/
Jack Jansen2d1306b2000-04-07 09:10:49 +0000334#ifdef USE_GUSI1
Jack Jansenf6865f71996-09-04 15:24:59 +0000335static int
336PyMac_GUSISpin(spin_msg msg, long arg)
337{
Jack Jansene3ae0df1997-06-03 15:28:29 +0000338 static Boolean inForeground = true;
339 int maxsleep = 6; /* 6 ticks is "normal" sleeptime */
Jack Jansenf6865f71996-09-04 15:24:59 +0000340
341 if (PyMac_ConsoleIsDead) return 0;
342#if 0
343 if (inForeground)
344 SpinCursor(msg == SP_AUTO_SPIN ? short(arg) : 1);
345#endif
346
347 if (interrupted) return -1;
348
Jack Jansene3ae0df1997-06-03 15:28:29 +0000349 if ( msg == SP_AUTO_SPIN )
350 maxsleep = 0;
351 if ( msg==SP_SLEEP||msg==SP_SELECT )
352 maxsleep = arg;
Jack Jansenf6865f71996-09-04 15:24:59 +0000353
Jack Jansene3ae0df1997-06-03 15:28:29 +0000354 PyMac_DoYield(maxsleep, 0); /* XXXX or is it safe to call python here? */
Jack Jansenf6865f71996-09-04 15:24:59 +0000355
356 return 0;
357}
358
359void
360PyMac_SetGUSISpin() {
361 GUSISetHook(GUSI_SpinHook, (GUSIHook)PyMac_GUSISpin);
362}
Jack Jansen2d1306b2000-04-07 09:10:49 +0000363#endif
Jack Jansenf6865f71996-09-04 15:24:59 +0000364
Jack Jansena39f1b01997-05-23 15:35:14 +0000365/* Called at exit() time thru atexit(), to stop event processing */
366void
367PyMac_StopGUSISpin() {
368 PyMac_ConsoleIsDead = 1;
369}
370
Jack Jansen6e68a7e2001-05-12 21:31:34 +0000371#if TARGET_API_MAC_OS8
Jack Jansena39f1b01997-05-23 15:35:14 +0000372/*
373** Replacement routines for the PLstr... functions so we don't need
Jack Jansen6ba34aa2001-01-11 23:03:56 +0000374** StdCLib.
Jack Jansena39f1b01997-05-23 15:35:14 +0000375*/
Jack Jansen8bb573e1999-12-12 21:37:14 +0000376pascal void
Jack Jansen9ae898b2000-07-11 21:16:03 +0000377PLstrcpy(unsigned char *to, unsigned char *fr)
Jack Jansena39f1b01997-05-23 15:35:14 +0000378{
379 memcpy(to, fr, fr[0]+1);
380}
381
Jack Jansen8bb573e1999-12-12 21:37:14 +0000382pascal int
Jack Jansen9ae898b2000-07-11 21:16:03 +0000383PLstrcmp(unsigned char *s1, unsigned char *s2)
Jack Jansena39f1b01997-05-23 15:35:14 +0000384{
385 int res;
386 int l = s1[0] < s2[0] ? s1[0] : s2[0];
387
388 res = memcmp(s1+1, s2+1, l);
389 if ( res != 0 )
390 return res;
391
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000392 if ( s1[0] < s2[0] )
Jack Jansena39f1b01997-05-23 15:35:14 +0000393 return -1;
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000394 else if ( s1[0] > s2[0] )
Jack Jansena39f1b01997-05-23 15:35:14 +0000395 return 1;
396 else
397 return 0;
398}
399
Jack Jansen8bb573e1999-12-12 21:37:14 +0000400pascal unsigned char *
Jack Jansen9ae898b2000-07-11 21:16:03 +0000401PLstrrchr(unsigned char *str, unsigned char chr)
Jack Jansena39f1b01997-05-23 15:35:14 +0000402{
403 unsigned char *ptr = 0;
404 unsigned char *p;
405
406 for(p=str+1; p<str+str[0]; p++)
407 if ( *p == chr )
408 ptr = p;
409 return ptr;
410}
411
Jack Jansen6e68a7e2001-05-12 21:31:34 +0000412#endif /* TARGET_API_MAC_OS8 */
Jack Jansena39f1b01997-05-23 15:35:14 +0000413#endif /* USE_GUSI */
Jack Jansen378815c1996-03-06 16:21:34 +0000414
Jack Jansen819f1771995-08-14 12:35:10 +0000415
Jack Jansen5f653091995-01-18 13:53:49 +0000416/* Convert C to Pascal string. Returns pointer to static buffer. */
417unsigned char *
418Pstring(char *str)
419{
420 static Str255 buf;
421 int len;
422
423 len = strlen(str);
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000424 if (len > 255)
425 len = 255;
Jack Jansen5f653091995-01-18 13:53:49 +0000426 buf[0] = (unsigned char)len;
427 strncpy((char *)buf+1, str, len);
428 return buf;
429}
430
Jack Jansen6e68a7e2001-05-12 21:31:34 +0000431#if TARGET_API_MAC_OS8
Jack Jansen5afad832000-12-12 22:12:14 +0000432void
433c2pstrcpy(unsigned char *dst, const char *src)
434{
435 int len;
436
437 len = strlen(src);
438 if ( len > 255 ) len = 255;
439 strncpy((char *)dst+1, src, len);
440 dst[0] = len;
441}
Jack Jansen6e68a7e2001-05-12 21:31:34 +0000442#endif /* TARGET_API_MAC_OS8 */
Jack Jansen5afad832000-12-12 22:12:14 +0000443
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000444/* Like strerror() but for Mac OS error numbers */
445char *PyMac_StrError(int err)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000446{
447 static char buf[256];
448 Handle h;
449 char *str;
450
451 h = GetResource('Estr', err);
452 if ( h ) {
453 HLock(h);
454 str = (char *)*h;
455 memcpy(buf, str+1, (unsigned char)str[0]);
Guido van Rossumcc9bc8f1995-02-13 16:17:03 +0000456 buf[(unsigned char)str[0]] = '\0';
Jack Jansenf93c72a1994-12-14 14:07:50 +0000457 HUnlock(h);
458 ReleaseResource(h);
459 } else {
460 sprintf(buf, "Mac OS error code %d", err);
461 }
462 return buf;
463}
464
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000465/* Exception object shared by all Mac specific modules for Mac OS errors */
466PyObject *PyMac_OSErrException;
467
468/* Initialize and return PyMac_OSErrException */
469PyObject *
470PyMac_GetOSErrException()
471{
472 if (PyMac_OSErrException == NULL)
unknownf428aef2001-07-04 22:36:27 +0000473 PyMac_OSErrException = PyString_FromString("MacOS.Error");
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000474 return PyMac_OSErrException;
475}
476
Jack Jansenf93c72a1994-12-14 14:07:50 +0000477/* Set a MAC-specific error from errno, and return NULL; return None if no error */
478PyObject *
Guido van Rossumfffb8bb1995-01-12 12:37:24 +0000479PyErr_Mac(PyObject *eobj, int err)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000480{
481 char *msg;
482 PyObject *v;
Jack Jansenf93c72a1994-12-14 14:07:50 +0000483
Guido van Rossum8f691791995-01-18 23:57:26 +0000484 if (err == 0 && !PyErr_Occurred()) {
Jack Jansenf93c72a1994-12-14 14:07:50 +0000485 Py_INCREF(Py_None);
486 return Py_None;
487 }
Guido van Rossum8f691791995-01-18 23:57:26 +0000488 if (err == -1 && PyErr_Occurred())
489 return NULL;
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000490 msg = PyMac_StrError(err);
Jack Jansenf93c72a1994-12-14 14:07:50 +0000491 v = Py_BuildValue("(is)", err, msg);
492 PyErr_SetObject(eobj, v);
493 Py_DECREF(v);
494 return NULL;
495}
496
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000497/* Call PyErr_Mac with PyMac_OSErrException */
498PyObject *
499PyMac_Error(OSErr err)
500{
501 return PyErr_Mac(PyMac_GetOSErrException(), err);
502}
503
Jack Jansen1ed95291996-07-22 15:25:10 +0000504#ifdef USE_STACKCHECK
505/* Check for stack overflow */
506int
507PyOS_CheckStack()
508{
Jack Jansen14a91712000-08-25 21:57:23 +0000509 char here;
510 static char *sentinel = 0;
Jack Jansen53bafd92000-09-08 22:05:48 +0000511 static PyThreadState *thread_for_sentinel = 0;
Jack Jansen1ed95291996-07-22 15:25:10 +0000512
Jack Jansen340eb882001-02-02 22:40:28 +0000513 if ( sentinel == 0 ) {
514 unsigned long stackspace = StackSpace();
515
516#ifdef MAXIMUM_STACK_SIZE
517 /* See the comment at the definition */
518 if ( stackspace > MAXIMUM_STACK_SIZE )
519 stackspace = MAXIMUM_STACK_SIZE;
520#endif
521 sentinel = &here - stackspace + MINIMUM_STACK_SIZE;
Jack Jansen14a91712000-08-25 21:57:23 +0000522 }
Jack Jansen53bafd92000-09-08 22:05:48 +0000523 if ( thread_for_sentinel == 0 ) {
524 thread_for_sentinel = PyThreadState_Get();
525 }
526 if ( &here < sentinel ) {
527 if (thread_for_sentinel == PyThreadState_Get()) {
528 return -1;
529#if 0
530 } else {
531 /* Else we are unsure... */
532 fprintf(stderr, "Stackcheck in other thread (was %x now %x)\n", thread_for_sentinel,PyThreadState_Get());
533#endif
534 }
535 }
Jack Jansen1ed95291996-07-22 15:25:10 +0000536 return 0;
537}
538#endif /* USE_STACKCHECK */
539
Jack Jansen0194ad52001-05-12 22:46:35 +0000540#if !TARGET_API_MAC_OSX
Jack Jansenee23d6e1995-01-27 14:43:25 +0000541/* The catcher routine (which may not be used for all compilers) */
542static RETSIGTYPE
543intcatcher(sig)
544 int sig;
545{
546 interrupted = 1;
547 signal(SIGINT, intcatcher);
548}
549
550void
551PyOS_InitInterrupts()
552{
553 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
554 signal(SIGINT, intcatcher);
555}
556
Jack Jansena8441de1997-08-08 14:57:37 +0000557void
558PyOS_FiniInterrupts()
559{
560}
561
Jack Jansenee23d6e1995-01-27 14:43:25 +0000562/*
563** This routine scans the event queue looking for cmd-.
564** This is the only way to get an interrupt under THINK (since it
565** doesn't do SIGINT handling), but is also used under MW, when
566** the full-fledged event loop is disabled. This way, we can at least
567** interrupt a runaway python program.
568*/
569static void
570scan_event_queue(flush)
571 int flush;
572{
Jack Jansen6e68a7e2001-05-12 21:31:34 +0000573#if !TARGET_API_MAC_OS8
Jack Jansend7b68022001-01-12 23:42:28 +0000574 if ( CheckEventQueueForUserCancel() )
575 interrupted = 1;
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000576#else
Jack Jansenee23d6e1995-01-27 14:43:25 +0000577 register EvQElPtr q;
578
Jack Jansenefaada71998-02-20 16:03:15 +0000579 q = (EvQElPtr) LMGetEventQueue()->qHead;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000580
581 for (; q; q = (EvQElPtr)q->qLink) {
582 if (q->evtQWhat == keyDown &&
583 (char)q->evtQMessage == '.' &&
584 (q->evtQModifiers & cmdKey) != 0) {
585 if ( flush )
586 FlushEvents(keyDownMask, 0);
587 interrupted = 1;
588 break;
589 }
590 }
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000591#endif
Jack Jansenee23d6e1995-01-27 14:43:25 +0000592}
593
594int
Jack Jansen36ed5061997-06-20 16:18:15 +0000595PyErr_CheckSignals()
Jack Jansenee23d6e1995-01-27 14:43:25 +0000596{
Jack Jansene3ae0df1997-06-03 15:28:29 +0000597 if (schedparams.enabled) {
598 if ( (unsigned long)LMGetTicks() > schedparams.next_check ) {
Jack Jansen36ed5061997-06-20 16:18:15 +0000599 if ( PyMac_Yield() < 0)
600 return -1;
Jack Jansene3ae0df1997-06-03 15:28:29 +0000601 schedparams.next_check = (unsigned long)LMGetTicks()
602 + schedparams.check_interval;
603 if (interrupted) {
Jack Jansencaa7c461997-06-12 10:49:13 +0000604 scan_event_queue(1); /* Eat events up to cmd-. */
Jack Jansene3ae0df1997-06-03 15:28:29 +0000605 interrupted = 0;
Jack Jansen36ed5061997-06-20 16:18:15 +0000606 PyErr_SetNone(PyExc_KeyboardInterrupt);
607 return -1;
Jack Jansene3ae0df1997-06-03 15:28:29 +0000608 }
609 }
Jack Jansenee23d6e1995-01-27 14:43:25 +0000610 }
611 return 0;
612}
613
Jack Jansen36ed5061997-06-20 16:18:15 +0000614int
615PyOS_InterruptOccurred()
616{
617 scan_event_queue(1);
618 return interrupted;
619}
Jack Jansen0194ad52001-05-12 22:46:35 +0000620
Jack Jansenee23d6e1995-01-27 14:43:25 +0000621/* Check whether we are in the foreground */
Jack Jansen9ae898b2000-07-11 21:16:03 +0000622static int
623PyMac_InForeground(void)
Jack Jansenee23d6e1995-01-27 14:43:25 +0000624{
625 static ProcessSerialNumber ours;
626 static inited;
627 ProcessSerialNumber curfg;
628 Boolean eq;
629
Jack Jansene3ae0df1997-06-03 15:28:29 +0000630 if ( inited == 0 ) {
Jack Jansenee23d6e1995-01-27 14:43:25 +0000631 (void)GetCurrentProcess(&ours);
Jack Jansene3ae0df1997-06-03 15:28:29 +0000632 inited = 1;
633 }
Jack Jansenee23d6e1995-01-27 14:43:25 +0000634 if ( GetFrontProcess(&curfg) < 0 )
635 eq = 1;
636 else if ( SameProcess(&ours, &curfg, &eq) < 0 )
637 eq = 1;
638 return (int)eq;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000639}
Jack Jansen0194ad52001-05-12 22:46:35 +0000640#endif
Jack Jansenee23d6e1995-01-27 14:43:25 +0000641
Jack Jansen36ed5061997-06-20 16:18:15 +0000642int
643PyMac_SetEventHandler(PyObject *evh)
644{
645 if ( evh && python_event_handler ) {
646 PyErr_SetString(PyExc_RuntimeError, "Python event handler already set");
647 return 0;
648 }
649 if ( python_event_handler )
650 Py_DECREF(python_event_handler);
651 if ( evh )
652 Py_INCREF(evh);
653 python_event_handler = evh;
654 return 1;
655}
656
Jack Jansenf93c72a1994-12-14 14:07:50 +0000657/*
Jack Jansena76382a1995-02-02 14:25:56 +0000658** Handle an event, either one found in the mainloop eventhandler or
659** one passed back from the python program.
660*/
661void
Jack Jansen36ed5061997-06-20 16:18:15 +0000662PyMac_HandleEventIntern(evp)
Jack Jansena76382a1995-02-02 14:25:56 +0000663 EventRecord *evp;
664{
Jack Jansen6e68a7e2001-05-12 21:31:34 +0000665#if TARGET_API_MAC_OS8
Jack Jansen0c968871997-08-26 13:20:34 +0000666 if ( evp->what == mouseDown ) {
667 WindowPtr wp;
668
669 if ( FindWindow(evp->where, &wp) == inSysWindow ) {
670 SystemClick(evp, wp);
671 return;
672 }
673 }
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000674#endif
Jack Jansena76382a1995-02-02 14:25:56 +0000675#ifdef __MWERKS__
Jack Jansen38e97661995-11-10 14:53:00 +0000676 {
677 int siouxdidit;
678
679 /* If SIOUX wants it we're done */
680 siouxdidit = SIOUXHandleOneEvent(evp);
681 if ( siouxdidit )
682 return;
683 }
Jack Jansena76382a1995-02-02 14:25:56 +0000684#else
Jack Jansen0c968871997-08-26 13:20:34 +0000685 /* Other compilers are just unlucky... */
Jack Jansena76382a1995-02-02 14:25:56 +0000686#endif /* !__MWERKS__ */
Jack Jansen36ed5061997-06-20 16:18:15 +0000687}
688
689/*
690** Handle an event, either through HandleEvent or by passing it to the Python
691** event handler.
692*/
693int
694PyMac_HandleEvent(evp)
695 EventRecord *evp;
696{
697 PyObject *rv;
698
699 if ( python_event_handler ) {
700 rv = PyObject_CallFunction(python_event_handler, "(O&)",
701 PyMac_BuildEventRecord, evp);
702 if ( rv )
703 Py_DECREF(rv);
704 else
705 return -1; /* Propagate exception */
706 } else {
707 PyMac_HandleEventIntern(evp);
708 }
709 return 0;
Jack Jansena76382a1995-02-02 14:25:56 +0000710}
711
Jack Jansen0194ad52001-05-12 22:46:35 +0000712#if !TARGET_API_MAC_OSX
Jack Jansena76382a1995-02-02 14:25:56 +0000713/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000714** Yield the CPU to other tasks without processing events.
Jack Jansene8e8ae01995-01-26 16:36:45 +0000715*/
Jack Jansen2d1306b2000-04-07 09:10:49 +0000716int
Jack Jansene3ae0df1997-06-03 15:28:29 +0000717PyMac_DoYield(int maxsleep, int maycallpython)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000718{
719 EventRecord ev;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000720 int gotone;
Jack Jansene3ae0df1997-06-03 15:28:29 +0000721 long latest_time_ready;
Jack Jansen36ed5061997-06-20 16:18:15 +0000722 static int in_here = 0;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000723
Jack Jansen36ed5061997-06-20 16:18:15 +0000724 in_here++;
Jack Jansene3ae0df1997-06-03 15:28:29 +0000725 /*
726 ** First check for interrupts, if wanted.
727 ** This sets a flag that will be picked up at an appropriate
728 ** moment in the mainloop.
729 */
730 if (schedparams.check_interrupt)
Jack Jansenee23d6e1995-01-27 14:43:25 +0000731 scan_event_queue(0);
Jack Jansene3ae0df1997-06-03 15:28:29 +0000732
733 /* XXXX Implementing an idle routine goes here */
Jack Jansene8e8ae01995-01-26 16:36:45 +0000734
Jack Jansene3ae0df1997-06-03 15:28:29 +0000735 /*
736 ** Check which of the eventloop cases we have:
737 ** - process events
738 ** - don't process events but do yield
739 ** - do neither
740 */
Jack Jansen36ed5061997-06-20 16:18:15 +0000741 if( in_here > 1 || !schedparams.process_events ||
742 (python_event_handler && !maycallpython) ) {
Jack Jansene3ae0df1997-06-03 15:28:29 +0000743 if ( maxsleep >= 0 ) {
Jack Jansen6e68a7e2001-05-12 21:31:34 +0000744#if TARGET_API_MAC_OS8
Jack Jansene8e8ae01995-01-26 16:36:45 +0000745 SystemTask();
Jack Jansen15f1c082001-04-25 22:07:27 +0000746#else
747 int xxx = 0;
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000748#endif
Jack Jansen15f1c082001-04-25 22:07:27 +0000749 }
Jack Jansene3ae0df1997-06-03 15:28:29 +0000750 } else {
751 latest_time_ready = LMGetTicks() + maxsleep;
Jack Jansen2d1306b2000-04-07 09:10:49 +0000752 do {
Jack Jansen0c968871997-08-26 13:20:34 +0000753 /* XXXX Hack by Jack.
754 ** In time.sleep() you can click to another application
755 ** once only. If you come back to Python you cannot get away
756 ** again.
757 **/
Jack Jansen36ed5061997-06-20 16:18:15 +0000758 gotone = WaitNextEvent(schedparams.process_events, &ev, maxsleep, NULL);
Jack Jansene3ae0df1997-06-03 15:28:29 +0000759 /* Get out quickly if nothing interesting is happening */
760 if ( !gotone || ev.what == nullEvent )
761 break;
Jack Jansen36ed5061997-06-20 16:18:15 +0000762 if ( PyMac_HandleEvent(&ev) < 0 ) {
763 in_here--;
764 return -1;
765 }
Jack Jansene3ae0df1997-06-03 15:28:29 +0000766 maxsleep = latest_time_ready - LMGetTicks();
Jack Jansen2d1306b2000-04-07 09:10:49 +0000767 } while ( maxsleep > 0 );
Jack Jansenf93c72a1994-12-14 14:07:50 +0000768 }
Jack Jansen36ed5061997-06-20 16:18:15 +0000769 in_here--;
770 return 0;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000771}
772
773/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000774** Process events and/or yield the CPU to other tasks if opportune
Jack Jansene8e8ae01995-01-26 16:36:45 +0000775*/
Jack Jansen36ed5061997-06-20 16:18:15 +0000776int
Jack Jansene8e8ae01995-01-26 16:36:45 +0000777PyMac_Yield() {
Jack Jansene3ae0df1997-06-03 15:28:29 +0000778 unsigned long maxsleep;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000779
Jack Jansene3ae0df1997-06-03 15:28:29 +0000780 if( PyMac_InForeground() )
781 maxsleep = 0;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000782 else
Jack Jansene3ae0df1997-06-03 15:28:29 +0000783 maxsleep = schedparams.bg_yield;
784
Jack Jansen36ed5061997-06-20 16:18:15 +0000785 return PyMac_DoYield(maxsleep, 1);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000786}
787
788/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000789** Return current scheduler parameters
Jack Jansene8e8ae01995-01-26 16:36:45 +0000790*/
Jack Jansene3ae0df1997-06-03 15:28:29 +0000791void
792PyMac_GetSchedParams(PyMacSchedParams *sp)
Jack Jansene8e8ae01995-01-26 16:36:45 +0000793{
Jack Jansene3ae0df1997-06-03 15:28:29 +0000794 sp->check_interrupt = schedparams.check_interrupt;
795 sp->process_events = schedparams.process_events;
796 sp->besocial = schedparams.besocial;
797 sp->check_interval = schedparams.check_interval / 60.0;
798 sp->bg_yield = schedparams.bg_yield / 60.0;
Jack Jansenf93c72a1994-12-14 14:07:50 +0000799}
Jack Jansenf6865f71996-09-04 15:24:59 +0000800
Jack Jansen74162f31995-02-15 22:58:33 +0000801/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000802** Set current scheduler parameters
803*/
804void
805PyMac_SetSchedParams(PyMacSchedParams *sp)
806{
807 schedparams.check_interrupt = sp->check_interrupt;
808 schedparams.process_events = sp->process_events;
809 schedparams.besocial = sp->besocial;
810 schedparams.check_interval = (unsigned long)(sp->check_interval*60);
811 schedparams.bg_yield = (unsigned long)(sp->bg_yield*60);
812 if ( schedparams.check_interrupt || schedparams.process_events ||
813 schedparams.besocial )
814 schedparams.enabled = 1;
815 else
816 schedparams.enabled = 0;
817 schedparams.next_check = 0; /* Check immedeately */
818}
Jack Jansencaa7c461997-06-12 10:49:13 +0000819
Jack Jansene3ae0df1997-06-03 15:28:29 +0000820/*
Jack Jansen3469e991996-09-06 00:30:45 +0000821** Install our menu bar.
822*/
823void
824PyMac_InitMenuBar()
825{
Jack Jansen3469e991996-09-06 00:30:45 +0000826 MenuHandle applemenu;
827
Jack Jansen15f1c082001-04-25 22:07:27 +0000828 if ( sioux_mbar ) return;
Jack Jansencaa7c461997-06-12 10:49:13 +0000829 if ( (sioux_mbar=GetMenuBar()) == NULL ) {
830 /* Sioux menu not installed yet. Do so */
831 SIOUXSetupMenus();
832 if ( (sioux_mbar=GetMenuBar()) == NULL )
833 return;
834 }
Jack Jansen08c3be31997-04-08 15:27:00 +0000835 if ( (applemenu=GetMenuHandle(SIOUX_APPLEID)) == NULL ) return;
Jack Jansen3469e991996-09-06 00:30:45 +0000836 SetMenuItemText(applemenu, 1, "\pAbout Python...");
837}
838
839/*
Jack Jansencaa7c461997-06-12 10:49:13 +0000840** Restore sioux menu bar
841*/
842void
843PyMac_RestoreMenuBar()
844{
Jack Jansen15f1c082001-04-25 22:07:27 +0000845#if 1
Jack Jansen657ba272001-02-17 22:02:07 +0000846 /* This doesn't seem to work anymore? Or only for Carbon? */
847 MenuBarHandle curmenubar;
848
849 curmenubar = GetMenuBar();
Jack Janseneda78631997-06-12 15:29:46 +0000850 if ( sioux_mbar ) {
Jack Jansencaa7c461997-06-12 10:49:13 +0000851 SetMenuBar(sioux_mbar);
Jack Janseneda78631997-06-12 15:29:46 +0000852 DrawMenuBar();
Jack Jansen657ba272001-02-17 22:02:07 +0000853 } else {
Jack Jansenefaada71998-02-20 16:03:15 +0000854 PyMac_InitMenuBar();
Jack Jansen657ba272001-02-17 22:02:07 +0000855 DrawMenuBar();
856 }
857#endif
Jack Jansencaa7c461997-06-12 10:49:13 +0000858}
859
Jack Jansen15f1c082001-04-25 22:07:27 +0000860void
861PyMac_RaiseConsoleWindow()
862{
863 /* Note: this is a hack. SIOUXTextWindow is SIOUX's internal structure
864 ** and we happen to know that the first entry is the window pointer.
865 */
866 extern WindowRef *SIOUXTextWindow;
867
868 if ( SIOUXTextWindow == NULL || *SIOUXTextWindow == NULL )
869 return;
870 if ( FrontWindow() != *SIOUXTextWindow )
871 BringToFront(*SIOUXTextWindow);
872}
Jack Jansencaa7c461997-06-12 10:49:13 +0000873
874/*
Jack Jansen3469e991996-09-06 00:30:45 +0000875** Our replacement about box
876*/
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000877
878#include "patchlevel.h"
879
Jack Jansen3469e991996-09-06 00:30:45 +0000880void
881SIOUXDoAboutBox(void)
882{
883 DialogPtr theDialog;
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000884 WindowPtr theWindow;
Jack Jansen3469e991996-09-06 00:30:45 +0000885 short item;
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000886 short fontID;
Jack Jansen3469e991996-09-06 00:30:45 +0000887
888 if( (theDialog = GetNewDialog(ABOUT_ID, NULL, (WindowPtr)-1)) == NULL )
889 return;
Jack Jansend617c571996-09-22 22:14:30 +0000890 theWindow = GetDialogWindow(theDialog);
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000891 SetPortWindowPort(theWindow);
892 GetFNum("\pPython-Sans", &fontID);
893 if (fontID == 0)
894 fontID = kFontIDGeneva;
895 TextFont(fontID);
896 TextSize(9);
897 ParamText(Pstring(PATCHLEVEL), "\p", "\p", "\p");
Jack Jansend617c571996-09-22 22:14:30 +0000898 ShowWindow(theWindow);
Jack Jansen3469e991996-09-06 00:30:45 +0000899 ModalDialog(NULL, &item);
900 DisposeDialog(theDialog);
901}
902
Jack Jansen0194ad52001-05-12 22:46:35 +0000903#endif /* !TARGET_API_MAC_OSX */
Jack Janseneda78631997-06-12 15:29:46 +0000904
Jack Jansen0194ad52001-05-12 22:46:35 +0000905#if TARGET_API_MAC_OS8
Jack Janseneda78631997-06-12 15:29:46 +0000906/*
Jack Jansen3ec804a1995-02-20 15:56:10 +0000907** Helper routine for GetDirectory
908*/
Guido van Rossum24a45e31995-02-20 23:45:53 +0000909static pascal short
Jack Jansen819f1771995-08-14 12:35:10 +0000910myhook_proc(short item, DialogPtr theDialog, struct hook_args *dataptr)
Jack Jansen3ec804a1995-02-20 15:56:10 +0000911{
Jack Jansen819f1771995-08-14 12:35:10 +0000912 if ( item == sfHookFirstCall && dataptr->prompt) {
913 Handle prompth;
914 short type;
915 Rect rect;
916
917 GetDialogItem(theDialog, PROMPT_ITEM, &type, &prompth, &rect);
918 if ( prompth )
919 SetDialogItemText(prompth, (unsigned char *)dataptr->prompt);
920 } else
Jack Jansen3ec804a1995-02-20 15:56:10 +0000921 if ( item == SELECTCUR_ITEM ) {
922 item = sfItemCancelButton;
Jack Jansen819f1771995-08-14 12:35:10 +0000923 dataptr->selectcur_hit = 1;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000924 }
925 return item;
926}
Jack Jansen0194ad52001-05-12 22:46:35 +0000927
Jack Jansen3ec804a1995-02-20 15:56:10 +0000928/*
929** Ask the user for a directory. I still can't understand
930** why Apple doesn't provide a standard solution for this...
931*/
932int
Jack Jansen819f1771995-08-14 12:35:10 +0000933PyMac_GetDirectory(dirfss, prompt)
Jack Jansen3ec804a1995-02-20 15:56:10 +0000934 FSSpec *dirfss;
Jack Jansen819f1771995-08-14 12:35:10 +0000935 char *prompt;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000936{
937 static SFTypeList list = {'fldr', 0, 0, 0};
938 static Point where = {-1, -1};
Jack Jansen3ec804a1995-02-20 15:56:10 +0000939 StandardFileReply reply;
Jack Jansen819f1771995-08-14 12:35:10 +0000940 struct hook_args hook_args;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000941
942 if ( !upp_inited ) {
943 myhook_upp = NewDlgHookYDProc(myhook_proc);
944 upp_inited = 1;
945 }
Jack Jansen819f1771995-08-14 12:35:10 +0000946 if ( prompt && *prompt )
947 hook_args.prompt = (char *)Pstring(prompt);
948 else
949 hook_args.prompt = NULL;
950 hook_args.selectcur_hit = 0;
Guido van Rossum24a45e31995-02-20 23:45:53 +0000951 CustomGetFile((FileFilterYDUPP)0, 1, list, &reply, GETDIR_ID, where, myhook_upp,
Jack Jansen819f1771995-08-14 12:35:10 +0000952 NULL, NULL, NULL, (void *)&hook_args);
Jack Jansen3ec804a1995-02-20 15:56:10 +0000953
954 reply.sfFile.name[0] = 0;
955 if( FSMakeFSSpec(reply.sfFile.vRefNum, reply.sfFile.parID, reply.sfFile.name, dirfss) )
956 return 0;
Jack Jansen819f1771995-08-14 12:35:10 +0000957 return hook_args.selectcur_hit;
958}
959
960/*
961** Slightly extended StandardGetFile: accepts a prompt */
962void PyMac_PromptGetFile(short numTypes, ConstSFTypeListPtr typeList,
963 StandardFileReply *reply, char *prompt)
964{
965 static Point where = {-1, -1};
966 struct hook_args hook_args;
967
968 if ( !upp_inited ) {
969 myhook_upp = NewDlgHookYDProc(myhook_proc);
970 upp_inited = 1;
971 }
972 if ( prompt && *prompt )
973 hook_args.prompt = (char *)Pstring(prompt);
974 else
975 hook_args.prompt = NULL;
976 hook_args.selectcur_hit = 0;
977 CustomGetFile((FileFilterYDUPP)0, numTypes, typeList, reply, GETFILEPROMPT_ID, where,
978 myhook_upp, NULL, NULL, NULL, (void *)&hook_args);
Jack Jansen3ec804a1995-02-20 15:56:10 +0000979}
Jack Jansen6e68a7e2001-05-12 21:31:34 +0000980#endif /* TARGET_API_MAC_OS8 */
Jack Jansen5f653091995-01-18 13:53:49 +0000981
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000982/* Convert a 4-char string object argument to an OSType value */
Jack Jansen5f653091995-01-18 13:53:49 +0000983int
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000984PyMac_GetOSType(PyObject *v, OSType *pr)
Jack Jansen5f653091995-01-18 13:53:49 +0000985{
986 if (!PyString_Check(v) || PyString_Size(v) != 4) {
987 PyErr_SetString(PyExc_TypeError,
988 "OSType arg must be string of 4 chars");
989 return 0;
990 }
991 memcpy((char *)pr, PyString_AsString(v), 4);
992 return 1;
993}
994
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000995/* Convert an OSType value to a 4-char string object */
996PyObject *
997PyMac_BuildOSType(OSType t)
998{
999 return PyString_FromStringAndSize((char *)&t, 4);
1000}
1001
Jack Jansend1f06311996-08-01 15:23:54 +00001002/* Convert an NumVersion value to a 4-element tuple */
1003PyObject *
1004PyMac_BuildNumVersion(NumVersion t)
1005{
1006 return Py_BuildValue("(hhhh)", t.majorRev, t.minorAndBugRev, t.stage, t.nonRelRev);
1007}
1008
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001009
1010/* Convert a Python string object to a Str255 */
Jack Jansen5f653091995-01-18 13:53:49 +00001011int
Guido van Rossum8f691791995-01-18 23:57:26 +00001012PyMac_GetStr255(PyObject *v, Str255 pbuf)
Jack Jansen5f653091995-01-18 13:53:49 +00001013{
1014 int len;
1015 if (!PyString_Check(v) || (len = PyString_Size(v)) > 255) {
1016 PyErr_SetString(PyExc_TypeError,
1017 "Str255 arg must be string of at most 255 chars");
1018 return 0;
1019 }
1020 pbuf[0] = len;
1021 memcpy((char *)(pbuf+1), PyString_AsString(v), len);
1022 return 1;
1023}
1024
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001025/* Convert a Str255 to a Python string object */
1026PyObject *
1027PyMac_BuildStr255(Str255 s)
1028{
Jack Jansenb734ade1999-12-17 17:15:50 +00001029 if ( s == NULL ) {
1030 PyErr_SetString(PyExc_SystemError, "Str255 pointer is NULL");
1031 return NULL;
1032 }
1033 return PyString_FromStringAndSize((char *)&s[1], (int)s[0]);
1034}
1035
1036PyObject *
1037PyMac_BuildOptStr255(Str255 s)
1038{
1039 if ( s == NULL ) {
1040 Py_INCREF(Py_None);
1041 return Py_None;
1042 }
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001043 return PyString_FromStringAndSize((char *)&s[1], (int)s[0]);
1044}
1045
1046
Jack Jansen5f653091995-01-18 13:53:49 +00001047/*
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001048** Convert a Python object to an FSSpec.
1049** The object may either be a full pathname or a triple
1050** (vrefnum, dirid, path).
Jack Jansen5f653091995-01-18 13:53:49 +00001051** NOTE: This routine will fail on pre-sys7 machines.
1052** The caller is responsible for not calling this routine
1053** in those cases (which is fine, since everyone calling
1054** this is probably sys7 dependent anyway).
1055*/
1056int
Guido van Rossum8f691791995-01-18 23:57:26 +00001057PyMac_GetFSSpec(PyObject *v, FSSpec *fs)
Jack Jansen5f653091995-01-18 13:53:49 +00001058{
1059 Str255 path;
1060 short refnum;
1061 long parid;
1062 OSErr err;
Jack Jansene8e8ae01995-01-26 16:36:45 +00001063 FSSpec *fs2;
Jack Jansen5f653091995-01-18 13:53:49 +00001064
Jack Jansen0194ad52001-05-12 22:46:35 +00001065#if !TARGET_API_MAC_OSX
1066 /* XXX This #if is temporary */
Jack Jansene8e8ae01995-01-26 16:36:45 +00001067 /* first check whether it already is an FSSpec */
1068 fs2 = mfs_GetFSSpecFSSpec(v);
1069 if ( fs2 ) {
Jack Jansen3ec804a1995-02-20 15:56:10 +00001070 (void)FSMakeFSSpec(fs2->vRefNum, fs2->parID, fs2->name, fs);
Jack Jansene8e8ae01995-01-26 16:36:45 +00001071 return 1;
1072 }
Jack Jansen0194ad52001-05-12 22:46:35 +00001073#endif
Jack Jansen5f653091995-01-18 13:53:49 +00001074 if ( PyString_Check(v) ) {
1075 /* It's a pathname */
Guido van Rossum9aa3d131995-01-21 13:46:04 +00001076 if( !PyArg_Parse(v, "O&", PyMac_GetStr255, &path) )
Jack Jansen5f653091995-01-18 13:53:49 +00001077 return 0;
Jack Jansen378815c1996-03-06 16:21:34 +00001078 refnum = 0; /* XXXX Should get CurWD here?? */
Jack Jansen5f653091995-01-18 13:53:49 +00001079 parid = 0;
1080 } else {
Guido van Rossum9aa3d131995-01-21 13:46:04 +00001081 if( !PyArg_Parse(v, "(hlO&); FSSpec should be fullpath or (vrefnum,dirid,path)",
1082 &refnum, &parid, PyMac_GetStr255, &path)) {
Jack Jansen5f653091995-01-18 13:53:49 +00001083 return 0;
Guido van Rossum9aa3d131995-01-21 13:46:04 +00001084 }
Jack Jansen5f653091995-01-18 13:53:49 +00001085 }
1086 err = FSMakeFSSpec(refnum, parid, path, fs);
1087 if ( err && err != fnfErr ) {
Jack Jansen3d757542000-01-24 09:56:06 +00001088 PyMac_Error(err);
Jack Jansen5f653091995-01-18 13:53:49 +00001089 return 0;
1090 }
1091 return 1;
1092}
1093
Jack Jansen8bb573e1999-12-12 21:37:14 +00001094/* Convert FSSpec to PyObject */
1095PyObject *PyMac_BuildFSSpec(FSSpec *v)
1096{
Jack Jansen0194ad52001-05-12 22:46:35 +00001097#if TARGET_API_MAC_OSX
1098 PyErr_SetString(PyExc_NotImplementedError, "FSSpec not yet done for OSX");
1099 return NULL;
1100#else
Jack Jansen8bb573e1999-12-12 21:37:14 +00001101 return newmfssobject(v);
Jack Jansen0194ad52001-05-12 22:46:35 +00001102#endif
Jack Jansen8bb573e1999-12-12 21:37:14 +00001103}
Guido van Rossum8f691791995-01-18 23:57:26 +00001104
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001105/* Convert a Python object to a Rect.
Guido van Rossum5279ec61995-01-26 22:56:59 +00001106 The object must be a (left, top, right, bottom) tuple.
1107 (This differs from the order in the struct but is consistent with
1108 the arguments to SetRect(), and also with STDWIN). */
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001109int
1110PyMac_GetRect(PyObject *v, Rect *r)
Guido van Rossum8f691791995-01-18 23:57:26 +00001111{
Guido van Rossum5279ec61995-01-26 22:56:59 +00001112 return PyArg_Parse(v, "(hhhh)", &r->left, &r->top, &r->right, &r->bottom);
Guido van Rossum8f691791995-01-18 23:57:26 +00001113}
Guido van Rossumb3404661995-01-22 18:36:13 +00001114
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001115/* Convert a Rect to a Python object */
Guido van Rossumb3404661995-01-22 18:36:13 +00001116PyObject *
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001117PyMac_BuildRect(Rect *r)
Guido van Rossumb3404661995-01-22 18:36:13 +00001118{
Guido van Rossum5279ec61995-01-26 22:56:59 +00001119 return Py_BuildValue("(hhhh)", r->left, r->top, r->right, r->bottom);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001120}
1121
1122
1123/* Convert a Python object to a Point.
Guido van Rossum5279ec61995-01-26 22:56:59 +00001124 The object must be a (h, v) tuple.
1125 (This differs from the order in the struct but is consistent with
1126 the arguments to SetPoint(), and also with STDWIN). */
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001127int
1128PyMac_GetPoint(PyObject *v, Point *p)
1129{
Guido van Rossum5279ec61995-01-26 22:56:59 +00001130 return PyArg_Parse(v, "(hh)", &p->h, &p->v);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001131}
1132
1133/* Convert a Point to a Python object */
1134PyObject *
1135PyMac_BuildPoint(Point p)
1136{
Guido van Rossum5279ec61995-01-26 22:56:59 +00001137 return Py_BuildValue("(hh)", p.h, p.v);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001138}
1139
1140
1141/* Convert a Python object to an EventRecord.
1142 The object must be a (what, message, when, (v, h), modifiers) tuple. */
1143int
1144PyMac_GetEventRecord(PyObject *v, EventRecord *e)
1145{
1146 return PyArg_Parse(v, "(hll(hh)h)",
1147 &e->what,
1148 &e->message,
1149 &e->when,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001150 &e->where.h,
Guido van Rossum5279ec61995-01-26 22:56:59 +00001151 &e->where.v,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001152 &e->modifiers);
1153}
1154
1155/* Convert a Rect to an EventRecord object */
1156PyObject *
1157PyMac_BuildEventRecord(EventRecord *e)
1158{
1159 return Py_BuildValue("(hll(hh)h)",
1160 e->what,
1161 e->message,
1162 e->when,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001163 e->where.h,
Guido van Rossum5279ec61995-01-26 22:56:59 +00001164 e->where.v,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001165 e->modifiers);
Guido van Rossumb3404661995-01-22 18:36:13 +00001166}
Jack Jansenfa4d5d01995-11-15 15:19:29 +00001167
1168/* Convert Python object to Fixed */
1169int
1170PyMac_GetFixed(PyObject *v, Fixed *f)
1171{
1172 double d;
1173
1174 if( !PyArg_Parse(v, "d", &d))
1175 return 0;
1176 *f = (Fixed)(d * 0x10000);
Jack Jansen31dd5c01996-05-31 13:01:39 +00001177 return 1;
Jack Jansenfa4d5d01995-11-15 15:19:29 +00001178}
1179
1180/* Convert a Point to a Python object */
1181PyObject *
1182PyMac_BuildFixed(Fixed f)
1183{
1184 double d;
1185
1186 d = f;
1187 d = d / 0x10000;
1188 return Py_BuildValue("d", d);
1189}
1190
Jack Jansend58cd631998-04-21 15:24:39 +00001191/* Convert wide to/from Python int or (hi, lo) tuple. XXXX Should use Python longs */
1192int
1193PyMac_Getwide(PyObject *v, wide *rv)
1194{
1195 if (PyInt_Check(v)) {
1196 rv->hi = 0;
1197 rv->lo = PyInt_AsLong(v);
1198 if( rv->lo & 0x80000000 )
1199 rv->hi = -1;
1200 return 1;
1201 }
1202 return PyArg_Parse(v, "(ll)", &rv->hi, &rv->lo);
1203}
1204
1205
1206PyObject *
Jack Jansenbbf4be21998-04-23 13:20:17 +00001207PyMac_Buildwide(wide *w)
Jack Jansend58cd631998-04-21 15:24:39 +00001208{
Jack Jansenbbf4be21998-04-23 13:20:17 +00001209 if ( (w->hi == 0 && (w->lo & 0x80000000) == 0) ||
1210 (w->hi == -1 && (w->lo & 0x80000000) ) )
1211 return PyInt_FromLong(w->lo);
1212 return Py_BuildValue("(ll)", w->hi, w->lo);
Jack Jansend58cd631998-04-21 15:24:39 +00001213}
Jack Jansen8bb1dc12001-05-19 12:31:09 +00001214
1215#ifdef USE_TOOLBOX_OBJECT_GLUE
1216/*
1217** Glue together the toolbox objects.
1218**
1219** Because toolbox modules interdepend on each other, they use each others
1220** object types, on MacOSX/MachO this leads to the situation that they
1221** cannot be dynamically loaded (or they would all have to be lumped into
1222** a single .so, but this would be bad for extensibility).
1223**
1224** This file defines wrappers for all the _New and _Convert functions,
1225** which are the Py_BuildValue and PyArg_ParseTuple helpers. The wrappers
1226** check an indirection function pointer, and if it isn't filled in yet
1227** they import the appropriate module, whose init routine should fill in
1228** the pointer.
1229*/
1230
1231#define GLUE_NEW(object, routinename, module) \
1232PyObject *(*PyMacGluePtr_##routinename)(object); \
1233\
1234PyObject *routinename(object cobj) { \
1235 if (!PyMacGluePtr_##routinename) { \
1236 if (!PyImport_ImportModule(module)) return NULL; \
1237 if (!PyMacGluePtr_##routinename) { \
1238 PyErr_SetString(PyExc_ImportError, "Module did not provide routine: " module ": " #routinename); \
1239 return NULL; \
1240 } \
1241 } \
1242 return (*PyMacGluePtr_##routinename)(cobj); \
1243}
1244
1245#define GLUE_CONVERT(object, routinename, module) \
1246int (*PyMacGluePtr_##routinename)(PyObject *, object *); \
1247\
1248int routinename(PyObject *pyobj, object *cobj) { \
1249 if (!PyMacGluePtr_##routinename) { \
1250 if (!PyImport_ImportModule(module)) return NULL; \
1251 if (!PyMacGluePtr_##routinename) { \
1252 PyErr_SetString(PyExc_ImportError, "Module did not provide routine: " module ": " #routinename); \
1253 return NULL; \
1254 } \
1255 } \
1256 return (*PyMacGluePtr_##routinename)(pyobj, cobj); \
1257}
1258
1259GLUE_NEW(AppleEvent *, AEDesc_New, "AE") /* XXXX Why by address? */
1260GLUE_CONVERT(AppleEvent, AEDesc_Convert, "AE")
1261
1262GLUE_NEW(Component, CmpObj_New, "Cm")
1263GLUE_CONVERT(Component, CmpObj_Convert, "Cm")
1264GLUE_NEW(ComponentInstance, CmpInstObj_New, "Cm")
1265GLUE_CONVERT(ComponentInstance, CmpInstObj_Convert, "Cm")
1266
1267GLUE_NEW(ControlHandle, CtlObj_New, "Ctl")
1268GLUE_CONVERT(ControlHandle, CtlObj_Convert, "Ctl")
1269
1270GLUE_NEW(DialogPtr, DlgObj_New, "Dlg")
1271GLUE_CONVERT(DialogPtr, DlgObj_Convert, "Dlg")
1272GLUE_NEW(DialogPtr, DlgObj_WhichDialog, "Dlg")
1273
1274GLUE_NEW(DragReference, DragObj_New, "Drag")
1275GLUE_CONVERT(DragReference, DragObj_Convert, "Drag")
1276
1277GLUE_NEW(ListHandle, ListObj_New, "List")
1278GLUE_CONVERT(ListHandle, ListObj_Convert, "List")
1279
1280GLUE_NEW(MenuHandle, MenuObj_New, "Menu")
1281GLUE_CONVERT(MenuHandle, MenuObj_Convert, "Menu")
1282
1283GLUE_NEW(GrafPtr, GrafObj_New, "Qd")
1284GLUE_CONVERT(GrafPtr, GrafObj_Convert, "Qd")
1285GLUE_NEW(BitMapPtr, BMObj_New, "Qd")
1286GLUE_CONVERT(BitMapPtr, BMObj_Convert, "Qd")
1287GLUE_NEW(RGBColor *, QdRGB_New, "Qd") /* XXXX Why? */
1288GLUE_CONVERT(RGBColor, QdRGB_Convert, "Qd")
1289
1290GLUE_NEW(GWorldPtr, GWorldObj_New, "Qdoffs")
1291GLUE_CONVERT(GWorldPtr, GWorldObj_Convert, "Qdoffs")
1292
1293GLUE_NEW(Track, TrackObj_New, "Qt")
1294GLUE_CONVERT(Track, TrackObj_Convert, "Qt")
1295GLUE_NEW(Movie, MovieObj_New, "Qt")
1296GLUE_CONVERT(Movie, MovieObj_Convert, "Qt")
1297GLUE_NEW(MovieController, MovieCtlObj_New, "Qt")
1298GLUE_CONVERT(MovieController, MovieCtlObj_Convert, "Qt")
1299GLUE_NEW(TimeBase, TimeBaseObj_New, "Qt")
1300GLUE_CONVERT(TimeBase, TimeBaseObj_Convert, "Qt")
1301GLUE_NEW(UserData, UserDataObj_New, "Qt")
1302GLUE_CONVERT(UserData, UserDataObj_Convert, "Qt")
1303GLUE_NEW(Media, MediaObj_New, "Qt")
1304GLUE_CONVERT(Media, MediaObj_Convert, "Qt")
1305
1306GLUE_NEW(Handle, ResObj_New, "Res")
1307GLUE_CONVERT(Handle, ResObj_Convert, "Res")
1308GLUE_NEW(Handle, OptResObj_New, "Res")
1309GLUE_CONVERT(Handle, OptResObj_Convert, "Res")
1310
1311GLUE_NEW(TEHandle, TEObj_New, "TE")
1312GLUE_CONVERT(TEHandle, TEObj_Convert, "TE")
1313
1314GLUE_NEW(WindowPtr, WinObj_New, "Win")
1315GLUE_CONVERT(WindowPtr, WinObj_Convert, "Win")
1316GLUE_NEW(WindowPtr, WinObj_WhichWindow, "Win")
1317
1318#endif /* USE_TOOLBOX_OBJECT_GLUE */