blob: 5579735b1a9a0ed73b15b5971f36ca3d4badb9da [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#ifdef __CFM68K__
26/* cfm68k InterfaceLib exports GetEventQueue, but Events.h doesn't know this
27** and defines it as GetEvQHdr (which is correct for PPC). This fix is for
28** CW9, check that the workaround is still needed for the next release.
29*/
30#define GetEvQHdr GetEventQueue
31#endif /* __CFM68K__ */
32
33#include <Events.h>
34
Jack Jansen74a1e632000-07-14 22:37:27 +000035#if TARGET_API_MAC_CARBON
Jack Jansenbb6d83a2000-06-02 21:27:11 +000036/* Unfortunately this call is probably slower... */
37#define LMGetTicks() TickCount()
38#endif
39
Jack Jansenbf05d4c1996-08-19 15:11:45 +000040#ifdef __CFM68K__
41#undef GetEventQueue
42#endif /* __CFM68K__ */
43
Jack Jansenf93c72a1994-12-14 14:07:50 +000044#include "Python.h"
Guido van Rossumbecdbec1995-02-14 01:27:24 +000045
Jack Jansenf93c72a1994-12-14 14:07:50 +000046#include "macglue.h"
Jack Jansen74162f31995-02-15 22:58:33 +000047#include "marshal.h"
48#include "import.h"
Jack Janseneda78631997-06-12 15:29:46 +000049#include "importdl.h"
Jack Jansenf93c72a1994-12-14 14:07:50 +000050
Jack Jansen819f1771995-08-14 12:35:10 +000051#include "pythonresources.h"
52
Jack Jansenf93c72a1994-12-14 14:07:50 +000053#include <OSUtils.h> /* for Set(Current)A5 */
Jack Jansene8e8ae01995-01-26 16:36:45 +000054#include <Files.h>
Jack Jansen8cd2b721995-02-13 11:33:28 +000055#include <StandardFile.h>
Jack Jansenf93c72a1994-12-14 14:07:50 +000056#include <Resources.h>
57#include <Memory.h>
Jack Jansenf93c72a1994-12-14 14:07:50 +000058#include <Windows.h>
Jack Jansene8e8ae01995-01-26 16:36:45 +000059#include <Traps.h>
Jack Jansenee23d6e1995-01-27 14:43:25 +000060#include <Processes.h>
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +000061#include <Fonts.h>
62#include <Menus.h>
Jack Jansen08305501995-06-18 20:03:40 +000063#include <TextUtils.h>
Jack Jansen16df2aa1995-02-27 16:17:28 +000064#ifdef __MWERKS__
65#include <SIOUX.h>
Jack Jansen9ae898b2000-07-11 21:16:03 +000066extern void SIOUXSetupMenus(void);
67extern void SIOUXDoAboutBox(void);
Jack Jansen16df2aa1995-02-27 16:17:28 +000068#endif
Jack Jansen9ae898b2000-07-11 21:16:03 +000069#ifdef USE_GUSI
70/* Functions we redefine because they're in obscure libraries */
71extern void SpinCursor(short x);
72extern void RotateCursor(short x);
73extern pascal void PLstrcpy(unsigned char *, unsigned char *);
74extern pascal int PLstrcmp(unsigned char *, unsigned char *);
75extern pascal unsigned char *PLstrrchr(unsigned char *, unsigned char);
76
77#endif
78
Jack Jansen2d1306b2000-04-07 09:10:49 +000079#ifdef USE_GUSI1
Jack Jansen911ad6b1996-03-05 16:56:24 +000080#include <TFileSpec.h> /* For Path2FSSpec */
Jack Jansenf6865f71996-09-04 15:24:59 +000081#include <GUSI.h>
Jack Jansen911ad6b1996-03-05 16:56:24 +000082#endif
Jack Jansen2d1306b2000-04-07 09:10:49 +000083#include <LowMem.h>
Jack Jansenee23d6e1995-01-27 14:43:25 +000084
Jack Jansen3469e991996-09-06 00:30:45 +000085/* The ID of the Sioux apple menu */
86#define SIOUX_APPLEID 32000
87
Jack Jansenee23d6e1995-01-27 14:43:25 +000088#include <signal.h>
Jack Jansen74162f31995-02-15 22:58:33 +000089#include <stdio.h>
Jack Jansene8e8ae01995-01-26 16:36:45 +000090
Jack Jansenee23d6e1995-01-27 14:43:25 +000091/*
Jack Jansend1f06311996-08-01 15:23:54 +000092** When less than this amount of stackspace is left we
93** raise a MemoryError.
94*/
95#ifndef MINIMUM_STACK_SIZE
96#ifdef __powerc
97#define MINIMUM_STACK_SIZE 8192
98#else
99#define MINIMUM_STACK_SIZE 4096
100#endif
101#endif
102
Jack Jansen340eb882001-02-02 22:40:28 +0000103#if TARGET_API_MAC_CARBON
104/*
105** On MacOSX StackSpace() lies: it gives the distance from heap end to stack pointer,
106** but the stack cannot grow that far due to rlimit values. We cannot get at this value
107** from Carbon, so we set a maximum to the stack here that is based on the default
108** stack limit of 512K.
109*/
110#define MAXIMUM_STACK_SIZE (256*1024)
111#endif
112
Jack Jansend1f06311996-08-01 15:23:54 +0000113/*
Jack Jansen16df2aa1995-02-27 16:17:28 +0000114** We have to be careful, since we can't handle
Jack Jansenee23d6e1995-01-27 14:43:25 +0000115** things like updates (and they'll keep coming back if we don't
Jack Jansen16df2aa1995-02-27 16:17:28 +0000116** handle them). Note that we don't know who has windows open, so
117** even handing updates off to SIOUX under MW isn't going to work.
Jack Jansenee23d6e1995-01-27 14:43:25 +0000118*/
Jack Jansen0c968871997-08-26 13:20:34 +0000119#define MAINLOOP_EVENTMASK (mDownMask|keyDownMask|osMask|activMask)
Jack Jansene8e8ae01995-01-26 16:36:45 +0000120
121#include <signal.h>
Jack Jansenf93c72a1994-12-14 14:07:50 +0000122
Guido van Rossumb3404661995-01-22 18:36:13 +0000123/* XXX We should include Errors.h here, but it has a name conflict
Jack Jansen5f653091995-01-18 13:53:49 +0000124** with the python errors.h. */
125#define fnfErr -43
126
Jack Jansene8e8ae01995-01-26 16:36:45 +0000127/* Declared in macfsmodule.c: */
Jack Jansen9ae898b2000-07-11 21:16:03 +0000128extern FSSpec *mfs_GetFSSpecFSSpec(PyObject *);
Jack Jansend88296d2000-07-11 19:51:05 +0000129extern PyObject *newmfssobject(FSSpec *);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000130
Jack Jansenee23d6e1995-01-27 14:43:25 +0000131/* Interrupt code variables: */
132static int interrupted; /* Set to true when cmd-. seen */
Jack Jansend88296d2000-07-11 19:51:05 +0000133static RETSIGTYPE intcatcher(int);
Jack Jansenee23d6e1995-01-27 14:43:25 +0000134
Jack Jansend88296d2000-07-11 19:51:05 +0000135static int PyMac_Yield(void);
Jack Jansenf6865f71996-09-04 15:24:59 +0000136
Jack Jansene8e8ae01995-01-26 16:36:45 +0000137/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000138** These are the real scheduling parameters that control what we check
139** in the event loop, and how often we check. The values are initialized
140** from pyMac_SchedParamStruct.
141*/
142
143struct real_sched_param_struct {
144 int check_interrupt; /* if true check for command-dot */
145 int process_events; /* if nonzero enable evt processing, this mask */
146 int besocial; /* if nonzero be a little social with CPU */
147 unsigned long check_interval; /* how often to check, in ticks */
148 unsigned long bg_yield; /* yield so long when in background */
149 /* these are computed from previous and clock and such */
150 int enabled; /* check_interrupt OR process_event OR yield */
151 unsigned long next_check; /* when to check/yield next, in ticks */
152};
153
154static struct real_sched_param_struct schedparams =
155 { 1, MAINLOOP_EVENTMASK, 1, 15, 15, 1, 0};
156
Jack Jansen819f1771995-08-14 12:35:10 +0000157/*
Jack Jansenf6865f71996-09-04 15:24:59 +0000158** Workaround for sioux/gusi combo: set when we are exiting
159*/
160int PyMac_ConsoleIsDead;
161
162/*
Jack Jansencaa7c461997-06-12 10:49:13 +0000163** Sioux menu bar, saved early so we can restore it
164*/
Jack Jansen657ba272001-02-17 22:02:07 +0000165static MenuBarHandle sioux_mbar;
Jack Jansencaa7c461997-06-12 10:49:13 +0000166
167/*
Jack Jansen819f1771995-08-14 12:35:10 +0000168** Some stuff for our GetDirectory and PromptGetFile routines
169*/
170struct hook_args {
171 int selectcur_hit; /* Set to true when "select current" selected */
172 char *prompt; /* The prompt */
173};
Jack Jansen74a1e632000-07-14 22:37:27 +0000174#if TARGET_API_MAC_CARBON
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000175/* The StandardFile hooks don't exist in Carbon. This breaks GetDirectory,
176** but the macfsn code will replace it by a NavServices version anyway.
177*/
178#define myhook_upp NULL
179#else
Jack Jansen819f1771995-08-14 12:35:10 +0000180static DlgHookYDUPP myhook_upp;
181static int upp_inited = 0;
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000182#endif
Jack Jansen819f1771995-08-14 12:35:10 +0000183
Jack Jansen36ed5061997-06-20 16:18:15 +0000184/*
185** The python-code event handler
186*/
187static PyObject *python_event_handler;
188
Jack Jansen8f5725a1999-12-07 23:08:10 +0000189/*
190** Set to true if we're appearance-compliant
191*/
192int PyMac_AppearanceCompliant;
193
Jack Jansen1f9f2f42000-07-24 19:50:16 +0000194/*
195** Find out what the current script is.
196** Donated by Fredrik Lund.
197*/
198char *PyMac_getscript()
199{
200 int font, script, lang;
201 font = 0;
202 font = GetSysFont();
203 script = FontToScript(font);
204 switch (script) {
205 case smRoman:
206 lang = GetScriptVariable(script, smScriptLang);
207 if (lang == langIcelandic)
208 return "mac-iceland";
209 else if (lang == langTurkish)
210 return "mac-turkish";
211 else if (lang == langGreek)
212 return "mac-greek";
213 else
214 return "mac-roman";
215 break;
216 case smJapanese:
217 return "mac-japan";
218 case smGreek:
219 return "mac-greek";
220 case smCyrillic:
221 return "mac-cyrillic";
222 default:
223 return "mac-roman"; /* better than nothing */
224 }
225}
226
227
Jack Jansen2d1306b2000-04-07 09:10:49 +0000228#ifdef USE_GUSI1
Jack Jansen378815c1996-03-06 16:21:34 +0000229/*
230** GUSI (1.6.0 and earlier, at the least) do not set the MacOS idea of
231** the working directory. Hence, we call this routine after each call
232** to chdir() to rectify things.
233*/
234void
235PyMac_FixGUSIcd()
236{
237 WDPBRec pb;
238 FSSpec curdirfss;
239
240 if ( Path2FSSpec(":x", &curdirfss) != noErr )
241 return;
242
243 /* Set MacOS "working directory" */
244 pb.ioNamePtr= "\p";
245 pb.ioVRefNum= curdirfss.vRefNum;
246 pb.ioWDDirID= curdirfss.parID;
Jack Jansen08c3be31997-04-08 15:27:00 +0000247 if (PBHSetVolSync(&pb) != noErr)
Jack Jansen378815c1996-03-06 16:21:34 +0000248 return;
Jack Jansen378815c1996-03-06 16:21:34 +0000249}
Jack Jansen2d1306b2000-04-07 09:10:49 +0000250#endif
Jack Jansen7ac70af1996-08-19 11:01:05 +0000251
Jack Jansen2d1306b2000-04-07 09:10:49 +0000252#ifdef USE_GUSI
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000253/*
254** SpinCursor (needed by GUSI) drags in heaps of stuff, so we
255** provide a dummy here.
256*/
Jack Jansencfadbd41996-08-19 11:36:25 +0000257void SpinCursor(short x) { /* Dummy */ }
Jack Jansenefaada71998-02-20 16:03:15 +0000258void RotateCursor(short x) { /* Dummy */ }
Jack Jansencfadbd41996-08-19 11:36:25 +0000259
Jack Jansenf6865f71996-09-04 15:24:59 +0000260/*
261** Replacement GUSI Spin function
262*/
Jack Jansen2d1306b2000-04-07 09:10:49 +0000263#ifdef USE_GUSI1
Jack Jansenf6865f71996-09-04 15:24:59 +0000264static int
265PyMac_GUSISpin(spin_msg msg, long arg)
266{
Jack Jansene3ae0df1997-06-03 15:28:29 +0000267 static Boolean inForeground = true;
268 int maxsleep = 6; /* 6 ticks is "normal" sleeptime */
Jack Jansenf6865f71996-09-04 15:24:59 +0000269
270 if (PyMac_ConsoleIsDead) return 0;
271#if 0
272 if (inForeground)
273 SpinCursor(msg == SP_AUTO_SPIN ? short(arg) : 1);
274#endif
275
276 if (interrupted) return -1;
277
Jack Jansene3ae0df1997-06-03 15:28:29 +0000278 if ( msg == SP_AUTO_SPIN )
279 maxsleep = 0;
280 if ( msg==SP_SLEEP||msg==SP_SELECT )
281 maxsleep = arg;
Jack Jansenf6865f71996-09-04 15:24:59 +0000282
Jack Jansene3ae0df1997-06-03 15:28:29 +0000283 PyMac_DoYield(maxsleep, 0); /* XXXX or is it safe to call python here? */
Jack Jansenf6865f71996-09-04 15:24:59 +0000284
285 return 0;
286}
287
288void
289PyMac_SetGUSISpin() {
290 GUSISetHook(GUSI_SpinHook, (GUSIHook)PyMac_GUSISpin);
291}
Jack Jansen2d1306b2000-04-07 09:10:49 +0000292#endif
Jack Jansenf6865f71996-09-04 15:24:59 +0000293
Jack Jansena39f1b01997-05-23 15:35:14 +0000294/* Called at exit() time thru atexit(), to stop event processing */
295void
296PyMac_StopGUSISpin() {
297 PyMac_ConsoleIsDead = 1;
298}
299
Jack Jansen6ba34aa2001-01-11 23:03:56 +0000300#if !TARGET_API_MAC_CARBON
Jack Jansena39f1b01997-05-23 15:35:14 +0000301/*
302** Replacement routines for the PLstr... functions so we don't need
Jack Jansen6ba34aa2001-01-11 23:03:56 +0000303** StdCLib.
Jack Jansena39f1b01997-05-23 15:35:14 +0000304*/
Jack Jansen8bb573e1999-12-12 21:37:14 +0000305pascal void
Jack Jansen9ae898b2000-07-11 21:16:03 +0000306PLstrcpy(unsigned char *to, unsigned char *fr)
Jack Jansena39f1b01997-05-23 15:35:14 +0000307{
308 memcpy(to, fr, fr[0]+1);
309}
310
Jack Jansen8bb573e1999-12-12 21:37:14 +0000311pascal int
Jack Jansen9ae898b2000-07-11 21:16:03 +0000312PLstrcmp(unsigned char *s1, unsigned char *s2)
Jack Jansena39f1b01997-05-23 15:35:14 +0000313{
314 int res;
315 int l = s1[0] < s2[0] ? s1[0] : s2[0];
316
317 res = memcmp(s1+1, s2+1, l);
318 if ( res != 0 )
319 return res;
320
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000321 if ( s1[0] < s2[0] )
Jack Jansena39f1b01997-05-23 15:35:14 +0000322 return -1;
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000323 else if ( s1[0] > s2[0] )
Jack Jansena39f1b01997-05-23 15:35:14 +0000324 return 1;
325 else
326 return 0;
327}
328
Jack Jansen8bb573e1999-12-12 21:37:14 +0000329pascal unsigned char *
Jack Jansen9ae898b2000-07-11 21:16:03 +0000330PLstrrchr(unsigned char *str, unsigned char chr)
Jack Jansena39f1b01997-05-23 15:35:14 +0000331{
332 unsigned char *ptr = 0;
333 unsigned char *p;
334
335 for(p=str+1; p<str+str[0]; p++)
336 if ( *p == chr )
337 ptr = p;
338 return ptr;
339}
340
Jack Jansen6ba34aa2001-01-11 23:03:56 +0000341#endif /* !TARGET_API_MAC_CARBON */
Jack Jansena39f1b01997-05-23 15:35:14 +0000342#endif /* USE_GUSI */
Jack Jansen378815c1996-03-06 16:21:34 +0000343
Jack Jansen819f1771995-08-14 12:35:10 +0000344
Jack Jansen5f653091995-01-18 13:53:49 +0000345/* Convert C to Pascal string. Returns pointer to static buffer. */
346unsigned char *
347Pstring(char *str)
348{
349 static Str255 buf;
350 int len;
351
352 len = strlen(str);
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000353 if (len > 255)
354 len = 255;
Jack Jansen5f653091995-01-18 13:53:49 +0000355 buf[0] = (unsigned char)len;
356 strncpy((char *)buf+1, str, len);
357 return buf;
358}
359
Jack Jansen91faef82001-01-09 22:24:56 +0000360#if !TARGET_API_MAC_CARBON
Jack Jansen5afad832000-12-12 22:12:14 +0000361void
362c2pstrcpy(unsigned char *dst, const char *src)
363{
364 int len;
365
366 len = strlen(src);
367 if ( len > 255 ) len = 255;
368 strncpy((char *)dst+1, src, len);
369 dst[0] = len;
370}
Jack Jansen6ba34aa2001-01-11 23:03:56 +0000371#endif /* !TARGET_API_MAC_CARBON */
Jack Jansen5afad832000-12-12 22:12:14 +0000372
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000373/* Like strerror() but for Mac OS error numbers */
374char *PyMac_StrError(int err)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000375{
376 static char buf[256];
377 Handle h;
378 char *str;
379
380 h = GetResource('Estr', err);
381 if ( h ) {
382 HLock(h);
383 str = (char *)*h;
384 memcpy(buf, str+1, (unsigned char)str[0]);
Guido van Rossumcc9bc8f1995-02-13 16:17:03 +0000385 buf[(unsigned char)str[0]] = '\0';
Jack Jansenf93c72a1994-12-14 14:07:50 +0000386 HUnlock(h);
387 ReleaseResource(h);
388 } else {
389 sprintf(buf, "Mac OS error code %d", err);
390 }
391 return buf;
392}
393
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000394/* Exception object shared by all Mac specific modules for Mac OS errors */
395PyObject *PyMac_OSErrException;
396
397/* Initialize and return PyMac_OSErrException */
398PyObject *
399PyMac_GetOSErrException()
400{
401 if (PyMac_OSErrException == NULL)
402 PyMac_OSErrException = PyString_FromString("Mac OS Error");
403 return PyMac_OSErrException;
404}
405
Jack Jansenf93c72a1994-12-14 14:07:50 +0000406/* Set a MAC-specific error from errno, and return NULL; return None if no error */
407PyObject *
Guido van Rossumfffb8bb1995-01-12 12:37:24 +0000408PyErr_Mac(PyObject *eobj, int err)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000409{
410 char *msg;
411 PyObject *v;
Jack Jansenf93c72a1994-12-14 14:07:50 +0000412
Guido van Rossum8f691791995-01-18 23:57:26 +0000413 if (err == 0 && !PyErr_Occurred()) {
Jack Jansenf93c72a1994-12-14 14:07:50 +0000414 Py_INCREF(Py_None);
415 return Py_None;
416 }
Guido van Rossum8f691791995-01-18 23:57:26 +0000417 if (err == -1 && PyErr_Occurred())
418 return NULL;
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000419 msg = PyMac_StrError(err);
Jack Jansenf93c72a1994-12-14 14:07:50 +0000420 v = Py_BuildValue("(is)", err, msg);
421 PyErr_SetObject(eobj, v);
422 Py_DECREF(v);
423 return NULL;
424}
425
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000426/* Call PyErr_Mac with PyMac_OSErrException */
427PyObject *
428PyMac_Error(OSErr err)
429{
430 return PyErr_Mac(PyMac_GetOSErrException(), err);
431}
432
Jack Jansen1ed95291996-07-22 15:25:10 +0000433#ifdef USE_STACKCHECK
434/* Check for stack overflow */
435int
436PyOS_CheckStack()
437{
Jack Jansen14a91712000-08-25 21:57:23 +0000438 char here;
439 static char *sentinel = 0;
Jack Jansen53bafd92000-09-08 22:05:48 +0000440 static PyThreadState *thread_for_sentinel = 0;
Jack Jansen1ed95291996-07-22 15:25:10 +0000441
Jack Jansen340eb882001-02-02 22:40:28 +0000442 if ( sentinel == 0 ) {
443 unsigned long stackspace = StackSpace();
444
445#ifdef MAXIMUM_STACK_SIZE
446 /* See the comment at the definition */
447 if ( stackspace > MAXIMUM_STACK_SIZE )
448 stackspace = MAXIMUM_STACK_SIZE;
449#endif
450 sentinel = &here - stackspace + MINIMUM_STACK_SIZE;
Jack Jansen14a91712000-08-25 21:57:23 +0000451 }
Jack Jansen53bafd92000-09-08 22:05:48 +0000452 if ( thread_for_sentinel == 0 ) {
453 thread_for_sentinel = PyThreadState_Get();
454 }
455 if ( &here < sentinel ) {
456 if (thread_for_sentinel == PyThreadState_Get()) {
457 return -1;
458#if 0
459 } else {
460 /* Else we are unsure... */
461 fprintf(stderr, "Stackcheck in other thread (was %x now %x)\n", thread_for_sentinel,PyThreadState_Get());
462#endif
463 }
464 }
Jack Jansen1ed95291996-07-22 15:25:10 +0000465 return 0;
466}
467#endif /* USE_STACKCHECK */
468
Jack Jansenee23d6e1995-01-27 14:43:25 +0000469/* The catcher routine (which may not be used for all compilers) */
470static RETSIGTYPE
471intcatcher(sig)
472 int sig;
473{
474 interrupted = 1;
475 signal(SIGINT, intcatcher);
476}
477
478void
479PyOS_InitInterrupts()
480{
481 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
482 signal(SIGINT, intcatcher);
483}
484
Jack Jansena8441de1997-08-08 14:57:37 +0000485void
486PyOS_FiniInterrupts()
487{
488}
489
Jack Jansenee23d6e1995-01-27 14:43:25 +0000490/*
491** This routine scans the event queue looking for cmd-.
492** This is the only way to get an interrupt under THINK (since it
493** doesn't do SIGINT handling), but is also used under MW, when
494** the full-fledged event loop is disabled. This way, we can at least
495** interrupt a runaway python program.
496*/
497static void
498scan_event_queue(flush)
499 int flush;
500{
Jack Jansen74a1e632000-07-14 22:37:27 +0000501#if TARGET_API_MAC_CARBON
Jack Jansend7b68022001-01-12 23:42:28 +0000502 if ( CheckEventQueueForUserCancel() )
503 interrupted = 1;
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000504#else
Jack Jansenee23d6e1995-01-27 14:43:25 +0000505 register EvQElPtr q;
506
Jack Jansenefaada71998-02-20 16:03:15 +0000507 q = (EvQElPtr) LMGetEventQueue()->qHead;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000508
509 for (; q; q = (EvQElPtr)q->qLink) {
510 if (q->evtQWhat == keyDown &&
511 (char)q->evtQMessage == '.' &&
512 (q->evtQModifiers & cmdKey) != 0) {
513 if ( flush )
514 FlushEvents(keyDownMask, 0);
515 interrupted = 1;
516 break;
517 }
518 }
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000519#endif
Jack Jansenee23d6e1995-01-27 14:43:25 +0000520}
521
522int
Jack Jansen36ed5061997-06-20 16:18:15 +0000523PyErr_CheckSignals()
Jack Jansenee23d6e1995-01-27 14:43:25 +0000524{
Jack Jansene3ae0df1997-06-03 15:28:29 +0000525 if (schedparams.enabled) {
526 if ( (unsigned long)LMGetTicks() > schedparams.next_check ) {
Jack Jansen36ed5061997-06-20 16:18:15 +0000527 if ( PyMac_Yield() < 0)
528 return -1;
Jack Jansene3ae0df1997-06-03 15:28:29 +0000529 schedparams.next_check = (unsigned long)LMGetTicks()
530 + schedparams.check_interval;
531 if (interrupted) {
Jack Jansencaa7c461997-06-12 10:49:13 +0000532 scan_event_queue(1); /* Eat events up to cmd-. */
Jack Jansene3ae0df1997-06-03 15:28:29 +0000533 interrupted = 0;
Jack Jansen36ed5061997-06-20 16:18:15 +0000534 PyErr_SetNone(PyExc_KeyboardInterrupt);
535 return -1;
Jack Jansene3ae0df1997-06-03 15:28:29 +0000536 }
537 }
Jack Jansenee23d6e1995-01-27 14:43:25 +0000538 }
539 return 0;
540}
541
Jack Jansen8a387142001-02-11 01:08:04 +0000542#if 0
543/*
544** This routine is called if we know that an external library yielded
545** to background tasks, so we shouldn't count that time in our computation
546** of how much CPU we used.
547** This happens with SIOUX, and the routine is called from our modified
548** GUSISIOUX.
549*/
550void
551PyMac_LibraryDidYield(int howlong)
552{
553 unsigned long maxnextcheck = (unsigned long)LMGetTicks() + schedparams.check_interval;
554
555 schedparams.next_check = schedparams.next_check + howlong;
556 if (schedparams.next_check > maxnextcheck )
557 schedparams.next_check = maxnextcheck;
558}
559#endif
560
Jack Jansen36ed5061997-06-20 16:18:15 +0000561int
562PyOS_InterruptOccurred()
563{
564 scan_event_queue(1);
565 return interrupted;
566}
Jack Jansenee23d6e1995-01-27 14:43:25 +0000567/* Check whether we are in the foreground */
Jack Jansen9ae898b2000-07-11 21:16:03 +0000568static int
569PyMac_InForeground(void)
Jack Jansenee23d6e1995-01-27 14:43:25 +0000570{
571 static ProcessSerialNumber ours;
572 static inited;
573 ProcessSerialNumber curfg;
574 Boolean eq;
575
Jack Jansene3ae0df1997-06-03 15:28:29 +0000576 if ( inited == 0 ) {
Jack Jansenee23d6e1995-01-27 14:43:25 +0000577 (void)GetCurrentProcess(&ours);
Jack Jansene3ae0df1997-06-03 15:28:29 +0000578 inited = 1;
579 }
Jack Jansenee23d6e1995-01-27 14:43:25 +0000580 if ( GetFrontProcess(&curfg) < 0 )
581 eq = 1;
582 else if ( SameProcess(&ours, &curfg, &eq) < 0 )
583 eq = 1;
584 return (int)eq;
585
586}
587
Jack Jansen36ed5061997-06-20 16:18:15 +0000588int
589PyMac_SetEventHandler(PyObject *evh)
590{
591 if ( evh && python_event_handler ) {
592 PyErr_SetString(PyExc_RuntimeError, "Python event handler already set");
593 return 0;
594 }
595 if ( python_event_handler )
596 Py_DECREF(python_event_handler);
597 if ( evh )
598 Py_INCREF(evh);
599 python_event_handler = evh;
600 return 1;
601}
602
Jack Jansenf93c72a1994-12-14 14:07:50 +0000603/*
Jack Jansena76382a1995-02-02 14:25:56 +0000604** Handle an event, either one found in the mainloop eventhandler or
605** one passed back from the python program.
606*/
607void
Jack Jansen36ed5061997-06-20 16:18:15 +0000608PyMac_HandleEventIntern(evp)
Jack Jansena76382a1995-02-02 14:25:56 +0000609 EventRecord *evp;
610{
Jack Jansen74a1e632000-07-14 22:37:27 +0000611#if !TARGET_API_MAC_CARBON
Jack Jansen0c968871997-08-26 13:20:34 +0000612 if ( evp->what == mouseDown ) {
613 WindowPtr wp;
614
615 if ( FindWindow(evp->where, &wp) == inSysWindow ) {
616 SystemClick(evp, wp);
617 return;
618 }
619 }
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000620#endif
Jack Jansena76382a1995-02-02 14:25:56 +0000621#ifdef __MWERKS__
Jack Jansen38e97661995-11-10 14:53:00 +0000622 {
623 int siouxdidit;
624
625 /* If SIOUX wants it we're done */
626 siouxdidit = SIOUXHandleOneEvent(evp);
627 if ( siouxdidit )
628 return;
629 }
Jack Jansena76382a1995-02-02 14:25:56 +0000630#else
Jack Jansen0c968871997-08-26 13:20:34 +0000631 /* Other compilers are just unlucky... */
Jack Jansena76382a1995-02-02 14:25:56 +0000632#endif /* !__MWERKS__ */
Jack Jansen36ed5061997-06-20 16:18:15 +0000633}
634
635/*
636** Handle an event, either through HandleEvent or by passing it to the Python
637** event handler.
638*/
639int
640PyMac_HandleEvent(evp)
641 EventRecord *evp;
642{
643 PyObject *rv;
644
645 if ( python_event_handler ) {
646 rv = PyObject_CallFunction(python_event_handler, "(O&)",
647 PyMac_BuildEventRecord, evp);
648 if ( rv )
649 Py_DECREF(rv);
650 else
651 return -1; /* Propagate exception */
652 } else {
653 PyMac_HandleEventIntern(evp);
654 }
655 return 0;
Jack Jansena76382a1995-02-02 14:25:56 +0000656}
657
658/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000659** Yield the CPU to other tasks without processing events.
Jack Jansene8e8ae01995-01-26 16:36:45 +0000660*/
Jack Jansen2d1306b2000-04-07 09:10:49 +0000661int
Jack Jansene3ae0df1997-06-03 15:28:29 +0000662PyMac_DoYield(int maxsleep, int maycallpython)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000663{
664 EventRecord ev;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000665 int gotone;
Jack Jansene3ae0df1997-06-03 15:28:29 +0000666 long latest_time_ready;
Jack Jansen36ed5061997-06-20 16:18:15 +0000667 static int in_here = 0;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000668
Jack Jansen36ed5061997-06-20 16:18:15 +0000669 in_here++;
Jack Jansene3ae0df1997-06-03 15:28:29 +0000670 /*
671 ** First check for interrupts, if wanted.
672 ** This sets a flag that will be picked up at an appropriate
673 ** moment in the mainloop.
674 */
675 if (schedparams.check_interrupt)
Jack Jansenee23d6e1995-01-27 14:43:25 +0000676 scan_event_queue(0);
Jack Jansene3ae0df1997-06-03 15:28:29 +0000677
678 /* XXXX Implementing an idle routine goes here */
Jack Jansene8e8ae01995-01-26 16:36:45 +0000679
Jack Jansene3ae0df1997-06-03 15:28:29 +0000680 /*
681 ** Check which of the eventloop cases we have:
682 ** - process events
683 ** - don't process events but do yield
684 ** - do neither
685 */
Jack Jansen36ed5061997-06-20 16:18:15 +0000686 if( in_here > 1 || !schedparams.process_events ||
687 (python_event_handler && !maycallpython) ) {
Jack Jansene3ae0df1997-06-03 15:28:29 +0000688 if ( maxsleep >= 0 ) {
Jack Jansen15f1c082001-04-25 22:07:27 +0000689#if !TARGET_API_MAC_CARBON
Jack Jansene8e8ae01995-01-26 16:36:45 +0000690 SystemTask();
Jack Jansen15f1c082001-04-25 22:07:27 +0000691#else
692 int xxx = 0;
Jack Jansenbb6d83a2000-06-02 21:27:11 +0000693#endif
Jack Jansen15f1c082001-04-25 22:07:27 +0000694 }
Jack Jansene3ae0df1997-06-03 15:28:29 +0000695 } else {
696 latest_time_ready = LMGetTicks() + maxsleep;
Jack Jansen2d1306b2000-04-07 09:10:49 +0000697 do {
Jack Jansen0c968871997-08-26 13:20:34 +0000698 /* XXXX Hack by Jack.
699 ** In time.sleep() you can click to another application
700 ** once only. If you come back to Python you cannot get away
701 ** again.
702 **/
Jack Jansen36ed5061997-06-20 16:18:15 +0000703 gotone = WaitNextEvent(schedparams.process_events, &ev, maxsleep, NULL);
Jack Jansene3ae0df1997-06-03 15:28:29 +0000704 /* Get out quickly if nothing interesting is happening */
705 if ( !gotone || ev.what == nullEvent )
706 break;
Jack Jansen36ed5061997-06-20 16:18:15 +0000707 if ( PyMac_HandleEvent(&ev) < 0 ) {
708 in_here--;
709 return -1;
710 }
Jack Jansene3ae0df1997-06-03 15:28:29 +0000711 maxsleep = latest_time_ready - LMGetTicks();
Jack Jansen2d1306b2000-04-07 09:10:49 +0000712 } while ( maxsleep > 0 );
Jack Jansenf93c72a1994-12-14 14:07:50 +0000713 }
Jack Jansen36ed5061997-06-20 16:18:15 +0000714 in_here--;
715 return 0;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000716}
717
718/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000719** Process events and/or yield the CPU to other tasks if opportune
Jack Jansene8e8ae01995-01-26 16:36:45 +0000720*/
Jack Jansen36ed5061997-06-20 16:18:15 +0000721int
Jack Jansene8e8ae01995-01-26 16:36:45 +0000722PyMac_Yield() {
Jack Jansene3ae0df1997-06-03 15:28:29 +0000723 unsigned long maxsleep;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000724
Jack Jansene3ae0df1997-06-03 15:28:29 +0000725 if( PyMac_InForeground() )
726 maxsleep = 0;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000727 else
Jack Jansene3ae0df1997-06-03 15:28:29 +0000728 maxsleep = schedparams.bg_yield;
729
Jack Jansen36ed5061997-06-20 16:18:15 +0000730 return PyMac_DoYield(maxsleep, 1);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000731}
732
733/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000734** Return current scheduler parameters
Jack Jansene8e8ae01995-01-26 16:36:45 +0000735*/
Jack Jansene3ae0df1997-06-03 15:28:29 +0000736void
737PyMac_GetSchedParams(PyMacSchedParams *sp)
Jack Jansene8e8ae01995-01-26 16:36:45 +0000738{
Jack Jansene3ae0df1997-06-03 15:28:29 +0000739 sp->check_interrupt = schedparams.check_interrupt;
740 sp->process_events = schedparams.process_events;
741 sp->besocial = schedparams.besocial;
742 sp->check_interval = schedparams.check_interval / 60.0;
743 sp->bg_yield = schedparams.bg_yield / 60.0;
Jack Jansenf93c72a1994-12-14 14:07:50 +0000744}
Jack Jansenf6865f71996-09-04 15:24:59 +0000745
Jack Jansen74162f31995-02-15 22:58:33 +0000746/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000747** Set current scheduler parameters
748*/
749void
750PyMac_SetSchedParams(PyMacSchedParams *sp)
751{
752 schedparams.check_interrupt = sp->check_interrupt;
753 schedparams.process_events = sp->process_events;
754 schedparams.besocial = sp->besocial;
755 schedparams.check_interval = (unsigned long)(sp->check_interval*60);
756 schedparams.bg_yield = (unsigned long)(sp->bg_yield*60);
757 if ( schedparams.check_interrupt || schedparams.process_events ||
758 schedparams.besocial )
759 schedparams.enabled = 1;
760 else
761 schedparams.enabled = 0;
762 schedparams.next_check = 0; /* Check immedeately */
763}
Jack Jansencaa7c461997-06-12 10:49:13 +0000764
Jack Jansene3ae0df1997-06-03 15:28:29 +0000765/*
Jack Jansen3469e991996-09-06 00:30:45 +0000766** Install our menu bar.
767*/
768void
769PyMac_InitMenuBar()
770{
Jack Jansen3469e991996-09-06 00:30:45 +0000771 MenuHandle applemenu;
772
Jack Jansen15f1c082001-04-25 22:07:27 +0000773 if ( sioux_mbar ) return;
Jack Jansencaa7c461997-06-12 10:49:13 +0000774 if ( (sioux_mbar=GetMenuBar()) == NULL ) {
775 /* Sioux menu not installed yet. Do so */
776 SIOUXSetupMenus();
777 if ( (sioux_mbar=GetMenuBar()) == NULL )
778 return;
779 }
Jack Jansen08c3be31997-04-08 15:27:00 +0000780 if ( (applemenu=GetMenuHandle(SIOUX_APPLEID)) == NULL ) return;
Jack Jansen3469e991996-09-06 00:30:45 +0000781 SetMenuItemText(applemenu, 1, "\pAbout Python...");
782}
783
784/*
Jack Jansencaa7c461997-06-12 10:49:13 +0000785** Restore sioux menu bar
786*/
787void
788PyMac_RestoreMenuBar()
789{
Jack Jansen15f1c082001-04-25 22:07:27 +0000790#if 1
Jack Jansen657ba272001-02-17 22:02:07 +0000791 /* This doesn't seem to work anymore? Or only for Carbon? */
792 MenuBarHandle curmenubar;
793
794 curmenubar = GetMenuBar();
Jack Janseneda78631997-06-12 15:29:46 +0000795 if ( sioux_mbar ) {
Jack Jansencaa7c461997-06-12 10:49:13 +0000796 SetMenuBar(sioux_mbar);
Jack Janseneda78631997-06-12 15:29:46 +0000797 DrawMenuBar();
Jack Jansen657ba272001-02-17 22:02:07 +0000798 } else {
Jack Jansenefaada71998-02-20 16:03:15 +0000799 PyMac_InitMenuBar();
Jack Jansen657ba272001-02-17 22:02:07 +0000800 DrawMenuBar();
801 }
802#endif
Jack Jansencaa7c461997-06-12 10:49:13 +0000803}
804
Jack Jansen15f1c082001-04-25 22:07:27 +0000805void
806PyMac_RaiseConsoleWindow()
807{
808 /* Note: this is a hack. SIOUXTextWindow is SIOUX's internal structure
809 ** and we happen to know that the first entry is the window pointer.
810 */
811 extern WindowRef *SIOUXTextWindow;
812
813 if ( SIOUXTextWindow == NULL || *SIOUXTextWindow == NULL )
814 return;
815 if ( FrontWindow() != *SIOUXTextWindow )
816 BringToFront(*SIOUXTextWindow);
817}
Jack Jansencaa7c461997-06-12 10:49:13 +0000818
819/*
Jack Jansen3469e991996-09-06 00:30:45 +0000820** Our replacement about box
821*/
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000822
823#include "patchlevel.h"
824
Jack Jansen3469e991996-09-06 00:30:45 +0000825void
826SIOUXDoAboutBox(void)
827{
828 DialogPtr theDialog;
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000829 WindowPtr theWindow;
Jack Jansen3469e991996-09-06 00:30:45 +0000830 short item;
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000831 short fontID;
Jack Jansen3469e991996-09-06 00:30:45 +0000832
833 if( (theDialog = GetNewDialog(ABOUT_ID, NULL, (WindowPtr)-1)) == NULL )
834 return;
Jack Jansend617c571996-09-22 22:14:30 +0000835 theWindow = GetDialogWindow(theDialog);
Jack Jansen7e1fb7c1998-07-31 09:36:30 +0000836 SetPortWindowPort(theWindow);
837 GetFNum("\pPython-Sans", &fontID);
838 if (fontID == 0)
839 fontID = kFontIDGeneva;
840 TextFont(fontID);
841 TextSize(9);
842 ParamText(Pstring(PATCHLEVEL), "\p", "\p", "\p");
Jack Jansend617c571996-09-22 22:14:30 +0000843 ShowWindow(theWindow);
Jack Jansen3469e991996-09-06 00:30:45 +0000844 ModalDialog(NULL, &item);
845 DisposeDialog(theDialog);
846}
847
Jack Janseneda78631997-06-12 15:29:46 +0000848#if 0
849int
850PyMac_FileExists(char *name)
851{
852 FSSpec fss;
853
854 if ( FSMakeFSSpec(0, 0, Pstring(name), &fss) == noErr )
855 return 1;
856 return 0;
857}
858#endif
859
860/*
Jack Jansen3ec804a1995-02-20 15:56:10 +0000861** Helper routine for GetDirectory
862*/
Guido van Rossum24a45e31995-02-20 23:45:53 +0000863static pascal short
Jack Jansen819f1771995-08-14 12:35:10 +0000864myhook_proc(short item, DialogPtr theDialog, struct hook_args *dataptr)
Jack Jansen3ec804a1995-02-20 15:56:10 +0000865{
Jack Jansen819f1771995-08-14 12:35:10 +0000866 if ( item == sfHookFirstCall && dataptr->prompt) {
867 Handle prompth;
868 short type;
869 Rect rect;
870
871 GetDialogItem(theDialog, PROMPT_ITEM, &type, &prompth, &rect);
872 if ( prompth )
873 SetDialogItemText(prompth, (unsigned char *)dataptr->prompt);
874 } else
Jack Jansen3ec804a1995-02-20 15:56:10 +0000875 if ( item == SELECTCUR_ITEM ) {
876 item = sfItemCancelButton;
Jack Jansen819f1771995-08-14 12:35:10 +0000877 dataptr->selectcur_hit = 1;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000878 }
879 return item;
880}
Jack Jansen74a1e632000-07-14 22:37:27 +0000881#if !TARGET_API_MAC_CARBON
Jack Jansen3ec804a1995-02-20 15:56:10 +0000882/*
883** Ask the user for a directory. I still can't understand
884** why Apple doesn't provide a standard solution for this...
885*/
886int
Jack Jansen819f1771995-08-14 12:35:10 +0000887PyMac_GetDirectory(dirfss, prompt)
Jack Jansen3ec804a1995-02-20 15:56:10 +0000888 FSSpec *dirfss;
Jack Jansen819f1771995-08-14 12:35:10 +0000889 char *prompt;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000890{
891 static SFTypeList list = {'fldr', 0, 0, 0};
892 static Point where = {-1, -1};
Jack Jansen3ec804a1995-02-20 15:56:10 +0000893 StandardFileReply reply;
Jack Jansen819f1771995-08-14 12:35:10 +0000894 struct hook_args hook_args;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000895
896 if ( !upp_inited ) {
897 myhook_upp = NewDlgHookYDProc(myhook_proc);
898 upp_inited = 1;
899 }
Jack Jansen819f1771995-08-14 12:35:10 +0000900 if ( prompt && *prompt )
901 hook_args.prompt = (char *)Pstring(prompt);
902 else
903 hook_args.prompt = NULL;
904 hook_args.selectcur_hit = 0;
Guido van Rossum24a45e31995-02-20 23:45:53 +0000905 CustomGetFile((FileFilterYDUPP)0, 1, list, &reply, GETDIR_ID, where, myhook_upp,
Jack Jansen819f1771995-08-14 12:35:10 +0000906 NULL, NULL, NULL, (void *)&hook_args);
Jack Jansen3ec804a1995-02-20 15:56:10 +0000907
908 reply.sfFile.name[0] = 0;
909 if( FSMakeFSSpec(reply.sfFile.vRefNum, reply.sfFile.parID, reply.sfFile.name, dirfss) )
910 return 0;
Jack Jansen819f1771995-08-14 12:35:10 +0000911 return hook_args.selectcur_hit;
912}
913
914/*
915** Slightly extended StandardGetFile: accepts a prompt */
916void PyMac_PromptGetFile(short numTypes, ConstSFTypeListPtr typeList,
917 StandardFileReply *reply, char *prompt)
918{
919 static Point where = {-1, -1};
920 struct hook_args hook_args;
921
922 if ( !upp_inited ) {
923 myhook_upp = NewDlgHookYDProc(myhook_proc);
924 upp_inited = 1;
925 }
926 if ( prompt && *prompt )
927 hook_args.prompt = (char *)Pstring(prompt);
928 else
929 hook_args.prompt = NULL;
930 hook_args.selectcur_hit = 0;
931 CustomGetFile((FileFilterYDUPP)0, numTypes, typeList, reply, GETFILEPROMPT_ID, where,
932 myhook_upp, NULL, NULL, NULL, (void *)&hook_args);
Jack Jansen3ec804a1995-02-20 15:56:10 +0000933}
Jack Jansenbb7e2132000-07-14 22:15:24 +0000934#endif /* TARGET_API_MAC_CARBON */
Jack Jansen5f653091995-01-18 13:53:49 +0000935
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000936/* Convert a 4-char string object argument to an OSType value */
Jack Jansen5f653091995-01-18 13:53:49 +0000937int
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000938PyMac_GetOSType(PyObject *v, OSType *pr)
Jack Jansen5f653091995-01-18 13:53:49 +0000939{
940 if (!PyString_Check(v) || PyString_Size(v) != 4) {
941 PyErr_SetString(PyExc_TypeError,
942 "OSType arg must be string of 4 chars");
943 return 0;
944 }
945 memcpy((char *)pr, PyString_AsString(v), 4);
946 return 1;
947}
948
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000949/* Convert an OSType value to a 4-char string object */
950PyObject *
951PyMac_BuildOSType(OSType t)
952{
953 return PyString_FromStringAndSize((char *)&t, 4);
954}
955
Jack Jansend1f06311996-08-01 15:23:54 +0000956/* Convert an NumVersion value to a 4-element tuple */
957PyObject *
958PyMac_BuildNumVersion(NumVersion t)
959{
960 return Py_BuildValue("(hhhh)", t.majorRev, t.minorAndBugRev, t.stage, t.nonRelRev);
961}
962
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000963
964/* Convert a Python string object to a Str255 */
Jack Jansen5f653091995-01-18 13:53:49 +0000965int
Guido van Rossum8f691791995-01-18 23:57:26 +0000966PyMac_GetStr255(PyObject *v, Str255 pbuf)
Jack Jansen5f653091995-01-18 13:53:49 +0000967{
968 int len;
969 if (!PyString_Check(v) || (len = PyString_Size(v)) > 255) {
970 PyErr_SetString(PyExc_TypeError,
971 "Str255 arg must be string of at most 255 chars");
972 return 0;
973 }
974 pbuf[0] = len;
975 memcpy((char *)(pbuf+1), PyString_AsString(v), len);
976 return 1;
977}
978
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000979/* Convert a Str255 to a Python string object */
980PyObject *
981PyMac_BuildStr255(Str255 s)
982{
Jack Jansenb734ade1999-12-17 17:15:50 +0000983 if ( s == NULL ) {
984 PyErr_SetString(PyExc_SystemError, "Str255 pointer is NULL");
985 return NULL;
986 }
987 return PyString_FromStringAndSize((char *)&s[1], (int)s[0]);
988}
989
990PyObject *
991PyMac_BuildOptStr255(Str255 s)
992{
993 if ( s == NULL ) {
994 Py_INCREF(Py_None);
995 return Py_None;
996 }
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000997 return PyString_FromStringAndSize((char *)&s[1], (int)s[0]);
998}
999
1000
Jack Jansen5f653091995-01-18 13:53:49 +00001001/*
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001002** Convert a Python object to an FSSpec.
1003** The object may either be a full pathname or a triple
1004** (vrefnum, dirid, path).
Jack Jansen5f653091995-01-18 13:53:49 +00001005** NOTE: This routine will fail on pre-sys7 machines.
1006** The caller is responsible for not calling this routine
1007** in those cases (which is fine, since everyone calling
1008** this is probably sys7 dependent anyway).
1009*/
1010int
Guido van Rossum8f691791995-01-18 23:57:26 +00001011PyMac_GetFSSpec(PyObject *v, FSSpec *fs)
Jack Jansen5f653091995-01-18 13:53:49 +00001012{
1013 Str255 path;
1014 short refnum;
1015 long parid;
1016 OSErr err;
Jack Jansene8e8ae01995-01-26 16:36:45 +00001017 FSSpec *fs2;
Jack Jansen5f653091995-01-18 13:53:49 +00001018
Jack Jansene8e8ae01995-01-26 16:36:45 +00001019 /* first check whether it already is an FSSpec */
1020 fs2 = mfs_GetFSSpecFSSpec(v);
1021 if ( fs2 ) {
Jack Jansen3ec804a1995-02-20 15:56:10 +00001022 (void)FSMakeFSSpec(fs2->vRefNum, fs2->parID, fs2->name, fs);
Jack Jansene8e8ae01995-01-26 16:36:45 +00001023 return 1;
1024 }
Jack Jansen5f653091995-01-18 13:53:49 +00001025 if ( PyString_Check(v) ) {
1026 /* It's a pathname */
Guido van Rossum9aa3d131995-01-21 13:46:04 +00001027 if( !PyArg_Parse(v, "O&", PyMac_GetStr255, &path) )
Jack Jansen5f653091995-01-18 13:53:49 +00001028 return 0;
Jack Jansen378815c1996-03-06 16:21:34 +00001029 refnum = 0; /* XXXX Should get CurWD here?? */
Jack Jansen5f653091995-01-18 13:53:49 +00001030 parid = 0;
1031 } else {
Guido van Rossum9aa3d131995-01-21 13:46:04 +00001032 if( !PyArg_Parse(v, "(hlO&); FSSpec should be fullpath or (vrefnum,dirid,path)",
1033 &refnum, &parid, PyMac_GetStr255, &path)) {
Jack Jansen5f653091995-01-18 13:53:49 +00001034 return 0;
Guido van Rossum9aa3d131995-01-21 13:46:04 +00001035 }
Jack Jansen5f653091995-01-18 13:53:49 +00001036 }
1037 err = FSMakeFSSpec(refnum, parid, path, fs);
1038 if ( err && err != fnfErr ) {
Jack Jansen3d757542000-01-24 09:56:06 +00001039 PyMac_Error(err);
Jack Jansen5f653091995-01-18 13:53:49 +00001040 return 0;
1041 }
1042 return 1;
1043}
1044
Jack Jansen8bb573e1999-12-12 21:37:14 +00001045/* Convert FSSpec to PyObject */
1046PyObject *PyMac_BuildFSSpec(FSSpec *v)
1047{
1048 return newmfssobject(v);
1049}
Guido van Rossum8f691791995-01-18 23:57:26 +00001050
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001051/* Convert a Python object to a Rect.
Guido van Rossum5279ec61995-01-26 22:56:59 +00001052 The object must be a (left, top, right, bottom) tuple.
1053 (This differs from the order in the struct but is consistent with
1054 the arguments to SetRect(), and also with STDWIN). */
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001055int
1056PyMac_GetRect(PyObject *v, Rect *r)
Guido van Rossum8f691791995-01-18 23:57:26 +00001057{
Guido van Rossum5279ec61995-01-26 22:56:59 +00001058 return PyArg_Parse(v, "(hhhh)", &r->left, &r->top, &r->right, &r->bottom);
Guido van Rossum8f691791995-01-18 23:57:26 +00001059}
Guido van Rossumb3404661995-01-22 18:36:13 +00001060
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001061/* Convert a Rect to a Python object */
Guido van Rossumb3404661995-01-22 18:36:13 +00001062PyObject *
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001063PyMac_BuildRect(Rect *r)
Guido van Rossumb3404661995-01-22 18:36:13 +00001064{
Guido van Rossum5279ec61995-01-26 22:56:59 +00001065 return Py_BuildValue("(hhhh)", r->left, r->top, r->right, r->bottom);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001066}
1067
1068
1069/* Convert a Python object to a Point.
Guido van Rossum5279ec61995-01-26 22:56:59 +00001070 The object must be a (h, v) tuple.
1071 (This differs from the order in the struct but is consistent with
1072 the arguments to SetPoint(), and also with STDWIN). */
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001073int
1074PyMac_GetPoint(PyObject *v, Point *p)
1075{
Guido van Rossum5279ec61995-01-26 22:56:59 +00001076 return PyArg_Parse(v, "(hh)", &p->h, &p->v);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001077}
1078
1079/* Convert a Point to a Python object */
1080PyObject *
1081PyMac_BuildPoint(Point p)
1082{
Guido van Rossum5279ec61995-01-26 22:56:59 +00001083 return Py_BuildValue("(hh)", p.h, p.v);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001084}
1085
1086
1087/* Convert a Python object to an EventRecord.
1088 The object must be a (what, message, when, (v, h), modifiers) tuple. */
1089int
1090PyMac_GetEventRecord(PyObject *v, EventRecord *e)
1091{
1092 return PyArg_Parse(v, "(hll(hh)h)",
1093 &e->what,
1094 &e->message,
1095 &e->when,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001096 &e->where.h,
Guido van Rossum5279ec61995-01-26 22:56:59 +00001097 &e->where.v,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001098 &e->modifiers);
1099}
1100
1101/* Convert a Rect to an EventRecord object */
1102PyObject *
1103PyMac_BuildEventRecord(EventRecord *e)
1104{
1105 return Py_BuildValue("(hll(hh)h)",
1106 e->what,
1107 e->message,
1108 e->when,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001109 e->where.h,
Guido van Rossum5279ec61995-01-26 22:56:59 +00001110 e->where.v,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001111 e->modifiers);
Guido van Rossumb3404661995-01-22 18:36:13 +00001112}
Jack Jansenfa4d5d01995-11-15 15:19:29 +00001113
1114/* Convert Python object to Fixed */
1115int
1116PyMac_GetFixed(PyObject *v, Fixed *f)
1117{
1118 double d;
1119
1120 if( !PyArg_Parse(v, "d", &d))
1121 return 0;
1122 *f = (Fixed)(d * 0x10000);
Jack Jansen31dd5c01996-05-31 13:01:39 +00001123 return 1;
Jack Jansenfa4d5d01995-11-15 15:19:29 +00001124}
1125
1126/* Convert a Point to a Python object */
1127PyObject *
1128PyMac_BuildFixed(Fixed f)
1129{
1130 double d;
1131
1132 d = f;
1133 d = d / 0x10000;
1134 return Py_BuildValue("d", d);
1135}
1136
Jack Jansend58cd631998-04-21 15:24:39 +00001137/* Convert wide to/from Python int or (hi, lo) tuple. XXXX Should use Python longs */
1138int
1139PyMac_Getwide(PyObject *v, wide *rv)
1140{
1141 if (PyInt_Check(v)) {
1142 rv->hi = 0;
1143 rv->lo = PyInt_AsLong(v);
1144 if( rv->lo & 0x80000000 )
1145 rv->hi = -1;
1146 return 1;
1147 }
1148 return PyArg_Parse(v, "(ll)", &rv->hi, &rv->lo);
1149}
1150
1151
1152PyObject *
Jack Jansenbbf4be21998-04-23 13:20:17 +00001153PyMac_Buildwide(wide *w)
Jack Jansend58cd631998-04-21 15:24:39 +00001154{
Jack Jansenbbf4be21998-04-23 13:20:17 +00001155 if ( (w->hi == 0 && (w->lo & 0x80000000) == 0) ||
1156 (w->hi == -1 && (w->lo & 0x80000000) ) )
1157 return PyInt_FromLong(w->lo);
1158 return Py_BuildValue("(ll)", w->hi, w->lo);
Jack Jansend58cd631998-04-21 15:24:39 +00001159}