1 /***********************************************************
2 Copyright 1991-1997 by Stichting Mathematisch Centrum, Amsterdam,
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 /* Macintosh OS-specific interface */
29 #include "pythonresources.h"
31 #ifdef WITHOUT_FRAMEWORKS
38 #include <Carbon/Carbon.h>
41 static PyObject
*MacOS_Error
; /* Exception MacOS.Error */
43 #ifdef TARGET_API_MAC_OSX
44 #define PATHNAMELEN 1024
46 #define PATHNAMELEN 256
50 #define bufferIsSmall -607 /*error returns from Post and Accept */
53 /* ----------------------------------------------------- */
55 /* Declarations for objects of type Resource fork */
63 static PyTypeObject Rftype
;
67 /* ---------------------------------------------------------------- */
70 do_close(rfobject
*self
)
72 if (self
->isclosed
) return;
73 (void)FSClose(self
->fRefNum
);
77 static char rf_read__doc__
[] =
78 "Read data from resource fork"
82 rf_read(rfobject
*self
, PyObject
*args
)
89 PyErr_SetString(PyExc_ValueError
, "Operation on closed file");
93 if (!PyArg_ParseTuple(args
, "l", &n
))
96 v
= PyString_FromStringAndSize((char *)NULL
, n
);
100 err
= FSRead(self
->fRefNum
, &n
, PyString_AsString(v
));
101 if (err
&& err
!= eofErr
) {
106 _PyString_Resize(&v
, n
);
111 static char rf_write__doc__
[] =
112 "Write to resource fork"
116 rf_write(rfobject
*self
, PyObject
*args
)
122 if (self
->isclosed
) {
123 PyErr_SetString(PyExc_ValueError
, "Operation on closed file");
126 if (!PyArg_ParseTuple(args
, "s#", &buffer
, &size
))
128 err
= FSWrite(self
->fRefNum
, &size
, buffer
);
138 static char rf_seek__doc__
[] =
143 rf_seek(rfobject
*self
, PyObject
*args
)
146 int whence
= SEEK_SET
;
150 if (self
->isclosed
) {
151 PyErr_SetString(PyExc_ValueError
, "Operation on closed file");
154 if (!PyArg_ParseTuple(args
, "l|i", &amount
, &whence
))
157 if ((err
= GetEOF(self
->fRefNum
, &eof
)))
162 if ((err
= GetFPos(self
->fRefNum
, &pos
)))
178 /* Don't bother implementing seek past EOF */
179 if (pos
> eof
|| pos
< 0) {
184 if ((err
= SetFPos(self
->fRefNum
, fsFromStart
, pos
)) ) {
194 static char rf_tell__doc__
[] =
199 rf_tell(rfobject
*self
, PyObject
*args
)
204 if (self
->isclosed
) {
205 PyErr_SetString(PyExc_ValueError
, "Operation on closed file");
208 if (!PyArg_ParseTuple(args
, ""))
210 if ((err
= GetFPos(self
->fRefNum
, &where
)) ) {
214 return PyInt_FromLong(where
);
217 static char rf_close__doc__
[] =
218 "Close resource fork"
222 rf_close(rfobject
*self
, PyObject
*args
)
224 if (!PyArg_ParseTuple(args
, ""))
232 static struct PyMethodDef rf_methods
[] = {
233 {"read", (PyCFunction
)rf_read
, 1, rf_read__doc__
},
234 {"write", (PyCFunction
)rf_write
, 1, rf_write__doc__
},
235 {"seek", (PyCFunction
)rf_seek
, 1, rf_seek__doc__
},
236 {"tell", (PyCFunction
)rf_tell
, 1, rf_tell__doc__
},
237 {"close", (PyCFunction
)rf_close
, 1, rf_close__doc__
},
239 {NULL
, NULL
} /* sentinel */
250 self
= PyObject_NEW(rfobject
, &Rftype
);
259 rf_dealloc(rfobject
*self
)
266 rf_getattr(rfobject
*self
, char *name
)
268 return Py_FindMethod(rf_methods
, (PyObject
*)self
, name
);
271 static char Rftype__doc__
[] =
272 "Resource fork file object"
275 static PyTypeObject Rftype
= {
276 PyObject_HEAD_INIT(&PyType_Type
)
278 "MacOS.ResourceFork", /*tp_name*/
279 sizeof(rfobject
), /*tp_basicsize*/
282 (destructor
)rf_dealloc
, /*tp_dealloc*/
283 (printfunc
)0, /*tp_print*/
284 (getattrfunc
)rf_getattr
, /*tp_getattr*/
285 (setattrfunc
)0, /*tp_setattr*/
286 (cmpfunc
)0, /*tp_compare*/
287 (reprfunc
)0, /*tp_repr*/
289 0, /*tp_as_sequence*/
291 (hashfunc
)0, /*tp_hash*/
292 (ternaryfunc
)0, /*tp_call*/
293 (reprfunc
)0, /*tp_str*/
295 /* Space for future expansion */
297 Rftype__doc__
/* Documentation string */
300 /* End of code for Resource fork objects */
301 /* -------------------------------------------------------- */
303 /*----------------------------------------------------------------------*/
304 /* Miscellaneous File System Operations */
306 static char getcrtp_doc
[] = "Obsolete, use macfs module";
309 MacOS_GetCreatorAndType(PyObject
*self
, PyObject
*args
)
313 PyObject
*creator
, *type
, *res
;
316 if (!PyArg_ParseTuple(args
, "O&", PyMac_GetFSSpec
, &fss
))
318 if ((err
= FSpGetFInfo(&fss
, &info
)) != noErr
)
319 return PyErr_Mac(MacOS_Error
, err
);
320 creator
= PyString_FromStringAndSize((char *)&info
.fdCreator
, 4);
321 type
= PyString_FromStringAndSize((char *)&info
.fdType
, 4);
322 res
= Py_BuildValue("OO", creator
, type
);
328 static char setcrtp_doc
[] = "Obsolete, use macfs module";
331 MacOS_SetCreatorAndType(PyObject
*self
, PyObject
*args
)
334 ResType creator
, type
;
338 if (!PyArg_ParseTuple(args
, "O&O&O&",
339 PyMac_GetFSSpec
, &fss
, PyMac_GetOSType
, &creator
, PyMac_GetOSType
, &type
))
341 if ((err
= FSpGetFInfo(&fss
, &info
)) != noErr
)
342 return PyErr_Mac(MacOS_Error
, err
);
343 info
.fdCreator
= creator
;
345 if ((err
= FSpSetFInfo(&fss
, &info
)) != noErr
)
346 return PyErr_Mac(MacOS_Error
, err
);
351 #if TARGET_API_MAC_OS8
352 /*----------------------------------------------------------------------*/
353 /* STDWIN High Level Event interface */
358 static char accepthle_doc
[] = "Get arguments of pending high-level event";
361 MacOS_AcceptHighLevelEvent(self
, args
)
366 unsigned long refcon
;
374 err
= AcceptHighLevelEvent(&sender
, &refcon
, buf
, &len
);
375 if (err
== bufferIsSmall
) {
378 return PyErr_NoMemory();
379 err
= AcceptHighLevelEvent(&sender
, &refcon
, buf
, &len
);
382 return PyErr_Mac(MacOS_Error
, (int)err
);
385 else if (err
!= noErr
)
386 return PyErr_Mac(MacOS_Error
, (int)err
);
387 res
= Py_BuildValue("s#ls#",
388 (char *)&sender
, (int)(sizeof sender
), refcon
, (char *)buf
, (int)len
);
394 #if !TARGET_API_MAC_OSX
395 static char schedparams_doc
[] = "Set/return mainloop interrupt check flag, etc";
398 ** Set scheduler parameters
401 MacOS_SchedParams(PyObject
*self
, PyObject
*args
)
403 PyMacSchedParams old
, new;
405 PyMac_GetSchedParams(&old
);
407 if (!PyArg_ParseTuple(args
, "|iiidd", &new.check_interrupt
, &new.process_events
,
408 &new.besocial
, &new.check_interval
, &new.bg_yield
))
410 PyMac_SetSchedParams(&new);
411 return Py_BuildValue("iiidd", old
.check_interrupt
, old
.process_events
,
412 old
.besocial
, old
.check_interval
, old
.bg_yield
);
415 static char appswitch_doc
[] = "Obsolete, use SchedParams";
417 /* Obsolete, for backward compatability */
419 MacOS_EnableAppswitch(PyObject
*self
, PyObject
*args
)
422 PyMacSchedParams schp
;
424 if (!PyArg_ParseTuple(args
, "i", &new))
426 PyMac_GetSchedParams(&schp
);
427 if ( schp
.process_events
)
429 else if ( schp
.check_interrupt
)
434 schp
.process_events
= mDownMask
|keyDownMask
|osMask
;
435 schp
.check_interrupt
= 1;
436 } else if ( new == 0 ) {
437 schp
.process_events
= 0;
438 schp
.check_interrupt
= 1;
440 schp
.process_events
= 0;
441 schp
.check_interrupt
= 0;
443 PyMac_SetSchedParams(&schp
);
444 return Py_BuildValue("i", old
);
447 static char setevh_doc
[] = "Set python event handler to be called in mainloop";
450 MacOS_SetEventHandler(PyObject
*self
, PyObject
*args
)
452 PyObject
*evh
= NULL
;
454 if (!PyArg_ParseTuple(args
, "|O", &evh
))
458 if ( evh
&& !PyCallable_Check(evh
) ) {
459 PyErr_SetString(PyExc_ValueError
, "SetEventHandler argument must be callable");
462 if ( !PyMac_SetEventHandler(evh
) )
468 static char handleev_doc
[] = "Pass event to other interested parties like sioux";
471 MacOS_HandleEvent(PyObject
*self
, PyObject
*args
)
475 if (!PyArg_ParseTuple(args
, "O&", PyMac_GetEventRecord
, &ev
))
477 PyMac_HandleEventIntern(&ev
);
481 #endif /* !TARGET_API_MAC_OSX */
483 static char geterr_doc
[] = "Convert OSErr number to string";
486 MacOS_GetErrorString(PyObject
*self
, PyObject
*args
)
490 if (!PyArg_ParseTuple(args
, "i", &errn
))
492 return Py_BuildValue("s", PyMac_StrError(errn
));
495 static char splash_doc
[] = "Open a splash-screen dialog by resource-id (0=close)";
498 MacOS_splash(PyObject
*self
, PyObject
*args
)
501 static DialogPtr curdialog
= NULL
;
506 short xpos
, ypos
, width
, height
, swidth
, sheight
;
509 if (!PyArg_ParseTuple(args
, "|i", &resid
))
511 olddialog
= curdialog
;
515 curdialog
= GetNewDialog(resid
, NULL
, (WindowPtr
)-1);
517 theWindow
= GetDialogWindow(curdialog
);
518 thePort
= GetWindowPort(theWindow
);
520 width
= thePort
->portRect
.right
- thePort
->portRect
.left
;
521 height
= thePort
->portRect
.bottom
- thePort
->portRect
.top
;
522 swidth
= qd
.screenBits
.bounds
.right
- qd
.screenBits
.bounds
.left
;
523 sheight
= qd
.screenBits
.bounds
.bottom
- qd
.screenBits
.bounds
.top
- LMGetMBarHeight();
524 xpos
= (swidth
-width
)/2;
525 ypos
= (sheight
-height
)/5 + LMGetMBarHeight();
526 MoveWindow(theWindow
, xpos
, ypos
, 0);
527 ShowWindow(theWindow
);
529 DrawDialog(curdialog
);
533 DisposeDialog(olddialog
);
538 static char DebugStr_doc
[] = "Switch to low-level debugger with a message";
541 MacOS_DebugStr(PyObject
*self
, PyObject
*args
)
544 PyObject
*object
= 0;
546 if (!PyArg_ParseTuple(args
, "O&|O", PyMac_GetStr255
, message
, &object
))
553 static char SysBeep_doc
[] = "BEEEEEP!!!";
556 MacOS_SysBeep(PyObject
*self
, PyObject
*args
)
560 if (!PyArg_ParseTuple(args
, "|i", &duration
))
567 static char GetTicks_doc
[] = "Return number of ticks since bootup";
570 MacOS_GetTicks(PyObject
*self
, PyObject
*args
)
572 return Py_BuildValue("i", (int)TickCount());
575 static char openrf_doc
[] = "Open resource fork of a file";
578 MacOS_openrf(PyObject
*self
, PyObject
*args
)
583 SignedByte permission
= 1;
586 if (!PyArg_ParseTuple(args
, "O&|s", PyMac_GetFSSpec
, &fss
, &mode
))
591 case 'r': permission
= 1; break;
592 case 'w': permission
= 2; break;
600 if ( (fp
= newrfobject()) == NULL
)
603 err
= HOpenRF(fss
.vRefNum
, fss
.parID
, fss
.name
, permission
, &fp
->fRefNum
);
605 if ( err
== fnfErr
) {
606 /* In stead of doing complicated things here to get creator/type
607 ** correct we let the standard i/o library handle it
610 char pathname
[PATHNAMELEN
];
612 if ( err
=PyMac_GetFullPathname(&fss
, pathname
, PATHNAMELEN
) ) {
618 if ( (tfp
= fopen(pathname
, "w")) == NULL
) {
619 PyMac_Error(fnfErr
); /* What else... */
624 err
= HOpenRF(fss
.vRefNum
, fss
.parID
, fss
.name
, permission
, &fp
->fRefNum
);
632 return (PyObject
*)fp
;
635 #if !TARGET_API_MAC_OSX
636 static char FreeMem_doc
[] = "Return the total amount of free space in the heap";
639 MacOS_FreeMem(PyObject
*self
, PyObject
*args
)
643 if (!PyArg_ParseTuple(args
, ""))
646 return Py_BuildValue("l", rv
);
649 static char MaxBlock_doc
[] = "Return the largest contiguous block of free space in the heap";
652 MacOS_MaxBlock(PyObject
*self
, PyObject
*args
)
656 if (!PyArg_ParseTuple(args
, ""))
659 return Py_BuildValue("l", rv
);
662 static char CompactMem_doc
[] = "(wanted size)->actual largest block after compacting";
665 MacOS_CompactMem(PyObject
*self
, PyObject
*args
)
670 if (!PyArg_ParseTuple(args
, "l", &value
))
672 rv
= CompactMem(value
);
673 return Py_BuildValue("l", rv
);
676 static char KeepConsole_doc
[] = "(flag) Keep console open 0:never, 1:on output 2:on error, 3:always";
679 MacOS_KeepConsole(PyObject
*self
, PyObject
*args
)
683 if (!PyArg_ParseTuple(args
, "i", &value
))
685 PyMac_options
.keep_console
= value
;
690 static char OutputSeen_doc
[] = "Call to reset the 'unseen output' flag for the keep-console-open option";
693 MacOS_OutputSeen(PyObject
*self
, PyObject
*args
)
695 if (!PyArg_ParseTuple(args
, ""))
701 #endif /* !TARGET_API_MAC_OSX */
703 static PyMethodDef MacOS_Methods
[] = {
704 #if TARGET_API_MAC_OS8
705 {"AcceptHighLevelEvent", MacOS_AcceptHighLevelEvent
, 1, accepthle_doc
},
707 {"GetCreatorAndType", MacOS_GetCreatorAndType
, 1, getcrtp_doc
},
708 {"SetCreatorAndType", MacOS_SetCreatorAndType
, 1, setcrtp_doc
},
709 #if !TARGET_API_MAC_OSX
710 {"SchedParams", MacOS_SchedParams
, 1, schedparams_doc
},
711 {"EnableAppswitch", MacOS_EnableAppswitch
, 1, appswitch_doc
},
712 {"SetEventHandler", MacOS_SetEventHandler
, 1, setevh_doc
},
713 {"HandleEvent", MacOS_HandleEvent
, 1, handleev_doc
},
715 {"GetErrorString", MacOS_GetErrorString
, 1, geterr_doc
},
716 {"openrf", MacOS_openrf
, 1, openrf_doc
},
717 {"splash", MacOS_splash
, 1, splash_doc
},
718 {"DebugStr", MacOS_DebugStr
, 1, DebugStr_doc
},
719 {"GetTicks", MacOS_GetTicks
, 1, GetTicks_doc
},
720 {"SysBeep", MacOS_SysBeep
, 1, SysBeep_doc
},
721 #if !TARGET_API_MAC_OSX
722 {"FreeMem", MacOS_FreeMem
, 1, FreeMem_doc
},
723 {"MaxBlock", MacOS_MaxBlock
, 1, MaxBlock_doc
},
724 {"CompactMem", MacOS_CompactMem
, 1, CompactMem_doc
},
725 {"KeepConsole", MacOS_KeepConsole
, 1, KeepConsole_doc
},
726 {"OutputSeen", MacOS_OutputSeen
, 1, OutputSeen_doc
},
728 {NULL
, NULL
} /* Sentinel */
737 m
= Py_InitModule("MacOS", MacOS_Methods
);
738 d
= PyModule_GetDict(m
);
740 /* Initialize MacOS.Error exception */
741 MacOS_Error
= PyMac_GetOSErrException();
742 if (MacOS_Error
== NULL
|| PyDict_SetItemString(d
, "Error", MacOS_Error
) != 0)
744 Rftype
.ob_type
= &PyType_Type
;
746 if (PyDict_SetItemString(d
, "ResourceForkType", (PyObject
*)&Rftype
) != 0)
749 ** This is a hack: the following constant added to the id() of a string
750 ** object gives you the address of the data. Unfortunately, it is needed for
751 ** some of the image and sound processing interfaces on the mac:-(
754 PyStringObject
*p
= 0;
755 long off
= (long)&(p
->ob_sval
[0]);
757 if( PyDict_SetItemString(d
, "string_id_to_buffer", Py_BuildValue("i", off
)) != 0)
760 #if TARGET_API_MAC_OSX
761 #define PY_RUNTIMEMODEL "macho"
762 #elif TARGET_API_MAC_OS8
763 #define PY_RUNTIMEMODEL "ppc"
764 #elif TARGET_API_MAC_CARBON
765 #define PY_RUNTIMEMODEL "carbon"
767 #error "None of the TARGET_API_MAC_XXX I know about is set"
769 if (PyDict_SetItemString(d
, "runtimemodel",
770 Py_BuildValue("s", PY_RUNTIMEMODEL
)) != 0)