summaryrefslogtreecommitdiffstats
path: root/Mac/Modules/MacOS.c
diff options
context:
space:
mode:
Diffstat (limited to 'Mac/Modules/MacOS.c')
-rw-r--r--Mac/Modules/MacOS.c644
1 files changed, 644 insertions, 0 deletions
diff --git a/Mac/Modules/MacOS.c b/Mac/Modules/MacOS.c
new file mode 100644
index 0000000..4eabb39
--- /dev/null
+++ b/Mac/Modules/MacOS.c
@@ -0,0 +1,644 @@
+/***********************************************************
+Copyright 1991-1997 by Stichting Mathematisch Centrum, Amsterdam,
+The Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Macintosh OS-specific interface */
+
+#include "Python.h"
+#include "pymactoolbox.h"
+
+#include <Carbon/Carbon.h>
+#include <ApplicationServices/ApplicationServices.h>
+
+static PyObject *MacOS_Error; /* Exception MacOS.Error */
+
+#define PATHNAMELEN 1024
+
+/* ----------------------------------------------------- */
+
+/* Declarations for objects of type Resource fork */
+
+typedef struct {
+ PyObject_HEAD
+ short fRefNum;
+ int isclosed;
+} rfobject;
+
+static PyTypeObject Rftype;
+
+
+
+/* ---------------------------------------------------------------- */
+
+static void
+do_close(rfobject *self)
+{
+ if (self->isclosed ) return;
+ (void)FSClose(self->fRefNum);
+ self->isclosed = 1;
+}
+
+static char rf_read__doc__[] =
+"Read data from resource fork"
+;
+
+static PyObject *
+rf_read(rfobject *self, PyObject *args)
+{
+ long n;
+ PyObject *v;
+ OSErr err;
+
+ if (self->isclosed) {
+ PyErr_SetString(PyExc_ValueError, "Operation on closed file");
+ return NULL;
+ }
+
+ if (!PyArg_ParseTuple(args, "l", &n))
+ return NULL;
+
+ v = PyString_FromStringAndSize((char *)NULL, n);
+ if (v == NULL)
+ return NULL;
+
+ err = FSRead(self->fRefNum, &n, PyString_AsString(v));
+ if (err && err != eofErr) {
+ PyMac_Error(err);
+ Py_DECREF(v);
+ return NULL;
+ }
+ _PyString_Resize(&v, n);
+ return v;
+}
+
+
+static char rf_write__doc__[] =
+"Write to resource fork"
+;
+
+static PyObject *
+rf_write(rfobject *self, PyObject *args)
+{
+ char *buffer;
+ long size;
+ OSErr err;
+
+ if (self->isclosed) {
+ PyErr_SetString(PyExc_ValueError, "Operation on closed file");
+ return NULL;
+ }
+ if (!PyArg_ParseTuple(args, "s#", &buffer, &size))
+ return NULL;
+ err = FSWrite(self->fRefNum, &size, buffer);
+ if (err) {
+ PyMac_Error(err);
+ return NULL;
+ }
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+
+static char rf_seek__doc__[] =
+"Set file position"
+;
+
+static PyObject *
+rf_seek(rfobject *self, PyObject *args)
+{
+ long amount, pos;
+ int whence = SEEK_SET;
+ long eof;
+ OSErr err;
+
+ if (self->isclosed) {
+ PyErr_SetString(PyExc_ValueError, "Operation on closed file");
+ return NULL;
+ }
+ if (!PyArg_ParseTuple(args, "l|i", &amount, &whence))
+ return NULL;
+
+ if ((err = GetEOF(self->fRefNum, &eof)))
+ goto ioerr;
+
+ switch (whence) {
+ case SEEK_CUR:
+ if ((err = GetFPos(self->fRefNum, &pos)))
+ goto ioerr;
+ break;
+ case SEEK_END:
+ pos = eof;
+ break;
+ case SEEK_SET:
+ pos = 0;
+ break;
+ default:
+ PyErr_BadArgument();
+ return NULL;
+ }
+
+ pos += amount;
+
+ /* Don't bother implementing seek past EOF */
+ if (pos > eof || pos < 0) {
+ PyErr_BadArgument();
+ return NULL;
+ }
+
+ if ((err = SetFPos(self->fRefNum, fsFromStart, pos)) ) {
+ioerr:
+ PyMac_Error(err);
+ return NULL;
+ }
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+
+static char rf_tell__doc__[] =
+"Get file position"
+;
+
+static PyObject *
+rf_tell(rfobject *self, PyObject *args)
+{
+ long where;
+ OSErr err;
+
+ if (self->isclosed) {
+ PyErr_SetString(PyExc_ValueError, "Operation on closed file");
+ return NULL;
+ }
+ if (!PyArg_ParseTuple(args, ""))
+ return NULL;
+ if ((err = GetFPos(self->fRefNum, &where)) ) {
+ PyMac_Error(err);
+ return NULL;
+ }
+ return PyInt_FromLong(where);
+}
+
+static char rf_close__doc__[] =
+"Close resource fork"
+;
+
+static PyObject *
+rf_close(rfobject *self, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ""))
+ return NULL;
+ do_close(self);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+
+static struct PyMethodDef rf_methods[] = {
+ {"read", (PyCFunction)rf_read, 1, rf_read__doc__},
+ {"write", (PyCFunction)rf_write, 1, rf_write__doc__},
+ {"seek", (PyCFunction)rf_seek, 1, rf_seek__doc__},
+ {"tell", (PyCFunction)rf_tell, 1, rf_tell__doc__},
+ {"close", (PyCFunction)rf_close, 1, rf_close__doc__},
+
+ {NULL, NULL} /* sentinel */
+};
+
+/* ---------- */
+
+
+static rfobject *
+newrfobject(void)
+{
+ rfobject *self;
+
+ self = PyObject_NEW(rfobject, &Rftype);
+ if (self == NULL)
+ return NULL;
+ self->isclosed = 1;
+ return self;
+}
+
+
+static void
+rf_dealloc(rfobject *self)
+{
+ do_close(self);
+ PyObject_DEL(self);
+}
+
+static PyObject *
+rf_getattr(rfobject *self, char *name)
+{
+ return Py_FindMethod(rf_methods, (PyObject *)self, name);
+}
+
+static char Rftype__doc__[] =
+"Resource fork file object"
+;
+
+static PyTypeObject Rftype = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0, /*ob_size*/
+ "MacOS.ResourceFork", /*tp_name*/
+ sizeof(rfobject), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ /* methods */
+ (destructor)rf_dealloc, /*tp_dealloc*/
+ (printfunc)0, /*tp_print*/
+ (getattrfunc)rf_getattr, /*tp_getattr*/
+ (setattrfunc)0, /*tp_setattr*/
+ (cmpfunc)0, /*tp_compare*/
+ (reprfunc)0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ (hashfunc)0, /*tp_hash*/
+ (ternaryfunc)0, /*tp_call*/
+ (reprfunc)0, /*tp_str*/
+
+ /* Space for future expansion */
+ 0L,0L,0L,0L,
+ Rftype__doc__ /* Documentation string */
+};
+
+/* End of code for Resource fork objects */
+/* -------------------------------------------------------- */
+
+/*----------------------------------------------------------------------*/
+/* Miscellaneous File System Operations */
+
+static char getcrtp_doc[] = "Get MacOS 4-char creator and type for a file";
+
+static PyObject *
+MacOS_GetCreatorAndType(PyObject *self, PyObject *args)
+{
+ FSSpec fss;
+ FInfo info;
+ PyObject *creator, *type, *res;
+ OSErr err;
+
+ if (!PyArg_ParseTuple(args, "O&", PyMac_GetFSSpec, &fss))
+ return NULL;
+ if ((err = FSpGetFInfo(&fss, &info)) != noErr)
+ return PyErr_Mac(MacOS_Error, err);
+ creator = PyString_FromStringAndSize((char *)&info.fdCreator, 4);
+ type = PyString_FromStringAndSize((char *)&info.fdType, 4);
+ res = Py_BuildValue("OO", creator, type);
+ Py_DECREF(creator);
+ Py_DECREF(type);
+ return res;
+}
+
+static char setcrtp_doc[] = "Set MacOS 4-char creator and type for a file";
+
+static PyObject *
+MacOS_SetCreatorAndType(PyObject *self, PyObject *args)
+{
+ FSSpec fss;
+ ResType creator, type;
+ FInfo info;
+ OSErr err;
+
+ if (!PyArg_ParseTuple(args, "O&O&O&",
+ PyMac_GetFSSpec, &fss, PyMac_GetOSType, &creator, PyMac_GetOSType, &type))
+ return NULL;
+ if ((err = FSpGetFInfo(&fss, &info)) != noErr)
+ return PyErr_Mac(MacOS_Error, err);
+ info.fdCreator = creator;
+ info.fdType = type;
+ if ((err = FSpSetFInfo(&fss, &info)) != noErr)
+ return PyErr_Mac(MacOS_Error, err);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+
+static char geterr_doc[] = "Convert OSErr number to string";
+
+static PyObject *
+MacOS_GetErrorString(PyObject *self, PyObject *args)
+{
+ int err;
+ char buf[256];
+ Handle h;
+ char *str;
+ static int errors_loaded;
+
+ if (!PyArg_ParseTuple(args, "i", &err))
+ return NULL;
+
+ h = GetResource('Estr', err);
+ if (!h && !errors_loaded) {
+ /*
+ ** Attempt to open the resource file containing the
+ ** Estr resources. We ignore all errors. We also try
+ ** this only once.
+ */
+ PyObject *m, *rv;
+ errors_loaded = 1;
+
+ m = PyImport_ImportModule("macresource");
+ if (!m) {
+ if (Py_VerboseFlag)
+ PyErr_Print();
+ PyErr_Clear();
+ }
+ else {
+ rv = PyObject_CallMethod(m, "open_error_resource", "");
+ if (!rv) {
+ if (Py_VerboseFlag)
+ PyErr_Print();
+ PyErr_Clear();
+ }
+ else {
+ Py_DECREF(rv);
+ /* And try again... */
+ h = GetResource('Estr', err);
+ }
+ Py_DECREF(m);
+ }
+ }
+ /*
+ ** Whether the code above succeeded or not, we won't try
+ ** again.
+ */
+ errors_loaded = 1;
+
+ if (h) {
+ HLock(h);
+ str = (char *)*h;
+ memcpy(buf, str+1, (unsigned char)str[0]);
+ buf[(unsigned char)str[0]] = '\0';
+ HUnlock(h);
+ ReleaseResource(h);
+ }
+ else {
+ PyOS_snprintf(buf, sizeof(buf), "Mac OS error code %d", err);
+ }
+
+ return Py_BuildValue("s", buf);
+}
+
+static char splash_doc[] = "Open a splash-screen dialog by resource-id (0=close)";
+
+static PyObject *
+MacOS_splash(PyObject *self, PyObject *args)
+{
+ int resid = -1;
+ static DialogPtr curdialog = NULL;
+ DialogPtr olddialog;
+ WindowRef theWindow;
+ CGrafPtr thePort;
+#if 0
+ short xpos, ypos, width, height, swidth, sheight;
+#endif
+
+ if (!PyArg_ParseTuple(args, "|i", &resid))
+ return NULL;
+ olddialog = curdialog;
+ curdialog = NULL;
+
+ if ( resid != -1 ) {
+ curdialog = GetNewDialog(resid, NULL, (WindowPtr)-1);
+ if ( curdialog ) {
+ theWindow = GetDialogWindow(curdialog);
+ thePort = GetWindowPort(theWindow);
+#if 0
+ width = thePort->portRect.right - thePort->portRect.left;
+ height = thePort->portRect.bottom - thePort->portRect.top;
+ swidth = qd.screenBits.bounds.right - qd.screenBits.bounds.left;
+ sheight = qd.screenBits.bounds.bottom - qd.screenBits.bounds.top - LMGetMBarHeight();
+ xpos = (swidth-width)/2;
+ ypos = (sheight-height)/5 + LMGetMBarHeight();
+ MoveWindow(theWindow, xpos, ypos, 0);
+ ShowWindow(theWindow);
+#endif
+ DrawDialog(curdialog);
+ }
+ }
+ if (olddialog)
+ DisposeDialog(olddialog);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static char DebugStr_doc[] = "Switch to low-level debugger with a message";
+
+static PyObject *
+MacOS_DebugStr(PyObject *self, PyObject *args)
+{
+ Str255 message;
+ PyObject *object = 0;
+
+ if (!PyArg_ParseTuple(args, "O&|O", PyMac_GetStr255, message, &object))
+ return NULL;
+ DebugStr(message);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static char SysBeep_doc[] = "BEEEEEP!!!";
+
+static PyObject *
+MacOS_SysBeep(PyObject *self, PyObject *args)
+{
+ int duration = 6;
+
+ if (!PyArg_ParseTuple(args, "|i", &duration))
+ return NULL;
+ SysBeep(duration);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static char WMAvailable_doc[] =
+ "True if this process can interact with the display."
+ "Will foreground the application on the first call as a side-effect."
+ ;
+
+static PyObject *
+MacOS_WMAvailable(PyObject *self, PyObject *args)
+{
+ static PyObject *rv = NULL;
+
+ if (!PyArg_ParseTuple(args, ""))
+ return NULL;
+ if (!rv) {
+ ProcessSerialNumber psn;
+
+ /*
+ ** This is a fairly innocuous call to make if we don't have a window
+ ** manager, or if we have no permission to talk to it. It will print
+ ** a message on stderr, but at least it won't abort the process.
+ ** It appears the function caches the result itself, and it's cheap, so
+ ** no need for us to cache.
+ */
+#ifdef kCGNullDirectDisplay
+ /* On 10.1 CGMainDisplayID() isn't available, and
+ ** kCGNullDirectDisplay isn't defined.
+ */
+ if (CGMainDisplayID() == 0) {
+ rv = Py_False;
+ } else {
+#else
+ {
+#endif
+ if (GetCurrentProcess(&psn) < 0 ||
+ SetFrontProcess(&psn) < 0) {
+ rv = Py_False;
+ } else {
+ rv = Py_True;
+ }
+ }
+ }
+ Py_INCREF(rv);
+ return rv;
+}
+
+static char GetTicks_doc[] = "Return number of ticks since bootup";
+
+static PyObject *
+MacOS_GetTicks(PyObject *self, PyObject *args)
+{
+ return Py_BuildValue("i", (int)TickCount());
+}
+
+static char openrf_doc[] = "Open resource fork of a file";
+
+static PyObject *
+MacOS_openrf(PyObject *self, PyObject *args)
+{
+ OSErr err;
+ char *mode = "r";
+ FSSpec fss;
+ SignedByte permission = 1;
+ rfobject *fp;
+
+ if (!PyArg_ParseTuple(args, "O&|s", PyMac_GetFSSpec, &fss, &mode))
+ return NULL;
+ while (*mode) {
+ switch (*mode++) {
+ case '*': break;
+ case 'r': permission = 1; break;
+ case 'w': permission = 2; break;
+ case 'b': break;
+ default:
+ PyErr_BadArgument();
+ return NULL;
+ }
+ }
+
+ if ( (fp = newrfobject()) == NULL )
+ return NULL;
+
+ err = HOpenRF(fss.vRefNum, fss.parID, fss.name, permission, &fp->fRefNum);
+
+ if ( err == fnfErr ) {
+ /* In stead of doing complicated things here to get creator/type
+ ** correct we let the standard i/o library handle it
+ */
+ FILE *tfp;
+ char pathname[PATHNAMELEN];
+
+ if ( (err=PyMac_GetFullPathname(&fss, pathname, PATHNAMELEN)) ) {
+ PyMac_Error(err);
+ Py_DECREF(fp);
+ return NULL;
+ }
+
+ if ( (tfp = fopen(pathname, "w")) == NULL ) {
+ PyMac_Error(fnfErr); /* What else... */
+ Py_DECREF(fp);
+ return NULL;
+ }
+ fclose(tfp);
+ err = HOpenRF(fss.vRefNum, fss.parID, fss.name, permission, &fp->fRefNum);
+ }
+ if ( err ) {
+ Py_DECREF(fp);
+ PyMac_Error(err);
+ return NULL;
+ }
+ fp->isclosed = 0;
+ return (PyObject *)fp;
+}
+
+
+static PyMethodDef MacOS_Methods[] = {
+ {"GetCreatorAndType", MacOS_GetCreatorAndType, 1, getcrtp_doc},
+ {"SetCreatorAndType", MacOS_SetCreatorAndType, 1, setcrtp_doc},
+ {"GetErrorString", MacOS_GetErrorString, 1, geterr_doc},
+ {"openrf", MacOS_openrf, 1, openrf_doc},
+ {"splash", MacOS_splash, 1, splash_doc},
+ {"DebugStr", MacOS_DebugStr, 1, DebugStr_doc},
+ {"GetTicks", MacOS_GetTicks, 1, GetTicks_doc},
+ {"SysBeep", MacOS_SysBeep, 1, SysBeep_doc},
+ {"WMAvailable", MacOS_WMAvailable, 1, WMAvailable_doc},
+ {NULL, NULL} /* Sentinel */
+};
+
+
+void
+initMacOS(void)
+{
+ PyObject *m, *d;
+
+ m = Py_InitModule("MacOS", MacOS_Methods);
+ d = PyModule_GetDict(m);
+
+ /* Initialize MacOS.Error exception */
+ MacOS_Error = PyMac_GetOSErrException();
+ if (MacOS_Error == NULL || PyDict_SetItemString(d, "Error", MacOS_Error) != 0)
+ return;
+ Rftype.ob_type = &PyType_Type;
+ Py_INCREF(&Rftype);
+ if (PyDict_SetItemString(d, "ResourceForkType", (PyObject *)&Rftype) != 0)
+ return;
+ /*
+ ** This is a hack: the following constant added to the id() of a string
+ ** object gives you the address of the data. Unfortunately, it is needed for
+ ** some of the image and sound processing interfaces on the mac:-(
+ */
+ {
+ PyStringObject *p = 0;
+ long off = (long)&(p->ob_sval[0]);
+
+ if( PyDict_SetItemString(d, "string_id_to_buffer", Py_BuildValue("i", off)) != 0)
+ return;
+ }
+#define PY_RUNTIMEMODEL "macho"
+ if (PyDict_SetItemString(d, "runtimemodel",
+ Py_BuildValue("s", PY_RUNTIMEMODEL)) != 0)
+ return;
+#if defined(WITH_NEXT_FRAMEWORK)
+#define PY_LINKMODEL "framework"
+#elif defined(Py_ENABLE_SHARED)
+#define PY_LINKMODEL "shared"
+#else
+#define PY_LINKMODEL "static"
+#endif
+ if (PyDict_SetItemString(d, "linkmodel",
+ Py_BuildValue("s", PY_LINKMODEL)) != 0)
+ return;
+
+}