blob: 2528e2538c858162b2e43834870b382e6967af24 [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__
Jack Jansen38e97661995-11-10 14:53:00 +0000313 {
314 int siouxdidit;
315
316 /* If SIOUX wants it we're done */
317 siouxdidit = SIOUXHandleOneEvent(evp);
318 if ( siouxdidit )
319 return;
320 }
Jack Jansena76382a1995-02-02 14:25:56 +0000321#else
322 /* Other compilers are just unlucky: we only weed out clicks in other applications */
323 if ( evp->what == mouseDown ) {
Jack Jansen847e89e1995-08-31 13:57:40 +0000324 WindowPtr wp;
325
Jack Jansen38e97661995-11-10 14:53:00 +0000326 if ( FindWindow(evp->where, &wp) == inSysWindow ) {
Jack Jansena76382a1995-02-02 14:25:56 +0000327 SystemClick(evp, wp);
Jack Jansen38e97661995-11-10 14:53:00 +0000328 return;
329 }
Jack Jansena76382a1995-02-02 14:25:56 +0000330 }
331#endif /* !__MWERKS__ */
332}
333
334/*
Jack Jansene8e8ae01995-01-26 16:36:45 +0000335** Yield the CPU to other tasks.
336*/
337static
338PyMac_DoYield()
Jack Jansenf93c72a1994-12-14 14:07:50 +0000339{
340 EventRecord ev;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000341 long yield;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000342 static int no_waitnextevent = -1;
343 int gotone;
344
345 if ( no_waitnextevent < 0 ) {
346 no_waitnextevent = (NGetTrapAddress(_WaitNextEvent, ToolTrap) ==
347 NGetTrapAddress(_Unimplemented, ToolTrap));
348 }
Jack Jansenf93c72a1994-12-14 14:07:50 +0000349
Jack Jansenee23d6e1995-01-27 14:43:25 +0000350 if ( !PyMac_DoYieldEnabled ) {
351#ifndef THINK_C
352 /* Under think this has been done before in intrcheck() or intrpeek() */
353 scan_event_queue(0);
354#endif
Jack Jansene8e8ae01995-01-26 16:36:45 +0000355 return;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000356 }
Jack Jansene8e8ae01995-01-26 16:36:45 +0000357
Jack Jansenee23d6e1995-01-27 14:43:25 +0000358 in_foreground = PyMac_InForeground();
359 if ( in_foreground )
Jack Jansene8e8ae01995-01-26 16:36:45 +0000360 yield = yield_fg;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000361 else
362 yield = yield_bg;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000363 while ( 1 ) {
364 if ( no_waitnextevent ) {
365 SystemTask();
Jack Jansenee23d6e1995-01-27 14:43:25 +0000366 gotone = GetNextEvent(MAINLOOP_EVENTMASK, &ev);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000367 } else {
Jack Jansenee23d6e1995-01-27 14:43:25 +0000368 gotone = WaitNextEvent(MAINLOOP_EVENTMASK, &ev, yield, NULL);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000369 }
370 /* Get out quickly if nothing interesting is happening */
371 if ( !gotone || ev.what == nullEvent )
372 break;
Jack Jansena76382a1995-02-02 14:25:56 +0000373 PyMac_HandleEvent(&ev);
Jack Jansenf93c72a1994-12-14 14:07:50 +0000374 }
Jack Jansene8e8ae01995-01-26 16:36:45 +0000375 lastyield = TickCount();
376}
377
378/*
379** Yield the CPU to other tasks if opportune
380*/
381void
382PyMac_Yield() {
383 long iv;
384
Jack Jansenee23d6e1995-01-27 14:43:25 +0000385 if ( in_foreground )
Jack Jansene8e8ae01995-01-26 16:36:45 +0000386 iv = interval_fg;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000387 else
388 iv = interval_bg;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000389 if ( TickCount() > lastyield + iv )
390 PyMac_DoYield();
391}
392
393/*
394** Idle routine for busy-wait loops.
395** Gives up CPU, handles events and returns true if an interrupt is pending
396** (but not actually handled yet).
397*/
398int
399PyMac_Idle()
400{
401 PyMac_DoYield();
402 return intrpeek();
Jack Jansenf93c72a1994-12-14 14:07:50 +0000403}
Jack Jansen74162f31995-02-15 22:58:33 +0000404/*
405** Returns true if the argument has a resource fork, and it contains
406** a 'PYC ' resource of the correct name
407*/
408int
409PyMac_FindResourceModule(module, filename)
410char *module;
411char *filename;
412{
413 FSSpec fss;
414 FInfo finfo;
415 short oldrh, filerh;
416 int ok;
417 Handle h;
418
419 if ( FSMakeFSSpec(0, 0, Pstring(filename), &fss) != noErr )
420 return 0; /* It doesn't exist */
421 if ( FSpGetFInfo(&fss, &finfo) != noErr )
422 return 0; /* shouldn't happen, I guess */
Jack Jansen74162f31995-02-15 22:58:33 +0000423 oldrh = CurResFile();
424 filerh = FSpOpenResFile(&fss, fsRdPerm);
425 if ( filerh == -1 )
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000426 return 0;
Jack Jansen74162f31995-02-15 22:58:33 +0000427 UseResFile(filerh);
428 SetResLoad(0);
429 h = Get1NamedResource('PYC ', Pstring(module));
430 SetResLoad(1);
431 ok = (h != NULL);
432 CloseResFile(filerh);
433 UseResFile(oldrh);
434 return ok;
435}
436
437/*
438** Load the specified module from a resource
439*/
440PyObject *
441PyMac_LoadResourceModule(module, filename)
442char *module;
443char *filename;
444{
445 FSSpec fss;
446 FInfo finfo;
447 short oldrh, filerh;
Jack Jansen74162f31995-02-15 22:58:33 +0000448 Handle h;
449 OSErr err;
450 PyObject *m, *co;
451 long num, size;
452
453 if ( (err=FSMakeFSSpec(0, 0, Pstring(filename), &fss)) != noErr )
454 goto error;
455 if ( (err=FSpGetFInfo(&fss, &finfo)) != noErr )
456 goto error;
Jack Jansen74162f31995-02-15 22:58:33 +0000457 oldrh = CurResFile();
458 filerh = FSpOpenResFile(&fss, fsRdPerm);
459 if ( filerh == -1 ) {
460 err = ResError();
461 goto error;
462 }
463 UseResFile(filerh);
464 h = Get1NamedResource('PYC ', Pstring(module));
465 if ( h == NULL ) {
466 err = ResError();
467 goto error;
468 }
469 HLock(h);
470 /*
471 ** XXXX The next few lines are intimately tied to the format of pyc
472 ** files. I'm not sure whether this code should be here or in import.c -- Jack
473 */
474 size = GetHandleSize(h);
475 if ( size < 8 ) {
476 PyErr_SetString(PyExc_ImportError, "Resource too small");
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000477 co = NULL;
Jack Jansen74162f31995-02-15 22:58:33 +0000478 } else {
479 num = (*h)[0] & 0xff;
480 num = num | (((*h)[1] & 0xff) << 8);
481 num = num | (((*h)[2] & 0xff) << 16);
482 num = num | (((*h)[3] & 0xff) << 24);
483 if ( num != PyImport_GetMagicNumber() ) {
484 PyErr_SetString(PyExc_ImportError, "Bad MAGIC in resource");
485 co = NULL;
486 } else {
487 co = PyMarshal_ReadObjectFromString((*h)+8, size-8);
488 }
489 }
490 HUnlock(h);
491 CloseResFile(filerh);
492 UseResFile(oldrh);
493 if ( co ) {
494 m = PyImport_ExecCodeModule(module, co);
495 Py_DECREF(co);
496 } else {
497 m = NULL;
498 }
499 return m;
500error:
501 {
502 char buf[512];
503
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000504 sprintf(buf, "%s: %s", filename, PyMac_StrError(err));
Jack Jansen74162f31995-02-15 22:58:33 +0000505 PyErr_SetString(PyExc_ImportError, buf);
506 return NULL;
507 }
508}
Guido van Rossum24a45e31995-02-20 23:45:53 +0000509
Jack Jansen3ec804a1995-02-20 15:56:10 +0000510/*
511** Helper routine for GetDirectory
512*/
Guido van Rossum24a45e31995-02-20 23:45:53 +0000513static pascal short
Jack Jansen819f1771995-08-14 12:35:10 +0000514myhook_proc(short item, DialogPtr theDialog, struct hook_args *dataptr)
Jack Jansen3ec804a1995-02-20 15:56:10 +0000515{
Jack Jansen819f1771995-08-14 12:35:10 +0000516 if ( item == sfHookFirstCall && dataptr->prompt) {
517 Handle prompth;
518 short type;
519 Rect rect;
520
521 GetDialogItem(theDialog, PROMPT_ITEM, &type, &prompth, &rect);
522 if ( prompth )
523 SetDialogItemText(prompth, (unsigned char *)dataptr->prompt);
524 } else
Jack Jansen3ec804a1995-02-20 15:56:10 +0000525 if ( item == SELECTCUR_ITEM ) {
526 item = sfItemCancelButton;
Jack Jansen819f1771995-08-14 12:35:10 +0000527 dataptr->selectcur_hit = 1;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000528 }
529 return item;
530}
531
532/*
533** Ask the user for a directory. I still can't understand
534** why Apple doesn't provide a standard solution for this...
535*/
536int
Jack Jansen819f1771995-08-14 12:35:10 +0000537PyMac_GetDirectory(dirfss, prompt)
Jack Jansen3ec804a1995-02-20 15:56:10 +0000538 FSSpec *dirfss;
Jack Jansen819f1771995-08-14 12:35:10 +0000539 char *prompt;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000540{
541 static SFTypeList list = {'fldr', 0, 0, 0};
542 static Point where = {-1, -1};
Jack Jansen3ec804a1995-02-20 15:56:10 +0000543 StandardFileReply reply;
Jack Jansen819f1771995-08-14 12:35:10 +0000544 struct hook_args hook_args;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000545
546 if ( !upp_inited ) {
547 myhook_upp = NewDlgHookYDProc(myhook_proc);
548 upp_inited = 1;
549 }
Jack Jansen819f1771995-08-14 12:35:10 +0000550 if ( prompt && *prompt )
551 hook_args.prompt = (char *)Pstring(prompt);
552 else
553 hook_args.prompt = NULL;
554 hook_args.selectcur_hit = 0;
Guido van Rossum24a45e31995-02-20 23:45:53 +0000555 CustomGetFile((FileFilterYDUPP)0, 1, list, &reply, GETDIR_ID, where, myhook_upp,
Jack Jansen819f1771995-08-14 12:35:10 +0000556 NULL, NULL, NULL, (void *)&hook_args);
Jack Jansen3ec804a1995-02-20 15:56:10 +0000557
558 reply.sfFile.name[0] = 0;
559 if( FSMakeFSSpec(reply.sfFile.vRefNum, reply.sfFile.parID, reply.sfFile.name, dirfss) )
560 return 0;
Jack Jansen819f1771995-08-14 12:35:10 +0000561 return hook_args.selectcur_hit;
562}
563
564/*
565** Slightly extended StandardGetFile: accepts a prompt */
566void PyMac_PromptGetFile(short numTypes, ConstSFTypeListPtr typeList,
567 StandardFileReply *reply, char *prompt)
568{
569 static Point where = {-1, -1};
570 struct hook_args hook_args;
571
572 if ( !upp_inited ) {
573 myhook_upp = NewDlgHookYDProc(myhook_proc);
574 upp_inited = 1;
575 }
576 if ( prompt && *prompt )
577 hook_args.prompt = (char *)Pstring(prompt);
578 else
579 hook_args.prompt = NULL;
580 hook_args.selectcur_hit = 0;
581 CustomGetFile((FileFilterYDUPP)0, numTypes, typeList, reply, GETFILEPROMPT_ID, where,
582 myhook_upp, NULL, NULL, NULL, (void *)&hook_args);
Jack Jansen3ec804a1995-02-20 15:56:10 +0000583}
Jack Jansen5f653091995-01-18 13:53:49 +0000584
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000585/* Convert a 4-char string object argument to an OSType value */
Jack Jansen5f653091995-01-18 13:53:49 +0000586int
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000587PyMac_GetOSType(PyObject *v, OSType *pr)
Jack Jansen5f653091995-01-18 13:53:49 +0000588{
589 if (!PyString_Check(v) || PyString_Size(v) != 4) {
590 PyErr_SetString(PyExc_TypeError,
591 "OSType arg must be string of 4 chars");
592 return 0;
593 }
594 memcpy((char *)pr, PyString_AsString(v), 4);
595 return 1;
596}
597
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000598/* Convert an OSType value to a 4-char string object */
599PyObject *
600PyMac_BuildOSType(OSType t)
601{
602 return PyString_FromStringAndSize((char *)&t, 4);
603}
604
605
606/* Convert a Python string object to a Str255 */
Jack Jansen5f653091995-01-18 13:53:49 +0000607int
Guido van Rossum8f691791995-01-18 23:57:26 +0000608PyMac_GetStr255(PyObject *v, Str255 pbuf)
Jack Jansen5f653091995-01-18 13:53:49 +0000609{
610 int len;
611 if (!PyString_Check(v) || (len = PyString_Size(v)) > 255) {
612 PyErr_SetString(PyExc_TypeError,
613 "Str255 arg must be string of at most 255 chars");
614 return 0;
615 }
616 pbuf[0] = len;
617 memcpy((char *)(pbuf+1), PyString_AsString(v), len);
618 return 1;
619}
620
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000621/* Convert a Str255 to a Python string object */
622PyObject *
623PyMac_BuildStr255(Str255 s)
624{
625 return PyString_FromStringAndSize((char *)&s[1], (int)s[0]);
626}
627
628
Jack Jansen5f653091995-01-18 13:53:49 +0000629/*
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000630** Convert a Python object to an FSSpec.
631** The object may either be a full pathname or a triple
632** (vrefnum, dirid, path).
Jack Jansen5f653091995-01-18 13:53:49 +0000633** NOTE: This routine will fail on pre-sys7 machines.
634** The caller is responsible for not calling this routine
635** in those cases (which is fine, since everyone calling
636** this is probably sys7 dependent anyway).
637*/
638int
Guido van Rossum8f691791995-01-18 23:57:26 +0000639PyMac_GetFSSpec(PyObject *v, FSSpec *fs)
Jack Jansen5f653091995-01-18 13:53:49 +0000640{
641 Str255 path;
642 short refnum;
643 long parid;
644 OSErr err;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000645 FSSpec *fs2;
Jack Jansen5f653091995-01-18 13:53:49 +0000646
Jack Jansene8e8ae01995-01-26 16:36:45 +0000647 /* first check whether it already is an FSSpec */
648 fs2 = mfs_GetFSSpecFSSpec(v);
649 if ( fs2 ) {
Jack Jansen3ec804a1995-02-20 15:56:10 +0000650 (void)FSMakeFSSpec(fs2->vRefNum, fs2->parID, fs2->name, fs);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000651 return 1;
652 }
Jack Jansen5f653091995-01-18 13:53:49 +0000653 if ( PyString_Check(v) ) {
654 /* It's a pathname */
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000655 if( !PyArg_Parse(v, "O&", PyMac_GetStr255, &path) )
Jack Jansen5f653091995-01-18 13:53:49 +0000656 return 0;
657 refnum = 0; /* XXXX Should get CurWD here... */
658 parid = 0;
659 } else {
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000660 if( !PyArg_Parse(v, "(hlO&); FSSpec should be fullpath or (vrefnum,dirid,path)",
661 &refnum, &parid, PyMac_GetStr255, &path)) {
Jack Jansen5f653091995-01-18 13:53:49 +0000662 return 0;
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000663 }
Jack Jansen5f653091995-01-18 13:53:49 +0000664 }
665 err = FSMakeFSSpec(refnum, parid, path, fs);
666 if ( err && err != fnfErr ) {
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000667 PyErr_Mac(PyExc_ValueError, err);
Jack Jansen5f653091995-01-18 13:53:49 +0000668 return 0;
669 }
670 return 1;
671}
672
Guido van Rossum8f691791995-01-18 23:57:26 +0000673
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000674
675/* Convert a Python object to a Rect.
Guido van Rossum5279ec61995-01-26 22:56:59 +0000676 The object must be a (left, top, right, bottom) tuple.
677 (This differs from the order in the struct but is consistent with
678 the arguments to SetRect(), and also with STDWIN). */
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000679int
680PyMac_GetRect(PyObject *v, Rect *r)
Guido van Rossum8f691791995-01-18 23:57:26 +0000681{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000682 return PyArg_Parse(v, "(hhhh)", &r->left, &r->top, &r->right, &r->bottom);
Guido van Rossum8f691791995-01-18 23:57:26 +0000683}
Guido van Rossumb3404661995-01-22 18:36:13 +0000684
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000685/* Convert a Rect to a Python object */
Guido van Rossumb3404661995-01-22 18:36:13 +0000686PyObject *
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000687PyMac_BuildRect(Rect *r)
Guido van Rossumb3404661995-01-22 18:36:13 +0000688{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000689 return Py_BuildValue("(hhhh)", r->left, r->top, r->right, r->bottom);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000690}
691
692
693/* Convert a Python object to a Point.
Guido van Rossum5279ec61995-01-26 22:56:59 +0000694 The object must be a (h, v) tuple.
695 (This differs from the order in the struct but is consistent with
696 the arguments to SetPoint(), and also with STDWIN). */
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000697int
698PyMac_GetPoint(PyObject *v, Point *p)
699{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000700 return PyArg_Parse(v, "(hh)", &p->h, &p->v);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000701}
702
703/* Convert a Point to a Python object */
704PyObject *
705PyMac_BuildPoint(Point p)
706{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000707 return Py_BuildValue("(hh)", p.h, p.v);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000708}
709
710
711/* Convert a Python object to an EventRecord.
712 The object must be a (what, message, when, (v, h), modifiers) tuple. */
713int
714PyMac_GetEventRecord(PyObject *v, EventRecord *e)
715{
716 return PyArg_Parse(v, "(hll(hh)h)",
717 &e->what,
718 &e->message,
719 &e->when,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000720 &e->where.h,
Guido van Rossum5279ec61995-01-26 22:56:59 +0000721 &e->where.v,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000722 &e->modifiers);
723}
724
725/* Convert a Rect to an EventRecord object */
726PyObject *
727PyMac_BuildEventRecord(EventRecord *e)
728{
729 return Py_BuildValue("(hll(hh)h)",
730 e->what,
731 e->message,
732 e->when,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000733 e->where.h,
Guido van Rossum5279ec61995-01-26 22:56:59 +0000734 e->where.v,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000735 e->modifiers);
Guido van Rossumb3404661995-01-22 18:36:13 +0000736}