blob: 50b89e253130bb24f42e11d7b893dc923a5dd6a0 [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
865 strcpy(buf+*lenp, module);
866 strcpy(buf+*lenp+modnamelen, _PyImport_Filetab[0].suffix);
867 if ( FSMakeFSSpec(0, 0, Pstring(buf), &fss) == noErr )
868 return _PyImport_Filetab;
869 /*
870 ** We cannot check for fnfErr (unfortunately), it can mean either that
871 ** the file doesn't exist (fine, we try others) or the path leading to it.
872 */
873 refnum = fss.vRefNum;
874 dirid = fss.parID;
875 if ( refnum == 0 || dirid == 0 ) /* Fail on nonexistent dir */
876 return 0;
877 /*
878 ** We now have the folder parameters. Setup the field for the filename
879 */
880 if ( modnamelen > 54 ) return 0; /* Leave room for extension */
881 strcpy((char *)fnbuf+1, module);
882
883 for( fdp = _PyImport_Filetab+1; fdp->suffix; fdp++ ) {
884 strcpy((char *)fnbuf+1+modnamelen, fdp->suffix);
885 fnbuf[0] = strlen((char *)fnbuf+1);
886 if (Py_VerboseFlag > 1)
887 fprintf(stderr, "# trying %s%s\n", buf, fdp->suffix);
888 if ( FSMakeFSSpec(refnum, dirid, fnbuf, &fss) == noErr ) {
889 /* Found it. */
890 strcpy(buf+*lenp+modnamelen, fdp->suffix);
891 *lenp = strlen(buf);
892 return fdp;
893 }
894 }
895 return 0;
896}
897
898#if 0
899int
900PyMac_FileExists(char *name)
901{
902 FSSpec fss;
903
904 if ( FSMakeFSSpec(0, 0, Pstring(name), &fss) == noErr )
905 return 1;
906 return 0;
907}
908#endif
909
910/*
Jack Jansen3ec804a1995-02-20 15:56:10 +0000911** Helper routine for GetDirectory
912*/
Guido van Rossum24a45e31995-02-20 23:45:53 +0000913static pascal short
Jack Jansen819f1771995-08-14 12:35:10 +0000914myhook_proc(short item, DialogPtr theDialog, struct hook_args *dataptr)
Jack Jansen3ec804a1995-02-20 15:56:10 +0000915{
Jack Jansen819f1771995-08-14 12:35:10 +0000916 if ( item == sfHookFirstCall && dataptr->prompt) {
917 Handle prompth;
918 short type;
919 Rect rect;
920
921 GetDialogItem(theDialog, PROMPT_ITEM, &type, &prompth, &rect);
922 if ( prompth )
923 SetDialogItemText(prompth, (unsigned char *)dataptr->prompt);
924 } else
Jack Jansen3ec804a1995-02-20 15:56:10 +0000925 if ( item == SELECTCUR_ITEM ) {
926 item = sfItemCancelButton;
Jack Jansen819f1771995-08-14 12:35:10 +0000927 dataptr->selectcur_hit = 1;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000928 }
929 return item;
930}
931
932/*
933** Ask the user for a directory. I still can't understand
934** why Apple doesn't provide a standard solution for this...
935*/
936int
Jack Jansen819f1771995-08-14 12:35:10 +0000937PyMac_GetDirectory(dirfss, prompt)
Jack Jansen3ec804a1995-02-20 15:56:10 +0000938 FSSpec *dirfss;
Jack Jansen819f1771995-08-14 12:35:10 +0000939 char *prompt;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000940{
941 static SFTypeList list = {'fldr', 0, 0, 0};
942 static Point where = {-1, -1};
Jack Jansen3ec804a1995-02-20 15:56:10 +0000943 StandardFileReply reply;
Jack Jansen819f1771995-08-14 12:35:10 +0000944 struct hook_args hook_args;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000945
946 if ( !upp_inited ) {
947 myhook_upp = NewDlgHookYDProc(myhook_proc);
948 upp_inited = 1;
949 }
Jack Jansen819f1771995-08-14 12:35:10 +0000950 if ( prompt && *prompt )
951 hook_args.prompt = (char *)Pstring(prompt);
952 else
953 hook_args.prompt = NULL;
954 hook_args.selectcur_hit = 0;
Guido van Rossum24a45e31995-02-20 23:45:53 +0000955 CustomGetFile((FileFilterYDUPP)0, 1, list, &reply, GETDIR_ID, where, myhook_upp,
Jack Jansen819f1771995-08-14 12:35:10 +0000956 NULL, NULL, NULL, (void *)&hook_args);
Jack Jansen3ec804a1995-02-20 15:56:10 +0000957
958 reply.sfFile.name[0] = 0;
959 if( FSMakeFSSpec(reply.sfFile.vRefNum, reply.sfFile.parID, reply.sfFile.name, dirfss) )
960 return 0;
Jack Jansen819f1771995-08-14 12:35:10 +0000961 return hook_args.selectcur_hit;
962}
963
964/*
965** Slightly extended StandardGetFile: accepts a prompt */
966void PyMac_PromptGetFile(short numTypes, ConstSFTypeListPtr typeList,
967 StandardFileReply *reply, char *prompt)
968{
969 static Point where = {-1, -1};
970 struct hook_args hook_args;
971
972 if ( !upp_inited ) {
973 myhook_upp = NewDlgHookYDProc(myhook_proc);
974 upp_inited = 1;
975 }
976 if ( prompt && *prompt )
977 hook_args.prompt = (char *)Pstring(prompt);
978 else
979 hook_args.prompt = NULL;
980 hook_args.selectcur_hit = 0;
981 CustomGetFile((FileFilterYDUPP)0, numTypes, typeList, reply, GETFILEPROMPT_ID, where,
982 myhook_upp, NULL, NULL, NULL, (void *)&hook_args);
Jack Jansen3ec804a1995-02-20 15:56:10 +0000983}
Jack Jansen5f653091995-01-18 13:53:49 +0000984
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000985/* Convert a 4-char string object argument to an OSType value */
Jack Jansen5f653091995-01-18 13:53:49 +0000986int
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000987PyMac_GetOSType(PyObject *v, OSType *pr)
Jack Jansen5f653091995-01-18 13:53:49 +0000988{
989 if (!PyString_Check(v) || PyString_Size(v) != 4) {
990 PyErr_SetString(PyExc_TypeError,
991 "OSType arg must be string of 4 chars");
992 return 0;
993 }
994 memcpy((char *)pr, PyString_AsString(v), 4);
995 return 1;
996}
997
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000998/* Convert an OSType value to a 4-char string object */
999PyObject *
1000PyMac_BuildOSType(OSType t)
1001{
1002 return PyString_FromStringAndSize((char *)&t, 4);
1003}
1004
Jack Jansend1f06311996-08-01 15:23:54 +00001005/* Convert an NumVersion value to a 4-element tuple */
1006PyObject *
1007PyMac_BuildNumVersion(NumVersion t)
1008{
1009 return Py_BuildValue("(hhhh)", t.majorRev, t.minorAndBugRev, t.stage, t.nonRelRev);
1010}
1011
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001012
1013/* Convert a Python string object to a Str255 */
Jack Jansen5f653091995-01-18 13:53:49 +00001014int
Guido van Rossum8f691791995-01-18 23:57:26 +00001015PyMac_GetStr255(PyObject *v, Str255 pbuf)
Jack Jansen5f653091995-01-18 13:53:49 +00001016{
1017 int len;
1018 if (!PyString_Check(v) || (len = PyString_Size(v)) > 255) {
1019 PyErr_SetString(PyExc_TypeError,
1020 "Str255 arg must be string of at most 255 chars");
1021 return 0;
1022 }
1023 pbuf[0] = len;
1024 memcpy((char *)(pbuf+1), PyString_AsString(v), len);
1025 return 1;
1026}
1027
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001028/* Convert a Str255 to a Python string object */
1029PyObject *
1030PyMac_BuildStr255(Str255 s)
1031{
1032 return PyString_FromStringAndSize((char *)&s[1], (int)s[0]);
1033}
1034
1035
Jack Jansen5f653091995-01-18 13:53:49 +00001036/*
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001037** Convert a Python object to an FSSpec.
1038** The object may either be a full pathname or a triple
1039** (vrefnum, dirid, path).
Jack Jansen5f653091995-01-18 13:53:49 +00001040** NOTE: This routine will fail on pre-sys7 machines.
1041** The caller is responsible for not calling this routine
1042** in those cases (which is fine, since everyone calling
1043** this is probably sys7 dependent anyway).
1044*/
1045int
Guido van Rossum8f691791995-01-18 23:57:26 +00001046PyMac_GetFSSpec(PyObject *v, FSSpec *fs)
Jack Jansen5f653091995-01-18 13:53:49 +00001047{
1048 Str255 path;
1049 short refnum;
1050 long parid;
1051 OSErr err;
Jack Jansene8e8ae01995-01-26 16:36:45 +00001052 FSSpec *fs2;
Jack Jansen5f653091995-01-18 13:53:49 +00001053
Jack Jansene8e8ae01995-01-26 16:36:45 +00001054 /* first check whether it already is an FSSpec */
1055 fs2 = mfs_GetFSSpecFSSpec(v);
1056 if ( fs2 ) {
Jack Jansen3ec804a1995-02-20 15:56:10 +00001057 (void)FSMakeFSSpec(fs2->vRefNum, fs2->parID, fs2->name, fs);
Jack Jansene8e8ae01995-01-26 16:36:45 +00001058 return 1;
1059 }
Jack Jansen5f653091995-01-18 13:53:49 +00001060 if ( PyString_Check(v) ) {
1061 /* It's a pathname */
Guido van Rossum9aa3d131995-01-21 13:46:04 +00001062 if( !PyArg_Parse(v, "O&", PyMac_GetStr255, &path) )
Jack Jansen5f653091995-01-18 13:53:49 +00001063 return 0;
Jack Jansen378815c1996-03-06 16:21:34 +00001064 refnum = 0; /* XXXX Should get CurWD here?? */
Jack Jansen5f653091995-01-18 13:53:49 +00001065 parid = 0;
1066 } else {
Guido van Rossum9aa3d131995-01-21 13:46:04 +00001067 if( !PyArg_Parse(v, "(hlO&); FSSpec should be fullpath or (vrefnum,dirid,path)",
1068 &refnum, &parid, PyMac_GetStr255, &path)) {
Jack Jansen5f653091995-01-18 13:53:49 +00001069 return 0;
Guido van Rossum9aa3d131995-01-21 13:46:04 +00001070 }
Jack Jansen5f653091995-01-18 13:53:49 +00001071 }
1072 err = FSMakeFSSpec(refnum, parid, path, fs);
1073 if ( err && err != fnfErr ) {
Guido van Rossum9aa3d131995-01-21 13:46:04 +00001074 PyErr_Mac(PyExc_ValueError, err);
Jack Jansen5f653091995-01-18 13:53:49 +00001075 return 0;
1076 }
1077 return 1;
1078}
1079
Guido van Rossum8f691791995-01-18 23:57:26 +00001080
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001081/* Convert a Python object to a Rect.
Guido van Rossum5279ec61995-01-26 22:56:59 +00001082 The object must be a (left, top, right, bottom) tuple.
1083 (This differs from the order in the struct but is consistent with
1084 the arguments to SetRect(), and also with STDWIN). */
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001085int
1086PyMac_GetRect(PyObject *v, Rect *r)
Guido van Rossum8f691791995-01-18 23:57:26 +00001087{
Guido van Rossum5279ec61995-01-26 22:56:59 +00001088 return PyArg_Parse(v, "(hhhh)", &r->left, &r->top, &r->right, &r->bottom);
Guido van Rossum8f691791995-01-18 23:57:26 +00001089}
Guido van Rossumb3404661995-01-22 18:36:13 +00001090
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001091/* Convert a Rect to a Python object */
Guido van Rossumb3404661995-01-22 18:36:13 +00001092PyObject *
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001093PyMac_BuildRect(Rect *r)
Guido van Rossumb3404661995-01-22 18:36:13 +00001094{
Guido van Rossum5279ec61995-01-26 22:56:59 +00001095 return Py_BuildValue("(hhhh)", r->left, r->top, r->right, r->bottom);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001096}
1097
1098
1099/* Convert a Python object to a Point.
Guido van Rossum5279ec61995-01-26 22:56:59 +00001100 The object must be a (h, v) tuple.
1101 (This differs from the order in the struct but is consistent with
1102 the arguments to SetPoint(), and also with STDWIN). */
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001103int
1104PyMac_GetPoint(PyObject *v, Point *p)
1105{
Guido van Rossum5279ec61995-01-26 22:56:59 +00001106 return PyArg_Parse(v, "(hh)", &p->h, &p->v);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001107}
1108
1109/* Convert a Point to a Python object */
1110PyObject *
1111PyMac_BuildPoint(Point p)
1112{
Guido van Rossum5279ec61995-01-26 22:56:59 +00001113 return Py_BuildValue("(hh)", p.h, p.v);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001114}
1115
1116
1117/* Convert a Python object to an EventRecord.
1118 The object must be a (what, message, when, (v, h), modifiers) tuple. */
1119int
1120PyMac_GetEventRecord(PyObject *v, EventRecord *e)
1121{
1122 return PyArg_Parse(v, "(hll(hh)h)",
1123 &e->what,
1124 &e->message,
1125 &e->when,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001126 &e->where.h,
Guido van Rossum5279ec61995-01-26 22:56:59 +00001127 &e->where.v,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001128 &e->modifiers);
1129}
1130
1131/* Convert a Rect to an EventRecord object */
1132PyObject *
1133PyMac_BuildEventRecord(EventRecord *e)
1134{
1135 return Py_BuildValue("(hll(hh)h)",
1136 e->what,
1137 e->message,
1138 e->when,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001139 e->where.h,
Guido van Rossum5279ec61995-01-26 22:56:59 +00001140 e->where.v,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +00001141 e->modifiers);
Guido van Rossumb3404661995-01-22 18:36:13 +00001142}
Jack Jansenfa4d5d01995-11-15 15:19:29 +00001143
1144/* Convert Python object to Fixed */
1145int
1146PyMac_GetFixed(PyObject *v, Fixed *f)
1147{
1148 double d;
1149
1150 if( !PyArg_Parse(v, "d", &d))
1151 return 0;
1152 *f = (Fixed)(d * 0x10000);
Jack Jansen31dd5c01996-05-31 13:01:39 +00001153 return 1;
Jack Jansenfa4d5d01995-11-15 15:19:29 +00001154}
1155
1156/* Convert a Point to a Python object */
1157PyObject *
1158PyMac_BuildFixed(Fixed f)
1159{
1160 double d;
1161
1162 d = f;
1163 d = d / 0x10000;
1164 return Py_BuildValue("d", d);
1165}
1166