Home | History | Annotate | Download | only in Python
      1 /***********************************************************
      2 Copyright 1991-1997 by Stichting Mathematisch Centrum, Amsterdam,
      3 The Netherlands.
      4 
      5                         All Rights Reserved
      6 
      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.
     14 
     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.
     22 
     23 ******************************************************************/
     24 
     25 
     26 #include "Python.h"
     27 #include "pymactoolbox.h"
     28 #include <arpa/inet.h>  /* for ntohl, htonl */
     29 
     30 
     31 /* Like strerror() but for Mac OS error numbers */
     32 char *
     33 PyMac_StrError(int err)
     34 {
     35     static char buf[256];
     36     PyObject *m;
     37     PyObject *rv;
     38 
     39     m = PyImport_ImportModuleNoBlock("MacOS");
     40     if (!m) {
     41         if (Py_VerboseFlag)
     42             PyErr_Print();
     43         PyErr_Clear();
     44         rv = NULL;
     45     }
     46     else {
     47         rv = PyObject_CallMethod(m, "GetErrorString", "i", err);
     48         if (!rv)
     49             PyErr_Clear();
     50     }
     51     if (!rv) {
     52         buf[0] = '\0';
     53     }
     54     else {
     55         char *input = PyString_AsString(rv);
     56         if (!input) {
     57             PyErr_Clear();
     58             buf[0] = '\0';
     59         } else {
     60             strncpy(buf, input, sizeof(buf) - 1);
     61             buf[sizeof(buf) - 1] = '\0';
     62         }
     63         Py_DECREF(rv);
     64     }
     65     Py_XDECREF(m);
     66     return buf;
     67 }
     68 
     69 /* Exception object shared by all Mac specific modules for Mac OS errors */
     70 PyObject *PyMac_OSErrException;
     71 
     72 /* Initialize and return PyMac_OSErrException */
     73 PyObject *
     74 PyMac_GetOSErrException(void)
     75 {
     76     if (PyMac_OSErrException == NULL)
     77         PyMac_OSErrException = PyErr_NewException("MacOS.Error", NULL, NULL);
     78     return PyMac_OSErrException;
     79 }
     80 
     81 /* Set a MAC-specific error from errno, and return NULL; return None if no error */
     82 PyObject *
     83 PyErr_Mac(PyObject *eobj, int err)
     84 {
     85     char *msg;
     86     PyObject *v;
     87 
     88     if (err == 0 && !PyErr_Occurred()) {
     89         Py_INCREF(Py_None);
     90         return Py_None;
     91     }
     92     if (err == -1 && PyErr_Occurred())
     93         return NULL;
     94     msg = PyMac_StrError(err);
     95     v = Py_BuildValue("(is)", err, msg);
     96     PyErr_SetObject(eobj, v);
     97     Py_DECREF(v);
     98     return NULL;
     99 }
    100 
    101 /* Call PyErr_Mac with PyMac_OSErrException */
    102 PyObject *
    103 PyMac_Error(OSErr err)
    104 {
    105     return PyErr_Mac(PyMac_GetOSErrException(), err);
    106 }
    107 
    108 
    109 #ifndef __LP64__
    110 OSErr
    111 PyMac_GetFullPathname(FSSpec *fss, char *path, int len)
    112 {
    113     PyObject *fs, *exc;
    114     PyObject *rv = NULL;
    115     char *input;
    116     OSErr err = noErr;
    117 
    118     *path = '\0';
    119 
    120     fs = PyMac_BuildFSSpec(fss);
    121     if (!fs)
    122         goto error;
    123 
    124     rv = PyObject_CallMethod(fs, "as_pathname", "");
    125     if (!rv)
    126         goto error;
    127 
    128     input = PyString_AsString(rv);
    129     if (!input)
    130         goto error;
    131 
    132     strncpy(path, input, len - 1);
    133     path[len - 1] = '\0';
    134 
    135     Py_XDECREF(rv);
    136     Py_XDECREF(fs);
    137     return err;
    138 
    139   error:
    140     exc = PyErr_Occurred();
    141     if (exc  && PyErr_GivenExceptionMatches(exc,
    142                                             PyMac_GetOSErrException())) {
    143         PyObject *args = PyObject_GetAttrString(exc, "args");
    144         if (args) {
    145             char *ignore;
    146             PyArg_ParseTuple(args, "is", &err, &ignore);
    147             Py_XDECREF(args);
    148         }
    149     }
    150     if (err == noErr)
    151         err = -1;
    152     PyErr_Clear();
    153     Py_XDECREF(rv);
    154     Py_XDECREF(fs);
    155     return err;
    156 }
    157 #endif /* !__LP64__ */
    158 
    159 /* Convert a 4-char string object argument to an OSType value */
    160 int
    161 PyMac_GetOSType(PyObject *v, OSType *pr)
    162 {
    163     uint32_t tmp;
    164     if (!PyString_Check(v) || PyString_Size(v) != 4) {
    165         PyErr_SetString(PyExc_TypeError,
    166             "OSType arg must be string of 4 chars");
    167         return 0;
    168     }
    169     memcpy((char *)&tmp, PyString_AsString(v), 4);
    170     *pr = (OSType)ntohl(tmp);
    171     return 1;
    172 }
    173 
    174 /* Convert an OSType value to a 4-char string object */
    175 PyObject *
    176 PyMac_BuildOSType(OSType t)
    177 {
    178     uint32_t tmp = htonl((uint32_t)t);
    179     return PyString_FromStringAndSize((char *)&tmp, 4);
    180 }
    181 
    182 /* Convert an NumVersion value to a 4-element tuple */
    183 PyObject *
    184 PyMac_BuildNumVersion(NumVersion t)
    185 {
    186     return Py_BuildValue("(hhhh)", t.majorRev, t.minorAndBugRev, t.stage, t.nonRelRev);
    187 }
    188 
    189 
    190 /* Convert a Python string object to a Str255 */
    191 int
    192 PyMac_GetStr255(PyObject *v, Str255 pbuf)
    193 {
    194     int len;
    195     if (!PyString_Check(v) || (len = PyString_Size(v)) > 255) {
    196         PyErr_SetString(PyExc_TypeError,
    197             "Str255 arg must be string of at most 255 chars");
    198         return 0;
    199     }
    200     pbuf[0] = len;
    201     memcpy((char *)(pbuf+1), PyString_AsString(v), len);
    202     return 1;
    203 }
    204 
    205 /* Convert a Str255 to a Python string object */
    206 PyObject *
    207 PyMac_BuildStr255(Str255 s)
    208 {
    209     if ( s == NULL ) {
    210         PyErr_SetString(PyExc_SystemError, "Str255 pointer is NULL");
    211         return NULL;
    212     }
    213     return PyString_FromStringAndSize((char *)&s[1], (int)s[0]);
    214 }
    215 
    216 PyObject *
    217 PyMac_BuildOptStr255(Str255 s)
    218 {
    219     if ( s == NULL ) {
    220         Py_INCREF(Py_None);
    221         return Py_None;
    222     }
    223     return PyString_FromStringAndSize((char *)&s[1], (int)s[0]);
    224 }
    225 
    226 
    227 
    228 /* Convert a Python object to a Rect.
    229    The object must be a (left, top, right, bottom) tuple.
    230    (This differs from the order in the struct but is consistent with
    231    the arguments to SetRect(), and also with STDWIN). */
    232 int
    233 PyMac_GetRect(PyObject *v, Rect *r)
    234 {
    235     return PyArg_Parse(v, "(hhhh)", &r->left, &r->top, &r->right, &r->bottom);
    236 }
    237 
    238 /* Convert a Rect to a Python object */
    239 PyObject *
    240 PyMac_BuildRect(Rect *r)
    241 {
    242     return Py_BuildValue("(hhhh)", r->left, r->top, r->right, r->bottom);
    243 }
    244 
    245 
    246 /* Convert a Python object to a Point.
    247    The object must be a (h, v) tuple.
    248    (This differs from the order in the struct but is consistent with
    249    the arguments to SetPoint(), and also with STDWIN). */
    250 int
    251 PyMac_GetPoint(PyObject *v, Point *p)
    252 {
    253     return PyArg_Parse(v, "(hh)", &p->h, &p->v);
    254 }
    255 
    256 /* Convert a Point to a Python object */
    257 PyObject *
    258 PyMac_BuildPoint(Point p)
    259 {
    260     return Py_BuildValue("(hh)", p.h, p.v);
    261 }
    262 
    263 
    264 /* Convert a Python object to an EventRecord.
    265    The object must be a (what, message, when, (v, h), modifiers) tuple. */
    266 int
    267 PyMac_GetEventRecord(PyObject *v, EventRecord *e)
    268 {
    269     return PyArg_Parse(v, "(Hkk(hh)H)",
    270                        &e->what,
    271                        &e->message,
    272                        &e->when,
    273                        &e->where.h,
    274                        &e->where.v,
    275                        &e->modifiers);
    276 }
    277 
    278 /* Convert a Rect to an EventRecord object */
    279 PyObject *
    280 PyMac_BuildEventRecord(EventRecord *e)
    281 {
    282     return Py_BuildValue("(hll(hh)h)",
    283                          e->what,
    284                          e->message,
    285                          e->when,
    286                          e->where.h,
    287                          e->where.v,
    288                          e->modifiers);
    289 }
    290 
    291 /* Convert Python object to Fixed */
    292 int
    293 PyMac_GetFixed(PyObject *v, Fixed *f)
    294 {
    295     double d;
    296 
    297     if( !PyArg_Parse(v, "d", &d))
    298         return 0;
    299     *f = (Fixed)(d * 0x10000);
    300     return 1;
    301 }
    302 
    303 /* Convert a Fixed to a Python object */
    304 PyObject *
    305 PyMac_BuildFixed(Fixed f)
    306 {
    307     double d;
    308 
    309     d = f;
    310     d = d / 0x10000;
    311     return Py_BuildValue("d", d);
    312 }
    313 
    314 /* Convert wide to/from Python int or (hi, lo) tuple. XXXX Should use Python longs */
    315 int
    316 PyMac_Getwide(PyObject *v, wide *rv)
    317 {
    318     if (PyInt_Check(v)) {
    319         rv->hi = 0;
    320         rv->lo = PyInt_AsLong(v);
    321         if( rv->lo & 0x80000000 )
    322             rv->hi = -1;
    323         return 1;
    324     }
    325     return PyArg_Parse(v, "(kk)", &rv->hi, &rv->lo);
    326 }
    327 
    328 
    329 PyObject *
    330 PyMac_Buildwide(wide *w)
    331 {
    332     if ( (w->hi == 0 && (w->lo & 0x80000000) == 0) ||
    333          (w->hi == -1 && (w->lo & 0x80000000) ) )
    334         return PyInt_FromLong(w->lo);
    335     return Py_BuildValue("(ll)", w->hi, w->lo);
    336 }
    337 
    338 #ifdef USE_TOOLBOX_OBJECT_GLUE
    339 /*
    340 ** Glue together the toolbox objects.
    341 **
    342 ** Because toolbox modules interdepend on each other, they use each others
    343 ** object types, on MacOSX/MachO this leads to the situation that they
    344 ** cannot be dynamically loaded (or they would all have to be lumped into
    345 ** a single .so, but this would be bad for extensibility).
    346 **
    347 ** This file defines wrappers for all the _New and _Convert functions,
    348 ** which are the Py_BuildValue and PyArg_ParseTuple helpers. The wrappers
    349 ** check an indirection function pointer, and if it isn't filled in yet
    350 ** they import the appropriate module, whose init routine should fill in
    351 ** the pointer.
    352 */
    353 
    354 #define GLUE_NEW(object, routinename, module) \
    355 PyObject *(*PyMacGluePtr_##routinename)(object); \
    356 \
    357 PyObject *routinename(object cobj) { \
    358     if (!PyMacGluePtr_##routinename) { \
    359        if (!PyImport_ImportModule(module)) return NULL; \
    360        if (!PyMacGluePtr_##routinename) { \
    361        PyErr_SetString(PyExc_ImportError, "Module did not provide routine: " module ": " #routinename); \
    362        return NULL; \
    363        } \
    364     } \
    365     return (*PyMacGluePtr_##routinename)(cobj); \
    366 }
    367 
    368 #define GLUE_CONVERT(object, routinename, module) \
    369 int (*PyMacGluePtr_##routinename)(PyObject *, object *); \
    370 \
    371 int routinename(PyObject *pyobj, object *cobj) { \
    372     if (!PyMacGluePtr_##routinename) { \
    373        if (!PyImport_ImportModule(module)) return 0; \
    374        if (!PyMacGluePtr_##routinename) { \
    375        PyErr_SetString(PyExc_ImportError, "Module did not provide routine: " module ": " #routinename); \
    376        return 0; \
    377        } \
    378     } \
    379     return (*PyMacGluePtr_##routinename)(pyobj, cobj); \
    380 }
    381 
    382 GLUE_NEW(FSSpec *, PyMac_BuildFSSpec, "Carbon.File")
    383 GLUE_CONVERT(FSSpec, PyMac_GetFSSpec, "Carbon.File")
    384 GLUE_NEW(FSRef *, PyMac_BuildFSRef, "Carbon.File")
    385 GLUE_CONVERT(FSRef, PyMac_GetFSRef, "Carbon.File")
    386 
    387 GLUE_NEW(AppleEvent *, AEDesc_New, "Carbon.AE") /* XXXX Why by address? */
    388 GLUE_NEW(AppleEvent *, AEDesc_NewBorrowed, "Carbon.AE")
    389 GLUE_CONVERT(AppleEvent, AEDesc_Convert, "Carbon.AE")
    390 
    391 GLUE_NEW(Component, CmpObj_New, "Carbon.Cm")
    392 GLUE_CONVERT(Component, CmpObj_Convert, "Carbon.Cm")
    393 GLUE_NEW(ComponentInstance, CmpInstObj_New, "Carbon.Cm")
    394 GLUE_CONVERT(ComponentInstance, CmpInstObj_Convert, "Carbon.Cm")
    395 
    396 GLUE_NEW(ControlHandle, CtlObj_New, "Carbon.Ctl")
    397 GLUE_CONVERT(ControlHandle, CtlObj_Convert, "Carbon.Ctl")
    398 
    399 GLUE_NEW(DialogPtr, DlgObj_New, "Carbon.Dlg")
    400 GLUE_CONVERT(DialogPtr, DlgObj_Convert, "Carbon.Dlg")
    401 GLUE_NEW(DialogPtr, DlgObj_WhichDialog, "Carbon.Dlg")
    402 
    403 GLUE_NEW(DragReference, DragObj_New, "Carbon.Drag")
    404 GLUE_CONVERT(DragReference, DragObj_Convert, "Carbon.Drag")
    405 
    406 GLUE_NEW(ListHandle, ListObj_New, "Carbon.List")
    407 GLUE_CONVERT(ListHandle, ListObj_Convert, "Carbon.List")
    408 
    409 GLUE_NEW(MenuHandle, MenuObj_New, "Carbon.Menu")
    410 GLUE_CONVERT(MenuHandle, MenuObj_Convert, "Carbon.Menu")
    411 
    412 GLUE_NEW(GrafPtr, GrafObj_New, "Carbon.Qd")
    413 GLUE_CONVERT(GrafPtr, GrafObj_Convert, "Carbon.Qd")
    414 GLUE_NEW(BitMapPtr, BMObj_New, "Carbon.Qd")
    415 GLUE_CONVERT(BitMapPtr, BMObj_Convert, "Carbon.Qd")
    416 GLUE_NEW(RGBColor *, QdRGB_New, "Carbon.Qd") /* XXXX Why? */
    417 GLUE_CONVERT(RGBColor, QdRGB_Convert, "Carbon.Qd")
    418 
    419 GLUE_NEW(GWorldPtr, GWorldObj_New, "Carbon.Qdoffs")
    420 GLUE_CONVERT(GWorldPtr, GWorldObj_Convert, "Carbon.Qdoffs")
    421 
    422 #ifndef __LP64__
    423 GLUE_NEW(Track, TrackObj_New, "Carbon.Qt")
    424 GLUE_CONVERT(Track, TrackObj_Convert, "Carbon.Qt")
    425 GLUE_NEW(Movie, MovieObj_New, "Carbon.Qt")
    426 GLUE_CONVERT(Movie, MovieObj_Convert, "Carbon.Qt")
    427 GLUE_NEW(MovieController, MovieCtlObj_New, "Carbon.Qt")
    428 GLUE_CONVERT(MovieController, MovieCtlObj_Convert, "Carbon.Qt")
    429 GLUE_NEW(TimeBase, TimeBaseObj_New, "Carbon.Qt")
    430 GLUE_CONVERT(TimeBase, TimeBaseObj_Convert, "Carbon.Qt")
    431 GLUE_NEW(UserData, UserDataObj_New, "Carbon.Qt")
    432 GLUE_CONVERT(UserData, UserDataObj_Convert, "Carbon.Qt")
    433 GLUE_NEW(Media, MediaObj_New, "Carbon.Qt")
    434 GLUE_CONVERT(Media, MediaObj_Convert, "Carbon.Qt")
    435 #endif /* !__LP64__ */
    436 
    437 GLUE_NEW(Handle, ResObj_New, "Carbon.Res")
    438 GLUE_CONVERT(Handle, ResObj_Convert, "Carbon.Res")
    439 GLUE_NEW(Handle, OptResObj_New, "Carbon.Res")
    440 GLUE_CONVERT(Handle, OptResObj_Convert, "Carbon.Res")
    441 
    442 GLUE_NEW(TEHandle, TEObj_New, "Carbon.TE")
    443 GLUE_CONVERT(TEHandle, TEObj_Convert, "Carbon.TE")
    444 
    445 GLUE_NEW(WindowPtr, WinObj_New, "Carbon.Win")
    446 GLUE_CONVERT(WindowPtr, WinObj_Convert, "Carbon.Win")
    447 GLUE_NEW(WindowPtr, WinObj_WhichWindow, "Carbon.Win")
    448 
    449 GLUE_CONVERT(CFTypeRef, CFObj_Convert, "Carbon.CF")
    450 GLUE_NEW(CFTypeRef, CFObj_New, "Carbon.CF")
    451 
    452 GLUE_CONVERT(CFTypeRef, CFTypeRefObj_Convert, "Carbon.CF")
    453 GLUE_NEW(CFTypeRef, CFTypeRefObj_New, "Carbon.CF")
    454 
    455 GLUE_CONVERT(CFStringRef, CFStringRefObj_Convert, "Carbon.CF")
    456 GLUE_NEW(CFStringRef, CFStringRefObj_New, "Carbon.CF")
    457 GLUE_CONVERT(CFMutableStringRef, CFMutableStringRefObj_Convert, "Carbon.CF")
    458 GLUE_NEW(CFMutableStringRef, CFMutableStringRefObj_New, "Carbon.CF")
    459 
    460 GLUE_CONVERT(CFArrayRef, CFArrayRefObj_Convert, "Carbon.CF")
    461 GLUE_NEW(CFArrayRef, CFArrayRefObj_New, "Carbon.CF")
    462 GLUE_CONVERT(CFMutableArrayRef, CFMutableArrayRefObj_Convert, "Carbon.CF")
    463 GLUE_NEW(CFMutableArrayRef, CFMutableArrayRefObj_New, "Carbon.CF")
    464 
    465 GLUE_CONVERT(CFDictionaryRef, CFDictionaryRefObj_Convert, "Carbon.CF")
    466 GLUE_NEW(CFDictionaryRef, CFDictionaryRefObj_New, "Carbon.CF")
    467 GLUE_CONVERT(CFMutableDictionaryRef, CFMutableDictionaryRefObj_Convert, "Carbon.CF")
    468 GLUE_NEW(CFMutableDictionaryRef, CFMutableDictionaryRefObj_New, "Carbon.CF")
    469 
    470 GLUE_CONVERT(CFURLRef, CFURLRefObj_Convert, "Carbon.CF")
    471 GLUE_CONVERT(CFURLRef, OptionalCFURLRefObj_Convert, "Carbon.CF")
    472 GLUE_NEW(CFURLRef, CFURLRefObj_New, "Carbon.CF")
    473 
    474 #endif /* USE_TOOLBOX_OBJECT_GLUE */
    475