diff options
Diffstat (limited to 'Mac/Modules/MacOS.c')
-rw-r--r-- | Mac/Modules/MacOS.c | 644 |
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; + +} |