blob: cab94cec6abbf0e6d906cfee441d2222f35b01ba [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
31#include <OSUtils.h> /* for Set(Current)A5 */
Jack Jansene8e8ae01995-01-26 16:36:45 +000032#include <Files.h>
Jack Jansen8cd2b721995-02-13 11:33:28 +000033#include <Aliases.h>
Jack Jansen6cfab231995-02-13 22:46:00 +000034#include <Folders.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>
Guido van Rossumcc0d8791995-01-30 08:57:13 +000045#ifdef THINK_C
46#include <OSEvents.h> /* For EvQElPtr */
47#endif
Jack Jansenee23d6e1995-01-27 14:43:25 +000048
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +000049#ifndef HAVE_UNIVERSAL_HEADERS
50#define GetResourceSizeOnDisk(x) SizeResource(x)
Guido van Rossum24a45e31995-02-20 23:45:53 +000051typedef DlgHookYDProcPtr DlgHookYDUPP;
52#define NewDlgHookYDProc(userRoutine) ((DlgHookYDUPP) (userRoutine))
53typedef FileFilterYDProcPtr FileFilterYDUPP;
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +000054#endif
55
Jack Jansenee23d6e1995-01-27 14:43:25 +000056#include <signal.h>
Jack Jansen74162f31995-02-15 22:58:33 +000057#include <stdio.h>
Jack Jansene8e8ae01995-01-26 16:36:45 +000058
Jack Jansen3ec804a1995-02-20 15:56:10 +000059/* The alert for "No Python directory, where is it?" */
Jack Jansen8cd2b721995-02-13 11:33:28 +000060#define NOPYTHON_ALERT 128
61#define YES_ITEM 1
62#define NO_ITEM 2
63#define CURWD_ITEM 3
64
Jack Jansen3ec804a1995-02-20 15:56:10 +000065/* The alert for "this is an applet template" */
66#define NOPYC_ALERT 129
67
68/* The dialog for our GetDirectory call */
69#define GETDIR_ID 130 /* Resource ID for our "get directory" */
70#define SELECTCUR_ITEM 10 /* "Select current directory" button */
71
Jack Jansene8e8ae01995-01-26 16:36:45 +000072#ifdef __MWERKS__
Jack Jansenee23d6e1995-01-27 14:43:25 +000073/*
74** With MW we can pass the event off to the console window, so
75** we might as well handle all events.
76*/
Jack Jansene8e8ae01995-01-26 16:36:45 +000077#include <SIOUX.h>
Jack Jansenee23d6e1995-01-27 14:43:25 +000078#define MAINLOOP_EVENTMASK everyEvent
79#else
80/*
81** For other compilers we're more careful, since we can't handle
82** things like updates (and they'll keep coming back if we don't
83** handle them)
84*/
85#define MAINLOOP_EVENTMASK (mDownMask|keyDownMask|osMask)
Jack Jansene8e8ae01995-01-26 16:36:45 +000086#endif /* __MWERKS__ */
87
88#include <signal.h>
Jack Jansenf93c72a1994-12-14 14:07:50 +000089
Guido van Rossumb3404661995-01-22 18:36:13 +000090/* XXX We should include Errors.h here, but it has a name conflict
Jack Jansen5f653091995-01-18 13:53:49 +000091** with the python errors.h. */
92#define fnfErr -43
93
Jack Jansene8e8ae01995-01-26 16:36:45 +000094/* Declared in macfsmodule.c: */
95extern FSSpec *mfs_GetFSSpecFSSpec();
96
Jack Jansenee23d6e1995-01-27 14:43:25 +000097/* Interrupt code variables: */
98static int interrupted; /* Set to true when cmd-. seen */
99static RETSIGTYPE intcatcher Py_PROTO((int));
100
Jack Jansene8e8ae01995-01-26 16:36:45 +0000101/*
102** We attempt to be a good citizen by giving up the CPU periodically.
103** When in the foreground we do this less often and for shorter periods
104** than when in the background. At this time we also check for events and
Jack Jansenee23d6e1995-01-27 14:43:25 +0000105** pass them off to SIOUX, if compiling with mwerks.
Jack Jansene8e8ae01995-01-26 16:36:45 +0000106** The counts here are in ticks of 1/60th second.
107** XXXX The initial values here are not based on anything.
108** FG-python gives up the cpu for 1/60th 5 times per second,
109** BG-python for .2 second 10 times per second.
110*/
111static long interval_fg = 12;
112static long interval_bg = 6;
113static long yield_fg = 1;
114static long yield_bg = 12;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000115static long lastyield;
116static int in_foreground;
117
118int PyMac_DoYieldEnabled = 1; /* Don't do eventloop when false */
119
Jack Jansene8e8ae01995-01-26 16:36:45 +0000120
Jack Jansen5f653091995-01-18 13:53:49 +0000121/* Convert C to Pascal string. Returns pointer to static buffer. */
122unsigned char *
123Pstring(char *str)
124{
125 static Str255 buf;
126 int len;
127
128 len = strlen(str);
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000129 if (len > 255)
130 len = 255;
Jack Jansen5f653091995-01-18 13:53:49 +0000131 buf[0] = (unsigned char)len;
132 strncpy((char *)buf+1, str, len);
133 return buf;
134}
135
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000136/* Like strerror() but for Mac OS error numbers */
137char *PyMac_StrError(int err)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000138{
139 static char buf[256];
140 Handle h;
141 char *str;
142
143 h = GetResource('Estr', err);
144 if ( h ) {
145 HLock(h);
146 str = (char *)*h;
147 memcpy(buf, str+1, (unsigned char)str[0]);
Guido van Rossumcc9bc8f1995-02-13 16:17:03 +0000148 buf[(unsigned char)str[0]] = '\0';
Jack Jansenf93c72a1994-12-14 14:07:50 +0000149 HUnlock(h);
150 ReleaseResource(h);
151 } else {
152 sprintf(buf, "Mac OS error code %d", err);
153 }
154 return buf;
155}
156
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000157/* Exception object shared by all Mac specific modules for Mac OS errors */
158PyObject *PyMac_OSErrException;
159
160/* Initialize and return PyMac_OSErrException */
161PyObject *
162PyMac_GetOSErrException()
163{
164 if (PyMac_OSErrException == NULL)
165 PyMac_OSErrException = PyString_FromString("Mac OS Error");
166 return PyMac_OSErrException;
167}
168
Jack Jansenf93c72a1994-12-14 14:07:50 +0000169/* Set a MAC-specific error from errno, and return NULL; return None if no error */
170PyObject *
Guido van Rossumfffb8bb1995-01-12 12:37:24 +0000171PyErr_Mac(PyObject *eobj, int err)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000172{
173 char *msg;
174 PyObject *v;
Jack Jansenf93c72a1994-12-14 14:07:50 +0000175
Guido van Rossum8f691791995-01-18 23:57:26 +0000176 if (err == 0 && !PyErr_Occurred()) {
Jack Jansenf93c72a1994-12-14 14:07:50 +0000177 Py_INCREF(Py_None);
178 return Py_None;
179 }
Guido van Rossum8f691791995-01-18 23:57:26 +0000180 if (err == -1 && PyErr_Occurred())
181 return NULL;
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000182 msg = PyMac_StrError(err);
Jack Jansenf93c72a1994-12-14 14:07:50 +0000183 v = Py_BuildValue("(is)", err, msg);
184 PyErr_SetObject(eobj, v);
185 Py_DECREF(v);
186 return NULL;
187}
188
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000189/* Call PyErr_Mac with PyMac_OSErrException */
190PyObject *
191PyMac_Error(OSErr err)
192{
193 return PyErr_Mac(PyMac_GetOSErrException(), err);
194}
195
Jack Jansenee23d6e1995-01-27 14:43:25 +0000196/* The catcher routine (which may not be used for all compilers) */
197static RETSIGTYPE
198intcatcher(sig)
199 int sig;
200{
201 interrupted = 1;
202 signal(SIGINT, intcatcher);
203}
204
205void
206PyOS_InitInterrupts()
207{
208 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
209 signal(SIGINT, intcatcher);
210}
211
212/*
213** This routine scans the event queue looking for cmd-.
214** This is the only way to get an interrupt under THINK (since it
215** doesn't do SIGINT handling), but is also used under MW, when
216** the full-fledged event loop is disabled. This way, we can at least
217** interrupt a runaway python program.
218*/
219static void
220scan_event_queue(flush)
221 int flush;
222{
223 register EvQElPtr q;
224
225 q = (EvQElPtr) GetEvQHdr()->qHead;
226
227 for (; q; q = (EvQElPtr)q->qLink) {
228 if (q->evtQWhat == keyDown &&
229 (char)q->evtQMessage == '.' &&
230 (q->evtQModifiers & cmdKey) != 0) {
231 if ( flush )
232 FlushEvents(keyDownMask, 0);
233 interrupted = 1;
234 break;
235 }
236 }
237}
238
239int
240PyOS_InterruptOccurred()
241{
242#ifdef THINK_C
243 scan_event_queue(1);
244#endif
245 PyMac_Yield();
246 if (interrupted) {
247 interrupted = 0;
248 return 1;
249 }
250 return 0;
251}
252
253/* intrpeek() is like intrcheck(), but it doesn't flush the events. The
254** idea is that you call intrpeek() somewhere in a busy-wait loop, and return
255** None as soon as it returns 1. The mainloop will then pick up the cmd-. soon
256** thereafter.
257*/
258static int
259intrpeek()
260{
261#ifdef THINK_C
262 scan_event_queue(0);
263#endif
264 return interrupted;
265}
266
267/* Check whether we are in the foreground */
268int
269PyMac_InForeground()
270{
271 static ProcessSerialNumber ours;
272 static inited;
273 ProcessSerialNumber curfg;
274 Boolean eq;
275
276 if ( inited == 0 )
277 (void)GetCurrentProcess(&ours);
278 inited = 1;
279 if ( GetFrontProcess(&curfg) < 0 )
280 eq = 1;
281 else if ( SameProcess(&ours, &curfg, &eq) < 0 )
282 eq = 1;
283 return (int)eq;
284
285}
286
Jack Jansenf93c72a1994-12-14 14:07:50 +0000287/*
Jack Jansene8e8ae01995-01-26 16:36:45 +0000288** Set yield timeouts
Jack Jansenf93c72a1994-12-14 14:07:50 +0000289*/
Jack Jansene8e8ae01995-01-26 16:36:45 +0000290void
291PyMac_SetYield(long fgi, long fgy, long bgi, long bgy)
292{
293 interval_fg = fgi;
294 yield_fg = fgy;
295 interval_bg = bgi;
296 yield_bg = bgy;
297}
298
299/*
Jack Jansena76382a1995-02-02 14:25:56 +0000300** Handle an event, either one found in the mainloop eventhandler or
301** one passed back from the python program.
302*/
303void
304PyMac_HandleEvent(evp)
305 EventRecord *evp;
306{
307 WindowPtr wp;
308
309#ifdef __MWERKS__
310 /* If SIOUX wants it we're done */
311 (void)SIOUXHandleOneEvent(evp);
312#else
313 /* Other compilers are just unlucky: we only weed out clicks in other applications */
314 if ( evp->what == mouseDown ) {
315 if ( FindWindow(evp->where, &wp) == inSysWindow )
316 SystemClick(evp, wp);
317 }
318#endif /* !__MWERKS__ */
319}
320
321/*
Jack Jansene8e8ae01995-01-26 16:36:45 +0000322** Yield the CPU to other tasks.
323*/
324static
325PyMac_DoYield()
Jack Jansenf93c72a1994-12-14 14:07:50 +0000326{
327 EventRecord ev;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000328 long yield;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000329 static int no_waitnextevent = -1;
330 int gotone;
331
332 if ( no_waitnextevent < 0 ) {
333 no_waitnextevent = (NGetTrapAddress(_WaitNextEvent, ToolTrap) ==
334 NGetTrapAddress(_Unimplemented, ToolTrap));
335 }
Jack Jansenf93c72a1994-12-14 14:07:50 +0000336
Jack Jansenee23d6e1995-01-27 14:43:25 +0000337 if ( !PyMac_DoYieldEnabled ) {
338#ifndef THINK_C
339 /* Under think this has been done before in intrcheck() or intrpeek() */
340 scan_event_queue(0);
341#endif
Jack Jansene8e8ae01995-01-26 16:36:45 +0000342 return;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000343 }
Jack Jansene8e8ae01995-01-26 16:36:45 +0000344
Jack Jansenee23d6e1995-01-27 14:43:25 +0000345 in_foreground = PyMac_InForeground();
346 if ( in_foreground )
Jack Jansene8e8ae01995-01-26 16:36:45 +0000347 yield = yield_fg;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000348 else
349 yield = yield_bg;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000350 while ( 1 ) {
351 if ( no_waitnextevent ) {
352 SystemTask();
Jack Jansenee23d6e1995-01-27 14:43:25 +0000353 gotone = GetNextEvent(MAINLOOP_EVENTMASK, &ev);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000354 } else {
Jack Jansenee23d6e1995-01-27 14:43:25 +0000355 gotone = WaitNextEvent(MAINLOOP_EVENTMASK, &ev, yield, NULL);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000356 }
357 /* Get out quickly if nothing interesting is happening */
358 if ( !gotone || ev.what == nullEvent )
359 break;
Jack Jansena76382a1995-02-02 14:25:56 +0000360 PyMac_HandleEvent(&ev);
Jack Jansenf93c72a1994-12-14 14:07:50 +0000361 }
Jack Jansene8e8ae01995-01-26 16:36:45 +0000362 lastyield = TickCount();
363}
364
365/*
366** Yield the CPU to other tasks if opportune
367*/
368void
369PyMac_Yield() {
370 long iv;
371
Jack Jansenee23d6e1995-01-27 14:43:25 +0000372 if ( in_foreground )
Jack Jansene8e8ae01995-01-26 16:36:45 +0000373 iv = interval_fg;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000374 else
375 iv = interval_bg;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000376 if ( TickCount() > lastyield + iv )
377 PyMac_DoYield();
378}
379
380/*
381** Idle routine for busy-wait loops.
382** Gives up CPU, handles events and returns true if an interrupt is pending
383** (but not actually handled yet).
384*/
385int
386PyMac_Idle()
387{
388 PyMac_DoYield();
389 return intrpeek();
Jack Jansenf93c72a1994-12-14 14:07:50 +0000390}
391
Jack Jansen8cd2b721995-02-13 11:33:28 +0000392/*
393** Return the name of the Python directory
394*/
395char *
396PyMac_GetPythonDir()
397{
398 int item;
399 static char name[256];
400 AliasHandle handle;
401 FSSpec dirspec;
402 int ok = 0, exists = 0;
Jack Jansen6cfab231995-02-13 22:46:00 +0000403 Boolean modified = 0, cannotmodify = 0;
Jack Jansen6cfab231995-02-13 22:46:00 +0000404 short oldrh, prefrh;
405 short prefdirRefNum;
406 long prefdirDirID;
Jack Jansen8cd2b721995-02-13 11:33:28 +0000407
Jack Jansen6cfab231995-02-13 22:46:00 +0000408 /*
409 ** Remember old resource file and try to open preferences file
410 ** in the preferences folder. If it doesn't exist we try to create
411 ** it. If anything fails here we limp on, but set cannotmodify so
412 ** we don't try to store things later on.
413 */
414 oldrh = CurResFile();
415 if ( FindFolder(kOnSystemDisk, 'pref', kDontCreateFolder, &prefdirRefNum,
416 &prefdirDirID) != noErr ) {
417 /* Something wrong with preferences folder */
418 cannotmodify = 1;
419 } else {
420 (void)FSMakeFSSpec(prefdirRefNum, prefdirDirID, "\pPython Preferences", &dirspec);
421 prefrh = FSpOpenResFile(&dirspec, fsRdWrShPerm);
422 if ( prefrh == -1 ) {
423 /* It doesn't exist. Try to create it */
Guido van Rossumbecdbec1995-02-14 01:27:24 +0000424 FSpCreateResFile(&dirspec, 'PYTH', 'pref', 0);
Jack Jansen6cfab231995-02-13 22:46:00 +0000425 prefrh = FSpOpenResFile(&dirspec, fsRdWrShPerm);
426 if ( prefrh == -1 ) {
427 cannotmodify = 1;
428 } else {
429 UseResFile(prefrh);
430 }
431 }
432 }
433 /* So, we've opened our preferences file, we hope. Look for the alias */
434 handle = (AliasHandle)Get1Resource('alis', 128);
Jack Jansen8cd2b721995-02-13 11:33:28 +0000435 if ( handle ) {
Jack Jansen6cfab231995-02-13 22:46:00 +0000436 /* It exists. Resolve it (possibly updating it) */
Jack Jansen8cd2b721995-02-13 11:33:28 +0000437 if ( ResolveAlias(NULL, handle, &dirspec, &modified) == noErr )
438 ok = 1;
439 exists = 1;
440 }
441 if ( !ok ) {
Jack Jansen6cfab231995-02-13 22:46:00 +0000442 /* No luck, so far. ask the user for help */
Jack Jansen8cd2b721995-02-13 11:33:28 +0000443 item = Alert(NOPYTHON_ALERT, NULL);
444 if ( item == YES_ITEM ) {
Jack Jansen6cfab231995-02-13 22:46:00 +0000445 /* The user wants to point us to a directory. Let her do so */
Jack Jansen3ec804a1995-02-20 15:56:10 +0000446 ok = PyMac_GetDirectory(&dirspec);
447 if ( ok )
448 modified = 1;
Jack Jansen8cd2b721995-02-13 11:33:28 +0000449 } else if ( item == CURWD_ITEM ) {
Jack Jansen6cfab231995-02-13 22:46:00 +0000450 /* The user told us the current directory is fine. Build an FSSpec for it */
Jack Jansen8cd2b721995-02-13 11:33:28 +0000451 if ( getwd(name) ) {
452 if ( FSMakeFSSpec(0, 0, Pstring(name), &dirspec) == 0 ) {
453 ok = 1;
454 modified = 1;
455 }
456 }
457 }
458 }
Jack Jansen6cfab231995-02-13 22:46:00 +0000459 if ( ok && modified && !cannotmodify) {
460 /* We have a new, valid fsspec and we can update the preferences file. Do so. */
Jack Jansen8cd2b721995-02-13 11:33:28 +0000461 if ( !exists ) {
462 if (NewAlias(NULL, &dirspec, &handle) == 0 )
463 AddResource((Handle)handle, 'alis', 128, "\p");
464 } else {
465 ChangedResource((Handle)handle);
466 }
Jack Jansen6cfab231995-02-13 22:46:00 +0000467 UpdateResFile(prefrh);
Jack Jansen8cd2b721995-02-13 11:33:28 +0000468 }
Jack Jansen6cfab231995-02-13 22:46:00 +0000469 if ( !cannotmodify ) {
470 /* This means we have the resfile open. Close it. */
471 CloseResFile(prefrh);
472 }
473 /* Back to the old resource file */
474 UseResFile(oldrh);
475 /* Now turn the fsspec into a path to give back to our caller */
Jack Jansen8cd2b721995-02-13 11:33:28 +0000476 if ( ok ) {
477 ok = (nfullpath(&dirspec, name) == 0);
478 if ( ok ) strcat(name, ":");
479 }
480 if ( !ok ) {
481 /* If all fails, we return the current directory */
482 name[0] = 0;
483 (void)getwd(name);
484 }
485 return name;
486}
487
Jack Jansen74162f31995-02-15 22:58:33 +0000488/*
489** Returns true if the argument has a resource fork, and it contains
490** a 'PYC ' resource of the correct name
491*/
492int
493PyMac_FindResourceModule(module, filename)
494char *module;
495char *filename;
496{
497 FSSpec fss;
498 FInfo finfo;
499 short oldrh, filerh;
500 int ok;
501 Handle h;
502
503 if ( FSMakeFSSpec(0, 0, Pstring(filename), &fss) != noErr )
504 return 0; /* It doesn't exist */
505 if ( FSpGetFInfo(&fss, &finfo) != noErr )
506 return 0; /* shouldn't happen, I guess */
Jack Jansen74162f31995-02-15 22:58:33 +0000507 oldrh = CurResFile();
508 filerh = FSpOpenResFile(&fss, fsRdPerm);
509 if ( filerh == -1 )
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000510 return 0;
Jack Jansen74162f31995-02-15 22:58:33 +0000511 UseResFile(filerh);
512 SetResLoad(0);
513 h = Get1NamedResource('PYC ', Pstring(module));
514 SetResLoad(1);
515 ok = (h != NULL);
516 CloseResFile(filerh);
517 UseResFile(oldrh);
518 return ok;
519}
520
521/*
522** Load the specified module from a resource
523*/
524PyObject *
525PyMac_LoadResourceModule(module, filename)
526char *module;
527char *filename;
528{
529 FSSpec fss;
530 FInfo finfo;
531 short oldrh, filerh;
532 int ok;
533 Handle h;
534 OSErr err;
535 PyObject *m, *co;
536 long num, size;
537
538 if ( (err=FSMakeFSSpec(0, 0, Pstring(filename), &fss)) != noErr )
539 goto error;
540 if ( (err=FSpGetFInfo(&fss, &finfo)) != noErr )
541 goto error;
Jack Jansen74162f31995-02-15 22:58:33 +0000542 oldrh = CurResFile();
543 filerh = FSpOpenResFile(&fss, fsRdPerm);
544 if ( filerh == -1 ) {
545 err = ResError();
546 goto error;
547 }
548 UseResFile(filerh);
549 h = Get1NamedResource('PYC ', Pstring(module));
550 if ( h == NULL ) {
551 err = ResError();
552 goto error;
553 }
554 HLock(h);
555 /*
556 ** XXXX The next few lines are intimately tied to the format of pyc
557 ** files. I'm not sure whether this code should be here or in import.c -- Jack
558 */
559 size = GetHandleSize(h);
560 if ( size < 8 ) {
561 PyErr_SetString(PyExc_ImportError, "Resource too small");
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000562 co = NULL;
Jack Jansen74162f31995-02-15 22:58:33 +0000563 } else {
564 num = (*h)[0] & 0xff;
565 num = num | (((*h)[1] & 0xff) << 8);
566 num = num | (((*h)[2] & 0xff) << 16);
567 num = num | (((*h)[3] & 0xff) << 24);
568 if ( num != PyImport_GetMagicNumber() ) {
569 PyErr_SetString(PyExc_ImportError, "Bad MAGIC in resource");
570 co = NULL;
571 } else {
572 co = PyMarshal_ReadObjectFromString((*h)+8, size-8);
573 }
574 }
575 HUnlock(h);
576 CloseResFile(filerh);
577 UseResFile(oldrh);
578 if ( co ) {
579 m = PyImport_ExecCodeModule(module, co);
580 Py_DECREF(co);
581 } else {
582 m = NULL;
583 }
584 return m;
585error:
586 {
587 char buf[512];
588
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000589 sprintf(buf, "%s: %s", filename, PyMac_StrError(err));
Jack Jansen74162f31995-02-15 22:58:33 +0000590 PyErr_SetString(PyExc_ImportError, buf);
591 return NULL;
592 }
593}
Guido van Rossum24a45e31995-02-20 23:45:53 +0000594
Jack Jansen3ec804a1995-02-20 15:56:10 +0000595/*
596** Helper routine for GetDirectory
597*/
Guido van Rossum24a45e31995-02-20 23:45:53 +0000598static pascal short
599myhook_proc(short item, DialogPtr theDialog, void *dataptr)
Jack Jansen3ec804a1995-02-20 15:56:10 +0000600{
601 if ( item == SELECTCUR_ITEM ) {
602 item = sfItemCancelButton;
603 * (int *)dataptr = 1;
604 }
605 return item;
606}
607
608/*
609** Ask the user for a directory. I still can't understand
610** why Apple doesn't provide a standard solution for this...
611*/
612int
613PyMac_GetDirectory(dirfss)
614 FSSpec *dirfss;
615{
616 static SFTypeList list = {'fldr', 0, 0, 0};
617 static Point where = {-1, -1};
618 static DlgHookYDUPP myhook_upp;
619 static int upp_inited = 0;
620 StandardFileReply reply;
621 int select_clicked = 0;
622
623 if ( !upp_inited ) {
624 myhook_upp = NewDlgHookYDProc(myhook_proc);
625 upp_inited = 1;
626 }
Guido van Rossum24a45e31995-02-20 23:45:53 +0000627 CustomGetFile((FileFilterYDUPP)0, 1, list, &reply, GETDIR_ID, where, myhook_upp,
Jack Jansen3ec804a1995-02-20 15:56:10 +0000628 NULL, NULL, NULL, (void *)&select_clicked);
629
630 reply.sfFile.name[0] = 0;
631 if( FSMakeFSSpec(reply.sfFile.vRefNum, reply.sfFile.parID, reply.sfFile.name, dirfss) )
632 return 0;
633 return select_clicked;
634}
Jack Jansen5f653091995-01-18 13:53:49 +0000635
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000636/* Convert a 4-char string object argument to an OSType value */
Jack Jansen5f653091995-01-18 13:53:49 +0000637int
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000638PyMac_GetOSType(PyObject *v, OSType *pr)
Jack Jansen5f653091995-01-18 13:53:49 +0000639{
640 if (!PyString_Check(v) || PyString_Size(v) != 4) {
641 PyErr_SetString(PyExc_TypeError,
642 "OSType arg must be string of 4 chars");
643 return 0;
644 }
645 memcpy((char *)pr, PyString_AsString(v), 4);
646 return 1;
647}
648
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000649/* Convert an OSType value to a 4-char string object */
650PyObject *
651PyMac_BuildOSType(OSType t)
652{
653 return PyString_FromStringAndSize((char *)&t, 4);
654}
655
656
657/* Convert a Python string object to a Str255 */
Jack Jansen5f653091995-01-18 13:53:49 +0000658int
Guido van Rossum8f691791995-01-18 23:57:26 +0000659PyMac_GetStr255(PyObject *v, Str255 pbuf)
Jack Jansen5f653091995-01-18 13:53:49 +0000660{
661 int len;
662 if (!PyString_Check(v) || (len = PyString_Size(v)) > 255) {
663 PyErr_SetString(PyExc_TypeError,
664 "Str255 arg must be string of at most 255 chars");
665 return 0;
666 }
667 pbuf[0] = len;
668 memcpy((char *)(pbuf+1), PyString_AsString(v), len);
669 return 1;
670}
671
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000672/* Convert a Str255 to a Python string object */
673PyObject *
674PyMac_BuildStr255(Str255 s)
675{
676 return PyString_FromStringAndSize((char *)&s[1], (int)s[0]);
677}
678
679
Jack Jansen5f653091995-01-18 13:53:49 +0000680/*
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000681** Convert a Python object to an FSSpec.
682** The object may either be a full pathname or a triple
683** (vrefnum, dirid, path).
Jack Jansen5f653091995-01-18 13:53:49 +0000684** NOTE: This routine will fail on pre-sys7 machines.
685** The caller is responsible for not calling this routine
686** in those cases (which is fine, since everyone calling
687** this is probably sys7 dependent anyway).
688*/
689int
Guido van Rossum8f691791995-01-18 23:57:26 +0000690PyMac_GetFSSpec(PyObject *v, FSSpec *fs)
Jack Jansen5f653091995-01-18 13:53:49 +0000691{
692 Str255 path;
693 short refnum;
694 long parid;
695 OSErr err;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000696 FSSpec *fs2;
Jack Jansen5f653091995-01-18 13:53:49 +0000697
Jack Jansene8e8ae01995-01-26 16:36:45 +0000698 /* first check whether it already is an FSSpec */
699 fs2 = mfs_GetFSSpecFSSpec(v);
700 if ( fs2 ) {
Jack Jansen3ec804a1995-02-20 15:56:10 +0000701 (void)FSMakeFSSpec(fs2->vRefNum, fs2->parID, fs2->name, fs);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000702 return 1;
703 }
Jack Jansen5f653091995-01-18 13:53:49 +0000704 if ( PyString_Check(v) ) {
705 /* It's a pathname */
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000706 if( !PyArg_Parse(v, "O&", PyMac_GetStr255, &path) )
Jack Jansen5f653091995-01-18 13:53:49 +0000707 return 0;
708 refnum = 0; /* XXXX Should get CurWD here... */
709 parid = 0;
710 } else {
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000711 if( !PyArg_Parse(v, "(hlO&); FSSpec should be fullpath or (vrefnum,dirid,path)",
712 &refnum, &parid, PyMac_GetStr255, &path)) {
Jack Jansen5f653091995-01-18 13:53:49 +0000713 return 0;
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000714 }
Jack Jansen5f653091995-01-18 13:53:49 +0000715 }
716 err = FSMakeFSSpec(refnum, parid, path, fs);
717 if ( err && err != fnfErr ) {
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000718 PyErr_Mac(PyExc_ValueError, err);
Jack Jansen5f653091995-01-18 13:53:49 +0000719 return 0;
720 }
721 return 1;
722}
723
Guido van Rossum8f691791995-01-18 23:57:26 +0000724
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000725
726/* Convert a Python object to a Rect.
Guido van Rossum5279ec61995-01-26 22:56:59 +0000727 The object must be a (left, top, right, bottom) tuple.
728 (This differs from the order in the struct but is consistent with
729 the arguments to SetRect(), and also with STDWIN). */
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000730int
731PyMac_GetRect(PyObject *v, Rect *r)
Guido van Rossum8f691791995-01-18 23:57:26 +0000732{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000733 return PyArg_Parse(v, "(hhhh)", &r->left, &r->top, &r->right, &r->bottom);
Guido van Rossum8f691791995-01-18 23:57:26 +0000734}
Guido van Rossumb3404661995-01-22 18:36:13 +0000735
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000736/* Convert a Rect to a Python object */
Guido van Rossumb3404661995-01-22 18:36:13 +0000737PyObject *
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000738PyMac_BuildRect(Rect *r)
Guido van Rossumb3404661995-01-22 18:36:13 +0000739{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000740 return Py_BuildValue("(hhhh)", r->left, r->top, r->right, r->bottom);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000741}
742
743
744/* Convert a Python object to a Point.
Guido van Rossum5279ec61995-01-26 22:56:59 +0000745 The object must be a (h, v) tuple.
746 (This differs from the order in the struct but is consistent with
747 the arguments to SetPoint(), and also with STDWIN). */
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000748int
749PyMac_GetPoint(PyObject *v, Point *p)
750{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000751 return PyArg_Parse(v, "(hh)", &p->h, &p->v);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000752}
753
754/* Convert a Point to a Python object */
755PyObject *
756PyMac_BuildPoint(Point p)
757{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000758 return Py_BuildValue("(hh)", p.h, p.v);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000759}
760
761
762/* Convert a Python object to an EventRecord.
763 The object must be a (what, message, when, (v, h), modifiers) tuple. */
764int
765PyMac_GetEventRecord(PyObject *v, EventRecord *e)
766{
767 return PyArg_Parse(v, "(hll(hh)h)",
768 &e->what,
769 &e->message,
770 &e->when,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000771 &e->where.h,
Guido van Rossum5279ec61995-01-26 22:56:59 +0000772 &e->where.v,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000773 &e->modifiers);
774}
775
776/* Convert a Rect to an EventRecord object */
777PyObject *
778PyMac_BuildEventRecord(EventRecord *e)
779{
780 return Py_BuildValue("(hll(hh)h)",
781 e->what,
782 e->message,
783 e->when,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000784 e->where.h,
Guido van Rossum5279ec61995-01-26 22:56:59 +0000785 e->where.v,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000786 e->modifiers);
Guido van Rossumb3404661995-01-22 18:36:13 +0000787}
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000788
789
Guido van Rossum24a45e31995-02-20 23:45:53 +0000790#ifndef USE_MAC_SHARED_LIBRARY
791
792/* For normal application */
793void
794main()
795{
796 int argc;
797 char **argv;
798
799#ifdef __MWERKS__
800 SIOUXSettings.asktosaveonclose = 0;
801 SIOUXSettings.showstatusline = 0;
802 SIOUXSettings.tabspaces = 4;
803#endif
804 argc = PyMac_GetArgv(&argv);
805 Py_Main(argc, argv);
806}
807
808#else /* USE_MAC_SHARED_LIBRARY */
809
Guido van Rossum8c89a6f1995-02-19 15:52:17 +0000810/* Applet support */
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000811
Guido van Rossum8c89a6f1995-02-19 15:52:17 +0000812/* Run a compiled Python Python script from 'PYC ' resource __main__ */
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000813static int
814run_main_resource()
815{
816 Handle h;
817 long size;
818 PyObject *code;
819 PyObject *result;
820
821 h = GetNamedResource('PYC ', "\p__main__");
822 if (h == NULL) {
Jack Jansen3ec804a1995-02-20 15:56:10 +0000823 Alert(NOPYC_ALERT, NULL);
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000824 return 1;
825 }
826 size = GetResourceSizeOnDisk(h);
827 HLock(h);
828 code = PyMarshal_ReadObjectFromString(*h + 8, (int)(size - 8));
829 HUnlock(h);
830 ReleaseResource(h);
831 if (code == NULL) {
832 PyErr_Print();
833 return 1;
834 }
835 result = PyImport_ExecCodeModule("__main__", code);
836 Py_DECREF(code);
837 if (result == NULL) {
838 PyErr_Print();
839 return 1;
840 }
841 Py_DECREF(result);
842 return 0;
843}
844
Guido van Rossum8c89a6f1995-02-19 15:52:17 +0000845/* Initialization sequence for applets */
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000846void
847PyMac_InitApplet()
848{
Guido van Rossum8c89a6f1995-02-19 15:52:17 +0000849 int argc;
850 char **argv;
Guido van Rossum24a45e31995-02-20 23:45:53 +0000851 int err;
Jack Jansen3ec804a1995-02-20 15:56:10 +0000852
Guido van Rossum24a45e31995-02-20 23:45:53 +0000853#ifdef USE_MAC_SHARED_LIBRARY
Jack Jansen3ec804a1995-02-20 15:56:10 +0000854 PyMac_AddLibResources();
Jack Jansen3ec804a1995-02-20 15:56:10 +0000855#endif
856#ifdef __MWERKS__
857 SIOUXSettings.asktosaveonclose = 0;
858 SIOUXSettings.showstatusline = 0;
859 SIOUXSettings.tabspaces = 4;
860#endif
Guido van Rossum8c89a6f1995-02-19 15:52:17 +0000861 argc = PyMac_GetArgv(&argv);
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000862 Py_Initialize();
Guido van Rossum8c89a6f1995-02-19 15:52:17 +0000863 PySys_SetArgv(argc, argv);
Jack Jansen3ec804a1995-02-20 15:56:10 +0000864 err = run_main_resource();
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000865 fflush(stderr);
866 fflush(stdout);
Jack Jansen3ec804a1995-02-20 15:56:10 +0000867#ifdef __MWERKS__
868 if (!err)
869 SIOUXSettings.autocloseonquit = 1;
870 else
871 SIOUXSettings.showstatusline = 1;
872#endif
Guido van Rossumc3d1c8e1995-02-18 15:01:31 +0000873 /* XXX Should we bother to Py_Exit(sts)? */
874}
Guido van Rossum24a45e31995-02-20 23:45:53 +0000875
876#endif /* USE_MAC_SHARED_LIBRARY */