PageRenderTime 38ms CodeModel.GetById 16ms app.highlight 18ms RepoModel.GetById 1ms app.codeStats 0ms

/Python/mactoolboxglue.c

http://unladen-swallow.googlecode.com/
C | 474 lines | 344 code | 67 blank | 63 comment | 48 complexity | 57b7c6e01f02cf2d0a9174b0371dd76d MD5 | raw file
  1/***********************************************************
  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"
 27#include "pymactoolbox.h"
 28#include <arpa/inet.h>	/* for ntohl, htonl */
 29
 30
 31/* Like strerror() but for Mac OS error numbers */
 32char *
 33PyMac_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 */
 70PyObject *PyMac_OSErrException;
 71
 72/* Initialize and return PyMac_OSErrException */
 73PyObject *
 74PyMac_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 */
 82PyObject * 
 83PyErr_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 */
102PyObject *
103PyMac_Error(OSErr err)
104{
105	return PyErr_Mac(PyMac_GetOSErrException(), err);
106}
107
108
109#ifndef __LP64__
110OSErr
111PyMac_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 */
160int
161PyMac_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 */
175PyObject *
176PyMac_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 */
183PyObject *
184PyMac_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 */
191int
192PyMac_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 */
206PyObject *
207PyMac_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
216PyObject *
217PyMac_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). */
232int
233PyMac_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 */
239PyObject *
240PyMac_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). */
250int
251PyMac_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 */
257PyObject *
258PyMac_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. */
266int
267PyMac_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 */
279PyObject *
280PyMac_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 */
292int
293PyMac_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 */
304PyObject *
305PyMac_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 */
315int
316PyMac_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
329PyObject *
330PyMac_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) \
355PyObject *(*PyMacGluePtr_##routinename)(object); \
356\
357PyObject *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) \
369int (*PyMacGluePtr_##routinename)(PyObject *, object *); \
370\
371int 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
382GLUE_NEW(FSSpec *, PyMac_BuildFSSpec, "Carbon.File")
383GLUE_CONVERT(FSSpec, PyMac_GetFSSpec, "Carbon.File")
384GLUE_NEW(FSRef *, PyMac_BuildFSRef, "Carbon.File")
385GLUE_CONVERT(FSRef, PyMac_GetFSRef, "Carbon.File")
386
387GLUE_NEW(AppleEvent *, AEDesc_New, "Carbon.AE") /* XXXX Why by address? */
388GLUE_NEW(AppleEvent *, AEDesc_NewBorrowed, "Carbon.AE")
389GLUE_CONVERT(AppleEvent, AEDesc_Convert, "Carbon.AE")
390
391GLUE_NEW(Component, CmpObj_New, "Carbon.Cm")
392GLUE_CONVERT(Component, CmpObj_Convert, "Carbon.Cm")
393GLUE_NEW(ComponentInstance, CmpInstObj_New, "Carbon.Cm")
394GLUE_CONVERT(ComponentInstance, CmpInstObj_Convert, "Carbon.Cm")
395
396GLUE_NEW(ControlHandle, CtlObj_New, "Carbon.Ctl")
397GLUE_CONVERT(ControlHandle, CtlObj_Convert, "Carbon.Ctl")
398
399GLUE_NEW(DialogPtr, DlgObj_New, "Carbon.Dlg")
400GLUE_CONVERT(DialogPtr, DlgObj_Convert, "Carbon.Dlg")
401GLUE_NEW(DialogPtr, DlgObj_WhichDialog, "Carbon.Dlg")
402
403GLUE_NEW(DragReference, DragObj_New, "Carbon.Drag")
404GLUE_CONVERT(DragReference, DragObj_Convert, "Carbon.Drag")
405
406GLUE_NEW(ListHandle, ListObj_New, "Carbon.List")
407GLUE_CONVERT(ListHandle, ListObj_Convert, "Carbon.List")
408
409GLUE_NEW(MenuHandle, MenuObj_New, "Carbon.Menu")
410GLUE_CONVERT(MenuHandle, MenuObj_Convert, "Carbon.Menu")
411
412GLUE_NEW(GrafPtr, GrafObj_New, "Carbon.Qd")
413GLUE_CONVERT(GrafPtr, GrafObj_Convert, "Carbon.Qd")
414GLUE_NEW(BitMapPtr, BMObj_New, "Carbon.Qd")
415GLUE_CONVERT(BitMapPtr, BMObj_Convert, "Carbon.Qd")
416GLUE_NEW(RGBColor *, QdRGB_New, "Carbon.Qd") /* XXXX Why? */
417GLUE_CONVERT(RGBColor, QdRGB_Convert, "Carbon.Qd")
418
419GLUE_NEW(GWorldPtr, GWorldObj_New, "Carbon.Qdoffs")
420GLUE_CONVERT(GWorldPtr, GWorldObj_Convert, "Carbon.Qdoffs")
421
422#ifndef __LP64__
423GLUE_NEW(Track, TrackObj_New, "Carbon.Qt")
424GLUE_CONVERT(Track, TrackObj_Convert, "Carbon.Qt")
425GLUE_NEW(Movie, MovieObj_New, "Carbon.Qt")
426GLUE_CONVERT(Movie, MovieObj_Convert, "Carbon.Qt")
427GLUE_NEW(MovieController, MovieCtlObj_New, "Carbon.Qt")
428GLUE_CONVERT(MovieController, MovieCtlObj_Convert, "Carbon.Qt")
429GLUE_NEW(TimeBase, TimeBaseObj_New, "Carbon.Qt")
430GLUE_CONVERT(TimeBase, TimeBaseObj_Convert, "Carbon.Qt")
431GLUE_NEW(UserData, UserDataObj_New, "Carbon.Qt")
432GLUE_CONVERT(UserData, UserDataObj_Convert, "Carbon.Qt")
433GLUE_NEW(Media, MediaObj_New, "Carbon.Qt")
434GLUE_CONVERT(Media, MediaObj_Convert, "Carbon.Qt")
435#endif /* !__LP64__ */
436
437GLUE_NEW(Handle, ResObj_New, "Carbon.Res")
438GLUE_CONVERT(Handle, ResObj_Convert, "Carbon.Res")
439GLUE_NEW(Handle, OptResObj_New, "Carbon.Res")
440GLUE_CONVERT(Handle, OptResObj_Convert, "Carbon.Res")
441
442GLUE_NEW(TEHandle, TEObj_New, "Carbon.TE")
443GLUE_CONVERT(TEHandle, TEObj_Convert, "Carbon.TE")
444
445GLUE_NEW(WindowPtr, WinObj_New, "Carbon.Win")
446GLUE_CONVERT(WindowPtr, WinObj_Convert, "Carbon.Win")
447GLUE_NEW(WindowPtr, WinObj_WhichWindow, "Carbon.Win")
448
449GLUE_CONVERT(CFTypeRef, CFObj_Convert, "Carbon.CF")
450GLUE_NEW(CFTypeRef, CFObj_New, "Carbon.CF")
451
452GLUE_CONVERT(CFTypeRef, CFTypeRefObj_Convert, "Carbon.CF")
453GLUE_NEW(CFTypeRef, CFTypeRefObj_New, "Carbon.CF")
454
455GLUE_CONVERT(CFStringRef, CFStringRefObj_Convert, "Carbon.CF")
456GLUE_NEW(CFStringRef, CFStringRefObj_New, "Carbon.CF")
457GLUE_CONVERT(CFMutableStringRef, CFMutableStringRefObj_Convert, "Carbon.CF")
458GLUE_NEW(CFMutableStringRef, CFMutableStringRefObj_New, "Carbon.CF")
459
460GLUE_CONVERT(CFArrayRef, CFArrayRefObj_Convert, "Carbon.CF")
461GLUE_NEW(CFArrayRef, CFArrayRefObj_New, "Carbon.CF")
462GLUE_CONVERT(CFMutableArrayRef, CFMutableArrayRefObj_Convert, "Carbon.CF")
463GLUE_NEW(CFMutableArrayRef, CFMutableArrayRefObj_New, "Carbon.CF")
464
465GLUE_CONVERT(CFDictionaryRef, CFDictionaryRefObj_Convert, "Carbon.CF")
466GLUE_NEW(CFDictionaryRef, CFDictionaryRefObj_New, "Carbon.CF")
467GLUE_CONVERT(CFMutableDictionaryRef, CFMutableDictionaryRefObj_Convert, "Carbon.CF")
468GLUE_NEW(CFMutableDictionaryRef, CFMutableDictionaryRefObj_New, "Carbon.CF")
469
470GLUE_CONVERT(CFURLRef, CFURLRefObj_Convert, "Carbon.CF")
471GLUE_CONVERT(CFURLRef, OptionalCFURLRefObj_Convert, "Carbon.CF")
472GLUE_NEW(CFURLRef, CFURLRefObj_New, "Carbon.CF")
473
474#endif /* USE_TOOLBOX_OBJECT_GLUE */