blob: c979e2a5dda37be09d8de67b0eacf7850128c635 [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"
28
29#include <OSUtils.h> /* for Set(Current)A5 */
Jack Jansene8e8ae01995-01-26 16:36:45 +000030#include <Files.h>
Jack Jansen8cd2b721995-02-13 11:33:28 +000031#include <Aliases.h>
Jack Jansen6cfab231995-02-13 22:46:00 +000032#include <Folders.h>
Jack Jansen8cd2b721995-02-13 11:33:28 +000033#include <StandardFile.h>
Jack Jansenf93c72a1994-12-14 14:07:50 +000034#include <Resources.h>
35#include <Memory.h>
36#include <Events.h>
37#include <Windows.h>
38#include <Desk.h>
Jack Jansene8e8ae01995-01-26 16:36:45 +000039#include <Traps.h>
Jack Jansenee23d6e1995-01-27 14:43:25 +000040#include <Processes.h>
Guido van Rossumcc0d8791995-01-30 08:57:13 +000041#ifdef THINK_C
42#include <OSEvents.h> /* For EvQElPtr */
43#endif
Jack Jansenee23d6e1995-01-27 14:43:25 +000044
45#include <signal.h>
Jack Jansene8e8ae01995-01-26 16:36:45 +000046
Jack Jansen8cd2b721995-02-13 11:33:28 +000047#define NOPYTHON_ALERT 128
48#define YES_ITEM 1
49#define NO_ITEM 2
50#define CURWD_ITEM 3
51
Jack Jansene8e8ae01995-01-26 16:36:45 +000052#ifdef __MWERKS__
Jack Jansenee23d6e1995-01-27 14:43:25 +000053/*
54** With MW we can pass the event off to the console window, so
55** we might as well handle all events.
56*/
Jack Jansene8e8ae01995-01-26 16:36:45 +000057#include <SIOUX.h>
Jack Jansenee23d6e1995-01-27 14:43:25 +000058#define MAINLOOP_EVENTMASK everyEvent
59#else
60/*
61** For other compilers we're more careful, since we can't handle
62** things like updates (and they'll keep coming back if we don't
63** handle them)
64*/
65#define MAINLOOP_EVENTMASK (mDownMask|keyDownMask|osMask)
Jack Jansene8e8ae01995-01-26 16:36:45 +000066#endif /* __MWERKS__ */
67
68#include <signal.h>
Jack Jansenf93c72a1994-12-14 14:07:50 +000069
Guido van Rossumb3404661995-01-22 18:36:13 +000070/* XXX We should include Errors.h here, but it has a name conflict
Jack Jansen5f653091995-01-18 13:53:49 +000071** with the python errors.h. */
72#define fnfErr -43
73
Jack Jansene8e8ae01995-01-26 16:36:45 +000074/* Declared in macfsmodule.c: */
75extern FSSpec *mfs_GetFSSpecFSSpec();
76
Jack Jansenee23d6e1995-01-27 14:43:25 +000077/* Interrupt code variables: */
78static int interrupted; /* Set to true when cmd-. seen */
79static RETSIGTYPE intcatcher Py_PROTO((int));
80
Jack Jansene8e8ae01995-01-26 16:36:45 +000081/*
82** We attempt to be a good citizen by giving up the CPU periodically.
83** When in the foreground we do this less often and for shorter periods
84** than when in the background. At this time we also check for events and
Jack Jansenee23d6e1995-01-27 14:43:25 +000085** pass them off to SIOUX, if compiling with mwerks.
Jack Jansene8e8ae01995-01-26 16:36:45 +000086** The counts here are in ticks of 1/60th second.
87** XXXX The initial values here are not based on anything.
88** FG-python gives up the cpu for 1/60th 5 times per second,
89** BG-python for .2 second 10 times per second.
90*/
91static long interval_fg = 12;
92static long interval_bg = 6;
93static long yield_fg = 1;
94static long yield_bg = 12;
Jack Jansenee23d6e1995-01-27 14:43:25 +000095static long lastyield;
96static int in_foreground;
97
98int PyMac_DoYieldEnabled = 1; /* Don't do eventloop when false */
99
Jack Jansene8e8ae01995-01-26 16:36:45 +0000100
Jack Jansen5f653091995-01-18 13:53:49 +0000101/* Convert C to Pascal string. Returns pointer to static buffer. */
102unsigned char *
103Pstring(char *str)
104{
105 static Str255 buf;
106 int len;
107
108 len = strlen(str);
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000109 if (len > 255)
110 len = 255;
Jack Jansen5f653091995-01-18 13:53:49 +0000111 buf[0] = (unsigned char)len;
112 strncpy((char *)buf+1, str, len);
113 return buf;
114}
115
Jack Jansenf93c72a1994-12-14 14:07:50 +0000116/* Replace strerror with something that might work */
117char *macstrerror(int err)
118{
119 static char buf[256];
120 Handle h;
121 char *str;
122
123 h = GetResource('Estr', err);
124 if ( h ) {
125 HLock(h);
126 str = (char *)*h;
127 memcpy(buf, str+1, (unsigned char)str[0]);
Guido van Rossumcc9bc8f1995-02-13 16:17:03 +0000128 buf[(unsigned char)str[0]] = '\0';
Jack Jansenf93c72a1994-12-14 14:07:50 +0000129 HUnlock(h);
130 ReleaseResource(h);
131 } else {
132 sprintf(buf, "Mac OS error code %d", err);
133 }
134 return buf;
135}
136
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000137/* Exception object shared by all Mac specific modules for Mac OS errors */
138PyObject *PyMac_OSErrException;
139
140/* Initialize and return PyMac_OSErrException */
141PyObject *
142PyMac_GetOSErrException()
143{
144 if (PyMac_OSErrException == NULL)
145 PyMac_OSErrException = PyString_FromString("Mac OS Error");
146 return PyMac_OSErrException;
147}
148
Jack Jansenf93c72a1994-12-14 14:07:50 +0000149/* Set a MAC-specific error from errno, and return NULL; return None if no error */
150PyObject *
Guido van Rossumfffb8bb1995-01-12 12:37:24 +0000151PyErr_Mac(PyObject *eobj, int err)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000152{
153 char *msg;
154 PyObject *v;
Jack Jansenf93c72a1994-12-14 14:07:50 +0000155
Guido van Rossum8f691791995-01-18 23:57:26 +0000156 if (err == 0 && !PyErr_Occurred()) {
Jack Jansenf93c72a1994-12-14 14:07:50 +0000157 Py_INCREF(Py_None);
158 return Py_None;
159 }
Guido van Rossum8f691791995-01-18 23:57:26 +0000160 if (err == -1 && PyErr_Occurred())
161 return NULL;
Jack Jansenf93c72a1994-12-14 14:07:50 +0000162 msg = macstrerror(err);
163 v = Py_BuildValue("(is)", err, msg);
164 PyErr_SetObject(eobj, v);
165 Py_DECREF(v);
166 return NULL;
167}
168
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000169/* Call PyErr_Mac with PyMac_OSErrException */
170PyObject *
171PyMac_Error(OSErr err)
172{
173 return PyErr_Mac(PyMac_GetOSErrException(), err);
174}
175
Jack Jansenee23d6e1995-01-27 14:43:25 +0000176/* The catcher routine (which may not be used for all compilers) */
177static RETSIGTYPE
178intcatcher(sig)
179 int sig;
180{
181 interrupted = 1;
182 signal(SIGINT, intcatcher);
183}
184
185void
186PyOS_InitInterrupts()
187{
188 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
189 signal(SIGINT, intcatcher);
190}
191
192/*
193** This routine scans the event queue looking for cmd-.
194** This is the only way to get an interrupt under THINK (since it
195** doesn't do SIGINT handling), but is also used under MW, when
196** the full-fledged event loop is disabled. This way, we can at least
197** interrupt a runaway python program.
198*/
199static void
200scan_event_queue(flush)
201 int flush;
202{
203 register EvQElPtr q;
204
205 q = (EvQElPtr) GetEvQHdr()->qHead;
206
207 for (; q; q = (EvQElPtr)q->qLink) {
208 if (q->evtQWhat == keyDown &&
209 (char)q->evtQMessage == '.' &&
210 (q->evtQModifiers & cmdKey) != 0) {
211 if ( flush )
212 FlushEvents(keyDownMask, 0);
213 interrupted = 1;
214 break;
215 }
216 }
217}
218
219int
220PyOS_InterruptOccurred()
221{
222#ifdef THINK_C
223 scan_event_queue(1);
224#endif
225 PyMac_Yield();
226 if (interrupted) {
227 interrupted = 0;
228 return 1;
229 }
230 return 0;
231}
232
233/* intrpeek() is like intrcheck(), but it doesn't flush the events. The
234** idea is that you call intrpeek() somewhere in a busy-wait loop, and return
235** None as soon as it returns 1. The mainloop will then pick up the cmd-. soon
236** thereafter.
237*/
238static int
239intrpeek()
240{
241#ifdef THINK_C
242 scan_event_queue(0);
243#endif
244 return interrupted;
245}
246
247/* Check whether we are in the foreground */
248int
249PyMac_InForeground()
250{
251 static ProcessSerialNumber ours;
252 static inited;
253 ProcessSerialNumber curfg;
254 Boolean eq;
255
256 if ( inited == 0 )
257 (void)GetCurrentProcess(&ours);
258 inited = 1;
259 if ( GetFrontProcess(&curfg) < 0 )
260 eq = 1;
261 else if ( SameProcess(&ours, &curfg, &eq) < 0 )
262 eq = 1;
263 return (int)eq;
264
265}
266
Jack Jansenf93c72a1994-12-14 14:07:50 +0000267/*
Jack Jansene8e8ae01995-01-26 16:36:45 +0000268** Set yield timeouts
Jack Jansenf93c72a1994-12-14 14:07:50 +0000269*/
Jack Jansene8e8ae01995-01-26 16:36:45 +0000270void
271PyMac_SetYield(long fgi, long fgy, long bgi, long bgy)
272{
273 interval_fg = fgi;
274 yield_fg = fgy;
275 interval_bg = bgi;
276 yield_bg = bgy;
277}
278
279/*
Jack Jansena76382a1995-02-02 14:25:56 +0000280** Handle an event, either one found in the mainloop eventhandler or
281** one passed back from the python program.
282*/
283void
284PyMac_HandleEvent(evp)
285 EventRecord *evp;
286{
287 WindowPtr wp;
288
289#ifdef __MWERKS__
290 /* If SIOUX wants it we're done */
291 (void)SIOUXHandleOneEvent(evp);
292#else
293 /* Other compilers are just unlucky: we only weed out clicks in other applications */
294 if ( evp->what == mouseDown ) {
295 if ( FindWindow(evp->where, &wp) == inSysWindow )
296 SystemClick(evp, wp);
297 }
298#endif /* !__MWERKS__ */
299}
300
301/*
Jack Jansene8e8ae01995-01-26 16:36:45 +0000302** Yield the CPU to other tasks.
303*/
304static
305PyMac_DoYield()
Jack Jansenf93c72a1994-12-14 14:07:50 +0000306{
307 EventRecord ev;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000308 long yield;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000309 static int no_waitnextevent = -1;
310 int gotone;
311
312 if ( no_waitnextevent < 0 ) {
313 no_waitnextevent = (NGetTrapAddress(_WaitNextEvent, ToolTrap) ==
314 NGetTrapAddress(_Unimplemented, ToolTrap));
315 }
Jack Jansenf93c72a1994-12-14 14:07:50 +0000316
Jack Jansenee23d6e1995-01-27 14:43:25 +0000317 if ( !PyMac_DoYieldEnabled ) {
318#ifndef THINK_C
319 /* Under think this has been done before in intrcheck() or intrpeek() */
320 scan_event_queue(0);
321#endif
Jack Jansene8e8ae01995-01-26 16:36:45 +0000322 return;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000323 }
Jack Jansene8e8ae01995-01-26 16:36:45 +0000324
Jack Jansenee23d6e1995-01-27 14:43:25 +0000325 in_foreground = PyMac_InForeground();
326 if ( in_foreground )
Jack Jansene8e8ae01995-01-26 16:36:45 +0000327 yield = yield_fg;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000328 else
329 yield = yield_bg;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000330 while ( 1 ) {
331 if ( no_waitnextevent ) {
332 SystemTask();
Jack Jansenee23d6e1995-01-27 14:43:25 +0000333 gotone = GetNextEvent(MAINLOOP_EVENTMASK, &ev);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000334 } else {
Jack Jansenee23d6e1995-01-27 14:43:25 +0000335 gotone = WaitNextEvent(MAINLOOP_EVENTMASK, &ev, yield, NULL);
Jack Jansene8e8ae01995-01-26 16:36:45 +0000336 }
337 /* Get out quickly if nothing interesting is happening */
338 if ( !gotone || ev.what == nullEvent )
339 break;
Jack Jansena76382a1995-02-02 14:25:56 +0000340 PyMac_HandleEvent(&ev);
Jack Jansenf93c72a1994-12-14 14:07:50 +0000341 }
Jack Jansene8e8ae01995-01-26 16:36:45 +0000342 lastyield = TickCount();
343}
344
345/*
346** Yield the CPU to other tasks if opportune
347*/
348void
349PyMac_Yield() {
350 long iv;
351
Jack Jansenee23d6e1995-01-27 14:43:25 +0000352 if ( in_foreground )
Jack Jansene8e8ae01995-01-26 16:36:45 +0000353 iv = interval_fg;
Jack Jansenee23d6e1995-01-27 14:43:25 +0000354 else
355 iv = interval_bg;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000356 if ( TickCount() > lastyield + iv )
357 PyMac_DoYield();
358}
359
360/*
361** Idle routine for busy-wait loops.
362** Gives up CPU, handles events and returns true if an interrupt is pending
363** (but not actually handled yet).
364*/
365int
366PyMac_Idle()
367{
368 PyMac_DoYield();
369 return intrpeek();
Jack Jansenf93c72a1994-12-14 14:07:50 +0000370}
371
Jack Jansen8cd2b721995-02-13 11:33:28 +0000372/*
373** Return the name of the Python directory
374*/
375char *
376PyMac_GetPythonDir()
377{
378 int item;
379 static char name[256];
380 AliasHandle handle;
381 FSSpec dirspec;
382 int ok = 0, exists = 0;
Jack Jansen6cfab231995-02-13 22:46:00 +0000383 Boolean modified = 0, cannotmodify = 0;
Jack Jansen8cd2b721995-02-13 11:33:28 +0000384 StandardFileReply sfreply;
Jack Jansen6cfab231995-02-13 22:46:00 +0000385 short oldrh, prefrh;
386 short prefdirRefNum;
387 long prefdirDirID;
Jack Jansen8cd2b721995-02-13 11:33:28 +0000388
Jack Jansen6cfab231995-02-13 22:46:00 +0000389 /*
390 ** Remember old resource file and try to open preferences file
391 ** in the preferences folder. If it doesn't exist we try to create
392 ** it. If anything fails here we limp on, but set cannotmodify so
393 ** we don't try to store things later on.
394 */
395 oldrh = CurResFile();
396 if ( FindFolder(kOnSystemDisk, 'pref', kDontCreateFolder, &prefdirRefNum,
397 &prefdirDirID) != noErr ) {
398 /* Something wrong with preferences folder */
399 cannotmodify = 1;
400 } else {
401 (void)FSMakeFSSpec(prefdirRefNum, prefdirDirID, "\pPython Preferences", &dirspec);
402 prefrh = FSpOpenResFile(&dirspec, fsRdWrShPerm);
403 if ( prefrh == -1 ) {
404 /* It doesn't exist. Try to create it */
Guido van Rossumbecdbec1995-02-14 01:27:24 +0000405 FSpCreateResFile(&dirspec, 'PYTH', 'pref', 0);
Jack Jansen6cfab231995-02-13 22:46:00 +0000406 prefrh = FSpOpenResFile(&dirspec, fsRdWrShPerm);
407 if ( prefrh == -1 ) {
408 cannotmodify = 1;
409 } else {
410 UseResFile(prefrh);
411 }
412 }
413 }
414 /* So, we've opened our preferences file, we hope. Look for the alias */
415 handle = (AliasHandle)Get1Resource('alis', 128);
Jack Jansen8cd2b721995-02-13 11:33:28 +0000416 if ( handle ) {
Jack Jansen6cfab231995-02-13 22:46:00 +0000417 /* It exists. Resolve it (possibly updating it) */
Jack Jansen8cd2b721995-02-13 11:33:28 +0000418 if ( ResolveAlias(NULL, handle, &dirspec, &modified) == noErr )
419 ok = 1;
420 exists = 1;
421 }
422 if ( !ok ) {
Jack Jansen6cfab231995-02-13 22:46:00 +0000423 /* No luck, so far. ask the user for help */
Jack Jansen8cd2b721995-02-13 11:33:28 +0000424 item = Alert(NOPYTHON_ALERT, NULL);
425 if ( item == YES_ITEM ) {
Jack Jansen6cfab231995-02-13 22:46:00 +0000426 /* The user wants to point us to a directory. Let her do so */
Jack Jansen8cd2b721995-02-13 11:33:28 +0000427 StandardGetFile(NULL, 0, NULL, &sfreply);
428 if ( sfreply.sfGood ) {
429 if ( sfreply.sfIsFolder ) {
430 dirspec = sfreply.sfFile;
431 ok = 1;
432 modified = 1;
433 } else {
434 /* User selected a file. Use folder containing it */
435 if (FSMakeFSSpec(sfreply.sfFile.vRefNum,
436 sfreply.sfFile.parID, "\p", &dirspec) == 0) {
437 ok = 1;
438 modified = 1;
439 }
440 }
441 }
442 } else if ( item == CURWD_ITEM ) {
Jack Jansen6cfab231995-02-13 22:46:00 +0000443 /* The user told us the current directory is fine. Build an FSSpec for it */
Jack Jansen8cd2b721995-02-13 11:33:28 +0000444 if ( getwd(name) ) {
445 if ( FSMakeFSSpec(0, 0, Pstring(name), &dirspec) == 0 ) {
446 ok = 1;
447 modified = 1;
448 }
449 }
450 }
451 }
Jack Jansen6cfab231995-02-13 22:46:00 +0000452 if ( ok && modified && !cannotmodify) {
453 /* We have a new, valid fsspec and we can update the preferences file. Do so. */
Jack Jansen8cd2b721995-02-13 11:33:28 +0000454 if ( !exists ) {
455 if (NewAlias(NULL, &dirspec, &handle) == 0 )
456 AddResource((Handle)handle, 'alis', 128, "\p");
457 } else {
458 ChangedResource((Handle)handle);
459 }
Jack Jansen6cfab231995-02-13 22:46:00 +0000460 UpdateResFile(prefrh);
Jack Jansen8cd2b721995-02-13 11:33:28 +0000461 }
Jack Jansen6cfab231995-02-13 22:46:00 +0000462 if ( !cannotmodify ) {
463 /* This means we have the resfile open. Close it. */
464 CloseResFile(prefrh);
465 }
466 /* Back to the old resource file */
467 UseResFile(oldrh);
468 /* Now turn the fsspec into a path to give back to our caller */
Jack Jansen8cd2b721995-02-13 11:33:28 +0000469 if ( ok ) {
470 ok = (nfullpath(&dirspec, name) == 0);
471 if ( ok ) strcat(name, ":");
472 }
473 if ( !ok ) {
474 /* If all fails, we return the current directory */
475 name[0] = 0;
476 (void)getwd(name);
477 }
478 return name;
479}
480
Jack Jansen5f653091995-01-18 13:53:49 +0000481
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000482/* Convert a 4-char string object argument to an OSType value */
Jack Jansen5f653091995-01-18 13:53:49 +0000483int
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000484PyMac_GetOSType(PyObject *v, OSType *pr)
Jack Jansen5f653091995-01-18 13:53:49 +0000485{
486 if (!PyString_Check(v) || PyString_Size(v) != 4) {
487 PyErr_SetString(PyExc_TypeError,
488 "OSType arg must be string of 4 chars");
489 return 0;
490 }
491 memcpy((char *)pr, PyString_AsString(v), 4);
492 return 1;
493}
494
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000495/* Convert an OSType value to a 4-char string object */
496PyObject *
497PyMac_BuildOSType(OSType t)
498{
499 return PyString_FromStringAndSize((char *)&t, 4);
500}
501
502
503/* Convert a Python string object to a Str255 */
Jack Jansen5f653091995-01-18 13:53:49 +0000504int
Guido van Rossum8f691791995-01-18 23:57:26 +0000505PyMac_GetStr255(PyObject *v, Str255 pbuf)
Jack Jansen5f653091995-01-18 13:53:49 +0000506{
507 int len;
508 if (!PyString_Check(v) || (len = PyString_Size(v)) > 255) {
509 PyErr_SetString(PyExc_TypeError,
510 "Str255 arg must be string of at most 255 chars");
511 return 0;
512 }
513 pbuf[0] = len;
514 memcpy((char *)(pbuf+1), PyString_AsString(v), len);
515 return 1;
516}
517
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000518/* Convert a Str255 to a Python string object */
519PyObject *
520PyMac_BuildStr255(Str255 s)
521{
522 return PyString_FromStringAndSize((char *)&s[1], (int)s[0]);
523}
524
525
Jack Jansen5f653091995-01-18 13:53:49 +0000526/*
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000527** Convert a Python object to an FSSpec.
528** The object may either be a full pathname or a triple
529** (vrefnum, dirid, path).
Jack Jansen5f653091995-01-18 13:53:49 +0000530** NOTE: This routine will fail on pre-sys7 machines.
531** The caller is responsible for not calling this routine
532** in those cases (which is fine, since everyone calling
533** this is probably sys7 dependent anyway).
534*/
535int
Guido van Rossum8f691791995-01-18 23:57:26 +0000536PyMac_GetFSSpec(PyObject *v, FSSpec *fs)
Jack Jansen5f653091995-01-18 13:53:49 +0000537{
538 Str255 path;
539 short refnum;
540 long parid;
541 OSErr err;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000542 FSSpec *fs2;
Jack Jansen5f653091995-01-18 13:53:49 +0000543
Jack Jansene8e8ae01995-01-26 16:36:45 +0000544 /* first check whether it already is an FSSpec */
545 fs2 = mfs_GetFSSpecFSSpec(v);
546 if ( fs2 ) {
547 fs = fs2;
548 return 1;
549 }
Jack Jansen5f653091995-01-18 13:53:49 +0000550 if ( PyString_Check(v) ) {
551 /* It's a pathname */
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000552 if( !PyArg_Parse(v, "O&", PyMac_GetStr255, &path) )
Jack Jansen5f653091995-01-18 13:53:49 +0000553 return 0;
554 refnum = 0; /* XXXX Should get CurWD here... */
555 parid = 0;
556 } else {
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000557 if( !PyArg_Parse(v, "(hlO&); FSSpec should be fullpath or (vrefnum,dirid,path)",
558 &refnum, &parid, PyMac_GetStr255, &path)) {
Jack Jansen5f653091995-01-18 13:53:49 +0000559 return 0;
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000560 }
Jack Jansen5f653091995-01-18 13:53:49 +0000561 }
562 err = FSMakeFSSpec(refnum, parid, path, fs);
563 if ( err && err != fnfErr ) {
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000564 PyErr_Mac(PyExc_ValueError, err);
Jack Jansen5f653091995-01-18 13:53:49 +0000565 return 0;
566 }
567 return 1;
568}
569
Guido van Rossum8f691791995-01-18 23:57:26 +0000570
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000571
572/* Convert a Python object to a Rect.
Guido van Rossum5279ec61995-01-26 22:56:59 +0000573 The object must be a (left, top, right, bottom) tuple.
574 (This differs from the order in the struct but is consistent with
575 the arguments to SetRect(), and also with STDWIN). */
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000576int
577PyMac_GetRect(PyObject *v, Rect *r)
Guido van Rossum8f691791995-01-18 23:57:26 +0000578{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000579 return PyArg_Parse(v, "(hhhh)", &r->left, &r->top, &r->right, &r->bottom);
Guido van Rossum8f691791995-01-18 23:57:26 +0000580}
Guido van Rossumb3404661995-01-22 18:36:13 +0000581
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000582/* Convert a Rect to a Python object */
Guido van Rossumb3404661995-01-22 18:36:13 +0000583PyObject *
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000584PyMac_BuildRect(Rect *r)
Guido van Rossumb3404661995-01-22 18:36:13 +0000585{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000586 return Py_BuildValue("(hhhh)", r->left, r->top, r->right, r->bottom);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000587}
588
589
590/* Convert a Python object to a Point.
Guido van Rossum5279ec61995-01-26 22:56:59 +0000591 The object must be a (h, v) tuple.
592 (This differs from the order in the struct but is consistent with
593 the arguments to SetPoint(), and also with STDWIN). */
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000594int
595PyMac_GetPoint(PyObject *v, Point *p)
596{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000597 return PyArg_Parse(v, "(hh)", &p->h, &p->v);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000598}
599
600/* Convert a Point to a Python object */
601PyObject *
602PyMac_BuildPoint(Point p)
603{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000604 return Py_BuildValue("(hh)", p.h, p.v);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000605}
606
607
608/* Convert a Python object to an EventRecord.
609 The object must be a (what, message, when, (v, h), modifiers) tuple. */
610int
611PyMac_GetEventRecord(PyObject *v, EventRecord *e)
612{
613 return PyArg_Parse(v, "(hll(hh)h)",
614 &e->what,
615 &e->message,
616 &e->when,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000617 &e->where.h,
Guido van Rossum5279ec61995-01-26 22:56:59 +0000618 &e->where.v,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000619 &e->modifiers);
620}
621
622/* Convert a Rect to an EventRecord object */
623PyObject *
624PyMac_BuildEventRecord(EventRecord *e)
625{
626 return Py_BuildValue("(hll(hh)h)",
627 e->what,
628 e->message,
629 e->when,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000630 e->where.h,
Guido van Rossum5279ec61995-01-26 22:56:59 +0000631 e->where.v,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000632 e->modifiers);
Guido van Rossumb3404661995-01-22 18:36:13 +0000633}