Fix an amazing number of typos & malformed sentences reported by Detlef
[python/dscho.git] / Mac / Python / macglue.c
blobfa27c79c4ff8b25ef04ad3d67d05b181333ca91c
1 /***********************************************************
2 Copyright 1991-1997 by Stichting Mathematisch Centrum, Amsterdam,
3 The Netherlands.
5 All Rights Reserved
7 Permission to use, copy, modify, and distribute this software and its
8 documentation for any purpose and without fee is hereby granted,
9 provided that the above copyright notice appear in all copies and that
10 both that copyright notice and this permission notice appear in
11 supporting documentation, and that the names of Stichting Mathematisch
12 Centrum or CWI not be used in advertising or publicity pertaining to
13 distribution of the software without specific, written prior permission.
15 STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16 THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18 FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21 OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 ******************************************************************/
25 #ifdef __CFM68K__
26 /* cfm68k InterfaceLib exports GetEventQueue, but Events.h doesn't know this
27 ** and defines it as GetEvQHdr (which is correct for PPC). This fix is for
28 ** CW9, check that the workaround is still needed for the next release.
30 #define GetEvQHdr GetEventQueue
31 #endif /* __CFM68K__ */
33 #include <Events.h>
35 #ifdef __CFM68K__
36 #undef GetEventQueue
37 #endif /* __CFM68K__ */
39 #include "Python.h"
41 #include "macglue.h"
42 #include "marshal.h"
43 #include "import.h"
44 #include "importdl.h"
46 #include "pythonresources.h"
48 #include <OSUtils.h> /* for Set(Current)A5 */
49 #include <Files.h>
50 #include <StandardFile.h>
51 #include <Resources.h>
52 #include <Memory.h>
53 #include <Windows.h>
54 #include <Traps.h>
55 #include <Processes.h>
56 #include <Fonts.h>
57 #include <Menus.h>
58 #include <TextUtils.h>
59 #ifdef THINK_C
60 #include <OSEvents.h> /* For EvQElPtr */
61 #endif
62 #ifdef __MWERKS__
63 #include <SIOUX.h>
64 #endif
65 #ifdef USE_GUSI
66 #include <TFileSpec.h> /* For Path2FSSpec */
67 #include <LowMem.h> /* For SetSFCurDir, etc */
68 #include <GUSI.h>
69 #endif
71 /* The ID of the Sioux apple menu */
72 #define SIOUX_APPLEID 32000
74 #include <signal.h>
75 #include <stdio.h>
78 ** When less than this amount of stackspace is left we
79 ** raise a MemoryError.
81 #ifndef MINIMUM_STACK_SIZE
82 #ifdef __powerc
83 #define MINIMUM_STACK_SIZE 8192
84 #else
85 #define MINIMUM_STACK_SIZE 4096
86 #endif
87 #endif
90 ** We have to be careful, since we can't handle
91 ** things like updates (and they'll keep coming back if we don't
92 ** handle them). Note that we don't know who has windows open, so
93 ** even handing updates off to SIOUX under MW isn't going to work.
95 #define MAINLOOP_EVENTMASK (mDownMask|keyDownMask|osMask|activMask)
97 #include <signal.h>
99 /* XXX We should include Errors.h here, but it has a name conflict
100 ** with the python errors.h. */
101 #define fnfErr -43
103 /* Declared in macfsmodule.c: */
104 extern FSSpec *mfs_GetFSSpecFSSpec();
106 /* Interrupt code variables: */
107 static int interrupted; /* Set to true when cmd-. seen */
108 static RETSIGTYPE intcatcher Py_PROTO((int));
110 static int PyMac_DoYield Py_PROTO((int, int));
111 static int PyMac_Yield Py_PROTO((void));
114 ** These are the real scheduling parameters that control what we check
115 ** in the event loop, and how often we check. The values are initialized
116 ** from pyMac_SchedParamStruct.
119 struct real_sched_param_struct {
120 int check_interrupt; /* if true check for command-dot */
121 int process_events; /* if nonzero enable evt processing, this mask */
122 int besocial; /* if nonzero be a little social with CPU */
123 unsigned long check_interval; /* how often to check, in ticks */
124 unsigned long bg_yield; /* yield so long when in background */
125 /* these are computed from previous and clock and such */
126 int enabled; /* check_interrupt OR process_event OR yield */
127 unsigned long next_check; /* when to check/yield next, in ticks */
130 static struct real_sched_param_struct schedparams =
131 { 1, MAINLOOP_EVENTMASK, 1, 15, 15, 1, 0};
134 ** Workaround for sioux/gusi combo: set when we are exiting
136 int PyMac_ConsoleIsDead;
139 ** Sioux menu bar, saved early so we can restore it
141 static Handle sioux_mbar;
144 ** Some stuff for our GetDirectory and PromptGetFile routines
146 struct hook_args {
147 int selectcur_hit; /* Set to true when "select current" selected */
148 char *prompt; /* The prompt */
150 static DlgHookYDUPP myhook_upp;
151 static int upp_inited = 0;
154 ** The python-code event handler
156 static PyObject *python_event_handler;
158 #ifdef USE_GUSI
160 ** GUSI (1.6.0 and earlier, at the least) do not set the MacOS idea of
161 ** the working directory. Hence, we call this routine after each call
162 ** to chdir() to rectify things.
164 void
165 PyMac_FixGUSIcd()
167 WDPBRec pb;
168 FSSpec curdirfss;
170 if ( Path2FSSpec(":x", &curdirfss) != noErr )
171 return;
173 /* Set MacOS "working directory" */
174 pb.ioNamePtr= "\p";
175 pb.ioVRefNum= curdirfss.vRefNum;
176 pb.ioWDDirID= curdirfss.parID;
177 if (PBHSetVolSync(&pb) != noErr)
178 return;
182 ** SpinCursor (needed by GUSI) drags in heaps of stuff, so we
183 ** provide a dummy here.
185 void SpinCursor(short x) { /* Dummy */ }
186 void RotateCursor(short x) { /* Dummy */ }
189 ** Replacement GUSI Spin function
191 static int
192 PyMac_GUSISpin(spin_msg msg, long arg)
194 static Boolean inForeground = true;
195 int maxsleep = 6; /* 6 ticks is "normal" sleeptime */
197 if (PyMac_ConsoleIsDead) return 0;
198 #if 0
199 if (inForeground)
200 SpinCursor(msg == SP_AUTO_SPIN ? short(arg) : 1);
201 #endif
203 if (interrupted) return -1;
205 if ( msg == SP_AUTO_SPIN )
206 maxsleep = 0;
207 if ( msg==SP_SLEEP||msg==SP_SELECT )
208 maxsleep = arg;
210 PyMac_DoYield(maxsleep, 0); /* XXXX or is it safe to call python here? */
212 return 0;
215 void
216 PyMac_SetGUSISpin() {
217 GUSISetHook(GUSI_SpinHook, (GUSIHook)PyMac_GUSISpin);
220 /* Called at exit() time thru atexit(), to stop event processing */
221 void
222 PyMac_StopGUSISpin() {
223 PyMac_ConsoleIsDead = 1;
227 ** Replacement routines for the PLstr... functions so we don't need
228 ** StdCLib. Moreover, that implementation is broken under cfm68k...
230 void
231 PLstrcpy(to, fr)
232 unsigned char *to, *fr;
234 memcpy(to, fr, fr[0]+1);
238 PLstrcmp(s1, s2)
239 unsigned char *s1, *s2;
241 int res;
242 int l = s1[0] < s2[0] ? s1[0] : s2[0];
244 res = memcmp(s1+1, s2+1, l);
245 if ( res != 0 )
246 return res;
248 if ( s1[0] < s2[0] )
249 return -1;
250 else if ( s1[0] > s2[0] )
251 return 1;
252 else
253 return 0;
256 unsigned char *
257 PLstrrchr(str, chr)
258 unsigned char *str;
259 unsigned char chr;
261 unsigned char *ptr = 0;
262 unsigned char *p;
264 for(p=str+1; p<str+str[0]; p++)
265 if ( *p == chr )
266 ptr = p;
267 return ptr;
270 #endif /* USE_GUSI */
273 /* Convert C to Pascal string. Returns pointer to static buffer. */
274 unsigned char *
275 Pstring(char *str)
277 static Str255 buf;
278 int len;
280 len = strlen(str);
281 if (len > 255)
282 len = 255;
283 buf[0] = (unsigned char)len;
284 strncpy((char *)buf+1, str, len);
285 return buf;
288 /* Like strerror() but for Mac OS error numbers */
289 char *PyMac_StrError(int err)
291 static char buf[256];
292 Handle h;
293 char *str;
295 h = GetResource('Estr', err);
296 if ( h ) {
297 HLock(h);
298 str = (char *)*h;
299 memcpy(buf, str+1, (unsigned char)str[0]);
300 buf[(unsigned char)str[0]] = '\0';
301 HUnlock(h);
302 ReleaseResource(h);
303 } else {
304 sprintf(buf, "Mac OS error code %d", err);
306 return buf;
309 /* Exception object shared by all Mac specific modules for Mac OS errors */
310 PyObject *PyMac_OSErrException;
312 /* Initialize and return PyMac_OSErrException */
313 PyObject *
314 PyMac_GetOSErrException()
316 if (PyMac_OSErrException == NULL)
317 PyMac_OSErrException = PyString_FromString("Mac OS Error");
318 return PyMac_OSErrException;
321 /* Set a MAC-specific error from errno, and return NULL; return None if no error */
322 PyObject *
323 PyErr_Mac(PyObject *eobj, int err)
325 char *msg;
326 PyObject *v;
328 if (err == 0 && !PyErr_Occurred()) {
329 Py_INCREF(Py_None);
330 return Py_None;
332 if (err == -1 && PyErr_Occurred())
333 return NULL;
334 msg = PyMac_StrError(err);
335 v = Py_BuildValue("(is)", err, msg);
336 PyErr_SetObject(eobj, v);
337 Py_DECREF(v);
338 return NULL;
341 /* Call PyErr_Mac with PyMac_OSErrException */
342 PyObject *
343 PyMac_Error(OSErr err)
345 return PyErr_Mac(PyMac_GetOSErrException(), err);
348 #ifdef USE_STACKCHECK
349 /* Check for stack overflow */
351 PyOS_CheckStack()
353 long left;
355 left = StackSpace();
356 if ( left < MINIMUM_STACK_SIZE )
357 return -1;
358 return 0;
360 #endif /* USE_STACKCHECK */
362 /* The catcher routine (which may not be used for all compilers) */
363 static RETSIGTYPE
364 intcatcher(sig)
365 int sig;
367 interrupted = 1;
368 signal(SIGINT, intcatcher);
371 void
372 PyOS_InitInterrupts()
374 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
375 signal(SIGINT, intcatcher);
378 void
379 PyOS_FiniInterrupts()
384 ** This routine scans the event queue looking for cmd-.
385 ** This is the only way to get an interrupt under THINK (since it
386 ** doesn't do SIGINT handling), but is also used under MW, when
387 ** the full-fledged event loop is disabled. This way, we can at least
388 ** interrupt a runaway python program.
390 static void
391 scan_event_queue(flush)
392 int flush;
394 register EvQElPtr q;
396 q = (EvQElPtr) LMGetEventQueue()->qHead;
398 for (; q; q = (EvQElPtr)q->qLink) {
399 if (q->evtQWhat == keyDown &&
400 (char)q->evtQMessage == '.' &&
401 (q->evtQModifiers & cmdKey) != 0) {
402 if ( flush )
403 FlushEvents(keyDownMask, 0);
404 interrupted = 1;
405 break;
411 PyErr_CheckSignals()
413 if (schedparams.enabled) {
414 if ( (unsigned long)LMGetTicks() > schedparams.next_check ) {
415 if ( PyMac_Yield() < 0)
416 return -1;
417 schedparams.next_check = (unsigned long)LMGetTicks()
418 + schedparams.check_interval;
419 if (interrupted) {
420 scan_event_queue(1); /* Eat events up to cmd-. */
421 interrupted = 0;
422 PyErr_SetNone(PyExc_KeyboardInterrupt);
423 return -1;
427 return 0;
431 PyOS_InterruptOccurred()
433 scan_event_queue(1);
434 return interrupted;
436 /* Check whether we are in the foreground */
438 PyMac_InForeground()
440 static ProcessSerialNumber ours;
441 static inited;
442 ProcessSerialNumber curfg;
443 Boolean eq;
445 if ( inited == 0 ) {
446 (void)GetCurrentProcess(&ours);
447 inited = 1;
449 if ( GetFrontProcess(&curfg) < 0 )
450 eq = 1;
451 else if ( SameProcess(&ours, &curfg, &eq) < 0 )
452 eq = 1;
453 return (int)eq;
458 PyMac_SetEventHandler(PyObject *evh)
460 if ( evh && python_event_handler ) {
461 PyErr_SetString(PyExc_RuntimeError, "Python event handler already set");
462 return 0;
464 if ( python_event_handler )
465 Py_DECREF(python_event_handler);
466 if ( evh )
467 Py_INCREF(evh);
468 python_event_handler = evh;
469 return 1;
473 ** Handle an event, either one found in the mainloop eventhandler or
474 ** one passed back from the python program.
476 void
477 PyMac_HandleEventIntern(evp)
478 EventRecord *evp;
480 if ( evp->what == mouseDown ) {
481 WindowPtr wp;
483 if ( FindWindow(evp->where, &wp) == inSysWindow ) {
484 SystemClick(evp, wp);
485 return;
488 #ifdef __MWERKS__
490 int siouxdidit;
492 /* If SIOUX wants it we're done */
493 siouxdidit = SIOUXHandleOneEvent(evp);
494 if ( siouxdidit )
495 return;
497 #else
498 /* Other compilers are just unlucky... */
499 #endif /* !__MWERKS__ */
503 ** Handle an event, either through HandleEvent or by passing it to the Python
504 ** event handler.
507 PyMac_HandleEvent(evp)
508 EventRecord *evp;
510 PyObject *rv;
512 if ( python_event_handler ) {
513 rv = PyObject_CallFunction(python_event_handler, "(O&)",
514 PyMac_BuildEventRecord, evp);
515 if ( rv )
516 Py_DECREF(rv);
517 else
518 return -1; /* Propagate exception */
519 } else {
520 PyMac_HandleEventIntern(evp);
522 return 0;
526 ** Yield the CPU to other tasks without processing events.
528 static int
529 PyMac_DoYield(int maxsleep, int maycallpython)
531 EventRecord ev;
532 int gotone;
533 long latest_time_ready;
534 static int in_here = 0;
536 in_here++;
538 ** First check for interrupts, if wanted.
539 ** This sets a flag that will be picked up at an appropriate
540 ** moment in the mainloop.
542 if (schedparams.check_interrupt)
543 scan_event_queue(0);
545 /* XXXX Implementing an idle routine goes here */
548 ** Check which of the eventloop cases we have:
549 ** - process events
550 ** - don't process events but do yield
551 ** - do neither
553 if( in_here > 1 || !schedparams.process_events ||
554 (python_event_handler && !maycallpython) ) {
555 if ( maxsleep >= 0 ) {
556 SystemTask();
558 } else {
559 latest_time_ready = LMGetTicks() + maxsleep;
560 while ( maxsleep >= 0 ) {
561 /* XXXX Hack by Jack.
562 ** In time.sleep() you can click to another application
563 ** once only. If you come back to Python you cannot get away
564 ** again.
566 gotone = WaitNextEvent(schedparams.process_events, &ev, maxsleep, NULL);
567 /* Get out quickly if nothing interesting is happening */
568 if ( !gotone || ev.what == nullEvent )
569 break;
570 if ( PyMac_HandleEvent(&ev) < 0 ) {
571 in_here--;
572 return -1;
574 maxsleep = latest_time_ready - LMGetTicks();
577 in_here--;
578 return 0;
582 ** Process events and/or yield the CPU to other tasks if opportune
585 PyMac_Yield() {
586 unsigned long maxsleep;
588 if( PyMac_InForeground() )
589 maxsleep = 0;
590 else
591 maxsleep = schedparams.bg_yield;
593 return PyMac_DoYield(maxsleep, 1);
597 ** Return current scheduler parameters
599 void
600 PyMac_GetSchedParams(PyMacSchedParams *sp)
602 sp->check_interrupt = schedparams.check_interrupt;
603 sp->process_events = schedparams.process_events;
604 sp->besocial = schedparams.besocial;
605 sp->check_interval = schedparams.check_interval / 60.0;
606 sp->bg_yield = schedparams.bg_yield / 60.0;
610 ** Set current scheduler parameters
612 void
613 PyMac_SetSchedParams(PyMacSchedParams *sp)
615 schedparams.check_interrupt = sp->check_interrupt;
616 schedparams.process_events = sp->process_events;
617 schedparams.besocial = sp->besocial;
618 schedparams.check_interval = (unsigned long)(sp->check_interval*60);
619 schedparams.bg_yield = (unsigned long)(sp->bg_yield*60);
620 if ( schedparams.check_interrupt || schedparams.process_events ||
621 schedparams.besocial )
622 schedparams.enabled = 1;
623 else
624 schedparams.enabled = 0;
625 schedparams.next_check = 0; /* Check immedeately */
629 ** Install our menu bar.
631 void
632 PyMac_InitMenuBar()
634 MenuHandle applemenu;
636 if ( (sioux_mbar=GetMenuBar()) == NULL ) {
637 /* Sioux menu not installed yet. Do so */
638 SIOUXSetupMenus();
639 if ( (sioux_mbar=GetMenuBar()) == NULL )
640 return;
642 if ( (applemenu=GetMenuHandle(SIOUX_APPLEID)) == NULL ) return;
643 SetMenuItemText(applemenu, 1, "\pAbout Python...");
647 ** Restore sioux menu bar
649 void
650 PyMac_RestoreMenuBar()
652 if ( sioux_mbar ) {
653 SetMenuBar(sioux_mbar);
654 DrawMenuBar();
655 } else
656 PyMac_InitMenuBar();
661 ** Our replacement about box
664 #include "patchlevel.h"
666 void
667 SIOUXDoAboutBox(void)
669 DialogPtr theDialog;
670 WindowPtr theWindow;
671 short item;
672 short fontID;
674 if( (theDialog = GetNewDialog(ABOUT_ID, NULL, (WindowPtr)-1)) == NULL )
675 return;
676 theWindow = GetDialogWindow(theDialog);
677 SetPortWindowPort(theWindow);
678 GetFNum("\pPython-Sans", &fontID);
679 if (fontID == 0)
680 fontID = kFontIDGeneva;
681 TextFont(fontID);
682 TextSize(9);
683 ParamText(Pstring(PATCHLEVEL), "\p", "\p", "\p");
684 ShowWindow(theWindow);
685 ModalDialog(NULL, &item);
686 DisposeDialog(theDialog);
689 #if 0
691 PyMac_FileExists(char *name)
693 FSSpec fss;
695 if ( FSMakeFSSpec(0, 0, Pstring(name), &fss) == noErr )
696 return 1;
697 return 0;
699 #endif
702 ** Helper routine for GetDirectory
704 static pascal short
705 myhook_proc(short item, DialogPtr theDialog, struct hook_args *dataptr)
707 if ( item == sfHookFirstCall && dataptr->prompt) {
708 Handle prompth;
709 short type;
710 Rect rect;
712 GetDialogItem(theDialog, PROMPT_ITEM, &type, &prompth, &rect);
713 if ( prompth )
714 SetDialogItemText(prompth, (unsigned char *)dataptr->prompt);
715 } else
716 if ( item == SELECTCUR_ITEM ) {
717 item = sfItemCancelButton;
718 dataptr->selectcur_hit = 1;
720 return item;
724 ** Ask the user for a directory. I still can't understand
725 ** why Apple doesn't provide a standard solution for this...
728 PyMac_GetDirectory(dirfss, prompt)
729 FSSpec *dirfss;
730 char *prompt;
732 static SFTypeList list = {'fldr', 0, 0, 0};
733 static Point where = {-1, -1};
734 StandardFileReply reply;
735 struct hook_args hook_args;
737 if ( !upp_inited ) {
738 myhook_upp = NewDlgHookYDProc(myhook_proc);
739 upp_inited = 1;
741 if ( prompt && *prompt )
742 hook_args.prompt = (char *)Pstring(prompt);
743 else
744 hook_args.prompt = NULL;
745 hook_args.selectcur_hit = 0;
746 CustomGetFile((FileFilterYDUPP)0, 1, list, &reply, GETDIR_ID, where, myhook_upp,
747 NULL, NULL, NULL, (void *)&hook_args);
749 reply.sfFile.name[0] = 0;
750 if( FSMakeFSSpec(reply.sfFile.vRefNum, reply.sfFile.parID, reply.sfFile.name, dirfss) )
751 return 0;
752 return hook_args.selectcur_hit;
756 ** Slightly extended StandardGetFile: accepts a prompt */
757 void PyMac_PromptGetFile(short numTypes, ConstSFTypeListPtr typeList,
758 StandardFileReply *reply, char *prompt)
760 static Point where = {-1, -1};
761 struct hook_args hook_args;
763 if ( !upp_inited ) {
764 myhook_upp = NewDlgHookYDProc(myhook_proc);
765 upp_inited = 1;
767 if ( prompt && *prompt )
768 hook_args.prompt = (char *)Pstring(prompt);
769 else
770 hook_args.prompt = NULL;
771 hook_args.selectcur_hit = 0;
772 CustomGetFile((FileFilterYDUPP)0, numTypes, typeList, reply, GETFILEPROMPT_ID, where,
773 myhook_upp, NULL, NULL, NULL, (void *)&hook_args);
776 /* Convert a 4-char string object argument to an OSType value */
778 PyMac_GetOSType(PyObject *v, OSType *pr)
780 if (!PyString_Check(v) || PyString_Size(v) != 4) {
781 PyErr_SetString(PyExc_TypeError,
782 "OSType arg must be string of 4 chars");
783 return 0;
785 memcpy((char *)pr, PyString_AsString(v), 4);
786 return 1;
789 /* Convert an OSType value to a 4-char string object */
790 PyObject *
791 PyMac_BuildOSType(OSType t)
793 return PyString_FromStringAndSize((char *)&t, 4);
796 /* Convert an NumVersion value to a 4-element tuple */
797 PyObject *
798 PyMac_BuildNumVersion(NumVersion t)
800 return Py_BuildValue("(hhhh)", t.majorRev, t.minorAndBugRev, t.stage, t.nonRelRev);
804 /* Convert a Python string object to a Str255 */
806 PyMac_GetStr255(PyObject *v, Str255 pbuf)
808 int len;
809 if (!PyString_Check(v) || (len = PyString_Size(v)) > 255) {
810 PyErr_SetString(PyExc_TypeError,
811 "Str255 arg must be string of at most 255 chars");
812 return 0;
814 pbuf[0] = len;
815 memcpy((char *)(pbuf+1), PyString_AsString(v), len);
816 return 1;
819 /* Convert a Str255 to a Python string object */
820 PyObject *
821 PyMac_BuildStr255(Str255 s)
823 return PyString_FromStringAndSize((char *)&s[1], (int)s[0]);
828 ** Convert a Python object to an FSSpec.
829 ** The object may either be a full pathname or a triple
830 ** (vrefnum, dirid, path).
831 ** NOTE: This routine will fail on pre-sys7 machines.
832 ** The caller is responsible for not calling this routine
833 ** in those cases (which is fine, since everyone calling
834 ** this is probably sys7 dependent anyway).
837 PyMac_GetFSSpec(PyObject *v, FSSpec *fs)
839 Str255 path;
840 short refnum;
841 long parid;
842 OSErr err;
843 FSSpec *fs2;
845 /* first check whether it already is an FSSpec */
846 fs2 = mfs_GetFSSpecFSSpec(v);
847 if ( fs2 ) {
848 (void)FSMakeFSSpec(fs2->vRefNum, fs2->parID, fs2->name, fs);
849 return 1;
851 if ( PyString_Check(v) ) {
852 /* It's a pathname */
853 if( !PyArg_Parse(v, "O&", PyMac_GetStr255, &path) )
854 return 0;
855 refnum = 0; /* XXXX Should get CurWD here?? */
856 parid = 0;
857 } else {
858 if( !PyArg_Parse(v, "(hlO&); FSSpec should be fullpath or (vrefnum,dirid,path)",
859 &refnum, &parid, PyMac_GetStr255, &path)) {
860 return 0;
863 err = FSMakeFSSpec(refnum, parid, path, fs);
864 if ( err && err != fnfErr ) {
865 PyErr_Mac(PyExc_ValueError, err);
866 return 0;
868 return 1;
872 /* Convert a Python object to a Rect.
873 The object must be a (left, top, right, bottom) tuple.
874 (This differs from the order in the struct but is consistent with
875 the arguments to SetRect(), and also with STDWIN). */
877 PyMac_GetRect(PyObject *v, Rect *r)
879 return PyArg_Parse(v, "(hhhh)", &r->left, &r->top, &r->right, &r->bottom);
882 /* Convert a Rect to a Python object */
883 PyObject *
884 PyMac_BuildRect(Rect *r)
886 return Py_BuildValue("(hhhh)", r->left, r->top, r->right, r->bottom);
890 /* Convert a Python object to a Point.
891 The object must be a (h, v) tuple.
892 (This differs from the order in the struct but is consistent with
893 the arguments to SetPoint(), and also with STDWIN). */
895 PyMac_GetPoint(PyObject *v, Point *p)
897 return PyArg_Parse(v, "(hh)", &p->h, &p->v);
900 /* Convert a Point to a Python object */
901 PyObject *
902 PyMac_BuildPoint(Point p)
904 return Py_BuildValue("(hh)", p.h, p.v);
908 /* Convert a Python object to an EventRecord.
909 The object must be a (what, message, when, (v, h), modifiers) tuple. */
911 PyMac_GetEventRecord(PyObject *v, EventRecord *e)
913 return PyArg_Parse(v, "(hll(hh)h)",
914 &e->what,
915 &e->message,
916 &e->when,
917 &e->where.h,
918 &e->where.v,
919 &e->modifiers);
922 /* Convert a Rect to an EventRecord object */
923 PyObject *
924 PyMac_BuildEventRecord(EventRecord *e)
926 return Py_BuildValue("(hll(hh)h)",
927 e->what,
928 e->message,
929 e->when,
930 e->where.h,
931 e->where.v,
932 e->modifiers);
935 /* Convert Python object to Fixed */
937 PyMac_GetFixed(PyObject *v, Fixed *f)
939 double d;
941 if( !PyArg_Parse(v, "d", &d))
942 return 0;
943 *f = (Fixed)(d * 0x10000);
944 return 1;
947 /* Convert a Point to a Python object */
948 PyObject *
949 PyMac_BuildFixed(Fixed f)
951 double d;
953 d = f;
954 d = d / 0x10000;
955 return Py_BuildValue("d", d);
958 /* Convert wide to/from Python int or (hi, lo) tuple. XXXX Should use Python longs */
960 PyMac_Getwide(PyObject *v, wide *rv)
962 if (PyInt_Check(v)) {
963 rv->hi = 0;
964 rv->lo = PyInt_AsLong(v);
965 if( rv->lo & 0x80000000 )
966 rv->hi = -1;
967 return 1;
969 return PyArg_Parse(v, "(ll)", &rv->hi, &rv->lo);
973 PyObject *
974 PyMac_Buildwide(wide *w)
976 if ( (w->hi == 0 && (w->lo & 0x80000000) == 0) ||
977 (w->hi == -1 && (w->lo & 0x80000000) ) )
978 return PyInt_FromLong(w->lo);
979 return Py_BuildValue("(ll)", w->hi, w->lo);