1 /***********************************************************
2 Copyright 1991-1997 by Stichting Mathematisch Centrum, Amsterdam,
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 ******************************************************************/
27 #include "pymactoolbox.h"
29 #ifdef WITHOUT_FRAMEWORKS
31 #include <Resources.h>
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).
47 int font
, script
, lang
;
50 script
= FontToScript(font
);
53 lang
= GetScriptVariable(script
, smScriptLang
);
54 if (lang
== langIcelandic
)
56 else if (lang
== langTurkish
)
58 else if (lang
== langGreek
)
64 /* We don't have a codec for this, so don't return it */
71 return "mac-cyrillic";
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
)
85 h
= GetResource('Estr', err
);
89 memcpy(buf
, str
+1, (unsigned char)str
[0]);
90 buf
[(unsigned char)str
[0]] = '\0';
94 PyOS_snprintf(buf
, sizeof(buf
), "Mac OS error code %d", err
);
99 /* Exception object shared by all Mac specific modules for Mac OS errors */
100 PyObject
*PyMac_OSErrException
;
102 /* Initialize and return PyMac_OSErrException */
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 */
113 PyErr_Mac(PyObject
*eobj
, int err
)
118 if (err
== 0 && !PyErr_Occurred()) {
122 if (err
== -1 && PyErr_Occurred())
124 msg
= PyMac_StrError(err
);
125 v
= Py_BuildValue("(is)", err
, msg
);
126 PyErr_SetObject(eobj
, v
);
131 /* Call PyErr_Mac with PyMac_OSErrException */
133 PyMac_Error(OSErr err
)
135 return PyErr_Mac(PyMac_GetOSErrException(), err
);
139 #if TARGET_API_MAC_OSX
141 PyMac_GetFullPathname(FSSpec
*fss
, char *path
, int len
)
147 err
= FSpMakeFSRef(fss
, &fsr
);
148 if ( err
== fnfErr
) {
149 /* FSSpecs can point to non-existing files, fsrefs can't. */
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...
164 tocopy
= fss
->name
[0];
165 if ( strlen(path
) + tocopy
>= len
)
166 tocopy
= len
- strlen(path
) - 1;
168 strncat(path
, fss
->name
+1, tocopy
);
170 if ( err
) return err
;
171 err
= (OSErr
)FSRefMakePath(&fsr
, path
, len
);
172 if ( err
) return err
;
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".
185 locateResourcePy(CFStringRef resourceType
, CFStringRef resourceName
, char *resourceURLCStr
, int length
)
187 CFBundleRef mainBundle
= NULL
;
188 CFURLRef URL
, absoluteURL
;
189 CFStringRef filenameString
, filepathString
;
191 CFArrayRef arrayRef
= NULL
;
194 #if TARGET_API_MAC_OSX
195 CFURLPathStyle thePathStyle
= kCFURLPOSIXPathStyle
;
197 CFURLPathStyle thePathStyle
= kCFURLHFSPathStyle
;
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. */
206 /* Look for py files in the main bundle by type */
207 arrayRef
= CFBundleCopyResourceURLsOfType( mainBundle
,
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
);
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.
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)) {
253 } else if (locateResourcePy(CFSTR("pyc"), CFSTR("__rawmain__.pyc"), scriptpath
, 1024)) {
255 } else if (locateResourcePy(CFSTR("py"), CFSTR("__main__.py"), scriptpath
, 1024)) {
257 } else if (locateResourcePy(CFSTR("pyc"), CFSTR("__main__.pyc"), scriptpath
, 1024)) {
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");
275 memcpy((char *)pr
, PyString_AsString(v
), 4);
279 /* Convert an OSType value to a 4-char string object */
281 PyMac_BuildOSType(OSType t
)
283 return PyString_FromStringAndSize((char *)&t
, 4);
286 /* Convert an NumVersion value to a 4-element tuple */
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
)
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");
305 memcpy((char *)(pbuf
+1), PyString_AsString(v
), len
);
309 /* Convert a Str255 to a Python string object */
311 PyMac_BuildStr255(Str255 s
)
314 PyErr_SetString(PyExc_SystemError
, "Str255 pointer is NULL");
317 return PyString_FromStringAndSize((char *)&s
[1], (int)s
[0]);
321 PyMac_BuildOptStr255(Str255 s
)
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 */
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 */
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)",
382 /* Convert a Rect to an EventRecord object */
384 PyMac_BuildEventRecord(EventRecord
*e
)
386 return Py_BuildValue("(hll(hh)h)",
395 /* Convert Python object to Fixed */
397 PyMac_GetFixed(PyObject
*v
, Fixed
*f
)
401 if( !PyArg_Parse(v
, "d", &d
))
403 *f
= (Fixed
)(d
* 0x10000);
407 /* Convert a Fixed to a Python object */
409 PyMac_BuildFixed(Fixed f
)
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
)) {
424 rv
->lo
= PyInt_AsLong(v
);
425 if( rv
->lo
& 0x80000000 )
429 return PyArg_Parse(v
, "(ll)", &rv
->hi
, &rv
->lo
);
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
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); \
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); \
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 */