blob: 6006474734341ab051edc3c184fe198de0a610a8 [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 Jansenee23d6e1995-01-27 14:43:25 +000052
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +000053#ifndef HAVE_UNIVERSAL_HEADERS
54#define GetResourceSizeOnDisk(x) SizeResource(x)
Guido van Rossum24a45e31995-02-20 23:45:53 +000055typedef DlgHookYDProcPtr DlgHookYDUPP;
56#define NewDlgHookYDProc(userRoutine) ((DlgHookYDUPP) (userRoutine))
57typedef FileFilterYDProcPtr FileFilterYDUPP;
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +000058#endif
59
Jack Jansenee23d6e1995-01-27 14:43:25 +000060#include <signal.h>
Jack Jansen74162f31995-02-15 22:58:33 +000061#include <stdio.h>
Jack Jansene8e8ae01995-01-26 16:36:45 +000062
Jack Jansenee23d6e1995-01-27 14:43:25 +000063/*
Jack Jansen16df2aa1995-02-27 16:17:28 +000064** We have to be careful, since we can't handle
Jack Jansenee23d6e1995-01-27 14:43:25 +000065** things like updates (and they'll keep coming back if we don't
Jack Jansen16df2aa1995-02-27 16:17:28 +000066** handle them). Note that we don't know who has windows open, so
67** even handing updates off to SIOUX under MW isn't going to work.
Jack Jansenee23d6e1995-01-27 14:43:25 +000068*/
69#define MAINLOOP_EVENTMASK (mDownMask|keyDownMask|osMask)
Jack Jansene8e8ae01995-01-26 16:36:45 +000070
71#include <signal.h>
Jack Jansenf93c72a1994-12-14 14:07:50 +000072
Guido van Rossumb3404661995-01-22 18:36:13 +000073/* XXX We should include Errors.h here, but it has a name conflict
Jack Jansen5f653091995-01-18 13:53:49 +000074** with the python errors.h. */
75#define fnfErr -43
76
Jack Jansene8e8ae01995-01-26 16:36:45 +000077/* Declared in macfsmodule.c: */
78extern FSSpec *mfs_GetFSSpecFSSpec();
79
Jack Jansenee23d6e1995-01-27 14:43:25 +000080/* Interrupt code variables: */
81static int interrupted; /* Set to true when cmd-. seen */
82static RETSIGTYPE intcatcher Py_PROTO((int));
83
Jack Jansene8e8ae01995-01-26 16:36:45 +000084/*
85** We attempt to be a good citizen by giving up the CPU periodically.
86** When in the foreground we do this less often and for shorter periods
87** than when in the background. At this time we also check for events and
Jack Jansenee23d6e1995-01-27 14:43:25 +000088** pass them off to SIOUX, if compiling with mwerks.
Jack Jansene8e8ae01995-01-26 16:36:45 +000089** The counts here are in ticks of 1/60th second.
90** XXXX The initial values here are not based on anything.
91** FG-python gives up the cpu for 1/60th 5 times per second,
92** BG-python for .2 second 10 times per second.
93*/
94static long interval_fg = 12;
95static long interval_bg = 6;
96static long yield_fg = 1;
97static long yield_bg = 12;
Jack Jansenee23d6e1995-01-27 14:43:25 +000098static long lastyield;
99static int in_foreground;
100
Guido van Rossume7134aa1995-02-26 10:20:53 +0000101/*
102** When > 0, do full scanning for events (program is not event aware)
103** when == 0, only scan for Command-period
104** when < 0, don't do any event scanning
105*/
106int PyMac_DoYieldEnabled = 1;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000107
Jack Jansen819f1771995-08-14 12:35:10 +0000108/*
109** Some stuff for our GetDirectory and PromptGetFile routines
110*/
111struct hook_args {
112 int selectcur_hit; /* Set to true when "select current" selected */
113 char *prompt; /* The prompt */
114};
115static DlgHookYDUPP myhook_upp;
116static int upp_inited = 0;
117
118
Jack Jansen5f653091995-01-18 13:53:49 +0000119/* Convert C to Pascal string. Returns pointer to static buffer. */
120unsigned char *
121Pstring(char *str)
122{
123 static Str255 buf;
124 int len;
125
126 len = strlen(str);
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000127 if (len > 255)
128 len = 255;
Jack Jansen5f653091995-01-18 13:53:49 +0000129 buf[0] = (unsigned char)len;
130 strncpy((char *)buf+1, str, len);
131 return buf;
132}
133
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000134/* Like strerror() but for Mac OS error numbers */
135char *PyMac_StrError(int err)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000136{
137 static char buf[256];
138 Handle h;
139 char *str;
140
141 h = GetResource('Estr', err);
142 if ( h ) {
143 HLock(h);
144 str = (char *)*h;
145 memcpy(buf, str+1, (unsigned char)str[0]);
Guido van Rossumcc9bc8f1995-02-13 16:17:03 +0000146 buf[(unsigned char)str[0]] = '\0';
Jack Jansenf93c72a1994-12-14 14:07:50 +0000147 HUnlock(h);
148 ReleaseResource(h);
149 } else {
150 sprintf(buf, "Mac OS error code %d", err);
151 }
152 return buf;
153}
154
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000155/* Exception object shared by all Mac specific modules for Mac OS errors */
156PyObject *PyMac_OSErrException;
157
158/* Initialize and return PyMac_OSErrException */
159PyObject *
160PyMac_GetOSErrException()
161{
162 if (PyMac_OSErrException == NULL)
163 PyMac_OSErrException = PyString_FromString("Mac OS Error");
164 return PyMac_OSErrException;
165}
166
Jack Jansenf93c72a1994-12-14 14:07:50 +0000167/* Set a MAC-specific error from errno, and return NULL; return None if no error */
168PyObject *
Guido van Rossumfffb8bb1995-01-12 12:37:24 +0000169PyErr_Mac(PyObject *eobj, int err)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000170{
171 char *msg;
172 PyObject *v;
Jack Jansenf93c72a1994-12-14 14:07:50 +0000173
Guido van Rossum8f691791995-01-18 23:57:26 +0000174 if (err == 0 && !PyErr_Occurred()) {
Jack Jansenf93c72a1994-12-14 14:07:50 +0000175 Py_INCREF(Py_None);
176 return Py_None;
177 }
Guido van Rossum8f691791995-01-18 23:57:26 +0000178 if (err == -1 && PyErr_Occurred())
179 return NULL;
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000180 msg = PyMac_StrError(err);
Jack Jansenf93c72a1994-12-14 14:07:50 +0000181 v = Py_BuildValue("(is)", err, msg);
182 PyErr_SetObject(eobj, v);
183 Py_DECREF(v);
184 return NULL;
185}
186
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000187/* Call PyErr_Mac with PyMac_OSErrException */
188PyObject *
189PyMac_Error(OSErr err)
190{
191 return PyErr_Mac(PyMac_GetOSErrException(), err);
192}
193
Jack Jansenee23d6e1995-01-27 14:43:25 +0000194/* The catcher routine (which may not be used for all compilers) */
195static RETSIGTYPE
196intcatcher(sig)
197 int sig;
198{
199 interrupted = 1;
200 signal(SIGINT, intcatcher);
201}
202
203void
204PyOS_InitInterrupts()
205{
206 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
207 signal(SIGINT, intcatcher);
208}
209
210/*
211** This routine scans the event queue looking for cmd-.
212** This is the only way to get an interrupt under THINK (since it
213** doesn't do SIGINT handling), but is also used under MW, when
214** the full-fledged event loop is disabled. This way, we can at least
215** interrupt a runaway python program.
216*/
217static void
218scan_event_queue(flush)
219 int flush;
220{
Jack Jansenf74f63a1995-06-27 13:18:14 +0000221#if defined(__MWERKS__) && defined(__CFM68K__)
222 return; /* No GetEvQHdr yet */
223#else
Jack Jansenee23d6e1995-01-27 14:43:25 +0000224 register EvQElPtr q;
225
226 q = (EvQElPtr) GetEvQHdr()->qHead;
227
228 for (; q; q = (EvQElPtr)q->qLink) {
229 if (q->evtQWhat == keyDown &&
230 (char)q->evtQMessage == '.' &&
231 (q->evtQModifiers & cmdKey) != 0) {
232 if ( flush )
233 FlushEvents(keyDownMask, 0);
234 interrupted = 1;
235 break;
236 }
237 }
Jack Jansenf74f63a1995-06-27 13:18:14 +0000238#endif
Jack Jansenee23d6e1995-01-27 14:43:25 +0000239}
240
241int
242PyOS_InterruptOccurred()
243{
Guido van Rossume7134aa1995-02-26 10:20:53 +0000244 if (PyMac_DoYieldEnabled < 0)
245 return 0;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000246#ifdef THINK_C
247 scan_event_queue(1);
248#endif
249 PyMac_Yield();
250 if (interrupted) {
251 interrupted = 0;
252 return 1;
253 }
254 return 0;
255}
256
257/* intrpeek() is like intrcheck(), but it doesn't flush the events. The
258** idea is that you call intrpeek() somewhere in a busy-wait loop, and return
259** None as soon as it returns 1. The mainloop will then pick up the cmd-. soon
260** thereafter.
261*/
262static int
263intrpeek()
264{
265#ifdef THINK_C
266 scan_event_queue(0);
267#endif
268 return interrupted;
269}
270
271/* Check whether we are in the foreground */
272int
273PyMac_InForeground()
274{
275 static ProcessSerialNumber ours;
276 static inited;
277 ProcessSerialNumber curfg;
278 Boolean eq;
279
280 if ( inited == 0 )
281 (void)GetCurrentProcess(&ours);
282 inited = 1;
283 if ( GetFrontProcess(&curfg) < 0 )
284 eq = 1;
285 else if ( SameProcess(&ours, &curfg, &eq) < 0 )
286 eq = 1;
287 return (int)eq;
288
289}
290
Jack Jansenf93c72a1994-12-14 14:07:50 +0000291/*
Jack Jansene8e8ae01995-01-26 16:36:45 +0000292** Set yield timeouts
Jack Jansenf93c72a1994-12-14 14:07:50 +0000293*/
Jack Jansene8e8ae01995-01-26 16:36:45 +0000294void
295PyMac_SetYield(long fgi, long fgy, long bgi, long bgy)
296{
297 interval_fg = fgi;
298 yield_fg = fgy;
299 interval_bg = bgi;
300 yield_bg = bgy;
301}
302
303/*
Jack Jansena76382a1995-02-02 14:25:56 +0000304** Handle an event, either one found in the mainloop eventhandler or
305** one passed back from the python program.
306*/
307void
308PyMac_HandleEvent(evp)
309 EventRecord *evp;
310{
Jack Jansena76382a1995-02-02 14:25:56 +0000311
312#ifdef __MWERKS__
313 /* If SIOUX wants it we're done */
314 (void)SIOUXHandleOneEvent(evp);
315#else
316 /* Other compilers are just unlucky: we only weed out clicks in other applications */
317 if ( evp->what == mouseDown ) {
Jack Jansen847e89e1995-08-31 13:57:40 +0000318 WindowPtr wp;
319
Jack Jansena76382a1995-02-02 14:25:56 +0000320 if ( FindWindow(evp->where, &wp) == inSysWindow )
321 SystemClick(evp, wp);
322 }
323#endif /* !__MWERKS__ */
324}
325
326/*
Jack Jansene8e8ae01995-01-26 16:36:45 +0000327** Yield the CPU to other tasks.
328*/
329static
330PyMac_DoYield()
Jack Jansenf93c72a1994-12-14 14:07:50 +0000331{
332 EventRecord ev;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000333 long yield;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000334 static int no_waitnextevent = -1;
335 int gotone;
336
337 if ( no_waitnextevent < 0 ) {
338 no_waitnextevent = (NGetTrapAddress(_WaitNextEvent, ToolTrap) ==
339 NGetTrapAddress(_Unimplemented, ToolTrap));
340 }
Jack Jansenf93c72a1994-12-14 14:07:50 +0000341
Jack Jansenee23d6e1995-01-27 14:43:25 +0000342 if ( !PyMac_DoYieldEnabled ) {
343#ifndef THINK_C
344 /* Under think this has been done before in intrcheck() or intrpeek() */
345 scan_event_queue(0);
346#endif
Jack Jansene8e8ae01995-01-26 16:36:45 +0000347 return;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000348 }
Jack Jansene8e8ae01995-01-26 16:36:45 +0000349
Jack Jansenee23d6e1995-01-27 14:43:25 +0000350 in_foreground = PyMac_InForeground();
351 if ( in_foreground )
Jack Jansene8e8ae01995-01-26 16:36:45 +0000352 yield = yield_fg;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000353 else
354 yield = yield_bg;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000355 while ( 1 ) {
356 if ( no_waitnextevent ) {
357 SystemTask();
Jack Jansenee23d6e1995-01-27 14:43:25 +0000358 gotone = GetNextEvent(MAINLOOP_EVENTMASK, &ev);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000359 } else {
Jack Jansenee23d6e1995-01-27 14:43:25 +0000360 gotone = WaitNextEvent(MAINLOOP_EVENTMASK, &ev, yield, NULL);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000361 }
362 /* Get out quickly if nothing interesting is happening */
363 if ( !gotone || ev.what == nullEvent )
364 break;
Jack Jansena76382a1995-02-02 14:25:56 +0000365 PyMac_HandleEvent(&ev);
Jack Jansenf93c72a1994-12-14 14:07:50 +0000366 }
Jack Jansene8e8ae01995-01-26 16:36:45 +0000367 lastyield = TickCount();
368}
369
370/*
371** Yield the CPU to other tasks if opportune
372*/
373void
374PyMac_Yield() {
375 long iv;
376
Jack Jansenee23d6e1995-01-27 14:43:25 +0000377 if ( in_foreground )
Jack Jansene8e8ae01995-01-26 16:36:45 +0000378 iv = interval_fg;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000379 else
380 iv = interval_bg;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000381 if ( TickCount() > lastyield + iv )
382 PyMac_DoYield();
383}
384
385/*
386** Idle routine for busy-wait loops.
387** Gives up CPU, handles events and returns true if an interrupt is pending
388** (but not actually handled yet).
389*/
390int
391PyMac_Idle()
392{
393 PyMac_DoYield();
394 return intrpeek();
Jack Jansenf93c72a1994-12-14 14:07:50 +0000395}
Jack Jansen74162f31995-02-15 22:58:33 +0000396/*
397** Returns true if the argument has a resource fork, and it contains
398** a 'PYC ' resource of the correct name
399*/
400int
401PyMac_FindResourceModule(module, filename)
402char *module;
403char *filename;
404{
405 FSSpec fss;
406 FInfo finfo;
407 short oldrh, filerh;
408 int ok;
409 Handle h;
410
411 if ( FSMakeFSSpec(0, 0, Pstring(filename), &fss) != noErr )
412 return 0; /* It doesn't exist */
413 if ( FSpGetFInfo(&fss, &finfo) != noErr )
414 return 0; /* shouldn't happen, I guess */
Jack Jansen74162f31995-02-15 22:58:33 +0000415 oldrh = CurResFile();
416 filerh = FSpOpenResFile(&fss, fsRdPerm);
417 if ( filerh == -1 )
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000418 return 0;
Jack Jansen74162f31995-02-15 22:58:33 +0000419 UseResFile(filerh);
420 SetResLoad(0);
421 h = Get1NamedResource('PYC ', Pstring(module));
422 SetResLoad(1);
423 ok = (h != NULL);
424 CloseResFile(filerh);
425 UseResFile(oldrh);
426 return ok;
427}
428
429/*
430** Load the specified module from a resource
431*/
432PyObject *
433PyMac_LoadResourceModule(module, filename)
434char *module;
435char *filename;
436{
437 FSSpec fss;
438 FInfo finfo;
439 short oldrh, filerh;
Jack Jansen74162f31995-02-15 22:58:33 +0000440 Handle h;
441 OSErr err;
442 PyObject *m, *co;
443 long num, size;
444
445 if ( (err=FSMakeFSSpec(0, 0, Pstring(filename), &fss)) != noErr )
446 goto error;
447 if ( (err=FSpGetFInfo(&fss, &finfo)) != noErr )
448 goto error;
Jack Jansen74162f31995-02-15 22:58:33 +0000449 oldrh = CurResFile();
450 filerh = FSpOpenResFile(&fss, fsRdPerm);
451 if ( filerh == -1 ) {
452 err = ResError();
453 goto error;
454 }
455 UseResFile(filerh);
456 h = Get1NamedResource('PYC ', Pstring(module));
457 if ( h == NULL ) {
458 err = ResError();
459 goto error;
460 }
461 HLock(h);
462 /*
463 ** XXXX The next few lines are intimately tied to the format of pyc
464 ** files. I'm not sure whether this code should be here or in import.c -- Jack
465 */
466 size = GetHandleSize(h);
467 if ( size < 8 ) {
468 PyErr_SetString(PyExc_ImportError, "Resource too small");
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000469 co = NULL;
Jack Jansen74162f31995-02-15 22:58:33 +0000470 } else {
471 num = (*h)[0] & 0xff;
472 num = num | (((*h)[1] & 0xff) << 8);
473 num = num | (((*h)[2] & 0xff) << 16);
474 num = num | (((*h)[3] & 0xff) << 24);
475 if ( num != PyImport_GetMagicNumber() ) {
476 PyErr_SetString(PyExc_ImportError, "Bad MAGIC in resource");
477 co = NULL;
478 } else {
479 co = PyMarshal_ReadObjectFromString((*h)+8, size-8);
480 }
481 }
482 HUnlock(h);
483 CloseResFile(filerh);
484 UseResFile(oldrh);
485 if ( co ) {
486 m = PyImport_ExecCodeModule(module, co);
487 Py_DECREF(co);
488 } else {
489 m = NULL;
490 }
491 return m;
492error:
493 {
494 char buf[512];
495
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000496 sprintf(buf, "%s: %s", filename, PyMac_StrError(err));
Jack Jansen74162f31995-02-15 22:58:33 +0000497 PyErr_SetString(PyExc_ImportError, buf);
498 return NULL;
499 }
500}
Guido van Rossum24a45e31995-02-20 23:45:53 +0000501
Jack Jansen3ec804a1995-02-20 15:56:10 +0000502/*
503** Helper routine for GetDirectory
504*/
Guido van Rossum24a45e31995-02-20 23:45:53 +0000505static pascal short
Jack Jansen819f1771995-08-14 12:35:10 +0000506myhook_proc(short item, DialogPtr theDialog, struct hook_args *dataptr)
Jack Jansen3ec804a1995-02-20 15:56:10 +0000507{
Jack Jansen819f1771995-08-14 12:35:10 +0000508 if ( item == sfHookFirstCall && dataptr->prompt) {
509 Handle prompth;
510 short type;
511 Rect rect;
512
513 GetDialogItem(theDialog, PROMPT_ITEM, &type, &prompth, &rect);
514 if ( prompth )
515 SetDialogItemText(prompth, (unsigned char *)dataptr->prompt);
516 } else
Jack Jansen3ec804a1995-02-20 15:56:10 +0000517 if ( item == SELECTCUR_ITEM ) {
518 item = sfItemCancelButton;
Jack Jansen819f1771995-08-14 12:35:10 +0000519 dataptr->selectcur_hit = 1;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000520 }
521 return item;
522}
523
524/*
525** Ask the user for a directory. I still can't understand
526** why Apple doesn't provide a standard solution for this...
527*/
528int
Jack Jansen819f1771995-08-14 12:35:10 +0000529PyMac_GetDirectory(dirfss, prompt)
Jack Jansen3ec804a1995-02-20 15:56:10 +0000530 FSSpec *dirfss;
Jack Jansen819f1771995-08-14 12:35:10 +0000531 char *prompt;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000532{
533 static SFTypeList list = {'fldr', 0, 0, 0};
534 static Point where = {-1, -1};
Jack Jansen3ec804a1995-02-20 15:56:10 +0000535 StandardFileReply reply;
Jack Jansen819f1771995-08-14 12:35:10 +0000536 struct hook_args hook_args;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000537
538 if ( !upp_inited ) {
539 myhook_upp = NewDlgHookYDProc(myhook_proc);
540 upp_inited = 1;
541 }
Jack Jansen819f1771995-08-14 12:35:10 +0000542 if ( prompt && *prompt )
543 hook_args.prompt = (char *)Pstring(prompt);
544 else
545 hook_args.prompt = NULL;
546 hook_args.selectcur_hit = 0;
Guido van Rossum24a45e31995-02-20 23:45:53 +0000547 CustomGetFile((FileFilterYDUPP)0, 1, list, &reply, GETDIR_ID, where, myhook_upp,
Jack Jansen819f1771995-08-14 12:35:10 +0000548 NULL, NULL, NULL, (void *)&hook_args);
Jack Jansen3ec804a1995-02-20 15:56:10 +0000549
550 reply.sfFile.name[0] = 0;
551 if( FSMakeFSSpec(reply.sfFile.vRefNum, reply.sfFile.parID, reply.sfFile.name, dirfss) )
552 return 0;
Jack Jansen819f1771995-08-14 12:35:10 +0000553 return hook_args.selectcur_hit;
554}
555
556/*
557** Slightly extended StandardGetFile: accepts a prompt */
558void PyMac_PromptGetFile(short numTypes, ConstSFTypeListPtr typeList,
559 StandardFileReply *reply, char *prompt)
560{
561 static Point where = {-1, -1};
562 struct hook_args hook_args;
563
564 if ( !upp_inited ) {
565 myhook_upp = NewDlgHookYDProc(myhook_proc);
566 upp_inited = 1;
567 }
568 if ( prompt && *prompt )
569 hook_args.prompt = (char *)Pstring(prompt);
570 else
571 hook_args.prompt = NULL;
572 hook_args.selectcur_hit = 0;
573 CustomGetFile((FileFilterYDUPP)0, numTypes, typeList, reply, GETFILEPROMPT_ID, where,
574 myhook_upp, NULL, NULL, NULL, (void *)&hook_args);
Jack Jansen3ec804a1995-02-20 15:56:10 +0000575}
Jack Jansen5f653091995-01-18 13:53:49 +0000576
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000577/* Convert a 4-char string object argument to an OSType value */
Jack Jansen5f653091995-01-18 13:53:49 +0000578int
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000579PyMac_GetOSType(PyObject *v, OSType *pr)
Jack Jansen5f653091995-01-18 13:53:49 +0000580{
581 if (!PyString_Check(v) || PyString_Size(v) != 4) {
582 PyErr_SetString(PyExc_TypeError,
583 "OSType arg must be string of 4 chars");
584 return 0;
585 }
586 memcpy((char *)pr, PyString_AsString(v), 4);
587 return 1;
588}
589
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000590/* Convert an OSType value to a 4-char string object */
591PyObject *
592PyMac_BuildOSType(OSType t)
593{
594 return PyString_FromStringAndSize((char *)&t, 4);
595}
596
597
598/* Convert a Python string object to a Str255 */
Jack Jansen5f653091995-01-18 13:53:49 +0000599int
Guido van Rossum8f691791995-01-18 23:57:26 +0000600PyMac_GetStr255(PyObject *v, Str255 pbuf)
Jack Jansen5f653091995-01-18 13:53:49 +0000601{
602 int len;
603 if (!PyString_Check(v) || (len = PyString_Size(v)) > 255) {
604 PyErr_SetString(PyExc_TypeError,
605 "Str255 arg must be string of at most 255 chars");
606 return 0;
607 }
608 pbuf[0] = len;
609 memcpy((char *)(pbuf+1), PyString_AsString(v), len);
610 return 1;
611}
612
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000613/* Convert a Str255 to a Python string object */
614PyObject *
615PyMac_BuildStr255(Str255 s)
616{
617 return PyString_FromStringAndSize((char *)&s[1], (int)s[0]);
618}
619
620
Jack Jansen5f653091995-01-18 13:53:49 +0000621/*
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000622** Convert a Python object to an FSSpec.
623** The object may either be a full pathname or a triple
624** (vrefnum, dirid, path).
Jack Jansen5f653091995-01-18 13:53:49 +0000625** NOTE: This routine will fail on pre-sys7 machines.
626** The caller is responsible for not calling this routine
627** in those cases (which is fine, since everyone calling
628** this is probably sys7 dependent anyway).
629*/
630int
Guido van Rossum8f691791995-01-18 23:57:26 +0000631PyMac_GetFSSpec(PyObject *v, FSSpec *fs)
Jack Jansen5f653091995-01-18 13:53:49 +0000632{
633 Str255 path;
634 short refnum;
635 long parid;
636 OSErr err;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000637 FSSpec *fs2;
Jack Jansen5f653091995-01-18 13:53:49 +0000638
Jack Jansene8e8ae01995-01-26 16:36:45 +0000639 /* first check whether it already is an FSSpec */
640 fs2 = mfs_GetFSSpecFSSpec(v);
641 if ( fs2 ) {
Jack Jansen3ec804a1995-02-20 15:56:10 +0000642 (void)FSMakeFSSpec(fs2->vRefNum, fs2->parID, fs2->name, fs);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000643 return 1;
644 }
Jack Jansen5f653091995-01-18 13:53:49 +0000645 if ( PyString_Check(v) ) {
646 /* It's a pathname */
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000647 if( !PyArg_Parse(v, "O&", PyMac_GetStr255, &path) )
Jack Jansen5f653091995-01-18 13:53:49 +0000648 return 0;
649 refnum = 0; /* XXXX Should get CurWD here... */
650 parid = 0;
651 } else {
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000652 if( !PyArg_Parse(v, "(hlO&); FSSpec should be fullpath or (vrefnum,dirid,path)",
653 &refnum, &parid, PyMac_GetStr255, &path)) {
Jack Jansen5f653091995-01-18 13:53:49 +0000654 return 0;
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000655 }
Jack Jansen5f653091995-01-18 13:53:49 +0000656 }
657 err = FSMakeFSSpec(refnum, parid, path, fs);
658 if ( err && err != fnfErr ) {
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000659 PyErr_Mac(PyExc_ValueError, err);
Jack Jansen5f653091995-01-18 13:53:49 +0000660 return 0;
661 }
662 return 1;
663}
664
Guido van Rossum8f691791995-01-18 23:57:26 +0000665
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000666
667/* Convert a Python object to a Rect.
Guido van Rossum5279ec61995-01-26 22:56:59 +0000668 The object must be a (left, top, right, bottom) tuple.
669 (This differs from the order in the struct but is consistent with
670 the arguments to SetRect(), and also with STDWIN). */
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000671int
672PyMac_GetRect(PyObject *v, Rect *r)
Guido van Rossum8f691791995-01-18 23:57:26 +0000673{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000674 return PyArg_Parse(v, "(hhhh)", &r->left, &r->top, &r->right, &r->bottom);
Guido van Rossum8f691791995-01-18 23:57:26 +0000675}
Guido van Rossumb3404661995-01-22 18:36:13 +0000676
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000677/* Convert a Rect to a Python object */
Guido van Rossumb3404661995-01-22 18:36:13 +0000678PyObject *
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000679PyMac_BuildRect(Rect *r)
Guido van Rossumb3404661995-01-22 18:36:13 +0000680{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000681 return Py_BuildValue("(hhhh)", r->left, r->top, r->right, r->bottom);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000682}
683
684
685/* Convert a Python object to a Point.
Guido van Rossum5279ec61995-01-26 22:56:59 +0000686 The object must be a (h, v) tuple.
687 (This differs from the order in the struct but is consistent with
688 the arguments to SetPoint(), and also with STDWIN). */
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000689int
690PyMac_GetPoint(PyObject *v, Point *p)
691{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000692 return PyArg_Parse(v, "(hh)", &p->h, &p->v);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000693}
694
695/* Convert a Point to a Python object */
696PyObject *
697PyMac_BuildPoint(Point p)
698{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000699 return Py_BuildValue("(hh)", p.h, p.v);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000700}
701
702
703/* Convert a Python object to an EventRecord.
704 The object must be a (what, message, when, (v, h), modifiers) tuple. */
705int
706PyMac_GetEventRecord(PyObject *v, EventRecord *e)
707{
708 return PyArg_Parse(v, "(hll(hh)h)",
709 &e->what,
710 &e->message,
711 &e->when,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000712 &e->where.h,
Guido van Rossum5279ec61995-01-26 22:56:59 +0000713 &e->where.v,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000714 &e->modifiers);
715}
716
717/* Convert a Rect to an EventRecord object */
718PyObject *
719PyMac_BuildEventRecord(EventRecord *e)
720{
721 return Py_BuildValue("(hll(hh)h)",
722 e->what,
723 e->message,
724 e->when,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000725 e->where.h,
Guido van Rossum5279ec61995-01-26 22:56:59 +0000726 e->where.v,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000727 e->modifiers);
Guido van Rossumb3404661995-01-22 18:36:13 +0000728}