blob: b4db23c4cfde29f4f561c4ded80983c0d209c7de [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
377/*
378** This routine scans the event queue looking for cmd-.
379** This is the only way to get an interrupt under THINK (since it
380** doesn't do SIGINT handling), but is also used under MW, when
381** the full-fledged event loop is disabled. This way, we can at least
382** interrupt a runaway python program.
383*/
384static void
385scan_event_queue(flush)
386 int flush;
387{
388 register EvQElPtr q;
389
Jack Jansencfadbd41996-08-19 11:36:25 +0000390 q = (EvQElPtr) GetEventQueue()->qHead;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000391
392 for (; q; q = (EvQElPtr)q->qLink) {
393 if (q->evtQWhat == keyDown &&
394 (char)q->evtQMessage == '.' &&
395 (q->evtQModifiers & cmdKey) != 0) {
396 if ( flush )
397 FlushEvents(keyDownMask, 0);
398 interrupted = 1;
399 break;
400 }
401 }
402}
403
404int
Jack Jansen36ed5061997-06-20 16:18:15 +0000405PyErr_CheckSignals()
Jack Jansenee23d6e1995-01-27 14:43:25 +0000406{
Jack Jansene3ae0df1997-06-03 15:28:29 +0000407 if (schedparams.enabled) {
408 if ( (unsigned long)LMGetTicks() > schedparams.next_check ) {
Jack Jansen36ed5061997-06-20 16:18:15 +0000409 if ( PyMac_Yield() < 0)
410 return -1;
Jack Jansene3ae0df1997-06-03 15:28:29 +0000411 schedparams.next_check = (unsigned long)LMGetTicks()
412 + schedparams.check_interval;
413 if (interrupted) {
Jack Jansencaa7c461997-06-12 10:49:13 +0000414 scan_event_queue(1); /* Eat events up to cmd-. */
Jack Jansene3ae0df1997-06-03 15:28:29 +0000415 interrupted = 0;
Jack Jansen36ed5061997-06-20 16:18:15 +0000416 PyErr_SetNone(PyExc_KeyboardInterrupt);
417 return -1;
Jack Jansene3ae0df1997-06-03 15:28:29 +0000418 }
419 }
Jack Jansenee23d6e1995-01-27 14:43:25 +0000420 }
421 return 0;
422}
423
Jack Jansen36ed5061997-06-20 16:18:15 +0000424int
425PyOS_InterruptOccurred()
426{
427 scan_event_queue(1);
428 return interrupted;
429}
Jack Jansenee23d6e1995-01-27 14:43:25 +0000430/* Check whether we are in the foreground */
431int
432PyMac_InForeground()
433{
434 static ProcessSerialNumber ours;
435 static inited;
436 ProcessSerialNumber curfg;
437 Boolean eq;
438
Jack Jansene3ae0df1997-06-03 15:28:29 +0000439 if ( inited == 0 ) {
Jack Jansenee23d6e1995-01-27 14:43:25 +0000440 (void)GetCurrentProcess(&ours);
Jack Jansene3ae0df1997-06-03 15:28:29 +0000441 inited = 1;
442 }
Jack Jansenee23d6e1995-01-27 14:43:25 +0000443 if ( GetFrontProcess(&curfg) < 0 )
444 eq = 1;
445 else if ( SameProcess(&ours, &curfg, &eq) < 0 )
446 eq = 1;
447 return (int)eq;
448
449}
450
Jack Jansen36ed5061997-06-20 16:18:15 +0000451int
452PyMac_SetEventHandler(PyObject *evh)
453{
454 if ( evh && python_event_handler ) {
455 PyErr_SetString(PyExc_RuntimeError, "Python event handler already set");
456 return 0;
457 }
458 if ( python_event_handler )
459 Py_DECREF(python_event_handler);
460 if ( evh )
461 Py_INCREF(evh);
462 python_event_handler = evh;
463 return 1;
464}
465
Jack Jansenf93c72a1994-12-14 14:07:50 +0000466/*
Jack Jansena76382a1995-02-02 14:25:56 +0000467** Handle an event, either one found in the mainloop eventhandler or
468** one passed back from the python program.
469*/
470void
Jack Jansen36ed5061997-06-20 16:18:15 +0000471PyMac_HandleEventIntern(evp)
Jack Jansena76382a1995-02-02 14:25:56 +0000472 EventRecord *evp;
473{
Jack Jansena76382a1995-02-02 14:25:56 +0000474#ifdef __MWERKS__
Jack Jansen38e97661995-11-10 14:53:00 +0000475 {
476 int siouxdidit;
477
478 /* If SIOUX wants it we're done */
479 siouxdidit = SIOUXHandleOneEvent(evp);
480 if ( siouxdidit )
481 return;
482 }
Jack Jansena76382a1995-02-02 14:25:56 +0000483#else
484 /* Other compilers are just unlucky: we only weed out clicks in other applications */
485 if ( evp->what == mouseDown ) {
Jack Jansen847e89e1995-08-31 13:57:40 +0000486 WindowPtr wp;
487
Jack Jansen38e97661995-11-10 14:53:00 +0000488 if ( FindWindow(evp->where, &wp) == inSysWindow ) {
Jack Jansena76382a1995-02-02 14:25:56 +0000489 SystemClick(evp, wp);
Jack Jansen38e97661995-11-10 14:53:00 +0000490 return;
491 }
Jack Jansena76382a1995-02-02 14:25:56 +0000492 }
493#endif /* !__MWERKS__ */
Jack Jansen36ed5061997-06-20 16:18:15 +0000494}
495
496/*
497** Handle an event, either through HandleEvent or by passing it to the Python
498** event handler.
499*/
500int
501PyMac_HandleEvent(evp)
502 EventRecord *evp;
503{
504 PyObject *rv;
505
506 if ( python_event_handler ) {
507 rv = PyObject_CallFunction(python_event_handler, "(O&)",
508 PyMac_BuildEventRecord, evp);
509 if ( rv )
510 Py_DECREF(rv);
511 else
512 return -1; /* Propagate exception */
513 } else {
514 PyMac_HandleEventIntern(evp);
515 }
516 return 0;
Jack Jansena76382a1995-02-02 14:25:56 +0000517}
518
519/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000520** Yield the CPU to other tasks without processing events.
Jack Jansene8e8ae01995-01-26 16:36:45 +0000521*/
Jack Jansen36ed5061997-06-20 16:18:15 +0000522static int
Jack Jansene3ae0df1997-06-03 15:28:29 +0000523PyMac_DoYield(int maxsleep, int maycallpython)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000524{
525 EventRecord ev;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000526 int gotone;
Jack Jansene3ae0df1997-06-03 15:28:29 +0000527 long latest_time_ready;
Jack Jansen36ed5061997-06-20 16:18:15 +0000528 static int in_here = 0;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000529
Jack Jansen36ed5061997-06-20 16:18:15 +0000530 in_here++;
Jack Jansene3ae0df1997-06-03 15:28:29 +0000531 /*
532 ** First check for interrupts, if wanted.
533 ** This sets a flag that will be picked up at an appropriate
534 ** moment in the mainloop.
535 */
536 if (schedparams.check_interrupt)
Jack Jansenee23d6e1995-01-27 14:43:25 +0000537 scan_event_queue(0);
Jack Jansene3ae0df1997-06-03 15:28:29 +0000538
539 /* XXXX Implementing an idle routine goes here */
Jack Jansene8e8ae01995-01-26 16:36:45 +0000540
Jack Jansene3ae0df1997-06-03 15:28:29 +0000541 /*
542 ** Check which of the eventloop cases we have:
543 ** - process events
544 ** - don't process events but do yield
545 ** - do neither
546 */
Jack Jansen36ed5061997-06-20 16:18:15 +0000547 if( in_here > 1 || !schedparams.process_events ||
548 (python_event_handler && !maycallpython) ) {
Jack Jansene3ae0df1997-06-03 15:28:29 +0000549 if ( maxsleep >= 0 ) {
Jack Jansene8e8ae01995-01-26 16:36:45 +0000550 SystemTask();
Jack Jansene3ae0df1997-06-03 15:28:29 +0000551 }
552 } else {
553 latest_time_ready = LMGetTicks() + maxsleep;
554 while ( maxsleep >= 0 ) {
Jack Jansen36ed5061997-06-20 16:18:15 +0000555 gotone = WaitNextEvent(schedparams.process_events, &ev, maxsleep, NULL);
Jack Jansene3ae0df1997-06-03 15:28:29 +0000556 /* Get out quickly if nothing interesting is happening */
557 if ( !gotone || ev.what == nullEvent )
558 break;
Jack Jansen36ed5061997-06-20 16:18:15 +0000559 if ( PyMac_HandleEvent(&ev) < 0 ) {
560 in_here--;
561 return -1;
562 }
Jack Jansene3ae0df1997-06-03 15:28:29 +0000563 maxsleep = latest_time_ready - LMGetTicks();
564 }
Jack Jansenf93c72a1994-12-14 14:07:50 +0000565 }
Jack Jansen36ed5061997-06-20 16:18:15 +0000566 in_here--;
567 return 0;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000568}
569
570/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000571** Process events and/or yield the CPU to other tasks if opportune
Jack Jansene8e8ae01995-01-26 16:36:45 +0000572*/
Jack Jansen36ed5061997-06-20 16:18:15 +0000573int
Jack Jansene8e8ae01995-01-26 16:36:45 +0000574PyMac_Yield() {
Jack Jansene3ae0df1997-06-03 15:28:29 +0000575 unsigned long maxsleep;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000576
Jack Jansene3ae0df1997-06-03 15:28:29 +0000577 if( PyMac_InForeground() )
578 maxsleep = 0;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000579 else
Jack Jansene3ae0df1997-06-03 15:28:29 +0000580 maxsleep = schedparams.bg_yield;
581
Jack Jansen36ed5061997-06-20 16:18:15 +0000582 return PyMac_DoYield(maxsleep, 1);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000583}
584
585/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000586** Return current scheduler parameters
Jack Jansene8e8ae01995-01-26 16:36:45 +0000587*/
Jack Jansene3ae0df1997-06-03 15:28:29 +0000588void
589PyMac_GetSchedParams(PyMacSchedParams *sp)
Jack Jansene8e8ae01995-01-26 16:36:45 +0000590{
Jack Jansene3ae0df1997-06-03 15:28:29 +0000591 sp->check_interrupt = schedparams.check_interrupt;
592 sp->process_events = schedparams.process_events;
593 sp->besocial = schedparams.besocial;
594 sp->check_interval = schedparams.check_interval / 60.0;
595 sp->bg_yield = schedparams.bg_yield / 60.0;
Jack Jansenf93c72a1994-12-14 14:07:50 +0000596}
Jack Jansenf6865f71996-09-04 15:24:59 +0000597
Jack Jansen74162f31995-02-15 22:58:33 +0000598/*
Jack Jansene3ae0df1997-06-03 15:28:29 +0000599** Set current scheduler parameters
600*/
601void
602PyMac_SetSchedParams(PyMacSchedParams *sp)
603{
604 schedparams.check_interrupt = sp->check_interrupt;
605 schedparams.process_events = sp->process_events;
606 schedparams.besocial = sp->besocial;
607 schedparams.check_interval = (unsigned long)(sp->check_interval*60);
608 schedparams.bg_yield = (unsigned long)(sp->bg_yield*60);
609 if ( schedparams.check_interrupt || schedparams.process_events ||
610 schedparams.besocial )
611 schedparams.enabled = 1;
612 else
613 schedparams.enabled = 0;
614 schedparams.next_check = 0; /* Check immedeately */
615}
Jack Jansencaa7c461997-06-12 10:49:13 +0000616
Jack Jansene3ae0df1997-06-03 15:28:29 +0000617/*
Jack Jansen3469e991996-09-06 00:30:45 +0000618** Install our menu bar.
619*/
620void
621PyMac_InitMenuBar()
622{
Jack Jansen3469e991996-09-06 00:30:45 +0000623 MenuHandle applemenu;
624
Jack Jansencaa7c461997-06-12 10:49:13 +0000625 if ( (sioux_mbar=GetMenuBar()) == NULL ) {
626 /* Sioux menu not installed yet. Do so */
627 SIOUXSetupMenus();
628 if ( (sioux_mbar=GetMenuBar()) == NULL )
629 return;
630 }
Jack Jansen08c3be31997-04-08 15:27:00 +0000631 if ( (applemenu=GetMenuHandle(SIOUX_APPLEID)) == NULL ) return;
Jack Jansen3469e991996-09-06 00:30:45 +0000632 SetMenuItemText(applemenu, 1, "\pAbout Python...");
633}
634
635/*
Jack Jansencaa7c461997-06-12 10:49:13 +0000636** Restore sioux menu bar
637*/
638void
639PyMac_RestoreMenuBar()
640{
Jack Janseneda78631997-06-12 15:29:46 +0000641 if ( sioux_mbar ) {
Jack Jansencaa7c461997-06-12 10:49:13 +0000642 SetMenuBar(sioux_mbar);
Jack Janseneda78631997-06-12 15:29:46 +0000643 DrawMenuBar();
644 }
Jack Jansencaa7c461997-06-12 10:49:13 +0000645}
646
647
648/*
Jack Jansen3469e991996-09-06 00:30:45 +0000649** Our replacement about box
650*/
651void
652SIOUXDoAboutBox(void)
653{
654 DialogPtr theDialog;
Jack Jansend617c571996-09-22 22:14:30 +0000655 WindowRef theWindow;
656 CGrafPtr thePort;
Jack Jansen3469e991996-09-06 00:30:45 +0000657 short item;
Jack Jansend617c571996-09-22 22:14:30 +0000658 short xpos, ypos, width, height, swidth, sheight;
Jack Jansen3469e991996-09-06 00:30:45 +0000659
660 if( (theDialog = GetNewDialog(ABOUT_ID, NULL, (WindowPtr)-1)) == NULL )
661 return;
Jack Jansend617c571996-09-22 22:14:30 +0000662 theWindow = GetDialogWindow(theDialog);
663 thePort = GetWindowPort(theWindow);
664 width = thePort->portRect.right - thePort->portRect.left;
665 height = thePort->portRect.bottom - thePort->portRect.top;
666 swidth = qd.screenBits.bounds.right - qd.screenBits.bounds.left;
667 sheight = qd.screenBits.bounds.bottom - qd.screenBits.bounds.top - LMGetMBarHeight();
668 xpos = (swidth-width)/2;
Jack Jansen0e06e7e1996-09-23 15:51:06 +0000669 ypos = (sheight-height)/5 + LMGetMBarHeight();
Jack Jansend617c571996-09-22 22:14:30 +0000670 MoveWindow(theWindow, xpos, ypos, 0);
671 ShowWindow(theWindow);
Jack Jansen3469e991996-09-06 00:30:45 +0000672 ModalDialog(NULL, &item);
673 DisposeDialog(theDialog);
674}
675
676/*
Jack Jansen74162f31995-02-15 22:58:33 +0000677** Returns true if the argument has a resource fork, and it contains
678** a 'PYC ' resource of the correct name
679*/
680int
Jack Janseneda78631997-06-12 15:29:46 +0000681PyMac_FindResourceModule(obj, module, filename)
682PyStringObject *obj;
Jack Jansen74162f31995-02-15 22:58:33 +0000683char *module;
684char *filename;
685{
686 FSSpec fss;
687 FInfo finfo;
688 short oldrh, filerh;
689 int ok;
690 Handle h;
Jack Janseneda78631997-06-12 15:29:46 +0000691
692#ifdef INTERN_STRINGS
693 /*
694 ** If we have interning find_module takes care of interning all
695 ** sys.path components. We then keep a record of all sys.path
696 ** components for which GetFInfo has failed (usually because the
697 ** component in question is a folder), and we don't try opening these
698 ** as resource files again.
699 */
700#define MAXPATHCOMPONENTS 32
701 static PyStringObject *not_a_file[MAXPATHCOMPONENTS];
702 static int max_not_a_file = 0;
703 int i;
704
705 if ( obj->ob_sinterned ) {
706 for( i=0; i< max_not_a_file; i++ )
707 if ( obj == not_a_file[i] )
708 return 0;
709 }
710#endif /* INTERN_STRINGS */
711
Jack Jansen8096daa1996-11-09 18:43:44 +0000712 if ( strcmp(filename, PyMac_ApplicationPath) == 0 ) {
713 /*
714 ** Special case: the application itself. Use a shortcut to
715 ** forestall opening and closing the application numerous times
716 ** (which is dead slow when running from CDROM)
717 */
718 oldrh = CurResFile();
719 UseResFile(PyMac_AppRefNum);
720 filerh = -1;
721 } else {
Jack Janseneda78631997-06-12 15:29:46 +0000722 if ( FSMakeFSSpec(0, 0, Pstring(filename), &fss) != noErr ||
723 FSpGetFInfo(&fss, &finfo) != noErr ) {
724#ifdef INTERN_STRINGS
725 if ( max_not_a_file < MAXPATHCOMPONENTS && obj->ob_sinterned )
726 not_a_file[max_not_a_file++] = obj;
727#endif /* INTERN_STRINGS */
728 /* doesn't exist or is folder */
729 return 0;
730 }
Jack Jansen8096daa1996-11-09 18:43:44 +0000731 oldrh = CurResFile();
732 filerh = FSpOpenResFile(&fss, fsRdPerm);
733 if ( filerh == -1 )
734 return 0;
735 UseResFile(filerh);
736 }
Jack Jansen74162f31995-02-15 22:58:33 +0000737 SetResLoad(0);
738 h = Get1NamedResource('PYC ', Pstring(module));
739 SetResLoad(1);
740 ok = (h != NULL);
Jack Jansen8096daa1996-11-09 18:43:44 +0000741 if ( filerh != -1 )
742 CloseResFile(filerh);
Jack Jansen74162f31995-02-15 22:58:33 +0000743 UseResFile(oldrh);
744 return ok;
745}
746
747/*
748** Load the specified module from a resource
749*/
750PyObject *
751PyMac_LoadResourceModule(module, filename)
752char *module;
753char *filename;
754{
755 FSSpec fss;
756 FInfo finfo;
757 short oldrh, filerh;
Jack Jansen74162f31995-02-15 22:58:33 +0000758 Handle h;
759 OSErr err;
760 PyObject *m, *co;
761 long num, size;
762
Jack Jansen8096daa1996-11-09 18:43:44 +0000763 if ( strcmp(filename, PyMac_ApplicationPath) == 0 ) {
764 /*
765 ** Special case: the application itself. Use a shortcut to
766 ** forestall opening and closing the application numerous times
767 ** (which is dead slow when running from CDROM)
768 */
769 oldrh = CurResFile();
770 UseResFile(PyMac_AppRefNum);
771 filerh = -1;
772 } else {
773 if ( (err=FSMakeFSSpec(0, 0, Pstring(filename), &fss)) != noErr )
774 goto error;
775 if ( (err=FSpGetFInfo(&fss, &finfo)) != noErr )
776 goto error;
777 oldrh = CurResFile();
778 filerh = FSpOpenResFile(&fss, fsRdPerm);
779 if ( filerh == -1 ) {
780 err = ResError();
781 goto error;
782 }
783 UseResFile(filerh);
Jack Jansen74162f31995-02-15 22:58:33 +0000784 }
Jack Jansen74162f31995-02-15 22:58:33 +0000785 h = Get1NamedResource('PYC ', Pstring(module));
786 if ( h == NULL ) {
787 err = ResError();
788 goto error;
789 }
790 HLock(h);
791 /*
792 ** XXXX The next few lines are intimately tied to the format of pyc
793 ** files. I'm not sure whether this code should be here or in import.c -- Jack
794 */
795 size = GetHandleSize(h);
796 if ( size < 8 ) {
797 PyErr_SetString(PyExc_ImportError, "Resource too small");
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000798 co = NULL;
Jack Jansen74162f31995-02-15 22:58:33 +0000799 } else {
800 num = (*h)[0] & 0xff;
801 num = num | (((*h)[1] & 0xff) << 8);
802 num = num | (((*h)[2] & 0xff) << 16);
803 num = num | (((*h)[3] & 0xff) << 24);
804 if ( num != PyImport_GetMagicNumber() ) {
805 PyErr_SetString(PyExc_ImportError, "Bad MAGIC in resource");
806 co = NULL;
807 } else {
808 co = PyMarshal_ReadObjectFromString((*h)+8, size-8);
809 }
810 }
811 HUnlock(h);
Jack Jansen8096daa1996-11-09 18:43:44 +0000812 if ( filerh != -1 )
813 CloseResFile(filerh);
Jack Jansen74162f31995-02-15 22:58:33 +0000814 UseResFile(oldrh);
815 if ( co ) {
816 m = PyImport_ExecCodeModule(module, co);
817 Py_DECREF(co);
818 } else {
819 m = NULL;
820 }
821 return m;
822error:
823 {
824 char buf[512];
825
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000826 sprintf(buf, "%s: %s", filename, PyMac_StrError(err));
Jack Jansen74162f31995-02-15 22:58:33 +0000827 PyErr_SetString(PyExc_ImportError, buf);
828 return NULL;
829 }
830}
Guido van Rossum24a45e31995-02-20 23:45:53 +0000831
Jack Jansen3ec804a1995-02-20 15:56:10 +0000832/*
Jack Janseneda78631997-06-12 15:29:46 +0000833** Look for a module in a single folder. Upon entry buf and len
834** point to the folder to search, upon exit they refer to the full
835** pathname of the module found (if any).
836*/
837struct filedescr *
838PyMac_FindModuleExtension(char *buf, int *lenp, char *module)
839{
840 struct filedescr *fdp;
841 unsigned char fnbuf[64];
842 int modnamelen = strlen(module);
843 FSSpec fss;
844 short refnum;
845 long dirid;
846
847 /*
848 ** Copy the module name to the buffer (already :-terminated)
849 ** We also copy the first suffix, if this matches immedeately we're
850 ** lucky and return immedeately.
851 */
852 if ( !_PyImport_Filetab[0].suffix )
853 return 0;
854
855 strcpy(buf+*lenp, module);
856 strcpy(buf+*lenp+modnamelen, _PyImport_Filetab[0].suffix);
857 if ( FSMakeFSSpec(0, 0, Pstring(buf), &fss) == noErr )
858 return _PyImport_Filetab;
859 /*
860 ** We cannot check for fnfErr (unfortunately), it can mean either that
861 ** the file doesn't exist (fine, we try others) or the path leading to it.
862 */
863 refnum = fss.vRefNum;
864 dirid = fss.parID;
865 if ( refnum == 0 || dirid == 0 ) /* Fail on nonexistent dir */
866 return 0;
867 /*
868 ** We now have the folder parameters. Setup the field for the filename
869 */
870 if ( modnamelen > 54 ) return 0; /* Leave room for extension */
871 strcpy((char *)fnbuf+1, module);
872
873 for( fdp = _PyImport_Filetab+1; fdp->suffix; fdp++ ) {
874 strcpy((char *)fnbuf+1+modnamelen, fdp->suffix);
875 fnbuf[0] = strlen((char *)fnbuf+1);
876 if (Py_VerboseFlag > 1)
877 fprintf(stderr, "# trying %s%s\n", buf, fdp->suffix);
878 if ( FSMakeFSSpec(refnum, dirid, fnbuf, &fss) == noErr ) {
879 /* Found it. */
880 strcpy(buf+*lenp+modnamelen, fdp->suffix);
881 *lenp = strlen(buf);
882 return fdp;
883 }
884 }
885 return 0;
886}
887
888#if 0
889int
890PyMac_FileExists(char *name)
891{
892 FSSpec fss;
893
894 if ( FSMakeFSSpec(0, 0, Pstring(name), &fss) == noErr )
895 return 1;
896 return 0;
897}
898#endif
899
900/*
Jack Jansen3ec804a1995-02-20 15:56:10 +0000901** Helper routine for GetDirectory
902*/
Guido van Rossum24a45e31995-02-20 23:45:53 +0000903static pascal short
Jack Jansen819f1771995-08-14 12:35:10 +0000904myhook_proc(short item, DialogPtr theDialog, struct hook_args *dataptr)
Jack Jansen3ec804a1995-02-20 15:56:10 +0000905{
Jack Jansen819f1771995-08-14 12:35:10 +0000906 if ( item == sfHookFirstCall && dataptr->prompt) {
907 Handle prompth;
908 short type;
909 Rect rect;
910
911 GetDialogItem(theDialog, PROMPT_ITEM, &type, &prompth, &rect);
912 if ( prompth )
913 SetDialogItemText(prompth, (unsigned char *)dataptr->prompt);
914 } else
Jack Jansen3ec804a1995-02-20 15:56:10 +0000915 if ( item == SELECTCUR_ITEM ) {
916 item = sfItemCancelButton;
Jack Jansen819f1771995-08-14 12:35:10 +0000917 dataptr->selectcur_hit = 1;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000918 }
919 return item;
920}
921
922/*
923** Ask the user for a directory. I still can't understand
924** why Apple doesn't provide a standard solution for this...
925*/
926int
Jack Jansen819f1771995-08-14 12:35:10 +0000927PyMac_GetDirectory(dirfss, prompt)
Jack Jansen3ec804a1995-02-20 15:56:10 +0000928 FSSpec *dirfss;
Jack Jansen819f1771995-08-14 12:35:10 +0000929 char *prompt;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000930{
931 static SFTypeList list = {'fldr', 0, 0, 0};
932 static Point where = {-1, -1};
Jack Jansen3ec804a1995-02-20 15:56:10 +0000933 StandardFileReply reply;
Jack Jansen819f1771995-08-14 12:35:10 +0000934 struct hook_args hook_args;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000935
936 if ( !upp_inited ) {
937 myhook_upp = NewDlgHookYDProc(myhook_proc);
938 upp_inited = 1;
939 }
Jack Jansen819f1771995-08-14 12:35:10 +0000940 if ( prompt && *prompt )
941 hook_args.prompt = (char *)Pstring(prompt);
942 else
943 hook_args.prompt = NULL;
944 hook_args.selectcur_hit = 0;
Guido van Rossum24a45e31995-02-20 23:45:53 +0000945 CustomGetFile((FileFilterYDUPP)0, 1, list, &reply, GETDIR_ID, where, myhook_upp,
Jack Jansen819f1771995-08-14 12:35:10 +0000946 NULL, NULL, NULL, (void *)&hook_args);
Jack Jansen3ec804a1995-02-20 15:56:10 +0000947
948 reply.sfFile.name[0] = 0;
949 if( FSMakeFSSpec(reply.sfFile.vRefNum, reply.sfFile.parID, reply.sfFile.name, dirfss) )
950 return 0;
Jack Jansen819f1771995-08-14 12:35:10 +0000951 return hook_args.selectcur_hit;
952}
953
954/*
955** Slightly extended StandardGetFile: accepts a prompt */
956void PyMac_PromptGetFile(short numTypes, ConstSFTypeListPtr typeList,
957 StandardFileReply *reply, char *prompt)
958{
959 static Point where = {-1, -1};
960 struct hook_args hook_args;
961
962 if ( !upp_inited ) {
963 myhook_upp = NewDlgHookYDProc(myhook_proc);
964 upp_inited = 1;
965 }
966 if ( prompt && *prompt )
967 hook_args.prompt = (char *)Pstring(prompt);
968 else
969 hook_args.prompt = NULL;
970 hook_args.selectcur_hit = 0;
971 CustomGetFile((FileFilterYDUPP)0, numTypes, typeList, reply, GETFILEPROMPT_ID, where,
972 myhook_upp, NULL, NULL, NULL, (void *)&hook_args);
Jack Jansen3ec804a1995-02-20 15:56:10 +0000973}
Jack Jansen5f653091995-01-18 13:53:49 +0000974
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000975/* Convert a 4-char string object argument to an OSType value */
Jack Jansen5f653091995-01-18 13:53:49 +0000976int
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000977PyMac_GetOSType(PyObject *v, OSType *pr)
Jack Jansen5f653091995-01-18 13:53:49 +0000978{
979 if (!PyString_Check(v) || PyString_Size(v) != 4) {
980 PyErr_SetString(PyExc_TypeError,
981 "OSType arg must be string of 4 chars");
982 return 0;
983 }
984 memcpy((char *)pr, PyString_AsString(v), 4);
985 return 1;
986}
987
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000988/* Convert an OSType value to a 4-char string object */
989PyObject *
990PyMac_BuildOSType(OSType t)
991{
992 return PyString_FromStringAndSize((char *)&t, 4);
993}
994
Jack Jansend1f06311996-08-01 15:23:54 +0000995/* Convert an NumVersion value to a 4-element tuple */
996PyObject *
997PyMac_BuildNumVersion(NumVersion t)
998{
999 return Py_BuildValue("(hhhh)", t.majorRev, t.minorAndBugRev, t.stage, t.nonRelRev);
1000}
1001
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001002
1003/* Convert a Python string object to a Str255 */
Jack Jansen5f653091995-01-18 13:53:49 +00001004int
Guido van Rossum8f691791995-01-18 23:57:26 +00001005PyMac_GetStr255(PyObject *v, Str255 pbuf)
Jack Jansen5f653091995-01-18 13:53:49 +00001006{
1007 int len;
1008 if (!PyString_Check(v) || (len = PyString_Size(v)) > 255) {
1009 PyErr_SetString(PyExc_TypeError,
1010 "Str255 arg must be string of at most 255 chars");
1011 return 0;
1012 }
1013 pbuf[0] = len;
1014 memcpy((char *)(pbuf+1), PyString_AsString(v), len);
1015 return 1;
1016}
1017
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001018/* Convert a Str255 to a Python string object */
1019PyObject *
1020PyMac_BuildStr255(Str255 s)
1021{
1022 return PyString_FromStringAndSize((char *)&s[1], (int)s[0]);
1023}
1024
1025
Jack Jansen5f653091995-01-18 13:53:49 +00001026/*
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001027** Convert a Python object to an FSSpec.
1028** The object may either be a full pathname or a triple
1029** (vrefnum, dirid, path).
Jack Jansen5f653091995-01-18 13:53:49 +00001030** NOTE: This routine will fail on pre-sys7 machines.
1031** The caller is responsible for not calling this routine
1032** in those cases (which is fine, since everyone calling
1033** this is probably sys7 dependent anyway).
1034*/
1035int
Guido van Rossum8f691791995-01-18 23:57:26 +00001036PyMac_GetFSSpec(PyObject *v, FSSpec *fs)
Jack Jansen5f653091995-01-18 13:53:49 +00001037{
1038 Str255 path;
1039 short refnum;
1040 long parid;
1041 OSErr err;
Jack Jansene8e8ae01995-01-26 16:36:45 +00001042 FSSpec *fs2;
Jack Jansen5f653091995-01-18 13:53:49 +00001043
Jack Jansene8e8ae01995-01-26 16:36:45 +00001044 /* first check whether it already is an FSSpec */
1045 fs2 = mfs_GetFSSpecFSSpec(v);
1046 if ( fs2 ) {
Jack Jansen3ec804a1995-02-20 15:56:10 +00001047 (void)FSMakeFSSpec(fs2->vRefNum, fs2->parID, fs2->name, fs);
Jack Jansene8e8ae01995-01-26 16:36:45 +00001048 return 1;
1049 }
Jack Jansen5f653091995-01-18 13:53:49 +00001050 if ( PyString_Check(v) ) {
1051 /* It's a pathname */
Guido van Rossum9aa3d131995-01-21 13:46:04 +00001052 if( !PyArg_Parse(v, "O&", PyMac_GetStr255, &path) )
Jack Jansen5f653091995-01-18 13:53:49 +00001053 return 0;
Jack Jansen378815c1996-03-06 16:21:34 +00001054 refnum = 0; /* XXXX Should get CurWD here?? */
Jack Jansen5f653091995-01-18 13:53:49 +00001055 parid = 0;
1056 } else {
Guido van Rossum9aa3d131995-01-21 13:46:04 +00001057 if( !PyArg_Parse(v, "(hlO&); FSSpec should be fullpath or (vrefnum,dirid,path)",
1058 &refnum, &parid, PyMac_GetStr255, &path)) {
Jack Jansen5f653091995-01-18 13:53:49 +00001059 return 0;
Guido van Rossum9aa3d131995-01-21 13:46:04 +00001060 }
Jack Jansen5f653091995-01-18 13:53:49 +00001061 }
1062 err = FSMakeFSSpec(refnum, parid, path, fs);
1063 if ( err && err != fnfErr ) {
Guido van Rossum9aa3d131995-01-21 13:46:04 +00001064 PyErr_Mac(PyExc_ValueError, err);
Jack Jansen5f653091995-01-18 13:53:49 +00001065 return 0;
1066 }
1067 return 1;
1068}
1069
Guido van Rossum8f691791995-01-18 23:57:26 +00001070
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001071/* Convert a Python object to a Rect.
Guido van Rossum5279ec61995-01-26 22:56:59 +00001072 The object must be a (left, top, right, bottom) tuple.
1073 (This differs from the order in the struct but is consistent with
1074 the arguments to SetRect(), and also with STDWIN). */
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001075int
1076PyMac_GetRect(PyObject *v, Rect *r)
Guido van Rossum8f691791995-01-18 23:57:26 +00001077{
Guido van Rossum5279ec61995-01-26 22:56:59 +00001078 return PyArg_Parse(v, "(hhhh)", &r->left, &r->top, &r->right, &r->bottom);
Guido van Rossum8f691791995-01-18 23:57:26 +00001079}
Guido van Rossumb3404661995-01-22 18:36:13 +00001080
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001081/* Convert a Rect to a Python object */
Guido van Rossumb3404661995-01-22 18:36:13 +00001082PyObject *
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001083PyMac_BuildRect(Rect *r)
Guido van Rossumb3404661995-01-22 18:36:13 +00001084{
Guido van Rossum5279ec61995-01-26 22:56:59 +00001085 return Py_BuildValue("(hhhh)", r->left, r->top, r->right, r->bottom);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001086}
1087
1088
1089/* Convert a Python object to a Point.
Guido van Rossum5279ec61995-01-26 22:56:59 +00001090 The object must be a (h, v) tuple.
1091 (This differs from the order in the struct but is consistent with
1092 the arguments to SetPoint(), and also with STDWIN). */
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001093int
1094PyMac_GetPoint(PyObject *v, Point *p)
1095{
Guido van Rossum5279ec61995-01-26 22:56:59 +00001096 return PyArg_Parse(v, "(hh)", &p->h, &p->v);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001097}
1098
1099/* Convert a Point to a Python object */
1100PyObject *
1101PyMac_BuildPoint(Point p)
1102{
Guido van Rossum5279ec61995-01-26 22:56:59 +00001103 return Py_BuildValue("(hh)", p.h, p.v);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001104}
1105
1106
1107/* Convert a Python object to an EventRecord.
1108 The object must be a (what, message, when, (v, h), modifiers) tuple. */
1109int
1110PyMac_GetEventRecord(PyObject *v, EventRecord *e)
1111{
1112 return PyArg_Parse(v, "(hll(hh)h)",
1113 &e->what,
1114 &e->message,
1115 &e->when,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001116 &e->where.h,
Guido van Rossum5279ec61995-01-26 22:56:59 +00001117 &e->where.v,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001118 &e->modifiers);
1119}
1120
1121/* Convert a Rect to an EventRecord object */
1122PyObject *
1123PyMac_BuildEventRecord(EventRecord *e)
1124{
1125 return Py_BuildValue("(hll(hh)h)",
1126 e->what,
1127 e->message,
1128 e->when,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001129 e->where.h,
Guido van Rossum5279ec61995-01-26 22:56:59 +00001130 e->where.v,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001131 e->modifiers);
Guido van Rossumb3404661995-01-22 18:36:13 +00001132}
Jack Jansenfa4d5d01995-11-15 15:19:29 +00001133
1134/* Convert Python object to Fixed */
1135int
1136PyMac_GetFixed(PyObject *v, Fixed *f)
1137{
1138 double d;
1139
1140 if( !PyArg_Parse(v, "d", &d))
1141 return 0;
1142 *f = (Fixed)(d * 0x10000);
Jack Jansen31dd5c01996-05-31 13:01:39 +00001143 return 1;
Jack Jansenfa4d5d01995-11-15 15:19:29 +00001144}
1145
1146/* Convert a Point to a Python object */
1147PyObject *
1148PyMac_BuildFixed(Fixed f)
1149{
1150 double d;
1151
1152 d = f;
1153 d = d / 0x10000;
1154 return Py_BuildValue("d", d);
1155}
1156