blob: 4d0fb1f77e71b2b551e8fd6142bf0b6e74024910 [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 Jansencfadbd41996-08-19 11:36:25 +0000186
Jack Jansenf6865f71996-09-04 15:24:59 +0000187/*
188** Replacement GUSI Spin function
189*/
190static int
191PyMac_GUSISpin(spin_msg msg, long arg)
192{
Jack Jansene3ae0df1997-06-03 15:28:29 +0000193 static Boolean inForeground = true;
194 int maxsleep = 6; /* 6 ticks is "normal" sleeptime */
Jack Jansenf6865f71996-09-04 15:24:59 +0000195
196 if (PyMac_ConsoleIsDead) return 0;
197#if 0
198 if (inForeground)
199 SpinCursor(msg == SP_AUTO_SPIN ? short(arg) : 1);
200#endif
201
202 if (interrupted) return -1;
203
Jack Jansene3ae0df1997-06-03 15:28:29 +0000204 if ( msg == SP_AUTO_SPIN )
205 maxsleep = 0;
206 if ( msg==SP_SLEEP||msg==SP_SELECT )
207 maxsleep = arg;
Jack Jansenf6865f71996-09-04 15:24:59 +0000208
Jack Jansene3ae0df1997-06-03 15:28:29 +0000209 PyMac_DoYield(maxsleep, 0); /* XXXX or is it safe to call python here? */
Jack Jansenf6865f71996-09-04 15:24:59 +0000210
211 return 0;
212}
213
214void
215PyMac_SetGUSISpin() {
216 GUSISetHook(GUSI_SpinHook, (GUSIHook)PyMac_GUSISpin);
217}
218
Jack Jansena39f1b01997-05-23 15:35:14 +0000219/* Called at exit() time thru atexit(), to stop event processing */
220void
221PyMac_StopGUSISpin() {
222 PyMac_ConsoleIsDead = 1;
223}
224
225/*
226** Replacement routines for the PLstr... functions so we don't need
227** StdCLib. Moreover, that implementation is broken under cfm68k...
228*/
229void
230PLstrcpy(to, fr)
231 unsigned char *to, *fr;
232{
233 memcpy(to, fr, fr[0]+1);
234}
235
236int
237PLstrcmp(s1, s2)
238 unsigned char *s1, *s2;
239{
240 int res;
241 int l = s1[0] < s2[0] ? s1[0] : s2[0];
242
243 res = memcmp(s1+1, s2+1, l);
244 if ( res != 0 )
245 return res;
246
247 if ( s1 < s2 )
248 return -1;
249 else if ( s1 > s2 )
250 return 1;
251 else
252 return 0;
253}
254
255unsigned char *
256PLstrrchr(str, chr)
257 unsigned char *str;
258 unsigned char chr;
259{
260 unsigned char *ptr = 0;
261 unsigned char *p;
262
263 for(p=str+1; p<str+str[0]; p++)
264 if ( *p == chr )
265 ptr = p;
266 return ptr;
267}
268
269#endif /* USE_GUSI */
Jack Jansen378815c1996-03-06 16:21:34 +0000270
Jack Jansen819f1771995-08-14 12:35:10 +0000271
Jack Jansen5f653091995-01-18 13:53:49 +0000272/* Convert C to Pascal string. Returns pointer to static buffer. */
273unsigned char *
274Pstring(char *str)
275{
276 static Str255 buf;
277 int len;
278
279 len = strlen(str);
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000280 if (len > 255)
281 len = 255;
Jack Jansen5f653091995-01-18 13:53:49 +0000282 buf[0] = (unsigned char)len;
283 strncpy((char *)buf+1, str, len);
284 return buf;
285}
286
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000287/* Like strerror() but for Mac OS error numbers */
288char *PyMac_StrError(int err)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000289{
290 static char buf[256];
291 Handle h;
292 char *str;
293
294 h = GetResource('Estr', err);
295 if ( h ) {
296 HLock(h);
297 str = (char *)*h;
298 memcpy(buf, str+1, (unsigned char)str[0]);
Guido van Rossumcc9bc8f1995-02-13 16:17:03 +0000299 buf[(unsigned char)str[0]] = '\0';
Jack Jansenf93c72a1994-12-14 14:07:50 +0000300 HUnlock(h);
301 ReleaseResource(h);
302 } else {
303 sprintf(buf, "Mac OS error code %d", err);
304 }
305 return buf;
306}
307
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000308/* Exception object shared by all Mac specific modules for Mac OS errors */
309PyObject *PyMac_OSErrException;
310
311/* Initialize and return PyMac_OSErrException */
312PyObject *
313PyMac_GetOSErrException()
314{
315 if (PyMac_OSErrException == NULL)
316 PyMac_OSErrException = PyString_FromString("Mac OS Error");
317 return PyMac_OSErrException;
318}
319
Jack Jansenf93c72a1994-12-14 14:07:50 +0000320/* Set a MAC-specific error from errno, and return NULL; return None if no error */
321PyObject *
Guido van Rossumfffb8bb1995-01-12 12:37:24 +0000322PyErr_Mac(PyObject *eobj, int err)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000323{
324 char *msg;
325 PyObject *v;
Jack Jansenf93c72a1994-12-14 14:07:50 +0000326
Guido van Rossum8f691791995-01-18 23:57:26 +0000327 if (err == 0 && !PyErr_Occurred()) {
Jack Jansenf93c72a1994-12-14 14:07:50 +0000328 Py_INCREF(Py_None);
329 return Py_None;
330 }
Guido van Rossum8f691791995-01-18 23:57:26 +0000331 if (err == -1 && PyErr_Occurred())
332 return NULL;
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000333 msg = PyMac_StrError(err);
Jack Jansenf93c72a1994-12-14 14:07:50 +0000334 v = Py_BuildValue("(is)", err, msg);
335 PyErr_SetObject(eobj, v);
336 Py_DECREF(v);
337 return NULL;
338}
339
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000340/* Call PyErr_Mac with PyMac_OSErrException */
341PyObject *
342PyMac_Error(OSErr err)
343{
344 return PyErr_Mac(PyMac_GetOSErrException(), err);
345}
346
Jack Jansen1ed95291996-07-22 15:25:10 +0000347#ifdef USE_STACKCHECK
348/* Check for stack overflow */
349int
350PyOS_CheckStack()
351{
352 long left;
353
354 left = StackSpace();
Jack Jansend1f06311996-08-01 15:23:54 +0000355 if ( left < MINIMUM_STACK_SIZE )
Jack Jansen1ed95291996-07-22 15:25:10 +0000356 return -1;
357 return 0;
358}
359#endif /* USE_STACKCHECK */
360
Jack Jansenee23d6e1995-01-27 14:43:25 +0000361/* The catcher routine (which may not be used for all compilers) */
362static RETSIGTYPE
363intcatcher(sig)
364 int sig;
365{
366 interrupted = 1;
367 signal(SIGINT, intcatcher);
368}
369
370void
371PyOS_InitInterrupts()
372{
373 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
374 signal(SIGINT, intcatcher);
375}
376
Jack Jansena8441de1997-08-08 14:57:37 +0000377void
378PyOS_FiniInterrupts()
379{
380}
381
Jack Jansenee23d6e1995-01-27 14:43:25 +0000382/*
383** This routine scans the event queue looking for cmd-.
384** This is the only way to get an interrupt under THINK (since it
385** doesn't do SIGINT handling), but is also used under MW, when
386** the full-fledged event loop is disabled. This way, we can at least
387** interrupt a runaway python program.
388*/
389static void
390scan_event_queue(flush)
391 int flush;
392{
393 register EvQElPtr q;
394
Jack Jansencfadbd41996-08-19 11:36:25 +0000395 q = (EvQElPtr) GetEventQueue()->qHead;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000396
397 for (; q; q = (EvQElPtr)q->qLink) {
398 if (q->evtQWhat == keyDown &&
399 (char)q->evtQMessage == '.' &&
400 (q->evtQModifiers & cmdKey) != 0) {
401 if ( flush )
402 FlushEvents(keyDownMask, 0);
403 interrupted = 1;
404 break;
405 }
406 }
407}
408
409int
Jack Jansen36ed5061997-06-20 16:18:15 +0000410PyErr_CheckSignals()
Jack Jansenee23d6e1995-01-27 14:43:25 +0000411{
Jack Jansene3ae0df1997-06-03 15:28:29 +0000412 if (schedparams.enabled) {
413 if ( (unsigned long)LMGetTicks() > schedparams.next_check ) {
Jack Jansen36ed5061997-06-20 16:18:15 +0000414 if ( PyMac_Yield() < 0)
415 return -1;
Jack Jansene3ae0df1997-06-03 15:28:29 +0000416 schedparams.next_check = (unsigned long)LMGetTicks()
417 + schedparams.check_interval;
418 if (interrupted) {
Jack Jansencaa7c461997-06-12 10:49:13 +0000419 scan_event_queue(1); /* Eat events up to cmd-. */
Jack Jansene3ae0df1997-06-03 15:28:29 +0000420 interrupted = 0;
Jack Jansen36ed5061997-06-20 16:18:15 +0000421 PyErr_SetNone(PyExc_KeyboardInterrupt);
422 return -1;
Jack Jansene3ae0df1997-06-03 15:28:29 +0000423 }
424 }
Jack Jansenee23d6e1995-01-27 14:43:25 +0000425 }
426 return 0;
427}
428
Jack Jansen36ed5061997-06-20 16:18:15 +0000429int
430PyOS_InterruptOccurred()
431{
432 scan_event_queue(1);
433 return interrupted;
434}
Jack Jansenee23d6e1995-01-27 14:43:25 +0000435/* Check whether we are in the foreground */
436int
437PyMac_InForeground()
438{
439 static ProcessSerialNumber ours;
440 static inited;
441 ProcessSerialNumber curfg;
442 Boolean eq;
443
Jack Jansene3ae0df1997-06-03 15:28:29 +0000444 if ( inited == 0 ) {
Jack Jansenee23d6e1995-01-27 14:43:25 +0000445 (void)GetCurrentProcess(&ours);
Jack Jansene3ae0df1997-06-03 15:28:29 +0000446 inited = 1;
447 }
Jack Jansenee23d6e1995-01-27 14:43:25 +0000448 if ( GetFrontProcess(&curfg) < 0 )
449 eq = 1;
450 else if ( SameProcess(&ours, &curfg, &eq) < 0 )
451 eq = 1;
452 return (int)eq;
453
454}
455
Jack Jansen36ed5061997-06-20 16:18:15 +0000456int
457PyMac_SetEventHandler(PyObject *evh)
458{
459 if ( evh && python_event_handler ) {
460 PyErr_SetString(PyExc_RuntimeError, "Python event handler already set");
461 return 0;
462 }
463 if ( python_event_handler )
464 Py_DECREF(python_event_handler);
465 if ( evh )
466 Py_INCREF(evh);
467 python_event_handler = evh;
468 return 1;
469}
470
Jack Jansenf93c72a1994-12-14 14:07:50 +0000471/*
Jack Jansena76382a1995-02-02 14:25:56 +0000472** Handle an event, either one found in the mainloop eventhandler or
473** one passed back from the python program.
474*/
475void
Jack Jansen36ed5061997-06-20 16:18:15 +0000476PyMac_HandleEventIntern(evp)
Jack Jansena76382a1995-02-02 14:25:56 +0000477 EventRecord *evp;
478{
Jack Jansen0c968871997-08-26 13:20:34 +0000479 if ( evp->what == mouseDown ) {
480 WindowPtr wp;
481
482 if ( FindWindow(evp->where, &wp) == inSysWindow ) {
483 SystemClick(evp, wp);
484 return;
485 }
486 }
Jack Jansena76382a1995-02-02 14:25:56 +0000487#ifdef __MWERKS__
Jack Jansen38e97661995-11-10 14:53:00 +0000488 {
489 int siouxdidit;
490
491 /* If SIOUX wants it we're done */
492 siouxdidit = SIOUXHandleOneEvent(evp);
493 if ( siouxdidit )
494 return;
495 }
Jack Jansena76382a1995-02-02 14:25:56 +0000496#else
Jack Jansen0c968871997-08-26 13:20:34 +0000497 /* Other compilers are just unlucky... */
Jack Jansena76382a1995-02-02 14:25:56 +0000498#endif /* !__MWERKS__ */
Jack Jansen36ed5061997-06-20 16:18:15 +0000499}
500
501/*
502** Handle an event, either through HandleEvent or by passing it to the Python
503** event handler.
504*/
505int
506PyMac_HandleEvent(evp)
507 EventRecord *evp;
508{
509 PyObject *rv;
510
511 if ( python_event_handler ) {
512 rv = PyObject_CallFunction(python_event_handler, "(O&)",
513 PyMac_BuildEventRecord, evp);
514 if ( rv )
515 Py_DECREF(rv);
516 else
517 return -1; /* Propagate exception */
518 } else {
519 PyMac_HandleEventIntern(evp);
520 }
521 return 0;
Jack Jansena76382a1995-02-02 14:25:56 +0000522}
523
524/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000525** Yield the CPU to other tasks without processing events.
Jack Jansene8e8ae01995-01-26 16:36:45 +0000526*/
Jack Jansen36ed5061997-06-20 16:18:15 +0000527static int
Jack Jansene3ae0df1997-06-03 15:28:29 +0000528PyMac_DoYield(int maxsleep, int maycallpython)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000529{
530 EventRecord ev;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000531 int gotone;
Jack Jansene3ae0df1997-06-03 15:28:29 +0000532 long latest_time_ready;
Jack Jansen36ed5061997-06-20 16:18:15 +0000533 static int in_here = 0;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000534
Jack Jansen36ed5061997-06-20 16:18:15 +0000535 in_here++;
Jack Jansene3ae0df1997-06-03 15:28:29 +0000536 /*
537 ** First check for interrupts, if wanted.
538 ** This sets a flag that will be picked up at an appropriate
539 ** moment in the mainloop.
540 */
541 if (schedparams.check_interrupt)
Jack Jansenee23d6e1995-01-27 14:43:25 +0000542 scan_event_queue(0);
Jack Jansene3ae0df1997-06-03 15:28:29 +0000543
544 /* XXXX Implementing an idle routine goes here */
Jack Jansene8e8ae01995-01-26 16:36:45 +0000545
Jack Jansene3ae0df1997-06-03 15:28:29 +0000546 /*
547 ** Check which of the eventloop cases we have:
548 ** - process events
549 ** - don't process events but do yield
550 ** - do neither
551 */
Jack Jansen36ed5061997-06-20 16:18:15 +0000552 if( in_here > 1 || !schedparams.process_events ||
553 (python_event_handler && !maycallpython) ) {
Jack Jansene3ae0df1997-06-03 15:28:29 +0000554 if ( maxsleep >= 0 ) {
Jack Jansene8e8ae01995-01-26 16:36:45 +0000555 SystemTask();
Jack Jansene3ae0df1997-06-03 15:28:29 +0000556 }
557 } else {
558 latest_time_ready = LMGetTicks() + maxsleep;
559 while ( maxsleep >= 0 ) {
Jack Jansen0c968871997-08-26 13:20:34 +0000560 /* XXXX Hack by Jack.
561 ** In time.sleep() you can click to another application
562 ** once only. If you come back to Python you cannot get away
563 ** again.
564 **/
Jack Jansen36ed5061997-06-20 16:18:15 +0000565 gotone = WaitNextEvent(schedparams.process_events, &ev, maxsleep, NULL);
Jack Jansene3ae0df1997-06-03 15:28:29 +0000566 /* Get out quickly if nothing interesting is happening */
567 if ( !gotone || ev.what == nullEvent )
568 break;
Jack Jansen36ed5061997-06-20 16:18:15 +0000569 if ( PyMac_HandleEvent(&ev) < 0 ) {
570 in_here--;
571 return -1;
572 }
Jack Jansene3ae0df1997-06-03 15:28:29 +0000573 maxsleep = latest_time_ready - LMGetTicks();
574 }
Jack Jansenf93c72a1994-12-14 14:07:50 +0000575 }
Jack Jansen36ed5061997-06-20 16:18:15 +0000576 in_here--;
577 return 0;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000578}
579
580/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000581** Process events and/or yield the CPU to other tasks if opportune
Jack Jansene8e8ae01995-01-26 16:36:45 +0000582*/
Jack Jansen36ed5061997-06-20 16:18:15 +0000583int
Jack Jansene8e8ae01995-01-26 16:36:45 +0000584PyMac_Yield() {
Jack Jansene3ae0df1997-06-03 15:28:29 +0000585 unsigned long maxsleep;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000586
Jack Jansene3ae0df1997-06-03 15:28:29 +0000587 if( PyMac_InForeground() )
588 maxsleep = 0;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000589 else
Jack Jansene3ae0df1997-06-03 15:28:29 +0000590 maxsleep = schedparams.bg_yield;
591
Jack Jansen36ed5061997-06-20 16:18:15 +0000592 return PyMac_DoYield(maxsleep, 1);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000593}
594
595/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000596** Return current scheduler parameters
Jack Jansene8e8ae01995-01-26 16:36:45 +0000597*/
Jack Jansene3ae0df1997-06-03 15:28:29 +0000598void
599PyMac_GetSchedParams(PyMacSchedParams *sp)
Jack Jansene8e8ae01995-01-26 16:36:45 +0000600{
Jack Jansene3ae0df1997-06-03 15:28:29 +0000601 sp->check_interrupt = schedparams.check_interrupt;
602 sp->process_events = schedparams.process_events;
603 sp->besocial = schedparams.besocial;
604 sp->check_interval = schedparams.check_interval / 60.0;
605 sp->bg_yield = schedparams.bg_yield / 60.0;
Jack Jansenf93c72a1994-12-14 14:07:50 +0000606}
Jack Jansenf6865f71996-09-04 15:24:59 +0000607
Jack Jansen74162f31995-02-15 22:58:33 +0000608/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000609** Set current scheduler parameters
610*/
611void
612PyMac_SetSchedParams(PyMacSchedParams *sp)
613{
614 schedparams.check_interrupt = sp->check_interrupt;
615 schedparams.process_events = sp->process_events;
616 schedparams.besocial = sp->besocial;
617 schedparams.check_interval = (unsigned long)(sp->check_interval*60);
618 schedparams.bg_yield = (unsigned long)(sp->bg_yield*60);
619 if ( schedparams.check_interrupt || schedparams.process_events ||
620 schedparams.besocial )
621 schedparams.enabled = 1;
622 else
623 schedparams.enabled = 0;
624 schedparams.next_check = 0; /* Check immedeately */
625}
Jack Jansencaa7c461997-06-12 10:49:13 +0000626
Jack Jansene3ae0df1997-06-03 15:28:29 +0000627/*
Jack Jansen3469e991996-09-06 00:30:45 +0000628** Install our menu bar.
629*/
630void
631PyMac_InitMenuBar()
632{
Jack Jansen3469e991996-09-06 00:30:45 +0000633 MenuHandle applemenu;
634
Jack Jansencaa7c461997-06-12 10:49:13 +0000635 if ( (sioux_mbar=GetMenuBar()) == NULL ) {
636 /* Sioux menu not installed yet. Do so */
637 SIOUXSetupMenus();
638 if ( (sioux_mbar=GetMenuBar()) == NULL )
639 return;
640 }
Jack Jansen08c3be31997-04-08 15:27:00 +0000641 if ( (applemenu=GetMenuHandle(SIOUX_APPLEID)) == NULL ) return;
Jack Jansen3469e991996-09-06 00:30:45 +0000642 SetMenuItemText(applemenu, 1, "\pAbout Python...");
643}
644
645/*
Jack Jansencaa7c461997-06-12 10:49:13 +0000646** Restore sioux menu bar
647*/
648void
649PyMac_RestoreMenuBar()
650{
Jack Janseneda78631997-06-12 15:29:46 +0000651 if ( sioux_mbar ) {
Jack Jansencaa7c461997-06-12 10:49:13 +0000652 SetMenuBar(sioux_mbar);
Jack Janseneda78631997-06-12 15:29:46 +0000653 DrawMenuBar();
654 }
Jack Jansencaa7c461997-06-12 10:49:13 +0000655}
656
657
658/*
Jack Jansen3469e991996-09-06 00:30:45 +0000659** Our replacement about box
660*/
661void
662SIOUXDoAboutBox(void)
663{
664 DialogPtr theDialog;
Jack Jansend617c571996-09-22 22:14:30 +0000665 WindowRef theWindow;
666 CGrafPtr thePort;
Jack Jansen3469e991996-09-06 00:30:45 +0000667 short item;
Jack Jansend617c571996-09-22 22:14:30 +0000668 short xpos, ypos, width, height, swidth, sheight;
Jack Jansen3469e991996-09-06 00:30:45 +0000669
670 if( (theDialog = GetNewDialog(ABOUT_ID, NULL, (WindowPtr)-1)) == NULL )
671 return;
Jack Jansend617c571996-09-22 22:14:30 +0000672 theWindow = GetDialogWindow(theDialog);
673 thePort = GetWindowPort(theWindow);
674 width = thePort->portRect.right - thePort->portRect.left;
675 height = thePort->portRect.bottom - thePort->portRect.top;
676 swidth = qd.screenBits.bounds.right - qd.screenBits.bounds.left;
677 sheight = qd.screenBits.bounds.bottom - qd.screenBits.bounds.top - LMGetMBarHeight();
678 xpos = (swidth-width)/2;
Jack Jansen0e06e7e1996-09-23 15:51:06 +0000679 ypos = (sheight-height)/5 + LMGetMBarHeight();
Jack Jansend617c571996-09-22 22:14:30 +0000680 MoveWindow(theWindow, xpos, ypos, 0);
681 ShowWindow(theWindow);
Jack Jansen3469e991996-09-06 00:30:45 +0000682 ModalDialog(NULL, &item);
683 DisposeDialog(theDialog);
684}
685
686/*
Jack Jansen74162f31995-02-15 22:58:33 +0000687** Returns true if the argument has a resource fork, and it contains
688** a 'PYC ' resource of the correct name
689*/
690int
Jack Janseneda78631997-06-12 15:29:46 +0000691PyMac_FindResourceModule(obj, module, filename)
692PyStringObject *obj;
Jack Jansen74162f31995-02-15 22:58:33 +0000693char *module;
694char *filename;
695{
696 FSSpec fss;
697 FInfo finfo;
698 short oldrh, filerh;
699 int ok;
700 Handle h;
Jack Janseneda78631997-06-12 15:29:46 +0000701
702#ifdef INTERN_STRINGS
703 /*
704 ** If we have interning find_module takes care of interning all
705 ** sys.path components. We then keep a record of all sys.path
706 ** components for which GetFInfo has failed (usually because the
707 ** component in question is a folder), and we don't try opening these
708 ** as resource files again.
709 */
710#define MAXPATHCOMPONENTS 32
711 static PyStringObject *not_a_file[MAXPATHCOMPONENTS];
712 static int max_not_a_file = 0;
713 int i;
714
715 if ( obj->ob_sinterned ) {
716 for( i=0; i< max_not_a_file; i++ )
717 if ( obj == not_a_file[i] )
718 return 0;
719 }
720#endif /* INTERN_STRINGS */
721
Jack Jansen8096daa1996-11-09 18:43:44 +0000722 if ( strcmp(filename, PyMac_ApplicationPath) == 0 ) {
723 /*
724 ** Special case: the application itself. Use a shortcut to
725 ** forestall opening and closing the application numerous times
726 ** (which is dead slow when running from CDROM)
727 */
728 oldrh = CurResFile();
729 UseResFile(PyMac_AppRefNum);
730 filerh = -1;
731 } else {
Jack Janseneda78631997-06-12 15:29:46 +0000732 if ( FSMakeFSSpec(0, 0, Pstring(filename), &fss) != noErr ||
733 FSpGetFInfo(&fss, &finfo) != noErr ) {
734#ifdef INTERN_STRINGS
735 if ( max_not_a_file < MAXPATHCOMPONENTS && obj->ob_sinterned )
736 not_a_file[max_not_a_file++] = obj;
737#endif /* INTERN_STRINGS */
738 /* doesn't exist or is folder */
739 return 0;
740 }
Jack Jansen8096daa1996-11-09 18:43:44 +0000741 oldrh = CurResFile();
742 filerh = FSpOpenResFile(&fss, fsRdPerm);
743 if ( filerh == -1 )
744 return 0;
745 UseResFile(filerh);
746 }
Jack Jansen74162f31995-02-15 22:58:33 +0000747 SetResLoad(0);
748 h = Get1NamedResource('PYC ', Pstring(module));
749 SetResLoad(1);
750 ok = (h != NULL);
Jack Jansen8096daa1996-11-09 18:43:44 +0000751 if ( filerh != -1 )
752 CloseResFile(filerh);
Jack Jansen74162f31995-02-15 22:58:33 +0000753 UseResFile(oldrh);
754 return ok;
755}
756
757/*
758** Load the specified module from a resource
759*/
760PyObject *
761PyMac_LoadResourceModule(module, filename)
762char *module;
763char *filename;
764{
765 FSSpec fss;
766 FInfo finfo;
767 short oldrh, filerh;
Jack Jansen74162f31995-02-15 22:58:33 +0000768 Handle h;
769 OSErr err;
770 PyObject *m, *co;
771 long num, size;
772
Jack Jansen8096daa1996-11-09 18:43:44 +0000773 if ( strcmp(filename, PyMac_ApplicationPath) == 0 ) {
774 /*
775 ** Special case: the application itself. Use a shortcut to
776 ** forestall opening and closing the application numerous times
777 ** (which is dead slow when running from CDROM)
778 */
779 oldrh = CurResFile();
780 UseResFile(PyMac_AppRefNum);
781 filerh = -1;
782 } else {
783 if ( (err=FSMakeFSSpec(0, 0, Pstring(filename), &fss)) != noErr )
784 goto error;
785 if ( (err=FSpGetFInfo(&fss, &finfo)) != noErr )
786 goto error;
787 oldrh = CurResFile();
788 filerh = FSpOpenResFile(&fss, fsRdPerm);
789 if ( filerh == -1 ) {
790 err = ResError();
791 goto error;
792 }
793 UseResFile(filerh);
Jack Jansen74162f31995-02-15 22:58:33 +0000794 }
Jack Jansen74162f31995-02-15 22:58:33 +0000795 h = Get1NamedResource('PYC ', Pstring(module));
796 if ( h == NULL ) {
797 err = ResError();
798 goto error;
799 }
800 HLock(h);
801 /*
802 ** XXXX The next few lines are intimately tied to the format of pyc
803 ** files. I'm not sure whether this code should be here or in import.c -- Jack
804 */
805 size = GetHandleSize(h);
806 if ( size < 8 ) {
807 PyErr_SetString(PyExc_ImportError, "Resource too small");
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000808 co = NULL;
Jack Jansen74162f31995-02-15 22:58:33 +0000809 } else {
810 num = (*h)[0] & 0xff;
811 num = num | (((*h)[1] & 0xff) << 8);
812 num = num | (((*h)[2] & 0xff) << 16);
813 num = num | (((*h)[3] & 0xff) << 24);
814 if ( num != PyImport_GetMagicNumber() ) {
815 PyErr_SetString(PyExc_ImportError, "Bad MAGIC in resource");
816 co = NULL;
817 } else {
818 co = PyMarshal_ReadObjectFromString((*h)+8, size-8);
819 }
820 }
821 HUnlock(h);
Jack Jansen8096daa1996-11-09 18:43:44 +0000822 if ( filerh != -1 )
823 CloseResFile(filerh);
Jack Jansen74162f31995-02-15 22:58:33 +0000824 UseResFile(oldrh);
825 if ( co ) {
826 m = PyImport_ExecCodeModule(module, co);
827 Py_DECREF(co);
828 } else {
829 m = NULL;
830 }
831 return m;
832error:
833 {
834 char buf[512];
835
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000836 sprintf(buf, "%s: %s", filename, PyMac_StrError(err));
Jack Jansen74162f31995-02-15 22:58:33 +0000837 PyErr_SetString(PyExc_ImportError, buf);
838 return NULL;
839 }
840}
Guido van Rossum24a45e31995-02-20 23:45:53 +0000841
Jack Jansen3ec804a1995-02-20 15:56:10 +0000842/*
Jack Janseneda78631997-06-12 15:29:46 +0000843** Look for a module in a single folder. Upon entry buf and len
844** point to the folder to search, upon exit they refer to the full
845** pathname of the module found (if any).
846*/
847struct filedescr *
848PyMac_FindModuleExtension(char *buf, int *lenp, char *module)
849{
850 struct filedescr *fdp;
851 unsigned char fnbuf[64];
852 int modnamelen = strlen(module);
853 FSSpec fss;
854 short refnum;
855 long dirid;
856
857 /*
858 ** Copy the module name to the buffer (already :-terminated)
859 ** We also copy the first suffix, if this matches immedeately we're
860 ** lucky and return immedeately.
861 */
862 if ( !_PyImport_Filetab[0].suffix )
863 return 0;
864
Jack Jansenc73f83c1997-10-07 21:48:31 +0000865#if 0
866 /* Pre 1.5a4 */
Jack Janseneda78631997-06-12 15:29:46 +0000867 strcpy(buf+*lenp, module);
868 strcpy(buf+*lenp+modnamelen, _PyImport_Filetab[0].suffix);
Jack Jansenc73f83c1997-10-07 21:48:31 +0000869#else
870 strcpy(buf+*lenp, _PyImport_Filetab[0].suffix);
871#endif
Jack Janseneda78631997-06-12 15:29:46 +0000872 if ( FSMakeFSSpec(0, 0, Pstring(buf), &fss) == noErr )
873 return _PyImport_Filetab;
874 /*
875 ** We cannot check for fnfErr (unfortunately), it can mean either that
876 ** the file doesn't exist (fine, we try others) or the path leading to it.
877 */
878 refnum = fss.vRefNum;
879 dirid = fss.parID;
880 if ( refnum == 0 || dirid == 0 ) /* Fail on nonexistent dir */
881 return 0;
882 /*
883 ** We now have the folder parameters. Setup the field for the filename
884 */
885 if ( modnamelen > 54 ) return 0; /* Leave room for extension */
886 strcpy((char *)fnbuf+1, module);
887
888 for( fdp = _PyImport_Filetab+1; fdp->suffix; fdp++ ) {
889 strcpy((char *)fnbuf+1+modnamelen, fdp->suffix);
890 fnbuf[0] = strlen((char *)fnbuf+1);
891 if (Py_VerboseFlag > 1)
892 fprintf(stderr, "# trying %s%s\n", buf, fdp->suffix);
893 if ( FSMakeFSSpec(refnum, dirid, fnbuf, &fss) == noErr ) {
894 /* Found it. */
Jack Jansenc73f83c1997-10-07 21:48:31 +0000895#if 0
Jack Janseneda78631997-06-12 15:29:46 +0000896 strcpy(buf+*lenp+modnamelen, fdp->suffix);
Jack Jansenc73f83c1997-10-07 21:48:31 +0000897#else
Jack Jansen21364901997-10-08 15:32:46 +0000898 strcpy(buf+*lenp, fdp->suffix);
Jack Jansenc73f83c1997-10-07 21:48:31 +0000899#endif
Jack Janseneda78631997-06-12 15:29:46 +0000900 *lenp = strlen(buf);
901 return fdp;
902 }
903 }
904 return 0;
905}
906
907#if 0
908int
909PyMac_FileExists(char *name)
910{
911 FSSpec fss;
912
913 if ( FSMakeFSSpec(0, 0, Pstring(name), &fss) == noErr )
914 return 1;
915 return 0;
916}
917#endif
918
919/*
Jack Jansen3ec804a1995-02-20 15:56:10 +0000920** Helper routine for GetDirectory
921*/
Guido van Rossum24a45e31995-02-20 23:45:53 +0000922static pascal short
Jack Jansen819f1771995-08-14 12:35:10 +0000923myhook_proc(short item, DialogPtr theDialog, struct hook_args *dataptr)
Jack Jansen3ec804a1995-02-20 15:56:10 +0000924{
Jack Jansen819f1771995-08-14 12:35:10 +0000925 if ( item == sfHookFirstCall && dataptr->prompt) {
926 Handle prompth;
927 short type;
928 Rect rect;
929
930 GetDialogItem(theDialog, PROMPT_ITEM, &type, &prompth, &rect);
931 if ( prompth )
932 SetDialogItemText(prompth, (unsigned char *)dataptr->prompt);
933 } else
Jack Jansen3ec804a1995-02-20 15:56:10 +0000934 if ( item == SELECTCUR_ITEM ) {
935 item = sfItemCancelButton;
Jack Jansen819f1771995-08-14 12:35:10 +0000936 dataptr->selectcur_hit = 1;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000937 }
938 return item;
939}
940
941/*
942** Ask the user for a directory. I still can't understand
943** why Apple doesn't provide a standard solution for this...
944*/
945int
Jack Jansen819f1771995-08-14 12:35:10 +0000946PyMac_GetDirectory(dirfss, prompt)
Jack Jansen3ec804a1995-02-20 15:56:10 +0000947 FSSpec *dirfss;
Jack Jansen819f1771995-08-14 12:35:10 +0000948 char *prompt;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000949{
950 static SFTypeList list = {'fldr', 0, 0, 0};
951 static Point where = {-1, -1};
Jack Jansen3ec804a1995-02-20 15:56:10 +0000952 StandardFileReply reply;
Jack Jansen819f1771995-08-14 12:35:10 +0000953 struct hook_args hook_args;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000954
955 if ( !upp_inited ) {
956 myhook_upp = NewDlgHookYDProc(myhook_proc);
957 upp_inited = 1;
958 }
Jack Jansen819f1771995-08-14 12:35:10 +0000959 if ( prompt && *prompt )
960 hook_args.prompt = (char *)Pstring(prompt);
961 else
962 hook_args.prompt = NULL;
963 hook_args.selectcur_hit = 0;
Guido van Rossum24a45e31995-02-20 23:45:53 +0000964 CustomGetFile((FileFilterYDUPP)0, 1, list, &reply, GETDIR_ID, where, myhook_upp,
Jack Jansen819f1771995-08-14 12:35:10 +0000965 NULL, NULL, NULL, (void *)&hook_args);
Jack Jansen3ec804a1995-02-20 15:56:10 +0000966
967 reply.sfFile.name[0] = 0;
968 if( FSMakeFSSpec(reply.sfFile.vRefNum, reply.sfFile.parID, reply.sfFile.name, dirfss) )
969 return 0;
Jack Jansen819f1771995-08-14 12:35:10 +0000970 return hook_args.selectcur_hit;
971}
972
973/*
974** Slightly extended StandardGetFile: accepts a prompt */
975void PyMac_PromptGetFile(short numTypes, ConstSFTypeListPtr typeList,
976 StandardFileReply *reply, char *prompt)
977{
978 static Point where = {-1, -1};
979 struct hook_args hook_args;
980
981 if ( !upp_inited ) {
982 myhook_upp = NewDlgHookYDProc(myhook_proc);
983 upp_inited = 1;
984 }
985 if ( prompt && *prompt )
986 hook_args.prompt = (char *)Pstring(prompt);
987 else
988 hook_args.prompt = NULL;
989 hook_args.selectcur_hit = 0;
990 CustomGetFile((FileFilterYDUPP)0, numTypes, typeList, reply, GETFILEPROMPT_ID, where,
991 myhook_upp, NULL, NULL, NULL, (void *)&hook_args);
Jack Jansen3ec804a1995-02-20 15:56:10 +0000992}
Jack Jansen5f653091995-01-18 13:53:49 +0000993
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000994/* Convert a 4-char string object argument to an OSType value */
Jack Jansen5f653091995-01-18 13:53:49 +0000995int
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000996PyMac_GetOSType(PyObject *v, OSType *pr)
Jack Jansen5f653091995-01-18 13:53:49 +0000997{
998 if (!PyString_Check(v) || PyString_Size(v) != 4) {
999 PyErr_SetString(PyExc_TypeError,
1000 "OSType arg must be string of 4 chars");
1001 return 0;
1002 }
1003 memcpy((char *)pr, PyString_AsString(v), 4);
1004 return 1;
1005}
1006
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001007/* Convert an OSType value to a 4-char string object */
1008PyObject *
1009PyMac_BuildOSType(OSType t)
1010{
1011 return PyString_FromStringAndSize((char *)&t, 4);
1012}
1013
Jack Jansend1f06311996-08-01 15:23:54 +00001014/* Convert an NumVersion value to a 4-element tuple */
1015PyObject *
1016PyMac_BuildNumVersion(NumVersion t)
1017{
1018 return Py_BuildValue("(hhhh)", t.majorRev, t.minorAndBugRev, t.stage, t.nonRelRev);
1019}
1020
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001021
1022/* Convert a Python string object to a Str255 */
Jack Jansen5f653091995-01-18 13:53:49 +00001023int
Guido van Rossum8f691791995-01-18 23:57:26 +00001024PyMac_GetStr255(PyObject *v, Str255 pbuf)
Jack Jansen5f653091995-01-18 13:53:49 +00001025{
1026 int len;
1027 if (!PyString_Check(v) || (len = PyString_Size(v)) > 255) {
1028 PyErr_SetString(PyExc_TypeError,
1029 "Str255 arg must be string of at most 255 chars");
1030 return 0;
1031 }
1032 pbuf[0] = len;
1033 memcpy((char *)(pbuf+1), PyString_AsString(v), len);
1034 return 1;
1035}
1036
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001037/* Convert a Str255 to a Python string object */
1038PyObject *
1039PyMac_BuildStr255(Str255 s)
1040{
1041 return PyString_FromStringAndSize((char *)&s[1], (int)s[0]);
1042}
1043
1044
Jack Jansen5f653091995-01-18 13:53:49 +00001045/*
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001046** Convert a Python object to an FSSpec.
1047** The object may either be a full pathname or a triple
1048** (vrefnum, dirid, path).
Jack Jansen5f653091995-01-18 13:53:49 +00001049** NOTE: This routine will fail on pre-sys7 machines.
1050** The caller is responsible for not calling this routine
1051** in those cases (which is fine, since everyone calling
1052** this is probably sys7 dependent anyway).
1053*/
1054int
Guido van Rossum8f691791995-01-18 23:57:26 +00001055PyMac_GetFSSpec(PyObject *v, FSSpec *fs)
Jack Jansen5f653091995-01-18 13:53:49 +00001056{
1057 Str255 path;
1058 short refnum;
1059 long parid;
1060 OSErr err;
Jack Jansene8e8ae01995-01-26 16:36:45 +00001061 FSSpec *fs2;
Jack Jansen5f653091995-01-18 13:53:49 +00001062
Jack Jansene8e8ae01995-01-26 16:36:45 +00001063 /* first check whether it already is an FSSpec */
1064 fs2 = mfs_GetFSSpecFSSpec(v);
1065 if ( fs2 ) {
Jack Jansen3ec804a1995-02-20 15:56:10 +00001066 (void)FSMakeFSSpec(fs2->vRefNum, fs2->parID, fs2->name, fs);
Jack Jansene8e8ae01995-01-26 16:36:45 +00001067 return 1;
1068 }
Jack Jansen5f653091995-01-18 13:53:49 +00001069 if ( PyString_Check(v) ) {
1070 /* It's a pathname */
Guido van Rossum9aa3d131995-01-21 13:46:04 +00001071 if( !PyArg_Parse(v, "O&", PyMac_GetStr255, &path) )
Jack Jansen5f653091995-01-18 13:53:49 +00001072 return 0;
Jack Jansen378815c1996-03-06 16:21:34 +00001073 refnum = 0; /* XXXX Should get CurWD here?? */
Jack Jansen5f653091995-01-18 13:53:49 +00001074 parid = 0;
1075 } else {
Guido van Rossum9aa3d131995-01-21 13:46:04 +00001076 if( !PyArg_Parse(v, "(hlO&); FSSpec should be fullpath or (vrefnum,dirid,path)",
1077 &refnum, &parid, PyMac_GetStr255, &path)) {
Jack Jansen5f653091995-01-18 13:53:49 +00001078 return 0;
Guido van Rossum9aa3d131995-01-21 13:46:04 +00001079 }
Jack Jansen5f653091995-01-18 13:53:49 +00001080 }
1081 err = FSMakeFSSpec(refnum, parid, path, fs);
1082 if ( err && err != fnfErr ) {
Guido van Rossum9aa3d131995-01-21 13:46:04 +00001083 PyErr_Mac(PyExc_ValueError, err);
Jack Jansen5f653091995-01-18 13:53:49 +00001084 return 0;
1085 }
1086 return 1;
1087}
1088
Guido van Rossum8f691791995-01-18 23:57:26 +00001089
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001090/* Convert a Python object to a Rect.
Guido van Rossum5279ec61995-01-26 22:56:59 +00001091 The object must be a (left, top, right, bottom) tuple.
1092 (This differs from the order in the struct but is consistent with
1093 the arguments to SetRect(), and also with STDWIN). */
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001094int
1095PyMac_GetRect(PyObject *v, Rect *r)
Guido van Rossum8f691791995-01-18 23:57:26 +00001096{
Guido van Rossum5279ec61995-01-26 22:56:59 +00001097 return PyArg_Parse(v, "(hhhh)", &r->left, &r->top, &r->right, &r->bottom);
Guido van Rossum8f691791995-01-18 23:57:26 +00001098}
Guido van Rossumb3404661995-01-22 18:36:13 +00001099
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001100/* Convert a Rect to a Python object */
Guido van Rossumb3404661995-01-22 18:36:13 +00001101PyObject *
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001102PyMac_BuildRect(Rect *r)
Guido van Rossumb3404661995-01-22 18:36:13 +00001103{
Guido van Rossum5279ec61995-01-26 22:56:59 +00001104 return Py_BuildValue("(hhhh)", r->left, r->top, r->right, r->bottom);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001105}
1106
1107
1108/* Convert a Python object to a Point.
Guido van Rossum5279ec61995-01-26 22:56:59 +00001109 The object must be a (h, v) tuple.
1110 (This differs from the order in the struct but is consistent with
1111 the arguments to SetPoint(), and also with STDWIN). */
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001112int
1113PyMac_GetPoint(PyObject *v, Point *p)
1114{
Guido van Rossum5279ec61995-01-26 22:56:59 +00001115 return PyArg_Parse(v, "(hh)", &p->h, &p->v);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001116}
1117
1118/* Convert a Point to a Python object */
1119PyObject *
1120PyMac_BuildPoint(Point p)
1121{
Guido van Rossum5279ec61995-01-26 22:56:59 +00001122 return Py_BuildValue("(hh)", p.h, p.v);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001123}
1124
1125
1126/* Convert a Python object to an EventRecord.
1127 The object must be a (what, message, when, (v, h), modifiers) tuple. */
1128int
1129PyMac_GetEventRecord(PyObject *v, EventRecord *e)
1130{
1131 return PyArg_Parse(v, "(hll(hh)h)",
1132 &e->what,
1133 &e->message,
1134 &e->when,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001135 &e->where.h,
Guido van Rossum5279ec61995-01-26 22:56:59 +00001136 &e->where.v,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001137 &e->modifiers);
1138}
1139
1140/* Convert a Rect to an EventRecord object */
1141PyObject *
1142PyMac_BuildEventRecord(EventRecord *e)
1143{
1144 return Py_BuildValue("(hll(hh)h)",
1145 e->what,
1146 e->message,
1147 e->when,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001148 e->where.h,
Guido van Rossum5279ec61995-01-26 22:56:59 +00001149 e->where.v,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001150 e->modifiers);
Guido van Rossumb3404661995-01-22 18:36:13 +00001151}
Jack Jansenfa4d5d01995-11-15 15:19:29 +00001152
1153/* Convert Python object to Fixed */
1154int
1155PyMac_GetFixed(PyObject *v, Fixed *f)
1156{
1157 double d;
1158
1159 if( !PyArg_Parse(v, "d", &d))
1160 return 0;
1161 *f = (Fixed)(d * 0x10000);
Jack Jansen31dd5c01996-05-31 13:01:39 +00001162 return 1;
Jack Jansenfa4d5d01995-11-15 15:19:29 +00001163}
1164
1165/* Convert a Point to a Python object */
1166PyObject *
1167PyMac_BuildFixed(Fixed f)
1168{
1169 double d;
1170
1171 d = f;
1172 d = d / 0x10000;
1173 return Py_BuildValue("d", d);
1174}
1175