source: python/trunk/Mac/Modules/MacOS.c@ 384

Last change on this file since 384 was 2, checked in by Yuri Dario, 15 years ago

Initial import for vendor code.

  • Property svn:eol-style set to native
File size: 16.2 KB
Line 
1/***********************************************************
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/* Macintosh OS-specific interface */
26
27#include "Python.h"
28#include "pymactoolbox.h"
29
30#include <Carbon/Carbon.h>
31#include <ApplicationServices/ApplicationServices.h>
32
33#ifndef HAVE_OSX105_SDK
34typedef SInt16 FSIORefNum;
35#endif
36
37static PyObject *MacOS_Error; /* Exception MacOS.Error */
38
39#define PATHNAMELEN 1024
40
41/* ----------------------------------------------------- */
42
43/* Declarations for objects of type Resource fork */
44
45typedef struct {
46 PyObject_HEAD
47 FSIORefNum fRefNum;
48 int isclosed;
49} rfobject;
50
51static PyTypeObject Rftype;
52
53
54
55/* ---------------------------------------------------------------- */
56
57static void
58do_close(rfobject *self)
59{
60 if (self->isclosed ) return;
61 (void)FSCloseFork(self->fRefNum);
62 self->isclosed = 1;
63}
64
65static char rf_read__doc__[] =
66"Read data from resource fork"
67;
68
69static PyObject *
70rf_read(rfobject *self, PyObject *args)
71{
72 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;
97}
98
99
100static char rf_write__doc__[] =
101"Write to resource fork"
102;
103
104static PyObject *
105rf_write(rfobject *self, PyObject *args)
106{
107 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;
124}
125
126
127static char rf_seek__doc__[] =
128"Set file position"
129;
130
131static PyObject *
132rf_seek(rfobject *self, PyObject *args)
133{
134 long amount;
135 int whence = SEEK_SET;
136 int mode;
137 OSErr err;
138
139 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;
169}
170
171
172static char rf_tell__doc__[] =
173"Get file position"
174;
175
176static PyObject *
177rf_tell(rfobject *self, PyObject *args)
178{
179 long long where;
180 OSErr err;
181
182 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);
195}
196
197static char rf_close__doc__[] =
198"Close resource fork"
199;
200
201static PyObject *
202rf_close(rfobject *self, PyObject *args)
203{
204 if (!PyArg_ParseTuple(args, ""))
205 return NULL;
206 do_close(self);
207 Py_INCREF(Py_None);
208 return Py_None;
209}
210
211
212static struct PyMethodDef rf_methods[] = {
213 {"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 */
220};
221
222/* ---------- */
223
224
225static rfobject *
226newrfobject(void)
227{
228 rfobject *self;
229
230 self = PyObject_NEW(rfobject, &Rftype);
231 if (self == NULL)
232 return NULL;
233 self->isclosed = 1;
234 return self;
235}
236
237
238static void
239rf_dealloc(rfobject *self)
240{
241 do_close(self);
242 PyObject_DEL(self);
243}
244
245static PyObject *
246rf_getattr(rfobject *self, char *name)
247{
248 return Py_FindMethod(rf_methods, (PyObject *)self, name);
249}
250
251static char Rftype__doc__[] =
252"Resource fork file object"
253;
254
255static PyTypeObject Rftype = {
256 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*/
274
275 /* Space for future expansion */
276 0L,0L,0L,0L,
277 Rftype__doc__ /* Documentation string */
278};
279
280
281/* End of code for Resource fork objects */
282/* -------------------------------------------------------- */
283
284/*----------------------------------------------------------------------*/
285/* Miscellaneous File System Operations */
286
287static char getcrtp_doc[] = "Get MacOS 4-char creator and type for a file";
288
289static PyObject *
290MacOS_GetCreatorAndType(PyObject *self, PyObject *args)
291{
292 PyObject *creator, *type, *res;
293 OSErr err;
294 FSRef ref;
295 FSCatalogInfo cataloginfo;
296 FileInfo* finfo;
297
298 if (!PyArg_ParseTuple(args, "O&", PyMac_GetFSRef, &ref)) {
299#ifndef __LP64__
300 /* 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;
306
307 if (!PyArg_ParseTuple(args, "O&", PyMac_GetFSSpec, &fss))
308 return NULL;
309
310 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 }
324
325 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 }
332
333 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;
341
342 }
343 finfo = (FileInfo*)&(cataloginfo.finderInfo);
344 creator = PyString_FromStringAndSize((char*)&(finfo->fileCreator), 4);
345 type = PyString_FromStringAndSize((char*)&(finfo->fileType), 4);
346
347 res = Py_BuildValue("OO", creator, type);
348 Py_DECREF(creator);
349 Py_DECREF(type);
350 return res;
351}
352
353static char setcrtp_doc[] = "Set MacOS 4-char creator and type for a file";
354
355static PyObject *
356MacOS_SetCreatorAndType(PyObject *self, PyObject *args)
357{
358 ResType creator, type;
359 FSRef ref;
360 FileInfo* finfo;
361 OSErr err;
362 FSCatalogInfo cataloginfo;
363
364 if (!PyArg_ParseTuple(args, "O&O&O&",
365 PyMac_GetFSRef, &ref, PyMac_GetOSType, &creator, PyMac_GetOSType, &type)) {
366#ifndef __LP64__
367 /* Try to handle FSSpec arguments, for backward compatibility */
368 FSSpec fss;
369 FInfo info;
370
371 if (!PyArg_ParseTuple(args, "O&O&O&",
372 PyMac_GetFSSpec, &fss, PyMac_GetOSType, &creator, PyMac_GetOSType, &type))
373 return NULL;
374
375 if ((err = FSpGetFInfo(&fss, &info)) != noErr)
376 return PyErr_Mac(MacOS_Error, err);
377
378 info.fdCreator = creator;
379 info.fdType = type;
380
381 if ((err = FSpSetFInfo(&fss, &info)) != noErr)
382 return PyErr_Mac(MacOS_Error, err);
383 Py_INCREF(Py_None);
384 return Py_None;
385#else /* __LP64__ */
386 return NULL;
387#endif /* __LP64__ */
388 }
389
390 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 }
397
398 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;
406
407 }
408 finfo = (FileInfo*)&(cataloginfo.finderInfo);
409 finfo->fileCreator = creator;
410 finfo->fileType = type;
411
412 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;
420}
421
422
423static char geterr_doc[] = "Convert OSErr number to string";
424
425static PyObject *
426MacOS_GetErrorString(PyObject *self, PyObject *args)
427{
428 int err;
429 char buf[256];
430 Handle h;
431 char *str;
432 static int errors_loaded;
433
434 if (!PyArg_ParseTuple(args, "i", &err))
435 return NULL;
436
437 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);
487}
488
489
490#ifndef __LP64__
491
492static char splash_doc[] = "Open a splash-screen dialog by resource-id (0=close)";
493
494static PyObject *
495MacOS_splash(PyObject *self, PyObject *args)
496{
497 int resid = -1;
498 static DialogPtr curdialog = NULL;
499 DialogPtr olddialog;
500 WindowRef theWindow;
501 CGrafPtr thePort;
502#if 0
503 short xpos, ypos, width, height, swidth, sheight;
504#endif
505
506 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);
516#if 0
517 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);
525#endif
526 DrawDialog(curdialog);
527 }
528 }
529 if (olddialog)
530 DisposeDialog(olddialog);
531 Py_INCREF(Py_None);
532 return Py_None;
533}
534
535static char DebugStr_doc[] = "Switch to low-level debugger with a message";
536
537static PyObject *
538MacOS_DebugStr(PyObject *self, PyObject *args)
539{
540 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;
549}
550
551
552static char SysBeep_doc[] = "BEEEEEP!!!";
553
554static PyObject *
555MacOS_SysBeep(PyObject *self, PyObject *args)
556{
557 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;
564}
565
566#endif /* __LP64__ */
567
568static 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 ;
572
573static PyObject *
574MacOS_WMAvailable(PyObject *self, PyObject *args)
575{
576 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 */
590#ifdef kCGNullDirectDisplay
591 /* On 10.1 CGMainDisplayID() isn't available, and
592 ** kCGNullDirectDisplay isn't defined.
593 */
594 if (CGMainDisplayID() == 0) {
595 rv = Py_False;
596 } else {
597#else
598 {
599#endif
600 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;
610}
611
612static char GetTicks_doc[] = "Return number of ticks since bootup";
613
614static PyObject *
615MacOS_GetTicks(PyObject *self, PyObject *args)
616{
617 return Py_BuildValue("i", (int)TickCount());
618}
619
620static char openrf_doc[] = "Open resource fork of a file";
621
622static PyObject *
623MacOS_openrf(PyObject *self, PyObject *args)
624{
625 OSErr err;
626 char *mode = "r";
627 FSRef ref;
628 SInt8 permission = fsRdPerm;
629 rfobject *fp;
630 HFSUniStr255 name;
631
632 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 }
645
646 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;
664}
665
666
667
668static PyMethodDef MacOS_Methods[] = {
669 {"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},
673#ifndef __LP64__
674 {"splash", MacOS_splash, 1, splash_doc},
675 {"DebugStr", MacOS_DebugStr, 1, DebugStr_doc},
676 {"SysBeep", MacOS_SysBeep, 1, SysBeep_doc},
677#endif /* __LP64__ */
678 {"GetTicks", MacOS_GetTicks, 1, GetTicks_doc},
679 {"WMAvailable", MacOS_WMAvailable, 1, WMAvailable_doc},
680 {NULL, NULL} /* Sentinel */
681};
682
683
684void
685initMacOS(void)
686{
687 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 }
715#define PY_RUNTIMEMODEL "macho"
716 if (PyDict_SetItemString(d, "runtimemodel",
717 Py_BuildValue("s", PY_RUNTIMEMODEL)) != 0)
718 return;
719#if defined(WITH_NEXT_FRAMEWORK)
720#define PY_LINKMODEL "framework"
721#elif defined(Py_ENABLE_SHARED)
722#define PY_LINKMODEL "shared"
723#else
724#define PY_LINKMODEL "static"
725#endif
726 if (PyDict_SetItemString(d, "linkmodel",
727 Py_BuildValue("s", PY_LINKMODEL)) != 0)
728 return;
729
730}
Note: See TracBrowser for help on using the repository browser.