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 ******************************************************************/
25 /* Macintosh OS-specific interface */
28 #include "pymactoolbox.h"
30 #include <Carbon/Carbon.h>
31 #include <ApplicationServices/ApplicationServices.h>
33 #include <arpa/inet.h> /* for ntohl, htonl */
36 #ifndef HAVE_OSX105_SDK
37 typedef SInt16 FSIORefNum
;
40 static PyObject
*MacOS_Error
; /* Exception MacOS.Error */
42 #define PATHNAMELEN 1024
44 /* ----------------------------------------------------- */
46 /* Declarations for objects of type Resource fork */
54 static PyTypeObject Rftype
;
58 /* ---------------------------------------------------------------- */
61 do_close(rfobject
*self
)
63 if (self
->isclosed
) return;
64 (void)FSCloseFork(self
->fRefNum
);
68 static char rf_read__doc__
[] =
69 "Read data from resource fork"
73 rf_read(rfobject
*self
, PyObject
*args
)
81 PyErr_SetString(PyExc_ValueError
, "Operation on closed file");
85 if (!PyArg_ParseTuple(args
, "l", &n
))
88 v
= PyBytes_FromStringAndSize((char *)NULL
, n
);
92 err
= FSReadFork(self
->fRefNum
, fsAtMark
, 0, n
, PyString_AsString(v
), &n2
);
93 if (err
&& err
!= eofErr
) {
98 _PyString_Resize(&v
, n2
);
103 static char rf_write__doc__
[] =
104 "Write to resource fork"
108 rf_write(rfobject
*self
, PyObject
*args
)
114 if (self
->isclosed
) {
115 PyErr_SetString(PyExc_ValueError
, "Operation on closed file");
118 if (!PyArg_ParseTuple(args
, "s#", &buffer
, &size
))
120 err
= FSWriteFork(self
->fRefNum
, fsAtMark
, 0, size
, buffer
, NULL
);
130 static char rf_seek__doc__
[] =
135 rf_seek(rfobject
*self
, PyObject
*args
)
138 int whence
= SEEK_SET
;
142 if (self
->isclosed
) {
143 PyErr_SetString(PyExc_ValueError
, "Operation on closed file");
146 if (!PyArg_ParseTuple(args
, "l|i", &amount
, &whence
)) {
165 err
= FSSetForkPosition(self
->fRefNum
, mode
, amount
);
175 static char rf_tell__doc__
[] =
180 rf_tell(rfobject
*self
, PyObject
*args
)
185 if (self
->isclosed
) {
186 PyErr_SetString(PyExc_ValueError
, "Operation on closed file");
189 if (!PyArg_ParseTuple(args
, ""))
192 err
= FSGetForkPosition(self
->fRefNum
, &where
);
197 return PyLong_FromLongLong(where
);
200 static char rf_close__doc__
[] =
201 "Close resource fork"
205 rf_close(rfobject
*self
, PyObject
*args
)
207 if (!PyArg_ParseTuple(args
, ""))
215 static struct PyMethodDef rf_methods
[] = {
216 {"read", (PyCFunction
)rf_read
, 1, rf_read__doc__
},
217 {"write", (PyCFunction
)rf_write
, 1, rf_write__doc__
},
218 {"seek", (PyCFunction
)rf_seek
, 1, rf_seek__doc__
},
219 {"tell", (PyCFunction
)rf_tell
, 1, rf_tell__doc__
},
220 {"close", (PyCFunction
)rf_close
, 1, rf_close__doc__
},
222 {NULL
, NULL
} /* sentinel */
233 self
= PyObject_NEW(rfobject
, &Rftype
);
242 rf_dealloc(rfobject
*self
)
249 rf_getattr(rfobject
*self
, char *name
)
251 return Py_FindMethod(rf_methods
, (PyObject
*)self
, name
);
254 static char Rftype__doc__
[] =
255 "Resource fork file object"
258 static PyTypeObject Rftype
= {
259 PyObject_HEAD_INIT(&PyType_Type
)
261 "MacOS.ResourceFork", /*tp_name*/
262 sizeof(rfobject
), /*tp_basicsize*/
265 (destructor
)rf_dealloc
, /*tp_dealloc*/
266 (printfunc
)0, /*tp_print*/
267 (getattrfunc
)rf_getattr
, /*tp_getattr*/
268 (setattrfunc
)0, /*tp_setattr*/
269 (cmpfunc
)0, /*tp_compare*/
270 (reprfunc
)0, /*tp_repr*/
272 0, /*tp_as_sequence*/
274 (hashfunc
)0, /*tp_hash*/
275 (ternaryfunc
)0, /*tp_call*/
276 (reprfunc
)0, /*tp_str*/
278 /* Space for future expansion */
280 Rftype__doc__
/* Documentation string */
284 /* End of code for Resource fork objects */
285 /* -------------------------------------------------------- */
287 /*----------------------------------------------------------------------*/
288 /* Miscellaneous File System Operations */
290 static char getcrtp_doc
[] = "Get MacOS 4-char creator and type for a file";
293 MacOS_GetCreatorAndType(PyObject
*self
, PyObject
*args
)
295 PyObject
*creator
, *type
, *res
;
298 FSCatalogInfo cataloginfo
;
301 if (!PyArg_ParseTuple(args
, "O&", PyMac_GetFSRef
, &ref
)) {
303 /* This function is documented to take an FSSpec as well,
304 * which only works in 32-bit mode.
310 if (!PyArg_ParseTuple(args
, "O&", PyMac_GetFSSpec
, &fss
))
313 if ((err
= FSpGetFInfo(&fss
, &info
)) != noErr
) {
314 return PyErr_Mac(MacOS_Error
, err
);
317 info
.fdCreator
= ntohl(info
.fdCreator
);
318 info
.fdType
= ntohl(info
.fdType
);
320 creator
= PyString_FromStringAndSize(
321 (char *)&info
.fdCreator
, 4);
322 type
= PyString_FromStringAndSize((char *)&info
.fdType
, 4);
323 res
= Py_BuildValue("OO", creator
, type
);
329 #endif /* __LP64__ */
332 err
= FSGetCatalogInfo(&ref
,
333 kFSCatInfoFinderInfo
|kFSCatInfoNodeFlags
, &cataloginfo
,
336 PyErr_Mac(MacOS_Error
, err
);
340 if ((cataloginfo
.nodeFlags
& kFSNodeIsDirectoryMask
) != 0) {
341 /* Directory: doesn't have type/creator info.
343 * The specific error code is for backward compatibility with
346 PyErr_Mac(MacOS_Error
, fnfErr
);
350 finfo
= (FileInfo
*)&(cataloginfo
.finderInfo
);
351 finfo
->fileCreator
= ntohl(finfo
->fileCreator
);
352 finfo
->fileType
= ntohl(finfo
->fileType
);
353 creator
= PyString_FromStringAndSize((char*)&(finfo
->fileCreator
), 4);
354 type
= PyString_FromStringAndSize((char*)&(finfo
->fileType
), 4);
356 res
= Py_BuildValue("OO", creator
, type
);
362 static char setcrtp_doc
[] = "Set MacOS 4-char creator and type for a file";
365 MacOS_SetCreatorAndType(PyObject
*self
, PyObject
*args
)
367 ResType creator
, type
;
371 FSCatalogInfo cataloginfo
;
373 if (!PyArg_ParseTuple(args
, "O&O&O&",
374 PyMac_GetFSRef
, &ref
, PyMac_GetOSType
, &creator
, PyMac_GetOSType
, &type
)) {
376 /* Try to handle FSSpec arguments, for backward compatibility */
380 if (!PyArg_ParseTuple(args
, "O&O&O&",
381 PyMac_GetFSSpec
, &fss
, PyMac_GetOSType
, &creator
, PyMac_GetOSType
, &type
))
384 if ((err
= FSpGetFInfo(&fss
, &info
)) != noErr
)
385 return PyErr_Mac(MacOS_Error
, err
);
387 info
.fdCreator
= creator
;
390 if ((err
= FSpSetFInfo(&fss
, &info
)) != noErr
)
391 return PyErr_Mac(MacOS_Error
, err
);
396 #endif /* __LP64__ */
399 err
= FSGetCatalogInfo(&ref
,
400 kFSCatInfoFinderInfo
|kFSCatInfoNodeFlags
, &cataloginfo
,
403 PyErr_Mac(MacOS_Error
, err
);
407 if ((cataloginfo
.nodeFlags
& kFSNodeIsDirectoryMask
) != 0) {
408 /* Directory: doesn't have type/creator info.
410 * The specific error code is for backward compatibility with
413 PyErr_Mac(MacOS_Error
, fnfErr
);
417 finfo
= (FileInfo
*)&(cataloginfo
.finderInfo
);
418 finfo
->fileCreator
= creator
;
419 finfo
->fileType
= type
;
421 err
= FSSetCatalogInfo(&ref
, kFSCatInfoFinderInfo
, &cataloginfo
);
423 PyErr_Mac(MacOS_Error
, fnfErr
);
432 static char geterr_doc
[] = "Convert OSErr number to string";
435 MacOS_GetErrorString(PyObject
*self
, PyObject
*args
)
441 static int errors_loaded
;
443 if (!PyArg_ParseTuple(args
, "i", &err
))
446 h
= GetResource('Estr', err
);
447 if (!h
&& !errors_loaded
) {
449 ** Attempt to open the resource file containing the
450 ** Estr resources. We ignore all errors. We also try
456 m
= PyImport_ImportModuleNoBlock("macresource");
463 rv
= PyObject_CallMethod(m
, "open_error_resource", "");
471 /* And try again... */
472 h
= GetResource('Estr', err
);
478 ** Whether the code above succeeded or not, we won't try
486 memcpy(buf
, str
+1, (unsigned char)str
[0]);
487 buf
[(unsigned char)str
[0]] = '\0';
492 PyOS_snprintf(buf
, sizeof(buf
), "Mac OS error code %d", err
);
495 return Py_BuildValue("s", buf
);
501 static char splash_doc
[] = "Open a splash-screen dialog by resource-id (0=close)";
504 MacOS_splash(PyObject
*self
, PyObject
*args
)
507 static DialogPtr curdialog
= NULL
;
512 short xpos
, ypos
, width
, height
, swidth
, sheight
;
515 if (!PyArg_ParseTuple(args
, "|i", &resid
))
517 olddialog
= curdialog
;
521 curdialog
= GetNewDialog(resid
, NULL
, (WindowPtr
)-1);
523 theWindow
= GetDialogWindow(curdialog
);
524 thePort
= GetWindowPort(theWindow
);
526 width
= thePort
->portRect
.right
- thePort
->portRect
.left
;
527 height
= thePort
->portRect
.bottom
- thePort
->portRect
.top
;
528 swidth
= qd
.screenBits
.bounds
.right
- qd
.screenBits
.bounds
.left
;
529 sheight
= qd
.screenBits
.bounds
.bottom
- qd
.screenBits
.bounds
.top
- LMGetMBarHeight();
530 xpos
= (swidth
-width
)/2;
531 ypos
= (sheight
-height
)/5 + LMGetMBarHeight();
532 MoveWindow(theWindow
, xpos
, ypos
, 0);
533 ShowWindow(theWindow
);
535 DrawDialog(curdialog
);
539 DisposeDialog(olddialog
);
544 static char DebugStr_doc
[] = "Switch to low-level debugger with a message";
547 MacOS_DebugStr(PyObject
*self
, PyObject
*args
)
550 PyObject
*object
= 0;
552 if (!PyArg_ParseTuple(args
, "O&|O", PyMac_GetStr255
, message
, &object
))
561 static char SysBeep_doc
[] = "BEEEEEP!!!";
564 MacOS_SysBeep(PyObject
*self
, PyObject
*args
)
568 if (!PyArg_ParseTuple(args
, "|i", &duration
))
575 #endif /* __LP64__ */
577 static char WMAvailable_doc
[] =
578 "True if this process can interact with the display."
579 "Will foreground the application on the first call as a side-effect."
583 MacOS_WMAvailable(PyObject
*self
, PyObject
*args
)
585 static PyObject
*rv
= NULL
;
587 if (!PyArg_ParseTuple(args
, ""))
590 ProcessSerialNumber psn
;
593 ** This is a fairly innocuous call to make if we don't have a window
594 ** manager, or if we have no permission to talk to it. It will print
595 ** a message on stderr, but at least it won't abort the process.
596 ** It appears the function caches the result itself, and it's cheap, so
597 ** no need for us to cache.
599 #ifdef kCGNullDirectDisplay
600 /* On 10.1 CGMainDisplayID() isn't available, and
601 ** kCGNullDirectDisplay isn't defined.
603 if (CGMainDisplayID() == 0) {
609 if (GetCurrentProcess(&psn
) < 0 ||
610 SetFrontProcess(&psn
) < 0) {
621 static char GetTicks_doc
[] = "Return number of ticks since bootup";
624 MacOS_GetTicks(PyObject
*self
, PyObject
*args
)
626 return Py_BuildValue("i", (int)TickCount());
629 static char openrf_doc
[] = "Open resource fork of a file";
632 MacOS_openrf(PyObject
*self
, PyObject
*args
)
637 SInt8 permission
= fsRdPerm
;
641 if (!PyArg_ParseTuple(args
, "O&|s", PyMac_GetFSRef
, &ref
, &mode
))
646 case 'r': permission
= fsRdPerm
; break;
647 case 'w': permission
= fsWrPerm
; break;
655 err
= FSGetResourceForkName(&name
);
661 if ( (fp
= newrfobject()) == NULL
)
665 err
= FSOpenFork(&ref
, name
.length
, name
.unicode
, permission
, &fp
->fRefNum
);
672 return (PyObject
*)fp
;
677 static PyMethodDef MacOS_Methods
[] = {
678 {"GetCreatorAndType", MacOS_GetCreatorAndType
, 1, getcrtp_doc
},
679 {"SetCreatorAndType", MacOS_SetCreatorAndType
, 1, setcrtp_doc
},
680 {"GetErrorString", MacOS_GetErrorString
, 1, geterr_doc
},
681 {"openrf", MacOS_openrf
, 1, openrf_doc
},
683 {"splash", MacOS_splash
, 1, splash_doc
},
684 {"DebugStr", MacOS_DebugStr
, 1, DebugStr_doc
},
685 {"SysBeep", MacOS_SysBeep
, 1, SysBeep_doc
},
686 #endif /* __LP64__ */
687 {"GetTicks", MacOS_GetTicks
, 1, GetTicks_doc
},
688 {"WMAvailable", MacOS_WMAvailable
, 1, WMAvailable_doc
},
689 {NULL
, NULL
} /* Sentinel */
698 if (PyErr_WarnPy3k("In 3.x, MacOS is removed.", 1))
701 m
= Py_InitModule("MacOS", MacOS_Methods
);
702 d
= PyModule_GetDict(m
);
704 /* Initialize MacOS.Error exception */
705 MacOS_Error
= PyMac_GetOSErrException();
706 if (MacOS_Error
== NULL
|| PyDict_SetItemString(d
, "Error", MacOS_Error
) != 0)
708 Rftype
.ob_type
= &PyType_Type
;
710 if (PyDict_SetItemString(d
, "ResourceForkType", (PyObject
*)&Rftype
) != 0)
713 ** This is a hack: the following constant added to the id() of a string
714 ** object gives you the address of the data. Unfortunately, it is needed for
715 ** some of the image and sound processing interfaces on the mac:-(
718 PyStringObject
*p
= 0;
719 long off
= (long)&(p
->ob_sval
[0]);
721 if( PyDict_SetItemString(d
, "string_id_to_buffer", Py_BuildValue("i", off
)) != 0)
724 #define PY_RUNTIMEMODEL "macho"
725 if (PyDict_SetItemString(d
, "runtimemodel",
726 Py_BuildValue("s", PY_RUNTIMEMODEL
)) != 0)
728 #if defined(WITH_NEXT_FRAMEWORK)
729 #define PY_LINKMODEL "framework"
730 #elif defined(Py_ENABLE_SHARED)
731 #define PY_LINKMODEL "shared"
733 #define PY_LINKMODEL "static"
735 if (PyDict_SetItemString(d
, "linkmodel",
736 Py_BuildValue("s", PY_LINKMODEL
)) != 0)