blob: 79b27649818a7c98ae9f83eca0d50c6e04b0b800 [file] [log] [blame]
Guido van Rossum2d167031994-09-16 10:54:21 +00001/***********************************************************
Jack Jansen42218ce1997-01-31 16:15:11 +00002Copyright 1991-1997 by Stichting Mathematisch Centrum, Amsterdam,
Guido van Rossum99546991995-01-08 14:33:34 +00003The Netherlands.
Guido van Rossum2d167031994-09-16 10:54:21 +00004
5 All Rights Reserved
6
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00007Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
Guido van Rossum2d167031994-09-16 10:54:21 +00009provided that the above copyright notice appear in all copies and that
Antoine Pitrouc7c96a92010-05-09 15:15:40 +000010both that copyright notice and this permission notice appear in
Guido van Rossum2d167031994-09-16 10:54:21 +000011supporting 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/* Macintosh OS-specific interface */
26
27#include "Python.h"
Jack Jansen7107c1a2003-11-20 13:31:00 +000028#include "pymactoolbox.h"
Guido van Rossum2d167031994-09-16 10:54:21 +000029
Jack Jansen6143d532001-05-19 12:34:59 +000030#include <Carbon/Carbon.h>
Jack Jansend7c17232003-02-21 16:31:11 +000031#include <ApplicationServices/ApplicationServices.h>
Jack Jansenee23d6e1995-01-27 14:43:25 +000032
Ronald Oussorenaa8efbf2008-08-12 12:41:45 +000033#ifndef HAVE_OSX105_SDK
Antoine Pitrouc7c96a92010-05-09 15:15:40 +000034typedef SInt16 FSIORefNum;
Ronald Oussoren0d236eb2008-06-06 21:31:33 +000035#endif
Ronald Oussoren5640ce22008-06-05 12:58:24 +000036
Guido van Rossum2d167031994-09-16 10:54:21 +000037static PyObject *MacOS_Error; /* Exception MacOS.Error */
38
Jack Jansen697842f2001-09-10 22:00:39 +000039#define PATHNAMELEN 1024
Jack Jansen697842f2001-09-10 22:00:39 +000040
Jack Jansen76a05891996-02-29 16:11:32 +000041/* ----------------------------------------------------- */
42
43/* Declarations for objects of type Resource fork */
44
45typedef struct {
Antoine Pitrouc7c96a92010-05-09 15:15:40 +000046 PyObject_HEAD
47 FSIORefNum fRefNum;
48 int isclosed;
Jack Jansen76a05891996-02-29 16:11:32 +000049} rfobject;
50
Jeremy Hylton938ace62002-07-17 16:30:39 +000051static PyTypeObject Rftype;
Jack Jansen76a05891996-02-29 16:11:32 +000052
53
54
55/* ---------------------------------------------------------------- */
56
57static void
Jack Jansendeefbe52001-08-08 13:46:49 +000058do_close(rfobject *self)
Jack Jansen76a05891996-02-29 16:11:32 +000059{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +000060 if (self->isclosed ) return;
61 (void)FSCloseFork(self->fRefNum);
62 self->isclosed = 1;
Jack Jansen76a05891996-02-29 16:11:32 +000063}
64
Antoine Pitrouc7c96a92010-05-09 15:15:40 +000065static char rf_read__doc__[] =
Jack Jansen76a05891996-02-29 16:11:32 +000066"Read data from resource fork"
67;
68
69static PyObject *
Jack Jansendeefbe52001-08-08 13:46:49 +000070rf_read(rfobject *self, PyObject *args)
Jack Jansen76a05891996-02-29 16:11:32 +000071{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +000072 long n;
73 PyObject *v;
74 OSErr err;
75 ByteCount n2;
76
77 if (self->isclosed) {
78 PyErr_SetString(PyExc_ValueError, "Operation on closed file");
79 return NULL;
80 }
81
82 if (!PyArg_ParseTuple(args, "l", &n))
83 return NULL;
84
85 v = PyBytes_FromStringAndSize((char *)NULL, n);
86 if (v == NULL)
87 return NULL;
88
89 err = FSReadFork(self->fRefNum, fsAtMark, 0, n, PyString_AsString(v), &n2);
90 if (err && err != eofErr) {
91 PyMac_Error(err);
92 Py_DECREF(v);
93 return NULL;
94 }
95 _PyString_Resize(&v, n2);
96 return v;
Jack Jansen76a05891996-02-29 16:11:32 +000097}
98
99
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000100static char rf_write__doc__[] =
Jack Jansen76a05891996-02-29 16:11:32 +0000101"Write to resource fork"
102;
103
104static PyObject *
Jack Jansendeefbe52001-08-08 13:46:49 +0000105rf_write(rfobject *self, PyObject *args)
Jack Jansen76a05891996-02-29 16:11:32 +0000106{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000107 char *buffer;
108 long size;
109 OSErr err;
110
111 if (self->isclosed) {
112 PyErr_SetString(PyExc_ValueError, "Operation on closed file");
113 return NULL;
114 }
115 if (!PyArg_ParseTuple(args, "s#", &buffer, &size))
116 return NULL;
117 err = FSWriteFork(self->fRefNum, fsAtMark, 0, size, buffer, NULL);
118 if (err) {
119 PyMac_Error(err);
120 return NULL;
121 }
122 Py_INCREF(Py_None);
123 return Py_None;
Jack Jansen76a05891996-02-29 16:11:32 +0000124}
125
126
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000127static char rf_seek__doc__[] =
Jack Jansen76a05891996-02-29 16:11:32 +0000128"Set file position"
129;
130
131static PyObject *
Jack Jansendeefbe52001-08-08 13:46:49 +0000132rf_seek(rfobject *self, PyObject *args)
Jack Jansen76a05891996-02-29 16:11:32 +0000133{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000134 long amount;
135 int whence = SEEK_SET;
136 int mode;
137 OSErr err;
Ronald Oussoren5640ce22008-06-05 12:58:24 +0000138
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000139 if (self->isclosed) {
140 PyErr_SetString(PyExc_ValueError, "Operation on closed file");
141 return NULL;
142 }
143 if (!PyArg_ParseTuple(args, "l|i", &amount, &whence)) {
144 return NULL;
145 }
146
147 switch (whence) {
148 case SEEK_CUR:
149 mode = fsFromMark;
150 break;
151 case SEEK_END:
152 mode = fsFromLEOF;
153 break;
154 case SEEK_SET:
155 mode = fsFromStart;
156 break;
157 default:
158 PyErr_BadArgument();
159 return NULL;
160 }
161
162 err = FSSetForkPosition(self->fRefNum, mode, amount);
163 if (err != noErr) {
164 PyMac_Error(err);
165 return NULL;
166 }
167 Py_INCREF(Py_None);
168 return Py_None;
Jack Jansen76a05891996-02-29 16:11:32 +0000169}
170
171
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000172static char rf_tell__doc__[] =
Jack Jansen76a05891996-02-29 16:11:32 +0000173"Get file position"
174;
175
176static PyObject *
Jack Jansendeefbe52001-08-08 13:46:49 +0000177rf_tell(rfobject *self, PyObject *args)
Jack Jansen76a05891996-02-29 16:11:32 +0000178{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000179 long long where;
180 OSErr err;
Ronald Oussoren5640ce22008-06-05 12:58:24 +0000181
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000182 if (self->isclosed) {
183 PyErr_SetString(PyExc_ValueError, "Operation on closed file");
184 return NULL;
185 }
186 if (!PyArg_ParseTuple(args, ""))
187 return NULL;
188
189 err = FSGetForkPosition(self->fRefNum, &where);
190 if (err != noErr) {
191 PyMac_Error(err);
192 return NULL;
193 }
194 return PyLong_FromLongLong(where);
Jack Jansen76a05891996-02-29 16:11:32 +0000195}
196
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000197static char rf_close__doc__[] =
Jack Jansen76a05891996-02-29 16:11:32 +0000198"Close resource fork"
199;
200
201static PyObject *
Jack Jansendeefbe52001-08-08 13:46:49 +0000202rf_close(rfobject *self, PyObject *args)
Jack Jansen76a05891996-02-29 16:11:32 +0000203{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000204 if (!PyArg_ParseTuple(args, ""))
205 return NULL;
206 do_close(self);
207 Py_INCREF(Py_None);
208 return Py_None;
Jack Jansen76a05891996-02-29 16:11:32 +0000209}
210
211
212static struct PyMethodDef rf_methods[] = {
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000213 {"read", (PyCFunction)rf_read, 1, rf_read__doc__},
214 {"write", (PyCFunction)rf_write, 1, rf_write__doc__},
215 {"seek", (PyCFunction)rf_seek, 1, rf_seek__doc__},
216 {"tell", (PyCFunction)rf_tell, 1, rf_tell__doc__},
217 {"close", (PyCFunction)rf_close, 1, rf_close__doc__},
218
219 {NULL, NULL} /* sentinel */
Jack Jansen76a05891996-02-29 16:11:32 +0000220};
221
222/* ---------- */
223
224
225static rfobject *
Jack Jansendeefbe52001-08-08 13:46:49 +0000226newrfobject(void)
Jack Jansen76a05891996-02-29 16:11:32 +0000227{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000228 rfobject *self;
229
230 self = PyObject_NEW(rfobject, &Rftype);
231 if (self == NULL)
232 return NULL;
233 self->isclosed = 1;
234 return self;
Jack Jansen76a05891996-02-29 16:11:32 +0000235}
236
237
238static void
Jack Jansendeefbe52001-08-08 13:46:49 +0000239rf_dealloc(rfobject *self)
Jack Jansen76a05891996-02-29 16:11:32 +0000240{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000241 do_close(self);
242 PyObject_DEL(self);
Jack Jansen76a05891996-02-29 16:11:32 +0000243}
244
245static PyObject *
Jack Jansendeefbe52001-08-08 13:46:49 +0000246rf_getattr(rfobject *self, char *name)
Jack Jansen76a05891996-02-29 16:11:32 +0000247{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000248 return Py_FindMethod(rf_methods, (PyObject *)self, name);
Jack Jansen76a05891996-02-29 16:11:32 +0000249}
250
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000251static char Rftype__doc__[] =
Jack Jansen76a05891996-02-29 16:11:32 +0000252"Resource fork file object"
253;
254
255static PyTypeObject Rftype = {
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000256 PyObject_HEAD_INIT(&PyType_Type)
257 0, /*ob_size*/
258 "MacOS.ResourceFork", /*tp_name*/
259 sizeof(rfobject), /*tp_basicsize*/
260 0, /*tp_itemsize*/
261 /* methods */
262 (destructor)rf_dealloc, /*tp_dealloc*/
263 (printfunc)0, /*tp_print*/
264 (getattrfunc)rf_getattr, /*tp_getattr*/
265 (setattrfunc)0, /*tp_setattr*/
266 (cmpfunc)0, /*tp_compare*/
267 (reprfunc)0, /*tp_repr*/
268 0, /*tp_as_number*/
269 0, /*tp_as_sequence*/
270 0, /*tp_as_mapping*/
271 (hashfunc)0, /*tp_hash*/
272 (ternaryfunc)0, /*tp_call*/
273 (reprfunc)0, /*tp_str*/
Jack Jansen76a05891996-02-29 16:11:32 +0000274
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000275 /* Space for future expansion */
276 0L,0L,0L,0L,
277 Rftype__doc__ /* Documentation string */
Jack Jansen76a05891996-02-29 16:11:32 +0000278};
279
Ronald Oussoren5640ce22008-06-05 12:58:24 +0000280
Jack Jansen76a05891996-02-29 16:11:32 +0000281/* End of code for Resource fork objects */
282/* -------------------------------------------------------- */
Guido van Rossum2d167031994-09-16 10:54:21 +0000283
284/*----------------------------------------------------------------------*/
Guido van Rossume791c2e1995-01-09 13:20:04 +0000285/* Miscellaneous File System Operations */
286
Jack Jansenfe94e972003-03-19 22:51:42 +0000287static char getcrtp_doc[] = "Get MacOS 4-char creator and type for a file";
Jack Jansen120a1051997-06-03 15:29:41 +0000288
Guido van Rossume791c2e1995-01-09 13:20:04 +0000289static PyObject *
Guido van Rossumb7e79e51995-01-22 18:42:12 +0000290MacOS_GetCreatorAndType(PyObject *self, PyObject *args)
Guido van Rossume791c2e1995-01-09 13:20:04 +0000291{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000292 PyObject *creator, *type, *res;
293 OSErr err;
294 FSRef ref;
295 FSCatalogInfo cataloginfo;
296 FileInfo* finfo;
Ronald Oussoren5640ce22008-06-05 12:58:24 +0000297
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000298 if (!PyArg_ParseTuple(args, "O&", PyMac_GetFSRef, &ref)) {
Ronald Oussoren5640ce22008-06-05 12:58:24 +0000299#ifndef __LP64__
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000300 /* This function is documented to take an FSSpec as well,
301 * which only works in 32-bit mode.
302 */
303 PyErr_Clear();
304 FSSpec fss;
305 FInfo info;
Ronald Oussoren5640ce22008-06-05 12:58:24 +0000306
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000307 if (!PyArg_ParseTuple(args, "O&", PyMac_GetFSSpec, &fss))
308 return NULL;
Ronald Oussoren5640ce22008-06-05 12:58:24 +0000309
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000310 if ((err = FSpGetFInfo(&fss, &info)) != noErr) {
311 return PyErr_Mac(MacOS_Error, err);
312 }
313 creator = PyString_FromStringAndSize(
314 (char *)&info.fdCreator, 4);
315 type = PyString_FromStringAndSize((char *)&info.fdType, 4);
316 res = Py_BuildValue("OO", creator, type);
317 Py_DECREF(creator);
318 Py_DECREF(type);
319 return res;
320#else /* __LP64__ */
321 return NULL;
322#endif /* __LP64__ */
323 }
Ronald Oussoren5640ce22008-06-05 12:58:24 +0000324
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000325 err = FSGetCatalogInfo(&ref,
326 kFSCatInfoFinderInfo|kFSCatInfoNodeFlags, &cataloginfo,
327 NULL, NULL, NULL);
328 if (err != noErr) {
329 PyErr_Mac(MacOS_Error, err);
330 return NULL;
331 }
Ronald Oussoren5640ce22008-06-05 12:58:24 +0000332
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000333 if ((cataloginfo.nodeFlags & kFSNodeIsDirectoryMask) != 0) {
334 /* Directory: doesn't have type/creator info.
335 *
336 * The specific error code is for backward compatibility with
337 * earlier versions.
338 */
339 PyErr_Mac(MacOS_Error, fnfErr);
340 return NULL;
Ronald Oussoren5640ce22008-06-05 12:58:24 +0000341
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000342 }
343 finfo = (FileInfo*)&(cataloginfo.finderInfo);
344 creator = PyString_FromStringAndSize((char*)&(finfo->fileCreator), 4);
345 type = PyString_FromStringAndSize((char*)&(finfo->fileType), 4);
Ronald Oussoren5640ce22008-06-05 12:58:24 +0000346
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000347 res = Py_BuildValue("OO", creator, type);
348 Py_DECREF(creator);
349 Py_DECREF(type);
350 return res;
Guido van Rossume791c2e1995-01-09 13:20:04 +0000351}
352
Jack Jansenfe94e972003-03-19 22:51:42 +0000353static char setcrtp_doc[] = "Set MacOS 4-char creator and type for a file";
Jack Jansen120a1051997-06-03 15:29:41 +0000354
Guido van Rossume791c2e1995-01-09 13:20:04 +0000355static PyObject *
Guido van Rossumb7e79e51995-01-22 18:42:12 +0000356MacOS_SetCreatorAndType(PyObject *self, PyObject *args)
Guido van Rossume791c2e1995-01-09 13:20:04 +0000357{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000358 ResType creator, type;
359 FSRef ref;
360 FileInfo* finfo;
361 OSErr err;
362 FSCatalogInfo cataloginfo;
Ronald Oussoren5640ce22008-06-05 12:58:24 +0000363
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000364 if (!PyArg_ParseTuple(args, "O&O&O&",
365 PyMac_GetFSRef, &ref, PyMac_GetOSType, &creator, PyMac_GetOSType, &type)) {
Ronald Oussoren5640ce22008-06-05 12:58:24 +0000366#ifndef __LP64__
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000367 /* Try to handle FSSpec arguments, for backward compatibility */
368 FSSpec fss;
369 FInfo info;
Ronald Oussoren5640ce22008-06-05 12:58:24 +0000370
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000371 if (!PyArg_ParseTuple(args, "O&O&O&",
372 PyMac_GetFSSpec, &fss, PyMac_GetOSType, &creator, PyMac_GetOSType, &type))
373 return NULL;
Ronald Oussoren5640ce22008-06-05 12:58:24 +0000374
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000375 if ((err = FSpGetFInfo(&fss, &info)) != noErr)
376 return PyErr_Mac(MacOS_Error, err);
Ronald Oussoren5640ce22008-06-05 12:58:24 +0000377
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000378 info.fdCreator = creator;
379 info.fdType = type;
Ronald Oussoren5640ce22008-06-05 12:58:24 +0000380
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000381 if ((err = FSpSetFInfo(&fss, &info)) != noErr)
382 return PyErr_Mac(MacOS_Error, err);
383 Py_INCREF(Py_None);
384 return Py_None;
Ronald Oussoren5640ce22008-06-05 12:58:24 +0000385#else /* __LP64__ */
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000386 return NULL;
Ronald Oussoren5640ce22008-06-05 12:58:24 +0000387#endif /* __LP64__ */
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000388 }
Ronald Oussoren5640ce22008-06-05 12:58:24 +0000389
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000390 err = FSGetCatalogInfo(&ref,
391 kFSCatInfoFinderInfo|kFSCatInfoNodeFlags, &cataloginfo,
392 NULL, NULL, NULL);
393 if (err != noErr) {
394 PyErr_Mac(MacOS_Error, err);
395 return NULL;
396 }
Ronald Oussoren5640ce22008-06-05 12:58:24 +0000397
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000398 if ((cataloginfo.nodeFlags & kFSNodeIsDirectoryMask) != 0) {
399 /* Directory: doesn't have type/creator info.
400 *
401 * The specific error code is for backward compatibility with
402 * earlier versions.
403 */
404 PyErr_Mac(MacOS_Error, fnfErr);
405 return NULL;
Ronald Oussoren5640ce22008-06-05 12:58:24 +0000406
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000407 }
408 finfo = (FileInfo*)&(cataloginfo.finderInfo);
409 finfo->fileCreator = creator;
410 finfo->fileType = type;
Ronald Oussoren5640ce22008-06-05 12:58:24 +0000411
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000412 err = FSSetCatalogInfo(&ref, kFSCatInfoFinderInfo, &cataloginfo);
413 if (err != noErr) {
414 PyErr_Mac(MacOS_Error, fnfErr);
415 return NULL;
416 }
417
418 Py_INCREF(Py_None);
419 return Py_None;
Guido van Rossume791c2e1995-01-09 13:20:04 +0000420}
421
Jack Jansena76382a1995-02-02 14:25:56 +0000422
Jack Jansen120a1051997-06-03 15:29:41 +0000423static char geterr_doc[] = "Convert OSErr number to string";
424
Jack Jansen829f88c1995-07-17 11:36:01 +0000425static PyObject *
426MacOS_GetErrorString(PyObject *self, PyObject *args)
427{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000428 int err;
429 char buf[256];
430 Handle h;
431 char *str;
432 static int errors_loaded;
Raymond Hettingerec6eb362004-11-05 07:02:59 +0000433
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000434 if (!PyArg_ParseTuple(args, "i", &err))
435 return NULL;
Raymond Hettingerec6eb362004-11-05 07:02:59 +0000436
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000437 h = GetResource('Estr', err);
438 if (!h && !errors_loaded) {
439 /*
440 ** Attempt to open the resource file containing the
441 ** Estr resources. We ignore all errors. We also try
442 ** this only once.
443 */
444 PyObject *m, *rv;
445 errors_loaded = 1;
446
447 m = PyImport_ImportModuleNoBlock("macresource");
448 if (!m) {
449 if (Py_VerboseFlag)
450 PyErr_Print();
451 PyErr_Clear();
452 }
453 else {
454 rv = PyObject_CallMethod(m, "open_error_resource", "");
455 if (!rv) {
456 if (Py_VerboseFlag)
457 PyErr_Print();
458 PyErr_Clear();
459 }
460 else {
461 Py_DECREF(rv);
462 /* And try again... */
463 h = GetResource('Estr', err);
464 }
465 Py_DECREF(m);
466 }
467 }
468 /*
469 ** Whether the code above succeeded or not, we won't try
470 ** again.
471 */
472 errors_loaded = 1;
473
474 if (h) {
475 HLock(h);
476 str = (char *)*h;
477 memcpy(buf, str+1, (unsigned char)str[0]);
478 buf[(unsigned char)str[0]] = '\0';
479 HUnlock(h);
480 ReleaseResource(h);
481 }
482 else {
483 PyOS_snprintf(buf, sizeof(buf), "Mac OS error code %d", err);
484 }
485
486 return Py_BuildValue("s", buf);
Jack Jansen829f88c1995-07-17 11:36:01 +0000487}
488
Ronald Oussoren5640ce22008-06-05 12:58:24 +0000489
490#ifndef __LP64__
491
Jack Jansenab7fcdd1996-05-20 11:32:00 +0000492static char splash_doc[] = "Open a splash-screen dialog by resource-id (0=close)";
493
494static PyObject *
495MacOS_splash(PyObject *self, PyObject *args)
496{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000497 int resid = -1;
498 static DialogPtr curdialog = NULL;
499 DialogPtr olddialog;
500 WindowRef theWindow;
501 CGrafPtr thePort;
Jack Jansene79dc762000-06-02 21:35:07 +0000502#if 0
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000503 short xpos, ypos, width, height, swidth, sheight;
Jack Jansene79dc762000-06-02 21:35:07 +0000504#endif
Ronald Oussoren5640ce22008-06-05 12:58:24 +0000505
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000506 if (!PyArg_ParseTuple(args, "|i", &resid))
507 return NULL;
508 olddialog = curdialog;
509 curdialog = NULL;
510
511 if ( resid != -1 ) {
512 curdialog = GetNewDialog(resid, NULL, (WindowPtr)-1);
513 if ( curdialog ) {
514 theWindow = GetDialogWindow(curdialog);
515 thePort = GetWindowPort(theWindow);
Jack Jansene79dc762000-06-02 21:35:07 +0000516#if 0
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000517 width = thePort->portRect.right - thePort->portRect.left;
518 height = thePort->portRect.bottom - thePort->portRect.top;
519 swidth = qd.screenBits.bounds.right - qd.screenBits.bounds.left;
520 sheight = qd.screenBits.bounds.bottom - qd.screenBits.bounds.top - LMGetMBarHeight();
521 xpos = (swidth-width)/2;
522 ypos = (sheight-height)/5 + LMGetMBarHeight();
523 MoveWindow(theWindow, xpos, ypos, 0);
524 ShowWindow(theWindow);
Jack Jansene79dc762000-06-02 21:35:07 +0000525#endif
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000526 DrawDialog(curdialog);
527 }
528 }
529 if (olddialog)
530 DisposeDialog(olddialog);
531 Py_INCREF(Py_None);
532 return Py_None;
Jack Jansenab7fcdd1996-05-20 11:32:00 +0000533}
534
Jack Janseneb76b841996-09-30 14:43:22 +0000535static char DebugStr_doc[] = "Switch to low-level debugger with a message";
536
537static PyObject *
538MacOS_DebugStr(PyObject *self, PyObject *args)
539{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000540 Str255 message;
541 PyObject *object = 0;
542
543 if (!PyArg_ParseTuple(args, "O&|O", PyMac_GetStr255, message, &object))
544 return NULL;
545
546 DebugStr(message);
547 Py_INCREF(Py_None);
548 return Py_None;
Jack Janseneb76b841996-09-30 14:43:22 +0000549}
Jack Jansenab7fcdd1996-05-20 11:32:00 +0000550
Ronald Oussoren5640ce22008-06-05 12:58:24 +0000551
Jack Jansen2e871e41997-09-08 13:23:19 +0000552static char SysBeep_doc[] = "BEEEEEP!!!";
553
554static PyObject *
555MacOS_SysBeep(PyObject *self, PyObject *args)
556{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000557 int duration = 6;
558
559 if (!PyArg_ParseTuple(args, "|i", &duration))
560 return NULL;
561 SysBeep(duration);
562 Py_INCREF(Py_None);
563 return Py_None;
Jack Jansen2e871e41997-09-08 13:23:19 +0000564}
565
Ronald Oussoren5640ce22008-06-05 12:58:24 +0000566#endif /* __LP64__ */
567
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000568static char WMAvailable_doc[] =
569 "True if this process can interact with the display."
570 "Will foreground the application on the first call as a side-effect."
571 ;
Jack Jansend7c17232003-02-21 16:31:11 +0000572
573static PyObject *
574MacOS_WMAvailable(PyObject *self, PyObject *args)
575{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000576 static PyObject *rv = NULL;
577
578 if (!PyArg_ParseTuple(args, ""))
579 return NULL;
580 if (!rv) {
581 ProcessSerialNumber psn;
582
583 /*
584 ** This is a fairly innocuous call to make if we don't have a window
585 ** manager, or if we have no permission to talk to it. It will print
586 ** a message on stderr, but at least it won't abort the process.
587 ** It appears the function caches the result itself, and it's cheap, so
588 ** no need for us to cache.
589 */
Jack Jansen43285d42004-06-02 13:44:05 +0000590#ifdef kCGNullDirectDisplay
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000591 /* On 10.1 CGMainDisplayID() isn't available, and
592 ** kCGNullDirectDisplay isn't defined.
593 */
594 if (CGMainDisplayID() == 0) {
595 rv = Py_False;
596 } else {
Jack Jansen43285d42004-06-02 13:44:05 +0000597#else
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000598 {
Jack Jansen43285d42004-06-02 13:44:05 +0000599#endif
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000600 if (GetCurrentProcess(&psn) < 0 ||
601 SetFrontProcess(&psn) < 0) {
602 rv = Py_False;
603 } else {
604 rv = Py_True;
605 }
606 }
607 }
608 Py_INCREF(rv);
609 return rv;
Jack Jansend7c17232003-02-21 16:31:11 +0000610}
611
Jack Jansen898ac1b1997-09-01 15:38:12 +0000612static char GetTicks_doc[] = "Return number of ticks since bootup";
613
614static PyObject *
615MacOS_GetTicks(PyObject *self, PyObject *args)
616{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000617 return Py_BuildValue("i", (int)TickCount());
Jack Jansen898ac1b1997-09-01 15:38:12 +0000618}
619
Jack Jansen76a05891996-02-29 16:11:32 +0000620static char openrf_doc[] = "Open resource fork of a file";
621
622static PyObject *
623MacOS_openrf(PyObject *self, PyObject *args)
624{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000625 OSErr err;
626 char *mode = "r";
627 FSRef ref;
628 SInt8 permission = fsRdPerm;
629 rfobject *fp;
630 HFSUniStr255 name;
Ronald Oussoren5640ce22008-06-05 12:58:24 +0000631
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000632 if (!PyArg_ParseTuple(args, "O&|s", PyMac_GetFSRef, &ref, &mode))
633 return NULL;
634 while (*mode) {
635 switch (*mode++) {
636 case '*': break;
637 case 'r': permission = fsRdPerm; break;
638 case 'w': permission = fsWrPerm; break;
639 case 'b': break;
640 default:
641 PyErr_BadArgument();
642 return NULL;
643 }
644 }
Ronald Oussoren5640ce22008-06-05 12:58:24 +0000645
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000646 err = FSGetResourceForkName(&name);
647 if (err != noErr) {
648 PyMac_Error(err);
649 return NULL;
650 }
651
652 if ( (fp = newrfobject()) == NULL )
653 return NULL;
654
655
656 err = FSOpenFork(&ref, name.length, name.unicode, permission, &fp->fRefNum);
657 if (err != noErr) {
658 Py_DECREF(fp);
659 PyMac_Error(err);
660 return NULL;
661 }
662 fp->isclosed = 0;
663 return (PyObject *)fp;
Jack Jansen76a05891996-02-29 16:11:32 +0000664}
665
Jack Jansen8413b472000-10-19 22:02:16 +0000666
Ronald Oussoren5640ce22008-06-05 12:58:24 +0000667
Guido van Rossum2d167031994-09-16 10:54:21 +0000668static PyMethodDef MacOS_Methods[] = {
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000669 {"GetCreatorAndType", MacOS_GetCreatorAndType, 1, getcrtp_doc},
670 {"SetCreatorAndType", MacOS_SetCreatorAndType, 1, setcrtp_doc},
671 {"GetErrorString", MacOS_GetErrorString, 1, geterr_doc},
672 {"openrf", MacOS_openrf, 1, openrf_doc},
Ronald Oussoren5640ce22008-06-05 12:58:24 +0000673#ifndef __LP64__
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000674 {"splash", MacOS_splash, 1, splash_doc},
675 {"DebugStr", MacOS_DebugStr, 1, DebugStr_doc},
676 {"SysBeep", MacOS_SysBeep, 1, SysBeep_doc},
Ronald Oussoren5640ce22008-06-05 12:58:24 +0000677#endif /* __LP64__ */
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000678 {"GetTicks", MacOS_GetTicks, 1, GetTicks_doc},
679 {"WMAvailable", MacOS_WMAvailable, 1, WMAvailable_doc},
680 {NULL, NULL} /* Sentinel */
Guido van Rossum2d167031994-09-16 10:54:21 +0000681};
682
683
684void
Jack Jansendeefbe52001-08-08 13:46:49 +0000685initMacOS(void)
Guido van Rossum2d167031994-09-16 10:54:21 +0000686{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000687 PyObject *m, *d;
688
689 if (PyErr_WarnPy3k("In 3.x, MacOS is removed.", 1))
690 return;
691
692 m = Py_InitModule("MacOS", MacOS_Methods);
693 d = PyModule_GetDict(m);
694
695 /* Initialize MacOS.Error exception */
696 MacOS_Error = PyMac_GetOSErrException();
697 if (MacOS_Error == NULL || PyDict_SetItemString(d, "Error", MacOS_Error) != 0)
698 return;
699 Rftype.ob_type = &PyType_Type;
700 Py_INCREF(&Rftype);
701 if (PyDict_SetItemString(d, "ResourceForkType", (PyObject *)&Rftype) != 0)
702 return;
703 /*
704 ** This is a hack: the following constant added to the id() of a string
705 ** object gives you the address of the data. Unfortunately, it is needed for
706 ** some of the image and sound processing interfaces on the mac:-(
707 */
708 {
709 PyStringObject *p = 0;
710 long off = (long)&(p->ob_sval[0]);
711
712 if( PyDict_SetItemString(d, "string_id_to_buffer", Py_BuildValue("i", off)) != 0)
713 return;
714 }
Jack Jansenf3163302001-05-19 12:50:05 +0000715#define PY_RUNTIMEMODEL "macho"
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000716 if (PyDict_SetItemString(d, "runtimemodel",
717 Py_BuildValue("s", PY_RUNTIMEMODEL)) != 0)
718 return;
Jack Jansena53f4eb2003-11-19 16:34:04 +0000719#if defined(WITH_NEXT_FRAMEWORK)
Jack Jansen8cd9a4f2003-02-23 23:23:47 +0000720#define PY_LINKMODEL "framework"
721#elif defined(Py_ENABLE_SHARED)
722#define PY_LINKMODEL "shared"
723#else
724#define PY_LINKMODEL "static"
725#endif
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000726 if (PyDict_SetItemString(d, "linkmodel",
727 Py_BuildValue("s", PY_LINKMODEL)) != 0)
728 return;
Jack Jansen8cd9a4f2003-02-23 23:23:47 +0000729
Guido van Rossum2d167031994-09-16 10:54:21 +0000730}