append(): Fixing the test for convertability after consultation with
[python/dscho.git] / Python / mactoolboxglue.c
blob68876eb08fbe201d3c9a41fbfbaa3fd03c9a8af9
1 /***********************************************************
2 Copyright 1991-1997 by Stichting Mathematisch Centrum, Amsterdam,
3 The Netherlands.
5 All Rights Reserved
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.
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.
23 ******************************************************************/
26 #include "Python.h"
27 #include "pymactoolbox.h"
29 #ifdef WITHOUT_FRAMEWORKS
30 #include <Script.h>
31 #include <Resources.h>
32 #endif
35 ** Find out what the current script is.
36 ** Donated by Fredrik Lund.
38 char *PyMac_getscript()
40 #if TARGET_API_MAC_OSX
41 /* We cannot use GetSysFont because it requires the window manager
42 ** There are other APIs to query the default 8 bit encoding, but
43 ** I don't know about them (yet).
45 return "ascii";
46 #else
47 int font, script, lang;
48 font = 0;
49 font = GetSysFont();
50 script = FontToScript(font);
51 switch (script) {
52 case smRoman:
53 lang = GetScriptVariable(script, smScriptLang);
54 if (lang == langIcelandic)
55 return "mac-iceland";
56 else if (lang == langTurkish)
57 return "mac-turkish";
58 else if (lang == langGreek)
59 return "mac-greek";
60 else
61 return "mac-roman";
62 break;
63 #if 0
64 /* We don't have a codec for this, so don't return it */
65 case smJapanese:
66 return "mac-japan";
67 #endif
68 case smGreek:
69 return "mac-greek";
70 case smCyrillic:
71 return "mac-cyrillic";
72 default:
73 return "ascii"; /* better than nothing */
75 #endif /* TARGET_API_MAC_OSX */
78 /* Like strerror() but for Mac OS error numbers */
79 char *PyMac_StrError(int err)
81 static char buf[256];
82 Handle h;
83 char *str;
85 h = GetResource('Estr', err);
86 if ( h ) {
87 HLock(h);
88 str = (char *)*h;
89 memcpy(buf, str+1, (unsigned char)str[0]);
90 buf[(unsigned char)str[0]] = '\0';
91 HUnlock(h);
92 ReleaseResource(h);
93 } else {
94 PyOS_snprintf(buf, sizeof(buf), "Mac OS error code %d", err);
96 return buf;
99 /* Exception object shared by all Mac specific modules for Mac OS errors */
100 PyObject *PyMac_OSErrException;
102 /* Initialize and return PyMac_OSErrException */
103 PyObject *
104 PyMac_GetOSErrException(void)
106 if (PyMac_OSErrException == NULL)
107 PyMac_OSErrException = PyString_FromString("MacOS.Error");
108 return PyMac_OSErrException;
111 /* Set a MAC-specific error from errno, and return NULL; return None if no error */
112 PyObject *
113 PyErr_Mac(PyObject *eobj, int err)
115 char *msg;
116 PyObject *v;
118 if (err == 0 && !PyErr_Occurred()) {
119 Py_INCREF(Py_None);
120 return Py_None;
122 if (err == -1 && PyErr_Occurred())
123 return NULL;
124 msg = PyMac_StrError(err);
125 v = Py_BuildValue("(is)", err, msg);
126 PyErr_SetObject(eobj, v);
127 Py_DECREF(v);
128 return NULL;
131 /* Call PyErr_Mac with PyMac_OSErrException */
132 PyObject *
133 PyMac_Error(OSErr err)
135 return PyErr_Mac(PyMac_GetOSErrException(), err);
139 #if TARGET_API_MAC_OSX
140 OSErr
141 PyMac_GetFullPathname(FSSpec *fss, char *path, int len)
143 FSRef fsr;
144 OSErr err;
146 *path = '\0';
147 err = FSpMakeFSRef(fss, &fsr);
148 if ( err == fnfErr ) {
149 /* FSSpecs can point to non-existing files, fsrefs can't. */
150 FSSpec fss2;
151 int tocopy;
153 err = FSMakeFSSpec(fss->vRefNum, fss->parID, "", &fss2);
154 if ( err ) return err;
155 err = FSpMakeFSRef(&fss2, &fsr);
156 if ( err ) return err;
157 err = (OSErr)FSRefMakePath(&fsr, path, len-1);
158 if ( err ) return err;
159 /* This part is not 100% safe: we append the filename part, but
160 ** I'm not sure that we don't run afoul of the various 8bit
161 ** encodings here. Will have to look this up at some point...
163 strcat(path, "/");
164 tocopy = fss->name[0];
165 if ( strlen(path) + tocopy >= len )
166 tocopy = len - strlen(path) - 1;
167 if ( tocopy > 0 )
168 strncat(path, fss->name+1, tocopy);
169 } else {
170 if ( err ) return err;
171 err = (OSErr)FSRefMakePath(&fsr, path, len);
172 if ( err ) return err;
174 return 0;
177 #endif /* TARGET_API_MAC_OSX */
179 #ifdef WITH_NEXT_FRAMEWORK
181 ** In a bundle, find a file "resourceName" of type "resourceType". Return the
182 ** full pathname in "resourceURLCstr".
184 static int
185 locateResourcePy(CFStringRef resourceType, CFStringRef resourceName, char *resourceURLCStr, int length)
187 CFBundleRef mainBundle = NULL;
188 CFURLRef URL, absoluteURL;
189 CFStringRef filenameString, filepathString;
190 CFIndex size, i;
191 CFArrayRef arrayRef = NULL;
192 int success = 0;
194 #if TARGET_API_MAC_OSX
195 CFURLPathStyle thePathStyle = kCFURLPOSIXPathStyle;
196 #else
197 CFURLPathStyle thePathStyle = kCFURLHFSPathStyle;
198 #endif
200 /* Get a reference to our main bundle */
201 mainBundle = CFBundleGetMainBundle();
203 /* If we are running inside a bundle, look through it. Otherwise, do nothing. */
204 if (mainBundle) {
206 /* Look for py files in the main bundle by type */
207 arrayRef = CFBundleCopyResourceURLsOfType( mainBundle,
208 resourceType,
209 NULL );
211 /* See if there are any filename matches */
212 size = CFArrayGetCount(arrayRef);
213 for (i = 0; i < size; i++) {
214 URL = CFArrayGetValueAtIndex(arrayRef, i);
215 filenameString = CFURLCopyLastPathComponent(URL);
216 if (CFStringCompare(filenameString, resourceName, 0) == kCFCompareEqualTo) {
217 /* We found a match, get the file's full path */
218 absoluteURL = CFURLCopyAbsoluteURL(URL);
219 filepathString = CFURLCopyFileSystemPath(absoluteURL, thePathStyle);
220 CFRelease(absoluteURL);
222 /* Copy the full path into the caller's character buffer */
223 success = CFStringGetCString(filepathString, resourceURLCStr, length,
224 kCFStringEncodingMacRoman);
226 CFRelease(filepathString);
228 CFRelease(filenameString);
230 CFRelease(arrayRef);
232 return success;
236 ** iff we are running in a .app framework then we could be
237 ** the main program for an applet. In that case, return the
238 ** script filename for the applet.
239 ** Otherwise return NULL.
241 char *
242 PyMac_GetAppletScriptFile(void)
244 static char scriptpath[1024];
246 /* First we see whether we have __rawmain__.py and run that if it
247 ** is there. This is used for applets that want sys.argv to be
248 ** unix-like: __rawmain__ will construct it (from the initial appleevent)
249 ** and then call __main__.py.
251 if (locateResourcePy(CFSTR("py"), CFSTR("__rawmain__.py"), scriptpath, 1024)) {
252 return scriptpath;
253 } else if (locateResourcePy(CFSTR("pyc"), CFSTR("__rawmain__.pyc"), scriptpath, 1024)) {
254 return scriptpath;
255 } else if (locateResourcePy(CFSTR("py"), CFSTR("__main__.py"), scriptpath, 1024)) {
256 return scriptpath;
257 } else if (locateResourcePy(CFSTR("pyc"), CFSTR("__main__.pyc"), scriptpath, 1024)) {
258 return scriptpath;
260 return NULL;
263 #endif
266 /* Convert a 4-char string object argument to an OSType value */
268 PyMac_GetOSType(PyObject *v, OSType *pr)
270 if (!PyString_Check(v) || PyString_Size(v) != 4) {
271 PyErr_SetString(PyExc_TypeError,
272 "OSType arg must be string of 4 chars");
273 return 0;
275 memcpy((char *)pr, PyString_AsString(v), 4);
276 return 1;
279 /* Convert an OSType value to a 4-char string object */
280 PyObject *
281 PyMac_BuildOSType(OSType t)
283 return PyString_FromStringAndSize((char *)&t, 4);
286 /* Convert an NumVersion value to a 4-element tuple */
287 PyObject *
288 PyMac_BuildNumVersion(NumVersion t)
290 return Py_BuildValue("(hhhh)", t.majorRev, t.minorAndBugRev, t.stage, t.nonRelRev);
294 /* Convert a Python string object to a Str255 */
296 PyMac_GetStr255(PyObject *v, Str255 pbuf)
298 int len;
299 if (!PyString_Check(v) || (len = PyString_Size(v)) > 255) {
300 PyErr_SetString(PyExc_TypeError,
301 "Str255 arg must be string of at most 255 chars");
302 return 0;
304 pbuf[0] = len;
305 memcpy((char *)(pbuf+1), PyString_AsString(v), len);
306 return 1;
309 /* Convert a Str255 to a Python string object */
310 PyObject *
311 PyMac_BuildStr255(Str255 s)
313 if ( s == NULL ) {
314 PyErr_SetString(PyExc_SystemError, "Str255 pointer is NULL");
315 return NULL;
317 return PyString_FromStringAndSize((char *)&s[1], (int)s[0]);
320 PyObject *
321 PyMac_BuildOptStr255(Str255 s)
323 if ( s == NULL ) {
324 Py_INCREF(Py_None);
325 return Py_None;
327 return PyString_FromStringAndSize((char *)&s[1], (int)s[0]);
332 /* Convert a Python object to a Rect.
333 The object must be a (left, top, right, bottom) tuple.
334 (This differs from the order in the struct but is consistent with
335 the arguments to SetRect(), and also with STDWIN). */
337 PyMac_GetRect(PyObject *v, Rect *r)
339 return PyArg_Parse(v, "(hhhh)", &r->left, &r->top, &r->right, &r->bottom);
342 /* Convert a Rect to a Python object */
343 PyObject *
344 PyMac_BuildRect(Rect *r)
346 return Py_BuildValue("(hhhh)", r->left, r->top, r->right, r->bottom);
350 /* Convert a Python object to a Point.
351 The object must be a (h, v) tuple.
352 (This differs from the order in the struct but is consistent with
353 the arguments to SetPoint(), and also with STDWIN). */
355 PyMac_GetPoint(PyObject *v, Point *p)
357 return PyArg_Parse(v, "(hh)", &p->h, &p->v);
360 /* Convert a Point to a Python object */
361 PyObject *
362 PyMac_BuildPoint(Point p)
364 return Py_BuildValue("(hh)", p.h, p.v);
368 /* Convert a Python object to an EventRecord.
369 The object must be a (what, message, when, (v, h), modifiers) tuple. */
371 PyMac_GetEventRecord(PyObject *v, EventRecord *e)
373 return PyArg_Parse(v, "(Hll(hh)H)",
374 &e->what,
375 &e->message,
376 &e->when,
377 &e->where.h,
378 &e->where.v,
379 &e->modifiers);
382 /* Convert a Rect to an EventRecord object */
383 PyObject *
384 PyMac_BuildEventRecord(EventRecord *e)
386 return Py_BuildValue("(hll(hh)h)",
387 e->what,
388 e->message,
389 e->when,
390 e->where.h,
391 e->where.v,
392 e->modifiers);
395 /* Convert Python object to Fixed */
397 PyMac_GetFixed(PyObject *v, Fixed *f)
399 double d;
401 if( !PyArg_Parse(v, "d", &d))
402 return 0;
403 *f = (Fixed)(d * 0x10000);
404 return 1;
407 /* Convert a Fixed to a Python object */
408 PyObject *
409 PyMac_BuildFixed(Fixed f)
411 double d;
413 d = f;
414 d = d / 0x10000;
415 return Py_BuildValue("d", d);
418 /* Convert wide to/from Python int or (hi, lo) tuple. XXXX Should use Python longs */
420 PyMac_Getwide(PyObject *v, wide *rv)
422 if (PyInt_Check(v)) {
423 rv->hi = 0;
424 rv->lo = PyInt_AsLong(v);
425 if( rv->lo & 0x80000000 )
426 rv->hi = -1;
427 return 1;
429 return PyArg_Parse(v, "(ll)", &rv->hi, &rv->lo);
433 PyObject *
434 PyMac_Buildwide(wide *w)
436 if ( (w->hi == 0 && (w->lo & 0x80000000) == 0) ||
437 (w->hi == -1 && (w->lo & 0x80000000) ) )
438 return PyInt_FromLong(w->lo);
439 return Py_BuildValue("(ll)", w->hi, w->lo);
442 #ifdef USE_TOOLBOX_OBJECT_GLUE
444 ** Glue together the toolbox objects.
446 ** Because toolbox modules interdepend on each other, they use each others
447 ** object types, on MacOSX/MachO this leads to the situation that they
448 ** cannot be dynamically loaded (or they would all have to be lumped into
449 ** a single .so, but this would be bad for extensibility).
451 ** This file defines wrappers for all the _New and _Convert functions,
452 ** which are the Py_BuildValue and PyArg_ParseTuple helpers. The wrappers
453 ** check an indirection function pointer, and if it isn't filled in yet
454 ** they import the appropriate module, whose init routine should fill in
455 ** the pointer.
458 #define GLUE_NEW(object, routinename, module) \
459 PyObject *(*PyMacGluePtr_##routinename)(object); \
461 PyObject *routinename(object cobj) { \
462 if (!PyMacGluePtr_##routinename) { \
463 if (!PyImport_ImportModule(module)) return NULL; \
464 if (!PyMacGluePtr_##routinename) { \
465 PyErr_SetString(PyExc_ImportError, "Module did not provide routine: " module ": " #routinename); \
466 return NULL; \
469 return (*PyMacGluePtr_##routinename)(cobj); \
472 #define GLUE_CONVERT(object, routinename, module) \
473 int (*PyMacGluePtr_##routinename)(PyObject *, object *); \
475 int routinename(PyObject *pyobj, object *cobj) { \
476 if (!PyMacGluePtr_##routinename) { \
477 if (!PyImport_ImportModule(module)) return NULL; \
478 if (!PyMacGluePtr_##routinename) { \
479 PyErr_SetString(PyExc_ImportError, "Module did not provide routine: " module ": " #routinename); \
480 return NULL; \
483 return (*PyMacGluePtr_##routinename)(pyobj, cobj); \
486 GLUE_NEW(FSSpec *, PyMac_BuildFSSpec, "macfs")
487 GLUE_CONVERT(FSSpec, PyMac_GetFSSpec, "macfs")
488 GLUE_NEW(FSRef *, PyMac_BuildFSRef, "macfs")
489 GLUE_CONVERT(FSRef, PyMac_GetFSRef, "macfs")
491 GLUE_NEW(AppleEvent *, AEDesc_New, "Carbon.AE") /* XXXX Why by address? */
492 GLUE_CONVERT(AppleEvent, AEDesc_Convert, "Carbon.AE")
494 GLUE_NEW(Component, CmpObj_New, "Carbon.Cm")
495 GLUE_CONVERT(Component, CmpObj_Convert, "Carbon.Cm")
496 GLUE_NEW(ComponentInstance, CmpInstObj_New, "Carbon.Cm")
497 GLUE_CONVERT(ComponentInstance, CmpInstObj_Convert, "Carbon.Cm")
499 GLUE_NEW(ControlHandle, CtlObj_New, "Carbon.Ctl")
500 GLUE_CONVERT(ControlHandle, CtlObj_Convert, "Carbon.Ctl")
502 GLUE_NEW(DialogPtr, DlgObj_New, "Carbon.Dlg")
503 GLUE_CONVERT(DialogPtr, DlgObj_Convert, "Carbon.Dlg")
504 GLUE_NEW(DialogPtr, DlgObj_WhichDialog, "Carbon.Dlg")
506 GLUE_NEW(DragReference, DragObj_New, "Carbon.Drag")
507 GLUE_CONVERT(DragReference, DragObj_Convert, "Carbon.Drag")
509 GLUE_NEW(ListHandle, ListObj_New, "Carbon.List")
510 GLUE_CONVERT(ListHandle, ListObj_Convert, "Carbon.List")
512 GLUE_NEW(MenuHandle, MenuObj_New, "Carbon.Menu")
513 GLUE_CONVERT(MenuHandle, MenuObj_Convert, "Carbon.Menu")
515 GLUE_NEW(GrafPtr, GrafObj_New, "Carbon.Qd")
516 GLUE_CONVERT(GrafPtr, GrafObj_Convert, "Carbon.Qd")
517 GLUE_NEW(BitMapPtr, BMObj_New, "Carbon.Qd")
518 GLUE_CONVERT(BitMapPtr, BMObj_Convert, "Carbon.Qd")
519 GLUE_NEW(RGBColor *, QdRGB_New, "Carbon.Qd") /* XXXX Why? */
520 GLUE_CONVERT(RGBColor, QdRGB_Convert, "Carbon.Qd")
522 GLUE_NEW(GWorldPtr, GWorldObj_New, "Carbon.Qdoffs")
523 GLUE_CONVERT(GWorldPtr, GWorldObj_Convert, "Carbon.Qdoffs")
525 GLUE_NEW(Track, TrackObj_New, "Carbon.Qt")
526 GLUE_CONVERT(Track, TrackObj_Convert, "Carbon.Qt")
527 GLUE_NEW(Movie, MovieObj_New, "Carbon.Qt")
528 GLUE_CONVERT(Movie, MovieObj_Convert, "Carbon.Qt")
529 GLUE_NEW(MovieController, MovieCtlObj_New, "Carbon.Qt")
530 GLUE_CONVERT(MovieController, MovieCtlObj_Convert, "Carbon.Qt")
531 GLUE_NEW(TimeBase, TimeBaseObj_New, "Carbon.Qt")
532 GLUE_CONVERT(TimeBase, TimeBaseObj_Convert, "Carbon.Qt")
533 GLUE_NEW(UserData, UserDataObj_New, "Carbon.Qt")
534 GLUE_CONVERT(UserData, UserDataObj_Convert, "Carbon.Qt")
535 GLUE_NEW(Media, MediaObj_New, "Carbon.Qt")
536 GLUE_CONVERT(Media, MediaObj_Convert, "Carbon.Qt")
538 GLUE_NEW(Handle, ResObj_New, "Carbon.Res")
539 GLUE_CONVERT(Handle, ResObj_Convert, "Carbon.Res")
540 GLUE_NEW(Handle, OptResObj_New, "Carbon.Res")
541 GLUE_CONVERT(Handle, OptResObj_Convert, "Carbon.Res")
543 GLUE_NEW(TEHandle, TEObj_New, "Carbon.TE")
544 GLUE_CONVERT(TEHandle, TEObj_Convert, "Carbon.TE")
546 GLUE_NEW(WindowPtr, WinObj_New, "Carbon.Win")
547 GLUE_CONVERT(WindowPtr, WinObj_Convert, "Carbon.Win")
548 GLUE_NEW(WindowPtr, WinObj_WhichWindow, "Carbon.Win")
550 GLUE_CONVERT(CFTypeRef, CFTypeRefObj_Convert, "Carbon.CF")
551 GLUE_NEW(CFTypeRef, CFTypeRefObj_New, "Carbon.CF")
553 GLUE_CONVERT(CFStringRef, CFStringRefObj_Convert, "Carbon.CF")
554 GLUE_NEW(CFStringRef, CFStringRefObj_New, "Carbon.CF")
555 GLUE_CONVERT(CFMutableStringRef, CFMutableStringRefObj_Convert, "Carbon.CF")
556 GLUE_NEW(CFMutableStringRef, CFMutableStringRefObj_New, "Carbon.CF")
558 GLUE_CONVERT(CFArrayRef, CFArrayRefObj_Convert, "Carbon.CF")
559 GLUE_NEW(CFArrayRef, CFArrayRefObj_New, "Carbon.CF")
560 GLUE_CONVERT(CFMutableArrayRef, CFMutableArrayRefObj_Convert, "Carbon.CF")
561 GLUE_NEW(CFMutableArrayRef, CFMutableArrayRefObj_New, "Carbon.CF")
563 GLUE_CONVERT(CFDictionaryRef, CFDictionaryRefObj_Convert, "Carbon.CF")
564 GLUE_NEW(CFDictionaryRef, CFDictionaryRefObj_New, "Carbon.CF")
565 GLUE_CONVERT(CFMutableDictionaryRef, CFMutableDictionaryRefObj_Convert, "Carbon.CF")
566 GLUE_NEW(CFMutableDictionaryRef, CFMutableDictionaryRefObj_New, "Carbon.CF")
568 GLUE_CONVERT(CFURLRef, CFURLRefObj_Convert, "Carbon.CF")
569 GLUE_CONVERT(CFURLRef, OptionalCFURLRefObj_Convert, "Carbon.CF")
570 GLUE_NEW(CFURLRef, CFURLRefObj_New, "Carbon.CF")
572 #endif /* USE_TOOLBOX_OBJECT_GLUE */