blob: 3385d270b06e223f9b1e4368244c9e010d8f92c4 [file] [log] [blame]
Guido van Rossumb3404661995-01-22 18:36:13 +00001/***********************************************************
2Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3The 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
25#include "Python.h"
Guido van Rossumbecdbec1995-02-14 01:27:24 +000026
Jack Jansenf93c72a1994-12-14 14:07:50 +000027#include "macglue.h"
Jack Jansen74162f31995-02-15 22:58:33 +000028#include "marshal.h"
29#include "import.h"
Jack Jansenf93c72a1994-12-14 14:07:50 +000030
Jack Jansen819f1771995-08-14 12:35:10 +000031#include "pythonresources.h"
32
Jack Jansenf93c72a1994-12-14 14:07:50 +000033#include <OSUtils.h> /* for Set(Current)A5 */
Jack Jansene8e8ae01995-01-26 16:36:45 +000034#include <Files.h>
Jack Jansen8cd2b721995-02-13 11:33:28 +000035#include <StandardFile.h>
Jack Jansenf93c72a1994-12-14 14:07:50 +000036#include <Resources.h>
37#include <Memory.h>
38#include <Events.h>
39#include <Windows.h>
40#include <Desk.h>
Jack Jansene8e8ae01995-01-26 16:36:45 +000041#include <Traps.h>
Jack Jansenee23d6e1995-01-27 14:43:25 +000042#include <Processes.h>
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +000043#include <Fonts.h>
44#include <Menus.h>
Jack Jansen08305501995-06-18 20:03:40 +000045#include <TextUtils.h>
Guido van Rossumcc0d8791995-01-30 08:57:13 +000046#ifdef THINK_C
47#include <OSEvents.h> /* For EvQElPtr */
48#endif
Jack Jansen16df2aa1995-02-27 16:17:28 +000049#ifdef __MWERKS__
50#include <SIOUX.h>
51#endif
Jack Jansen911ad6b1996-03-05 16:56:24 +000052#ifdef USE_GUSI
53#include <TFileSpec.h> /* For Path2FSSpec */
Jack Jansen378815c1996-03-06 16:21:34 +000054#include <LowMem.h> /* For SetSFCurDir, etc */
Jack Jansen911ad6b1996-03-05 16:56:24 +000055#endif
Jack Jansenee23d6e1995-01-27 14:43:25 +000056
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +000057#ifndef HAVE_UNIVERSAL_HEADERS
58#define GetResourceSizeOnDisk(x) SizeResource(x)
Guido van Rossum24a45e31995-02-20 23:45:53 +000059typedef DlgHookYDProcPtr DlgHookYDUPP;
60#define NewDlgHookYDProc(userRoutine) ((DlgHookYDUPP) (userRoutine))
61typedef FileFilterYDProcPtr FileFilterYDUPP;
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +000062#endif
63
Jack Jansenee23d6e1995-01-27 14:43:25 +000064#include <signal.h>
Jack Jansen74162f31995-02-15 22:58:33 +000065#include <stdio.h>
Jack Jansene8e8ae01995-01-26 16:36:45 +000066
Jack Jansenee23d6e1995-01-27 14:43:25 +000067/*
Jack Jansen16df2aa1995-02-27 16:17:28 +000068** We have to be careful, since we can't handle
Jack Jansenee23d6e1995-01-27 14:43:25 +000069** things like updates (and they'll keep coming back if we don't
Jack Jansen16df2aa1995-02-27 16:17:28 +000070** handle them). Note that we don't know who has windows open, so
71** even handing updates off to SIOUX under MW isn't going to work.
Jack Jansenee23d6e1995-01-27 14:43:25 +000072*/
73#define MAINLOOP_EVENTMASK (mDownMask|keyDownMask|osMask)
Jack Jansene8e8ae01995-01-26 16:36:45 +000074
75#include <signal.h>
Jack Jansenf93c72a1994-12-14 14:07:50 +000076
Guido van Rossumb3404661995-01-22 18:36:13 +000077/* XXX We should include Errors.h here, but it has a name conflict
Jack Jansen5f653091995-01-18 13:53:49 +000078** with the python errors.h. */
79#define fnfErr -43
80
Jack Jansene8e8ae01995-01-26 16:36:45 +000081/* Declared in macfsmodule.c: */
82extern FSSpec *mfs_GetFSSpecFSSpec();
83
Jack Jansenee23d6e1995-01-27 14:43:25 +000084/* Interrupt code variables: */
85static int interrupted; /* Set to true when cmd-. seen */
86static RETSIGTYPE intcatcher Py_PROTO((int));
87
Jack Jansene8e8ae01995-01-26 16:36:45 +000088/*
89** We attempt to be a good citizen by giving up the CPU periodically.
90** When in the foreground we do this less often and for shorter periods
91** than when in the background. At this time we also check for events and
Jack Jansenee23d6e1995-01-27 14:43:25 +000092** pass them off to SIOUX, if compiling with mwerks.
Jack Jansene8e8ae01995-01-26 16:36:45 +000093** The counts here are in ticks of 1/60th second.
94** XXXX The initial values here are not based on anything.
95** FG-python gives up the cpu for 1/60th 5 times per second,
96** BG-python for .2 second 10 times per second.
97*/
98static long interval_fg = 12;
99static long interval_bg = 6;
100static long yield_fg = 1;
101static long yield_bg = 12;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000102static long lastyield;
103static int in_foreground;
104
Guido van Rossume7134aa1995-02-26 10:20:53 +0000105/*
106** When > 0, do full scanning for events (program is not event aware)
107** when == 0, only scan for Command-period
108** when < 0, don't do any event scanning
109*/
110int PyMac_DoYieldEnabled = 1;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000111
Jack Jansen819f1771995-08-14 12:35:10 +0000112/*
113** Some stuff for our GetDirectory and PromptGetFile routines
114*/
115struct hook_args {
116 int selectcur_hit; /* Set to true when "select current" selected */
117 char *prompt; /* The prompt */
118};
119static DlgHookYDUPP myhook_upp;
120static int upp_inited = 0;
121
Jack Jansen378815c1996-03-06 16:21:34 +0000122#ifdef USE_GUSI
123/*
124** GUSI (1.6.0 and earlier, at the least) do not set the MacOS idea of
125** the working directory. Hence, we call this routine after each call
126** to chdir() to rectify things.
127*/
128void
129PyMac_FixGUSIcd()
130{
131 WDPBRec pb;
132 FSSpec curdirfss;
133
134 if ( Path2FSSpec(":x", &curdirfss) != noErr )
135 return;
136
137 /* Set MacOS "working directory" */
138 pb.ioNamePtr= "\p";
139 pb.ioVRefNum= curdirfss.vRefNum;
140 pb.ioWDDirID= curdirfss.parID;
141 if (PBHSetVol(&pb, 0) != noErr)
142 return;
143
Jack Jansen975aa221996-03-25 15:46:25 +0000144#if 0
Jack Jansen378815c1996-03-06 16:21:34 +0000145 /* Set standard-file working directory */
146 LMSetSFSaveDisk(-curdirfss.vRefNum);
147 LMSetCurDirStore(curdirfss.parID);
Jack Jansen975aa221996-03-25 15:46:25 +0000148#endif
Jack Jansen378815c1996-03-06 16:21:34 +0000149}
150#endif
151
Jack Jansen819f1771995-08-14 12:35:10 +0000152
Jack Jansen5f653091995-01-18 13:53:49 +0000153/* Convert C to Pascal string. Returns pointer to static buffer. */
154unsigned char *
155Pstring(char *str)
156{
157 static Str255 buf;
158 int len;
159
160 len = strlen(str);
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000161 if (len > 255)
162 len = 255;
Jack Jansen5f653091995-01-18 13:53:49 +0000163 buf[0] = (unsigned char)len;
164 strncpy((char *)buf+1, str, len);
165 return buf;
166}
167
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000168/* Like strerror() but for Mac OS error numbers */
169char *PyMac_StrError(int err)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000170{
171 static char buf[256];
172 Handle h;
173 char *str;
174
175 h = GetResource('Estr', err);
176 if ( h ) {
177 HLock(h);
178 str = (char *)*h;
179 memcpy(buf, str+1, (unsigned char)str[0]);
Guido van Rossumcc9bc8f1995-02-13 16:17:03 +0000180 buf[(unsigned char)str[0]] = '\0';
Jack Jansenf93c72a1994-12-14 14:07:50 +0000181 HUnlock(h);
182 ReleaseResource(h);
183 } else {
184 sprintf(buf, "Mac OS error code %d", err);
185 }
186 return buf;
187}
188
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000189/* Exception object shared by all Mac specific modules for Mac OS errors */
190PyObject *PyMac_OSErrException;
191
192/* Initialize and return PyMac_OSErrException */
193PyObject *
194PyMac_GetOSErrException()
195{
196 if (PyMac_OSErrException == NULL)
197 PyMac_OSErrException = PyString_FromString("Mac OS Error");
198 return PyMac_OSErrException;
199}
200
Jack Jansenf93c72a1994-12-14 14:07:50 +0000201/* Set a MAC-specific error from errno, and return NULL; return None if no error */
202PyObject *
Guido van Rossumfffb8bb1995-01-12 12:37:24 +0000203PyErr_Mac(PyObject *eobj, int err)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000204{
205 char *msg;
206 PyObject *v;
Jack Jansenf93c72a1994-12-14 14:07:50 +0000207
Guido van Rossum8f691791995-01-18 23:57:26 +0000208 if (err == 0 && !PyErr_Occurred()) {
Jack Jansenf93c72a1994-12-14 14:07:50 +0000209 Py_INCREF(Py_None);
210 return Py_None;
211 }
Guido van Rossum8f691791995-01-18 23:57:26 +0000212 if (err == -1 && PyErr_Occurred())
213 return NULL;
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000214 msg = PyMac_StrError(err);
Jack Jansenf93c72a1994-12-14 14:07:50 +0000215 v = Py_BuildValue("(is)", err, msg);
216 PyErr_SetObject(eobj, v);
217 Py_DECREF(v);
218 return NULL;
219}
220
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000221/* Call PyErr_Mac with PyMac_OSErrException */
222PyObject *
223PyMac_Error(OSErr err)
224{
225 return PyErr_Mac(PyMac_GetOSErrException(), err);
226}
227
Jack Jansenee23d6e1995-01-27 14:43:25 +0000228/* The catcher routine (which may not be used for all compilers) */
229static RETSIGTYPE
230intcatcher(sig)
231 int sig;
232{
233 interrupted = 1;
234 signal(SIGINT, intcatcher);
235}
236
237void
238PyOS_InitInterrupts()
239{
240 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
241 signal(SIGINT, intcatcher);
242}
243
244/*
245** This routine scans the event queue looking for cmd-.
246** This is the only way to get an interrupt under THINK (since it
247** doesn't do SIGINT handling), but is also used under MW, when
248** the full-fledged event loop is disabled. This way, we can at least
249** interrupt a runaway python program.
250*/
251static void
252scan_event_queue(flush)
253 int flush;
254{
Jack Jansenf74f63a1995-06-27 13:18:14 +0000255#if defined(__MWERKS__) && defined(__CFM68K__)
256 return; /* No GetEvQHdr yet */
257#else
Jack Jansenee23d6e1995-01-27 14:43:25 +0000258 register EvQElPtr q;
259
260 q = (EvQElPtr) GetEvQHdr()->qHead;
261
262 for (; q; q = (EvQElPtr)q->qLink) {
263 if (q->evtQWhat == keyDown &&
264 (char)q->evtQMessage == '.' &&
265 (q->evtQModifiers & cmdKey) != 0) {
266 if ( flush )
267 FlushEvents(keyDownMask, 0);
268 interrupted = 1;
269 break;
270 }
271 }
Jack Jansenf74f63a1995-06-27 13:18:14 +0000272#endif
Jack Jansenee23d6e1995-01-27 14:43:25 +0000273}
274
275int
276PyOS_InterruptOccurred()
277{
Guido van Rossume7134aa1995-02-26 10:20:53 +0000278 if (PyMac_DoYieldEnabled < 0)
279 return 0;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000280#ifdef THINK_C
281 scan_event_queue(1);
282#endif
283 PyMac_Yield();
284 if (interrupted) {
285 interrupted = 0;
286 return 1;
287 }
288 return 0;
289}
290
291/* intrpeek() is like intrcheck(), but it doesn't flush the events. The
292** idea is that you call intrpeek() somewhere in a busy-wait loop, and return
293** None as soon as it returns 1. The mainloop will then pick up the cmd-. soon
294** thereafter.
295*/
296static int
297intrpeek()
298{
299#ifdef THINK_C
300 scan_event_queue(0);
301#endif
302 return interrupted;
303}
304
305/* Check whether we are in the foreground */
306int
307PyMac_InForeground()
308{
309 static ProcessSerialNumber ours;
310 static inited;
311 ProcessSerialNumber curfg;
312 Boolean eq;
313
314 if ( inited == 0 )
315 (void)GetCurrentProcess(&ours);
316 inited = 1;
317 if ( GetFrontProcess(&curfg) < 0 )
318 eq = 1;
319 else if ( SameProcess(&ours, &curfg, &eq) < 0 )
320 eq = 1;
321 return (int)eq;
322
323}
324
Jack Jansenf93c72a1994-12-14 14:07:50 +0000325/*
Jack Jansene8e8ae01995-01-26 16:36:45 +0000326** Set yield timeouts
Jack Jansenf93c72a1994-12-14 14:07:50 +0000327*/
Jack Jansene8e8ae01995-01-26 16:36:45 +0000328void
329PyMac_SetYield(long fgi, long fgy, long bgi, long bgy)
330{
331 interval_fg = fgi;
332 yield_fg = fgy;
333 interval_bg = bgi;
334 yield_bg = bgy;
335}
336
337/*
Jack Jansena76382a1995-02-02 14:25:56 +0000338** Handle an event, either one found in the mainloop eventhandler or
339** one passed back from the python program.
340*/
341void
342PyMac_HandleEvent(evp)
343 EventRecord *evp;
344{
Jack Jansena76382a1995-02-02 14:25:56 +0000345
346#ifdef __MWERKS__
Jack Jansen38e97661995-11-10 14:53:00 +0000347 {
348 int siouxdidit;
349
350 /* If SIOUX wants it we're done */
351 siouxdidit = SIOUXHandleOneEvent(evp);
352 if ( siouxdidit )
353 return;
354 }
Jack Jansena76382a1995-02-02 14:25:56 +0000355#else
356 /* Other compilers are just unlucky: we only weed out clicks in other applications */
357 if ( evp->what == mouseDown ) {
Jack Jansen847e89e1995-08-31 13:57:40 +0000358 WindowPtr wp;
359
Jack Jansen38e97661995-11-10 14:53:00 +0000360 if ( FindWindow(evp->where, &wp) == inSysWindow ) {
Jack Jansena76382a1995-02-02 14:25:56 +0000361 SystemClick(evp, wp);
Jack Jansen38e97661995-11-10 14:53:00 +0000362 return;
363 }
Jack Jansena76382a1995-02-02 14:25:56 +0000364 }
365#endif /* !__MWERKS__ */
366}
367
368/*
Jack Jansene8e8ae01995-01-26 16:36:45 +0000369** Yield the CPU to other tasks.
370*/
371static
372PyMac_DoYield()
Jack Jansenf93c72a1994-12-14 14:07:50 +0000373{
374 EventRecord ev;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000375 long yield;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000376 static int no_waitnextevent = -1;
377 int gotone;
378
379 if ( no_waitnextevent < 0 ) {
380 no_waitnextevent = (NGetTrapAddress(_WaitNextEvent, ToolTrap) ==
381 NGetTrapAddress(_Unimplemented, ToolTrap));
382 }
Jack Jansenf93c72a1994-12-14 14:07:50 +0000383
Jack Jansenee23d6e1995-01-27 14:43:25 +0000384 if ( !PyMac_DoYieldEnabled ) {
385#ifndef THINK_C
386 /* Under think this has been done before in intrcheck() or intrpeek() */
387 scan_event_queue(0);
388#endif
Jack Jansene8e8ae01995-01-26 16:36:45 +0000389 return;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000390 }
Jack Jansene8e8ae01995-01-26 16:36:45 +0000391
Jack Jansenee23d6e1995-01-27 14:43:25 +0000392 in_foreground = PyMac_InForeground();
393 if ( in_foreground )
Jack Jansene8e8ae01995-01-26 16:36:45 +0000394 yield = yield_fg;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000395 else
396 yield = yield_bg;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000397 while ( 1 ) {
398 if ( no_waitnextevent ) {
399 SystemTask();
Jack Jansenee23d6e1995-01-27 14:43:25 +0000400 gotone = GetNextEvent(MAINLOOP_EVENTMASK, &ev);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000401 } else {
Jack Jansenee23d6e1995-01-27 14:43:25 +0000402 gotone = WaitNextEvent(MAINLOOP_EVENTMASK, &ev, yield, NULL);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000403 }
404 /* Get out quickly if nothing interesting is happening */
405 if ( !gotone || ev.what == nullEvent )
406 break;
Jack Jansena76382a1995-02-02 14:25:56 +0000407 PyMac_HandleEvent(&ev);
Jack Jansenf93c72a1994-12-14 14:07:50 +0000408 }
Jack Jansene8e8ae01995-01-26 16:36:45 +0000409 lastyield = TickCount();
410}
411
412/*
413** Yield the CPU to other tasks if opportune
414*/
415void
416PyMac_Yield() {
417 long iv;
418
Jack Jansenee23d6e1995-01-27 14:43:25 +0000419 if ( in_foreground )
Jack Jansene8e8ae01995-01-26 16:36:45 +0000420 iv = interval_fg;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000421 else
422 iv = interval_bg;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000423 if ( TickCount() > lastyield + iv )
424 PyMac_DoYield();
425}
426
427/*
428** Idle routine for busy-wait loops.
429** Gives up CPU, handles events and returns true if an interrupt is pending
430** (but not actually handled yet).
431*/
432int
433PyMac_Idle()
434{
435 PyMac_DoYield();
436 return intrpeek();
Jack Jansenf93c72a1994-12-14 14:07:50 +0000437}
Jack Jansen74162f31995-02-15 22:58:33 +0000438/*
439** Returns true if the argument has a resource fork, and it contains
440** a 'PYC ' resource of the correct name
441*/
442int
443PyMac_FindResourceModule(module, filename)
444char *module;
445char *filename;
446{
447 FSSpec fss;
448 FInfo finfo;
449 short oldrh, filerh;
450 int ok;
451 Handle h;
452
453 if ( FSMakeFSSpec(0, 0, Pstring(filename), &fss) != noErr )
454 return 0; /* It doesn't exist */
455 if ( FSpGetFInfo(&fss, &finfo) != noErr )
456 return 0; /* shouldn't happen, I guess */
Jack Jansen74162f31995-02-15 22:58:33 +0000457 oldrh = CurResFile();
458 filerh = FSpOpenResFile(&fss, fsRdPerm);
459 if ( filerh == -1 )
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000460 return 0;
Jack Jansen74162f31995-02-15 22:58:33 +0000461 UseResFile(filerh);
462 SetResLoad(0);
463 h = Get1NamedResource('PYC ', Pstring(module));
464 SetResLoad(1);
465 ok = (h != NULL);
466 CloseResFile(filerh);
467 UseResFile(oldrh);
468 return ok;
469}
470
471/*
472** Load the specified module from a resource
473*/
474PyObject *
475PyMac_LoadResourceModule(module, filename)
476char *module;
477char *filename;
478{
479 FSSpec fss;
480 FInfo finfo;
481 short oldrh, filerh;
Jack Jansen74162f31995-02-15 22:58:33 +0000482 Handle h;
483 OSErr err;
484 PyObject *m, *co;
485 long num, size;
486
487 if ( (err=FSMakeFSSpec(0, 0, Pstring(filename), &fss)) != noErr )
488 goto error;
489 if ( (err=FSpGetFInfo(&fss, &finfo)) != noErr )
490 goto error;
Jack Jansen74162f31995-02-15 22:58:33 +0000491 oldrh = CurResFile();
492 filerh = FSpOpenResFile(&fss, fsRdPerm);
493 if ( filerh == -1 ) {
494 err = ResError();
495 goto error;
496 }
497 UseResFile(filerh);
498 h = Get1NamedResource('PYC ', Pstring(module));
499 if ( h == NULL ) {
500 err = ResError();
501 goto error;
502 }
503 HLock(h);
504 /*
505 ** XXXX The next few lines are intimately tied to the format of pyc
506 ** files. I'm not sure whether this code should be here or in import.c -- Jack
507 */
508 size = GetHandleSize(h);
509 if ( size < 8 ) {
510 PyErr_SetString(PyExc_ImportError, "Resource too small");
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000511 co = NULL;
Jack Jansen74162f31995-02-15 22:58:33 +0000512 } else {
513 num = (*h)[0] & 0xff;
514 num = num | (((*h)[1] & 0xff) << 8);
515 num = num | (((*h)[2] & 0xff) << 16);
516 num = num | (((*h)[3] & 0xff) << 24);
517 if ( num != PyImport_GetMagicNumber() ) {
518 PyErr_SetString(PyExc_ImportError, "Bad MAGIC in resource");
519 co = NULL;
520 } else {
521 co = PyMarshal_ReadObjectFromString((*h)+8, size-8);
522 }
523 }
524 HUnlock(h);
525 CloseResFile(filerh);
526 UseResFile(oldrh);
527 if ( co ) {
528 m = PyImport_ExecCodeModule(module, co);
529 Py_DECREF(co);
530 } else {
531 m = NULL;
532 }
533 return m;
534error:
535 {
536 char buf[512];
537
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000538 sprintf(buf, "%s: %s", filename, PyMac_StrError(err));
Jack Jansen74162f31995-02-15 22:58:33 +0000539 PyErr_SetString(PyExc_ImportError, buf);
540 return NULL;
541 }
542}
Guido van Rossum24a45e31995-02-20 23:45:53 +0000543
Jack Jansen3ec804a1995-02-20 15:56:10 +0000544/*
545** Helper routine for GetDirectory
546*/
Guido van Rossum24a45e31995-02-20 23:45:53 +0000547static pascal short
Jack Jansen819f1771995-08-14 12:35:10 +0000548myhook_proc(short item, DialogPtr theDialog, struct hook_args *dataptr)
Jack Jansen3ec804a1995-02-20 15:56:10 +0000549{
Jack Jansen819f1771995-08-14 12:35:10 +0000550 if ( item == sfHookFirstCall && dataptr->prompt) {
551 Handle prompth;
552 short type;
553 Rect rect;
554
555 GetDialogItem(theDialog, PROMPT_ITEM, &type, &prompth, &rect);
556 if ( prompth )
557 SetDialogItemText(prompth, (unsigned char *)dataptr->prompt);
558 } else
Jack Jansen3ec804a1995-02-20 15:56:10 +0000559 if ( item == SELECTCUR_ITEM ) {
560 item = sfItemCancelButton;
Jack Jansen819f1771995-08-14 12:35:10 +0000561 dataptr->selectcur_hit = 1;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000562 }
563 return item;
564}
565
566/*
567** Ask the user for a directory. I still can't understand
568** why Apple doesn't provide a standard solution for this...
569*/
570int
Jack Jansen819f1771995-08-14 12:35:10 +0000571PyMac_GetDirectory(dirfss, prompt)
Jack Jansen3ec804a1995-02-20 15:56:10 +0000572 FSSpec *dirfss;
Jack Jansen819f1771995-08-14 12:35:10 +0000573 char *prompt;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000574{
575 static SFTypeList list = {'fldr', 0, 0, 0};
576 static Point where = {-1, -1};
Jack Jansen3ec804a1995-02-20 15:56:10 +0000577 StandardFileReply reply;
Jack Jansen819f1771995-08-14 12:35:10 +0000578 struct hook_args hook_args;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000579
580 if ( !upp_inited ) {
581 myhook_upp = NewDlgHookYDProc(myhook_proc);
582 upp_inited = 1;
583 }
Jack Jansen819f1771995-08-14 12:35:10 +0000584 if ( prompt && *prompt )
585 hook_args.prompt = (char *)Pstring(prompt);
586 else
587 hook_args.prompt = NULL;
588 hook_args.selectcur_hit = 0;
Guido van Rossum24a45e31995-02-20 23:45:53 +0000589 CustomGetFile((FileFilterYDUPP)0, 1, list, &reply, GETDIR_ID, where, myhook_upp,
Jack Jansen819f1771995-08-14 12:35:10 +0000590 NULL, NULL, NULL, (void *)&hook_args);
Jack Jansen3ec804a1995-02-20 15:56:10 +0000591
592 reply.sfFile.name[0] = 0;
593 if( FSMakeFSSpec(reply.sfFile.vRefNum, reply.sfFile.parID, reply.sfFile.name, dirfss) )
594 return 0;
Jack Jansen819f1771995-08-14 12:35:10 +0000595 return hook_args.selectcur_hit;
596}
597
598/*
599** Slightly extended StandardGetFile: accepts a prompt */
600void PyMac_PromptGetFile(short numTypes, ConstSFTypeListPtr typeList,
601 StandardFileReply *reply, char *prompt)
602{
603 static Point where = {-1, -1};
604 struct hook_args hook_args;
605
606 if ( !upp_inited ) {
607 myhook_upp = NewDlgHookYDProc(myhook_proc);
608 upp_inited = 1;
609 }
610 if ( prompt && *prompt )
611 hook_args.prompt = (char *)Pstring(prompt);
612 else
613 hook_args.prompt = NULL;
614 hook_args.selectcur_hit = 0;
615 CustomGetFile((FileFilterYDUPP)0, numTypes, typeList, reply, GETFILEPROMPT_ID, where,
616 myhook_upp, NULL, NULL, NULL, (void *)&hook_args);
Jack Jansen3ec804a1995-02-20 15:56:10 +0000617}
Jack Jansen5f653091995-01-18 13:53:49 +0000618
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000619/* Convert a 4-char string object argument to an OSType value */
Jack Jansen5f653091995-01-18 13:53:49 +0000620int
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000621PyMac_GetOSType(PyObject *v, OSType *pr)
Jack Jansen5f653091995-01-18 13:53:49 +0000622{
623 if (!PyString_Check(v) || PyString_Size(v) != 4) {
624 PyErr_SetString(PyExc_TypeError,
625 "OSType arg must be string of 4 chars");
626 return 0;
627 }
628 memcpy((char *)pr, PyString_AsString(v), 4);
629 return 1;
630}
631
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000632/* Convert an OSType value to a 4-char string object */
633PyObject *
634PyMac_BuildOSType(OSType t)
635{
636 return PyString_FromStringAndSize((char *)&t, 4);
637}
638
639
640/* Convert a Python string object to a Str255 */
Jack Jansen5f653091995-01-18 13:53:49 +0000641int
Guido van Rossum8f691791995-01-18 23:57:26 +0000642PyMac_GetStr255(PyObject *v, Str255 pbuf)
Jack Jansen5f653091995-01-18 13:53:49 +0000643{
644 int len;
645 if (!PyString_Check(v) || (len = PyString_Size(v)) > 255) {
646 PyErr_SetString(PyExc_TypeError,
647 "Str255 arg must be string of at most 255 chars");
648 return 0;
649 }
650 pbuf[0] = len;
651 memcpy((char *)(pbuf+1), PyString_AsString(v), len);
652 return 1;
653}
654
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000655/* Convert a Str255 to a Python string object */
656PyObject *
657PyMac_BuildStr255(Str255 s)
658{
659 return PyString_FromStringAndSize((char *)&s[1], (int)s[0]);
660}
661
662
Jack Jansen5f653091995-01-18 13:53:49 +0000663/*
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000664** Convert a Python object to an FSSpec.
665** The object may either be a full pathname or a triple
666** (vrefnum, dirid, path).
Jack Jansen5f653091995-01-18 13:53:49 +0000667** NOTE: This routine will fail on pre-sys7 machines.
668** The caller is responsible for not calling this routine
669** in those cases (which is fine, since everyone calling
670** this is probably sys7 dependent anyway).
671*/
672int
Guido van Rossum8f691791995-01-18 23:57:26 +0000673PyMac_GetFSSpec(PyObject *v, FSSpec *fs)
Jack Jansen5f653091995-01-18 13:53:49 +0000674{
675 Str255 path;
676 short refnum;
677 long parid;
678 OSErr err;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000679 FSSpec *fs2;
Jack Jansen5f653091995-01-18 13:53:49 +0000680
Jack Jansene8e8ae01995-01-26 16:36:45 +0000681 /* first check whether it already is an FSSpec */
682 fs2 = mfs_GetFSSpecFSSpec(v);
683 if ( fs2 ) {
Jack Jansen3ec804a1995-02-20 15:56:10 +0000684 (void)FSMakeFSSpec(fs2->vRefNum, fs2->parID, fs2->name, fs);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000685 return 1;
686 }
Jack Jansen5f653091995-01-18 13:53:49 +0000687 if ( PyString_Check(v) ) {
688 /* It's a pathname */
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000689 if( !PyArg_Parse(v, "O&", PyMac_GetStr255, &path) )
Jack Jansen5f653091995-01-18 13:53:49 +0000690 return 0;
Jack Jansen378815c1996-03-06 16:21:34 +0000691 refnum = 0; /* XXXX Should get CurWD here?? */
Jack Jansen5f653091995-01-18 13:53:49 +0000692 parid = 0;
693 } else {
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000694 if( !PyArg_Parse(v, "(hlO&); FSSpec should be fullpath or (vrefnum,dirid,path)",
695 &refnum, &parid, PyMac_GetStr255, &path)) {
Jack Jansen5f653091995-01-18 13:53:49 +0000696 return 0;
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000697 }
Jack Jansen5f653091995-01-18 13:53:49 +0000698 }
699 err = FSMakeFSSpec(refnum, parid, path, fs);
700 if ( err && err != fnfErr ) {
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000701 PyErr_Mac(PyExc_ValueError, err);
Jack Jansen5f653091995-01-18 13:53:49 +0000702 return 0;
703 }
704 return 1;
705}
706
Guido van Rossum8f691791995-01-18 23:57:26 +0000707
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000708/* Convert a Python object to a Rect.
Guido van Rossum5279ec61995-01-26 22:56:59 +0000709 The object must be a (left, top, right, bottom) tuple.
710 (This differs from the order in the struct but is consistent with
711 the arguments to SetRect(), and also with STDWIN). */
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000712int
713PyMac_GetRect(PyObject *v, Rect *r)
Guido van Rossum8f691791995-01-18 23:57:26 +0000714{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000715 return PyArg_Parse(v, "(hhhh)", &r->left, &r->top, &r->right, &r->bottom);
Guido van Rossum8f691791995-01-18 23:57:26 +0000716}
Guido van Rossumb3404661995-01-22 18:36:13 +0000717
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000718/* Convert a Rect to a Python object */
Guido van Rossumb3404661995-01-22 18:36:13 +0000719PyObject *
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000720PyMac_BuildRect(Rect *r)
Guido van Rossumb3404661995-01-22 18:36:13 +0000721{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000722 return Py_BuildValue("(hhhh)", r->left, r->top, r->right, r->bottom);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000723}
724
725
726/* Convert a Python object to a Point.
Guido van Rossum5279ec61995-01-26 22:56:59 +0000727 The object must be a (h, v) tuple.
728 (This differs from the order in the struct but is consistent with
729 the arguments to SetPoint(), and also with STDWIN). */
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000730int
731PyMac_GetPoint(PyObject *v, Point *p)
732{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000733 return PyArg_Parse(v, "(hh)", &p->h, &p->v);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000734}
735
736/* Convert a Point to a Python object */
737PyObject *
738PyMac_BuildPoint(Point p)
739{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000740 return Py_BuildValue("(hh)", p.h, p.v);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000741}
742
743
744/* Convert a Python object to an EventRecord.
745 The object must be a (what, message, when, (v, h), modifiers) tuple. */
746int
747PyMac_GetEventRecord(PyObject *v, EventRecord *e)
748{
749 return PyArg_Parse(v, "(hll(hh)h)",
750 &e->what,
751 &e->message,
752 &e->when,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000753 &e->where.h,
Guido van Rossum5279ec61995-01-26 22:56:59 +0000754 &e->where.v,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000755 &e->modifiers);
756}
757
758/* Convert a Rect to an EventRecord object */
759PyObject *
760PyMac_BuildEventRecord(EventRecord *e)
761{
762 return Py_BuildValue("(hll(hh)h)",
763 e->what,
764 e->message,
765 e->when,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000766 e->where.h,
Guido van Rossum5279ec61995-01-26 22:56:59 +0000767 e->where.v,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000768 e->modifiers);
Guido van Rossumb3404661995-01-22 18:36:13 +0000769}
Jack Jansenfa4d5d01995-11-15 15:19:29 +0000770
771/* Convert Python object to Fixed */
772int
773PyMac_GetFixed(PyObject *v, Fixed *f)
774{
775 double d;
776
777 if( !PyArg_Parse(v, "d", &d))
778 return 0;
779 *f = (Fixed)(d * 0x10000);
780}
781
782/* Convert a Point to a Python object */
783PyObject *
784PyMac_BuildFixed(Fixed f)
785{
786 double d;
787
788 d = f;
789 d = d / 0x10000;
790 return Py_BuildValue("d", d);
791}
792