blob: 406b00238f0cf05b243c249fc0c1b05831b4ecc2 [file] [log] [blame]
Jack Jansen94bebc02001-08-08 13:17:31 +00001/***********************************************************
2Copyright 1991-1997 by Stichting Mathematisch Centrum, Amsterdam,
3The Netherlands.
4
5 All Rights Reserved
6
7Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
9provided that the above copyright notice appear in all copies and that
10both that copyright notice and this permission notice appear in
11supporting documentation, and that the names of Stichting Mathematisch
12Centrum or CWI not be used in advertising or publicity pertaining to
13distribution of the software without specific, written prior permission.
14
15STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22
23******************************************************************/
24
25
26#include "Python.h"
Jack Jansen94bebc02001-08-08 13:17:31 +000027#include "pymactoolbox.h"
28
Jack Jansen94bebc02001-08-08 13:17:31 +000029
Jack Jansen94bebc02001-08-08 13:17:31 +000030/* Like strerror() but for Mac OS error numbers */
Raymond Hettingerec6eb362004-11-05 07:02:59 +000031char *
32PyMac_StrError(int err)
Jack Jansen94bebc02001-08-08 13:17:31 +000033{
34 static char buf[256];
Raymond Hettingerec6eb362004-11-05 07:02:59 +000035 PyObject *m;
36 PyObject *rv;
37
38 m = PyImport_ImportModule("MacOS");
39 if (!m) {
40 if (Py_VerboseFlag)
41 PyErr_Print();
42 PyErr_Clear();
43 rv = NULL;
44 }
45 else {
46 rv = PyObject_CallMethod(m, "GetErrorString", "i", err);
47 if (!rv)
Jack Jansendde800e2002-11-07 23:07:05 +000048 PyErr_Clear();
Raymond Hettingerec6eb362004-11-05 07:02:59 +000049 }
50 if (!rv) {
51 buf[0] = '\0';
52 }
53 else {
54 char *input = PyString_AsString(rv);
55 if (!input) {
56 PyErr_Clear();
57 buf[0] = '\0';
Jack Jansendde800e2002-11-07 23:07:05 +000058 } else {
Raymond Hettingerec6eb362004-11-05 07:02:59 +000059 strncpy(buf, input, sizeof(buf) - 1);
60 buf[sizeof(buf) - 1] = '\0';
Jack Jansendde800e2002-11-07 23:07:05 +000061 }
62 }
Raymond Hettingerec6eb362004-11-05 07:02:59 +000063
Jack Jansen94bebc02001-08-08 13:17:31 +000064 return buf;
65}
66
67/* Exception object shared by all Mac specific modules for Mac OS errors */
68PyObject *PyMac_OSErrException;
69
70/* Initialize and return PyMac_OSErrException */
71PyObject *
Jack Jansen697842f2001-09-10 22:00:39 +000072PyMac_GetOSErrException(void)
Jack Jansen94bebc02001-08-08 13:17:31 +000073{
74 if (PyMac_OSErrException == NULL)
Jack Jansen8fce2ef2002-10-19 22:02:21 +000075 PyMac_OSErrException = PyErr_NewException("MacOS.Error", NULL, NULL);
Jack Jansen94bebc02001-08-08 13:17:31 +000076 return PyMac_OSErrException;
77}
78
79/* Set a MAC-specific error from errno, and return NULL; return None if no error */
80PyObject *
81PyErr_Mac(PyObject *eobj, int err)
82{
83 char *msg;
84 PyObject *v;
85
86 if (err == 0 && !PyErr_Occurred()) {
87 Py_INCREF(Py_None);
88 return Py_None;
89 }
90 if (err == -1 && PyErr_Occurred())
91 return NULL;
92 msg = PyMac_StrError(err);
93 v = Py_BuildValue("(is)", err, msg);
94 PyErr_SetObject(eobj, v);
95 Py_DECREF(v);
96 return NULL;
97}
98
99/* Call PyErr_Mac with PyMac_OSErrException */
100PyObject *
101PyMac_Error(OSErr err)
102{
103 return PyErr_Mac(PyMac_GetOSErrException(), err);
104}
105
Jack Jansen697842f2001-09-10 22:00:39 +0000106
Jack Jansen697842f2001-09-10 22:00:39 +0000107OSErr
108PyMac_GetFullPathname(FSSpec *fss, char *path, int len)
109{
Raymond Hettingerec6eb362004-11-05 07:02:59 +0000110 PyObject *fs, *exc;
111 PyObject *rv = NULL;
112 char *input;
113 OSErr err = noErr;
114
Jack Jansen697842f2001-09-10 22:00:39 +0000115 *path = '\0';
Raymond Hettingerec6eb362004-11-05 07:02:59 +0000116
117 fs = PyMac_BuildFSSpec(fss);
118 if (!fs)
119 goto error;
120
121 rv = PyObject_CallMethod(fs, "as_pathname", "");
122 if (!rv)
123 goto error;
124
125 input = PyString_AsString(rv);
126 if (!input)
127 goto error;
128
129 strncpy(path, input, len - 1);
130 path[len - 1] = '\0';
131
132 Py_XDECREF(rv);
133 Py_XDECREF(fs);
134 return err;
135
136 error:
137 exc = PyErr_Occurred();
138 if (exc && PyErr_GivenExceptionMatches(exc,
139 PyMac_GetOSErrException())) {
140 PyObject *args = PyObject_GetAttrString(exc, "args");
141 if (args) {
142 char *ignore;
143 PyArg_ParseTuple(args, "is", &err, &ignore);
144 Py_XDECREF(args);
145 }
Jack Jansen697842f2001-09-10 22:00:39 +0000146 }
Raymond Hettingerec6eb362004-11-05 07:02:59 +0000147 if (err == noErr)
148 err = -1;
149 PyErr_Clear();
150 Py_XDECREF(rv);
151 Py_XDECREF(fs);
152 return err;
Jack Jansen697842f2001-09-10 22:00:39 +0000153}
154
Jack Jansen94bebc02001-08-08 13:17:31 +0000155/* Convert a 4-char string object argument to an OSType value */
156int
157PyMac_GetOSType(PyObject *v, OSType *pr)
158{
159 if (!PyString_Check(v) || PyString_Size(v) != 4) {
160 PyErr_SetString(PyExc_TypeError,
161 "OSType arg must be string of 4 chars");
162 return 0;
163 }
164 memcpy((char *)pr, PyString_AsString(v), 4);
165 return 1;
166}
167
168/* Convert an OSType value to a 4-char string object */
169PyObject *
170PyMac_BuildOSType(OSType t)
171{
172 return PyString_FromStringAndSize((char *)&t, 4);
173}
174
175/* Convert an NumVersion value to a 4-element tuple */
176PyObject *
177PyMac_BuildNumVersion(NumVersion t)
178{
179 return Py_BuildValue("(hhhh)", t.majorRev, t.minorAndBugRev, t.stage, t.nonRelRev);
180}
181
182
183/* Convert a Python string object to a Str255 */
184int
185PyMac_GetStr255(PyObject *v, Str255 pbuf)
186{
187 int len;
188 if (!PyString_Check(v) || (len = PyString_Size(v)) > 255) {
189 PyErr_SetString(PyExc_TypeError,
190 "Str255 arg must be string of at most 255 chars");
191 return 0;
192 }
193 pbuf[0] = len;
194 memcpy((char *)(pbuf+1), PyString_AsString(v), len);
195 return 1;
196}
197
198/* Convert a Str255 to a Python string object */
199PyObject *
200PyMac_BuildStr255(Str255 s)
201{
202 if ( s == NULL ) {
203 PyErr_SetString(PyExc_SystemError, "Str255 pointer is NULL");
204 return NULL;
205 }
206 return PyString_FromStringAndSize((char *)&s[1], (int)s[0]);
207}
208
209PyObject *
210PyMac_BuildOptStr255(Str255 s)
211{
212 if ( s == NULL ) {
213 Py_INCREF(Py_None);
214 return Py_None;
215 }
216 return PyString_FromStringAndSize((char *)&s[1], (int)s[0]);
217}
218
219
220
221/* Convert a Python object to a Rect.
222 The object must be a (left, top, right, bottom) tuple.
223 (This differs from the order in the struct but is consistent with
224 the arguments to SetRect(), and also with STDWIN). */
225int
226PyMac_GetRect(PyObject *v, Rect *r)
227{
228 return PyArg_Parse(v, "(hhhh)", &r->left, &r->top, &r->right, &r->bottom);
229}
230
231/* Convert a Rect to a Python object */
232PyObject *
233PyMac_BuildRect(Rect *r)
234{
235 return Py_BuildValue("(hhhh)", r->left, r->top, r->right, r->bottom);
236}
237
238
239/* Convert a Python object to a Point.
240 The object must be a (h, v) tuple.
241 (This differs from the order in the struct but is consistent with
242 the arguments to SetPoint(), and also with STDWIN). */
243int
244PyMac_GetPoint(PyObject *v, Point *p)
245{
246 return PyArg_Parse(v, "(hh)", &p->h, &p->v);
247}
248
249/* Convert a Point to a Python object */
250PyObject *
251PyMac_BuildPoint(Point p)
252{
253 return Py_BuildValue("(hh)", p.h, p.v);
254}
255
256
257/* Convert a Python object to an EventRecord.
258 The object must be a (what, message, when, (v, h), modifiers) tuple. */
259int
260PyMac_GetEventRecord(PyObject *v, EventRecord *e)
261{
Jack Jansen84c2b1b2003-04-17 20:44:21 +0000262 return PyArg_Parse(v, "(Hkk(hh)H)",
Jack Jansen94bebc02001-08-08 13:17:31 +0000263 &e->what,
264 &e->message,
265 &e->when,
266 &e->where.h,
267 &e->where.v,
268 &e->modifiers);
269}
270
271/* Convert a Rect to an EventRecord object */
272PyObject *
273PyMac_BuildEventRecord(EventRecord *e)
274{
275 return Py_BuildValue("(hll(hh)h)",
276 e->what,
277 e->message,
278 e->when,
279 e->where.h,
280 e->where.v,
281 e->modifiers);
282}
283
284/* Convert Python object to Fixed */
285int
286PyMac_GetFixed(PyObject *v, Fixed *f)
287{
288 double d;
289
290 if( !PyArg_Parse(v, "d", &d))
291 return 0;
292 *f = (Fixed)(d * 0x10000);
293 return 1;
294}
295
Jack Jansen06bd3232001-08-27 14:01:05 +0000296/* Convert a Fixed to a Python object */
Jack Jansen94bebc02001-08-08 13:17:31 +0000297PyObject *
298PyMac_BuildFixed(Fixed f)
299{
300 double d;
301
302 d = f;
303 d = d / 0x10000;
304 return Py_BuildValue("d", d);
305}
306
307/* Convert wide to/from Python int or (hi, lo) tuple. XXXX Should use Python longs */
308int
309PyMac_Getwide(PyObject *v, wide *rv)
310{
311 if (PyInt_Check(v)) {
312 rv->hi = 0;
313 rv->lo = PyInt_AsLong(v);
314 if( rv->lo & 0x80000000 )
315 rv->hi = -1;
316 return 1;
317 }
Jack Jansen84c2b1b2003-04-17 20:44:21 +0000318 return PyArg_Parse(v, "(kk)", &rv->hi, &rv->lo);
Jack Jansen94bebc02001-08-08 13:17:31 +0000319}
320
321
322PyObject *
323PyMac_Buildwide(wide *w)
324{
325 if ( (w->hi == 0 && (w->lo & 0x80000000) == 0) ||
326 (w->hi == -1 && (w->lo & 0x80000000) ) )
327 return PyInt_FromLong(w->lo);
328 return Py_BuildValue("(ll)", w->hi, w->lo);
329}
330
331#ifdef USE_TOOLBOX_OBJECT_GLUE
332/*
333** Glue together the toolbox objects.
334**
335** Because toolbox modules interdepend on each other, they use each others
336** object types, on MacOSX/MachO this leads to the situation that they
337** cannot be dynamically loaded (or they would all have to be lumped into
338** a single .so, but this would be bad for extensibility).
339**
340** This file defines wrappers for all the _New and _Convert functions,
341** which are the Py_BuildValue and PyArg_ParseTuple helpers. The wrappers
342** check an indirection function pointer, and if it isn't filled in yet
343** they import the appropriate module, whose init routine should fill in
344** the pointer.
345*/
346
347#define GLUE_NEW(object, routinename, module) \
348PyObject *(*PyMacGluePtr_##routinename)(object); \
349\
350PyObject *routinename(object cobj) { \
351 if (!PyMacGluePtr_##routinename) { \
352 if (!PyImport_ImportModule(module)) return NULL; \
353 if (!PyMacGluePtr_##routinename) { \
354 PyErr_SetString(PyExc_ImportError, "Module did not provide routine: " module ": " #routinename); \
355 return NULL; \
356 } \
357 } \
358 return (*PyMacGluePtr_##routinename)(cobj); \
359}
360
361#define GLUE_CONVERT(object, routinename, module) \
362int (*PyMacGluePtr_##routinename)(PyObject *, object *); \
363\
364int routinename(PyObject *pyobj, object *cobj) { \
365 if (!PyMacGluePtr_##routinename) { \
366 if (!PyImport_ImportModule(module)) return NULL; \
367 if (!PyMacGluePtr_##routinename) { \
368 PyErr_SetString(PyExc_ImportError, "Module did not provide routine: " module ": " #routinename); \
369 return NULL; \
370 } \
371 } \
372 return (*PyMacGluePtr_##routinename)(pyobj, cobj); \
373}
Jack Jansenfabd00f2001-09-01 23:39:58 +0000374
Jack Jansenad5e76a2003-03-02 23:16:50 +0000375GLUE_NEW(FSSpec *, PyMac_BuildFSSpec, "Carbon.File")
376GLUE_CONVERT(FSSpec, PyMac_GetFSSpec, "Carbon.File")
377GLUE_NEW(FSRef *, PyMac_BuildFSRef, "Carbon.File")
378GLUE_CONVERT(FSRef, PyMac_GetFSRef, "Carbon.File")
Jack Jansen94bebc02001-08-08 13:17:31 +0000379
Jack Jansen06bd3232001-08-27 14:01:05 +0000380GLUE_NEW(AppleEvent *, AEDesc_New, "Carbon.AE") /* XXXX Why by address? */
Jack Jansenb2a57722003-01-17 23:11:17 +0000381GLUE_NEW(AppleEvent *, AEDesc_NewBorrowed, "Carbon.AE")
Jack Jansen06bd3232001-08-27 14:01:05 +0000382GLUE_CONVERT(AppleEvent, AEDesc_Convert, "Carbon.AE")
Jack Jansen94bebc02001-08-08 13:17:31 +0000383
Jack Jansen06bd3232001-08-27 14:01:05 +0000384GLUE_NEW(Component, CmpObj_New, "Carbon.Cm")
385GLUE_CONVERT(Component, CmpObj_Convert, "Carbon.Cm")
386GLUE_NEW(ComponentInstance, CmpInstObj_New, "Carbon.Cm")
387GLUE_CONVERT(ComponentInstance, CmpInstObj_Convert, "Carbon.Cm")
Jack Jansen94bebc02001-08-08 13:17:31 +0000388
Jack Jansen06bd3232001-08-27 14:01:05 +0000389GLUE_NEW(ControlHandle, CtlObj_New, "Carbon.Ctl")
390GLUE_CONVERT(ControlHandle, CtlObj_Convert, "Carbon.Ctl")
Jack Jansen94bebc02001-08-08 13:17:31 +0000391
Jack Jansen06bd3232001-08-27 14:01:05 +0000392GLUE_NEW(DialogPtr, DlgObj_New, "Carbon.Dlg")
393GLUE_CONVERT(DialogPtr, DlgObj_Convert, "Carbon.Dlg")
394GLUE_NEW(DialogPtr, DlgObj_WhichDialog, "Carbon.Dlg")
Jack Jansen94bebc02001-08-08 13:17:31 +0000395
Jack Jansen06bd3232001-08-27 14:01:05 +0000396GLUE_NEW(DragReference, DragObj_New, "Carbon.Drag")
397GLUE_CONVERT(DragReference, DragObj_Convert, "Carbon.Drag")
Jack Jansen94bebc02001-08-08 13:17:31 +0000398
Jack Jansen06bd3232001-08-27 14:01:05 +0000399GLUE_NEW(ListHandle, ListObj_New, "Carbon.List")
400GLUE_CONVERT(ListHandle, ListObj_Convert, "Carbon.List")
Jack Jansen94bebc02001-08-08 13:17:31 +0000401
Jack Jansen06bd3232001-08-27 14:01:05 +0000402GLUE_NEW(MenuHandle, MenuObj_New, "Carbon.Menu")
403GLUE_CONVERT(MenuHandle, MenuObj_Convert, "Carbon.Menu")
Jack Jansen94bebc02001-08-08 13:17:31 +0000404
Jack Jansen06bd3232001-08-27 14:01:05 +0000405GLUE_NEW(GrafPtr, GrafObj_New, "Carbon.Qd")
406GLUE_CONVERT(GrafPtr, GrafObj_Convert, "Carbon.Qd")
407GLUE_NEW(BitMapPtr, BMObj_New, "Carbon.Qd")
408GLUE_CONVERT(BitMapPtr, BMObj_Convert, "Carbon.Qd")
409GLUE_NEW(RGBColor *, QdRGB_New, "Carbon.Qd") /* XXXX Why? */
410GLUE_CONVERT(RGBColor, QdRGB_Convert, "Carbon.Qd")
Jack Jansen94bebc02001-08-08 13:17:31 +0000411
Jack Jansen06bd3232001-08-27 14:01:05 +0000412GLUE_NEW(GWorldPtr, GWorldObj_New, "Carbon.Qdoffs")
413GLUE_CONVERT(GWorldPtr, GWorldObj_Convert, "Carbon.Qdoffs")
Jack Jansen94bebc02001-08-08 13:17:31 +0000414
Jack Jansen06bd3232001-08-27 14:01:05 +0000415GLUE_NEW(Track, TrackObj_New, "Carbon.Qt")
416GLUE_CONVERT(Track, TrackObj_Convert, "Carbon.Qt")
417GLUE_NEW(Movie, MovieObj_New, "Carbon.Qt")
418GLUE_CONVERT(Movie, MovieObj_Convert, "Carbon.Qt")
419GLUE_NEW(MovieController, MovieCtlObj_New, "Carbon.Qt")
420GLUE_CONVERT(MovieController, MovieCtlObj_Convert, "Carbon.Qt")
421GLUE_NEW(TimeBase, TimeBaseObj_New, "Carbon.Qt")
422GLUE_CONVERT(TimeBase, TimeBaseObj_Convert, "Carbon.Qt")
423GLUE_NEW(UserData, UserDataObj_New, "Carbon.Qt")
424GLUE_CONVERT(UserData, UserDataObj_Convert, "Carbon.Qt")
425GLUE_NEW(Media, MediaObj_New, "Carbon.Qt")
426GLUE_CONVERT(Media, MediaObj_Convert, "Carbon.Qt")
Jack Jansen94bebc02001-08-08 13:17:31 +0000427
Jack Jansen06bd3232001-08-27 14:01:05 +0000428GLUE_NEW(Handle, ResObj_New, "Carbon.Res")
429GLUE_CONVERT(Handle, ResObj_Convert, "Carbon.Res")
430GLUE_NEW(Handle, OptResObj_New, "Carbon.Res")
431GLUE_CONVERT(Handle, OptResObj_Convert, "Carbon.Res")
Jack Jansen94bebc02001-08-08 13:17:31 +0000432
Jack Jansen06bd3232001-08-27 14:01:05 +0000433GLUE_NEW(TEHandle, TEObj_New, "Carbon.TE")
434GLUE_CONVERT(TEHandle, TEObj_Convert, "Carbon.TE")
Jack Jansen94bebc02001-08-08 13:17:31 +0000435
Jack Jansen06bd3232001-08-27 14:01:05 +0000436GLUE_NEW(WindowPtr, WinObj_New, "Carbon.Win")
437GLUE_CONVERT(WindowPtr, WinObj_Convert, "Carbon.Win")
438GLUE_NEW(WindowPtr, WinObj_WhichWindow, "Carbon.Win")
Jack Jansen94bebc02001-08-08 13:17:31 +0000439
Jack Jansen4eb45e72003-05-27 21:39:58 +0000440GLUE_CONVERT(CFTypeRef, CFObj_Convert, "Carbon.CF")
441GLUE_NEW(CFTypeRef, CFObj_New, "Carbon.CF")
442
Jack Jansen537a69f2001-11-05 14:39:22 +0000443GLUE_CONVERT(CFTypeRef, CFTypeRefObj_Convert, "Carbon.CF")
444GLUE_NEW(CFTypeRef, CFTypeRefObj_New, "Carbon.CF")
445
446GLUE_CONVERT(CFStringRef, CFStringRefObj_Convert, "Carbon.CF")
447GLUE_NEW(CFStringRef, CFStringRefObj_New, "Carbon.CF")
448GLUE_CONVERT(CFMutableStringRef, CFMutableStringRefObj_Convert, "Carbon.CF")
449GLUE_NEW(CFMutableStringRef, CFMutableStringRefObj_New, "Carbon.CF")
450
451GLUE_CONVERT(CFArrayRef, CFArrayRefObj_Convert, "Carbon.CF")
452GLUE_NEW(CFArrayRef, CFArrayRefObj_New, "Carbon.CF")
453GLUE_CONVERT(CFMutableArrayRef, CFMutableArrayRefObj_Convert, "Carbon.CF")
454GLUE_NEW(CFMutableArrayRef, CFMutableArrayRefObj_New, "Carbon.CF")
455
456GLUE_CONVERT(CFDictionaryRef, CFDictionaryRefObj_Convert, "Carbon.CF")
457GLUE_NEW(CFDictionaryRef, CFDictionaryRefObj_New, "Carbon.CF")
458GLUE_CONVERT(CFMutableDictionaryRef, CFMutableDictionaryRefObj_Convert, "Carbon.CF")
459GLUE_NEW(CFMutableDictionaryRef, CFMutableDictionaryRefObj_New, "Carbon.CF")
460
461GLUE_CONVERT(CFURLRef, CFURLRefObj_Convert, "Carbon.CF")
462GLUE_CONVERT(CFURLRef, OptionalCFURLRefObj_Convert, "Carbon.CF")
463GLUE_NEW(CFURLRef, CFURLRefObj_New, "Carbon.CF")
464
Michael W. Hudson5f26dda2002-11-09 14:47:18 +0000465#endif /* USE_TOOLBOX_OBJECT_GLUE */