blob: dd4499e32f0639eadbaf3439ff91cc0964fb29e0 [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 */
54#endif
Jack Jansenee23d6e1995-01-27 14:43:25 +000055
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +000056#ifndef HAVE_UNIVERSAL_HEADERS
57#define GetResourceSizeOnDisk(x) SizeResource(x)
Guido van Rossum24a45e31995-02-20 23:45:53 +000058typedef DlgHookYDProcPtr DlgHookYDUPP;
59#define NewDlgHookYDProc(userRoutine) ((DlgHookYDUPP) (userRoutine))
60typedef FileFilterYDProcPtr FileFilterYDUPP;
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +000061#endif
62
Jack Jansenee23d6e1995-01-27 14:43:25 +000063#include <signal.h>
Jack Jansen74162f31995-02-15 22:58:33 +000064#include <stdio.h>
Jack Jansene8e8ae01995-01-26 16:36:45 +000065
Jack Jansenee23d6e1995-01-27 14:43:25 +000066/*
Jack Jansen16df2aa1995-02-27 16:17:28 +000067** We have to be careful, since we can't handle
Jack Jansenee23d6e1995-01-27 14:43:25 +000068** things like updates (and they'll keep coming back if we don't
Jack Jansen16df2aa1995-02-27 16:17:28 +000069** handle them). Note that we don't know who has windows open, so
70** even handing updates off to SIOUX under MW isn't going to work.
Jack Jansenee23d6e1995-01-27 14:43:25 +000071*/
72#define MAINLOOP_EVENTMASK (mDownMask|keyDownMask|osMask)
Jack Jansene8e8ae01995-01-26 16:36:45 +000073
74#include <signal.h>
Jack Jansenf93c72a1994-12-14 14:07:50 +000075
Guido van Rossumb3404661995-01-22 18:36:13 +000076/* XXX We should include Errors.h here, but it has a name conflict
Jack Jansen5f653091995-01-18 13:53:49 +000077** with the python errors.h. */
78#define fnfErr -43
79
Jack Jansene8e8ae01995-01-26 16:36:45 +000080/* Declared in macfsmodule.c: */
81extern FSSpec *mfs_GetFSSpecFSSpec();
82
Jack Jansenee23d6e1995-01-27 14:43:25 +000083/* Interrupt code variables: */
84static int interrupted; /* Set to true when cmd-. seen */
85static RETSIGTYPE intcatcher Py_PROTO((int));
86
Jack Jansene8e8ae01995-01-26 16:36:45 +000087/*
88** We attempt to be a good citizen by giving up the CPU periodically.
89** When in the foreground we do this less often and for shorter periods
90** than when in the background. At this time we also check for events and
Jack Jansenee23d6e1995-01-27 14:43:25 +000091** pass them off to SIOUX, if compiling with mwerks.
Jack Jansene8e8ae01995-01-26 16:36:45 +000092** The counts here are in ticks of 1/60th second.
93** XXXX The initial values here are not based on anything.
94** FG-python gives up the cpu for 1/60th 5 times per second,
95** BG-python for .2 second 10 times per second.
96*/
97static long interval_fg = 12;
98static long interval_bg = 6;
99static long yield_fg = 1;
100static long yield_bg = 12;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000101static long lastyield;
102static int in_foreground;
103
Guido van Rossume7134aa1995-02-26 10:20:53 +0000104/*
105** When > 0, do full scanning for events (program is not event aware)
106** when == 0, only scan for Command-period
107** when < 0, don't do any event scanning
108*/
109int PyMac_DoYieldEnabled = 1;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000110
Jack Jansen819f1771995-08-14 12:35:10 +0000111/*
112** Some stuff for our GetDirectory and PromptGetFile routines
113*/
114struct hook_args {
115 int selectcur_hit; /* Set to true when "select current" selected */
116 char *prompt; /* The prompt */
117};
118static DlgHookYDUPP myhook_upp;
119static int upp_inited = 0;
120
121
Jack Jansen5f653091995-01-18 13:53:49 +0000122/* Convert C to Pascal string. Returns pointer to static buffer. */
123unsigned char *
124Pstring(char *str)
125{
126 static Str255 buf;
127 int len;
128
129 len = strlen(str);
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000130 if (len > 255)
131 len = 255;
Jack Jansen5f653091995-01-18 13:53:49 +0000132 buf[0] = (unsigned char)len;
133 strncpy((char *)buf+1, str, len);
134 return buf;
135}
136
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000137/* Like strerror() but for Mac OS error numbers */
138char *PyMac_StrError(int err)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000139{
140 static char buf[256];
141 Handle h;
142 char *str;
143
144 h = GetResource('Estr', err);
145 if ( h ) {
146 HLock(h);
147 str = (char *)*h;
148 memcpy(buf, str+1, (unsigned char)str[0]);
Guido van Rossumcc9bc8f1995-02-13 16:17:03 +0000149 buf[(unsigned char)str[0]] = '\0';
Jack Jansenf93c72a1994-12-14 14:07:50 +0000150 HUnlock(h);
151 ReleaseResource(h);
152 } else {
153 sprintf(buf, "Mac OS error code %d", err);
154 }
155 return buf;
156}
157
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000158/* Exception object shared by all Mac specific modules for Mac OS errors */
159PyObject *PyMac_OSErrException;
160
161/* Initialize and return PyMac_OSErrException */
162PyObject *
163PyMac_GetOSErrException()
164{
165 if (PyMac_OSErrException == NULL)
166 PyMac_OSErrException = PyString_FromString("Mac OS Error");
167 return PyMac_OSErrException;
168}
169
Jack Jansenf93c72a1994-12-14 14:07:50 +0000170/* Set a MAC-specific error from errno, and return NULL; return None if no error */
171PyObject *
Guido van Rossumfffb8bb1995-01-12 12:37:24 +0000172PyErr_Mac(PyObject *eobj, int err)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000173{
174 char *msg;
175 PyObject *v;
Jack Jansenf93c72a1994-12-14 14:07:50 +0000176
Guido van Rossum8f691791995-01-18 23:57:26 +0000177 if (err == 0 && !PyErr_Occurred()) {
Jack Jansenf93c72a1994-12-14 14:07:50 +0000178 Py_INCREF(Py_None);
179 return Py_None;
180 }
Guido van Rossum8f691791995-01-18 23:57:26 +0000181 if (err == -1 && PyErr_Occurred())
182 return NULL;
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000183 msg = PyMac_StrError(err);
Jack Jansenf93c72a1994-12-14 14:07:50 +0000184 v = Py_BuildValue("(is)", err, msg);
185 PyErr_SetObject(eobj, v);
186 Py_DECREF(v);
187 return NULL;
188}
189
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000190/* Call PyErr_Mac with PyMac_OSErrException */
191PyObject *
192PyMac_Error(OSErr err)
193{
194 return PyErr_Mac(PyMac_GetOSErrException(), err);
195}
196
Jack Jansenee23d6e1995-01-27 14:43:25 +0000197/* The catcher routine (which may not be used for all compilers) */
198static RETSIGTYPE
199intcatcher(sig)
200 int sig;
201{
202 interrupted = 1;
203 signal(SIGINT, intcatcher);
204}
205
206void
207PyOS_InitInterrupts()
208{
209 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
210 signal(SIGINT, intcatcher);
211}
212
213/*
214** This routine scans the event queue looking for cmd-.
215** This is the only way to get an interrupt under THINK (since it
216** doesn't do SIGINT handling), but is also used under MW, when
217** the full-fledged event loop is disabled. This way, we can at least
218** interrupt a runaway python program.
219*/
220static void
221scan_event_queue(flush)
222 int flush;
223{
Jack Jansenf74f63a1995-06-27 13:18:14 +0000224#if defined(__MWERKS__) && defined(__CFM68K__)
225 return; /* No GetEvQHdr yet */
226#else
Jack Jansenee23d6e1995-01-27 14:43:25 +0000227 register EvQElPtr q;
228
229 q = (EvQElPtr) GetEvQHdr()->qHead;
230
231 for (; q; q = (EvQElPtr)q->qLink) {
232 if (q->evtQWhat == keyDown &&
233 (char)q->evtQMessage == '.' &&
234 (q->evtQModifiers & cmdKey) != 0) {
235 if ( flush )
236 FlushEvents(keyDownMask, 0);
237 interrupted = 1;
238 break;
239 }
240 }
Jack Jansenf74f63a1995-06-27 13:18:14 +0000241#endif
Jack Jansenee23d6e1995-01-27 14:43:25 +0000242}
243
244int
245PyOS_InterruptOccurred()
246{
Guido van Rossume7134aa1995-02-26 10:20:53 +0000247 if (PyMac_DoYieldEnabled < 0)
248 return 0;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000249#ifdef THINK_C
250 scan_event_queue(1);
251#endif
252 PyMac_Yield();
253 if (interrupted) {
254 interrupted = 0;
255 return 1;
256 }
257 return 0;
258}
259
260/* intrpeek() is like intrcheck(), but it doesn't flush the events. The
261** idea is that you call intrpeek() somewhere in a busy-wait loop, and return
262** None as soon as it returns 1. The mainloop will then pick up the cmd-. soon
263** thereafter.
264*/
265static int
266intrpeek()
267{
268#ifdef THINK_C
269 scan_event_queue(0);
270#endif
271 return interrupted;
272}
273
274/* Check whether we are in the foreground */
275int
276PyMac_InForeground()
277{
278 static ProcessSerialNumber ours;
279 static inited;
280 ProcessSerialNumber curfg;
281 Boolean eq;
282
283 if ( inited == 0 )
284 (void)GetCurrentProcess(&ours);
285 inited = 1;
286 if ( GetFrontProcess(&curfg) < 0 )
287 eq = 1;
288 else if ( SameProcess(&ours, &curfg, &eq) < 0 )
289 eq = 1;
290 return (int)eq;
291
292}
293
Jack Jansenf93c72a1994-12-14 14:07:50 +0000294/*
Jack Jansene8e8ae01995-01-26 16:36:45 +0000295** Set yield timeouts
Jack Jansenf93c72a1994-12-14 14:07:50 +0000296*/
Jack Jansene8e8ae01995-01-26 16:36:45 +0000297void
298PyMac_SetYield(long fgi, long fgy, long bgi, long bgy)
299{
300 interval_fg = fgi;
301 yield_fg = fgy;
302 interval_bg = bgi;
303 yield_bg = bgy;
304}
305
306/*
Jack Jansena76382a1995-02-02 14:25:56 +0000307** Handle an event, either one found in the mainloop eventhandler or
308** one passed back from the python program.
309*/
310void
311PyMac_HandleEvent(evp)
312 EventRecord *evp;
313{
Jack Jansena76382a1995-02-02 14:25:56 +0000314
315#ifdef __MWERKS__
Jack Jansen38e97661995-11-10 14:53:00 +0000316 {
317 int siouxdidit;
318
319 /* If SIOUX wants it we're done */
320 siouxdidit = SIOUXHandleOneEvent(evp);
321 if ( siouxdidit )
322 return;
323 }
Jack Jansena76382a1995-02-02 14:25:56 +0000324#else
325 /* Other compilers are just unlucky: we only weed out clicks in other applications */
326 if ( evp->what == mouseDown ) {
Jack Jansen847e89e1995-08-31 13:57:40 +0000327 WindowPtr wp;
328
Jack Jansen38e97661995-11-10 14:53:00 +0000329 if ( FindWindow(evp->where, &wp) == inSysWindow ) {
Jack Jansena76382a1995-02-02 14:25:56 +0000330 SystemClick(evp, wp);
Jack Jansen38e97661995-11-10 14:53:00 +0000331 return;
332 }
Jack Jansena76382a1995-02-02 14:25:56 +0000333 }
334#endif /* !__MWERKS__ */
335}
336
337/*
Jack Jansene8e8ae01995-01-26 16:36:45 +0000338** Yield the CPU to other tasks.
339*/
340static
341PyMac_DoYield()
Jack Jansenf93c72a1994-12-14 14:07:50 +0000342{
343 EventRecord ev;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000344 long yield;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000345 static int no_waitnextevent = -1;
346 int gotone;
347
348 if ( no_waitnextevent < 0 ) {
349 no_waitnextevent = (NGetTrapAddress(_WaitNextEvent, ToolTrap) ==
350 NGetTrapAddress(_Unimplemented, ToolTrap));
351 }
Jack Jansenf93c72a1994-12-14 14:07:50 +0000352
Jack Jansenee23d6e1995-01-27 14:43:25 +0000353 if ( !PyMac_DoYieldEnabled ) {
354#ifndef THINK_C
355 /* Under think this has been done before in intrcheck() or intrpeek() */
356 scan_event_queue(0);
357#endif
Jack Jansene8e8ae01995-01-26 16:36:45 +0000358 return;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000359 }
Jack Jansene8e8ae01995-01-26 16:36:45 +0000360
Jack Jansenee23d6e1995-01-27 14:43:25 +0000361 in_foreground = PyMac_InForeground();
362 if ( in_foreground )
Jack Jansene8e8ae01995-01-26 16:36:45 +0000363 yield = yield_fg;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000364 else
365 yield = yield_bg;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000366 while ( 1 ) {
367 if ( no_waitnextevent ) {
368 SystemTask();
Jack Jansenee23d6e1995-01-27 14:43:25 +0000369 gotone = GetNextEvent(MAINLOOP_EVENTMASK, &ev);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000370 } else {
Jack Jansenee23d6e1995-01-27 14:43:25 +0000371 gotone = WaitNextEvent(MAINLOOP_EVENTMASK, &ev, yield, NULL);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000372 }
373 /* Get out quickly if nothing interesting is happening */
374 if ( !gotone || ev.what == nullEvent )
375 break;
Jack Jansena76382a1995-02-02 14:25:56 +0000376 PyMac_HandleEvent(&ev);
Jack Jansenf93c72a1994-12-14 14:07:50 +0000377 }
Jack Jansene8e8ae01995-01-26 16:36:45 +0000378 lastyield = TickCount();
379}
380
381/*
382** Yield the CPU to other tasks if opportune
383*/
384void
385PyMac_Yield() {
386 long iv;
387
Jack Jansenee23d6e1995-01-27 14:43:25 +0000388 if ( in_foreground )
Jack Jansene8e8ae01995-01-26 16:36:45 +0000389 iv = interval_fg;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000390 else
391 iv = interval_bg;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000392 if ( TickCount() > lastyield + iv )
393 PyMac_DoYield();
394}
395
396/*
397** Idle routine for busy-wait loops.
398** Gives up CPU, handles events and returns true if an interrupt is pending
399** (but not actually handled yet).
400*/
401int
402PyMac_Idle()
403{
404 PyMac_DoYield();
405 return intrpeek();
Jack Jansenf93c72a1994-12-14 14:07:50 +0000406}
Jack Jansen74162f31995-02-15 22:58:33 +0000407/*
408** Returns true if the argument has a resource fork, and it contains
409** a 'PYC ' resource of the correct name
410*/
411int
412PyMac_FindResourceModule(module, filename)
413char *module;
414char *filename;
415{
416 FSSpec fss;
417 FInfo finfo;
418 short oldrh, filerh;
419 int ok;
420 Handle h;
421
422 if ( FSMakeFSSpec(0, 0, Pstring(filename), &fss) != noErr )
423 return 0; /* It doesn't exist */
424 if ( FSpGetFInfo(&fss, &finfo) != noErr )
425 return 0; /* shouldn't happen, I guess */
Jack Jansen74162f31995-02-15 22:58:33 +0000426 oldrh = CurResFile();
427 filerh = FSpOpenResFile(&fss, fsRdPerm);
428 if ( filerh == -1 )
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000429 return 0;
Jack Jansen74162f31995-02-15 22:58:33 +0000430 UseResFile(filerh);
431 SetResLoad(0);
432 h = Get1NamedResource('PYC ', Pstring(module));
433 SetResLoad(1);
434 ok = (h != NULL);
435 CloseResFile(filerh);
436 UseResFile(oldrh);
437 return ok;
438}
439
440/*
441** Load the specified module from a resource
442*/
443PyObject *
444PyMac_LoadResourceModule(module, filename)
445char *module;
446char *filename;
447{
448 FSSpec fss;
449 FInfo finfo;
450 short oldrh, filerh;
Jack Jansen74162f31995-02-15 22:58:33 +0000451 Handle h;
452 OSErr err;
453 PyObject *m, *co;
454 long num, size;
455
456 if ( (err=FSMakeFSSpec(0, 0, Pstring(filename), &fss)) != noErr )
457 goto error;
458 if ( (err=FSpGetFInfo(&fss, &finfo)) != noErr )
459 goto error;
Jack Jansen74162f31995-02-15 22:58:33 +0000460 oldrh = CurResFile();
461 filerh = FSpOpenResFile(&fss, fsRdPerm);
462 if ( filerh == -1 ) {
463 err = ResError();
464 goto error;
465 }
466 UseResFile(filerh);
467 h = Get1NamedResource('PYC ', Pstring(module));
468 if ( h == NULL ) {
469 err = ResError();
470 goto error;
471 }
472 HLock(h);
473 /*
474 ** XXXX The next few lines are intimately tied to the format of pyc
475 ** files. I'm not sure whether this code should be here or in import.c -- Jack
476 */
477 size = GetHandleSize(h);
478 if ( size < 8 ) {
479 PyErr_SetString(PyExc_ImportError, "Resource too small");
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000480 co = NULL;
Jack Jansen74162f31995-02-15 22:58:33 +0000481 } else {
482 num = (*h)[0] & 0xff;
483 num = num | (((*h)[1] & 0xff) << 8);
484 num = num | (((*h)[2] & 0xff) << 16);
485 num = num | (((*h)[3] & 0xff) << 24);
486 if ( num != PyImport_GetMagicNumber() ) {
487 PyErr_SetString(PyExc_ImportError, "Bad MAGIC in resource");
488 co = NULL;
489 } else {
490 co = PyMarshal_ReadObjectFromString((*h)+8, size-8);
491 }
492 }
493 HUnlock(h);
494 CloseResFile(filerh);
495 UseResFile(oldrh);
496 if ( co ) {
497 m = PyImport_ExecCodeModule(module, co);
498 Py_DECREF(co);
499 } else {
500 m = NULL;
501 }
502 return m;
503error:
504 {
505 char buf[512];
506
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000507 sprintf(buf, "%s: %s", filename, PyMac_StrError(err));
Jack Jansen74162f31995-02-15 22:58:33 +0000508 PyErr_SetString(PyExc_ImportError, buf);
509 return NULL;
510 }
511}
Guido van Rossum24a45e31995-02-20 23:45:53 +0000512
Jack Jansen3ec804a1995-02-20 15:56:10 +0000513/*
514** Helper routine for GetDirectory
515*/
Guido van Rossum24a45e31995-02-20 23:45:53 +0000516static pascal short
Jack Jansen819f1771995-08-14 12:35:10 +0000517myhook_proc(short item, DialogPtr theDialog, struct hook_args *dataptr)
Jack Jansen3ec804a1995-02-20 15:56:10 +0000518{
Jack Jansen819f1771995-08-14 12:35:10 +0000519 if ( item == sfHookFirstCall && dataptr->prompt) {
520 Handle prompth;
521 short type;
522 Rect rect;
523
524 GetDialogItem(theDialog, PROMPT_ITEM, &type, &prompth, &rect);
525 if ( prompth )
526 SetDialogItemText(prompth, (unsigned char *)dataptr->prompt);
527 } else
Jack Jansen3ec804a1995-02-20 15:56:10 +0000528 if ( item == SELECTCUR_ITEM ) {
529 item = sfItemCancelButton;
Jack Jansen819f1771995-08-14 12:35:10 +0000530 dataptr->selectcur_hit = 1;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000531 }
532 return item;
533}
534
535/*
536** Ask the user for a directory. I still can't understand
537** why Apple doesn't provide a standard solution for this...
538*/
539int
Jack Jansen819f1771995-08-14 12:35:10 +0000540PyMac_GetDirectory(dirfss, prompt)
Jack Jansen3ec804a1995-02-20 15:56:10 +0000541 FSSpec *dirfss;
Jack Jansen819f1771995-08-14 12:35:10 +0000542 char *prompt;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000543{
544 static SFTypeList list = {'fldr', 0, 0, 0};
545 static Point where = {-1, -1};
Jack Jansen3ec804a1995-02-20 15:56:10 +0000546 StandardFileReply reply;
Jack Jansen819f1771995-08-14 12:35:10 +0000547 struct hook_args hook_args;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000548
549 if ( !upp_inited ) {
550 myhook_upp = NewDlgHookYDProc(myhook_proc);
551 upp_inited = 1;
552 }
Jack Jansen819f1771995-08-14 12:35:10 +0000553 if ( prompt && *prompt )
554 hook_args.prompt = (char *)Pstring(prompt);
555 else
556 hook_args.prompt = NULL;
557 hook_args.selectcur_hit = 0;
Guido van Rossum24a45e31995-02-20 23:45:53 +0000558 CustomGetFile((FileFilterYDUPP)0, 1, list, &reply, GETDIR_ID, where, myhook_upp,
Jack Jansen819f1771995-08-14 12:35:10 +0000559 NULL, NULL, NULL, (void *)&hook_args);
Jack Jansen3ec804a1995-02-20 15:56:10 +0000560
561 reply.sfFile.name[0] = 0;
562 if( FSMakeFSSpec(reply.sfFile.vRefNum, reply.sfFile.parID, reply.sfFile.name, dirfss) )
563 return 0;
Jack Jansen819f1771995-08-14 12:35:10 +0000564 return hook_args.selectcur_hit;
565}
566
567/*
568** Slightly extended StandardGetFile: accepts a prompt */
569void PyMac_PromptGetFile(short numTypes, ConstSFTypeListPtr typeList,
570 StandardFileReply *reply, char *prompt)
571{
572 static Point where = {-1, -1};
573 struct hook_args hook_args;
574
575 if ( !upp_inited ) {
576 myhook_upp = NewDlgHookYDProc(myhook_proc);
577 upp_inited = 1;
578 }
579 if ( prompt && *prompt )
580 hook_args.prompt = (char *)Pstring(prompt);
581 else
582 hook_args.prompt = NULL;
583 hook_args.selectcur_hit = 0;
584 CustomGetFile((FileFilterYDUPP)0, numTypes, typeList, reply, GETFILEPROMPT_ID, where,
585 myhook_upp, NULL, NULL, NULL, (void *)&hook_args);
Jack Jansen3ec804a1995-02-20 15:56:10 +0000586}
Jack Jansen5f653091995-01-18 13:53:49 +0000587
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000588/* Convert a 4-char string object argument to an OSType value */
Jack Jansen5f653091995-01-18 13:53:49 +0000589int
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000590PyMac_GetOSType(PyObject *v, OSType *pr)
Jack Jansen5f653091995-01-18 13:53:49 +0000591{
592 if (!PyString_Check(v) || PyString_Size(v) != 4) {
593 PyErr_SetString(PyExc_TypeError,
594 "OSType arg must be string of 4 chars");
595 return 0;
596 }
597 memcpy((char *)pr, PyString_AsString(v), 4);
598 return 1;
599}
600
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000601/* Convert an OSType value to a 4-char string object */
602PyObject *
603PyMac_BuildOSType(OSType t)
604{
605 return PyString_FromStringAndSize((char *)&t, 4);
606}
607
608
609/* Convert a Python string object to a Str255 */
Jack Jansen5f653091995-01-18 13:53:49 +0000610int
Guido van Rossum8f691791995-01-18 23:57:26 +0000611PyMac_GetStr255(PyObject *v, Str255 pbuf)
Jack Jansen5f653091995-01-18 13:53:49 +0000612{
613 int len;
614 if (!PyString_Check(v) || (len = PyString_Size(v)) > 255) {
615 PyErr_SetString(PyExc_TypeError,
616 "Str255 arg must be string of at most 255 chars");
617 return 0;
618 }
619 pbuf[0] = len;
620 memcpy((char *)(pbuf+1), PyString_AsString(v), len);
621 return 1;
622}
623
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000624/* Convert a Str255 to a Python string object */
625PyObject *
626PyMac_BuildStr255(Str255 s)
627{
628 return PyString_FromStringAndSize((char *)&s[1], (int)s[0]);
629}
630
631
Jack Jansen5f653091995-01-18 13:53:49 +0000632/*
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000633** Convert a Python object to an FSSpec.
634** The object may either be a full pathname or a triple
635** (vrefnum, dirid, path).
Jack Jansen5f653091995-01-18 13:53:49 +0000636** NOTE: This routine will fail on pre-sys7 machines.
637** The caller is responsible for not calling this routine
638** in those cases (which is fine, since everyone calling
639** this is probably sys7 dependent anyway).
640*/
641int
Guido van Rossum8f691791995-01-18 23:57:26 +0000642PyMac_GetFSSpec(PyObject *v, FSSpec *fs)
Jack Jansen5f653091995-01-18 13:53:49 +0000643{
644 Str255 path;
645 short refnum;
646 long parid;
647 OSErr err;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000648 FSSpec *fs2;
Jack Jansen5f653091995-01-18 13:53:49 +0000649
Jack Jansene8e8ae01995-01-26 16:36:45 +0000650 /* first check whether it already is an FSSpec */
651 fs2 = mfs_GetFSSpecFSSpec(v);
652 if ( fs2 ) {
Jack Jansen3ec804a1995-02-20 15:56:10 +0000653 (void)FSMakeFSSpec(fs2->vRefNum, fs2->parID, fs2->name, fs);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000654 return 1;
655 }
Jack Jansen5f653091995-01-18 13:53:49 +0000656 if ( PyString_Check(v) ) {
657 /* It's a pathname */
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000658 if( !PyArg_Parse(v, "O&", PyMac_GetStr255, &path) )
Jack Jansen5f653091995-01-18 13:53:49 +0000659 return 0;
Jack Jansen911ad6b1996-03-05 16:56:24 +0000660#ifdef USE_GUSI
661 {
662 FSSpec curdirfss;
663
664 if ( Path2FSSpec(":x", &curdirfss) == 0 ) {
665 refnum = curdirfss.vRefNum;
666 parid = curdirfss.parID;
667 } else {
668 return 0;
669 }
670 }
671#else
Jack Jansen5f653091995-01-18 13:53:49 +0000672 refnum = 0; /* XXXX Should get CurWD here... */
673 parid = 0;
Jack Jansen911ad6b1996-03-05 16:56:24 +0000674#endif
Jack Jansen5f653091995-01-18 13:53:49 +0000675 } else {
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000676 if( !PyArg_Parse(v, "(hlO&); FSSpec should be fullpath or (vrefnum,dirid,path)",
677 &refnum, &parid, PyMac_GetStr255, &path)) {
Jack Jansen5f653091995-01-18 13:53:49 +0000678 return 0;
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000679 }
Jack Jansen5f653091995-01-18 13:53:49 +0000680 }
681 err = FSMakeFSSpec(refnum, parid, path, fs);
682 if ( err && err != fnfErr ) {
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000683 PyErr_Mac(PyExc_ValueError, err);
Jack Jansen5f653091995-01-18 13:53:49 +0000684 return 0;
685 }
686 return 1;
687}
688
Guido van Rossum8f691791995-01-18 23:57:26 +0000689
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000690
691/* Convert a Python object to a Rect.
Guido van Rossum5279ec61995-01-26 22:56:59 +0000692 The object must be a (left, top, right, bottom) tuple.
693 (This differs from the order in the struct but is consistent with
694 the arguments to SetRect(), and also with STDWIN). */
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000695int
696PyMac_GetRect(PyObject *v, Rect *r)
Guido van Rossum8f691791995-01-18 23:57:26 +0000697{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000698 return PyArg_Parse(v, "(hhhh)", &r->left, &r->top, &r->right, &r->bottom);
Guido van Rossum8f691791995-01-18 23:57:26 +0000699}
Guido van Rossumb3404661995-01-22 18:36:13 +0000700
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000701/* Convert a Rect to a Python object */
Guido van Rossumb3404661995-01-22 18:36:13 +0000702PyObject *
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000703PyMac_BuildRect(Rect *r)
Guido van Rossumb3404661995-01-22 18:36:13 +0000704{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000705 return Py_BuildValue("(hhhh)", r->left, r->top, r->right, r->bottom);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000706}
707
708
709/* Convert a Python object to a Point.
Guido van Rossum5279ec61995-01-26 22:56:59 +0000710 The object must be a (h, v) tuple.
711 (This differs from the order in the struct but is consistent with
712 the arguments to SetPoint(), and also with STDWIN). */
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000713int
714PyMac_GetPoint(PyObject *v, Point *p)
715{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000716 return PyArg_Parse(v, "(hh)", &p->h, &p->v);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000717}
718
719/* Convert a Point to a Python object */
720PyObject *
721PyMac_BuildPoint(Point p)
722{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000723 return Py_BuildValue("(hh)", p.h, p.v);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000724}
725
726
727/* Convert a Python object to an EventRecord.
728 The object must be a (what, message, when, (v, h), modifiers) tuple. */
729int
730PyMac_GetEventRecord(PyObject *v, EventRecord *e)
731{
732 return PyArg_Parse(v, "(hll(hh)h)",
733 &e->what,
734 &e->message,
735 &e->when,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000736 &e->where.h,
Guido van Rossum5279ec61995-01-26 22:56:59 +0000737 &e->where.v,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000738 &e->modifiers);
739}
740
741/* Convert a Rect to an EventRecord object */
742PyObject *
743PyMac_BuildEventRecord(EventRecord *e)
744{
745 return Py_BuildValue("(hll(hh)h)",
746 e->what,
747 e->message,
748 e->when,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000749 e->where.h,
Guido van Rossum5279ec61995-01-26 22:56:59 +0000750 e->where.v,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000751 e->modifiers);
Guido van Rossumb3404661995-01-22 18:36:13 +0000752}
Jack Jansenfa4d5d01995-11-15 15:19:29 +0000753
754/* Convert Python object to Fixed */
755int
756PyMac_GetFixed(PyObject *v, Fixed *f)
757{
758 double d;
759
760 if( !PyArg_Parse(v, "d", &d))
761 return 0;
762 *f = (Fixed)(d * 0x10000);
763}
764
765/* Convert a Point to a Python object */
766PyObject *
767PyMac_BuildFixed(Fixed f)
768{
769 double d;
770
771 d = f;
772 d = d / 0x10000;
773 return Py_BuildValue("d", d);
774}
775