blob: a8993f5c162a5e548a48436d7329ef5a7a915778 [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>
Jack Jansen0194ad52001-05-12 22:46:35 +000049#include <Events.h>
Jack Jansen0194ad52001-05-12 22:46:35 +000050#else
51#include <Carbon/Carbon.h>
52#endif
53
54#if !TARGET_API_MAC_OS8
55/* Unfortunately this call is probably slower... */
56#define LMGetTicks() TickCount()
57#endif
58
Jack Jansen16df2aa1995-02-27 16:17:28 +000059#ifdef __MWERKS__
60#include <SIOUX.h>
Jack Jansen9ae898b2000-07-11 21:16:03 +000061extern void SIOUXSetupMenus(void);
62extern void SIOUXDoAboutBox(void);
Jack Jansen16df2aa1995-02-27 16:17:28 +000063#endif
Jack Jansen9ae898b2000-07-11 21:16:03 +000064#ifdef USE_GUSI
65/* Functions we redefine because they're in obscure libraries */
66extern void SpinCursor(short x);
67extern void RotateCursor(short x);
68extern pascal void PLstrcpy(unsigned char *, unsigned char *);
69extern pascal int PLstrcmp(unsigned char *, unsigned char *);
70extern pascal unsigned char *PLstrrchr(unsigned char *, unsigned char);
71
72#endif
73
Jack Jansen2d1306b2000-04-07 09:10:49 +000074#ifdef USE_GUSI1
Jack Jansen911ad6b1996-03-05 16:56:24 +000075#include <TFileSpec.h> /* For Path2FSSpec */
Jack Jansenf6865f71996-09-04 15:24:59 +000076#include <GUSI.h>
Jack Jansen911ad6b1996-03-05 16:56:24 +000077#endif
Jack Jansenee23d6e1995-01-27 14:43:25 +000078
Jack Jansen3469e991996-09-06 00:30:45 +000079/* The ID of the Sioux apple menu */
80#define SIOUX_APPLEID 32000
81
Jack Jansenee23d6e1995-01-27 14:43:25 +000082#include <signal.h>
Jack Jansen74162f31995-02-15 22:58:33 +000083#include <stdio.h>
Jack Jansene8e8ae01995-01-26 16:36:45 +000084
Jack Jansenee23d6e1995-01-27 14:43:25 +000085/*
Jack Jansend1f06311996-08-01 15:23:54 +000086** When less than this amount of stackspace is left we
87** raise a MemoryError.
88*/
89#ifndef MINIMUM_STACK_SIZE
Jack Jansend1f06311996-08-01 15:23:54 +000090#define MINIMUM_STACK_SIZE 8192
Jack Jansend1f06311996-08-01 15:23:54 +000091#endif
92
Jack Jansen340eb882001-02-02 22:40:28 +000093#if TARGET_API_MAC_CARBON
94/*
95** On MacOSX StackSpace() lies: it gives the distance from heap end to stack pointer,
96** but the stack cannot grow that far due to rlimit values. We cannot get at this value
97** from Carbon, so we set a maximum to the stack here that is based on the default
98** stack limit of 512K.
99*/
100#define MAXIMUM_STACK_SIZE (256*1024)
101#endif
102
Jack Jansend1f06311996-08-01 15:23:54 +0000103/*
Jack Jansen16df2aa1995-02-27 16:17:28 +0000104** We have to be careful, since we can't handle
Jack Jansenee23d6e1995-01-27 14:43:25 +0000105** things like updates (and they'll keep coming back if we don't
Jack Jansen16df2aa1995-02-27 16:17:28 +0000106** handle them). Note that we don't know who has windows open, so
107** even handing updates off to SIOUX under MW isn't going to work.
Jack Jansenee23d6e1995-01-27 14:43:25 +0000108*/
Jack Jansen0c968871997-08-26 13:20:34 +0000109#define MAINLOOP_EVENTMASK (mDownMask|keyDownMask|osMask|activMask)
Jack Jansene8e8ae01995-01-26 16:36:45 +0000110
111#include <signal.h>
Jack Jansenf93c72a1994-12-14 14:07:50 +0000112
Guido van Rossumb3404661995-01-22 18:36:13 +0000113/* XXX We should include Errors.h here, but it has a name conflict
Jack Jansen5f653091995-01-18 13:53:49 +0000114** with the python errors.h. */
115#define fnfErr -43
116
Jack Jansenee23d6e1995-01-27 14:43:25 +0000117/* Interrupt code variables: */
118static int interrupted; /* Set to true when cmd-. seen */
Jack Jansend88296d2000-07-11 19:51:05 +0000119static RETSIGTYPE intcatcher(int);
Jack Jansenee23d6e1995-01-27 14:43:25 +0000120
Jack Jansen0194ad52001-05-12 22:46:35 +0000121#if !TARGET_API_MAC_OSX
Jack Jansend88296d2000-07-11 19:51:05 +0000122static int PyMac_Yield(void);
Jack Jansen0194ad52001-05-12 22:46:35 +0000123#endif
Jack Jansenf6865f71996-09-04 15:24:59 +0000124
Jack Jansene8e8ae01995-01-26 16:36:45 +0000125/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000126** These are the real scheduling parameters that control what we check
127** in the event loop, and how often we check. The values are initialized
128** from pyMac_SchedParamStruct.
129*/
130
131struct real_sched_param_struct {
132 int check_interrupt; /* if true check for command-dot */
133 int process_events; /* if nonzero enable evt processing, this mask */
134 int besocial; /* if nonzero be a little social with CPU */
135 unsigned long check_interval; /* how often to check, in ticks */
136 unsigned long bg_yield; /* yield so long when in background */
137 /* these are computed from previous and clock and such */
138 int enabled; /* check_interrupt OR process_event OR yield */
139 unsigned long next_check; /* when to check/yield next, in ticks */
140};
141
142static struct real_sched_param_struct schedparams =
143 { 1, MAINLOOP_EVENTMASK, 1, 15, 15, 1, 0};
144
Jack Jansen819f1771995-08-14 12:35:10 +0000145/*
Jack Jansenf6865f71996-09-04 15:24:59 +0000146** Workaround for sioux/gusi combo: set when we are exiting
147*/
148int PyMac_ConsoleIsDead;
149
150/*
Jack Jansencaa7c461997-06-12 10:49:13 +0000151** Sioux menu bar, saved early so we can restore it
152*/
Jack Jansen657ba272001-02-17 22:02:07 +0000153static MenuBarHandle sioux_mbar;
Jack Jansencaa7c461997-06-12 10:49:13 +0000154
155/*
Jack Jansen819f1771995-08-14 12:35:10 +0000156** Some stuff for our GetDirectory and PromptGetFile routines
157*/
158struct hook_args {
159 int selectcur_hit; /* Set to true when "select current" selected */
160 char *prompt; /* The prompt */
161};
Jack Jansen6e68a7e2001-05-12 21:31:34 +0000162#if !TARGET_API_MAC_OS8
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000163/* The StandardFile hooks don't exist in Carbon. This breaks GetDirectory,
164** but the macfsn code will replace it by a NavServices version anyway.
165*/
166#define myhook_upp NULL
167#else
Jack Jansen819f1771995-08-14 12:35:10 +0000168static DlgHookYDUPP myhook_upp;
169static int upp_inited = 0;
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000170#endif
Jack Jansen819f1771995-08-14 12:35:10 +0000171
Jack Jansen36ed5061997-06-20 16:18:15 +0000172/*
173** The python-code event handler
174*/
175static PyObject *python_event_handler;
176
Jack Jansen8f5725a1999-12-07 23:08:10 +0000177/*
178** Set to true if we're appearance-compliant
179*/
180int PyMac_AppearanceCompliant;
181
Jack Jansen1f9f2f42000-07-24 19:50:16 +0000182/*
183** Find out what the current script is.
184** Donated by Fredrik Lund.
185*/
186char *PyMac_getscript()
187{
188 int font, script, lang;
189 font = 0;
190 font = GetSysFont();
191 script = FontToScript(font);
192 switch (script) {
193 case smRoman:
194 lang = GetScriptVariable(script, smScriptLang);
195 if (lang == langIcelandic)
196 return "mac-iceland";
197 else if (lang == langTurkish)
198 return "mac-turkish";
199 else if (lang == langGreek)
200 return "mac-greek";
201 else
202 return "mac-roman";
203 break;
unknownf428aef2001-07-04 22:36:27 +0000204#if 0
205 /* We don't have a codec for this, so don't return it */
Jack Jansen1f9f2f42000-07-24 19:50:16 +0000206 case smJapanese:
207 return "mac-japan";
unknownf428aef2001-07-04 22:36:27 +0000208#endif
Jack Jansen1f9f2f42000-07-24 19:50:16 +0000209 case smGreek:
210 return "mac-greek";
211 case smCyrillic:
212 return "mac-cyrillic";
213 default:
Jack Jansencbed91b2001-08-03 13:31:36 +0000214 return "ascii"; /* better than nothing */
Jack Jansen1f9f2f42000-07-24 19:50:16 +0000215 }
216}
217
Jack Jansen741e0372001-05-19 12:55:57 +0000218/* Given an FSSpec, return the FSSpec of the parent folder */
219
220static OSErr
221get_folder_parent (FSSpec * fss, FSSpec * parent)
222{
223 CInfoPBRec rec;
224 short err;
225
226 * parent = * fss;
227 rec.hFileInfo.ioNamePtr = parent->name;
228 rec.hFileInfo.ioVRefNum = parent->vRefNum;
229 rec.hFileInfo.ioDirID = parent->parID;
230 rec.hFileInfo.ioFDirIndex = -1;
231 rec.hFileInfo.ioFVersNum = 0;
232 if (err = PBGetCatInfoSync (& rec))
233 return err;
234 parent->parID = rec.dirInfo.ioDrParID;
235/* parent->name[0] = 0; */
236 return 0;
237}
238
239/* Given an FSSpec return a full, colon-separated pathname */
240
241OSErr
242PyMac_GetFullPath (FSSpec *fss, char *buf)
243{
244 short err;
245 FSSpec fss_parent, fss_current;
246 char tmpbuf[1024];
247 int plen;
248
249 fss_current = *fss;
250 plen = fss_current.name[0];
251 memcpy(buf, &fss_current.name[1], plen);
252 buf[plen] = 0;
253 /* Special case for disk names */
254 if ( fss_current.parID <= 1 ) {
255 buf[plen++] = ':';
256 buf[plen] = 0;
257 return 0;
258 }
259 while (fss_current.parID > 1) {
260 /* Get parent folder name */
261 if (err = get_folder_parent(&fss_current, &fss_parent))
262 return err;
263 fss_current = fss_parent;
264 /* Prepend path component just found to buf */
265 plen = fss_current.name[0];
266 if (strlen(buf) + plen + 1 > 1024) {
267 /* Oops... Not enough space (shouldn't happen) */
268 *buf = 0;
269 return -1;
270 }
271 memcpy(tmpbuf, &fss_current.name[1], plen);
272 tmpbuf[plen] = ':';
273 strcpy(&tmpbuf[plen+1], buf);
274 strcpy(buf, tmpbuf);
275 }
276 return 0;
277}
Jack Jansen1f9f2f42000-07-24 19:50:16 +0000278
Jack Jansen2d1306b2000-04-07 09:10:49 +0000279#ifdef USE_GUSI1
Jack Jansen378815c1996-03-06 16:21:34 +0000280/*
281** GUSI (1.6.0 and earlier, at the least) do not set the MacOS idea of
282** the working directory. Hence, we call this routine after each call
283** to chdir() to rectify things.
284*/
285void
286PyMac_FixGUSIcd()
287{
288 WDPBRec pb;
289 FSSpec curdirfss;
290
291 if ( Path2FSSpec(":x", &curdirfss) != noErr )
292 return;
293
294 /* Set MacOS "working directory" */
295 pb.ioNamePtr= "\p";
296 pb.ioVRefNum= curdirfss.vRefNum;
297 pb.ioWDDirID= curdirfss.parID;
Jack Jansen08c3be31997-04-08 15:27:00 +0000298 if (PBHSetVolSync(&pb) != noErr)
Jack Jansen378815c1996-03-06 16:21:34 +0000299 return;
Jack Jansen378815c1996-03-06 16:21:34 +0000300}
Jack Jansen2d1306b2000-04-07 09:10:49 +0000301#endif
Jack Jansen7ac70af1996-08-19 11:01:05 +0000302
Jack Jansen2d1306b2000-04-07 09:10:49 +0000303#ifdef USE_GUSI
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000304/*
305** SpinCursor (needed by GUSI) drags in heaps of stuff, so we
306** provide a dummy here.
307*/
Jack Jansencfadbd41996-08-19 11:36:25 +0000308void SpinCursor(short x) { /* Dummy */ }
Jack Jansenefaada71998-02-20 16:03:15 +0000309void RotateCursor(short x) { /* Dummy */ }
Jack Jansencfadbd41996-08-19 11:36:25 +0000310
Jack Jansenf6865f71996-09-04 15:24:59 +0000311/*
312** Replacement GUSI Spin function
313*/
Jack Jansen2d1306b2000-04-07 09:10:49 +0000314#ifdef USE_GUSI1
Jack Jansenf6865f71996-09-04 15:24:59 +0000315static int
316PyMac_GUSISpin(spin_msg msg, long arg)
317{
Jack Jansene3ae0df1997-06-03 15:28:29 +0000318 static Boolean inForeground = true;
319 int maxsleep = 6; /* 6 ticks is "normal" sleeptime */
Jack Jansenf6865f71996-09-04 15:24:59 +0000320
321 if (PyMac_ConsoleIsDead) return 0;
322#if 0
323 if (inForeground)
324 SpinCursor(msg == SP_AUTO_SPIN ? short(arg) : 1);
325#endif
326
327 if (interrupted) return -1;
328
Jack Jansene3ae0df1997-06-03 15:28:29 +0000329 if ( msg == SP_AUTO_SPIN )
330 maxsleep = 0;
331 if ( msg==SP_SLEEP||msg==SP_SELECT )
332 maxsleep = arg;
Jack Jansenf6865f71996-09-04 15:24:59 +0000333
Jack Jansene3ae0df1997-06-03 15:28:29 +0000334 PyMac_DoYield(maxsleep, 0); /* XXXX or is it safe to call python here? */
Jack Jansenf6865f71996-09-04 15:24:59 +0000335
336 return 0;
337}
338
339void
340PyMac_SetGUSISpin() {
341 GUSISetHook(GUSI_SpinHook, (GUSIHook)PyMac_GUSISpin);
342}
Jack Jansen2d1306b2000-04-07 09:10:49 +0000343#endif
Jack Jansenf6865f71996-09-04 15:24:59 +0000344
Jack Jansena39f1b01997-05-23 15:35:14 +0000345/* Called at exit() time thru atexit(), to stop event processing */
346void
347PyMac_StopGUSISpin() {
348 PyMac_ConsoleIsDead = 1;
349}
350
Jack Jansen6e68a7e2001-05-12 21:31:34 +0000351#if TARGET_API_MAC_OS8
Jack Jansena39f1b01997-05-23 15:35:14 +0000352/*
353** Replacement routines for the PLstr... functions so we don't need
Jack Jansen6ba34aa2001-01-11 23:03:56 +0000354** StdCLib.
Jack Jansena39f1b01997-05-23 15:35:14 +0000355*/
Jack Jansen8bb573e1999-12-12 21:37:14 +0000356pascal void
Jack Jansen9ae898b2000-07-11 21:16:03 +0000357PLstrcpy(unsigned char *to, unsigned char *fr)
Jack Jansena39f1b01997-05-23 15:35:14 +0000358{
359 memcpy(to, fr, fr[0]+1);
360}
361
Jack Jansen8bb573e1999-12-12 21:37:14 +0000362pascal int
Jack Jansen9ae898b2000-07-11 21:16:03 +0000363PLstrcmp(unsigned char *s1, unsigned char *s2)
Jack Jansena39f1b01997-05-23 15:35:14 +0000364{
365 int res;
366 int l = s1[0] < s2[0] ? s1[0] : s2[0];
367
368 res = memcmp(s1+1, s2+1, l);
369 if ( res != 0 )
370 return res;
371
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000372 if ( s1[0] < s2[0] )
Jack Jansena39f1b01997-05-23 15:35:14 +0000373 return -1;
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000374 else if ( s1[0] > s2[0] )
Jack Jansena39f1b01997-05-23 15:35:14 +0000375 return 1;
376 else
377 return 0;
378}
379
Jack Jansen8bb573e1999-12-12 21:37:14 +0000380pascal unsigned char *
Jack Jansen9ae898b2000-07-11 21:16:03 +0000381PLstrrchr(unsigned char *str, unsigned char chr)
Jack Jansena39f1b01997-05-23 15:35:14 +0000382{
383 unsigned char *ptr = 0;
384 unsigned char *p;
385
386 for(p=str+1; p<str+str[0]; p++)
387 if ( *p == chr )
388 ptr = p;
389 return ptr;
390}
391
Jack Jansen6e68a7e2001-05-12 21:31:34 +0000392#endif /* TARGET_API_MAC_OS8 */
Jack Jansena39f1b01997-05-23 15:35:14 +0000393#endif /* USE_GUSI */
Jack Jansen378815c1996-03-06 16:21:34 +0000394
Jack Jansen819f1771995-08-14 12:35:10 +0000395
Jack Jansen5f653091995-01-18 13:53:49 +0000396/* Convert C to Pascal string. Returns pointer to static buffer. */
397unsigned char *
398Pstring(char *str)
399{
400 static Str255 buf;
401 int len;
402
403 len = strlen(str);
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000404 if (len > 255)
405 len = 255;
Jack Jansen5f653091995-01-18 13:53:49 +0000406 buf[0] = (unsigned char)len;
407 strncpy((char *)buf+1, str, len);
408 return buf;
409}
410
Jack Jansen6e68a7e2001-05-12 21:31:34 +0000411#if TARGET_API_MAC_OS8
Jack Jansen5afad832000-12-12 22:12:14 +0000412void
413c2pstrcpy(unsigned char *dst, const char *src)
414{
415 int len;
416
417 len = strlen(src);
418 if ( len > 255 ) len = 255;
419 strncpy((char *)dst+1, src, len);
420 dst[0] = len;
421}
Jack Jansen6e68a7e2001-05-12 21:31:34 +0000422#endif /* TARGET_API_MAC_OS8 */
Jack Jansen5afad832000-12-12 22:12:14 +0000423
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000424/* Like strerror() but for Mac OS error numbers */
425char *PyMac_StrError(int err)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000426{
427 static char buf[256];
428 Handle h;
429 char *str;
430
431 h = GetResource('Estr', err);
432 if ( h ) {
433 HLock(h);
434 str = (char *)*h;
435 memcpy(buf, str+1, (unsigned char)str[0]);
Guido van Rossumcc9bc8f1995-02-13 16:17:03 +0000436 buf[(unsigned char)str[0]] = '\0';
Jack Jansenf93c72a1994-12-14 14:07:50 +0000437 HUnlock(h);
438 ReleaseResource(h);
439 } else {
440 sprintf(buf, "Mac OS error code %d", err);
441 }
442 return buf;
443}
444
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000445/* Exception object shared by all Mac specific modules for Mac OS errors */
446PyObject *PyMac_OSErrException;
447
448/* Initialize and return PyMac_OSErrException */
449PyObject *
450PyMac_GetOSErrException()
451{
452 if (PyMac_OSErrException == NULL)
unknownf428aef2001-07-04 22:36:27 +0000453 PyMac_OSErrException = PyString_FromString("MacOS.Error");
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000454 return PyMac_OSErrException;
455}
456
Jack Jansenf93c72a1994-12-14 14:07:50 +0000457/* Set a MAC-specific error from errno, and return NULL; return None if no error */
458PyObject *
Guido van Rossumfffb8bb1995-01-12 12:37:24 +0000459PyErr_Mac(PyObject *eobj, int err)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000460{
461 char *msg;
462 PyObject *v;
Jack Jansenf93c72a1994-12-14 14:07:50 +0000463
Guido van Rossum8f691791995-01-18 23:57:26 +0000464 if (err == 0 && !PyErr_Occurred()) {
Jack Jansenf93c72a1994-12-14 14:07:50 +0000465 Py_INCREF(Py_None);
466 return Py_None;
467 }
Guido van Rossum8f691791995-01-18 23:57:26 +0000468 if (err == -1 && PyErr_Occurred())
469 return NULL;
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000470 msg = PyMac_StrError(err);
Jack Jansenf93c72a1994-12-14 14:07:50 +0000471 v = Py_BuildValue("(is)", err, msg);
472 PyErr_SetObject(eobj, v);
473 Py_DECREF(v);
474 return NULL;
475}
476
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000477/* Call PyErr_Mac with PyMac_OSErrException */
478PyObject *
479PyMac_Error(OSErr err)
480{
481 return PyErr_Mac(PyMac_GetOSErrException(), err);
482}
483
Jack Jansen1ed95291996-07-22 15:25:10 +0000484#ifdef USE_STACKCHECK
485/* Check for stack overflow */
486int
487PyOS_CheckStack()
488{
Jack Jansen14a91712000-08-25 21:57:23 +0000489 char here;
490 static char *sentinel = 0;
Jack Jansen53bafd92000-09-08 22:05:48 +0000491 static PyThreadState *thread_for_sentinel = 0;
Jack Jansen1ed95291996-07-22 15:25:10 +0000492
Jack Jansen340eb882001-02-02 22:40:28 +0000493 if ( sentinel == 0 ) {
494 unsigned long stackspace = StackSpace();
495
496#ifdef MAXIMUM_STACK_SIZE
497 /* See the comment at the definition */
498 if ( stackspace > MAXIMUM_STACK_SIZE )
499 stackspace = MAXIMUM_STACK_SIZE;
500#endif
501 sentinel = &here - stackspace + MINIMUM_STACK_SIZE;
Jack Jansen14a91712000-08-25 21:57:23 +0000502 }
Jack Jansen53bafd92000-09-08 22:05:48 +0000503 if ( thread_for_sentinel == 0 ) {
504 thread_for_sentinel = PyThreadState_Get();
505 }
506 if ( &here < sentinel ) {
507 if (thread_for_sentinel == PyThreadState_Get()) {
508 return -1;
509#if 0
510 } else {
511 /* Else we are unsure... */
512 fprintf(stderr, "Stackcheck in other thread (was %x now %x)\n", thread_for_sentinel,PyThreadState_Get());
513#endif
514 }
515 }
Jack Jansen1ed95291996-07-22 15:25:10 +0000516 return 0;
517}
518#endif /* USE_STACKCHECK */
519
Jack Jansen0194ad52001-05-12 22:46:35 +0000520#if !TARGET_API_MAC_OSX
Jack Jansenee23d6e1995-01-27 14:43:25 +0000521/* The catcher routine (which may not be used for all compilers) */
522static RETSIGTYPE
523intcatcher(sig)
524 int sig;
525{
526 interrupted = 1;
527 signal(SIGINT, intcatcher);
528}
529
530void
531PyOS_InitInterrupts()
532{
533 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
534 signal(SIGINT, intcatcher);
535}
536
Jack Jansena8441de1997-08-08 14:57:37 +0000537void
538PyOS_FiniInterrupts()
539{
540}
541
Jack Jansenee23d6e1995-01-27 14:43:25 +0000542/*
543** This routine scans the event queue looking for cmd-.
544** This is the only way to get an interrupt under THINK (since it
545** doesn't do SIGINT handling), but is also used under MW, when
546** the full-fledged event loop is disabled. This way, we can at least
547** interrupt a runaway python program.
548*/
549static void
550scan_event_queue(flush)
551 int flush;
552{
Jack Jansen6e68a7e2001-05-12 21:31:34 +0000553#if !TARGET_API_MAC_OS8
Jack Jansend7b68022001-01-12 23:42:28 +0000554 if ( CheckEventQueueForUserCancel() )
555 interrupted = 1;
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000556#else
Jack Jansenee23d6e1995-01-27 14:43:25 +0000557 register EvQElPtr q;
558
Jack Jansenefaada71998-02-20 16:03:15 +0000559 q = (EvQElPtr) LMGetEventQueue()->qHead;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000560
561 for (; q; q = (EvQElPtr)q->qLink) {
562 if (q->evtQWhat == keyDown &&
563 (char)q->evtQMessage == '.' &&
564 (q->evtQModifiers & cmdKey) != 0) {
565 if ( flush )
566 FlushEvents(keyDownMask, 0);
567 interrupted = 1;
568 break;
569 }
570 }
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000571#endif
Jack Jansenee23d6e1995-01-27 14:43:25 +0000572}
573
574int
Jack Jansen36ed5061997-06-20 16:18:15 +0000575PyErr_CheckSignals()
Jack Jansenee23d6e1995-01-27 14:43:25 +0000576{
Jack Jansene3ae0df1997-06-03 15:28:29 +0000577 if (schedparams.enabled) {
578 if ( (unsigned long)LMGetTicks() > schedparams.next_check ) {
Jack Jansen36ed5061997-06-20 16:18:15 +0000579 if ( PyMac_Yield() < 0)
580 return -1;
Jack Jansene3ae0df1997-06-03 15:28:29 +0000581 schedparams.next_check = (unsigned long)LMGetTicks()
582 + schedparams.check_interval;
583 if (interrupted) {
Jack Jansencaa7c461997-06-12 10:49:13 +0000584 scan_event_queue(1); /* Eat events up to cmd-. */
Jack Jansene3ae0df1997-06-03 15:28:29 +0000585 interrupted = 0;
Jack Jansen36ed5061997-06-20 16:18:15 +0000586 PyErr_SetNone(PyExc_KeyboardInterrupt);
587 return -1;
Jack Jansene3ae0df1997-06-03 15:28:29 +0000588 }
589 }
Jack Jansenee23d6e1995-01-27 14:43:25 +0000590 }
591 return 0;
592}
593
Jack Jansen36ed5061997-06-20 16:18:15 +0000594int
595PyOS_InterruptOccurred()
596{
597 scan_event_queue(1);
598 return interrupted;
599}
Jack Jansen0194ad52001-05-12 22:46:35 +0000600
Jack Jansenee23d6e1995-01-27 14:43:25 +0000601/* Check whether we are in the foreground */
Jack Jansen9ae898b2000-07-11 21:16:03 +0000602static int
603PyMac_InForeground(void)
Jack Jansenee23d6e1995-01-27 14:43:25 +0000604{
605 static ProcessSerialNumber ours;
606 static inited;
607 ProcessSerialNumber curfg;
608 Boolean eq;
609
Jack Jansene3ae0df1997-06-03 15:28:29 +0000610 if ( inited == 0 ) {
Jack Jansenee23d6e1995-01-27 14:43:25 +0000611 (void)GetCurrentProcess(&ours);
Jack Jansene3ae0df1997-06-03 15:28:29 +0000612 inited = 1;
613 }
Jack Jansenee23d6e1995-01-27 14:43:25 +0000614 if ( GetFrontProcess(&curfg) < 0 )
615 eq = 1;
616 else if ( SameProcess(&ours, &curfg, &eq) < 0 )
617 eq = 1;
618 return (int)eq;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000619}
Jack Jansen0194ad52001-05-12 22:46:35 +0000620#endif
Jack Jansenee23d6e1995-01-27 14:43:25 +0000621
Jack Jansen36ed5061997-06-20 16:18:15 +0000622int
623PyMac_SetEventHandler(PyObject *evh)
624{
625 if ( evh && python_event_handler ) {
626 PyErr_SetString(PyExc_RuntimeError, "Python event handler already set");
627 return 0;
628 }
629 if ( python_event_handler )
630 Py_DECREF(python_event_handler);
631 if ( evh )
632 Py_INCREF(evh);
633 python_event_handler = evh;
634 return 1;
635}
636
Jack Jansenf93c72a1994-12-14 14:07:50 +0000637/*
Jack Jansena76382a1995-02-02 14:25:56 +0000638** Handle an event, either one found in the mainloop eventhandler or
639** one passed back from the python program.
640*/
641void
Jack Jansen36ed5061997-06-20 16:18:15 +0000642PyMac_HandleEventIntern(evp)
Jack Jansena76382a1995-02-02 14:25:56 +0000643 EventRecord *evp;
644{
Jack Jansen6e68a7e2001-05-12 21:31:34 +0000645#if TARGET_API_MAC_OS8
Jack Jansen0c968871997-08-26 13:20:34 +0000646 if ( evp->what == mouseDown ) {
647 WindowPtr wp;
648
649 if ( FindWindow(evp->where, &wp) == inSysWindow ) {
650 SystemClick(evp, wp);
651 return;
652 }
653 }
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000654#endif
Jack Jansena76382a1995-02-02 14:25:56 +0000655#ifdef __MWERKS__
Jack Jansen38e97661995-11-10 14:53:00 +0000656 {
657 int siouxdidit;
658
659 /* If SIOUX wants it we're done */
660 siouxdidit = SIOUXHandleOneEvent(evp);
661 if ( siouxdidit )
662 return;
663 }
Jack Jansena76382a1995-02-02 14:25:56 +0000664#else
Jack Jansen0c968871997-08-26 13:20:34 +0000665 /* Other compilers are just unlucky... */
Jack Jansena76382a1995-02-02 14:25:56 +0000666#endif /* !__MWERKS__ */
Jack Jansen36ed5061997-06-20 16:18:15 +0000667}
668
669/*
670** Handle an event, either through HandleEvent or by passing it to the Python
671** event handler.
672*/
673int
674PyMac_HandleEvent(evp)
675 EventRecord *evp;
676{
677 PyObject *rv;
678
679 if ( python_event_handler ) {
680 rv = PyObject_CallFunction(python_event_handler, "(O&)",
681 PyMac_BuildEventRecord, evp);
682 if ( rv )
683 Py_DECREF(rv);
684 else
685 return -1; /* Propagate exception */
686 } else {
687 PyMac_HandleEventIntern(evp);
688 }
689 return 0;
Jack Jansena76382a1995-02-02 14:25:56 +0000690}
691
Jack Jansen0194ad52001-05-12 22:46:35 +0000692#if !TARGET_API_MAC_OSX
Jack Jansena76382a1995-02-02 14:25:56 +0000693/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000694** Yield the CPU to other tasks without processing events.
Jack Jansene8e8ae01995-01-26 16:36:45 +0000695*/
Jack Jansen2d1306b2000-04-07 09:10:49 +0000696int
Jack Jansene3ae0df1997-06-03 15:28:29 +0000697PyMac_DoYield(int maxsleep, int maycallpython)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000698{
699 EventRecord ev;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000700 int gotone;
Jack Jansene3ae0df1997-06-03 15:28:29 +0000701 long latest_time_ready;
Jack Jansen36ed5061997-06-20 16:18:15 +0000702 static int in_here = 0;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000703
Jack Jansen36ed5061997-06-20 16:18:15 +0000704 in_here++;
Jack Jansene3ae0df1997-06-03 15:28:29 +0000705 /*
706 ** First check for interrupts, if wanted.
707 ** This sets a flag that will be picked up at an appropriate
708 ** moment in the mainloop.
709 */
710 if (schedparams.check_interrupt)
Jack Jansenee23d6e1995-01-27 14:43:25 +0000711 scan_event_queue(0);
Jack Jansene3ae0df1997-06-03 15:28:29 +0000712
713 /* XXXX Implementing an idle routine goes here */
Jack Jansene8e8ae01995-01-26 16:36:45 +0000714
Jack Jansene3ae0df1997-06-03 15:28:29 +0000715 /*
716 ** Check which of the eventloop cases we have:
717 ** - process events
718 ** - don't process events but do yield
719 ** - do neither
720 */
Jack Jansen36ed5061997-06-20 16:18:15 +0000721 if( in_here > 1 || !schedparams.process_events ||
722 (python_event_handler && !maycallpython) ) {
Jack Jansene3ae0df1997-06-03 15:28:29 +0000723 if ( maxsleep >= 0 ) {
Jack Jansen6e68a7e2001-05-12 21:31:34 +0000724#if TARGET_API_MAC_OS8
Jack Jansene8e8ae01995-01-26 16:36:45 +0000725 SystemTask();
Jack Jansen15f1c082001-04-25 22:07:27 +0000726#else
727 int xxx = 0;
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000728#endif
Jack Jansen15f1c082001-04-25 22:07:27 +0000729 }
Jack Jansene3ae0df1997-06-03 15:28:29 +0000730 } else {
731 latest_time_ready = LMGetTicks() + maxsleep;
Jack Jansen2d1306b2000-04-07 09:10:49 +0000732 do {
Jack Jansen0c968871997-08-26 13:20:34 +0000733 /* XXXX Hack by Jack.
734 ** In time.sleep() you can click to another application
735 ** once only. If you come back to Python you cannot get away
736 ** again.
737 **/
Jack Jansen36ed5061997-06-20 16:18:15 +0000738 gotone = WaitNextEvent(schedparams.process_events, &ev, maxsleep, NULL);
Jack Jansene3ae0df1997-06-03 15:28:29 +0000739 /* Get out quickly if nothing interesting is happening */
740 if ( !gotone || ev.what == nullEvent )
741 break;
Jack Jansen36ed5061997-06-20 16:18:15 +0000742 if ( PyMac_HandleEvent(&ev) < 0 ) {
743 in_here--;
744 return -1;
745 }
Jack Jansene3ae0df1997-06-03 15:28:29 +0000746 maxsleep = latest_time_ready - LMGetTicks();
Jack Jansen2d1306b2000-04-07 09:10:49 +0000747 } while ( maxsleep > 0 );
Jack Jansenf93c72a1994-12-14 14:07:50 +0000748 }
Jack Jansen36ed5061997-06-20 16:18:15 +0000749 in_here--;
750 return 0;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000751}
752
753/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000754** Process events and/or yield the CPU to other tasks if opportune
Jack Jansene8e8ae01995-01-26 16:36:45 +0000755*/
Jack Jansen36ed5061997-06-20 16:18:15 +0000756int
Jack Jansene8e8ae01995-01-26 16:36:45 +0000757PyMac_Yield() {
Jack Jansene3ae0df1997-06-03 15:28:29 +0000758 unsigned long maxsleep;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000759
Jack Jansene3ae0df1997-06-03 15:28:29 +0000760 if( PyMac_InForeground() )
761 maxsleep = 0;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000762 else
Jack Jansene3ae0df1997-06-03 15:28:29 +0000763 maxsleep = schedparams.bg_yield;
764
Jack Jansen36ed5061997-06-20 16:18:15 +0000765 return PyMac_DoYield(maxsleep, 1);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000766}
767
768/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000769** Return current scheduler parameters
Jack Jansene8e8ae01995-01-26 16:36:45 +0000770*/
Jack Jansene3ae0df1997-06-03 15:28:29 +0000771void
772PyMac_GetSchedParams(PyMacSchedParams *sp)
Jack Jansene8e8ae01995-01-26 16:36:45 +0000773{
Jack Jansene3ae0df1997-06-03 15:28:29 +0000774 sp->check_interrupt = schedparams.check_interrupt;
775 sp->process_events = schedparams.process_events;
776 sp->besocial = schedparams.besocial;
777 sp->check_interval = schedparams.check_interval / 60.0;
778 sp->bg_yield = schedparams.bg_yield / 60.0;
Jack Jansenf93c72a1994-12-14 14:07:50 +0000779}
Jack Jansenf6865f71996-09-04 15:24:59 +0000780
Jack Jansen74162f31995-02-15 22:58:33 +0000781/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000782** Set current scheduler parameters
783*/
784void
785PyMac_SetSchedParams(PyMacSchedParams *sp)
786{
787 schedparams.check_interrupt = sp->check_interrupt;
788 schedparams.process_events = sp->process_events;
789 schedparams.besocial = sp->besocial;
790 schedparams.check_interval = (unsigned long)(sp->check_interval*60);
791 schedparams.bg_yield = (unsigned long)(sp->bg_yield*60);
792 if ( schedparams.check_interrupt || schedparams.process_events ||
793 schedparams.besocial )
794 schedparams.enabled = 1;
795 else
796 schedparams.enabled = 0;
797 schedparams.next_check = 0; /* Check immedeately */
798}
Jack Jansencaa7c461997-06-12 10:49:13 +0000799
Jack Jansene3ae0df1997-06-03 15:28:29 +0000800/*
Jack Jansen3469e991996-09-06 00:30:45 +0000801** Install our menu bar.
802*/
803void
804PyMac_InitMenuBar()
805{
Jack Jansen3469e991996-09-06 00:30:45 +0000806 MenuHandle applemenu;
807
Jack Jansen15f1c082001-04-25 22:07:27 +0000808 if ( sioux_mbar ) return;
Jack Jansencaa7c461997-06-12 10:49:13 +0000809 if ( (sioux_mbar=GetMenuBar()) == NULL ) {
810 /* Sioux menu not installed yet. Do so */
811 SIOUXSetupMenus();
812 if ( (sioux_mbar=GetMenuBar()) == NULL )
813 return;
814 }
Jack Jansen08c3be31997-04-08 15:27:00 +0000815 if ( (applemenu=GetMenuHandle(SIOUX_APPLEID)) == NULL ) return;
Jack Jansen3469e991996-09-06 00:30:45 +0000816 SetMenuItemText(applemenu, 1, "\pAbout Python...");
817}
818
819/*
Jack Jansencaa7c461997-06-12 10:49:13 +0000820** Restore sioux menu bar
821*/
822void
823PyMac_RestoreMenuBar()
824{
Jack Jansen15f1c082001-04-25 22:07:27 +0000825#if 1
Jack Jansen657ba272001-02-17 22:02:07 +0000826 /* This doesn't seem to work anymore? Or only for Carbon? */
827 MenuBarHandle curmenubar;
828
829 curmenubar = GetMenuBar();
Jack Janseneda78631997-06-12 15:29:46 +0000830 if ( sioux_mbar ) {
Jack Jansencaa7c461997-06-12 10:49:13 +0000831 SetMenuBar(sioux_mbar);
Jack Janseneda78631997-06-12 15:29:46 +0000832 DrawMenuBar();
Jack Jansen657ba272001-02-17 22:02:07 +0000833 } else {
Jack Jansenefaada71998-02-20 16:03:15 +0000834 PyMac_InitMenuBar();
Jack Jansen657ba272001-02-17 22:02:07 +0000835 DrawMenuBar();
836 }
837#endif
Jack Jansencaa7c461997-06-12 10:49:13 +0000838}
839
Jack Jansen15f1c082001-04-25 22:07:27 +0000840void
841PyMac_RaiseConsoleWindow()
842{
843 /* Note: this is a hack. SIOUXTextWindow is SIOUX's internal structure
844 ** and we happen to know that the first entry is the window pointer.
845 */
846 extern WindowRef *SIOUXTextWindow;
847
848 if ( SIOUXTextWindow == NULL || *SIOUXTextWindow == NULL )
849 return;
850 if ( FrontWindow() != *SIOUXTextWindow )
851 BringToFront(*SIOUXTextWindow);
852}
Jack Jansencaa7c461997-06-12 10:49:13 +0000853
854/*
Jack Jansen3469e991996-09-06 00:30:45 +0000855** Our replacement about box
856*/
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000857
858#include "patchlevel.h"
859
Jack Jansen3469e991996-09-06 00:30:45 +0000860void
861SIOUXDoAboutBox(void)
862{
863 DialogPtr theDialog;
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000864 WindowPtr theWindow;
Jack Jansen3469e991996-09-06 00:30:45 +0000865 short item;
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000866 short fontID;
Jack Jansen3469e991996-09-06 00:30:45 +0000867
868 if( (theDialog = GetNewDialog(ABOUT_ID, NULL, (WindowPtr)-1)) == NULL )
869 return;
Jack Jansend617c571996-09-22 22:14:30 +0000870 theWindow = GetDialogWindow(theDialog);
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000871 SetPortWindowPort(theWindow);
872 GetFNum("\pPython-Sans", &fontID);
873 if (fontID == 0)
874 fontID = kFontIDGeneva;
875 TextFont(fontID);
876 TextSize(9);
877 ParamText(Pstring(PATCHLEVEL), "\p", "\p", "\p");
Jack Jansend617c571996-09-22 22:14:30 +0000878 ShowWindow(theWindow);
Jack Jansen3469e991996-09-06 00:30:45 +0000879 ModalDialog(NULL, &item);
880 DisposeDialog(theDialog);
881}
882
Jack Jansen0194ad52001-05-12 22:46:35 +0000883#endif /* !TARGET_API_MAC_OSX */
Jack Janseneda78631997-06-12 15:29:46 +0000884
Jack Jansen0194ad52001-05-12 22:46:35 +0000885#if TARGET_API_MAC_OS8
Jack Janseneda78631997-06-12 15:29:46 +0000886/*
Jack Jansen3ec804a1995-02-20 15:56:10 +0000887** Helper routine for GetDirectory
888*/
Guido van Rossum24a45e31995-02-20 23:45:53 +0000889static pascal short
Jack Jansen819f1771995-08-14 12:35:10 +0000890myhook_proc(short item, DialogPtr theDialog, struct hook_args *dataptr)
Jack Jansen3ec804a1995-02-20 15:56:10 +0000891{
Jack Jansen819f1771995-08-14 12:35:10 +0000892 if ( item == sfHookFirstCall && dataptr->prompt) {
893 Handle prompth;
894 short type;
895 Rect rect;
896
897 GetDialogItem(theDialog, PROMPT_ITEM, &type, &prompth, &rect);
898 if ( prompth )
899 SetDialogItemText(prompth, (unsigned char *)dataptr->prompt);
900 } else
Jack Jansen3ec804a1995-02-20 15:56:10 +0000901 if ( item == SELECTCUR_ITEM ) {
902 item = sfItemCancelButton;
Jack Jansen819f1771995-08-14 12:35:10 +0000903 dataptr->selectcur_hit = 1;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000904 }
905 return item;
906}
Jack Jansen0194ad52001-05-12 22:46:35 +0000907
Jack Jansen3ec804a1995-02-20 15:56:10 +0000908/*
909** Ask the user for a directory. I still can't understand
910** why Apple doesn't provide a standard solution for this...
911*/
912int
Jack Jansen819f1771995-08-14 12:35:10 +0000913PyMac_GetDirectory(dirfss, prompt)
Jack Jansen3ec804a1995-02-20 15:56:10 +0000914 FSSpec *dirfss;
Jack Jansen819f1771995-08-14 12:35:10 +0000915 char *prompt;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000916{
917 static SFTypeList list = {'fldr', 0, 0, 0};
918 static Point where = {-1, -1};
Jack Jansen3ec804a1995-02-20 15:56:10 +0000919 StandardFileReply reply;
Jack Jansen819f1771995-08-14 12:35:10 +0000920 struct hook_args hook_args;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000921
922 if ( !upp_inited ) {
923 myhook_upp = NewDlgHookYDProc(myhook_proc);
924 upp_inited = 1;
925 }
Jack Jansen819f1771995-08-14 12:35:10 +0000926 if ( prompt && *prompt )
927 hook_args.prompt = (char *)Pstring(prompt);
928 else
929 hook_args.prompt = NULL;
930 hook_args.selectcur_hit = 0;
Guido van Rossum24a45e31995-02-20 23:45:53 +0000931 CustomGetFile((FileFilterYDUPP)0, 1, list, &reply, GETDIR_ID, where, myhook_upp,
Jack Jansen819f1771995-08-14 12:35:10 +0000932 NULL, NULL, NULL, (void *)&hook_args);
Jack Jansen3ec804a1995-02-20 15:56:10 +0000933
934 reply.sfFile.name[0] = 0;
935 if( FSMakeFSSpec(reply.sfFile.vRefNum, reply.sfFile.parID, reply.sfFile.name, dirfss) )
936 return 0;
Jack Jansen819f1771995-08-14 12:35:10 +0000937 return hook_args.selectcur_hit;
938}
939
940/*
941** Slightly extended StandardGetFile: accepts a prompt */
942void PyMac_PromptGetFile(short numTypes, ConstSFTypeListPtr typeList,
943 StandardFileReply *reply, char *prompt)
944{
945 static Point where = {-1, -1};
946 struct hook_args hook_args;
947
948 if ( !upp_inited ) {
949 myhook_upp = NewDlgHookYDProc(myhook_proc);
950 upp_inited = 1;
951 }
952 if ( prompt && *prompt )
953 hook_args.prompt = (char *)Pstring(prompt);
954 else
955 hook_args.prompt = NULL;
956 hook_args.selectcur_hit = 0;
957 CustomGetFile((FileFilterYDUPP)0, numTypes, typeList, reply, GETFILEPROMPT_ID, where,
958 myhook_upp, NULL, NULL, NULL, (void *)&hook_args);
Jack Jansen3ec804a1995-02-20 15:56:10 +0000959}
Jack Jansen6e68a7e2001-05-12 21:31:34 +0000960#endif /* TARGET_API_MAC_OS8 */
Jack Jansen5f653091995-01-18 13:53:49 +0000961
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000962/* Convert a 4-char string object argument to an OSType value */
Jack Jansen5f653091995-01-18 13:53:49 +0000963int
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000964PyMac_GetOSType(PyObject *v, OSType *pr)
Jack Jansen5f653091995-01-18 13:53:49 +0000965{
966 if (!PyString_Check(v) || PyString_Size(v) != 4) {
967 PyErr_SetString(PyExc_TypeError,
968 "OSType arg must be string of 4 chars");
969 return 0;
970 }
971 memcpy((char *)pr, PyString_AsString(v), 4);
972 return 1;
973}
974
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000975/* Convert an OSType value to a 4-char string object */
976PyObject *
977PyMac_BuildOSType(OSType t)
978{
979 return PyString_FromStringAndSize((char *)&t, 4);
980}
981
Jack Jansend1f06311996-08-01 15:23:54 +0000982/* Convert an NumVersion value to a 4-element tuple */
983PyObject *
984PyMac_BuildNumVersion(NumVersion t)
985{
986 return Py_BuildValue("(hhhh)", t.majorRev, t.minorAndBugRev, t.stage, t.nonRelRev);
987}
988
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000989
990/* Convert a Python string object to a Str255 */
Jack Jansen5f653091995-01-18 13:53:49 +0000991int
Guido van Rossum8f691791995-01-18 23:57:26 +0000992PyMac_GetStr255(PyObject *v, Str255 pbuf)
Jack Jansen5f653091995-01-18 13:53:49 +0000993{
994 int len;
995 if (!PyString_Check(v) || (len = PyString_Size(v)) > 255) {
996 PyErr_SetString(PyExc_TypeError,
997 "Str255 arg must be string of at most 255 chars");
998 return 0;
999 }
1000 pbuf[0] = len;
1001 memcpy((char *)(pbuf+1), PyString_AsString(v), len);
1002 return 1;
1003}
1004
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001005/* Convert a Str255 to a Python string object */
1006PyObject *
1007PyMac_BuildStr255(Str255 s)
1008{
Jack Jansenb734ade1999-12-17 17:15:50 +00001009 if ( s == NULL ) {
1010 PyErr_SetString(PyExc_SystemError, "Str255 pointer is NULL");
1011 return NULL;
1012 }
1013 return PyString_FromStringAndSize((char *)&s[1], (int)s[0]);
1014}
1015
1016PyObject *
1017PyMac_BuildOptStr255(Str255 s)
1018{
1019 if ( s == NULL ) {
1020 Py_INCREF(Py_None);
1021 return Py_None;
1022 }
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001023 return PyString_FromStringAndSize((char *)&s[1], (int)s[0]);
1024}
1025
1026
Guido van Rossum8f691791995-01-18 23:57:26 +00001027
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001028/* Convert a Python object to a Rect.
Guido van Rossum5279ec61995-01-26 22:56:59 +00001029 The object must be a (left, top, right, bottom) tuple.
1030 (This differs from the order in the struct but is consistent with
1031 the arguments to SetRect(), and also with STDWIN). */
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001032int
1033PyMac_GetRect(PyObject *v, Rect *r)
Guido van Rossum8f691791995-01-18 23:57:26 +00001034{
Guido van Rossum5279ec61995-01-26 22:56:59 +00001035 return PyArg_Parse(v, "(hhhh)", &r->left, &r->top, &r->right, &r->bottom);
Guido van Rossum8f691791995-01-18 23:57:26 +00001036}
Guido van Rossumb3404661995-01-22 18:36:13 +00001037
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001038/* Convert a Rect to a Python object */
Guido van Rossumb3404661995-01-22 18:36:13 +00001039PyObject *
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001040PyMac_BuildRect(Rect *r)
Guido van Rossumb3404661995-01-22 18:36:13 +00001041{
Guido van Rossum5279ec61995-01-26 22:56:59 +00001042 return Py_BuildValue("(hhhh)", r->left, r->top, r->right, r->bottom);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001043}
1044
1045
1046/* Convert a Python object to a Point.
Guido van Rossum5279ec61995-01-26 22:56:59 +00001047 The object must be a (h, v) tuple.
1048 (This differs from the order in the struct but is consistent with
1049 the arguments to SetPoint(), and also with STDWIN). */
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001050int
1051PyMac_GetPoint(PyObject *v, Point *p)
1052{
Guido van Rossum5279ec61995-01-26 22:56:59 +00001053 return PyArg_Parse(v, "(hh)", &p->h, &p->v);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001054}
1055
1056/* Convert a Point to a Python object */
1057PyObject *
1058PyMac_BuildPoint(Point p)
1059{
Guido van Rossum5279ec61995-01-26 22:56:59 +00001060 return Py_BuildValue("(hh)", p.h, p.v);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001061}
1062
1063
1064/* Convert a Python object to an EventRecord.
1065 The object must be a (what, message, when, (v, h), modifiers) tuple. */
1066int
1067PyMac_GetEventRecord(PyObject *v, EventRecord *e)
1068{
Jack Jansen2c278ed2001-07-12 21:48:10 +00001069 return PyArg_Parse(v, "(Hll(hh)H)",
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001070 &e->what,
1071 &e->message,
1072 &e->when,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001073 &e->where.h,
Guido van Rossum5279ec61995-01-26 22:56:59 +00001074 &e->where.v,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001075 &e->modifiers);
1076}
1077
1078/* Convert a Rect to an EventRecord object */
1079PyObject *
1080PyMac_BuildEventRecord(EventRecord *e)
1081{
1082 return Py_BuildValue("(hll(hh)h)",
1083 e->what,
1084 e->message,
1085 e->when,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001086 e->where.h,
Guido van Rossum5279ec61995-01-26 22:56:59 +00001087 e->where.v,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001088 e->modifiers);
Guido van Rossumb3404661995-01-22 18:36:13 +00001089}
Jack Jansenfa4d5d01995-11-15 15:19:29 +00001090
1091/* Convert Python object to Fixed */
1092int
1093PyMac_GetFixed(PyObject *v, Fixed *f)
1094{
1095 double d;
1096
1097 if( !PyArg_Parse(v, "d", &d))
1098 return 0;
1099 *f = (Fixed)(d * 0x10000);
Jack Jansen31dd5c01996-05-31 13:01:39 +00001100 return 1;
Jack Jansenfa4d5d01995-11-15 15:19:29 +00001101}
1102
1103/* Convert a Point to a Python object */
1104PyObject *
1105PyMac_BuildFixed(Fixed f)
1106{
1107 double d;
1108
1109 d = f;
1110 d = d / 0x10000;
1111 return Py_BuildValue("d", d);
1112}
1113
Jack Jansend58cd631998-04-21 15:24:39 +00001114/* Convert wide to/from Python int or (hi, lo) tuple. XXXX Should use Python longs */
1115int
1116PyMac_Getwide(PyObject *v, wide *rv)
1117{
1118 if (PyInt_Check(v)) {
1119 rv->hi = 0;
1120 rv->lo = PyInt_AsLong(v);
1121 if( rv->lo & 0x80000000 )
1122 rv->hi = -1;
1123 return 1;
1124 }
1125 return PyArg_Parse(v, "(ll)", &rv->hi, &rv->lo);
1126}
1127
1128
1129PyObject *
Jack Jansenbbf4be21998-04-23 13:20:17 +00001130PyMac_Buildwide(wide *w)
Jack Jansend58cd631998-04-21 15:24:39 +00001131{
Jack Jansenbbf4be21998-04-23 13:20:17 +00001132 if ( (w->hi == 0 && (w->lo & 0x80000000) == 0) ||
1133 (w->hi == -1 && (w->lo & 0x80000000) ) )
1134 return PyInt_FromLong(w->lo);
1135 return Py_BuildValue("(ll)", w->hi, w->lo);
Jack Jansend58cd631998-04-21 15:24:39 +00001136}
Jack Jansen8bb1dc12001-05-19 12:31:09 +00001137
1138#ifdef USE_TOOLBOX_OBJECT_GLUE
1139/*
1140** Glue together the toolbox objects.
1141**
1142** Because toolbox modules interdepend on each other, they use each others
1143** object types, on MacOSX/MachO this leads to the situation that they
1144** cannot be dynamically loaded (or they would all have to be lumped into
1145** a single .so, but this would be bad for extensibility).
1146**
1147** This file defines wrappers for all the _New and _Convert functions,
1148** which are the Py_BuildValue and PyArg_ParseTuple helpers. The wrappers
1149** check an indirection function pointer, and if it isn't filled in yet
1150** they import the appropriate module, whose init routine should fill in
1151** the pointer.
1152*/
1153
1154#define GLUE_NEW(object, routinename, module) \
1155PyObject *(*PyMacGluePtr_##routinename)(object); \
1156\
1157PyObject *routinename(object cobj) { \
1158 if (!PyMacGluePtr_##routinename) { \
1159 if (!PyImport_ImportModule(module)) return NULL; \
1160 if (!PyMacGluePtr_##routinename) { \
1161 PyErr_SetString(PyExc_ImportError, "Module did not provide routine: " module ": " #routinename); \
1162 return NULL; \
1163 } \
1164 } \
1165 return (*PyMacGluePtr_##routinename)(cobj); \
1166}
1167
1168#define GLUE_CONVERT(object, routinename, module) \
1169int (*PyMacGluePtr_##routinename)(PyObject *, object *); \
1170\
1171int routinename(PyObject *pyobj, object *cobj) { \
1172 if (!PyMacGluePtr_##routinename) { \
1173 if (!PyImport_ImportModule(module)) return NULL; \
1174 if (!PyMacGluePtr_##routinename) { \
1175 PyErr_SetString(PyExc_ImportError, "Module did not provide routine: " module ": " #routinename); \
1176 return NULL; \
1177 } \
1178 } \
1179 return (*PyMacGluePtr_##routinename)(pyobj, cobj); \
1180}
Jack Jansena5bca572001-08-03 15:39:27 +00001181GLUE_CONVERT(FSSpec, PyMac_GetFSSpec, "macfs")
Jack Jansen8bb1dc12001-05-19 12:31:09 +00001182
1183GLUE_NEW(AppleEvent *, AEDesc_New, "AE") /* XXXX Why by address? */
1184GLUE_CONVERT(AppleEvent, AEDesc_Convert, "AE")
1185
1186GLUE_NEW(Component, CmpObj_New, "Cm")
1187GLUE_CONVERT(Component, CmpObj_Convert, "Cm")
1188GLUE_NEW(ComponentInstance, CmpInstObj_New, "Cm")
1189GLUE_CONVERT(ComponentInstance, CmpInstObj_Convert, "Cm")
1190
1191GLUE_NEW(ControlHandle, CtlObj_New, "Ctl")
1192GLUE_CONVERT(ControlHandle, CtlObj_Convert, "Ctl")
1193
1194GLUE_NEW(DialogPtr, DlgObj_New, "Dlg")
1195GLUE_CONVERT(DialogPtr, DlgObj_Convert, "Dlg")
1196GLUE_NEW(DialogPtr, DlgObj_WhichDialog, "Dlg")
1197
1198GLUE_NEW(DragReference, DragObj_New, "Drag")
1199GLUE_CONVERT(DragReference, DragObj_Convert, "Drag")
1200
1201GLUE_NEW(ListHandle, ListObj_New, "List")
1202GLUE_CONVERT(ListHandle, ListObj_Convert, "List")
1203
1204GLUE_NEW(MenuHandle, MenuObj_New, "Menu")
1205GLUE_CONVERT(MenuHandle, MenuObj_Convert, "Menu")
1206
1207GLUE_NEW(GrafPtr, GrafObj_New, "Qd")
1208GLUE_CONVERT(GrafPtr, GrafObj_Convert, "Qd")
1209GLUE_NEW(BitMapPtr, BMObj_New, "Qd")
1210GLUE_CONVERT(BitMapPtr, BMObj_Convert, "Qd")
1211GLUE_NEW(RGBColor *, QdRGB_New, "Qd") /* XXXX Why? */
1212GLUE_CONVERT(RGBColor, QdRGB_Convert, "Qd")
1213
1214GLUE_NEW(GWorldPtr, GWorldObj_New, "Qdoffs")
1215GLUE_CONVERT(GWorldPtr, GWorldObj_Convert, "Qdoffs")
1216
1217GLUE_NEW(Track, TrackObj_New, "Qt")
1218GLUE_CONVERT(Track, TrackObj_Convert, "Qt")
1219GLUE_NEW(Movie, MovieObj_New, "Qt")
1220GLUE_CONVERT(Movie, MovieObj_Convert, "Qt")
1221GLUE_NEW(MovieController, MovieCtlObj_New, "Qt")
1222GLUE_CONVERT(MovieController, MovieCtlObj_Convert, "Qt")
1223GLUE_NEW(TimeBase, TimeBaseObj_New, "Qt")
1224GLUE_CONVERT(TimeBase, TimeBaseObj_Convert, "Qt")
1225GLUE_NEW(UserData, UserDataObj_New, "Qt")
1226GLUE_CONVERT(UserData, UserDataObj_Convert, "Qt")
1227GLUE_NEW(Media, MediaObj_New, "Qt")
1228GLUE_CONVERT(Media, MediaObj_Convert, "Qt")
1229
1230GLUE_NEW(Handle, ResObj_New, "Res")
1231GLUE_CONVERT(Handle, ResObj_Convert, "Res")
1232GLUE_NEW(Handle, OptResObj_New, "Res")
1233GLUE_CONVERT(Handle, OptResObj_Convert, "Res")
1234
1235GLUE_NEW(TEHandle, TEObj_New, "TE")
1236GLUE_CONVERT(TEHandle, TEObj_Convert, "TE")
1237
1238GLUE_NEW(WindowPtr, WinObj_New, "Win")
1239GLUE_CONVERT(WindowPtr, WinObj_Convert, "Win")
1240GLUE_NEW(WindowPtr, WinObj_WhichWindow, "Win")
1241
1242#endif /* USE_TOOLBOX_OBJECT_GLUE */