blob: 52ff00b470ad173e7869389dae3f5a9efe8cbfa7 [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{
40 int font, script, lang;
41 font = 0;
42 font = GetSysFont();
43 script = FontToScript(font);
44 switch (script) {
45 case smRoman:
46 lang = GetScriptVariable(script, smScriptLang);
47 if (lang == langIcelandic)
48 return "mac-iceland";
49 else if (lang == langTurkish)
50 return "mac-turkish";
51 else if (lang == langGreek)
52 return "mac-greek";
53 else
54 return "mac-roman";
55 break;
56#if 0
57 /* We don't have a codec for this, so don't return it */
58 case smJapanese:
59 return "mac-japan";
60#endif
61 case smGreek:
62 return "mac-greek";
63 case smCyrillic:
64 return "mac-cyrillic";
65 default:
66 return "ascii"; /* better than nothing */
67 }
68}
69
70/* Like strerror() but for Mac OS error numbers */
71char *PyMac_StrError(int err)
72{
73 static char buf[256];
74 Handle h;
75 char *str;
76
77 h = GetResource('Estr', err);
78 if ( h ) {
79 HLock(h);
80 str = (char *)*h;
81 memcpy(buf, str+1, (unsigned char)str[0]);
82 buf[(unsigned char)str[0]] = '\0';
83 HUnlock(h);
84 ReleaseResource(h);
85 } else {
86 sprintf(buf, "Mac OS error code %d", err);
87 }
88 return buf;
89}
90
91/* Exception object shared by all Mac specific modules for Mac OS errors */
92PyObject *PyMac_OSErrException;
93
94/* Initialize and return PyMac_OSErrException */
95PyObject *
Jack Jansen697842f2001-09-10 22:00:39 +000096PyMac_GetOSErrException(void)
Jack Jansen94bebc02001-08-08 13:17:31 +000097{
98 if (PyMac_OSErrException == NULL)
99 PyMac_OSErrException = PyString_FromString("MacOS.Error");
100 return PyMac_OSErrException;
101}
102
103/* Set a MAC-specific error from errno, and return NULL; return None if no error */
104PyObject *
105PyErr_Mac(PyObject *eobj, int err)
106{
107 char *msg;
108 PyObject *v;
109
110 if (err == 0 && !PyErr_Occurred()) {
111 Py_INCREF(Py_None);
112 return Py_None;
113 }
114 if (err == -1 && PyErr_Occurred())
115 return NULL;
116 msg = PyMac_StrError(err);
117 v = Py_BuildValue("(is)", err, msg);
118 PyErr_SetObject(eobj, v);
119 Py_DECREF(v);
120 return NULL;
121}
122
123/* Call PyErr_Mac with PyMac_OSErrException */
124PyObject *
125PyMac_Error(OSErr err)
126{
127 return PyErr_Mac(PyMac_GetOSErrException(), err);
128}
129
Jack Jansen697842f2001-09-10 22:00:39 +0000130
131#if TARGET_API_MAC_OSX
132OSErr
133PyMac_GetFullPathname(FSSpec *fss, char *path, int len)
134{
135 FSRef fsr;
136 OSErr err;
137
138 *path = '\0';
139 err = FSpMakeFSRef(fss, &fsr);
140 if ( err == fnfErr ) {
141 /* FSSpecs can point to non-existing files, fsrefs can't. */
142 FSSpec fss2;
143 int tocopy;
144
145 err = FSMakeFSSpec(fss->vRefNum, fss->parID, "", &fss2);
146 if ( err ) return err;
147 err = FSpMakeFSRef(&fss2, &fsr);
148 if ( err ) return err;
149 err = (OSErr)FSRefMakePath(&fsr, path, len-1);
150 if ( err ) return err;
151 /* This part is not 100% safe: we append the filename part, but
152 ** I'm not sure that we don't run afoul of the various 8bit
153 ** encodings here. Will have to look this up at some point...
154 */
155 strcat(path, "/");
156 tocopy = fss->name[0];
157 if ( strlen(path) + tocopy >= len )
158 tocopy = len - strlen(path) - 1;
159 if ( tocopy > 0 )
160 strncat(path, fss->name+1, tocopy);
161 } else {
162 if ( err ) return err;
163 err = (OSErr)FSRefMakePath(&fsr, path, len);
164 if ( err ) return err;
165 }
166 return 0;
167}
168
169#endif /* TARGET_API_MAC_OSX */
Jack Jansen94bebc02001-08-08 13:17:31 +0000170/* Convert a 4-char string object argument to an OSType value */
171int
172PyMac_GetOSType(PyObject *v, OSType *pr)
173{
174 if (!PyString_Check(v) || PyString_Size(v) != 4) {
175 PyErr_SetString(PyExc_TypeError,
176 "OSType arg must be string of 4 chars");
177 return 0;
178 }
179 memcpy((char *)pr, PyString_AsString(v), 4);
180 return 1;
181}
182
183/* Convert an OSType value to a 4-char string object */
184PyObject *
185PyMac_BuildOSType(OSType t)
186{
187 return PyString_FromStringAndSize((char *)&t, 4);
188}
189
190/* Convert an NumVersion value to a 4-element tuple */
191PyObject *
192PyMac_BuildNumVersion(NumVersion t)
193{
194 return Py_BuildValue("(hhhh)", t.majorRev, t.minorAndBugRev, t.stage, t.nonRelRev);
195}
196
197
198/* Convert a Python string object to a Str255 */
199int
200PyMac_GetStr255(PyObject *v, Str255 pbuf)
201{
202 int len;
203 if (!PyString_Check(v) || (len = PyString_Size(v)) > 255) {
204 PyErr_SetString(PyExc_TypeError,
205 "Str255 arg must be string of at most 255 chars");
206 return 0;
207 }
208 pbuf[0] = len;
209 memcpy((char *)(pbuf+1), PyString_AsString(v), len);
210 return 1;
211}
212
213/* Convert a Str255 to a Python string object */
214PyObject *
215PyMac_BuildStr255(Str255 s)
216{
217 if ( s == NULL ) {
218 PyErr_SetString(PyExc_SystemError, "Str255 pointer is NULL");
219 return NULL;
220 }
221 return PyString_FromStringAndSize((char *)&s[1], (int)s[0]);
222}
223
224PyObject *
225PyMac_BuildOptStr255(Str255 s)
226{
227 if ( s == NULL ) {
228 Py_INCREF(Py_None);
229 return Py_None;
230 }
231 return PyString_FromStringAndSize((char *)&s[1], (int)s[0]);
232}
233
234
235
236/* Convert a Python object to a Rect.
237 The object must be a (left, top, right, bottom) tuple.
238 (This differs from the order in the struct but is consistent with
239 the arguments to SetRect(), and also with STDWIN). */
240int
241PyMac_GetRect(PyObject *v, Rect *r)
242{
243 return PyArg_Parse(v, "(hhhh)", &r->left, &r->top, &r->right, &r->bottom);
244}
245
246/* Convert a Rect to a Python object */
247PyObject *
248PyMac_BuildRect(Rect *r)
249{
250 return Py_BuildValue("(hhhh)", r->left, r->top, r->right, r->bottom);
251}
252
253
254/* Convert a Python object to a Point.
255 The object must be a (h, v) tuple.
256 (This differs from the order in the struct but is consistent with
257 the arguments to SetPoint(), and also with STDWIN). */
258int
259PyMac_GetPoint(PyObject *v, Point *p)
260{
261 return PyArg_Parse(v, "(hh)", &p->h, &p->v);
262}
263
264/* Convert a Point to a Python object */
265PyObject *
266PyMac_BuildPoint(Point p)
267{
268 return Py_BuildValue("(hh)", p.h, p.v);
269}
270
271
272/* Convert a Python object to an EventRecord.
273 The object must be a (what, message, when, (v, h), modifiers) tuple. */
274int
275PyMac_GetEventRecord(PyObject *v, EventRecord *e)
276{
277 return PyArg_Parse(v, "(Hll(hh)H)",
278 &e->what,
279 &e->message,
280 &e->when,
281 &e->where.h,
282 &e->where.v,
283 &e->modifiers);
284}
285
286/* Convert a Rect to an EventRecord object */
287PyObject *
288PyMac_BuildEventRecord(EventRecord *e)
289{
290 return Py_BuildValue("(hll(hh)h)",
291 e->what,
292 e->message,
293 e->when,
294 e->where.h,
295 e->where.v,
296 e->modifiers);
297}
298
299/* Convert Python object to Fixed */
300int
301PyMac_GetFixed(PyObject *v, Fixed *f)
302{
303 double d;
304
305 if( !PyArg_Parse(v, "d", &d))
306 return 0;
307 *f = (Fixed)(d * 0x10000);
308 return 1;
309}
310
Jack Jansen06bd3232001-08-27 14:01:05 +0000311/* Convert a Fixed to a Python object */
Jack Jansen94bebc02001-08-08 13:17:31 +0000312PyObject *
313PyMac_BuildFixed(Fixed f)
314{
315 double d;
316
317 d = f;
318 d = d / 0x10000;
319 return Py_BuildValue("d", d);
320}
321
322/* Convert wide to/from Python int or (hi, lo) tuple. XXXX Should use Python longs */
323int
324PyMac_Getwide(PyObject *v, wide *rv)
325{
326 if (PyInt_Check(v)) {
327 rv->hi = 0;
328 rv->lo = PyInt_AsLong(v);
329 if( rv->lo & 0x80000000 )
330 rv->hi = -1;
331 return 1;
332 }
333 return PyArg_Parse(v, "(ll)", &rv->hi, &rv->lo);
334}
335
336
337PyObject *
338PyMac_Buildwide(wide *w)
339{
340 if ( (w->hi == 0 && (w->lo & 0x80000000) == 0) ||
341 (w->hi == -1 && (w->lo & 0x80000000) ) )
342 return PyInt_FromLong(w->lo);
343 return Py_BuildValue("(ll)", w->hi, w->lo);
344}
345
346#ifdef USE_TOOLBOX_OBJECT_GLUE
347/*
348** Glue together the toolbox objects.
349**
350** Because toolbox modules interdepend on each other, they use each others
351** object types, on MacOSX/MachO this leads to the situation that they
352** cannot be dynamically loaded (or they would all have to be lumped into
353** a single .so, but this would be bad for extensibility).
354**
355** This file defines wrappers for all the _New and _Convert functions,
356** which are the Py_BuildValue and PyArg_ParseTuple helpers. The wrappers
357** check an indirection function pointer, and if it isn't filled in yet
358** they import the appropriate module, whose init routine should fill in
359** the pointer.
360*/
361
362#define GLUE_NEW(object, routinename, module) \
363PyObject *(*PyMacGluePtr_##routinename)(object); \
364\
365PyObject *routinename(object cobj) { \
366 if (!PyMacGluePtr_##routinename) { \
367 if (!PyImport_ImportModule(module)) return NULL; \
368 if (!PyMacGluePtr_##routinename) { \
369 PyErr_SetString(PyExc_ImportError, "Module did not provide routine: " module ": " #routinename); \
370 return NULL; \
371 } \
372 } \
373 return (*PyMacGluePtr_##routinename)(cobj); \
374}
375
376#define GLUE_CONVERT(object, routinename, module) \
377int (*PyMacGluePtr_##routinename)(PyObject *, object *); \
378\
379int routinename(PyObject *pyobj, object *cobj) { \
380 if (!PyMacGluePtr_##routinename) { \
381 if (!PyImport_ImportModule(module)) return NULL; \
382 if (!PyMacGluePtr_##routinename) { \
383 PyErr_SetString(PyExc_ImportError, "Module did not provide routine: " module ": " #routinename); \
384 return NULL; \
385 } \
386 } \
387 return (*PyMacGluePtr_##routinename)(pyobj, cobj); \
388}
Jack Jansenfabd00f2001-09-01 23:39:58 +0000389
390GLUE_NEW(FSSpec *, PyMac_BuildFSSpec, "macfs")
Jack Jansen94bebc02001-08-08 13:17:31 +0000391GLUE_CONVERT(FSSpec, PyMac_GetFSSpec, "macfs")
Jack Jansenfabd00f2001-09-01 23:39:58 +0000392GLUE_NEW(FSRef *, PyMac_BuildFSRef, "macfs")
393GLUE_CONVERT(FSRef, PyMac_GetFSRef, "macfs")
Jack Jansen94bebc02001-08-08 13:17:31 +0000394
Jack Jansen06bd3232001-08-27 14:01:05 +0000395GLUE_NEW(AppleEvent *, AEDesc_New, "Carbon.AE") /* XXXX Why by address? */
396GLUE_CONVERT(AppleEvent, AEDesc_Convert, "Carbon.AE")
Jack Jansen94bebc02001-08-08 13:17:31 +0000397
Jack Jansen06bd3232001-08-27 14:01:05 +0000398GLUE_NEW(Component, CmpObj_New, "Carbon.Cm")
399GLUE_CONVERT(Component, CmpObj_Convert, "Carbon.Cm")
400GLUE_NEW(ComponentInstance, CmpInstObj_New, "Carbon.Cm")
401GLUE_CONVERT(ComponentInstance, CmpInstObj_Convert, "Carbon.Cm")
Jack Jansen94bebc02001-08-08 13:17:31 +0000402
Jack Jansen06bd3232001-08-27 14:01:05 +0000403GLUE_NEW(ControlHandle, CtlObj_New, "Carbon.Ctl")
404GLUE_CONVERT(ControlHandle, CtlObj_Convert, "Carbon.Ctl")
Jack Jansen94bebc02001-08-08 13:17:31 +0000405
Jack Jansen06bd3232001-08-27 14:01:05 +0000406GLUE_NEW(DialogPtr, DlgObj_New, "Carbon.Dlg")
407GLUE_CONVERT(DialogPtr, DlgObj_Convert, "Carbon.Dlg")
408GLUE_NEW(DialogPtr, DlgObj_WhichDialog, "Carbon.Dlg")
Jack Jansen94bebc02001-08-08 13:17:31 +0000409
Jack Jansen06bd3232001-08-27 14:01:05 +0000410GLUE_NEW(DragReference, DragObj_New, "Carbon.Drag")
411GLUE_CONVERT(DragReference, DragObj_Convert, "Carbon.Drag")
Jack Jansen94bebc02001-08-08 13:17:31 +0000412
Jack Jansen06bd3232001-08-27 14:01:05 +0000413GLUE_NEW(ListHandle, ListObj_New, "Carbon.List")
414GLUE_CONVERT(ListHandle, ListObj_Convert, "Carbon.List")
Jack Jansen94bebc02001-08-08 13:17:31 +0000415
Jack Jansen06bd3232001-08-27 14:01:05 +0000416GLUE_NEW(MenuHandle, MenuObj_New, "Carbon.Menu")
417GLUE_CONVERT(MenuHandle, MenuObj_Convert, "Carbon.Menu")
Jack Jansen94bebc02001-08-08 13:17:31 +0000418
Jack Jansen06bd3232001-08-27 14:01:05 +0000419GLUE_NEW(GrafPtr, GrafObj_New, "Carbon.Qd")
420GLUE_CONVERT(GrafPtr, GrafObj_Convert, "Carbon.Qd")
421GLUE_NEW(BitMapPtr, BMObj_New, "Carbon.Qd")
422GLUE_CONVERT(BitMapPtr, BMObj_Convert, "Carbon.Qd")
423GLUE_NEW(RGBColor *, QdRGB_New, "Carbon.Qd") /* XXXX Why? */
424GLUE_CONVERT(RGBColor, QdRGB_Convert, "Carbon.Qd")
Jack Jansen94bebc02001-08-08 13:17:31 +0000425
Jack Jansen06bd3232001-08-27 14:01:05 +0000426GLUE_NEW(GWorldPtr, GWorldObj_New, "Carbon.Qdoffs")
427GLUE_CONVERT(GWorldPtr, GWorldObj_Convert, "Carbon.Qdoffs")
Jack Jansen94bebc02001-08-08 13:17:31 +0000428
Jack Jansen06bd3232001-08-27 14:01:05 +0000429GLUE_NEW(Track, TrackObj_New, "Carbon.Qt")
430GLUE_CONVERT(Track, TrackObj_Convert, "Carbon.Qt")
431GLUE_NEW(Movie, MovieObj_New, "Carbon.Qt")
432GLUE_CONVERT(Movie, MovieObj_Convert, "Carbon.Qt")
433GLUE_NEW(MovieController, MovieCtlObj_New, "Carbon.Qt")
434GLUE_CONVERT(MovieController, MovieCtlObj_Convert, "Carbon.Qt")
435GLUE_NEW(TimeBase, TimeBaseObj_New, "Carbon.Qt")
436GLUE_CONVERT(TimeBase, TimeBaseObj_Convert, "Carbon.Qt")
437GLUE_NEW(UserData, UserDataObj_New, "Carbon.Qt")
438GLUE_CONVERT(UserData, UserDataObj_Convert, "Carbon.Qt")
439GLUE_NEW(Media, MediaObj_New, "Carbon.Qt")
440GLUE_CONVERT(Media, MediaObj_Convert, "Carbon.Qt")
Jack Jansen94bebc02001-08-08 13:17:31 +0000441
Jack Jansen06bd3232001-08-27 14:01:05 +0000442GLUE_NEW(Handle, ResObj_New, "Carbon.Res")
443GLUE_CONVERT(Handle, ResObj_Convert, "Carbon.Res")
444GLUE_NEW(Handle, OptResObj_New, "Carbon.Res")
445GLUE_CONVERT(Handle, OptResObj_Convert, "Carbon.Res")
Jack Jansen94bebc02001-08-08 13:17:31 +0000446
Jack Jansen06bd3232001-08-27 14:01:05 +0000447GLUE_NEW(TEHandle, TEObj_New, "Carbon.TE")
448GLUE_CONVERT(TEHandle, TEObj_Convert, "Carbon.TE")
Jack Jansen94bebc02001-08-08 13:17:31 +0000449
Jack Jansen06bd3232001-08-27 14:01:05 +0000450GLUE_NEW(WindowPtr, WinObj_New, "Carbon.Win")
451GLUE_CONVERT(WindowPtr, WinObj_Convert, "Carbon.Win")
452GLUE_NEW(WindowPtr, WinObj_WhichWindow, "Carbon.Win")
Jack Jansen94bebc02001-08-08 13:17:31 +0000453
454#endif /* USE_TOOLBOX_OBJECT_GLUE */