blob: 0aa2cfda3701b5cfbc3b97b88e2e070d2cec8bf8 [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"
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000028#include <arpa/inet.h> /* for ntohl, htonl */
Jack Jansen94bebc02001-08-08 13:17:31 +000029
Jack Jansen94bebc02001-08-08 13:17:31 +000030
Jack Jansen94bebc02001-08-08 13:17:31 +000031/* Like strerror() but for Mac OS error numbers */
Raymond Hettingerec6eb362004-11-05 07:02:59 +000032char *
33PyMac_StrError(int err)
Jack Jansen94bebc02001-08-08 13:17:31 +000034{
35 static char buf[256];
Raymond Hettingerec6eb362004-11-05 07:02:59 +000036 PyObject *m;
37 PyObject *rv;
38
39 m = PyImport_ImportModule("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)
Jack Jansendde800e2002-11-07 23:07:05 +000049 PyErr_Clear();
Raymond Hettingerec6eb362004-11-05 07:02:59 +000050 }
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';
Jack Jansendde800e2002-11-07 23:07:05 +000059 } else {
Raymond Hettingerec6eb362004-11-05 07:02:59 +000060 strncpy(buf, input, sizeof(buf) - 1);
61 buf[sizeof(buf) - 1] = '\0';
Jack Jansendde800e2002-11-07 23:07:05 +000062 }
63 }
Raymond Hettingerec6eb362004-11-05 07:02:59 +000064
Jack Jansen94bebc02001-08-08 13:17:31 +000065 return buf;
66}
67
68/* Exception object shared by all Mac specific modules for Mac OS errors */
69PyObject *PyMac_OSErrException;
70
71/* Initialize and return PyMac_OSErrException */
72PyObject *
Jack Jansen697842f2001-09-10 22:00:39 +000073PyMac_GetOSErrException(void)
Jack Jansen94bebc02001-08-08 13:17:31 +000074{
75 if (PyMac_OSErrException == NULL)
Jack Jansen8fce2ef2002-10-19 22:02:21 +000076 PyMac_OSErrException = PyErr_NewException("MacOS.Error", NULL, NULL);
Jack Jansen94bebc02001-08-08 13:17:31 +000077 return PyMac_OSErrException;
78}
79
80/* Set a MAC-specific error from errno, and return NULL; return None if no error */
81PyObject *
82PyErr_Mac(PyObject *eobj, int err)
83{
84 char *msg;
85 PyObject *v;
86
87 if (err == 0 && !PyErr_Occurred()) {
88 Py_INCREF(Py_None);
89 return Py_None;
90 }
91 if (err == -1 && PyErr_Occurred())
92 return NULL;
93 msg = PyMac_StrError(err);
94 v = Py_BuildValue("(is)", err, msg);
95 PyErr_SetObject(eobj, v);
96 Py_DECREF(v);
97 return NULL;
98}
99
100/* Call PyErr_Mac with PyMac_OSErrException */
101PyObject *
102PyMac_Error(OSErr err)
103{
104 return PyErr_Mac(PyMac_GetOSErrException(), err);
105}
106
Jack Jansen697842f2001-09-10 22:00:39 +0000107
Jack Jansen697842f2001-09-10 22:00:39 +0000108OSErr
109PyMac_GetFullPathname(FSSpec *fss, char *path, int len)
110{
Raymond Hettingerec6eb362004-11-05 07:02:59 +0000111 PyObject *fs, *exc;
112 PyObject *rv = NULL;
113 char *input;
114 OSErr err = noErr;
115
Jack Jansen697842f2001-09-10 22:00:39 +0000116 *path = '\0';
Raymond Hettingerec6eb362004-11-05 07:02:59 +0000117
118 fs = PyMac_BuildFSSpec(fss);
119 if (!fs)
120 goto error;
121
122 rv = PyObject_CallMethod(fs, "as_pathname", "");
123 if (!rv)
124 goto error;
125
126 input = PyString_AsString(rv);
127 if (!input)
128 goto error;
129
130 strncpy(path, input, len - 1);
131 path[len - 1] = '\0';
132
133 Py_XDECREF(rv);
134 Py_XDECREF(fs);
135 return err;
136
137 error:
138 exc = PyErr_Occurred();
139 if (exc && PyErr_GivenExceptionMatches(exc,
140 PyMac_GetOSErrException())) {
141 PyObject *args = PyObject_GetAttrString(exc, "args");
142 if (args) {
143 char *ignore;
144 PyArg_ParseTuple(args, "is", &err, &ignore);
145 Py_XDECREF(args);
146 }
Jack Jansen697842f2001-09-10 22:00:39 +0000147 }
Raymond Hettingerec6eb362004-11-05 07:02:59 +0000148 if (err == noErr)
149 err = -1;
150 PyErr_Clear();
151 Py_XDECREF(rv);
152 Py_XDECREF(fs);
153 return err;
Jack Jansen697842f2001-09-10 22:00:39 +0000154}
155
Jack Jansen94bebc02001-08-08 13:17:31 +0000156/* Convert a 4-char string object argument to an OSType value */
157int
158PyMac_GetOSType(PyObject *v, OSType *pr)
159{
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000160 uint32_t tmp;
Jack Jansen94bebc02001-08-08 13:17:31 +0000161 if (!PyString_Check(v) || PyString_Size(v) != 4) {
162 PyErr_SetString(PyExc_TypeError,
163 "OSType arg must be string of 4 chars");
164 return 0;
165 }
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000166 memcpy((char *)&tmp, PyString_AsString(v), 4);
167 *pr = (OSType)ntohl(tmp);
Jack Jansen94bebc02001-08-08 13:17:31 +0000168 return 1;
169}
170
171/* Convert an OSType value to a 4-char string object */
172PyObject *
173PyMac_BuildOSType(OSType t)
174{
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000175 uint32_t tmp = htonl((uint32_t)t);
176 return PyString_FromStringAndSize((char *)&tmp, 4);
Jack Jansen94bebc02001-08-08 13:17:31 +0000177}
178
179/* Convert an NumVersion value to a 4-element tuple */
180PyObject *
181PyMac_BuildNumVersion(NumVersion t)
182{
183 return Py_BuildValue("(hhhh)", t.majorRev, t.minorAndBugRev, t.stage, t.nonRelRev);
184}
185
186
187/* Convert a Python string object to a Str255 */
188int
189PyMac_GetStr255(PyObject *v, Str255 pbuf)
190{
191 int len;
192 if (!PyString_Check(v) || (len = PyString_Size(v)) > 255) {
193 PyErr_SetString(PyExc_TypeError,
194 "Str255 arg must be string of at most 255 chars");
195 return 0;
196 }
197 pbuf[0] = len;
198 memcpy((char *)(pbuf+1), PyString_AsString(v), len);
199 return 1;
200}
201
202/* Convert a Str255 to a Python string object */
203PyObject *
204PyMac_BuildStr255(Str255 s)
205{
206 if ( s == NULL ) {
207 PyErr_SetString(PyExc_SystemError, "Str255 pointer is NULL");
208 return NULL;
209 }
210 return PyString_FromStringAndSize((char *)&s[1], (int)s[0]);
211}
212
213PyObject *
214PyMac_BuildOptStr255(Str255 s)
215{
216 if ( s == NULL ) {
217 Py_INCREF(Py_None);
218 return Py_None;
219 }
220 return PyString_FromStringAndSize((char *)&s[1], (int)s[0]);
221}
222
223
224
225/* Convert a Python object to a Rect.
226 The object must be a (left, top, right, bottom) tuple.
227 (This differs from the order in the struct but is consistent with
228 the arguments to SetRect(), and also with STDWIN). */
229int
230PyMac_GetRect(PyObject *v, Rect *r)
231{
232 return PyArg_Parse(v, "(hhhh)", &r->left, &r->top, &r->right, &r->bottom);
233}
234
235/* Convert a Rect to a Python object */
236PyObject *
237PyMac_BuildRect(Rect *r)
238{
239 return Py_BuildValue("(hhhh)", r->left, r->top, r->right, r->bottom);
240}
241
242
243/* Convert a Python object to a Point.
244 The object must be a (h, v) tuple.
245 (This differs from the order in the struct but is consistent with
246 the arguments to SetPoint(), and also with STDWIN). */
247int
248PyMac_GetPoint(PyObject *v, Point *p)
249{
250 return PyArg_Parse(v, "(hh)", &p->h, &p->v);
251}
252
253/* Convert a Point to a Python object */
254PyObject *
255PyMac_BuildPoint(Point p)
256{
257 return Py_BuildValue("(hh)", p.h, p.v);
258}
259
260
261/* Convert a Python object to an EventRecord.
262 The object must be a (what, message, when, (v, h), modifiers) tuple. */
263int
264PyMac_GetEventRecord(PyObject *v, EventRecord *e)
265{
Jack Jansen84c2b1b2003-04-17 20:44:21 +0000266 return PyArg_Parse(v, "(Hkk(hh)H)",
Jack Jansen94bebc02001-08-08 13:17:31 +0000267 &e->what,
268 &e->message,
269 &e->when,
270 &e->where.h,
271 &e->where.v,
272 &e->modifiers);
273}
274
275/* Convert a Rect to an EventRecord object */
276PyObject *
277PyMac_BuildEventRecord(EventRecord *e)
278{
279 return Py_BuildValue("(hll(hh)h)",
280 e->what,
281 e->message,
282 e->when,
283 e->where.h,
284 e->where.v,
285 e->modifiers);
286}
287
288/* Convert Python object to Fixed */
289int
290PyMac_GetFixed(PyObject *v, Fixed *f)
291{
292 double d;
293
294 if( !PyArg_Parse(v, "d", &d))
295 return 0;
296 *f = (Fixed)(d * 0x10000);
297 return 1;
298}
299
Jack Jansen06bd3232001-08-27 14:01:05 +0000300/* Convert a Fixed to a Python object */
Jack Jansen94bebc02001-08-08 13:17:31 +0000301PyObject *
302PyMac_BuildFixed(Fixed f)
303{
304 double d;
305
306 d = f;
307 d = d / 0x10000;
308 return Py_BuildValue("d", d);
309}
310
311/* Convert wide to/from Python int or (hi, lo) tuple. XXXX Should use Python longs */
312int
313PyMac_Getwide(PyObject *v, wide *rv)
314{
315 if (PyInt_Check(v)) {
316 rv->hi = 0;
317 rv->lo = PyInt_AsLong(v);
318 if( rv->lo & 0x80000000 )
319 rv->hi = -1;
320 return 1;
321 }
Jack Jansen84c2b1b2003-04-17 20:44:21 +0000322 return PyArg_Parse(v, "(kk)", &rv->hi, &rv->lo);
Jack Jansen94bebc02001-08-08 13:17:31 +0000323}
324
325
326PyObject *
327PyMac_Buildwide(wide *w)
328{
329 if ( (w->hi == 0 && (w->lo & 0x80000000) == 0) ||
330 (w->hi == -1 && (w->lo & 0x80000000) ) )
331 return PyInt_FromLong(w->lo);
332 return Py_BuildValue("(ll)", w->hi, w->lo);
333}
334
335#ifdef USE_TOOLBOX_OBJECT_GLUE
336/*
337** Glue together the toolbox objects.
338**
339** Because toolbox modules interdepend on each other, they use each others
340** object types, on MacOSX/MachO this leads to the situation that they
341** cannot be dynamically loaded (or they would all have to be lumped into
342** a single .so, but this would be bad for extensibility).
343**
344** This file defines wrappers for all the _New and _Convert functions,
345** which are the Py_BuildValue and PyArg_ParseTuple helpers. The wrappers
346** check an indirection function pointer, and if it isn't filled in yet
347** they import the appropriate module, whose init routine should fill in
348** the pointer.
349*/
350
351#define GLUE_NEW(object, routinename, module) \
352PyObject *(*PyMacGluePtr_##routinename)(object); \
353\
354PyObject *routinename(object cobj) { \
355 if (!PyMacGluePtr_##routinename) { \
356 if (!PyImport_ImportModule(module)) return NULL; \
357 if (!PyMacGluePtr_##routinename) { \
358 PyErr_SetString(PyExc_ImportError, "Module did not provide routine: " module ": " #routinename); \
359 return NULL; \
360 } \
361 } \
362 return (*PyMacGluePtr_##routinename)(cobj); \
363}
364
365#define GLUE_CONVERT(object, routinename, module) \
366int (*PyMacGluePtr_##routinename)(PyObject *, object *); \
367\
368int routinename(PyObject *pyobj, object *cobj) { \
369 if (!PyMacGluePtr_##routinename) { \
Martin v. Löwis18e16552006-02-15 17:27:45 +0000370 if (!PyImport_ImportModule(module)) return 0; \
Jack Jansen94bebc02001-08-08 13:17:31 +0000371 if (!PyMacGluePtr_##routinename) { \
372 PyErr_SetString(PyExc_ImportError, "Module did not provide routine: " module ": " #routinename); \
Martin v. Löwis18e16552006-02-15 17:27:45 +0000373 return 0; \
Jack Jansen94bebc02001-08-08 13:17:31 +0000374 } \
375 } \
376 return (*PyMacGluePtr_##routinename)(pyobj, cobj); \
377}
Jack Jansenfabd00f2001-09-01 23:39:58 +0000378
Jack Jansenad5e76a2003-03-02 23:16:50 +0000379GLUE_NEW(FSSpec *, PyMac_BuildFSSpec, "Carbon.File")
380GLUE_CONVERT(FSSpec, PyMac_GetFSSpec, "Carbon.File")
381GLUE_NEW(FSRef *, PyMac_BuildFSRef, "Carbon.File")
382GLUE_CONVERT(FSRef, PyMac_GetFSRef, "Carbon.File")
Jack Jansen94bebc02001-08-08 13:17:31 +0000383
Jack Jansen06bd3232001-08-27 14:01:05 +0000384GLUE_NEW(AppleEvent *, AEDesc_New, "Carbon.AE") /* XXXX Why by address? */
Jack Jansenb2a57722003-01-17 23:11:17 +0000385GLUE_NEW(AppleEvent *, AEDesc_NewBorrowed, "Carbon.AE")
Jack Jansen06bd3232001-08-27 14:01:05 +0000386GLUE_CONVERT(AppleEvent, AEDesc_Convert, "Carbon.AE")
Jack Jansen94bebc02001-08-08 13:17:31 +0000387
Jack Jansen06bd3232001-08-27 14:01:05 +0000388GLUE_NEW(Component, CmpObj_New, "Carbon.Cm")
389GLUE_CONVERT(Component, CmpObj_Convert, "Carbon.Cm")
390GLUE_NEW(ComponentInstance, CmpInstObj_New, "Carbon.Cm")
391GLUE_CONVERT(ComponentInstance, CmpInstObj_Convert, "Carbon.Cm")
Jack Jansen94bebc02001-08-08 13:17:31 +0000392
Jack Jansen06bd3232001-08-27 14:01:05 +0000393GLUE_NEW(ControlHandle, CtlObj_New, "Carbon.Ctl")
394GLUE_CONVERT(ControlHandle, CtlObj_Convert, "Carbon.Ctl")
Jack Jansen94bebc02001-08-08 13:17:31 +0000395
Jack Jansen06bd3232001-08-27 14:01:05 +0000396GLUE_NEW(DialogPtr, DlgObj_New, "Carbon.Dlg")
397GLUE_CONVERT(DialogPtr, DlgObj_Convert, "Carbon.Dlg")
398GLUE_NEW(DialogPtr, DlgObj_WhichDialog, "Carbon.Dlg")
Jack Jansen94bebc02001-08-08 13:17:31 +0000399
Jack Jansen06bd3232001-08-27 14:01:05 +0000400GLUE_NEW(DragReference, DragObj_New, "Carbon.Drag")
401GLUE_CONVERT(DragReference, DragObj_Convert, "Carbon.Drag")
Jack Jansen94bebc02001-08-08 13:17:31 +0000402
Jack Jansen06bd3232001-08-27 14:01:05 +0000403GLUE_NEW(ListHandle, ListObj_New, "Carbon.List")
404GLUE_CONVERT(ListHandle, ListObj_Convert, "Carbon.List")
Jack Jansen94bebc02001-08-08 13:17:31 +0000405
Jack Jansen06bd3232001-08-27 14:01:05 +0000406GLUE_NEW(MenuHandle, MenuObj_New, "Carbon.Menu")
407GLUE_CONVERT(MenuHandle, MenuObj_Convert, "Carbon.Menu")
Jack Jansen94bebc02001-08-08 13:17:31 +0000408
Jack Jansen06bd3232001-08-27 14:01:05 +0000409GLUE_NEW(GrafPtr, GrafObj_New, "Carbon.Qd")
410GLUE_CONVERT(GrafPtr, GrafObj_Convert, "Carbon.Qd")
411GLUE_NEW(BitMapPtr, BMObj_New, "Carbon.Qd")
412GLUE_CONVERT(BitMapPtr, BMObj_Convert, "Carbon.Qd")
413GLUE_NEW(RGBColor *, QdRGB_New, "Carbon.Qd") /* XXXX Why? */
414GLUE_CONVERT(RGBColor, QdRGB_Convert, "Carbon.Qd")
Jack Jansen94bebc02001-08-08 13:17:31 +0000415
Jack Jansen06bd3232001-08-27 14:01:05 +0000416GLUE_NEW(GWorldPtr, GWorldObj_New, "Carbon.Qdoffs")
417GLUE_CONVERT(GWorldPtr, GWorldObj_Convert, "Carbon.Qdoffs")
Jack Jansen94bebc02001-08-08 13:17:31 +0000418
Jack Jansen06bd3232001-08-27 14:01:05 +0000419GLUE_NEW(Track, TrackObj_New, "Carbon.Qt")
420GLUE_CONVERT(Track, TrackObj_Convert, "Carbon.Qt")
421GLUE_NEW(Movie, MovieObj_New, "Carbon.Qt")
422GLUE_CONVERT(Movie, MovieObj_Convert, "Carbon.Qt")
423GLUE_NEW(MovieController, MovieCtlObj_New, "Carbon.Qt")
424GLUE_CONVERT(MovieController, MovieCtlObj_Convert, "Carbon.Qt")
425GLUE_NEW(TimeBase, TimeBaseObj_New, "Carbon.Qt")
426GLUE_CONVERT(TimeBase, TimeBaseObj_Convert, "Carbon.Qt")
427GLUE_NEW(UserData, UserDataObj_New, "Carbon.Qt")
428GLUE_CONVERT(UserData, UserDataObj_Convert, "Carbon.Qt")
429GLUE_NEW(Media, MediaObj_New, "Carbon.Qt")
430GLUE_CONVERT(Media, MediaObj_Convert, "Carbon.Qt")
Jack Jansen94bebc02001-08-08 13:17:31 +0000431
Jack Jansen06bd3232001-08-27 14:01:05 +0000432GLUE_NEW(Handle, ResObj_New, "Carbon.Res")
433GLUE_CONVERT(Handle, ResObj_Convert, "Carbon.Res")
434GLUE_NEW(Handle, OptResObj_New, "Carbon.Res")
435GLUE_CONVERT(Handle, OptResObj_Convert, "Carbon.Res")
Jack Jansen94bebc02001-08-08 13:17:31 +0000436
Jack Jansen06bd3232001-08-27 14:01:05 +0000437GLUE_NEW(TEHandle, TEObj_New, "Carbon.TE")
438GLUE_CONVERT(TEHandle, TEObj_Convert, "Carbon.TE")
Jack Jansen94bebc02001-08-08 13:17:31 +0000439
Jack Jansen06bd3232001-08-27 14:01:05 +0000440GLUE_NEW(WindowPtr, WinObj_New, "Carbon.Win")
441GLUE_CONVERT(WindowPtr, WinObj_Convert, "Carbon.Win")
442GLUE_NEW(WindowPtr, WinObj_WhichWindow, "Carbon.Win")
Jack Jansen94bebc02001-08-08 13:17:31 +0000443
Jack Jansen4eb45e72003-05-27 21:39:58 +0000444GLUE_CONVERT(CFTypeRef, CFObj_Convert, "Carbon.CF")
445GLUE_NEW(CFTypeRef, CFObj_New, "Carbon.CF")
446
Jack Jansen537a69f2001-11-05 14:39:22 +0000447GLUE_CONVERT(CFTypeRef, CFTypeRefObj_Convert, "Carbon.CF")
448GLUE_NEW(CFTypeRef, CFTypeRefObj_New, "Carbon.CF")
449
450GLUE_CONVERT(CFStringRef, CFStringRefObj_Convert, "Carbon.CF")
451GLUE_NEW(CFStringRef, CFStringRefObj_New, "Carbon.CF")
452GLUE_CONVERT(CFMutableStringRef, CFMutableStringRefObj_Convert, "Carbon.CF")
453GLUE_NEW(CFMutableStringRef, CFMutableStringRefObj_New, "Carbon.CF")
454
455GLUE_CONVERT(CFArrayRef, CFArrayRefObj_Convert, "Carbon.CF")
456GLUE_NEW(CFArrayRef, CFArrayRefObj_New, "Carbon.CF")
457GLUE_CONVERT(CFMutableArrayRef, CFMutableArrayRefObj_Convert, "Carbon.CF")
458GLUE_NEW(CFMutableArrayRef, CFMutableArrayRefObj_New, "Carbon.CF")
459
460GLUE_CONVERT(CFDictionaryRef, CFDictionaryRefObj_Convert, "Carbon.CF")
461GLUE_NEW(CFDictionaryRef, CFDictionaryRefObj_New, "Carbon.CF")
462GLUE_CONVERT(CFMutableDictionaryRef, CFMutableDictionaryRefObj_Convert, "Carbon.CF")
463GLUE_NEW(CFMutableDictionaryRef, CFMutableDictionaryRefObj_New, "Carbon.CF")
464
465GLUE_CONVERT(CFURLRef, CFURLRefObj_Convert, "Carbon.CF")
466GLUE_CONVERT(CFURLRef, OptionalCFURLRefObj_Convert, "Carbon.CF")
467GLUE_NEW(CFURLRef, CFURLRefObj_New, "Carbon.CF")
468
Michael W. Hudson5f26dda2002-11-09 14:47:18 +0000469#endif /* USE_TOOLBOX_OBJECT_GLUE */