blob: 9c21ed20abffcb345d1c1d6680e290f54c6694e4 [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 Jansenee23d6e1995-01-27 14:43:25 +0000133/* Interrupt code variables: */
134static int interrupted; /* Set to true when cmd-. seen */
Jack Jansend88296d2000-07-11 19:51:05 +0000135static RETSIGTYPE intcatcher(int);
Jack Jansenee23d6e1995-01-27 14:43:25 +0000136
Jack Jansen0194ad52001-05-12 22:46:35 +0000137#if !TARGET_API_MAC_OSX
Jack Jansend88296d2000-07-11 19:51:05 +0000138static int PyMac_Yield(void);
Jack Jansen0194ad52001-05-12 22:46:35 +0000139#endif
Jack Jansenf6865f71996-09-04 15:24:59 +0000140
Jack Jansene8e8ae01995-01-26 16:36:45 +0000141/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000142** These are the real scheduling parameters that control what we check
143** in the event loop, and how often we check. The values are initialized
144** from pyMac_SchedParamStruct.
145*/
146
147struct real_sched_param_struct {
148 int check_interrupt; /* if true check for command-dot */
149 int process_events; /* if nonzero enable evt processing, this mask */
150 int besocial; /* if nonzero be a little social with CPU */
151 unsigned long check_interval; /* how often to check, in ticks */
152 unsigned long bg_yield; /* yield so long when in background */
153 /* these are computed from previous and clock and such */
154 int enabled; /* check_interrupt OR process_event OR yield */
155 unsigned long next_check; /* when to check/yield next, in ticks */
156};
157
158static struct real_sched_param_struct schedparams =
159 { 1, MAINLOOP_EVENTMASK, 1, 15, 15, 1, 0};
160
Jack Jansen819f1771995-08-14 12:35:10 +0000161/*
Jack Jansenf6865f71996-09-04 15:24:59 +0000162** Workaround for sioux/gusi combo: set when we are exiting
163*/
164int PyMac_ConsoleIsDead;
165
166/*
Jack Jansencaa7c461997-06-12 10:49:13 +0000167** Sioux menu bar, saved early so we can restore it
168*/
Jack Jansen657ba272001-02-17 22:02:07 +0000169static MenuBarHandle sioux_mbar;
Jack Jansencaa7c461997-06-12 10:49:13 +0000170
171/*
Jack Jansen819f1771995-08-14 12:35:10 +0000172** Some stuff for our GetDirectory and PromptGetFile routines
173*/
174struct hook_args {
175 int selectcur_hit; /* Set to true when "select current" selected */
176 char *prompt; /* The prompt */
177};
Jack Jansen6e68a7e2001-05-12 21:31:34 +0000178#if !TARGET_API_MAC_OS8
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000179/* The StandardFile hooks don't exist in Carbon. This breaks GetDirectory,
180** but the macfsn code will replace it by a NavServices version anyway.
181*/
182#define myhook_upp NULL
183#else
Jack Jansen819f1771995-08-14 12:35:10 +0000184static DlgHookYDUPP myhook_upp;
185static int upp_inited = 0;
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000186#endif
Jack Jansen819f1771995-08-14 12:35:10 +0000187
Jack Jansen36ed5061997-06-20 16:18:15 +0000188/*
189** The python-code event handler
190*/
191static PyObject *python_event_handler;
192
Jack Jansen8f5725a1999-12-07 23:08:10 +0000193/*
194** Set to true if we're appearance-compliant
195*/
196int PyMac_AppearanceCompliant;
197
Jack Jansen1f9f2f42000-07-24 19:50:16 +0000198/*
199** Find out what the current script is.
200** Donated by Fredrik Lund.
201*/
202char *PyMac_getscript()
203{
204 int font, script, lang;
205 font = 0;
206 font = GetSysFont();
207 script = FontToScript(font);
208 switch (script) {
209 case smRoman:
210 lang = GetScriptVariable(script, smScriptLang);
211 if (lang == langIcelandic)
212 return "mac-iceland";
213 else if (lang == langTurkish)
214 return "mac-turkish";
215 else if (lang == langGreek)
216 return "mac-greek";
217 else
218 return "mac-roman";
219 break;
unknownf428aef2001-07-04 22:36:27 +0000220#if 0
221 /* We don't have a codec for this, so don't return it */
Jack Jansen1f9f2f42000-07-24 19:50:16 +0000222 case smJapanese:
223 return "mac-japan";
unknownf428aef2001-07-04 22:36:27 +0000224#endif
Jack Jansen1f9f2f42000-07-24 19:50:16 +0000225 case smGreek:
226 return "mac-greek";
227 case smCyrillic:
228 return "mac-cyrillic";
229 default:
230 return "mac-roman"; /* better than nothing */
231 }
232}
233
Jack Jansen741e0372001-05-19 12:55:57 +0000234/* Given an FSSpec, return the FSSpec of the parent folder */
235
236static OSErr
237get_folder_parent (FSSpec * fss, FSSpec * parent)
238{
239 CInfoPBRec rec;
240 short err;
241
242 * parent = * fss;
243 rec.hFileInfo.ioNamePtr = parent->name;
244 rec.hFileInfo.ioVRefNum = parent->vRefNum;
245 rec.hFileInfo.ioDirID = parent->parID;
246 rec.hFileInfo.ioFDirIndex = -1;
247 rec.hFileInfo.ioFVersNum = 0;
248 if (err = PBGetCatInfoSync (& rec))
249 return err;
250 parent->parID = rec.dirInfo.ioDrParID;
251/* parent->name[0] = 0; */
252 return 0;
253}
254
255/* Given an FSSpec return a full, colon-separated pathname */
256
257OSErr
258PyMac_GetFullPath (FSSpec *fss, char *buf)
259{
260 short err;
261 FSSpec fss_parent, fss_current;
262 char tmpbuf[1024];
263 int plen;
264
265 fss_current = *fss;
266 plen = fss_current.name[0];
267 memcpy(buf, &fss_current.name[1], plen);
268 buf[plen] = 0;
269 /* Special case for disk names */
270 if ( fss_current.parID <= 1 ) {
271 buf[plen++] = ':';
272 buf[plen] = 0;
273 return 0;
274 }
275 while (fss_current.parID > 1) {
276 /* Get parent folder name */
277 if (err = get_folder_parent(&fss_current, &fss_parent))
278 return err;
279 fss_current = fss_parent;
280 /* Prepend path component just found to buf */
281 plen = fss_current.name[0];
282 if (strlen(buf) + plen + 1 > 1024) {
283 /* Oops... Not enough space (shouldn't happen) */
284 *buf = 0;
285 return -1;
286 }
287 memcpy(tmpbuf, &fss_current.name[1], plen);
288 tmpbuf[plen] = ':';
289 strcpy(&tmpbuf[plen+1], buf);
290 strcpy(buf, tmpbuf);
291 }
292 return 0;
293}
Jack Jansen1f9f2f42000-07-24 19:50:16 +0000294
Jack Jansen2d1306b2000-04-07 09:10:49 +0000295#ifdef USE_GUSI1
Jack Jansen378815c1996-03-06 16:21:34 +0000296/*
297** GUSI (1.6.0 and earlier, at the least) do not set the MacOS idea of
298** the working directory. Hence, we call this routine after each call
299** to chdir() to rectify things.
300*/
301void
302PyMac_FixGUSIcd()
303{
304 WDPBRec pb;
305 FSSpec curdirfss;
306
307 if ( Path2FSSpec(":x", &curdirfss) != noErr )
308 return;
309
310 /* Set MacOS "working directory" */
311 pb.ioNamePtr= "\p";
312 pb.ioVRefNum= curdirfss.vRefNum;
313 pb.ioWDDirID= curdirfss.parID;
Jack Jansen08c3be31997-04-08 15:27:00 +0000314 if (PBHSetVolSync(&pb) != noErr)
Jack Jansen378815c1996-03-06 16:21:34 +0000315 return;
Jack Jansen378815c1996-03-06 16:21:34 +0000316}
Jack Jansen2d1306b2000-04-07 09:10:49 +0000317#endif
Jack Jansen7ac70af1996-08-19 11:01:05 +0000318
Jack Jansen2d1306b2000-04-07 09:10:49 +0000319#ifdef USE_GUSI
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000320/*
321** SpinCursor (needed by GUSI) drags in heaps of stuff, so we
322** provide a dummy here.
323*/
Jack Jansencfadbd41996-08-19 11:36:25 +0000324void SpinCursor(short x) { /* Dummy */ }
Jack Jansenefaada71998-02-20 16:03:15 +0000325void RotateCursor(short x) { /* Dummy */ }
Jack Jansencfadbd41996-08-19 11:36:25 +0000326
Jack Jansenf6865f71996-09-04 15:24:59 +0000327/*
328** Replacement GUSI Spin function
329*/
Jack Jansen2d1306b2000-04-07 09:10:49 +0000330#ifdef USE_GUSI1
Jack Jansenf6865f71996-09-04 15:24:59 +0000331static int
332PyMac_GUSISpin(spin_msg msg, long arg)
333{
Jack Jansene3ae0df1997-06-03 15:28:29 +0000334 static Boolean inForeground = true;
335 int maxsleep = 6; /* 6 ticks is "normal" sleeptime */
Jack Jansenf6865f71996-09-04 15:24:59 +0000336
337 if (PyMac_ConsoleIsDead) return 0;
338#if 0
339 if (inForeground)
340 SpinCursor(msg == SP_AUTO_SPIN ? short(arg) : 1);
341#endif
342
343 if (interrupted) return -1;
344
Jack Jansene3ae0df1997-06-03 15:28:29 +0000345 if ( msg == SP_AUTO_SPIN )
346 maxsleep = 0;
347 if ( msg==SP_SLEEP||msg==SP_SELECT )
348 maxsleep = arg;
Jack Jansenf6865f71996-09-04 15:24:59 +0000349
Jack Jansene3ae0df1997-06-03 15:28:29 +0000350 PyMac_DoYield(maxsleep, 0); /* XXXX or is it safe to call python here? */
Jack Jansenf6865f71996-09-04 15:24:59 +0000351
352 return 0;
353}
354
355void
356PyMac_SetGUSISpin() {
357 GUSISetHook(GUSI_SpinHook, (GUSIHook)PyMac_GUSISpin);
358}
Jack Jansen2d1306b2000-04-07 09:10:49 +0000359#endif
Jack Jansenf6865f71996-09-04 15:24:59 +0000360
Jack Jansena39f1b01997-05-23 15:35:14 +0000361/* Called at exit() time thru atexit(), to stop event processing */
362void
363PyMac_StopGUSISpin() {
364 PyMac_ConsoleIsDead = 1;
365}
366
Jack Jansen6e68a7e2001-05-12 21:31:34 +0000367#if TARGET_API_MAC_OS8
Jack Jansena39f1b01997-05-23 15:35:14 +0000368/*
369** Replacement routines for the PLstr... functions so we don't need
Jack Jansen6ba34aa2001-01-11 23:03:56 +0000370** StdCLib.
Jack Jansena39f1b01997-05-23 15:35:14 +0000371*/
Jack Jansen8bb573e1999-12-12 21:37:14 +0000372pascal void
Jack Jansen9ae898b2000-07-11 21:16:03 +0000373PLstrcpy(unsigned char *to, unsigned char *fr)
Jack Jansena39f1b01997-05-23 15:35:14 +0000374{
375 memcpy(to, fr, fr[0]+1);
376}
377
Jack Jansen8bb573e1999-12-12 21:37:14 +0000378pascal int
Jack Jansen9ae898b2000-07-11 21:16:03 +0000379PLstrcmp(unsigned char *s1, unsigned char *s2)
Jack Jansena39f1b01997-05-23 15:35:14 +0000380{
381 int res;
382 int l = s1[0] < s2[0] ? s1[0] : s2[0];
383
384 res = memcmp(s1+1, s2+1, l);
385 if ( res != 0 )
386 return res;
387
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000388 if ( s1[0] < s2[0] )
Jack Jansena39f1b01997-05-23 15:35:14 +0000389 return -1;
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000390 else if ( s1[0] > s2[0] )
Jack Jansena39f1b01997-05-23 15:35:14 +0000391 return 1;
392 else
393 return 0;
394}
395
Jack Jansen8bb573e1999-12-12 21:37:14 +0000396pascal unsigned char *
Jack Jansen9ae898b2000-07-11 21:16:03 +0000397PLstrrchr(unsigned char *str, unsigned char chr)
Jack Jansena39f1b01997-05-23 15:35:14 +0000398{
399 unsigned char *ptr = 0;
400 unsigned char *p;
401
402 for(p=str+1; p<str+str[0]; p++)
403 if ( *p == chr )
404 ptr = p;
405 return ptr;
406}
407
Jack Jansen6e68a7e2001-05-12 21:31:34 +0000408#endif /* TARGET_API_MAC_OS8 */
Jack Jansena39f1b01997-05-23 15:35:14 +0000409#endif /* USE_GUSI */
Jack Jansen378815c1996-03-06 16:21:34 +0000410
Jack Jansen819f1771995-08-14 12:35:10 +0000411
Jack Jansen5f653091995-01-18 13:53:49 +0000412/* Convert C to Pascal string. Returns pointer to static buffer. */
413unsigned char *
414Pstring(char *str)
415{
416 static Str255 buf;
417 int len;
418
419 len = strlen(str);
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000420 if (len > 255)
421 len = 255;
Jack Jansen5f653091995-01-18 13:53:49 +0000422 buf[0] = (unsigned char)len;
423 strncpy((char *)buf+1, str, len);
424 return buf;
425}
426
Jack Jansen6e68a7e2001-05-12 21:31:34 +0000427#if TARGET_API_MAC_OS8
Jack Jansen5afad832000-12-12 22:12:14 +0000428void
429c2pstrcpy(unsigned char *dst, const char *src)
430{
431 int len;
432
433 len = strlen(src);
434 if ( len > 255 ) len = 255;
435 strncpy((char *)dst+1, src, len);
436 dst[0] = len;
437}
Jack Jansen6e68a7e2001-05-12 21:31:34 +0000438#endif /* TARGET_API_MAC_OS8 */
Jack Jansen5afad832000-12-12 22:12:14 +0000439
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000440/* Like strerror() but for Mac OS error numbers */
441char *PyMac_StrError(int err)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000442{
443 static char buf[256];
444 Handle h;
445 char *str;
446
447 h = GetResource('Estr', err);
448 if ( h ) {
449 HLock(h);
450 str = (char *)*h;
451 memcpy(buf, str+1, (unsigned char)str[0]);
Guido van Rossumcc9bc8f1995-02-13 16:17:03 +0000452 buf[(unsigned char)str[0]] = '\0';
Jack Jansenf93c72a1994-12-14 14:07:50 +0000453 HUnlock(h);
454 ReleaseResource(h);
455 } else {
456 sprintf(buf, "Mac OS error code %d", err);
457 }
458 return buf;
459}
460
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000461/* Exception object shared by all Mac specific modules for Mac OS errors */
462PyObject *PyMac_OSErrException;
463
464/* Initialize and return PyMac_OSErrException */
465PyObject *
466PyMac_GetOSErrException()
467{
468 if (PyMac_OSErrException == NULL)
unknownf428aef2001-07-04 22:36:27 +0000469 PyMac_OSErrException = PyString_FromString("MacOS.Error");
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000470 return PyMac_OSErrException;
471}
472
Jack Jansenf93c72a1994-12-14 14:07:50 +0000473/* Set a MAC-specific error from errno, and return NULL; return None if no error */
474PyObject *
Guido van Rossumfffb8bb1995-01-12 12:37:24 +0000475PyErr_Mac(PyObject *eobj, int err)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000476{
477 char *msg;
478 PyObject *v;
Jack Jansenf93c72a1994-12-14 14:07:50 +0000479
Guido van Rossum8f691791995-01-18 23:57:26 +0000480 if (err == 0 && !PyErr_Occurred()) {
Jack Jansenf93c72a1994-12-14 14:07:50 +0000481 Py_INCREF(Py_None);
482 return Py_None;
483 }
Guido van Rossum8f691791995-01-18 23:57:26 +0000484 if (err == -1 && PyErr_Occurred())
485 return NULL;
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000486 msg = PyMac_StrError(err);
Jack Jansenf93c72a1994-12-14 14:07:50 +0000487 v = Py_BuildValue("(is)", err, msg);
488 PyErr_SetObject(eobj, v);
489 Py_DECREF(v);
490 return NULL;
491}
492
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000493/* Call PyErr_Mac with PyMac_OSErrException */
494PyObject *
495PyMac_Error(OSErr err)
496{
497 return PyErr_Mac(PyMac_GetOSErrException(), err);
498}
499
Jack Jansen1ed95291996-07-22 15:25:10 +0000500#ifdef USE_STACKCHECK
501/* Check for stack overflow */
502int
503PyOS_CheckStack()
504{
Jack Jansen14a91712000-08-25 21:57:23 +0000505 char here;
506 static char *sentinel = 0;
Jack Jansen53bafd92000-09-08 22:05:48 +0000507 static PyThreadState *thread_for_sentinel = 0;
Jack Jansen1ed95291996-07-22 15:25:10 +0000508
Jack Jansen340eb882001-02-02 22:40:28 +0000509 if ( sentinel == 0 ) {
510 unsigned long stackspace = StackSpace();
511
512#ifdef MAXIMUM_STACK_SIZE
513 /* See the comment at the definition */
514 if ( stackspace > MAXIMUM_STACK_SIZE )
515 stackspace = MAXIMUM_STACK_SIZE;
516#endif
517 sentinel = &here - stackspace + MINIMUM_STACK_SIZE;
Jack Jansen14a91712000-08-25 21:57:23 +0000518 }
Jack Jansen53bafd92000-09-08 22:05:48 +0000519 if ( thread_for_sentinel == 0 ) {
520 thread_for_sentinel = PyThreadState_Get();
521 }
522 if ( &here < sentinel ) {
523 if (thread_for_sentinel == PyThreadState_Get()) {
524 return -1;
525#if 0
526 } else {
527 /* Else we are unsure... */
528 fprintf(stderr, "Stackcheck in other thread (was %x now %x)\n", thread_for_sentinel,PyThreadState_Get());
529#endif
530 }
531 }
Jack Jansen1ed95291996-07-22 15:25:10 +0000532 return 0;
533}
534#endif /* USE_STACKCHECK */
535
Jack Jansen0194ad52001-05-12 22:46:35 +0000536#if !TARGET_API_MAC_OSX
Jack Jansenee23d6e1995-01-27 14:43:25 +0000537/* The catcher routine (which may not be used for all compilers) */
538static RETSIGTYPE
539intcatcher(sig)
540 int sig;
541{
542 interrupted = 1;
543 signal(SIGINT, intcatcher);
544}
545
546void
547PyOS_InitInterrupts()
548{
549 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
550 signal(SIGINT, intcatcher);
551}
552
Jack Jansena8441de1997-08-08 14:57:37 +0000553void
554PyOS_FiniInterrupts()
555{
556}
557
Jack Jansenee23d6e1995-01-27 14:43:25 +0000558/*
559** This routine scans the event queue looking for cmd-.
560** This is the only way to get an interrupt under THINK (since it
561** doesn't do SIGINT handling), but is also used under MW, when
562** the full-fledged event loop is disabled. This way, we can at least
563** interrupt a runaway python program.
564*/
565static void
566scan_event_queue(flush)
567 int flush;
568{
Jack Jansen6e68a7e2001-05-12 21:31:34 +0000569#if !TARGET_API_MAC_OS8
Jack Jansend7b68022001-01-12 23:42:28 +0000570 if ( CheckEventQueueForUserCancel() )
571 interrupted = 1;
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000572#else
Jack Jansenee23d6e1995-01-27 14:43:25 +0000573 register EvQElPtr q;
574
Jack Jansenefaada71998-02-20 16:03:15 +0000575 q = (EvQElPtr) LMGetEventQueue()->qHead;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000576
577 for (; q; q = (EvQElPtr)q->qLink) {
578 if (q->evtQWhat == keyDown &&
579 (char)q->evtQMessage == '.' &&
580 (q->evtQModifiers & cmdKey) != 0) {
581 if ( flush )
582 FlushEvents(keyDownMask, 0);
583 interrupted = 1;
584 break;
585 }
586 }
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000587#endif
Jack Jansenee23d6e1995-01-27 14:43:25 +0000588}
589
590int
Jack Jansen36ed5061997-06-20 16:18:15 +0000591PyErr_CheckSignals()
Jack Jansenee23d6e1995-01-27 14:43:25 +0000592{
Jack Jansene3ae0df1997-06-03 15:28:29 +0000593 if (schedparams.enabled) {
594 if ( (unsigned long)LMGetTicks() > schedparams.next_check ) {
Jack Jansen36ed5061997-06-20 16:18:15 +0000595 if ( PyMac_Yield() < 0)
596 return -1;
Jack Jansene3ae0df1997-06-03 15:28:29 +0000597 schedparams.next_check = (unsigned long)LMGetTicks()
598 + schedparams.check_interval;
599 if (interrupted) {
Jack Jansencaa7c461997-06-12 10:49:13 +0000600 scan_event_queue(1); /* Eat events up to cmd-. */
Jack Jansene3ae0df1997-06-03 15:28:29 +0000601 interrupted = 0;
Jack Jansen36ed5061997-06-20 16:18:15 +0000602 PyErr_SetNone(PyExc_KeyboardInterrupt);
603 return -1;
Jack Jansene3ae0df1997-06-03 15:28:29 +0000604 }
605 }
Jack Jansenee23d6e1995-01-27 14:43:25 +0000606 }
607 return 0;
608}
609
Jack Jansen36ed5061997-06-20 16:18:15 +0000610int
611PyOS_InterruptOccurred()
612{
613 scan_event_queue(1);
614 return interrupted;
615}
Jack Jansen0194ad52001-05-12 22:46:35 +0000616
Jack Jansenee23d6e1995-01-27 14:43:25 +0000617/* Check whether we are in the foreground */
Jack Jansen9ae898b2000-07-11 21:16:03 +0000618static int
619PyMac_InForeground(void)
Jack Jansenee23d6e1995-01-27 14:43:25 +0000620{
621 static ProcessSerialNumber ours;
622 static inited;
623 ProcessSerialNumber curfg;
624 Boolean eq;
625
Jack Jansene3ae0df1997-06-03 15:28:29 +0000626 if ( inited == 0 ) {
Jack Jansenee23d6e1995-01-27 14:43:25 +0000627 (void)GetCurrentProcess(&ours);
Jack Jansene3ae0df1997-06-03 15:28:29 +0000628 inited = 1;
629 }
Jack Jansenee23d6e1995-01-27 14:43:25 +0000630 if ( GetFrontProcess(&curfg) < 0 )
631 eq = 1;
632 else if ( SameProcess(&ours, &curfg, &eq) < 0 )
633 eq = 1;
634 return (int)eq;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000635}
Jack Jansen0194ad52001-05-12 22:46:35 +0000636#endif
Jack Jansenee23d6e1995-01-27 14:43:25 +0000637
Jack Jansen36ed5061997-06-20 16:18:15 +0000638int
639PyMac_SetEventHandler(PyObject *evh)
640{
641 if ( evh && python_event_handler ) {
642 PyErr_SetString(PyExc_RuntimeError, "Python event handler already set");
643 return 0;
644 }
645 if ( python_event_handler )
646 Py_DECREF(python_event_handler);
647 if ( evh )
648 Py_INCREF(evh);
649 python_event_handler = evh;
650 return 1;
651}
652
Jack Jansenf93c72a1994-12-14 14:07:50 +0000653/*
Jack Jansena76382a1995-02-02 14:25:56 +0000654** Handle an event, either one found in the mainloop eventhandler or
655** one passed back from the python program.
656*/
657void
Jack Jansen36ed5061997-06-20 16:18:15 +0000658PyMac_HandleEventIntern(evp)
Jack Jansena76382a1995-02-02 14:25:56 +0000659 EventRecord *evp;
660{
Jack Jansen6e68a7e2001-05-12 21:31:34 +0000661#if TARGET_API_MAC_OS8
Jack Jansen0c968871997-08-26 13:20:34 +0000662 if ( evp->what == mouseDown ) {
663 WindowPtr wp;
664
665 if ( FindWindow(evp->where, &wp) == inSysWindow ) {
666 SystemClick(evp, wp);
667 return;
668 }
669 }
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000670#endif
Jack Jansena76382a1995-02-02 14:25:56 +0000671#ifdef __MWERKS__
Jack Jansen38e97661995-11-10 14:53:00 +0000672 {
673 int siouxdidit;
674
675 /* If SIOUX wants it we're done */
676 siouxdidit = SIOUXHandleOneEvent(evp);
677 if ( siouxdidit )
678 return;
679 }
Jack Jansena76382a1995-02-02 14:25:56 +0000680#else
Jack Jansen0c968871997-08-26 13:20:34 +0000681 /* Other compilers are just unlucky... */
Jack Jansena76382a1995-02-02 14:25:56 +0000682#endif /* !__MWERKS__ */
Jack Jansen36ed5061997-06-20 16:18:15 +0000683}
684
685/*
686** Handle an event, either through HandleEvent or by passing it to the Python
687** event handler.
688*/
689int
690PyMac_HandleEvent(evp)
691 EventRecord *evp;
692{
693 PyObject *rv;
694
695 if ( python_event_handler ) {
696 rv = PyObject_CallFunction(python_event_handler, "(O&)",
697 PyMac_BuildEventRecord, evp);
698 if ( rv )
699 Py_DECREF(rv);
700 else
701 return -1; /* Propagate exception */
702 } else {
703 PyMac_HandleEventIntern(evp);
704 }
705 return 0;
Jack Jansena76382a1995-02-02 14:25:56 +0000706}
707
Jack Jansen0194ad52001-05-12 22:46:35 +0000708#if !TARGET_API_MAC_OSX
Jack Jansena76382a1995-02-02 14:25:56 +0000709/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000710** Yield the CPU to other tasks without processing events.
Jack Jansene8e8ae01995-01-26 16:36:45 +0000711*/
Jack Jansen2d1306b2000-04-07 09:10:49 +0000712int
Jack Jansene3ae0df1997-06-03 15:28:29 +0000713PyMac_DoYield(int maxsleep, int maycallpython)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000714{
715 EventRecord ev;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000716 int gotone;
Jack Jansene3ae0df1997-06-03 15:28:29 +0000717 long latest_time_ready;
Jack Jansen36ed5061997-06-20 16:18:15 +0000718 static int in_here = 0;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000719
Jack Jansen36ed5061997-06-20 16:18:15 +0000720 in_here++;
Jack Jansene3ae0df1997-06-03 15:28:29 +0000721 /*
722 ** First check for interrupts, if wanted.
723 ** This sets a flag that will be picked up at an appropriate
724 ** moment in the mainloop.
725 */
726 if (schedparams.check_interrupt)
Jack Jansenee23d6e1995-01-27 14:43:25 +0000727 scan_event_queue(0);
Jack Jansene3ae0df1997-06-03 15:28:29 +0000728
729 /* XXXX Implementing an idle routine goes here */
Jack Jansene8e8ae01995-01-26 16:36:45 +0000730
Jack Jansene3ae0df1997-06-03 15:28:29 +0000731 /*
732 ** Check which of the eventloop cases we have:
733 ** - process events
734 ** - don't process events but do yield
735 ** - do neither
736 */
Jack Jansen36ed5061997-06-20 16:18:15 +0000737 if( in_here > 1 || !schedparams.process_events ||
738 (python_event_handler && !maycallpython) ) {
Jack Jansene3ae0df1997-06-03 15:28:29 +0000739 if ( maxsleep >= 0 ) {
Jack Jansen6e68a7e2001-05-12 21:31:34 +0000740#if TARGET_API_MAC_OS8
Jack Jansene8e8ae01995-01-26 16:36:45 +0000741 SystemTask();
Jack Jansen15f1c082001-04-25 22:07:27 +0000742#else
743 int xxx = 0;
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000744#endif
Jack Jansen15f1c082001-04-25 22:07:27 +0000745 }
Jack Jansene3ae0df1997-06-03 15:28:29 +0000746 } else {
747 latest_time_ready = LMGetTicks() + maxsleep;
Jack Jansen2d1306b2000-04-07 09:10:49 +0000748 do {
Jack Jansen0c968871997-08-26 13:20:34 +0000749 /* XXXX Hack by Jack.
750 ** In time.sleep() you can click to another application
751 ** once only. If you come back to Python you cannot get away
752 ** again.
753 **/
Jack Jansen36ed5061997-06-20 16:18:15 +0000754 gotone = WaitNextEvent(schedparams.process_events, &ev, maxsleep, NULL);
Jack Jansene3ae0df1997-06-03 15:28:29 +0000755 /* Get out quickly if nothing interesting is happening */
756 if ( !gotone || ev.what == nullEvent )
757 break;
Jack Jansen36ed5061997-06-20 16:18:15 +0000758 if ( PyMac_HandleEvent(&ev) < 0 ) {
759 in_here--;
760 return -1;
761 }
Jack Jansene3ae0df1997-06-03 15:28:29 +0000762 maxsleep = latest_time_ready - LMGetTicks();
Jack Jansen2d1306b2000-04-07 09:10:49 +0000763 } while ( maxsleep > 0 );
Jack Jansenf93c72a1994-12-14 14:07:50 +0000764 }
Jack Jansen36ed5061997-06-20 16:18:15 +0000765 in_here--;
766 return 0;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000767}
768
769/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000770** Process events and/or yield the CPU to other tasks if opportune
Jack Jansene8e8ae01995-01-26 16:36:45 +0000771*/
Jack Jansen36ed5061997-06-20 16:18:15 +0000772int
Jack Jansene8e8ae01995-01-26 16:36:45 +0000773PyMac_Yield() {
Jack Jansene3ae0df1997-06-03 15:28:29 +0000774 unsigned long maxsleep;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000775
Jack Jansene3ae0df1997-06-03 15:28:29 +0000776 if( PyMac_InForeground() )
777 maxsleep = 0;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000778 else
Jack Jansene3ae0df1997-06-03 15:28:29 +0000779 maxsleep = schedparams.bg_yield;
780
Jack Jansen36ed5061997-06-20 16:18:15 +0000781 return PyMac_DoYield(maxsleep, 1);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000782}
783
784/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000785** Return current scheduler parameters
Jack Jansene8e8ae01995-01-26 16:36:45 +0000786*/
Jack Jansene3ae0df1997-06-03 15:28:29 +0000787void
788PyMac_GetSchedParams(PyMacSchedParams *sp)
Jack Jansene8e8ae01995-01-26 16:36:45 +0000789{
Jack Jansene3ae0df1997-06-03 15:28:29 +0000790 sp->check_interrupt = schedparams.check_interrupt;
791 sp->process_events = schedparams.process_events;
792 sp->besocial = schedparams.besocial;
793 sp->check_interval = schedparams.check_interval / 60.0;
794 sp->bg_yield = schedparams.bg_yield / 60.0;
Jack Jansenf93c72a1994-12-14 14:07:50 +0000795}
Jack Jansenf6865f71996-09-04 15:24:59 +0000796
Jack Jansen74162f31995-02-15 22:58:33 +0000797/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000798** Set current scheduler parameters
799*/
800void
801PyMac_SetSchedParams(PyMacSchedParams *sp)
802{
803 schedparams.check_interrupt = sp->check_interrupt;
804 schedparams.process_events = sp->process_events;
805 schedparams.besocial = sp->besocial;
806 schedparams.check_interval = (unsigned long)(sp->check_interval*60);
807 schedparams.bg_yield = (unsigned long)(sp->bg_yield*60);
808 if ( schedparams.check_interrupt || schedparams.process_events ||
809 schedparams.besocial )
810 schedparams.enabled = 1;
811 else
812 schedparams.enabled = 0;
813 schedparams.next_check = 0; /* Check immedeately */
814}
Jack Jansencaa7c461997-06-12 10:49:13 +0000815
Jack Jansene3ae0df1997-06-03 15:28:29 +0000816/*
Jack Jansen3469e991996-09-06 00:30:45 +0000817** Install our menu bar.
818*/
819void
820PyMac_InitMenuBar()
821{
Jack Jansen3469e991996-09-06 00:30:45 +0000822 MenuHandle applemenu;
823
Jack Jansen15f1c082001-04-25 22:07:27 +0000824 if ( sioux_mbar ) return;
Jack Jansencaa7c461997-06-12 10:49:13 +0000825 if ( (sioux_mbar=GetMenuBar()) == NULL ) {
826 /* Sioux menu not installed yet. Do so */
827 SIOUXSetupMenus();
828 if ( (sioux_mbar=GetMenuBar()) == NULL )
829 return;
830 }
Jack Jansen08c3be31997-04-08 15:27:00 +0000831 if ( (applemenu=GetMenuHandle(SIOUX_APPLEID)) == NULL ) return;
Jack Jansen3469e991996-09-06 00:30:45 +0000832 SetMenuItemText(applemenu, 1, "\pAbout Python...");
833}
834
835/*
Jack Jansencaa7c461997-06-12 10:49:13 +0000836** Restore sioux menu bar
837*/
838void
839PyMac_RestoreMenuBar()
840{
Jack Jansen15f1c082001-04-25 22:07:27 +0000841#if 1
Jack Jansen657ba272001-02-17 22:02:07 +0000842 /* This doesn't seem to work anymore? Or only for Carbon? */
843 MenuBarHandle curmenubar;
844
845 curmenubar = GetMenuBar();
Jack Janseneda78631997-06-12 15:29:46 +0000846 if ( sioux_mbar ) {
Jack Jansencaa7c461997-06-12 10:49:13 +0000847 SetMenuBar(sioux_mbar);
Jack Janseneda78631997-06-12 15:29:46 +0000848 DrawMenuBar();
Jack Jansen657ba272001-02-17 22:02:07 +0000849 } else {
Jack Jansenefaada71998-02-20 16:03:15 +0000850 PyMac_InitMenuBar();
Jack Jansen657ba272001-02-17 22:02:07 +0000851 DrawMenuBar();
852 }
853#endif
Jack Jansencaa7c461997-06-12 10:49:13 +0000854}
855
Jack Jansen15f1c082001-04-25 22:07:27 +0000856void
857PyMac_RaiseConsoleWindow()
858{
859 /* Note: this is a hack. SIOUXTextWindow is SIOUX's internal structure
860 ** and we happen to know that the first entry is the window pointer.
861 */
862 extern WindowRef *SIOUXTextWindow;
863
864 if ( SIOUXTextWindow == NULL || *SIOUXTextWindow == NULL )
865 return;
866 if ( FrontWindow() != *SIOUXTextWindow )
867 BringToFront(*SIOUXTextWindow);
868}
Jack Jansencaa7c461997-06-12 10:49:13 +0000869
870/*
Jack Jansen3469e991996-09-06 00:30:45 +0000871** Our replacement about box
872*/
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000873
874#include "patchlevel.h"
875
Jack Jansen3469e991996-09-06 00:30:45 +0000876void
877SIOUXDoAboutBox(void)
878{
879 DialogPtr theDialog;
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000880 WindowPtr theWindow;
Jack Jansen3469e991996-09-06 00:30:45 +0000881 short item;
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000882 short fontID;
Jack Jansen3469e991996-09-06 00:30:45 +0000883
884 if( (theDialog = GetNewDialog(ABOUT_ID, NULL, (WindowPtr)-1)) == NULL )
885 return;
Jack Jansend617c571996-09-22 22:14:30 +0000886 theWindow = GetDialogWindow(theDialog);
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000887 SetPortWindowPort(theWindow);
888 GetFNum("\pPython-Sans", &fontID);
889 if (fontID == 0)
890 fontID = kFontIDGeneva;
891 TextFont(fontID);
892 TextSize(9);
893 ParamText(Pstring(PATCHLEVEL), "\p", "\p", "\p");
Jack Jansend617c571996-09-22 22:14:30 +0000894 ShowWindow(theWindow);
Jack Jansen3469e991996-09-06 00:30:45 +0000895 ModalDialog(NULL, &item);
896 DisposeDialog(theDialog);
897}
898
Jack Jansen0194ad52001-05-12 22:46:35 +0000899#endif /* !TARGET_API_MAC_OSX */
Jack Janseneda78631997-06-12 15:29:46 +0000900
Jack Jansen0194ad52001-05-12 22:46:35 +0000901#if TARGET_API_MAC_OS8
Jack Janseneda78631997-06-12 15:29:46 +0000902/*
Jack Jansen3ec804a1995-02-20 15:56:10 +0000903** Helper routine for GetDirectory
904*/
Guido van Rossum24a45e31995-02-20 23:45:53 +0000905static pascal short
Jack Jansen819f1771995-08-14 12:35:10 +0000906myhook_proc(short item, DialogPtr theDialog, struct hook_args *dataptr)
Jack Jansen3ec804a1995-02-20 15:56:10 +0000907{
Jack Jansen819f1771995-08-14 12:35:10 +0000908 if ( item == sfHookFirstCall && dataptr->prompt) {
909 Handle prompth;
910 short type;
911 Rect rect;
912
913 GetDialogItem(theDialog, PROMPT_ITEM, &type, &prompth, &rect);
914 if ( prompth )
915 SetDialogItemText(prompth, (unsigned char *)dataptr->prompt);
916 } else
Jack Jansen3ec804a1995-02-20 15:56:10 +0000917 if ( item == SELECTCUR_ITEM ) {
918 item = sfItemCancelButton;
Jack Jansen819f1771995-08-14 12:35:10 +0000919 dataptr->selectcur_hit = 1;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000920 }
921 return item;
922}
Jack Jansen0194ad52001-05-12 22:46:35 +0000923
Jack Jansen3ec804a1995-02-20 15:56:10 +0000924/*
925** Ask the user for a directory. I still can't understand
926** why Apple doesn't provide a standard solution for this...
927*/
928int
Jack Jansen819f1771995-08-14 12:35:10 +0000929PyMac_GetDirectory(dirfss, prompt)
Jack Jansen3ec804a1995-02-20 15:56:10 +0000930 FSSpec *dirfss;
Jack Jansen819f1771995-08-14 12:35:10 +0000931 char *prompt;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000932{
933 static SFTypeList list = {'fldr', 0, 0, 0};
934 static Point where = {-1, -1};
Jack Jansen3ec804a1995-02-20 15:56:10 +0000935 StandardFileReply reply;
Jack Jansen819f1771995-08-14 12:35:10 +0000936 struct hook_args hook_args;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000937
938 if ( !upp_inited ) {
939 myhook_upp = NewDlgHookYDProc(myhook_proc);
940 upp_inited = 1;
941 }
Jack Jansen819f1771995-08-14 12:35:10 +0000942 if ( prompt && *prompt )
943 hook_args.prompt = (char *)Pstring(prompt);
944 else
945 hook_args.prompt = NULL;
946 hook_args.selectcur_hit = 0;
Guido van Rossum24a45e31995-02-20 23:45:53 +0000947 CustomGetFile((FileFilterYDUPP)0, 1, list, &reply, GETDIR_ID, where, myhook_upp,
Jack Jansen819f1771995-08-14 12:35:10 +0000948 NULL, NULL, NULL, (void *)&hook_args);
Jack Jansen3ec804a1995-02-20 15:56:10 +0000949
950 reply.sfFile.name[0] = 0;
951 if( FSMakeFSSpec(reply.sfFile.vRefNum, reply.sfFile.parID, reply.sfFile.name, dirfss) )
952 return 0;
Jack Jansen819f1771995-08-14 12:35:10 +0000953 return hook_args.selectcur_hit;
954}
955
956/*
957** Slightly extended StandardGetFile: accepts a prompt */
958void PyMac_PromptGetFile(short numTypes, ConstSFTypeListPtr typeList,
959 StandardFileReply *reply, char *prompt)
960{
961 static Point where = {-1, -1};
962 struct hook_args hook_args;
963
964 if ( !upp_inited ) {
965 myhook_upp = NewDlgHookYDProc(myhook_proc);
966 upp_inited = 1;
967 }
968 if ( prompt && *prompt )
969 hook_args.prompt = (char *)Pstring(prompt);
970 else
971 hook_args.prompt = NULL;
972 hook_args.selectcur_hit = 0;
973 CustomGetFile((FileFilterYDUPP)0, numTypes, typeList, reply, GETFILEPROMPT_ID, where,
974 myhook_upp, NULL, NULL, NULL, (void *)&hook_args);
Jack Jansen3ec804a1995-02-20 15:56:10 +0000975}
Jack Jansen6e68a7e2001-05-12 21:31:34 +0000976#endif /* TARGET_API_MAC_OS8 */
Jack Jansen5f653091995-01-18 13:53:49 +0000977
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000978/* Convert a 4-char string object argument to an OSType value */
Jack Jansen5f653091995-01-18 13:53:49 +0000979int
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000980PyMac_GetOSType(PyObject *v, OSType *pr)
Jack Jansen5f653091995-01-18 13:53:49 +0000981{
982 if (!PyString_Check(v) || PyString_Size(v) != 4) {
983 PyErr_SetString(PyExc_TypeError,
984 "OSType arg must be string of 4 chars");
985 return 0;
986 }
987 memcpy((char *)pr, PyString_AsString(v), 4);
988 return 1;
989}
990
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000991/* Convert an OSType value to a 4-char string object */
992PyObject *
993PyMac_BuildOSType(OSType t)
994{
995 return PyString_FromStringAndSize((char *)&t, 4);
996}
997
Jack Jansend1f06311996-08-01 15:23:54 +0000998/* Convert an NumVersion value to a 4-element tuple */
999PyObject *
1000PyMac_BuildNumVersion(NumVersion t)
1001{
1002 return Py_BuildValue("(hhhh)", t.majorRev, t.minorAndBugRev, t.stage, t.nonRelRev);
1003}
1004
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001005
1006/* Convert a Python string object to a Str255 */
Jack Jansen5f653091995-01-18 13:53:49 +00001007int
Guido van Rossum8f691791995-01-18 23:57:26 +00001008PyMac_GetStr255(PyObject *v, Str255 pbuf)
Jack Jansen5f653091995-01-18 13:53:49 +00001009{
1010 int len;
1011 if (!PyString_Check(v) || (len = PyString_Size(v)) > 255) {
1012 PyErr_SetString(PyExc_TypeError,
1013 "Str255 arg must be string of at most 255 chars");
1014 return 0;
1015 }
1016 pbuf[0] = len;
1017 memcpy((char *)(pbuf+1), PyString_AsString(v), len);
1018 return 1;
1019}
1020
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001021/* Convert a Str255 to a Python string object */
1022PyObject *
1023PyMac_BuildStr255(Str255 s)
1024{
Jack Jansenb734ade1999-12-17 17:15:50 +00001025 if ( s == NULL ) {
1026 PyErr_SetString(PyExc_SystemError, "Str255 pointer is NULL");
1027 return NULL;
1028 }
1029 return PyString_FromStringAndSize((char *)&s[1], (int)s[0]);
1030}
1031
1032PyObject *
1033PyMac_BuildOptStr255(Str255 s)
1034{
1035 if ( s == NULL ) {
1036 Py_INCREF(Py_None);
1037 return Py_None;
1038 }
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001039 return PyString_FromStringAndSize((char *)&s[1], (int)s[0]);
1040}
1041
1042
Guido van Rossum8f691791995-01-18 23:57:26 +00001043
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001044/* Convert a Python object to a Rect.
Guido van Rossum5279ec61995-01-26 22:56:59 +00001045 The object must be a (left, top, right, bottom) tuple.
1046 (This differs from the order in the struct but is consistent with
1047 the arguments to SetRect(), and also with STDWIN). */
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001048int
1049PyMac_GetRect(PyObject *v, Rect *r)
Guido van Rossum8f691791995-01-18 23:57:26 +00001050{
Guido van Rossum5279ec61995-01-26 22:56:59 +00001051 return PyArg_Parse(v, "(hhhh)", &r->left, &r->top, &r->right, &r->bottom);
Guido van Rossum8f691791995-01-18 23:57:26 +00001052}
Guido van Rossumb3404661995-01-22 18:36:13 +00001053
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001054/* Convert a Rect to a Python object */
Guido van Rossumb3404661995-01-22 18:36:13 +00001055PyObject *
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001056PyMac_BuildRect(Rect *r)
Guido van Rossumb3404661995-01-22 18:36:13 +00001057{
Guido van Rossum5279ec61995-01-26 22:56:59 +00001058 return Py_BuildValue("(hhhh)", r->left, r->top, r->right, r->bottom);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001059}
1060
1061
1062/* Convert a Python object to a Point.
Guido van Rossum5279ec61995-01-26 22:56:59 +00001063 The object must be a (h, v) tuple.
1064 (This differs from the order in the struct but is consistent with
1065 the arguments to SetPoint(), and also with STDWIN). */
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001066int
1067PyMac_GetPoint(PyObject *v, Point *p)
1068{
Guido van Rossum5279ec61995-01-26 22:56:59 +00001069 return PyArg_Parse(v, "(hh)", &p->h, &p->v);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001070}
1071
1072/* Convert a Point to a Python object */
1073PyObject *
1074PyMac_BuildPoint(Point p)
1075{
Guido van Rossum5279ec61995-01-26 22:56:59 +00001076 return Py_BuildValue("(hh)", p.h, p.v);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001077}
1078
1079
1080/* Convert a Python object to an EventRecord.
1081 The object must be a (what, message, when, (v, h), modifiers) tuple. */
1082int
1083PyMac_GetEventRecord(PyObject *v, EventRecord *e)
1084{
1085 return PyArg_Parse(v, "(hll(hh)h)",
1086 &e->what,
1087 &e->message,
1088 &e->when,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001089 &e->where.h,
Guido van Rossum5279ec61995-01-26 22:56:59 +00001090 &e->where.v,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001091 &e->modifiers);
1092}
1093
1094/* Convert a Rect to an EventRecord object */
1095PyObject *
1096PyMac_BuildEventRecord(EventRecord *e)
1097{
1098 return Py_BuildValue("(hll(hh)h)",
1099 e->what,
1100 e->message,
1101 e->when,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001102 e->where.h,
Guido van Rossum5279ec61995-01-26 22:56:59 +00001103 e->where.v,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001104 e->modifiers);
Guido van Rossumb3404661995-01-22 18:36:13 +00001105}
Jack Jansenfa4d5d01995-11-15 15:19:29 +00001106
1107/* Convert Python object to Fixed */
1108int
1109PyMac_GetFixed(PyObject *v, Fixed *f)
1110{
1111 double d;
1112
1113 if( !PyArg_Parse(v, "d", &d))
1114 return 0;
1115 *f = (Fixed)(d * 0x10000);
Jack Jansen31dd5c01996-05-31 13:01:39 +00001116 return 1;
Jack Jansenfa4d5d01995-11-15 15:19:29 +00001117}
1118
1119/* Convert a Point to a Python object */
1120PyObject *
1121PyMac_BuildFixed(Fixed f)
1122{
1123 double d;
1124
1125 d = f;
1126 d = d / 0x10000;
1127 return Py_BuildValue("d", d);
1128}
1129
Jack Jansend58cd631998-04-21 15:24:39 +00001130/* Convert wide to/from Python int or (hi, lo) tuple. XXXX Should use Python longs */
1131int
1132PyMac_Getwide(PyObject *v, wide *rv)
1133{
1134 if (PyInt_Check(v)) {
1135 rv->hi = 0;
1136 rv->lo = PyInt_AsLong(v);
1137 if( rv->lo & 0x80000000 )
1138 rv->hi = -1;
1139 return 1;
1140 }
1141 return PyArg_Parse(v, "(ll)", &rv->hi, &rv->lo);
1142}
1143
1144
1145PyObject *
Jack Jansenbbf4be21998-04-23 13:20:17 +00001146PyMac_Buildwide(wide *w)
Jack Jansend58cd631998-04-21 15:24:39 +00001147{
Jack Jansenbbf4be21998-04-23 13:20:17 +00001148 if ( (w->hi == 0 && (w->lo & 0x80000000) == 0) ||
1149 (w->hi == -1 && (w->lo & 0x80000000) ) )
1150 return PyInt_FromLong(w->lo);
1151 return Py_BuildValue("(ll)", w->hi, w->lo);
Jack Jansend58cd631998-04-21 15:24:39 +00001152}
Jack Jansen8bb1dc12001-05-19 12:31:09 +00001153
1154#ifdef USE_TOOLBOX_OBJECT_GLUE
1155/*
1156** Glue together the toolbox objects.
1157**
1158** Because toolbox modules interdepend on each other, they use each others
1159** object types, on MacOSX/MachO this leads to the situation that they
1160** cannot be dynamically loaded (or they would all have to be lumped into
1161** a single .so, but this would be bad for extensibility).
1162**
1163** This file defines wrappers for all the _New and _Convert functions,
1164** which are the Py_BuildValue and PyArg_ParseTuple helpers. The wrappers
1165** check an indirection function pointer, and if it isn't filled in yet
1166** they import the appropriate module, whose init routine should fill in
1167** the pointer.
1168*/
1169
1170#define GLUE_NEW(object, routinename, module) \
1171PyObject *(*PyMacGluePtr_##routinename)(object); \
1172\
1173PyObject *routinename(object cobj) { \
1174 if (!PyMacGluePtr_##routinename) { \
1175 if (!PyImport_ImportModule(module)) return NULL; \
1176 if (!PyMacGluePtr_##routinename) { \
1177 PyErr_SetString(PyExc_ImportError, "Module did not provide routine: " module ": " #routinename); \
1178 return NULL; \
1179 } \
1180 } \
1181 return (*PyMacGluePtr_##routinename)(cobj); \
1182}
1183
1184#define GLUE_CONVERT(object, routinename, module) \
1185int (*PyMacGluePtr_##routinename)(PyObject *, object *); \
1186\
1187int routinename(PyObject *pyobj, object *cobj) { \
1188 if (!PyMacGluePtr_##routinename) { \
1189 if (!PyImport_ImportModule(module)) return NULL; \
1190 if (!PyMacGluePtr_##routinename) { \
1191 PyErr_SetString(PyExc_ImportError, "Module did not provide routine: " module ": " #routinename); \
1192 return NULL; \
1193 } \
1194 } \
1195 return (*PyMacGluePtr_##routinename)(pyobj, cobj); \
1196}
1197
1198GLUE_NEW(AppleEvent *, AEDesc_New, "AE") /* XXXX Why by address? */
1199GLUE_CONVERT(AppleEvent, AEDesc_Convert, "AE")
1200
1201GLUE_NEW(Component, CmpObj_New, "Cm")
1202GLUE_CONVERT(Component, CmpObj_Convert, "Cm")
1203GLUE_NEW(ComponentInstance, CmpInstObj_New, "Cm")
1204GLUE_CONVERT(ComponentInstance, CmpInstObj_Convert, "Cm")
1205
1206GLUE_NEW(ControlHandle, CtlObj_New, "Ctl")
1207GLUE_CONVERT(ControlHandle, CtlObj_Convert, "Ctl")
1208
1209GLUE_NEW(DialogPtr, DlgObj_New, "Dlg")
1210GLUE_CONVERT(DialogPtr, DlgObj_Convert, "Dlg")
1211GLUE_NEW(DialogPtr, DlgObj_WhichDialog, "Dlg")
1212
1213GLUE_NEW(DragReference, DragObj_New, "Drag")
1214GLUE_CONVERT(DragReference, DragObj_Convert, "Drag")
1215
1216GLUE_NEW(ListHandle, ListObj_New, "List")
1217GLUE_CONVERT(ListHandle, ListObj_Convert, "List")
1218
1219GLUE_NEW(MenuHandle, MenuObj_New, "Menu")
1220GLUE_CONVERT(MenuHandle, MenuObj_Convert, "Menu")
1221
1222GLUE_NEW(GrafPtr, GrafObj_New, "Qd")
1223GLUE_CONVERT(GrafPtr, GrafObj_Convert, "Qd")
1224GLUE_NEW(BitMapPtr, BMObj_New, "Qd")
1225GLUE_CONVERT(BitMapPtr, BMObj_Convert, "Qd")
1226GLUE_NEW(RGBColor *, QdRGB_New, "Qd") /* XXXX Why? */
1227GLUE_CONVERT(RGBColor, QdRGB_Convert, "Qd")
1228
1229GLUE_NEW(GWorldPtr, GWorldObj_New, "Qdoffs")
1230GLUE_CONVERT(GWorldPtr, GWorldObj_Convert, "Qdoffs")
1231
1232GLUE_NEW(Track, TrackObj_New, "Qt")
1233GLUE_CONVERT(Track, TrackObj_Convert, "Qt")
1234GLUE_NEW(Movie, MovieObj_New, "Qt")
1235GLUE_CONVERT(Movie, MovieObj_Convert, "Qt")
1236GLUE_NEW(MovieController, MovieCtlObj_New, "Qt")
1237GLUE_CONVERT(MovieController, MovieCtlObj_Convert, "Qt")
1238GLUE_NEW(TimeBase, TimeBaseObj_New, "Qt")
1239GLUE_CONVERT(TimeBase, TimeBaseObj_Convert, "Qt")
1240GLUE_NEW(UserData, UserDataObj_New, "Qt")
1241GLUE_CONVERT(UserData, UserDataObj_Convert, "Qt")
1242GLUE_NEW(Media, MediaObj_New, "Qt")
1243GLUE_CONVERT(Media, MediaObj_Convert, "Qt")
1244
1245GLUE_NEW(Handle, ResObj_New, "Res")
1246GLUE_CONVERT(Handle, ResObj_Convert, "Res")
1247GLUE_NEW(Handle, OptResObj_New, "Res")
1248GLUE_CONVERT(Handle, OptResObj_Convert, "Res")
1249
1250GLUE_NEW(TEHandle, TEObj_New, "TE")
1251GLUE_CONVERT(TEHandle, TEObj_Convert, "TE")
1252
1253GLUE_NEW(WindowPtr, WinObj_New, "Win")
1254GLUE_CONVERT(WindowPtr, WinObj_Convert, "Win")
1255GLUE_NEW(WindowPtr, WinObj_WhichWindow, "Win")
1256
1257#endif /* USE_TOOLBOX_OBJECT_GLUE */