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