blob: 215accc6932dbef9d653d5bbe28528c5ee1eed83 [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
144 /* Set standard-file working directory */
145 LMSetSFSaveDisk(-curdirfss.vRefNum);
146 LMSetCurDirStore(curdirfss.parID);
147}
148#endif
149
Jack Jansen819f1771995-08-14 12:35:10 +0000150
Jack Jansen5f653091995-01-18 13:53:49 +0000151/* Convert C to Pascal string. Returns pointer to static buffer. */
152unsigned char *
153Pstring(char *str)
154{
155 static Str255 buf;
156 int len;
157
158 len = strlen(str);
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000159 if (len > 255)
160 len = 255;
Jack Jansen5f653091995-01-18 13:53:49 +0000161 buf[0] = (unsigned char)len;
162 strncpy((char *)buf+1, str, len);
163 return buf;
164}
165
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000166/* Like strerror() but for Mac OS error numbers */
167char *PyMac_StrError(int err)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000168{
169 static char buf[256];
170 Handle h;
171 char *str;
172
173 h = GetResource('Estr', err);
174 if ( h ) {
175 HLock(h);
176 str = (char *)*h;
177 memcpy(buf, str+1, (unsigned char)str[0]);
Guido van Rossumcc9bc8f1995-02-13 16:17:03 +0000178 buf[(unsigned char)str[0]] = '\0';
Jack Jansenf93c72a1994-12-14 14:07:50 +0000179 HUnlock(h);
180 ReleaseResource(h);
181 } else {
182 sprintf(buf, "Mac OS error code %d", err);
183 }
184 return buf;
185}
186
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000187/* Exception object shared by all Mac specific modules for Mac OS errors */
188PyObject *PyMac_OSErrException;
189
190/* Initialize and return PyMac_OSErrException */
191PyObject *
192PyMac_GetOSErrException()
193{
194 if (PyMac_OSErrException == NULL)
195 PyMac_OSErrException = PyString_FromString("Mac OS Error");
196 return PyMac_OSErrException;
197}
198
Jack Jansenf93c72a1994-12-14 14:07:50 +0000199/* Set a MAC-specific error from errno, and return NULL; return None if no error */
200PyObject *
Guido van Rossumfffb8bb1995-01-12 12:37:24 +0000201PyErr_Mac(PyObject *eobj, int err)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000202{
203 char *msg;
204 PyObject *v;
Jack Jansenf93c72a1994-12-14 14:07:50 +0000205
Guido van Rossum8f691791995-01-18 23:57:26 +0000206 if (err == 0 && !PyErr_Occurred()) {
Jack Jansenf93c72a1994-12-14 14:07:50 +0000207 Py_INCREF(Py_None);
208 return Py_None;
209 }
Guido van Rossum8f691791995-01-18 23:57:26 +0000210 if (err == -1 && PyErr_Occurred())
211 return NULL;
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000212 msg = PyMac_StrError(err);
Jack Jansenf93c72a1994-12-14 14:07:50 +0000213 v = Py_BuildValue("(is)", err, msg);
214 PyErr_SetObject(eobj, v);
215 Py_DECREF(v);
216 return NULL;
217}
218
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000219/* Call PyErr_Mac with PyMac_OSErrException */
220PyObject *
221PyMac_Error(OSErr err)
222{
223 return PyErr_Mac(PyMac_GetOSErrException(), err);
224}
225
Jack Jansenee23d6e1995-01-27 14:43:25 +0000226/* The catcher routine (which may not be used for all compilers) */
227static RETSIGTYPE
228intcatcher(sig)
229 int sig;
230{
231 interrupted = 1;
232 signal(SIGINT, intcatcher);
233}
234
235void
236PyOS_InitInterrupts()
237{
238 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
239 signal(SIGINT, intcatcher);
240}
241
242/*
243** This routine scans the event queue looking for cmd-.
244** This is the only way to get an interrupt under THINK (since it
245** doesn't do SIGINT handling), but is also used under MW, when
246** the full-fledged event loop is disabled. This way, we can at least
247** interrupt a runaway python program.
248*/
249static void
250scan_event_queue(flush)
251 int flush;
252{
Jack Jansenf74f63a1995-06-27 13:18:14 +0000253#if defined(__MWERKS__) && defined(__CFM68K__)
254 return; /* No GetEvQHdr yet */
255#else
Jack Jansenee23d6e1995-01-27 14:43:25 +0000256 register EvQElPtr q;
257
258 q = (EvQElPtr) GetEvQHdr()->qHead;
259
260 for (; q; q = (EvQElPtr)q->qLink) {
261 if (q->evtQWhat == keyDown &&
262 (char)q->evtQMessage == '.' &&
263 (q->evtQModifiers & cmdKey) != 0) {
264 if ( flush )
265 FlushEvents(keyDownMask, 0);
266 interrupted = 1;
267 break;
268 }
269 }
Jack Jansenf74f63a1995-06-27 13:18:14 +0000270#endif
Jack Jansenee23d6e1995-01-27 14:43:25 +0000271}
272
273int
274PyOS_InterruptOccurred()
275{
Guido van Rossume7134aa1995-02-26 10:20:53 +0000276 if (PyMac_DoYieldEnabled < 0)
277 return 0;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000278#ifdef THINK_C
279 scan_event_queue(1);
280#endif
281 PyMac_Yield();
282 if (interrupted) {
283 interrupted = 0;
284 return 1;
285 }
286 return 0;
287}
288
289/* intrpeek() is like intrcheck(), but it doesn't flush the events. The
290** idea is that you call intrpeek() somewhere in a busy-wait loop, and return
291** None as soon as it returns 1. The mainloop will then pick up the cmd-. soon
292** thereafter.
293*/
294static int
295intrpeek()
296{
297#ifdef THINK_C
298 scan_event_queue(0);
299#endif
300 return interrupted;
301}
302
303/* Check whether we are in the foreground */
304int
305PyMac_InForeground()
306{
307 static ProcessSerialNumber ours;
308 static inited;
309 ProcessSerialNumber curfg;
310 Boolean eq;
311
312 if ( inited == 0 )
313 (void)GetCurrentProcess(&ours);
314 inited = 1;
315 if ( GetFrontProcess(&curfg) < 0 )
316 eq = 1;
317 else if ( SameProcess(&ours, &curfg, &eq) < 0 )
318 eq = 1;
319 return (int)eq;
320
321}
322
Jack Jansenf93c72a1994-12-14 14:07:50 +0000323/*
Jack Jansene8e8ae01995-01-26 16:36:45 +0000324** Set yield timeouts
Jack Jansenf93c72a1994-12-14 14:07:50 +0000325*/
Jack Jansene8e8ae01995-01-26 16:36:45 +0000326void
327PyMac_SetYield(long fgi, long fgy, long bgi, long bgy)
328{
329 interval_fg = fgi;
330 yield_fg = fgy;
331 interval_bg = bgi;
332 yield_bg = bgy;
333}
334
335/*
Jack Jansena76382a1995-02-02 14:25:56 +0000336** Handle an event, either one found in the mainloop eventhandler or
337** one passed back from the python program.
338*/
339void
340PyMac_HandleEvent(evp)
341 EventRecord *evp;
342{
Jack Jansena76382a1995-02-02 14:25:56 +0000343
344#ifdef __MWERKS__
Jack Jansen38e97661995-11-10 14:53:00 +0000345 {
346 int siouxdidit;
347
348 /* If SIOUX wants it we're done */
349 siouxdidit = SIOUXHandleOneEvent(evp);
350 if ( siouxdidit )
351 return;
352 }
Jack Jansena76382a1995-02-02 14:25:56 +0000353#else
354 /* Other compilers are just unlucky: we only weed out clicks in other applications */
355 if ( evp->what == mouseDown ) {
Jack Jansen847e89e1995-08-31 13:57:40 +0000356 WindowPtr wp;
357
Jack Jansen38e97661995-11-10 14:53:00 +0000358 if ( FindWindow(evp->where, &wp) == inSysWindow ) {
Jack Jansena76382a1995-02-02 14:25:56 +0000359 SystemClick(evp, wp);
Jack Jansen38e97661995-11-10 14:53:00 +0000360 return;
361 }
Jack Jansena76382a1995-02-02 14:25:56 +0000362 }
363#endif /* !__MWERKS__ */
364}
365
366/*
Jack Jansene8e8ae01995-01-26 16:36:45 +0000367** Yield the CPU to other tasks.
368*/
369static
370PyMac_DoYield()
Jack Jansenf93c72a1994-12-14 14:07:50 +0000371{
372 EventRecord ev;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000373 long yield;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000374 static int no_waitnextevent = -1;
375 int gotone;
376
377 if ( no_waitnextevent < 0 ) {
378 no_waitnextevent = (NGetTrapAddress(_WaitNextEvent, ToolTrap) ==
379 NGetTrapAddress(_Unimplemented, ToolTrap));
380 }
Jack Jansenf93c72a1994-12-14 14:07:50 +0000381
Jack Jansenee23d6e1995-01-27 14:43:25 +0000382 if ( !PyMac_DoYieldEnabled ) {
383#ifndef THINK_C
384 /* Under think this has been done before in intrcheck() or intrpeek() */
385 scan_event_queue(0);
386#endif
Jack Jansene8e8ae01995-01-26 16:36:45 +0000387 return;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000388 }
Jack Jansene8e8ae01995-01-26 16:36:45 +0000389
Jack Jansenee23d6e1995-01-27 14:43:25 +0000390 in_foreground = PyMac_InForeground();
391 if ( in_foreground )
Jack Jansene8e8ae01995-01-26 16:36:45 +0000392 yield = yield_fg;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000393 else
394 yield = yield_bg;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000395 while ( 1 ) {
396 if ( no_waitnextevent ) {
397 SystemTask();
Jack Jansenee23d6e1995-01-27 14:43:25 +0000398 gotone = GetNextEvent(MAINLOOP_EVENTMASK, &ev);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000399 } else {
Jack Jansenee23d6e1995-01-27 14:43:25 +0000400 gotone = WaitNextEvent(MAINLOOP_EVENTMASK, &ev, yield, NULL);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000401 }
402 /* Get out quickly if nothing interesting is happening */
403 if ( !gotone || ev.what == nullEvent )
404 break;
Jack Jansena76382a1995-02-02 14:25:56 +0000405 PyMac_HandleEvent(&ev);
Jack Jansenf93c72a1994-12-14 14:07:50 +0000406 }
Jack Jansene8e8ae01995-01-26 16:36:45 +0000407 lastyield = TickCount();
408}
409
410/*
411** Yield the CPU to other tasks if opportune
412*/
413void
414PyMac_Yield() {
415 long iv;
416
Jack Jansenee23d6e1995-01-27 14:43:25 +0000417 if ( in_foreground )
Jack Jansene8e8ae01995-01-26 16:36:45 +0000418 iv = interval_fg;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000419 else
420 iv = interval_bg;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000421 if ( TickCount() > lastyield + iv )
422 PyMac_DoYield();
423}
424
425/*
426** Idle routine for busy-wait loops.
427** Gives up CPU, handles events and returns true if an interrupt is pending
428** (but not actually handled yet).
429*/
430int
431PyMac_Idle()
432{
433 PyMac_DoYield();
434 return intrpeek();
Jack Jansenf93c72a1994-12-14 14:07:50 +0000435}
Jack Jansen74162f31995-02-15 22:58:33 +0000436/*
437** Returns true if the argument has a resource fork, and it contains
438** a 'PYC ' resource of the correct name
439*/
440int
441PyMac_FindResourceModule(module, filename)
442char *module;
443char *filename;
444{
445 FSSpec fss;
446 FInfo finfo;
447 short oldrh, filerh;
448 int ok;
449 Handle h;
450
451 if ( FSMakeFSSpec(0, 0, Pstring(filename), &fss) != noErr )
452 return 0; /* It doesn't exist */
453 if ( FSpGetFInfo(&fss, &finfo) != noErr )
454 return 0; /* shouldn't happen, I guess */
Jack Jansen74162f31995-02-15 22:58:33 +0000455 oldrh = CurResFile();
456 filerh = FSpOpenResFile(&fss, fsRdPerm);
457 if ( filerh == -1 )
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000458 return 0;
Jack Jansen74162f31995-02-15 22:58:33 +0000459 UseResFile(filerh);
460 SetResLoad(0);
461 h = Get1NamedResource('PYC ', Pstring(module));
462 SetResLoad(1);
463 ok = (h != NULL);
464 CloseResFile(filerh);
465 UseResFile(oldrh);
466 return ok;
467}
468
469/*
470** Load the specified module from a resource
471*/
472PyObject *
473PyMac_LoadResourceModule(module, filename)
474char *module;
475char *filename;
476{
477 FSSpec fss;
478 FInfo finfo;
479 short oldrh, filerh;
Jack Jansen74162f31995-02-15 22:58:33 +0000480 Handle h;
481 OSErr err;
482 PyObject *m, *co;
483 long num, size;
484
485 if ( (err=FSMakeFSSpec(0, 0, Pstring(filename), &fss)) != noErr )
486 goto error;
487 if ( (err=FSpGetFInfo(&fss, &finfo)) != noErr )
488 goto error;
Jack Jansen74162f31995-02-15 22:58:33 +0000489 oldrh = CurResFile();
490 filerh = FSpOpenResFile(&fss, fsRdPerm);
491 if ( filerh == -1 ) {
492 err = ResError();
493 goto error;
494 }
495 UseResFile(filerh);
496 h = Get1NamedResource('PYC ', Pstring(module));
497 if ( h == NULL ) {
498 err = ResError();
499 goto error;
500 }
501 HLock(h);
502 /*
503 ** XXXX The next few lines are intimately tied to the format of pyc
504 ** files. I'm not sure whether this code should be here or in import.c -- Jack
505 */
506 size = GetHandleSize(h);
507 if ( size < 8 ) {
508 PyErr_SetString(PyExc_ImportError, "Resource too small");
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000509 co = NULL;
Jack Jansen74162f31995-02-15 22:58:33 +0000510 } else {
511 num = (*h)[0] & 0xff;
512 num = num | (((*h)[1] & 0xff) << 8);
513 num = num | (((*h)[2] & 0xff) << 16);
514 num = num | (((*h)[3] & 0xff) << 24);
515 if ( num != PyImport_GetMagicNumber() ) {
516 PyErr_SetString(PyExc_ImportError, "Bad MAGIC in resource");
517 co = NULL;
518 } else {
519 co = PyMarshal_ReadObjectFromString((*h)+8, size-8);
520 }
521 }
522 HUnlock(h);
523 CloseResFile(filerh);
524 UseResFile(oldrh);
525 if ( co ) {
526 m = PyImport_ExecCodeModule(module, co);
527 Py_DECREF(co);
528 } else {
529 m = NULL;
530 }
531 return m;
532error:
533 {
534 char buf[512];
535
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000536 sprintf(buf, "%s: %s", filename, PyMac_StrError(err));
Jack Jansen74162f31995-02-15 22:58:33 +0000537 PyErr_SetString(PyExc_ImportError, buf);
538 return NULL;
539 }
540}
Guido van Rossum24a45e31995-02-20 23:45:53 +0000541
Jack Jansen3ec804a1995-02-20 15:56:10 +0000542/*
543** Helper routine for GetDirectory
544*/
Guido van Rossum24a45e31995-02-20 23:45:53 +0000545static pascal short
Jack Jansen819f1771995-08-14 12:35:10 +0000546myhook_proc(short item, DialogPtr theDialog, struct hook_args *dataptr)
Jack Jansen3ec804a1995-02-20 15:56:10 +0000547{
Jack Jansen819f1771995-08-14 12:35:10 +0000548 if ( item == sfHookFirstCall && dataptr->prompt) {
549 Handle prompth;
550 short type;
551 Rect rect;
552
553 GetDialogItem(theDialog, PROMPT_ITEM, &type, &prompth, &rect);
554 if ( prompth )
555 SetDialogItemText(prompth, (unsigned char *)dataptr->prompt);
556 } else
Jack Jansen3ec804a1995-02-20 15:56:10 +0000557 if ( item == SELECTCUR_ITEM ) {
558 item = sfItemCancelButton;
Jack Jansen819f1771995-08-14 12:35:10 +0000559 dataptr->selectcur_hit = 1;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000560 }
561 return item;
562}
563
564/*
565** Ask the user for a directory. I still can't understand
566** why Apple doesn't provide a standard solution for this...
567*/
568int
Jack Jansen819f1771995-08-14 12:35:10 +0000569PyMac_GetDirectory(dirfss, prompt)
Jack Jansen3ec804a1995-02-20 15:56:10 +0000570 FSSpec *dirfss;
Jack Jansen819f1771995-08-14 12:35:10 +0000571 char *prompt;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000572{
573 static SFTypeList list = {'fldr', 0, 0, 0};
574 static Point where = {-1, -1};
Jack Jansen3ec804a1995-02-20 15:56:10 +0000575 StandardFileReply reply;
Jack Jansen819f1771995-08-14 12:35:10 +0000576 struct hook_args hook_args;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000577
578 if ( !upp_inited ) {
579 myhook_upp = NewDlgHookYDProc(myhook_proc);
580 upp_inited = 1;
581 }
Jack Jansen819f1771995-08-14 12:35:10 +0000582 if ( prompt && *prompt )
583 hook_args.prompt = (char *)Pstring(prompt);
584 else
585 hook_args.prompt = NULL;
586 hook_args.selectcur_hit = 0;
Guido van Rossum24a45e31995-02-20 23:45:53 +0000587 CustomGetFile((FileFilterYDUPP)0, 1, list, &reply, GETDIR_ID, where, myhook_upp,
Jack Jansen819f1771995-08-14 12:35:10 +0000588 NULL, NULL, NULL, (void *)&hook_args);
Jack Jansen3ec804a1995-02-20 15:56:10 +0000589
590 reply.sfFile.name[0] = 0;
591 if( FSMakeFSSpec(reply.sfFile.vRefNum, reply.sfFile.parID, reply.sfFile.name, dirfss) )
592 return 0;
Jack Jansen819f1771995-08-14 12:35:10 +0000593 return hook_args.selectcur_hit;
594}
595
596/*
597** Slightly extended StandardGetFile: accepts a prompt */
598void PyMac_PromptGetFile(short numTypes, ConstSFTypeListPtr typeList,
599 StandardFileReply *reply, char *prompt)
600{
601 static Point where = {-1, -1};
602 struct hook_args hook_args;
603
604 if ( !upp_inited ) {
605 myhook_upp = NewDlgHookYDProc(myhook_proc);
606 upp_inited = 1;
607 }
608 if ( prompt && *prompt )
609 hook_args.prompt = (char *)Pstring(prompt);
610 else
611 hook_args.prompt = NULL;
612 hook_args.selectcur_hit = 0;
613 CustomGetFile((FileFilterYDUPP)0, numTypes, typeList, reply, GETFILEPROMPT_ID, where,
614 myhook_upp, NULL, NULL, NULL, (void *)&hook_args);
Jack Jansen3ec804a1995-02-20 15:56:10 +0000615}
Jack Jansen5f653091995-01-18 13:53:49 +0000616
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000617/* Convert a 4-char string object argument to an OSType value */
Jack Jansen5f653091995-01-18 13:53:49 +0000618int
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000619PyMac_GetOSType(PyObject *v, OSType *pr)
Jack Jansen5f653091995-01-18 13:53:49 +0000620{
621 if (!PyString_Check(v) || PyString_Size(v) != 4) {
622 PyErr_SetString(PyExc_TypeError,
623 "OSType arg must be string of 4 chars");
624 return 0;
625 }
626 memcpy((char *)pr, PyString_AsString(v), 4);
627 return 1;
628}
629
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000630/* Convert an OSType value to a 4-char string object */
631PyObject *
632PyMac_BuildOSType(OSType t)
633{
634 return PyString_FromStringAndSize((char *)&t, 4);
635}
636
637
638/* Convert a Python string object to a Str255 */
Jack Jansen5f653091995-01-18 13:53:49 +0000639int
Guido van Rossum8f691791995-01-18 23:57:26 +0000640PyMac_GetStr255(PyObject *v, Str255 pbuf)
Jack Jansen5f653091995-01-18 13:53:49 +0000641{
642 int len;
643 if (!PyString_Check(v) || (len = PyString_Size(v)) > 255) {
644 PyErr_SetString(PyExc_TypeError,
645 "Str255 arg must be string of at most 255 chars");
646 return 0;
647 }
648 pbuf[0] = len;
649 memcpy((char *)(pbuf+1), PyString_AsString(v), len);
650 return 1;
651}
652
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000653/* Convert a Str255 to a Python string object */
654PyObject *
655PyMac_BuildStr255(Str255 s)
656{
657 return PyString_FromStringAndSize((char *)&s[1], (int)s[0]);
658}
659
660
Jack Jansen5f653091995-01-18 13:53:49 +0000661/*
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000662** Convert a Python object to an FSSpec.
663** The object may either be a full pathname or a triple
664** (vrefnum, dirid, path).
Jack Jansen5f653091995-01-18 13:53:49 +0000665** NOTE: This routine will fail on pre-sys7 machines.
666** The caller is responsible for not calling this routine
667** in those cases (which is fine, since everyone calling
668** this is probably sys7 dependent anyway).
669*/
670int
Guido van Rossum8f691791995-01-18 23:57:26 +0000671PyMac_GetFSSpec(PyObject *v, FSSpec *fs)
Jack Jansen5f653091995-01-18 13:53:49 +0000672{
673 Str255 path;
674 short refnum;
675 long parid;
676 OSErr err;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000677 FSSpec *fs2;
Jack Jansen5f653091995-01-18 13:53:49 +0000678
Jack Jansene8e8ae01995-01-26 16:36:45 +0000679 /* first check whether it already is an FSSpec */
680 fs2 = mfs_GetFSSpecFSSpec(v);
681 if ( fs2 ) {
Jack Jansen3ec804a1995-02-20 15:56:10 +0000682 (void)FSMakeFSSpec(fs2->vRefNum, fs2->parID, fs2->name, fs);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000683 return 1;
684 }
Jack Jansen5f653091995-01-18 13:53:49 +0000685 if ( PyString_Check(v) ) {
686 /* It's a pathname */
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000687 if( !PyArg_Parse(v, "O&", PyMac_GetStr255, &path) )
Jack Jansen5f653091995-01-18 13:53:49 +0000688 return 0;
Jack Jansen378815c1996-03-06 16:21:34 +0000689 refnum = 0; /* XXXX Should get CurWD here?? */
Jack Jansen5f653091995-01-18 13:53:49 +0000690 parid = 0;
691 } else {
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000692 if( !PyArg_Parse(v, "(hlO&); FSSpec should be fullpath or (vrefnum,dirid,path)",
693 &refnum, &parid, PyMac_GetStr255, &path)) {
Jack Jansen5f653091995-01-18 13:53:49 +0000694 return 0;
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000695 }
Jack Jansen5f653091995-01-18 13:53:49 +0000696 }
697 err = FSMakeFSSpec(refnum, parid, path, fs);
698 if ( err && err != fnfErr ) {
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000699 PyErr_Mac(PyExc_ValueError, err);
Jack Jansen5f653091995-01-18 13:53:49 +0000700 return 0;
701 }
702 return 1;
703}
704
Guido van Rossum8f691791995-01-18 23:57:26 +0000705
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000706/* Convert a Python object to a Rect.
Guido van Rossum5279ec61995-01-26 22:56:59 +0000707 The object must be a (left, top, right, bottom) tuple.
708 (This differs from the order in the struct but is consistent with
709 the arguments to SetRect(), and also with STDWIN). */
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000710int
711PyMac_GetRect(PyObject *v, Rect *r)
Guido van Rossum8f691791995-01-18 23:57:26 +0000712{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000713 return PyArg_Parse(v, "(hhhh)", &r->left, &r->top, &r->right, &r->bottom);
Guido van Rossum8f691791995-01-18 23:57:26 +0000714}
Guido van Rossumb3404661995-01-22 18:36:13 +0000715
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000716/* Convert a Rect to a Python object */
Guido van Rossumb3404661995-01-22 18:36:13 +0000717PyObject *
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000718PyMac_BuildRect(Rect *r)
Guido van Rossumb3404661995-01-22 18:36:13 +0000719{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000720 return Py_BuildValue("(hhhh)", r->left, r->top, r->right, r->bottom);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000721}
722
723
724/* Convert a Python object to a Point.
Guido van Rossum5279ec61995-01-26 22:56:59 +0000725 The object must be a (h, v) tuple.
726 (This differs from the order in the struct but is consistent with
727 the arguments to SetPoint(), and also with STDWIN). */
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000728int
729PyMac_GetPoint(PyObject *v, Point *p)
730{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000731 return PyArg_Parse(v, "(hh)", &p->h, &p->v);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000732}
733
734/* Convert a Point to a Python object */
735PyObject *
736PyMac_BuildPoint(Point p)
737{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000738 return Py_BuildValue("(hh)", p.h, p.v);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000739}
740
741
742/* Convert a Python object to an EventRecord.
743 The object must be a (what, message, when, (v, h), modifiers) tuple. */
744int
745PyMac_GetEventRecord(PyObject *v, EventRecord *e)
746{
747 return PyArg_Parse(v, "(hll(hh)h)",
748 &e->what,
749 &e->message,
750 &e->when,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000751 &e->where.h,
Guido van Rossum5279ec61995-01-26 22:56:59 +0000752 &e->where.v,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000753 &e->modifiers);
754}
755
756/* Convert a Rect to an EventRecord object */
757PyObject *
758PyMac_BuildEventRecord(EventRecord *e)
759{
760 return Py_BuildValue("(hll(hh)h)",
761 e->what,
762 e->message,
763 e->when,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000764 e->where.h,
Guido van Rossum5279ec61995-01-26 22:56:59 +0000765 e->where.v,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000766 e->modifiers);
Guido van Rossumb3404661995-01-22 18:36:13 +0000767}
Jack Jansenfa4d5d01995-11-15 15:19:29 +0000768
769/* Convert Python object to Fixed */
770int
771PyMac_GetFixed(PyObject *v, Fixed *f)
772{
773 double d;
774
775 if( !PyArg_Parse(v, "d", &d))
776 return 0;
777 *f = (Fixed)(d * 0x10000);
778}
779
780/* Convert a Point to a Python object */
781PyObject *
782PyMac_BuildFixed(Fixed f)
783{
784 double d;
785
786 d = f;
787 d = d / 0x10000;
788 return Py_BuildValue("d", d);
789}
790