blob: ea21b4e045ee99bcc6f38b9fbced0512227433ac [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#ifdef WITHOUT_FRAMEWORKS
Jack Jansend844a5f2001-08-08 15:28:03 +000030#include <Script.h>
31#include <Resources.h>
Jack Jansen94bebc02001-08-08 13:17:31 +000032#endif
33
34/*
35** Find out what the current script is.
36** Donated by Fredrik Lund.
37*/
38char *PyMac_getscript()
39{
Jack Jansen666b1e72001-10-31 12:11:48 +000040#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).
44 */
45 return "ascii";
46#else
Jack Jansen94bebc02001-08-08 13:17:31 +000047 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 */
74 }
Jack Jansen666b1e72001-10-31 12:11:48 +000075#endif /* TARGET_API_MAC_OSX */
Jack Jansen94bebc02001-08-08 13:17:31 +000076}
77
78/* Like strerror() but for Mac OS error numbers */
79char *PyMac_StrError(int err)
80{
81 static char buf[256];
82 Handle h;
83 char *str;
84
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 sprintf(buf, "Mac OS error code %d", err);
95 }
96 return buf;
97}
98
99/* Exception object shared by all Mac specific modules for Mac OS errors */
100PyObject *PyMac_OSErrException;
101
102/* Initialize and return PyMac_OSErrException */
103PyObject *
Jack Jansen697842f2001-09-10 22:00:39 +0000104PyMac_GetOSErrException(void)
Jack Jansen94bebc02001-08-08 13:17:31 +0000105{
106 if (PyMac_OSErrException == NULL)
107 PyMac_OSErrException = PyString_FromString("MacOS.Error");
108 return PyMac_OSErrException;
109}
110
111/* Set a MAC-specific error from errno, and return NULL; return None if no error */
112PyObject *
113PyErr_Mac(PyObject *eobj, int err)
114{
115 char *msg;
116 PyObject *v;
117
118 if (err == 0 && !PyErr_Occurred()) {
119 Py_INCREF(Py_None);
120 return Py_None;
121 }
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;
129}
130
131/* Call PyErr_Mac with PyMac_OSErrException */
132PyObject *
133PyMac_Error(OSErr err)
134{
135 return PyErr_Mac(PyMac_GetOSErrException(), err);
136}
137
Jack Jansen697842f2001-09-10 22:00:39 +0000138
139#if TARGET_API_MAC_OSX
140OSErr
141PyMac_GetFullPathname(FSSpec *fss, char *path, int len)
142{
143 FSRef fsr;
144 OSErr err;
145
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;
152
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...
162 */
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;
173 }
174 return 0;
175}
176
177#endif /* TARGET_API_MAC_OSX */
Jack Jansen94bebc02001-08-08 13:17:31 +0000178/* Convert a 4-char string object argument to an OSType value */
179int
180PyMac_GetOSType(PyObject *v, OSType *pr)
181{
182 if (!PyString_Check(v) || PyString_Size(v) != 4) {
183 PyErr_SetString(PyExc_TypeError,
184 "OSType arg must be string of 4 chars");
185 return 0;
186 }
187 memcpy((char *)pr, PyString_AsString(v), 4);
188 return 1;
189}
190
191/* Convert an OSType value to a 4-char string object */
192PyObject *
193PyMac_BuildOSType(OSType t)
194{
195 return PyString_FromStringAndSize((char *)&t, 4);
196}
197
198/* Convert an NumVersion value to a 4-element tuple */
199PyObject *
200PyMac_BuildNumVersion(NumVersion t)
201{
202 return Py_BuildValue("(hhhh)", t.majorRev, t.minorAndBugRev, t.stage, t.nonRelRev);
203}
204
205
206/* Convert a Python string object to a Str255 */
207int
208PyMac_GetStr255(PyObject *v, Str255 pbuf)
209{
210 int len;
211 if (!PyString_Check(v) || (len = PyString_Size(v)) > 255) {
212 PyErr_SetString(PyExc_TypeError,
213 "Str255 arg must be string of at most 255 chars");
214 return 0;
215 }
216 pbuf[0] = len;
217 memcpy((char *)(pbuf+1), PyString_AsString(v), len);
218 return 1;
219}
220
221/* Convert a Str255 to a Python string object */
222PyObject *
223PyMac_BuildStr255(Str255 s)
224{
225 if ( s == NULL ) {
226 PyErr_SetString(PyExc_SystemError, "Str255 pointer is NULL");
227 return NULL;
228 }
229 return PyString_FromStringAndSize((char *)&s[1], (int)s[0]);
230}
231
232PyObject *
233PyMac_BuildOptStr255(Str255 s)
234{
235 if ( s == NULL ) {
236 Py_INCREF(Py_None);
237 return Py_None;
238 }
239 return PyString_FromStringAndSize((char *)&s[1], (int)s[0]);
240}
241
242
243
244/* Convert a Python object to a Rect.
245 The object must be a (left, top, right, bottom) tuple.
246 (This differs from the order in the struct but is consistent with
247 the arguments to SetRect(), and also with STDWIN). */
248int
249PyMac_GetRect(PyObject *v, Rect *r)
250{
251 return PyArg_Parse(v, "(hhhh)", &r->left, &r->top, &r->right, &r->bottom);
252}
253
254/* Convert a Rect to a Python object */
255PyObject *
256PyMac_BuildRect(Rect *r)
257{
258 return Py_BuildValue("(hhhh)", r->left, r->top, r->right, r->bottom);
259}
260
261
262/* Convert a Python object to a Point.
263 The object must be a (h, v) tuple.
264 (This differs from the order in the struct but is consistent with
265 the arguments to SetPoint(), and also with STDWIN). */
266int
267PyMac_GetPoint(PyObject *v, Point *p)
268{
269 return PyArg_Parse(v, "(hh)", &p->h, &p->v);
270}
271
272/* Convert a Point to a Python object */
273PyObject *
274PyMac_BuildPoint(Point p)
275{
276 return Py_BuildValue("(hh)", p.h, p.v);
277}
278
279
280/* Convert a Python object to an EventRecord.
281 The object must be a (what, message, when, (v, h), modifiers) tuple. */
282int
283PyMac_GetEventRecord(PyObject *v, EventRecord *e)
284{
285 return PyArg_Parse(v, "(Hll(hh)H)",
286 &e->what,
287 &e->message,
288 &e->when,
289 &e->where.h,
290 &e->where.v,
291 &e->modifiers);
292}
293
294/* Convert a Rect to an EventRecord object */
295PyObject *
296PyMac_BuildEventRecord(EventRecord *e)
297{
298 return Py_BuildValue("(hll(hh)h)",
299 e->what,
300 e->message,
301 e->when,
302 e->where.h,
303 e->where.v,
304 e->modifiers);
305}
306
307/* Convert Python object to Fixed */
308int
309PyMac_GetFixed(PyObject *v, Fixed *f)
310{
311 double d;
312
313 if( !PyArg_Parse(v, "d", &d))
314 return 0;
315 *f = (Fixed)(d * 0x10000);
316 return 1;
317}
318
Jack Jansen06bd3232001-08-27 14:01:05 +0000319/* Convert a Fixed to a Python object */
Jack Jansen94bebc02001-08-08 13:17:31 +0000320PyObject *
321PyMac_BuildFixed(Fixed f)
322{
323 double d;
324
325 d = f;
326 d = d / 0x10000;
327 return Py_BuildValue("d", d);
328}
329
330/* Convert wide to/from Python int or (hi, lo) tuple. XXXX Should use Python longs */
331int
332PyMac_Getwide(PyObject *v, wide *rv)
333{
334 if (PyInt_Check(v)) {
335 rv->hi = 0;
336 rv->lo = PyInt_AsLong(v);
337 if( rv->lo & 0x80000000 )
338 rv->hi = -1;
339 return 1;
340 }
341 return PyArg_Parse(v, "(ll)", &rv->hi, &rv->lo);
342}
343
344
345PyObject *
346PyMac_Buildwide(wide *w)
347{
348 if ( (w->hi == 0 && (w->lo & 0x80000000) == 0) ||
349 (w->hi == -1 && (w->lo & 0x80000000) ) )
350 return PyInt_FromLong(w->lo);
351 return Py_BuildValue("(ll)", w->hi, w->lo);
352}
353
354#ifdef USE_TOOLBOX_OBJECT_GLUE
355/*
356** Glue together the toolbox objects.
357**
358** Because toolbox modules interdepend on each other, they use each others
359** object types, on MacOSX/MachO this leads to the situation that they
360** cannot be dynamically loaded (or they would all have to be lumped into
361** a single .so, but this would be bad for extensibility).
362**
363** This file defines wrappers for all the _New and _Convert functions,
364** which are the Py_BuildValue and PyArg_ParseTuple helpers. The wrappers
365** check an indirection function pointer, and if it isn't filled in yet
366** they import the appropriate module, whose init routine should fill in
367** the pointer.
368*/
369
370#define GLUE_NEW(object, routinename, module) \
371PyObject *(*PyMacGluePtr_##routinename)(object); \
372\
373PyObject *routinename(object cobj) { \
374 if (!PyMacGluePtr_##routinename) { \
375 if (!PyImport_ImportModule(module)) return NULL; \
376 if (!PyMacGluePtr_##routinename) { \
377 PyErr_SetString(PyExc_ImportError, "Module did not provide routine: " module ": " #routinename); \
378 return NULL; \
379 } \
380 } \
381 return (*PyMacGluePtr_##routinename)(cobj); \
382}
383
384#define GLUE_CONVERT(object, routinename, module) \
385int (*PyMacGluePtr_##routinename)(PyObject *, object *); \
386\
387int routinename(PyObject *pyobj, object *cobj) { \
388 if (!PyMacGluePtr_##routinename) { \
389 if (!PyImport_ImportModule(module)) return NULL; \
390 if (!PyMacGluePtr_##routinename) { \
391 PyErr_SetString(PyExc_ImportError, "Module did not provide routine: " module ": " #routinename); \
392 return NULL; \
393 } \
394 } \
395 return (*PyMacGluePtr_##routinename)(pyobj, cobj); \
396}
Jack Jansenfabd00f2001-09-01 23:39:58 +0000397
398GLUE_NEW(FSSpec *, PyMac_BuildFSSpec, "macfs")
Jack Jansen94bebc02001-08-08 13:17:31 +0000399GLUE_CONVERT(FSSpec, PyMac_GetFSSpec, "macfs")
Jack Jansenfabd00f2001-09-01 23:39:58 +0000400GLUE_NEW(FSRef *, PyMac_BuildFSRef, "macfs")
401GLUE_CONVERT(FSRef, PyMac_GetFSRef, "macfs")
Jack Jansen94bebc02001-08-08 13:17:31 +0000402
Jack Jansen06bd3232001-08-27 14:01:05 +0000403GLUE_NEW(AppleEvent *, AEDesc_New, "Carbon.AE") /* XXXX Why by address? */
404GLUE_CONVERT(AppleEvent, AEDesc_Convert, "Carbon.AE")
Jack Jansen94bebc02001-08-08 13:17:31 +0000405
Jack Jansen06bd3232001-08-27 14:01:05 +0000406GLUE_NEW(Component, CmpObj_New, "Carbon.Cm")
407GLUE_CONVERT(Component, CmpObj_Convert, "Carbon.Cm")
408GLUE_NEW(ComponentInstance, CmpInstObj_New, "Carbon.Cm")
409GLUE_CONVERT(ComponentInstance, CmpInstObj_Convert, "Carbon.Cm")
Jack Jansen94bebc02001-08-08 13:17:31 +0000410
Jack Jansen06bd3232001-08-27 14:01:05 +0000411GLUE_NEW(ControlHandle, CtlObj_New, "Carbon.Ctl")
412GLUE_CONVERT(ControlHandle, CtlObj_Convert, "Carbon.Ctl")
Jack Jansen94bebc02001-08-08 13:17:31 +0000413
Jack Jansen06bd3232001-08-27 14:01:05 +0000414GLUE_NEW(DialogPtr, DlgObj_New, "Carbon.Dlg")
415GLUE_CONVERT(DialogPtr, DlgObj_Convert, "Carbon.Dlg")
416GLUE_NEW(DialogPtr, DlgObj_WhichDialog, "Carbon.Dlg")
Jack Jansen94bebc02001-08-08 13:17:31 +0000417
Jack Jansen06bd3232001-08-27 14:01:05 +0000418GLUE_NEW(DragReference, DragObj_New, "Carbon.Drag")
419GLUE_CONVERT(DragReference, DragObj_Convert, "Carbon.Drag")
Jack Jansen94bebc02001-08-08 13:17:31 +0000420
Jack Jansen06bd3232001-08-27 14:01:05 +0000421GLUE_NEW(ListHandle, ListObj_New, "Carbon.List")
422GLUE_CONVERT(ListHandle, ListObj_Convert, "Carbon.List")
Jack Jansen94bebc02001-08-08 13:17:31 +0000423
Jack Jansen06bd3232001-08-27 14:01:05 +0000424GLUE_NEW(MenuHandle, MenuObj_New, "Carbon.Menu")
425GLUE_CONVERT(MenuHandle, MenuObj_Convert, "Carbon.Menu")
Jack Jansen94bebc02001-08-08 13:17:31 +0000426
Jack Jansen06bd3232001-08-27 14:01:05 +0000427GLUE_NEW(GrafPtr, GrafObj_New, "Carbon.Qd")
428GLUE_CONVERT(GrafPtr, GrafObj_Convert, "Carbon.Qd")
429GLUE_NEW(BitMapPtr, BMObj_New, "Carbon.Qd")
430GLUE_CONVERT(BitMapPtr, BMObj_Convert, "Carbon.Qd")
431GLUE_NEW(RGBColor *, QdRGB_New, "Carbon.Qd") /* XXXX Why? */
432GLUE_CONVERT(RGBColor, QdRGB_Convert, "Carbon.Qd")
Jack Jansen94bebc02001-08-08 13:17:31 +0000433
Jack Jansen06bd3232001-08-27 14:01:05 +0000434GLUE_NEW(GWorldPtr, GWorldObj_New, "Carbon.Qdoffs")
435GLUE_CONVERT(GWorldPtr, GWorldObj_Convert, "Carbon.Qdoffs")
Jack Jansen94bebc02001-08-08 13:17:31 +0000436
Jack Jansen06bd3232001-08-27 14:01:05 +0000437GLUE_NEW(Track, TrackObj_New, "Carbon.Qt")
438GLUE_CONVERT(Track, TrackObj_Convert, "Carbon.Qt")
439GLUE_NEW(Movie, MovieObj_New, "Carbon.Qt")
440GLUE_CONVERT(Movie, MovieObj_Convert, "Carbon.Qt")
441GLUE_NEW(MovieController, MovieCtlObj_New, "Carbon.Qt")
442GLUE_CONVERT(MovieController, MovieCtlObj_Convert, "Carbon.Qt")
443GLUE_NEW(TimeBase, TimeBaseObj_New, "Carbon.Qt")
444GLUE_CONVERT(TimeBase, TimeBaseObj_Convert, "Carbon.Qt")
445GLUE_NEW(UserData, UserDataObj_New, "Carbon.Qt")
446GLUE_CONVERT(UserData, UserDataObj_Convert, "Carbon.Qt")
447GLUE_NEW(Media, MediaObj_New, "Carbon.Qt")
448GLUE_CONVERT(Media, MediaObj_Convert, "Carbon.Qt")
Jack Jansen94bebc02001-08-08 13:17:31 +0000449
Jack Jansen06bd3232001-08-27 14:01:05 +0000450GLUE_NEW(Handle, ResObj_New, "Carbon.Res")
451GLUE_CONVERT(Handle, ResObj_Convert, "Carbon.Res")
452GLUE_NEW(Handle, OptResObj_New, "Carbon.Res")
453GLUE_CONVERT(Handle, OptResObj_Convert, "Carbon.Res")
Jack Jansen94bebc02001-08-08 13:17:31 +0000454
Jack Jansen06bd3232001-08-27 14:01:05 +0000455GLUE_NEW(TEHandle, TEObj_New, "Carbon.TE")
456GLUE_CONVERT(TEHandle, TEObj_Convert, "Carbon.TE")
Jack Jansen94bebc02001-08-08 13:17:31 +0000457
Jack Jansen06bd3232001-08-27 14:01:05 +0000458GLUE_NEW(WindowPtr, WinObj_New, "Carbon.Win")
459GLUE_CONVERT(WindowPtr, WinObj_Convert, "Carbon.Win")
460GLUE_NEW(WindowPtr, WinObj_WhichWindow, "Carbon.Win")
Jack Jansen94bebc02001-08-08 13:17:31 +0000461
Jack Jansen537a69f2001-11-05 14:39:22 +0000462GLUE_CONVERT(CFTypeRef, CFTypeRefObj_Convert, "Carbon.CF")
463GLUE_NEW(CFTypeRef, CFTypeRefObj_New, "Carbon.CF")
464
465GLUE_CONVERT(CFStringRef, CFStringRefObj_Convert, "Carbon.CF")
466GLUE_NEW(CFStringRef, CFStringRefObj_New, "Carbon.CF")
467GLUE_CONVERT(CFMutableStringRef, CFMutableStringRefObj_Convert, "Carbon.CF")
468GLUE_NEW(CFMutableStringRef, CFMutableStringRefObj_New, "Carbon.CF")
469
470GLUE_CONVERT(CFArrayRef, CFArrayRefObj_Convert, "Carbon.CF")
471GLUE_NEW(CFArrayRef, CFArrayRefObj_New, "Carbon.CF")
472GLUE_CONVERT(CFMutableArrayRef, CFMutableArrayRefObj_Convert, "Carbon.CF")
473GLUE_NEW(CFMutableArrayRef, CFMutableArrayRefObj_New, "Carbon.CF")
474
475GLUE_CONVERT(CFDictionaryRef, CFDictionaryRefObj_Convert, "Carbon.CF")
476GLUE_NEW(CFDictionaryRef, CFDictionaryRefObj_New, "Carbon.CF")
477GLUE_CONVERT(CFMutableDictionaryRef, CFMutableDictionaryRefObj_Convert, "Carbon.CF")
478GLUE_NEW(CFMutableDictionaryRef, CFMutableDictionaryRefObj_New, "Carbon.CF")
479
480GLUE_CONVERT(CFURLRef, CFURLRefObj_Convert, "Carbon.CF")
481GLUE_CONVERT(CFURLRef, OptionalCFURLRefObj_Convert, "Carbon.CF")
482GLUE_NEW(CFURLRef, CFURLRefObj_New, "Carbon.CF")
483
Jack Jansen94bebc02001-08-08 13:17:31 +0000484#endif /* USE_TOOLBOX_OBJECT_GLUE */