blob: 2dc6cfa548668a692e629f5f2927da0172b0dc8e [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
35#ifdef __CFM68K__
36#undef GetEventQueue
37#endif /* __CFM68K__ */
38
Jack Jansenf93c72a1994-12-14 14:07:50 +000039#include "Python.h"
Guido van Rossumbecdbec1995-02-14 01:27:24 +000040
Jack Jansenf93c72a1994-12-14 14:07:50 +000041#include "macglue.h"
Jack Jansen74162f31995-02-15 22:58:33 +000042#include "marshal.h"
43#include "import.h"
Jack Janseneda78631997-06-12 15:29:46 +000044#include "importdl.h"
Jack Jansenf93c72a1994-12-14 14:07:50 +000045
Jack Jansen819f1771995-08-14 12:35:10 +000046#include "pythonresources.h"
47
Jack Jansenf93c72a1994-12-14 14:07:50 +000048#include <OSUtils.h> /* for Set(Current)A5 */
Jack Jansene8e8ae01995-01-26 16:36:45 +000049#include <Files.h>
Jack Jansen8cd2b721995-02-13 11:33:28 +000050#include <StandardFile.h>
Jack Jansenf93c72a1994-12-14 14:07:50 +000051#include <Resources.h>
52#include <Memory.h>
Jack Jansenf93c72a1994-12-14 14:07:50 +000053#include <Windows.h>
Jack Jansene8e8ae01995-01-26 16:36:45 +000054#include <Traps.h>
Jack Jansenee23d6e1995-01-27 14:43:25 +000055#include <Processes.h>
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +000056#include <Fonts.h>
57#include <Menus.h>
Jack Jansen08305501995-06-18 20:03:40 +000058#include <TextUtils.h>
Guido van Rossumcc0d8791995-01-30 08:57:13 +000059#ifdef THINK_C
60#include <OSEvents.h> /* For EvQElPtr */
61#endif
Jack Jansen16df2aa1995-02-27 16:17:28 +000062#ifdef __MWERKS__
63#include <SIOUX.h>
64#endif
Jack Jansen911ad6b1996-03-05 16:56:24 +000065#ifdef USE_GUSI
66#include <TFileSpec.h> /* For Path2FSSpec */
Jack Jansen378815c1996-03-06 16:21:34 +000067#include <LowMem.h> /* For SetSFCurDir, etc */
Jack Jansenf6865f71996-09-04 15:24:59 +000068#include <GUSI.h>
Jack Jansen911ad6b1996-03-05 16:56:24 +000069#endif
Jack Jansenee23d6e1995-01-27 14:43:25 +000070
Jack Jansen3469e991996-09-06 00:30:45 +000071/* The ID of the Sioux apple menu */
72#define SIOUX_APPLEID 32000
73
Jack Jansenee23d6e1995-01-27 14:43:25 +000074#include <signal.h>
Jack Jansen74162f31995-02-15 22:58:33 +000075#include <stdio.h>
Jack Jansene8e8ae01995-01-26 16:36:45 +000076
Jack Jansenee23d6e1995-01-27 14:43:25 +000077/*
Jack Jansend1f06311996-08-01 15:23:54 +000078** When less than this amount of stackspace is left we
79** raise a MemoryError.
80*/
81#ifndef MINIMUM_STACK_SIZE
82#ifdef __powerc
83#define MINIMUM_STACK_SIZE 8192
84#else
85#define MINIMUM_STACK_SIZE 4096
86#endif
87#endif
88
89/*
Jack Jansen16df2aa1995-02-27 16:17:28 +000090** We have to be careful, since we can't handle
Jack Jansenee23d6e1995-01-27 14:43:25 +000091** things like updates (and they'll keep coming back if we don't
Jack Jansen16df2aa1995-02-27 16:17:28 +000092** handle them). Note that we don't know who has windows open, so
93** even handing updates off to SIOUX under MW isn't going to work.
Jack Jansenee23d6e1995-01-27 14:43:25 +000094*/
Jack Jansen0c968871997-08-26 13:20:34 +000095#define MAINLOOP_EVENTMASK (mDownMask|keyDownMask|osMask|activMask)
Jack Jansene8e8ae01995-01-26 16:36:45 +000096
97#include <signal.h>
Jack Jansenf93c72a1994-12-14 14:07:50 +000098
Guido van Rossumb3404661995-01-22 18:36:13 +000099/* XXX We should include Errors.h here, but it has a name conflict
Jack Jansen5f653091995-01-18 13:53:49 +0000100** with the python errors.h. */
101#define fnfErr -43
102
Jack Jansene8e8ae01995-01-26 16:36:45 +0000103/* Declared in macfsmodule.c: */
104extern FSSpec *mfs_GetFSSpecFSSpec();
105
Jack Jansenee23d6e1995-01-27 14:43:25 +0000106/* Interrupt code variables: */
107static int interrupted; /* Set to true when cmd-. seen */
108static RETSIGTYPE intcatcher Py_PROTO((int));
109
Jack Jansen36ed5061997-06-20 16:18:15 +0000110static int PyMac_DoYield Py_PROTO((int, int));
111static int PyMac_Yield Py_PROTO((void));
Jack Jansenf6865f71996-09-04 15:24:59 +0000112
Jack Jansene8e8ae01995-01-26 16:36:45 +0000113/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000114** These are the real scheduling parameters that control what we check
115** in the event loop, and how often we check. The values are initialized
116** from pyMac_SchedParamStruct.
117*/
118
119struct real_sched_param_struct {
120 int check_interrupt; /* if true check for command-dot */
121 int process_events; /* if nonzero enable evt processing, this mask */
122 int besocial; /* if nonzero be a little social with CPU */
123 unsigned long check_interval; /* how often to check, in ticks */
124 unsigned long bg_yield; /* yield so long when in background */
125 /* these are computed from previous and clock and such */
126 int enabled; /* check_interrupt OR process_event OR yield */
127 unsigned long next_check; /* when to check/yield next, in ticks */
128};
129
130static struct real_sched_param_struct schedparams =
131 { 1, MAINLOOP_EVENTMASK, 1, 15, 15, 1, 0};
132
Jack Jansen819f1771995-08-14 12:35:10 +0000133/*
Jack Jansenf6865f71996-09-04 15:24:59 +0000134** Workaround for sioux/gusi combo: set when we are exiting
135*/
136int PyMac_ConsoleIsDead;
137
138/*
Jack Jansencaa7c461997-06-12 10:49:13 +0000139** Sioux menu bar, saved early so we can restore it
140*/
141static Handle sioux_mbar;
142
143/*
Jack Jansen819f1771995-08-14 12:35:10 +0000144** Some stuff for our GetDirectory and PromptGetFile routines
145*/
146struct hook_args {
147 int selectcur_hit; /* Set to true when "select current" selected */
148 char *prompt; /* The prompt */
149};
150static DlgHookYDUPP myhook_upp;
151static int upp_inited = 0;
152
Jack Jansen36ed5061997-06-20 16:18:15 +0000153/*
154** The python-code event handler
155*/
156static PyObject *python_event_handler;
157
Jack Jansen378815c1996-03-06 16:21:34 +0000158#ifdef USE_GUSI
159/*
160** GUSI (1.6.0 and earlier, at the least) do not set the MacOS idea of
161** the working directory. Hence, we call this routine after each call
162** to chdir() to rectify things.
163*/
164void
165PyMac_FixGUSIcd()
166{
167 WDPBRec pb;
168 FSSpec curdirfss;
169
170 if ( Path2FSSpec(":x", &curdirfss) != noErr )
171 return;
172
173 /* Set MacOS "working directory" */
174 pb.ioNamePtr= "\p";
175 pb.ioVRefNum= curdirfss.vRefNum;
176 pb.ioWDDirID= curdirfss.parID;
Jack Jansen08c3be31997-04-08 15:27:00 +0000177 if (PBHSetVolSync(&pb) != noErr)
Jack Jansen378815c1996-03-06 16:21:34 +0000178 return;
Jack Jansen378815c1996-03-06 16:21:34 +0000179}
Jack Jansen7ac70af1996-08-19 11:01:05 +0000180
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000181/*
182** SpinCursor (needed by GUSI) drags in heaps of stuff, so we
183** provide a dummy here.
184*/
Jack Jansencfadbd41996-08-19 11:36:25 +0000185void SpinCursor(short x) { /* Dummy */ }
Jack Jansenefaada71998-02-20 16:03:15 +0000186void RotateCursor(short x) { /* Dummy */ }
Jack Jansencfadbd41996-08-19 11:36:25 +0000187
Jack Jansenf6865f71996-09-04 15:24:59 +0000188/*
189** Replacement GUSI Spin function
190*/
191static int
192PyMac_GUSISpin(spin_msg msg, long arg)
193{
Jack Jansene3ae0df1997-06-03 15:28:29 +0000194 static Boolean inForeground = true;
195 int maxsleep = 6; /* 6 ticks is "normal" sleeptime */
Jack Jansenf6865f71996-09-04 15:24:59 +0000196
197 if (PyMac_ConsoleIsDead) return 0;
198#if 0
199 if (inForeground)
200 SpinCursor(msg == SP_AUTO_SPIN ? short(arg) : 1);
201#endif
202
203 if (interrupted) return -1;
204
Jack Jansene3ae0df1997-06-03 15:28:29 +0000205 if ( msg == SP_AUTO_SPIN )
206 maxsleep = 0;
207 if ( msg==SP_SLEEP||msg==SP_SELECT )
208 maxsleep = arg;
Jack Jansenf6865f71996-09-04 15:24:59 +0000209
Jack Jansene3ae0df1997-06-03 15:28:29 +0000210 PyMac_DoYield(maxsleep, 0); /* XXXX or is it safe to call python here? */
Jack Jansenf6865f71996-09-04 15:24:59 +0000211
212 return 0;
213}
214
215void
216PyMac_SetGUSISpin() {
217 GUSISetHook(GUSI_SpinHook, (GUSIHook)PyMac_GUSISpin);
218}
219
Jack Jansena39f1b01997-05-23 15:35:14 +0000220/* Called at exit() time thru atexit(), to stop event processing */
221void
222PyMac_StopGUSISpin() {
223 PyMac_ConsoleIsDead = 1;
224}
225
226/*
227** Replacement routines for the PLstr... functions so we don't need
228** StdCLib. Moreover, that implementation is broken under cfm68k...
229*/
230void
231PLstrcpy(to, fr)
232 unsigned char *to, *fr;
233{
234 memcpy(to, fr, fr[0]+1);
235}
236
237int
238PLstrcmp(s1, s2)
239 unsigned char *s1, *s2;
240{
241 int res;
242 int l = s1[0] < s2[0] ? s1[0] : s2[0];
243
244 res = memcmp(s1+1, s2+1, l);
245 if ( res != 0 )
246 return res;
247
248 if ( s1 < s2 )
249 return -1;
250 else if ( s1 > s2 )
251 return 1;
252 else
253 return 0;
254}
255
256unsigned char *
257PLstrrchr(str, chr)
258 unsigned char *str;
259 unsigned char chr;
260{
261 unsigned char *ptr = 0;
262 unsigned char *p;
263
264 for(p=str+1; p<str+str[0]; p++)
265 if ( *p == chr )
266 ptr = p;
267 return ptr;
268}
269
270#endif /* USE_GUSI */
Jack Jansen378815c1996-03-06 16:21:34 +0000271
Jack Jansen819f1771995-08-14 12:35:10 +0000272
Jack Jansen5f653091995-01-18 13:53:49 +0000273/* Convert C to Pascal string. Returns pointer to static buffer. */
274unsigned char *
275Pstring(char *str)
276{
277 static Str255 buf;
278 int len;
279
280 len = strlen(str);
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000281 if (len > 255)
282 len = 255;
Jack Jansen5f653091995-01-18 13:53:49 +0000283 buf[0] = (unsigned char)len;
284 strncpy((char *)buf+1, str, len);
285 return buf;
286}
287
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000288/* Like strerror() but for Mac OS error numbers */
289char *PyMac_StrError(int err)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000290{
291 static char buf[256];
292 Handle h;
293 char *str;
294
295 h = GetResource('Estr', err);
296 if ( h ) {
297 HLock(h);
298 str = (char *)*h;
299 memcpy(buf, str+1, (unsigned char)str[0]);
Guido van Rossumcc9bc8f1995-02-13 16:17:03 +0000300 buf[(unsigned char)str[0]] = '\0';
Jack Jansenf93c72a1994-12-14 14:07:50 +0000301 HUnlock(h);
302 ReleaseResource(h);
303 } else {
304 sprintf(buf, "Mac OS error code %d", err);
305 }
306 return buf;
307}
308
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000309/* Exception object shared by all Mac specific modules for Mac OS errors */
310PyObject *PyMac_OSErrException;
311
312/* Initialize and return PyMac_OSErrException */
313PyObject *
314PyMac_GetOSErrException()
315{
316 if (PyMac_OSErrException == NULL)
317 PyMac_OSErrException = PyString_FromString("Mac OS Error");
318 return PyMac_OSErrException;
319}
320
Jack Jansenf93c72a1994-12-14 14:07:50 +0000321/* Set a MAC-specific error from errno, and return NULL; return None if no error */
322PyObject *
Guido van Rossumfffb8bb1995-01-12 12:37:24 +0000323PyErr_Mac(PyObject *eobj, int err)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000324{
325 char *msg;
326 PyObject *v;
Jack Jansenf93c72a1994-12-14 14:07:50 +0000327
Guido van Rossum8f691791995-01-18 23:57:26 +0000328 if (err == 0 && !PyErr_Occurred()) {
Jack Jansenf93c72a1994-12-14 14:07:50 +0000329 Py_INCREF(Py_None);
330 return Py_None;
331 }
Guido van Rossum8f691791995-01-18 23:57:26 +0000332 if (err == -1 && PyErr_Occurred())
333 return NULL;
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000334 msg = PyMac_StrError(err);
Jack Jansenf93c72a1994-12-14 14:07:50 +0000335 v = Py_BuildValue("(is)", err, msg);
336 PyErr_SetObject(eobj, v);
337 Py_DECREF(v);
338 return NULL;
339}
340
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000341/* Call PyErr_Mac with PyMac_OSErrException */
342PyObject *
343PyMac_Error(OSErr err)
344{
345 return PyErr_Mac(PyMac_GetOSErrException(), err);
346}
347
Jack Jansen1ed95291996-07-22 15:25:10 +0000348#ifdef USE_STACKCHECK
349/* Check for stack overflow */
350int
351PyOS_CheckStack()
352{
353 long left;
354
355 left = StackSpace();
Jack Jansend1f06311996-08-01 15:23:54 +0000356 if ( left < MINIMUM_STACK_SIZE )
Jack Jansen1ed95291996-07-22 15:25:10 +0000357 return -1;
358 return 0;
359}
360#endif /* USE_STACKCHECK */
361
Jack Jansenee23d6e1995-01-27 14:43:25 +0000362/* The catcher routine (which may not be used for all compilers) */
363static RETSIGTYPE
364intcatcher(sig)
365 int sig;
366{
367 interrupted = 1;
368 signal(SIGINT, intcatcher);
369}
370
371void
372PyOS_InitInterrupts()
373{
374 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
375 signal(SIGINT, intcatcher);
376}
377
Jack Jansena8441de1997-08-08 14:57:37 +0000378void
379PyOS_FiniInterrupts()
380{
381}
382
Jack Jansenee23d6e1995-01-27 14:43:25 +0000383/*
384** This routine scans the event queue looking for cmd-.
385** This is the only way to get an interrupt under THINK (since it
386** doesn't do SIGINT handling), but is also used under MW, when
387** the full-fledged event loop is disabled. This way, we can at least
388** interrupt a runaway python program.
389*/
390static void
391scan_event_queue(flush)
392 int flush;
393{
394 register EvQElPtr q;
395
Jack Jansenefaada71998-02-20 16:03:15 +0000396 q = (EvQElPtr) LMGetEventQueue()->qHead;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000397
398 for (; q; q = (EvQElPtr)q->qLink) {
399 if (q->evtQWhat == keyDown &&
400 (char)q->evtQMessage == '.' &&
401 (q->evtQModifiers & cmdKey) != 0) {
402 if ( flush )
403 FlushEvents(keyDownMask, 0);
404 interrupted = 1;
405 break;
406 }
407 }
408}
409
410int
Jack Jansen36ed5061997-06-20 16:18:15 +0000411PyErr_CheckSignals()
Jack Jansenee23d6e1995-01-27 14:43:25 +0000412{
Jack Jansene3ae0df1997-06-03 15:28:29 +0000413 if (schedparams.enabled) {
414 if ( (unsigned long)LMGetTicks() > schedparams.next_check ) {
Jack Jansen36ed5061997-06-20 16:18:15 +0000415 if ( PyMac_Yield() < 0)
416 return -1;
Jack Jansene3ae0df1997-06-03 15:28:29 +0000417 schedparams.next_check = (unsigned long)LMGetTicks()
418 + schedparams.check_interval;
419 if (interrupted) {
Jack Jansencaa7c461997-06-12 10:49:13 +0000420 scan_event_queue(1); /* Eat events up to cmd-. */
Jack Jansene3ae0df1997-06-03 15:28:29 +0000421 interrupted = 0;
Jack Jansen36ed5061997-06-20 16:18:15 +0000422 PyErr_SetNone(PyExc_KeyboardInterrupt);
423 return -1;
Jack Jansene3ae0df1997-06-03 15:28:29 +0000424 }
425 }
Jack Jansenee23d6e1995-01-27 14:43:25 +0000426 }
427 return 0;
428}
429
Jack Jansen36ed5061997-06-20 16:18:15 +0000430int
431PyOS_InterruptOccurred()
432{
433 scan_event_queue(1);
434 return interrupted;
435}
Jack Jansenee23d6e1995-01-27 14:43:25 +0000436/* Check whether we are in the foreground */
437int
438PyMac_InForeground()
439{
440 static ProcessSerialNumber ours;
441 static inited;
442 ProcessSerialNumber curfg;
443 Boolean eq;
444
Jack Jansene3ae0df1997-06-03 15:28:29 +0000445 if ( inited == 0 ) {
Jack Jansenee23d6e1995-01-27 14:43:25 +0000446 (void)GetCurrentProcess(&ours);
Jack Jansene3ae0df1997-06-03 15:28:29 +0000447 inited = 1;
448 }
Jack Jansenee23d6e1995-01-27 14:43:25 +0000449 if ( GetFrontProcess(&curfg) < 0 )
450 eq = 1;
451 else if ( SameProcess(&ours, &curfg, &eq) < 0 )
452 eq = 1;
453 return (int)eq;
454
455}
456
Jack Jansen36ed5061997-06-20 16:18:15 +0000457int
458PyMac_SetEventHandler(PyObject *evh)
459{
460 if ( evh && python_event_handler ) {
461 PyErr_SetString(PyExc_RuntimeError, "Python event handler already set");
462 return 0;
463 }
464 if ( python_event_handler )
465 Py_DECREF(python_event_handler);
466 if ( evh )
467 Py_INCREF(evh);
468 python_event_handler = evh;
469 return 1;
470}
471
Jack Jansenf93c72a1994-12-14 14:07:50 +0000472/*
Jack Jansena76382a1995-02-02 14:25:56 +0000473** Handle an event, either one found in the mainloop eventhandler or
474** one passed back from the python program.
475*/
476void
Jack Jansen36ed5061997-06-20 16:18:15 +0000477PyMac_HandleEventIntern(evp)
Jack Jansena76382a1995-02-02 14:25:56 +0000478 EventRecord *evp;
479{
Jack Jansen0c968871997-08-26 13:20:34 +0000480 if ( evp->what == mouseDown ) {
481 WindowPtr wp;
482
483 if ( FindWindow(evp->where, &wp) == inSysWindow ) {
484 SystemClick(evp, wp);
485 return;
486 }
487 }
Jack Jansena76382a1995-02-02 14:25:56 +0000488#ifdef __MWERKS__
Jack Jansen38e97661995-11-10 14:53:00 +0000489 {
490 int siouxdidit;
491
492 /* If SIOUX wants it we're done */
493 siouxdidit = SIOUXHandleOneEvent(evp);
494 if ( siouxdidit )
495 return;
496 }
Jack Jansena76382a1995-02-02 14:25:56 +0000497#else
Jack Jansen0c968871997-08-26 13:20:34 +0000498 /* Other compilers are just unlucky... */
Jack Jansena76382a1995-02-02 14:25:56 +0000499#endif /* !__MWERKS__ */
Jack Jansen36ed5061997-06-20 16:18:15 +0000500}
501
502/*
503** Handle an event, either through HandleEvent or by passing it to the Python
504** event handler.
505*/
506int
507PyMac_HandleEvent(evp)
508 EventRecord *evp;
509{
510 PyObject *rv;
511
512 if ( python_event_handler ) {
513 rv = PyObject_CallFunction(python_event_handler, "(O&)",
514 PyMac_BuildEventRecord, evp);
515 if ( rv )
516 Py_DECREF(rv);
517 else
518 return -1; /* Propagate exception */
519 } else {
520 PyMac_HandleEventIntern(evp);
521 }
522 return 0;
Jack Jansena76382a1995-02-02 14:25:56 +0000523}
524
525/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000526** Yield the CPU to other tasks without processing events.
Jack Jansene8e8ae01995-01-26 16:36:45 +0000527*/
Jack Jansen36ed5061997-06-20 16:18:15 +0000528static int
Jack Jansene3ae0df1997-06-03 15:28:29 +0000529PyMac_DoYield(int maxsleep, int maycallpython)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000530{
531 EventRecord ev;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000532 int gotone;
Jack Jansene3ae0df1997-06-03 15:28:29 +0000533 long latest_time_ready;
Jack Jansen36ed5061997-06-20 16:18:15 +0000534 static int in_here = 0;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000535
Jack Jansen36ed5061997-06-20 16:18:15 +0000536 in_here++;
Jack Jansene3ae0df1997-06-03 15:28:29 +0000537 /*
538 ** First check for interrupts, if wanted.
539 ** This sets a flag that will be picked up at an appropriate
540 ** moment in the mainloop.
541 */
542 if (schedparams.check_interrupt)
Jack Jansenee23d6e1995-01-27 14:43:25 +0000543 scan_event_queue(0);
Jack Jansene3ae0df1997-06-03 15:28:29 +0000544
545 /* XXXX Implementing an idle routine goes here */
Jack Jansene8e8ae01995-01-26 16:36:45 +0000546
Jack Jansene3ae0df1997-06-03 15:28:29 +0000547 /*
548 ** Check which of the eventloop cases we have:
549 ** - process events
550 ** - don't process events but do yield
551 ** - do neither
552 */
Jack Jansen36ed5061997-06-20 16:18:15 +0000553 if( in_here > 1 || !schedparams.process_events ||
554 (python_event_handler && !maycallpython) ) {
Jack Jansene3ae0df1997-06-03 15:28:29 +0000555 if ( maxsleep >= 0 ) {
Jack Jansene8e8ae01995-01-26 16:36:45 +0000556 SystemTask();
Jack Jansene3ae0df1997-06-03 15:28:29 +0000557 }
558 } else {
559 latest_time_ready = LMGetTicks() + maxsleep;
560 while ( maxsleep >= 0 ) {
Jack Jansen0c968871997-08-26 13:20:34 +0000561 /* XXXX Hack by Jack.
562 ** In time.sleep() you can click to another application
563 ** once only. If you come back to Python you cannot get away
564 ** again.
565 **/
Jack Jansen36ed5061997-06-20 16:18:15 +0000566 gotone = WaitNextEvent(schedparams.process_events, &ev, maxsleep, NULL);
Jack Jansene3ae0df1997-06-03 15:28:29 +0000567 /* Get out quickly if nothing interesting is happening */
568 if ( !gotone || ev.what == nullEvent )
569 break;
Jack Jansen36ed5061997-06-20 16:18:15 +0000570 if ( PyMac_HandleEvent(&ev) < 0 ) {
571 in_here--;
572 return -1;
573 }
Jack Jansene3ae0df1997-06-03 15:28:29 +0000574 maxsleep = latest_time_ready - LMGetTicks();
575 }
Jack Jansenf93c72a1994-12-14 14:07:50 +0000576 }
Jack Jansen36ed5061997-06-20 16:18:15 +0000577 in_here--;
578 return 0;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000579}
580
581/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000582** Process events and/or yield the CPU to other tasks if opportune
Jack Jansene8e8ae01995-01-26 16:36:45 +0000583*/
Jack Jansen36ed5061997-06-20 16:18:15 +0000584int
Jack Jansene8e8ae01995-01-26 16:36:45 +0000585PyMac_Yield() {
Jack Jansene3ae0df1997-06-03 15:28:29 +0000586 unsigned long maxsleep;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000587
Jack Jansene3ae0df1997-06-03 15:28:29 +0000588 if( PyMac_InForeground() )
589 maxsleep = 0;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000590 else
Jack Jansene3ae0df1997-06-03 15:28:29 +0000591 maxsleep = schedparams.bg_yield;
592
Jack Jansen36ed5061997-06-20 16:18:15 +0000593 return PyMac_DoYield(maxsleep, 1);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000594}
595
596/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000597** Return current scheduler parameters
Jack Jansene8e8ae01995-01-26 16:36:45 +0000598*/
Jack Jansene3ae0df1997-06-03 15:28:29 +0000599void
600PyMac_GetSchedParams(PyMacSchedParams *sp)
Jack Jansene8e8ae01995-01-26 16:36:45 +0000601{
Jack Jansene3ae0df1997-06-03 15:28:29 +0000602 sp->check_interrupt = schedparams.check_interrupt;
603 sp->process_events = schedparams.process_events;
604 sp->besocial = schedparams.besocial;
605 sp->check_interval = schedparams.check_interval / 60.0;
606 sp->bg_yield = schedparams.bg_yield / 60.0;
Jack Jansenf93c72a1994-12-14 14:07:50 +0000607}
Jack Jansenf6865f71996-09-04 15:24:59 +0000608
Jack Jansen74162f31995-02-15 22:58:33 +0000609/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000610** Set current scheduler parameters
611*/
612void
613PyMac_SetSchedParams(PyMacSchedParams *sp)
614{
615 schedparams.check_interrupt = sp->check_interrupt;
616 schedparams.process_events = sp->process_events;
617 schedparams.besocial = sp->besocial;
618 schedparams.check_interval = (unsigned long)(sp->check_interval*60);
619 schedparams.bg_yield = (unsigned long)(sp->bg_yield*60);
620 if ( schedparams.check_interrupt || schedparams.process_events ||
621 schedparams.besocial )
622 schedparams.enabled = 1;
623 else
624 schedparams.enabled = 0;
625 schedparams.next_check = 0; /* Check immedeately */
626}
Jack Jansencaa7c461997-06-12 10:49:13 +0000627
Jack Jansene3ae0df1997-06-03 15:28:29 +0000628/*
Jack Jansen3469e991996-09-06 00:30:45 +0000629** Install our menu bar.
630*/
631void
632PyMac_InitMenuBar()
633{
Jack Jansen3469e991996-09-06 00:30:45 +0000634 MenuHandle applemenu;
635
Jack Jansencaa7c461997-06-12 10:49:13 +0000636 if ( (sioux_mbar=GetMenuBar()) == NULL ) {
637 /* Sioux menu not installed yet. Do so */
638 SIOUXSetupMenus();
639 if ( (sioux_mbar=GetMenuBar()) == NULL )
640 return;
641 }
Jack Jansen08c3be31997-04-08 15:27:00 +0000642 if ( (applemenu=GetMenuHandle(SIOUX_APPLEID)) == NULL ) return;
Jack Jansen3469e991996-09-06 00:30:45 +0000643 SetMenuItemText(applemenu, 1, "\pAbout Python...");
644}
645
646/*
Jack Jansencaa7c461997-06-12 10:49:13 +0000647** Restore sioux menu bar
648*/
649void
650PyMac_RestoreMenuBar()
651{
Jack Janseneda78631997-06-12 15:29:46 +0000652 if ( sioux_mbar ) {
Jack Jansencaa7c461997-06-12 10:49:13 +0000653 SetMenuBar(sioux_mbar);
Jack Janseneda78631997-06-12 15:29:46 +0000654 DrawMenuBar();
Jack Jansenefaada71998-02-20 16:03:15 +0000655 } else
656 PyMac_InitMenuBar();
Jack Jansencaa7c461997-06-12 10:49:13 +0000657}
658
659
660/*
Jack Jansen3469e991996-09-06 00:30:45 +0000661** Our replacement about box
662*/
663void
664SIOUXDoAboutBox(void)
665{
666 DialogPtr theDialog;
Jack Jansend617c571996-09-22 22:14:30 +0000667 WindowRef theWindow;
668 CGrafPtr thePort;
Jack Jansen3469e991996-09-06 00:30:45 +0000669 short item;
Jack Jansend617c571996-09-22 22:14:30 +0000670 short xpos, ypos, width, height, swidth, sheight;
Jack Jansen3469e991996-09-06 00:30:45 +0000671
672 if( (theDialog = GetNewDialog(ABOUT_ID, NULL, (WindowPtr)-1)) == NULL )
673 return;
Jack Jansend617c571996-09-22 22:14:30 +0000674 theWindow = GetDialogWindow(theDialog);
675 thePort = GetWindowPort(theWindow);
676 width = thePort->portRect.right - thePort->portRect.left;
677 height = thePort->portRect.bottom - thePort->portRect.top;
678 swidth = qd.screenBits.bounds.right - qd.screenBits.bounds.left;
679 sheight = qd.screenBits.bounds.bottom - qd.screenBits.bounds.top - LMGetMBarHeight();
680 xpos = (swidth-width)/2;
Jack Jansen0e06e7e1996-09-23 15:51:06 +0000681 ypos = (sheight-height)/5 + LMGetMBarHeight();
Jack Jansend617c571996-09-22 22:14:30 +0000682 MoveWindow(theWindow, xpos, ypos, 0);
683 ShowWindow(theWindow);
Jack Jansen3469e991996-09-06 00:30:45 +0000684 ModalDialog(NULL, &item);
685 DisposeDialog(theDialog);
686}
687
688/*
Jack Jansen74162f31995-02-15 22:58:33 +0000689** Returns true if the argument has a resource fork, and it contains
690** a 'PYC ' resource of the correct name
691*/
692int
Jack Janseneda78631997-06-12 15:29:46 +0000693PyMac_FindResourceModule(obj, module, filename)
694PyStringObject *obj;
Jack Jansen74162f31995-02-15 22:58:33 +0000695char *module;
696char *filename;
697{
698 FSSpec fss;
699 FInfo finfo;
700 short oldrh, filerh;
701 int ok;
702 Handle h;
Jack Janseneda78631997-06-12 15:29:46 +0000703
704#ifdef INTERN_STRINGS
705 /*
706 ** If we have interning find_module takes care of interning all
707 ** sys.path components. We then keep a record of all sys.path
708 ** components for which GetFInfo has failed (usually because the
709 ** component in question is a folder), and we don't try opening these
710 ** as resource files again.
711 */
712#define MAXPATHCOMPONENTS 32
713 static PyStringObject *not_a_file[MAXPATHCOMPONENTS];
714 static int max_not_a_file = 0;
715 int i;
716
717 if ( obj->ob_sinterned ) {
718 for( i=0; i< max_not_a_file; i++ )
719 if ( obj == not_a_file[i] )
720 return 0;
721 }
722#endif /* INTERN_STRINGS */
723
Jack Jansen8096daa1996-11-09 18:43:44 +0000724 if ( strcmp(filename, PyMac_ApplicationPath) == 0 ) {
725 /*
726 ** Special case: the application itself. Use a shortcut to
727 ** forestall opening and closing the application numerous times
728 ** (which is dead slow when running from CDROM)
729 */
730 oldrh = CurResFile();
731 UseResFile(PyMac_AppRefNum);
732 filerh = -1;
733 } else {
Jack Janseneda78631997-06-12 15:29:46 +0000734 if ( FSMakeFSSpec(0, 0, Pstring(filename), &fss) != noErr ||
735 FSpGetFInfo(&fss, &finfo) != noErr ) {
736#ifdef INTERN_STRINGS
737 if ( max_not_a_file < MAXPATHCOMPONENTS && obj->ob_sinterned )
738 not_a_file[max_not_a_file++] = obj;
739#endif /* INTERN_STRINGS */
740 /* doesn't exist or is folder */
741 return 0;
742 }
Jack Jansen8096daa1996-11-09 18:43:44 +0000743 oldrh = CurResFile();
744 filerh = FSpOpenResFile(&fss, fsRdPerm);
745 if ( filerh == -1 )
746 return 0;
747 UseResFile(filerh);
748 }
Jack Jansen74162f31995-02-15 22:58:33 +0000749 SetResLoad(0);
750 h = Get1NamedResource('PYC ', Pstring(module));
751 SetResLoad(1);
752 ok = (h != NULL);
Jack Jansen8096daa1996-11-09 18:43:44 +0000753 if ( filerh != -1 )
754 CloseResFile(filerh);
Jack Jansen74162f31995-02-15 22:58:33 +0000755 UseResFile(oldrh);
756 return ok;
757}
758
759/*
760** Load the specified module from a resource
761*/
762PyObject *
763PyMac_LoadResourceModule(module, filename)
764char *module;
765char *filename;
766{
767 FSSpec fss;
768 FInfo finfo;
769 short oldrh, filerh;
Jack Jansen74162f31995-02-15 22:58:33 +0000770 Handle h;
771 OSErr err;
772 PyObject *m, *co;
773 long num, size;
774
Jack Jansen8096daa1996-11-09 18:43:44 +0000775 if ( strcmp(filename, PyMac_ApplicationPath) == 0 ) {
776 /*
777 ** Special case: the application itself. Use a shortcut to
778 ** forestall opening and closing the application numerous times
779 ** (which is dead slow when running from CDROM)
780 */
781 oldrh = CurResFile();
782 UseResFile(PyMac_AppRefNum);
783 filerh = -1;
784 } else {
785 if ( (err=FSMakeFSSpec(0, 0, Pstring(filename), &fss)) != noErr )
786 goto error;
787 if ( (err=FSpGetFInfo(&fss, &finfo)) != noErr )
788 goto error;
789 oldrh = CurResFile();
790 filerh = FSpOpenResFile(&fss, fsRdPerm);
791 if ( filerh == -1 ) {
792 err = ResError();
793 goto error;
794 }
795 UseResFile(filerh);
Jack Jansen74162f31995-02-15 22:58:33 +0000796 }
Jack Jansen74162f31995-02-15 22:58:33 +0000797 h = Get1NamedResource('PYC ', Pstring(module));
798 if ( h == NULL ) {
799 err = ResError();
800 goto error;
801 }
802 HLock(h);
803 /*
804 ** XXXX The next few lines are intimately tied to the format of pyc
805 ** files. I'm not sure whether this code should be here or in import.c -- Jack
806 */
807 size = GetHandleSize(h);
808 if ( size < 8 ) {
809 PyErr_SetString(PyExc_ImportError, "Resource too small");
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000810 co = NULL;
Jack Jansen74162f31995-02-15 22:58:33 +0000811 } else {
812 num = (*h)[0] & 0xff;
813 num = num | (((*h)[1] & 0xff) << 8);
814 num = num | (((*h)[2] & 0xff) << 16);
815 num = num | (((*h)[3] & 0xff) << 24);
816 if ( num != PyImport_GetMagicNumber() ) {
817 PyErr_SetString(PyExc_ImportError, "Bad MAGIC in resource");
818 co = NULL;
819 } else {
820 co = PyMarshal_ReadObjectFromString((*h)+8, size-8);
821 }
822 }
823 HUnlock(h);
Jack Jansen8096daa1996-11-09 18:43:44 +0000824 if ( filerh != -1 )
825 CloseResFile(filerh);
Jack Jansen74162f31995-02-15 22:58:33 +0000826 UseResFile(oldrh);
827 if ( co ) {
828 m = PyImport_ExecCodeModule(module, co);
829 Py_DECREF(co);
830 } else {
831 m = NULL;
832 }
Jack Jansenfa68b071998-06-26 14:52:04 +0000833 if (Py_VerboseFlag)
834 fprintf(stderr, "import %s # pyc resource from %s\n",
835 module, filename);
Jack Jansen74162f31995-02-15 22:58:33 +0000836 return m;
837error:
838 {
839 char buf[512];
840
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000841 sprintf(buf, "%s: %s", filename, PyMac_StrError(err));
Jack Jansen74162f31995-02-15 22:58:33 +0000842 PyErr_SetString(PyExc_ImportError, buf);
843 return NULL;
844 }
845}
Guido van Rossum24a45e31995-02-20 23:45:53 +0000846
Jack Jansen3ec804a1995-02-20 15:56:10 +0000847/*
Jack Janseneda78631997-06-12 15:29:46 +0000848** Look for a module in a single folder. Upon entry buf and len
849** point to the folder to search, upon exit they refer to the full
850** pathname of the module found (if any).
851*/
852struct filedescr *
853PyMac_FindModuleExtension(char *buf, int *lenp, char *module)
854{
855 struct filedescr *fdp;
856 unsigned char fnbuf[64];
857 int modnamelen = strlen(module);
858 FSSpec fss;
859 short refnum;
860 long dirid;
861
862 /*
863 ** Copy the module name to the buffer (already :-terminated)
864 ** We also copy the first suffix, if this matches immedeately we're
865 ** lucky and return immedeately.
866 */
867 if ( !_PyImport_Filetab[0].suffix )
868 return 0;
869
Jack Jansenc73f83c1997-10-07 21:48:31 +0000870#if 0
871 /* Pre 1.5a4 */
Jack Janseneda78631997-06-12 15:29:46 +0000872 strcpy(buf+*lenp, module);
873 strcpy(buf+*lenp+modnamelen, _PyImport_Filetab[0].suffix);
Jack Jansenc73f83c1997-10-07 21:48:31 +0000874#else
875 strcpy(buf+*lenp, _PyImport_Filetab[0].suffix);
876#endif
Jack Janseneda78631997-06-12 15:29:46 +0000877 if ( FSMakeFSSpec(0, 0, Pstring(buf), &fss) == noErr )
878 return _PyImport_Filetab;
879 /*
880 ** We cannot check for fnfErr (unfortunately), it can mean either that
881 ** the file doesn't exist (fine, we try others) or the path leading to it.
882 */
883 refnum = fss.vRefNum;
884 dirid = fss.parID;
885 if ( refnum == 0 || dirid == 0 ) /* Fail on nonexistent dir */
886 return 0;
887 /*
888 ** We now have the folder parameters. Setup the field for the filename
889 */
890 if ( modnamelen > 54 ) return 0; /* Leave room for extension */
891 strcpy((char *)fnbuf+1, module);
892
893 for( fdp = _PyImport_Filetab+1; fdp->suffix; fdp++ ) {
894 strcpy((char *)fnbuf+1+modnamelen, fdp->suffix);
895 fnbuf[0] = strlen((char *)fnbuf+1);
896 if (Py_VerboseFlag > 1)
897 fprintf(stderr, "# trying %s%s\n", buf, fdp->suffix);
898 if ( FSMakeFSSpec(refnum, dirid, fnbuf, &fss) == noErr ) {
899 /* Found it. */
Jack Jansenc73f83c1997-10-07 21:48:31 +0000900#if 0
Jack Janseneda78631997-06-12 15:29:46 +0000901 strcpy(buf+*lenp+modnamelen, fdp->suffix);
Jack Jansenc73f83c1997-10-07 21:48:31 +0000902#else
Jack Jansen21364901997-10-08 15:32:46 +0000903 strcpy(buf+*lenp, fdp->suffix);
Jack Jansenc73f83c1997-10-07 21:48:31 +0000904#endif
Jack Janseneda78631997-06-12 15:29:46 +0000905 *lenp = strlen(buf);
906 return fdp;
907 }
908 }
909 return 0;
910}
911
912#if 0
913int
914PyMac_FileExists(char *name)
915{
916 FSSpec fss;
917
918 if ( FSMakeFSSpec(0, 0, Pstring(name), &fss) == noErr )
919 return 1;
920 return 0;
921}
922#endif
923
924/*
Jack Jansen3ec804a1995-02-20 15:56:10 +0000925** Helper routine for GetDirectory
926*/
Guido van Rossum24a45e31995-02-20 23:45:53 +0000927static pascal short
Jack Jansen819f1771995-08-14 12:35:10 +0000928myhook_proc(short item, DialogPtr theDialog, struct hook_args *dataptr)
Jack Jansen3ec804a1995-02-20 15:56:10 +0000929{
Jack Jansen819f1771995-08-14 12:35:10 +0000930 if ( item == sfHookFirstCall && dataptr->prompt) {
931 Handle prompth;
932 short type;
933 Rect rect;
934
935 GetDialogItem(theDialog, PROMPT_ITEM, &type, &prompth, &rect);
936 if ( prompth )
937 SetDialogItemText(prompth, (unsigned char *)dataptr->prompt);
938 } else
Jack Jansen3ec804a1995-02-20 15:56:10 +0000939 if ( item == SELECTCUR_ITEM ) {
940 item = sfItemCancelButton;
Jack Jansen819f1771995-08-14 12:35:10 +0000941 dataptr->selectcur_hit = 1;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000942 }
943 return item;
944}
945
946/*
947** Ask the user for a directory. I still can't understand
948** why Apple doesn't provide a standard solution for this...
949*/
950int
Jack Jansen819f1771995-08-14 12:35:10 +0000951PyMac_GetDirectory(dirfss, prompt)
Jack Jansen3ec804a1995-02-20 15:56:10 +0000952 FSSpec *dirfss;
Jack Jansen819f1771995-08-14 12:35:10 +0000953 char *prompt;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000954{
955 static SFTypeList list = {'fldr', 0, 0, 0};
956 static Point where = {-1, -1};
Jack Jansen3ec804a1995-02-20 15:56:10 +0000957 StandardFileReply reply;
Jack Jansen819f1771995-08-14 12:35:10 +0000958 struct hook_args hook_args;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000959
960 if ( !upp_inited ) {
961 myhook_upp = NewDlgHookYDProc(myhook_proc);
962 upp_inited = 1;
963 }
Jack Jansen819f1771995-08-14 12:35:10 +0000964 if ( prompt && *prompt )
965 hook_args.prompt = (char *)Pstring(prompt);
966 else
967 hook_args.prompt = NULL;
968 hook_args.selectcur_hit = 0;
Guido van Rossum24a45e31995-02-20 23:45:53 +0000969 CustomGetFile((FileFilterYDUPP)0, 1, list, &reply, GETDIR_ID, where, myhook_upp,
Jack Jansen819f1771995-08-14 12:35:10 +0000970 NULL, NULL, NULL, (void *)&hook_args);
Jack Jansen3ec804a1995-02-20 15:56:10 +0000971
972 reply.sfFile.name[0] = 0;
973 if( FSMakeFSSpec(reply.sfFile.vRefNum, reply.sfFile.parID, reply.sfFile.name, dirfss) )
974 return 0;
Jack Jansen819f1771995-08-14 12:35:10 +0000975 return hook_args.selectcur_hit;
976}
977
978/*
979** Slightly extended StandardGetFile: accepts a prompt */
980void PyMac_PromptGetFile(short numTypes, ConstSFTypeListPtr typeList,
981 StandardFileReply *reply, char *prompt)
982{
983 static Point where = {-1, -1};
984 struct hook_args hook_args;
985
986 if ( !upp_inited ) {
987 myhook_upp = NewDlgHookYDProc(myhook_proc);
988 upp_inited = 1;
989 }
990 if ( prompt && *prompt )
991 hook_args.prompt = (char *)Pstring(prompt);
992 else
993 hook_args.prompt = NULL;
994 hook_args.selectcur_hit = 0;
995 CustomGetFile((FileFilterYDUPP)0, numTypes, typeList, reply, GETFILEPROMPT_ID, where,
996 myhook_upp, NULL, NULL, NULL, (void *)&hook_args);
Jack Jansen3ec804a1995-02-20 15:56:10 +0000997}
Jack Jansen5f653091995-01-18 13:53:49 +0000998
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000999/* Convert a 4-char string object argument to an OSType value */
Jack Jansen5f653091995-01-18 13:53:49 +00001000int
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001001PyMac_GetOSType(PyObject *v, OSType *pr)
Jack Jansen5f653091995-01-18 13:53:49 +00001002{
1003 if (!PyString_Check(v) || PyString_Size(v) != 4) {
1004 PyErr_SetString(PyExc_TypeError,
1005 "OSType arg must be string of 4 chars");
1006 return 0;
1007 }
1008 memcpy((char *)pr, PyString_AsString(v), 4);
1009 return 1;
1010}
1011
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001012/* Convert an OSType value to a 4-char string object */
1013PyObject *
1014PyMac_BuildOSType(OSType t)
1015{
1016 return PyString_FromStringAndSize((char *)&t, 4);
1017}
1018
Jack Jansend1f06311996-08-01 15:23:54 +00001019/* Convert an NumVersion value to a 4-element tuple */
1020PyObject *
1021PyMac_BuildNumVersion(NumVersion t)
1022{
1023 return Py_BuildValue("(hhhh)", t.majorRev, t.minorAndBugRev, t.stage, t.nonRelRev);
1024}
1025
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001026
1027/* Convert a Python string object to a Str255 */
Jack Jansen5f653091995-01-18 13:53:49 +00001028int
Guido van Rossum8f691791995-01-18 23:57:26 +00001029PyMac_GetStr255(PyObject *v, Str255 pbuf)
Jack Jansen5f653091995-01-18 13:53:49 +00001030{
1031 int len;
1032 if (!PyString_Check(v) || (len = PyString_Size(v)) > 255) {
1033 PyErr_SetString(PyExc_TypeError,
1034 "Str255 arg must be string of at most 255 chars");
1035 return 0;
1036 }
1037 pbuf[0] = len;
1038 memcpy((char *)(pbuf+1), PyString_AsString(v), len);
1039 return 1;
1040}
1041
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001042/* Convert a Str255 to a Python string object */
1043PyObject *
1044PyMac_BuildStr255(Str255 s)
1045{
1046 return PyString_FromStringAndSize((char *)&s[1], (int)s[0]);
1047}
1048
1049
Jack Jansen5f653091995-01-18 13:53:49 +00001050/*
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001051** Convert a Python object to an FSSpec.
1052** The object may either be a full pathname or a triple
1053** (vrefnum, dirid, path).
Jack Jansen5f653091995-01-18 13:53:49 +00001054** NOTE: This routine will fail on pre-sys7 machines.
1055** The caller is responsible for not calling this routine
1056** in those cases (which is fine, since everyone calling
1057** this is probably sys7 dependent anyway).
1058*/
1059int
Guido van Rossum8f691791995-01-18 23:57:26 +00001060PyMac_GetFSSpec(PyObject *v, FSSpec *fs)
Jack Jansen5f653091995-01-18 13:53:49 +00001061{
1062 Str255 path;
1063 short refnum;
1064 long parid;
1065 OSErr err;
Jack Jansene8e8ae01995-01-26 16:36:45 +00001066 FSSpec *fs2;
Jack Jansen5f653091995-01-18 13:53:49 +00001067
Jack Jansene8e8ae01995-01-26 16:36:45 +00001068 /* first check whether it already is an FSSpec */
1069 fs2 = mfs_GetFSSpecFSSpec(v);
1070 if ( fs2 ) {
Jack Jansen3ec804a1995-02-20 15:56:10 +00001071 (void)FSMakeFSSpec(fs2->vRefNum, fs2->parID, fs2->name, fs);
Jack Jansene8e8ae01995-01-26 16:36:45 +00001072 return 1;
1073 }
Jack Jansen5f653091995-01-18 13:53:49 +00001074 if ( PyString_Check(v) ) {
1075 /* It's a pathname */
Guido van Rossum9aa3d131995-01-21 13:46:04 +00001076 if( !PyArg_Parse(v, "O&", PyMac_GetStr255, &path) )
Jack Jansen5f653091995-01-18 13:53:49 +00001077 return 0;
Jack Jansen378815c1996-03-06 16:21:34 +00001078 refnum = 0; /* XXXX Should get CurWD here?? */
Jack Jansen5f653091995-01-18 13:53:49 +00001079 parid = 0;
1080 } else {
Guido van Rossum9aa3d131995-01-21 13:46:04 +00001081 if( !PyArg_Parse(v, "(hlO&); FSSpec should be fullpath or (vrefnum,dirid,path)",
1082 &refnum, &parid, PyMac_GetStr255, &path)) {
Jack Jansen5f653091995-01-18 13:53:49 +00001083 return 0;
Guido van Rossum9aa3d131995-01-21 13:46:04 +00001084 }
Jack Jansen5f653091995-01-18 13:53:49 +00001085 }
1086 err = FSMakeFSSpec(refnum, parid, path, fs);
1087 if ( err && err != fnfErr ) {
Guido van Rossum9aa3d131995-01-21 13:46:04 +00001088 PyErr_Mac(PyExc_ValueError, err);
Jack Jansen5f653091995-01-18 13:53:49 +00001089 return 0;
1090 }
1091 return 1;
1092}
1093
Guido van Rossum8f691791995-01-18 23:57:26 +00001094
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001095/* Convert a Python object to a Rect.
Guido van Rossum5279ec61995-01-26 22:56:59 +00001096 The object must be a (left, top, right, bottom) tuple.
1097 (This differs from the order in the struct but is consistent with
1098 the arguments to SetRect(), and also with STDWIN). */
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001099int
1100PyMac_GetRect(PyObject *v, Rect *r)
Guido van Rossum8f691791995-01-18 23:57:26 +00001101{
Guido van Rossum5279ec61995-01-26 22:56:59 +00001102 return PyArg_Parse(v, "(hhhh)", &r->left, &r->top, &r->right, &r->bottom);
Guido van Rossum8f691791995-01-18 23:57:26 +00001103}
Guido van Rossumb3404661995-01-22 18:36:13 +00001104
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001105/* Convert a Rect to a Python object */
Guido van Rossumb3404661995-01-22 18:36:13 +00001106PyObject *
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001107PyMac_BuildRect(Rect *r)
Guido van Rossumb3404661995-01-22 18:36:13 +00001108{
Guido van Rossum5279ec61995-01-26 22:56:59 +00001109 return Py_BuildValue("(hhhh)", r->left, r->top, r->right, r->bottom);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001110}
1111
1112
1113/* Convert a Python object to a Point.
Guido van Rossum5279ec61995-01-26 22:56:59 +00001114 The object must be a (h, v) tuple.
1115 (This differs from the order in the struct but is consistent with
1116 the arguments to SetPoint(), and also with STDWIN). */
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001117int
1118PyMac_GetPoint(PyObject *v, Point *p)
1119{
Guido van Rossum5279ec61995-01-26 22:56:59 +00001120 return PyArg_Parse(v, "(hh)", &p->h, &p->v);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001121}
1122
1123/* Convert a Point to a Python object */
1124PyObject *
1125PyMac_BuildPoint(Point p)
1126{
Guido van Rossum5279ec61995-01-26 22:56:59 +00001127 return Py_BuildValue("(hh)", p.h, p.v);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001128}
1129
1130
1131/* Convert a Python object to an EventRecord.
1132 The object must be a (what, message, when, (v, h), modifiers) tuple. */
1133int
1134PyMac_GetEventRecord(PyObject *v, EventRecord *e)
1135{
1136 return PyArg_Parse(v, "(hll(hh)h)",
1137 &e->what,
1138 &e->message,
1139 &e->when,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001140 &e->where.h,
Guido van Rossum5279ec61995-01-26 22:56:59 +00001141 &e->where.v,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001142 &e->modifiers);
1143}
1144
1145/* Convert a Rect to an EventRecord object */
1146PyObject *
1147PyMac_BuildEventRecord(EventRecord *e)
1148{
1149 return Py_BuildValue("(hll(hh)h)",
1150 e->what,
1151 e->message,
1152 e->when,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001153 e->where.h,
Guido van Rossum5279ec61995-01-26 22:56:59 +00001154 e->where.v,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001155 e->modifiers);
Guido van Rossumb3404661995-01-22 18:36:13 +00001156}
Jack Jansenfa4d5d01995-11-15 15:19:29 +00001157
1158/* Convert Python object to Fixed */
1159int
1160PyMac_GetFixed(PyObject *v, Fixed *f)
1161{
1162 double d;
1163
1164 if( !PyArg_Parse(v, "d", &d))
1165 return 0;
1166 *f = (Fixed)(d * 0x10000);
Jack Jansen31dd5c01996-05-31 13:01:39 +00001167 return 1;
Jack Jansenfa4d5d01995-11-15 15:19:29 +00001168}
1169
1170/* Convert a Point to a Python object */
1171PyObject *
1172PyMac_BuildFixed(Fixed f)
1173{
1174 double d;
1175
1176 d = f;
1177 d = d / 0x10000;
1178 return Py_BuildValue("d", d);
1179}
1180
Jack Jansend58cd631998-04-21 15:24:39 +00001181/* Convert wide to/from Python int or (hi, lo) tuple. XXXX Should use Python longs */
1182int
1183PyMac_Getwide(PyObject *v, wide *rv)
1184{
1185 if (PyInt_Check(v)) {
1186 rv->hi = 0;
1187 rv->lo = PyInt_AsLong(v);
1188 if( rv->lo & 0x80000000 )
1189 rv->hi = -1;
1190 return 1;
1191 }
1192 return PyArg_Parse(v, "(ll)", &rv->hi, &rv->lo);
1193}
1194
1195
1196PyObject *
Jack Jansenbbf4be21998-04-23 13:20:17 +00001197PyMac_Buildwide(wide *w)
Jack Jansend58cd631998-04-21 15:24:39 +00001198{
Jack Jansenbbf4be21998-04-23 13:20:17 +00001199 if ( (w->hi == 0 && (w->lo & 0x80000000) == 0) ||
1200 (w->hi == -1 && (w->lo & 0x80000000) ) )
1201 return PyInt_FromLong(w->lo);
1202 return Py_BuildValue("(ll)", w->hi, w->lo);
Jack Jansend58cd631998-04-21 15:24:39 +00001203}