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>
39 #include <ApplicationServices/ApplicationServices.h>
42 static PyObject
*MacOS_Error
; /* Exception MacOS.Error */
44 #ifdef TARGET_API_MAC_OSX
45 #define PATHNAMELEN 1024
47 #define PATHNAMELEN 256
51 #define bufferIsSmall -607 /*error returns from Post and Accept */
54 /* ----------------------------------------------------- */
56 /* Declarations for objects of type Resource fork */
64 static PyTypeObject Rftype
;
68 /* ---------------------------------------------------------------- */
71 do_close(rfobject
*self
)
73 if (self
->isclosed
) return;
74 (void)FSClose(self
->fRefNum
);
78 static char rf_read__doc__
[] =
79 "Read data from resource fork"
83 rf_read(rfobject
*self
, PyObject
*args
)
90 PyErr_SetString(PyExc_ValueError
, "Operation on closed file");
94 if (!PyArg_ParseTuple(args
, "l", &n
))
97 v
= PyString_FromStringAndSize((char *)NULL
, n
);
101 err
= FSRead(self
->fRefNum
, &n
, PyString_AsString(v
));
102 if (err
&& err
!= eofErr
) {
107 _PyString_Resize(&v
, n
);
112 static char rf_write__doc__
[] =
113 "Write to resource fork"
117 rf_write(rfobject
*self
, PyObject
*args
)
123 if (self
->isclosed
) {
124 PyErr_SetString(PyExc_ValueError
, "Operation on closed file");
127 if (!PyArg_ParseTuple(args
, "s#", &buffer
, &size
))
129 err
= FSWrite(self
->fRefNum
, &size
, buffer
);
139 static char rf_seek__doc__
[] =
144 rf_seek(rfobject
*self
, PyObject
*args
)
147 int whence
= SEEK_SET
;
151 if (self
->isclosed
) {
152 PyErr_SetString(PyExc_ValueError
, "Operation on closed file");
155 if (!PyArg_ParseTuple(args
, "l|i", &amount
, &whence
))
158 if ((err
= GetEOF(self
->fRefNum
, &eof
)))
163 if ((err
= GetFPos(self
->fRefNum
, &pos
)))
179 /* Don't bother implementing seek past EOF */
180 if (pos
> eof
|| pos
< 0) {
185 if ((err
= SetFPos(self
->fRefNum
, fsFromStart
, pos
)) ) {
195 static char rf_tell__doc__
[] =
200 rf_tell(rfobject
*self
, PyObject
*args
)
205 if (self
->isclosed
) {
206 PyErr_SetString(PyExc_ValueError
, "Operation on closed file");
209 if (!PyArg_ParseTuple(args
, ""))
211 if ((err
= GetFPos(self
->fRefNum
, &where
)) ) {
215 return PyInt_FromLong(where
);
218 static char rf_close__doc__
[] =
219 "Close resource fork"
223 rf_close(rfobject
*self
, PyObject
*args
)
225 if (!PyArg_ParseTuple(args
, ""))
233 static struct PyMethodDef rf_methods
[] = {
234 {"read", (PyCFunction
)rf_read
, 1, rf_read__doc__
},
235 {"write", (PyCFunction
)rf_write
, 1, rf_write__doc__
},
236 {"seek", (PyCFunction
)rf_seek
, 1, rf_seek__doc__
},
237 {"tell", (PyCFunction
)rf_tell
, 1, rf_tell__doc__
},
238 {"close", (PyCFunction
)rf_close
, 1, rf_close__doc__
},
240 {NULL
, NULL
} /* sentinel */
251 self
= PyObject_NEW(rfobject
, &Rftype
);
260 rf_dealloc(rfobject
*self
)
267 rf_getattr(rfobject
*self
, char *name
)
269 return Py_FindMethod(rf_methods
, (PyObject
*)self
, name
);
272 static char Rftype__doc__
[] =
273 "Resource fork file object"
276 static PyTypeObject Rftype
= {
277 PyObject_HEAD_INIT(&PyType_Type
)
279 "MacOS.ResourceFork", /*tp_name*/
280 sizeof(rfobject
), /*tp_basicsize*/
283 (destructor
)rf_dealloc
, /*tp_dealloc*/
284 (printfunc
)0, /*tp_print*/
285 (getattrfunc
)rf_getattr
, /*tp_getattr*/
286 (setattrfunc
)0, /*tp_setattr*/
287 (cmpfunc
)0, /*tp_compare*/
288 (reprfunc
)0, /*tp_repr*/
290 0, /*tp_as_sequence*/
292 (hashfunc
)0, /*tp_hash*/
293 (ternaryfunc
)0, /*tp_call*/
294 (reprfunc
)0, /*tp_str*/
296 /* Space for future expansion */
298 Rftype__doc__
/* Documentation string */
301 /* End of code for Resource fork objects */
302 /* -------------------------------------------------------- */
304 /*----------------------------------------------------------------------*/
305 /* Miscellaneous File System Operations */
307 static char getcrtp_doc
[] = "Get MacOS 4-char creator and type for a file";
310 MacOS_GetCreatorAndType(PyObject
*self
, PyObject
*args
)
314 PyObject
*creator
, *type
, *res
;
317 if (!PyArg_ParseTuple(args
, "O&", PyMac_GetFSSpec
, &fss
))
319 if ((err
= FSpGetFInfo(&fss
, &info
)) != noErr
)
320 return PyErr_Mac(MacOS_Error
, err
);
321 creator
= PyString_FromStringAndSize((char *)&info
.fdCreator
, 4);
322 type
= PyString_FromStringAndSize((char *)&info
.fdType
, 4);
323 res
= Py_BuildValue("OO", creator
, type
);
329 static char setcrtp_doc
[] = "Set MacOS 4-char creator and type for a file";
332 MacOS_SetCreatorAndType(PyObject
*self
, PyObject
*args
)
335 ResType creator
, type
;
339 if (!PyArg_ParseTuple(args
, "O&O&O&",
340 PyMac_GetFSSpec
, &fss
, PyMac_GetOSType
, &creator
, PyMac_GetOSType
, &type
))
342 if ((err
= FSpGetFInfo(&fss
, &info
)) != noErr
)
343 return PyErr_Mac(MacOS_Error
, err
);
344 info
.fdCreator
= creator
;
346 if ((err
= FSpSetFInfo(&fss
, &info
)) != noErr
)
347 return PyErr_Mac(MacOS_Error
, err
);
352 #if !TARGET_API_MAC_OSX
353 static char schedparams_doc
[] = "Set/return mainloop interrupt check flag, etc";
356 ** Set scheduler parameters
359 MacOS_SchedParams(PyObject
*self
, PyObject
*args
)
361 PyMacSchedParams old
, new;
363 PyMac_GetSchedParams(&old
);
365 if (!PyArg_ParseTuple(args
, "|iiidd", &new.check_interrupt
, &new.process_events
,
366 &new.besocial
, &new.check_interval
, &new.bg_yield
))
368 PyMac_SetSchedParams(&new);
369 return Py_BuildValue("iiidd", old
.check_interrupt
, old
.process_events
,
370 old
.besocial
, old
.check_interval
, old
.bg_yield
);
373 static char appswitch_doc
[] = "Obsolete, use SchedParams";
375 /* Obsolete, for backward compatability */
377 MacOS_EnableAppswitch(PyObject
*self
, PyObject
*args
)
380 PyMacSchedParams schp
;
382 if (!PyArg_ParseTuple(args
, "i", &new))
384 PyMac_GetSchedParams(&schp
);
385 if ( schp
.process_events
)
387 else if ( schp
.check_interrupt
)
392 schp
.process_events
= mDownMask
|keyDownMask
|osMask
;
393 schp
.check_interrupt
= 1;
394 } else if ( new == 0 ) {
395 schp
.process_events
= 0;
396 schp
.check_interrupt
= 1;
398 schp
.process_events
= 0;
399 schp
.check_interrupt
= 0;
401 PyMac_SetSchedParams(&schp
);
402 return Py_BuildValue("i", old
);
405 static char setevh_doc
[] = "Set python event handler to be called in mainloop";
408 MacOS_SetEventHandler(PyObject
*self
, PyObject
*args
)
410 PyObject
*evh
= NULL
;
412 if (!PyArg_ParseTuple(args
, "|O", &evh
))
416 if ( evh
&& !PyCallable_Check(evh
) ) {
417 PyErr_SetString(PyExc_ValueError
, "SetEventHandler argument must be callable");
420 if ( !PyMac_SetEventHandler(evh
) )
426 static char handleev_doc
[] = "Pass event to other interested parties like sioux";
429 MacOS_HandleEvent(PyObject
*self
, PyObject
*args
)
433 if (!PyArg_ParseTuple(args
, "O&", PyMac_GetEventRecord
, &ev
))
435 PyMac_HandleEventIntern(&ev
);
439 #endif /* !TARGET_API_MAC_OSX */
441 static char geterr_doc
[] = "Convert OSErr number to string";
444 MacOS_GetErrorString(PyObject
*self
, PyObject
*args
)
448 if (!PyArg_ParseTuple(args
, "i", &errn
))
450 return Py_BuildValue("s", PyMac_StrError(errn
));
453 static char splash_doc
[] = "Open a splash-screen dialog by resource-id (0=close)";
456 MacOS_splash(PyObject
*self
, PyObject
*args
)
459 static DialogPtr curdialog
= NULL
;
464 short xpos
, ypos
, width
, height
, swidth
, sheight
;
467 if (!PyArg_ParseTuple(args
, "|i", &resid
))
469 olddialog
= curdialog
;
473 curdialog
= GetNewDialog(resid
, NULL
, (WindowPtr
)-1);
475 theWindow
= GetDialogWindow(curdialog
);
476 thePort
= GetWindowPort(theWindow
);
478 width
= thePort
->portRect
.right
- thePort
->portRect
.left
;
479 height
= thePort
->portRect
.bottom
- thePort
->portRect
.top
;
480 swidth
= qd
.screenBits
.bounds
.right
- qd
.screenBits
.bounds
.left
;
481 sheight
= qd
.screenBits
.bounds
.bottom
- qd
.screenBits
.bounds
.top
- LMGetMBarHeight();
482 xpos
= (swidth
-width
)/2;
483 ypos
= (sheight
-height
)/5 + LMGetMBarHeight();
484 MoveWindow(theWindow
, xpos
, ypos
, 0);
485 ShowWindow(theWindow
);
487 DrawDialog(curdialog
);
491 DisposeDialog(olddialog
);
496 static char DebugStr_doc
[] = "Switch to low-level debugger with a message";
499 MacOS_DebugStr(PyObject
*self
, PyObject
*args
)
502 PyObject
*object
= 0;
504 if (!PyArg_ParseTuple(args
, "O&|O", PyMac_GetStr255
, message
, &object
))
511 static char SysBeep_doc
[] = "BEEEEEP!!!";
514 MacOS_SysBeep(PyObject
*self
, PyObject
*args
)
518 if (!PyArg_ParseTuple(args
, "|i", &duration
))
525 static char WMAvailable_doc
[] =
526 "True if this process can interact with the display."
527 "Will foreground the application on the first call as a side-effect."
531 MacOS_WMAvailable(PyObject
*self
, PyObject
*args
)
533 static PyObject
*rv
= NULL
;
535 if (!PyArg_ParseTuple(args
, ""))
538 #if TARGET_API_MAC_OSX
539 ProcessSerialNumber psn
;
542 ** This is a fairly innocuous call to make if we don't have a window
543 ** manager, or if we have no permission to talk to it. It will print
544 ** a message on stderr, but at least it won't abort the process.
545 ** It appears the function caches the result itself, and it's cheap, so
546 ** no need for us to cache.
548 if (CGMainDisplayID() == 0) {
551 if (GetCurrentProcess(&psn
) < 0 ||
552 SetFrontProcess(&psn
) < 0) {
566 static char GetTicks_doc
[] = "Return number of ticks since bootup";
569 MacOS_GetTicks(PyObject
*self
, PyObject
*args
)
571 return Py_BuildValue("i", (int)TickCount());
574 static char openrf_doc
[] = "Open resource fork of a file";
577 MacOS_openrf(PyObject
*self
, PyObject
*args
)
582 SignedByte permission
= 1;
585 if (!PyArg_ParseTuple(args
, "O&|s", PyMac_GetFSSpec
, &fss
, &mode
))
590 case 'r': permission
= 1; break;
591 case 'w': permission
= 2; break;
599 if ( (fp
= newrfobject()) == NULL
)
602 err
= HOpenRF(fss
.vRefNum
, fss
.parID
, fss
.name
, permission
, &fp
->fRefNum
);
604 if ( err
== fnfErr
) {
605 /* In stead of doing complicated things here to get creator/type
606 ** correct we let the standard i/o library handle it
609 char pathname
[PATHNAMELEN
];
611 if ( (err
=PyMac_GetFullPathname(&fss
, pathname
, PATHNAMELEN
)) ) {
617 if ( (tfp
= fopen(pathname
, "w")) == NULL
) {
618 PyMac_Error(fnfErr
); /* What else... */
623 err
= HOpenRF(fss
.vRefNum
, fss
.parID
, fss
.name
, permission
, &fp
->fRefNum
);
631 return (PyObject
*)fp
;
634 #if !TARGET_API_MAC_OSX
635 static char FreeMem_doc
[] = "Return the total amount of free space in the heap";
638 MacOS_FreeMem(PyObject
*self
, PyObject
*args
)
642 if (!PyArg_ParseTuple(args
, ""))
645 return Py_BuildValue("l", rv
);
648 static char MaxBlock_doc
[] = "Return the largest contiguous block of free space in the heap";
651 MacOS_MaxBlock(PyObject
*self
, PyObject
*args
)
655 if (!PyArg_ParseTuple(args
, ""))
658 return Py_BuildValue("l", rv
);
661 static char CompactMem_doc
[] = "(wanted size)->actual largest block after compacting";
664 MacOS_CompactMem(PyObject
*self
, PyObject
*args
)
669 if (!PyArg_ParseTuple(args
, "l", &value
))
671 rv
= CompactMem(value
);
672 return Py_BuildValue("l", rv
);
675 static char KeepConsole_doc
[] = "(flag) Keep console open 0:never, 1:on output 2:on error, 3:always";
678 MacOS_KeepConsole(PyObject
*self
, PyObject
*args
)
682 if (!PyArg_ParseTuple(args
, "i", &value
))
684 PyMac_options
.keep_console
= value
;
689 static char OutputSeen_doc
[] = "Call to reset the 'unseen output' flag for the keep-console-open option";
692 MacOS_OutputSeen(PyObject
*self
, PyObject
*args
)
694 if (!PyArg_ParseTuple(args
, ""))
700 #endif /* !TARGET_API_MAC_OSX */
702 static PyMethodDef MacOS_Methods
[] = {
703 {"GetCreatorAndType", MacOS_GetCreatorAndType
, 1, getcrtp_doc
},
704 {"SetCreatorAndType", MacOS_SetCreatorAndType
, 1, setcrtp_doc
},
705 #if !TARGET_API_MAC_OSX
706 {"SchedParams", MacOS_SchedParams
, 1, schedparams_doc
},
707 {"EnableAppswitch", MacOS_EnableAppswitch
, 1, appswitch_doc
},
708 {"SetEventHandler", MacOS_SetEventHandler
, 1, setevh_doc
},
709 {"HandleEvent", MacOS_HandleEvent
, 1, handleev_doc
},
711 {"GetErrorString", MacOS_GetErrorString
, 1, geterr_doc
},
712 {"openrf", MacOS_openrf
, 1, openrf_doc
},
713 {"splash", MacOS_splash
, 1, splash_doc
},
714 {"DebugStr", MacOS_DebugStr
, 1, DebugStr_doc
},
715 {"GetTicks", MacOS_GetTicks
, 1, GetTicks_doc
},
716 {"SysBeep", MacOS_SysBeep
, 1, SysBeep_doc
},
717 {"WMAvailable", MacOS_WMAvailable
, 1, WMAvailable_doc
},
718 #if !TARGET_API_MAC_OSX
719 {"FreeMem", MacOS_FreeMem
, 1, FreeMem_doc
},
720 {"MaxBlock", MacOS_MaxBlock
, 1, MaxBlock_doc
},
721 {"CompactMem", MacOS_CompactMem
, 1, CompactMem_doc
},
722 {"KeepConsole", MacOS_KeepConsole
, 1, KeepConsole_doc
},
723 {"OutputSeen", MacOS_OutputSeen
, 1, OutputSeen_doc
},
725 {NULL
, NULL
} /* Sentinel */
734 m
= Py_InitModule("MacOS", MacOS_Methods
);
735 d
= PyModule_GetDict(m
);
737 /* Initialize MacOS.Error exception */
738 MacOS_Error
= PyMac_GetOSErrException();
739 if (MacOS_Error
== NULL
|| PyDict_SetItemString(d
, "Error", MacOS_Error
) != 0)
741 Rftype
.ob_type
= &PyType_Type
;
743 if (PyDict_SetItemString(d
, "ResourceForkType", (PyObject
*)&Rftype
) != 0)
746 ** This is a hack: the following constant added to the id() of a string
747 ** object gives you the address of the data. Unfortunately, it is needed for
748 ** some of the image and sound processing interfaces on the mac:-(
751 PyStringObject
*p
= 0;
752 long off
= (long)&(p
->ob_sval
[0]);
754 if( PyDict_SetItemString(d
, "string_id_to_buffer", Py_BuildValue("i", off
)) != 0)
757 #if TARGET_API_MAC_OSX
758 #define PY_RUNTIMEMODEL "macho"
759 #elif TARGET_API_MAC_CARBON
760 #define PY_RUNTIMEMODEL "carbon"
762 #error "None of the TARGET_API_MAC_XXX I know about is set"
764 if (PyDict_SetItemString(d
, "runtimemodel",
765 Py_BuildValue("s", PY_RUNTIMEMODEL
)) != 0)
767 #if !TARGET_API_MAC_OSX
768 #define PY_LINKMODEL "cfm"
769 #elif defined(WITH_NEXT_FRAMEWORK)
770 #define PY_LINKMODEL "framework"
771 #elif defined(Py_ENABLE_SHARED)
772 #define PY_LINKMODEL "shared"
774 #define PY_LINKMODEL "static"
776 if (PyDict_SetItemString(d
, "linkmodel",
777 Py_BuildValue("s", PY_LINKMODEL
)) != 0)