blob: 04e6bbb4cd8f55def83b73a501c336115332fdc1 [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*/
95#define MAINLOOP_EVENTMASK (mDownMask|keyDownMask|osMask)
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 Jansena76382a1995-02-02 14:25:56 +0000479#ifdef __MWERKS__
Jack Jansen38e97661995-11-10 14:53:00 +0000480 {
481 int siouxdidit;
482
483 /* If SIOUX wants it we're done */
484 siouxdidit = SIOUXHandleOneEvent(evp);
485 if ( siouxdidit )
486 return;
487 }
Jack Jansena76382a1995-02-02 14:25:56 +0000488#else
489 /* Other compilers are just unlucky: we only weed out clicks in other applications */
490 if ( evp->what == mouseDown ) {
Jack Jansen847e89e1995-08-31 13:57:40 +0000491 WindowPtr wp;
492
Jack Jansen38e97661995-11-10 14:53:00 +0000493 if ( FindWindow(evp->where, &wp) == inSysWindow ) {
Jack Jansena76382a1995-02-02 14:25:56 +0000494 SystemClick(evp, wp);
Jack Jansen38e97661995-11-10 14:53:00 +0000495 return;
496 }
Jack Jansena76382a1995-02-02 14:25:56 +0000497 }
498#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 Jansen36ed5061997-06-20 16:18:15 +0000560 gotone = WaitNextEvent(schedparams.process_events, &ev, maxsleep, NULL);
Jack Jansene3ae0df1997-06-03 15:28:29 +0000561 /* Get out quickly if nothing interesting is happening */
562 if ( !gotone || ev.what == nullEvent )
563 break;
Jack Jansen36ed5061997-06-20 16:18:15 +0000564 if ( PyMac_HandleEvent(&ev) < 0 ) {
565 in_here--;
566 return -1;
567 }
Jack Jansene3ae0df1997-06-03 15:28:29 +0000568 maxsleep = latest_time_ready - LMGetTicks();
569 }
Jack Jansenf93c72a1994-12-14 14:07:50 +0000570 }
Jack Jansen36ed5061997-06-20 16:18:15 +0000571 in_here--;
572 return 0;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000573}
574
575/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000576** Process events and/or yield the CPU to other tasks if opportune
Jack Jansene8e8ae01995-01-26 16:36:45 +0000577*/
Jack Jansen36ed5061997-06-20 16:18:15 +0000578int
Jack Jansene8e8ae01995-01-26 16:36:45 +0000579PyMac_Yield() {
Jack Jansene3ae0df1997-06-03 15:28:29 +0000580 unsigned long maxsleep;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000581
Jack Jansene3ae0df1997-06-03 15:28:29 +0000582 if( PyMac_InForeground() )
583 maxsleep = 0;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000584 else
Jack Jansene3ae0df1997-06-03 15:28:29 +0000585 maxsleep = schedparams.bg_yield;
586
Jack Jansen36ed5061997-06-20 16:18:15 +0000587 return PyMac_DoYield(maxsleep, 1);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000588}
589
590/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000591** Return current scheduler parameters
Jack Jansene8e8ae01995-01-26 16:36:45 +0000592*/
Jack Jansene3ae0df1997-06-03 15:28:29 +0000593void
594PyMac_GetSchedParams(PyMacSchedParams *sp)
Jack Jansene8e8ae01995-01-26 16:36:45 +0000595{
Jack Jansene3ae0df1997-06-03 15:28:29 +0000596 sp->check_interrupt = schedparams.check_interrupt;
597 sp->process_events = schedparams.process_events;
598 sp->besocial = schedparams.besocial;
599 sp->check_interval = schedparams.check_interval / 60.0;
600 sp->bg_yield = schedparams.bg_yield / 60.0;
Jack Jansenf93c72a1994-12-14 14:07:50 +0000601}
Jack Jansenf6865f71996-09-04 15:24:59 +0000602
Jack Jansen74162f31995-02-15 22:58:33 +0000603/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000604** Set current scheduler parameters
605*/
606void
607PyMac_SetSchedParams(PyMacSchedParams *sp)
608{
609 schedparams.check_interrupt = sp->check_interrupt;
610 schedparams.process_events = sp->process_events;
611 schedparams.besocial = sp->besocial;
612 schedparams.check_interval = (unsigned long)(sp->check_interval*60);
613 schedparams.bg_yield = (unsigned long)(sp->bg_yield*60);
614 if ( schedparams.check_interrupt || schedparams.process_events ||
615 schedparams.besocial )
616 schedparams.enabled = 1;
617 else
618 schedparams.enabled = 0;
619 schedparams.next_check = 0; /* Check immedeately */
620}
Jack Jansencaa7c461997-06-12 10:49:13 +0000621
Jack Jansene3ae0df1997-06-03 15:28:29 +0000622/*
Jack Jansen3469e991996-09-06 00:30:45 +0000623** Install our menu bar.
624*/
625void
626PyMac_InitMenuBar()
627{
Jack Jansen3469e991996-09-06 00:30:45 +0000628 MenuHandle applemenu;
629
Jack Jansencaa7c461997-06-12 10:49:13 +0000630 if ( (sioux_mbar=GetMenuBar()) == NULL ) {
631 /* Sioux menu not installed yet. Do so */
632 SIOUXSetupMenus();
633 if ( (sioux_mbar=GetMenuBar()) == NULL )
634 return;
635 }
Jack Jansen08c3be31997-04-08 15:27:00 +0000636 if ( (applemenu=GetMenuHandle(SIOUX_APPLEID)) == NULL ) return;
Jack Jansen3469e991996-09-06 00:30:45 +0000637 SetMenuItemText(applemenu, 1, "\pAbout Python...");
638}
639
640/*
Jack Jansencaa7c461997-06-12 10:49:13 +0000641** Restore sioux menu bar
642*/
643void
644PyMac_RestoreMenuBar()
645{
Jack Janseneda78631997-06-12 15:29:46 +0000646 if ( sioux_mbar ) {
Jack Jansencaa7c461997-06-12 10:49:13 +0000647 SetMenuBar(sioux_mbar);
Jack Janseneda78631997-06-12 15:29:46 +0000648 DrawMenuBar();
649 }
Jack Jansencaa7c461997-06-12 10:49:13 +0000650}
651
652
653/*
Jack Jansen3469e991996-09-06 00:30:45 +0000654** Our replacement about box
655*/
656void
657SIOUXDoAboutBox(void)
658{
659 DialogPtr theDialog;
Jack Jansend617c571996-09-22 22:14:30 +0000660 WindowRef theWindow;
661 CGrafPtr thePort;
Jack Jansen3469e991996-09-06 00:30:45 +0000662 short item;
Jack Jansend617c571996-09-22 22:14:30 +0000663 short xpos, ypos, width, height, swidth, sheight;
Jack Jansen3469e991996-09-06 00:30:45 +0000664
665 if( (theDialog = GetNewDialog(ABOUT_ID, NULL, (WindowPtr)-1)) == NULL )
666 return;
Jack Jansend617c571996-09-22 22:14:30 +0000667 theWindow = GetDialogWindow(theDialog);
668 thePort = GetWindowPort(theWindow);
669 width = thePort->portRect.right - thePort->portRect.left;
670 height = thePort->portRect.bottom - thePort->portRect.top;
671 swidth = qd.screenBits.bounds.right - qd.screenBits.bounds.left;
672 sheight = qd.screenBits.bounds.bottom - qd.screenBits.bounds.top - LMGetMBarHeight();
673 xpos = (swidth-width)/2;
Jack Jansen0e06e7e1996-09-23 15:51:06 +0000674 ypos = (sheight-height)/5 + LMGetMBarHeight();
Jack Jansend617c571996-09-22 22:14:30 +0000675 MoveWindow(theWindow, xpos, ypos, 0);
676 ShowWindow(theWindow);
Jack Jansen3469e991996-09-06 00:30:45 +0000677 ModalDialog(NULL, &item);
678 DisposeDialog(theDialog);
679}
680
681/*
Jack Jansen74162f31995-02-15 22:58:33 +0000682** Returns true if the argument has a resource fork, and it contains
683** a 'PYC ' resource of the correct name
684*/
685int
Jack Janseneda78631997-06-12 15:29:46 +0000686PyMac_FindResourceModule(obj, module, filename)
687PyStringObject *obj;
Jack Jansen74162f31995-02-15 22:58:33 +0000688char *module;
689char *filename;
690{
691 FSSpec fss;
692 FInfo finfo;
693 short oldrh, filerh;
694 int ok;
695 Handle h;
Jack Janseneda78631997-06-12 15:29:46 +0000696
697#ifdef INTERN_STRINGS
698 /*
699 ** If we have interning find_module takes care of interning all
700 ** sys.path components. We then keep a record of all sys.path
701 ** components for which GetFInfo has failed (usually because the
702 ** component in question is a folder), and we don't try opening these
703 ** as resource files again.
704 */
705#define MAXPATHCOMPONENTS 32
706 static PyStringObject *not_a_file[MAXPATHCOMPONENTS];
707 static int max_not_a_file = 0;
708 int i;
709
710 if ( obj->ob_sinterned ) {
711 for( i=0; i< max_not_a_file; i++ )
712 if ( obj == not_a_file[i] )
713 return 0;
714 }
715#endif /* INTERN_STRINGS */
716
Jack Jansen8096daa1996-11-09 18:43:44 +0000717 if ( strcmp(filename, PyMac_ApplicationPath) == 0 ) {
718 /*
719 ** Special case: the application itself. Use a shortcut to
720 ** forestall opening and closing the application numerous times
721 ** (which is dead slow when running from CDROM)
722 */
723 oldrh = CurResFile();
724 UseResFile(PyMac_AppRefNum);
725 filerh = -1;
726 } else {
Jack Janseneda78631997-06-12 15:29:46 +0000727 if ( FSMakeFSSpec(0, 0, Pstring(filename), &fss) != noErr ||
728 FSpGetFInfo(&fss, &finfo) != noErr ) {
729#ifdef INTERN_STRINGS
730 if ( max_not_a_file < MAXPATHCOMPONENTS && obj->ob_sinterned )
731 not_a_file[max_not_a_file++] = obj;
732#endif /* INTERN_STRINGS */
733 /* doesn't exist or is folder */
734 return 0;
735 }
Jack Jansen8096daa1996-11-09 18:43:44 +0000736 oldrh = CurResFile();
737 filerh = FSpOpenResFile(&fss, fsRdPerm);
738 if ( filerh == -1 )
739 return 0;
740 UseResFile(filerh);
741 }
Jack Jansen74162f31995-02-15 22:58:33 +0000742 SetResLoad(0);
743 h = Get1NamedResource('PYC ', Pstring(module));
744 SetResLoad(1);
745 ok = (h != NULL);
Jack Jansen8096daa1996-11-09 18:43:44 +0000746 if ( filerh != -1 )
747 CloseResFile(filerh);
Jack Jansen74162f31995-02-15 22:58:33 +0000748 UseResFile(oldrh);
749 return ok;
750}
751
752/*
753** Load the specified module from a resource
754*/
755PyObject *
756PyMac_LoadResourceModule(module, filename)
757char *module;
758char *filename;
759{
760 FSSpec fss;
761 FInfo finfo;
762 short oldrh, filerh;
Jack Jansen74162f31995-02-15 22:58:33 +0000763 Handle h;
764 OSErr err;
765 PyObject *m, *co;
766 long num, size;
767
Jack Jansen8096daa1996-11-09 18:43:44 +0000768 if ( strcmp(filename, PyMac_ApplicationPath) == 0 ) {
769 /*
770 ** Special case: the application itself. Use a shortcut to
771 ** forestall opening and closing the application numerous times
772 ** (which is dead slow when running from CDROM)
773 */
774 oldrh = CurResFile();
775 UseResFile(PyMac_AppRefNum);
776 filerh = -1;
777 } else {
778 if ( (err=FSMakeFSSpec(0, 0, Pstring(filename), &fss)) != noErr )
779 goto error;
780 if ( (err=FSpGetFInfo(&fss, &finfo)) != noErr )
781 goto error;
782 oldrh = CurResFile();
783 filerh = FSpOpenResFile(&fss, fsRdPerm);
784 if ( filerh == -1 ) {
785 err = ResError();
786 goto error;
787 }
788 UseResFile(filerh);
Jack Jansen74162f31995-02-15 22:58:33 +0000789 }
Jack Jansen74162f31995-02-15 22:58:33 +0000790 h = Get1NamedResource('PYC ', Pstring(module));
791 if ( h == NULL ) {
792 err = ResError();
793 goto error;
794 }
795 HLock(h);
796 /*
797 ** XXXX The next few lines are intimately tied to the format of pyc
798 ** files. I'm not sure whether this code should be here or in import.c -- Jack
799 */
800 size = GetHandleSize(h);
801 if ( size < 8 ) {
802 PyErr_SetString(PyExc_ImportError, "Resource too small");
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000803 co = NULL;
Jack Jansen74162f31995-02-15 22:58:33 +0000804 } else {
805 num = (*h)[0] & 0xff;
806 num = num | (((*h)[1] & 0xff) << 8);
807 num = num | (((*h)[2] & 0xff) << 16);
808 num = num | (((*h)[3] & 0xff) << 24);
809 if ( num != PyImport_GetMagicNumber() ) {
810 PyErr_SetString(PyExc_ImportError, "Bad MAGIC in resource");
811 co = NULL;
812 } else {
813 co = PyMarshal_ReadObjectFromString((*h)+8, size-8);
814 }
815 }
816 HUnlock(h);
Jack Jansen8096daa1996-11-09 18:43:44 +0000817 if ( filerh != -1 )
818 CloseResFile(filerh);
Jack Jansen74162f31995-02-15 22:58:33 +0000819 UseResFile(oldrh);
820 if ( co ) {
821 m = PyImport_ExecCodeModule(module, co);
822 Py_DECREF(co);
823 } else {
824 m = NULL;
825 }
826 return m;
827error:
828 {
829 char buf[512];
830
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000831 sprintf(buf, "%s: %s", filename, PyMac_StrError(err));
Jack Jansen74162f31995-02-15 22:58:33 +0000832 PyErr_SetString(PyExc_ImportError, buf);
833 return NULL;
834 }
835}
Guido van Rossum24a45e31995-02-20 23:45:53 +0000836
Jack Jansen3ec804a1995-02-20 15:56:10 +0000837/*
Jack Janseneda78631997-06-12 15:29:46 +0000838** Look for a module in a single folder. Upon entry buf and len
839** point to the folder to search, upon exit they refer to the full
840** pathname of the module found (if any).
841*/
842struct filedescr *
843PyMac_FindModuleExtension(char *buf, int *lenp, char *module)
844{
845 struct filedescr *fdp;
846 unsigned char fnbuf[64];
847 int modnamelen = strlen(module);
848 FSSpec fss;
849 short refnum;
850 long dirid;
851
852 /*
853 ** Copy the module name to the buffer (already :-terminated)
854 ** We also copy the first suffix, if this matches immedeately we're
855 ** lucky and return immedeately.
856 */
857 if ( !_PyImport_Filetab[0].suffix )
858 return 0;
859
860 strcpy(buf+*lenp, module);
861 strcpy(buf+*lenp+modnamelen, _PyImport_Filetab[0].suffix);
862 if ( FSMakeFSSpec(0, 0, Pstring(buf), &fss) == noErr )
863 return _PyImport_Filetab;
864 /*
865 ** We cannot check for fnfErr (unfortunately), it can mean either that
866 ** the file doesn't exist (fine, we try others) or the path leading to it.
867 */
868 refnum = fss.vRefNum;
869 dirid = fss.parID;
870 if ( refnum == 0 || dirid == 0 ) /* Fail on nonexistent dir */
871 return 0;
872 /*
873 ** We now have the folder parameters. Setup the field for the filename
874 */
875 if ( modnamelen > 54 ) return 0; /* Leave room for extension */
876 strcpy((char *)fnbuf+1, module);
877
878 for( fdp = _PyImport_Filetab+1; fdp->suffix; fdp++ ) {
879 strcpy((char *)fnbuf+1+modnamelen, fdp->suffix);
880 fnbuf[0] = strlen((char *)fnbuf+1);
881 if (Py_VerboseFlag > 1)
882 fprintf(stderr, "# trying %s%s\n", buf, fdp->suffix);
883 if ( FSMakeFSSpec(refnum, dirid, fnbuf, &fss) == noErr ) {
884 /* Found it. */
885 strcpy(buf+*lenp+modnamelen, fdp->suffix);
886 *lenp = strlen(buf);
887 return fdp;
888 }
889 }
890 return 0;
891}
892
893#if 0
894int
895PyMac_FileExists(char *name)
896{
897 FSSpec fss;
898
899 if ( FSMakeFSSpec(0, 0, Pstring(name), &fss) == noErr )
900 return 1;
901 return 0;
902}
903#endif
904
905/*
Jack Jansen3ec804a1995-02-20 15:56:10 +0000906** Helper routine for GetDirectory
907*/
Guido van Rossum24a45e31995-02-20 23:45:53 +0000908static pascal short
Jack Jansen819f1771995-08-14 12:35:10 +0000909myhook_proc(short item, DialogPtr theDialog, struct hook_args *dataptr)
Jack Jansen3ec804a1995-02-20 15:56:10 +0000910{
Jack Jansen819f1771995-08-14 12:35:10 +0000911 if ( item == sfHookFirstCall && dataptr->prompt) {
912 Handle prompth;
913 short type;
914 Rect rect;
915
916 GetDialogItem(theDialog, PROMPT_ITEM, &type, &prompth, &rect);
917 if ( prompth )
918 SetDialogItemText(prompth, (unsigned char *)dataptr->prompt);
919 } else
Jack Jansen3ec804a1995-02-20 15:56:10 +0000920 if ( item == SELECTCUR_ITEM ) {
921 item = sfItemCancelButton;
Jack Jansen819f1771995-08-14 12:35:10 +0000922 dataptr->selectcur_hit = 1;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000923 }
924 return item;
925}
926
927/*
928** Ask the user for a directory. I still can't understand
929** why Apple doesn't provide a standard solution for this...
930*/
931int
Jack Jansen819f1771995-08-14 12:35:10 +0000932PyMac_GetDirectory(dirfss, prompt)
Jack Jansen3ec804a1995-02-20 15:56:10 +0000933 FSSpec *dirfss;
Jack Jansen819f1771995-08-14 12:35:10 +0000934 char *prompt;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000935{
936 static SFTypeList list = {'fldr', 0, 0, 0};
937 static Point where = {-1, -1};
Jack Jansen3ec804a1995-02-20 15:56:10 +0000938 StandardFileReply reply;
Jack Jansen819f1771995-08-14 12:35:10 +0000939 struct hook_args hook_args;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000940
941 if ( !upp_inited ) {
942 myhook_upp = NewDlgHookYDProc(myhook_proc);
943 upp_inited = 1;
944 }
Jack Jansen819f1771995-08-14 12:35:10 +0000945 if ( prompt && *prompt )
946 hook_args.prompt = (char *)Pstring(prompt);
947 else
948 hook_args.prompt = NULL;
949 hook_args.selectcur_hit = 0;
Guido van Rossum24a45e31995-02-20 23:45:53 +0000950 CustomGetFile((FileFilterYDUPP)0, 1, list, &reply, GETDIR_ID, where, myhook_upp,
Jack Jansen819f1771995-08-14 12:35:10 +0000951 NULL, NULL, NULL, (void *)&hook_args);
Jack Jansen3ec804a1995-02-20 15:56:10 +0000952
953 reply.sfFile.name[0] = 0;
954 if( FSMakeFSSpec(reply.sfFile.vRefNum, reply.sfFile.parID, reply.sfFile.name, dirfss) )
955 return 0;
Jack Jansen819f1771995-08-14 12:35:10 +0000956 return hook_args.selectcur_hit;
957}
958
959/*
960** Slightly extended StandardGetFile: accepts a prompt */
961void PyMac_PromptGetFile(short numTypes, ConstSFTypeListPtr typeList,
962 StandardFileReply *reply, char *prompt)
963{
964 static Point where = {-1, -1};
965 struct hook_args hook_args;
966
967 if ( !upp_inited ) {
968 myhook_upp = NewDlgHookYDProc(myhook_proc);
969 upp_inited = 1;
970 }
971 if ( prompt && *prompt )
972 hook_args.prompt = (char *)Pstring(prompt);
973 else
974 hook_args.prompt = NULL;
975 hook_args.selectcur_hit = 0;
976 CustomGetFile((FileFilterYDUPP)0, numTypes, typeList, reply, GETFILEPROMPT_ID, where,
977 myhook_upp, NULL, NULL, NULL, (void *)&hook_args);
Jack Jansen3ec804a1995-02-20 15:56:10 +0000978}
Jack Jansen5f653091995-01-18 13:53:49 +0000979
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000980/* Convert a 4-char string object argument to an OSType value */
Jack Jansen5f653091995-01-18 13:53:49 +0000981int
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000982PyMac_GetOSType(PyObject *v, OSType *pr)
Jack Jansen5f653091995-01-18 13:53:49 +0000983{
984 if (!PyString_Check(v) || PyString_Size(v) != 4) {
985 PyErr_SetString(PyExc_TypeError,
986 "OSType arg must be string of 4 chars");
987 return 0;
988 }
989 memcpy((char *)pr, PyString_AsString(v), 4);
990 return 1;
991}
992
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000993/* Convert an OSType value to a 4-char string object */
994PyObject *
995PyMac_BuildOSType(OSType t)
996{
997 return PyString_FromStringAndSize((char *)&t, 4);
998}
999
Jack Jansend1f06311996-08-01 15:23:54 +00001000/* Convert an NumVersion value to a 4-element tuple */
1001PyObject *
1002PyMac_BuildNumVersion(NumVersion t)
1003{
1004 return Py_BuildValue("(hhhh)", t.majorRev, t.minorAndBugRev, t.stage, t.nonRelRev);
1005}
1006
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001007
1008/* Convert a Python string object to a Str255 */
Jack Jansen5f653091995-01-18 13:53:49 +00001009int
Guido van Rossum8f691791995-01-18 23:57:26 +00001010PyMac_GetStr255(PyObject *v, Str255 pbuf)
Jack Jansen5f653091995-01-18 13:53:49 +00001011{
1012 int len;
1013 if (!PyString_Check(v) || (len = PyString_Size(v)) > 255) {
1014 PyErr_SetString(PyExc_TypeError,
1015 "Str255 arg must be string of at most 255 chars");
1016 return 0;
1017 }
1018 pbuf[0] = len;
1019 memcpy((char *)(pbuf+1), PyString_AsString(v), len);
1020 return 1;
1021}
1022
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001023/* Convert a Str255 to a Python string object */
1024PyObject *
1025PyMac_BuildStr255(Str255 s)
1026{
1027 return PyString_FromStringAndSize((char *)&s[1], (int)s[0]);
1028}
1029
1030
Jack Jansen5f653091995-01-18 13:53:49 +00001031/*
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001032** Convert a Python object to an FSSpec.
1033** The object may either be a full pathname or a triple
1034** (vrefnum, dirid, path).
Jack Jansen5f653091995-01-18 13:53:49 +00001035** NOTE: This routine will fail on pre-sys7 machines.
1036** The caller is responsible for not calling this routine
1037** in those cases (which is fine, since everyone calling
1038** this is probably sys7 dependent anyway).
1039*/
1040int
Guido van Rossum8f691791995-01-18 23:57:26 +00001041PyMac_GetFSSpec(PyObject *v, FSSpec *fs)
Jack Jansen5f653091995-01-18 13:53:49 +00001042{
1043 Str255 path;
1044 short refnum;
1045 long parid;
1046 OSErr err;
Jack Jansene8e8ae01995-01-26 16:36:45 +00001047 FSSpec *fs2;
Jack Jansen5f653091995-01-18 13:53:49 +00001048
Jack Jansene8e8ae01995-01-26 16:36:45 +00001049 /* first check whether it already is an FSSpec */
1050 fs2 = mfs_GetFSSpecFSSpec(v);
1051 if ( fs2 ) {
Jack Jansen3ec804a1995-02-20 15:56:10 +00001052 (void)FSMakeFSSpec(fs2->vRefNum, fs2->parID, fs2->name, fs);
Jack Jansene8e8ae01995-01-26 16:36:45 +00001053 return 1;
1054 }
Jack Jansen5f653091995-01-18 13:53:49 +00001055 if ( PyString_Check(v) ) {
1056 /* It's a pathname */
Guido van Rossum9aa3d131995-01-21 13:46:04 +00001057 if( !PyArg_Parse(v, "O&", PyMac_GetStr255, &path) )
Jack Jansen5f653091995-01-18 13:53:49 +00001058 return 0;
Jack Jansen378815c1996-03-06 16:21:34 +00001059 refnum = 0; /* XXXX Should get CurWD here?? */
Jack Jansen5f653091995-01-18 13:53:49 +00001060 parid = 0;
1061 } else {
Guido van Rossum9aa3d131995-01-21 13:46:04 +00001062 if( !PyArg_Parse(v, "(hlO&); FSSpec should be fullpath or (vrefnum,dirid,path)",
1063 &refnum, &parid, PyMac_GetStr255, &path)) {
Jack Jansen5f653091995-01-18 13:53:49 +00001064 return 0;
Guido van Rossum9aa3d131995-01-21 13:46:04 +00001065 }
Jack Jansen5f653091995-01-18 13:53:49 +00001066 }
1067 err = FSMakeFSSpec(refnum, parid, path, fs);
1068 if ( err && err != fnfErr ) {
Guido van Rossum9aa3d131995-01-21 13:46:04 +00001069 PyErr_Mac(PyExc_ValueError, err);
Jack Jansen5f653091995-01-18 13:53:49 +00001070 return 0;
1071 }
1072 return 1;
1073}
1074
Guido van Rossum8f691791995-01-18 23:57:26 +00001075
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001076/* Convert a Python object to a Rect.
Guido van Rossum5279ec61995-01-26 22:56:59 +00001077 The object must be a (left, top, right, bottom) tuple.
1078 (This differs from the order in the struct but is consistent with
1079 the arguments to SetRect(), and also with STDWIN). */
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001080int
1081PyMac_GetRect(PyObject *v, Rect *r)
Guido van Rossum8f691791995-01-18 23:57:26 +00001082{
Guido van Rossum5279ec61995-01-26 22:56:59 +00001083 return PyArg_Parse(v, "(hhhh)", &r->left, &r->top, &r->right, &r->bottom);
Guido van Rossum8f691791995-01-18 23:57:26 +00001084}
Guido van Rossumb3404661995-01-22 18:36:13 +00001085
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001086/* Convert a Rect to a Python object */
Guido van Rossumb3404661995-01-22 18:36:13 +00001087PyObject *
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001088PyMac_BuildRect(Rect *r)
Guido van Rossumb3404661995-01-22 18:36:13 +00001089{
Guido van Rossum5279ec61995-01-26 22:56:59 +00001090 return Py_BuildValue("(hhhh)", r->left, r->top, r->right, r->bottom);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001091}
1092
1093
1094/* Convert a Python object to a Point.
Guido van Rossum5279ec61995-01-26 22:56:59 +00001095 The object must be a (h, v) tuple.
1096 (This differs from the order in the struct but is consistent with
1097 the arguments to SetPoint(), and also with STDWIN). */
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001098int
1099PyMac_GetPoint(PyObject *v, Point *p)
1100{
Guido van Rossum5279ec61995-01-26 22:56:59 +00001101 return PyArg_Parse(v, "(hh)", &p->h, &p->v);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001102}
1103
1104/* Convert a Point to a Python object */
1105PyObject *
1106PyMac_BuildPoint(Point p)
1107{
Guido van Rossum5279ec61995-01-26 22:56:59 +00001108 return Py_BuildValue("(hh)", p.h, p.v);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001109}
1110
1111
1112/* Convert a Python object to an EventRecord.
1113 The object must be a (what, message, when, (v, h), modifiers) tuple. */
1114int
1115PyMac_GetEventRecord(PyObject *v, EventRecord *e)
1116{
1117 return PyArg_Parse(v, "(hll(hh)h)",
1118 &e->what,
1119 &e->message,
1120 &e->when,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001121 &e->where.h,
Guido van Rossum5279ec61995-01-26 22:56:59 +00001122 &e->where.v,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001123 &e->modifiers);
1124}
1125
1126/* Convert a Rect to an EventRecord object */
1127PyObject *
1128PyMac_BuildEventRecord(EventRecord *e)
1129{
1130 return Py_BuildValue("(hll(hh)h)",
1131 e->what,
1132 e->message,
1133 e->when,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001134 e->where.h,
Guido van Rossum5279ec61995-01-26 22:56:59 +00001135 e->where.v,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001136 e->modifiers);
Guido van Rossumb3404661995-01-22 18:36:13 +00001137}
Jack Jansenfa4d5d01995-11-15 15:19:29 +00001138
1139/* Convert Python object to Fixed */
1140int
1141PyMac_GetFixed(PyObject *v, Fixed *f)
1142{
1143 double d;
1144
1145 if( !PyArg_Parse(v, "d", &d))
1146 return 0;
1147 *f = (Fixed)(d * 0x10000);
Jack Jansen31dd5c01996-05-31 13:01:39 +00001148 return 1;
Jack Jansenfa4d5d01995-11-15 15:19:29 +00001149}
1150
1151/* Convert a Point to a Python object */
1152PyObject *
1153PyMac_BuildFixed(Fixed f)
1154{
1155 double d;
1156
1157 d = f;
1158 d = d / 0x10000;
1159 return Py_BuildValue("d", d);
1160}
1161