source: vendor/python/2.5/Mac/Modules/MacOS.c

Last change on this file was 3225, checked in by bird, 18 years ago

Python 2.5

File size: 14.5 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
33static PyObject *MacOS_Error; /* Exception MacOS.Error */
34
35#define PATHNAMELEN 1024
36
37/* ----------------------------------------------------- */
38
39/* Declarations for objects of type Resource fork */
40
41typedef struct {
42 PyObject_HEAD
43 short fRefNum;
44 int isclosed;
45} rfobject;
46
47static PyTypeObject Rftype;
48
49
50
51/* ---------------------------------------------------------------- */
52
53static void
54do_close(rfobject *self)
55{
56 if (self->isclosed ) return;
57 (void)FSClose(self->fRefNum);
58 self->isclosed = 1;
59}
60
61static char rf_read__doc__[] =
62"Read data from resource fork"
63;
64
65static PyObject *
66rf_read(rfobject *self, PyObject *args)
67{
68 long n;
69 PyObject *v;
70 OSErr err;
71
72 if (self->isclosed) {
73 PyErr_SetString(PyExc_ValueError, "Operation on closed file");
74 return NULL;
75 }
76
77 if (!PyArg_ParseTuple(args, "l", &n))
78 return NULL;
79
80 v = PyString_FromStringAndSize((char *)NULL, n);
81 if (v == NULL)
82 return NULL;
83
84 err = FSRead(self->fRefNum, &n, PyString_AsString(v));
85 if (err && err != eofErr) {
86 PyMac_Error(err);
87 Py_DECREF(v);
88 return NULL;
89 }
90 _PyString_Resize(&v, n);
91 return v;
92}
93
94
95static char rf_write__doc__[] =
96"Write to resource fork"
97;
98
99static PyObject *
100rf_write(rfobject *self, PyObject *args)
101{
102 char *buffer;
103 long size;
104 OSErr err;
105
106 if (self->isclosed) {
107 PyErr_SetString(PyExc_ValueError, "Operation on closed file");
108 return NULL;
109 }
110 if (!PyArg_ParseTuple(args, "s#", &buffer, &size))
111 return NULL;
112 err = FSWrite(self->fRefNum, &size, buffer);
113 if (err) {
114 PyMac_Error(err);
115 return NULL;
116 }
117 Py_INCREF(Py_None);
118 return Py_None;
119}
120
121
122static char rf_seek__doc__[] =
123"Set file position"
124;
125
126static PyObject *
127rf_seek(rfobject *self, PyObject *args)
128{
129 long amount, pos;
130 int whence = SEEK_SET;
131 long eof;
132 OSErr err;
133
134 if (self->isclosed) {
135 PyErr_SetString(PyExc_ValueError, "Operation on closed file");
136 return NULL;
137 }
138 if (!PyArg_ParseTuple(args, "l|i", &amount, &whence))
139 return NULL;
140
141 if ((err = GetEOF(self->fRefNum, &eof)))
142 goto ioerr;
143
144 switch (whence) {
145 case SEEK_CUR:
146 if ((err = GetFPos(self->fRefNum, &pos)))
147 goto ioerr;
148 break;
149 case SEEK_END:
150 pos = eof;
151 break;
152 case SEEK_SET:
153 pos = 0;
154 break;
155 default:
156 PyErr_BadArgument();
157 return NULL;
158 }
159
160 pos += amount;
161
162 /* Don't bother implementing seek past EOF */
163 if (pos > eof || pos < 0) {
164 PyErr_BadArgument();
165 return NULL;
166 }
167
168 if ((err = SetFPos(self->fRefNum, fsFromStart, pos)) ) {
169ioerr:
170 PyMac_Error(err);
171 return NULL;
172 }
173 Py_INCREF(Py_None);
174 return Py_None;
175}
176
177
178static char rf_tell__doc__[] =
179"Get file position"
180;
181
182static PyObject *
183rf_tell(rfobject *self, PyObject *args)
184{
185 long where;
186 OSErr err;
187
188 if (self->isclosed) {
189 PyErr_SetString(PyExc_ValueError, "Operation on closed file");
190 return NULL;
191 }
192 if (!PyArg_ParseTuple(args, ""))
193 return NULL;
194 if ((err = GetFPos(self->fRefNum, &where)) ) {
195 PyMac_Error(err);
196 return NULL;
197 }
198 return PyInt_FromLong(where);
199}
200
201static char rf_close__doc__[] =
202"Close resource fork"
203;
204
205static PyObject *
206rf_close(rfobject *self, PyObject *args)
207{
208 if (!PyArg_ParseTuple(args, ""))
209 return NULL;
210 do_close(self);
211 Py_INCREF(Py_None);
212 return Py_None;
213}
214
215
216static struct PyMethodDef rf_methods[] = {
217 {"read", (PyCFunction)rf_read, 1, rf_read__doc__},
218 {"write", (PyCFunction)rf_write, 1, rf_write__doc__},
219 {"seek", (PyCFunction)rf_seek, 1, rf_seek__doc__},
220 {"tell", (PyCFunction)rf_tell, 1, rf_tell__doc__},
221 {"close", (PyCFunction)rf_close, 1, rf_close__doc__},
222
223 {NULL, NULL} /* sentinel */
224};
225
226/* ---------- */
227
228
229static rfobject *
230newrfobject(void)
231{
232 rfobject *self;
233
234 self = PyObject_NEW(rfobject, &Rftype);
235 if (self == NULL)
236 return NULL;
237 self->isclosed = 1;
238 return self;
239}
240
241
242static void
243rf_dealloc(rfobject *self)
244{
245 do_close(self);
246 PyObject_DEL(self);
247}
248
249static PyObject *
250rf_getattr(rfobject *self, char *name)
251{
252 return Py_FindMethod(rf_methods, (PyObject *)self, name);
253}
254
255static char Rftype__doc__[] =
256"Resource fork file object"
257;
258
259static PyTypeObject Rftype = {
260 PyObject_HEAD_INIT(&PyType_Type)
261 0, /*ob_size*/
262 "MacOS.ResourceFork", /*tp_name*/
263 sizeof(rfobject), /*tp_basicsize*/
264 0, /*tp_itemsize*/
265 /* methods */
266 (destructor)rf_dealloc, /*tp_dealloc*/
267 (printfunc)0, /*tp_print*/
268 (getattrfunc)rf_getattr, /*tp_getattr*/
269 (setattrfunc)0, /*tp_setattr*/
270 (cmpfunc)0, /*tp_compare*/
271 (reprfunc)0, /*tp_repr*/
272 0, /*tp_as_number*/
273 0, /*tp_as_sequence*/
274 0, /*tp_as_mapping*/
275 (hashfunc)0, /*tp_hash*/
276 (ternaryfunc)0, /*tp_call*/
277 (reprfunc)0, /*tp_str*/
278
279 /* Space for future expansion */
280 0L,0L,0L,0L,
281 Rftype__doc__ /* Documentation string */
282};
283
284/* End of code for Resource fork objects */
285/* -------------------------------------------------------- */
286
287/*----------------------------------------------------------------------*/
288/* Miscellaneous File System Operations */
289
290static char getcrtp_doc[] = "Get MacOS 4-char creator and type for a file";
291
292static PyObject *
293MacOS_GetCreatorAndType(PyObject *self, PyObject *args)
294{
295 FSSpec fss;
296 FInfo info;
297 PyObject *creator, *type, *res;
298 OSErr err;
299
300 if (!PyArg_ParseTuple(args, "O&", PyMac_GetFSSpec, &fss))
301 return NULL;
302 if ((err = FSpGetFInfo(&fss, &info)) != noErr)
303 return PyErr_Mac(MacOS_Error, err);
304 creator = PyString_FromStringAndSize((char *)&info.fdCreator, 4);
305 type = PyString_FromStringAndSize((char *)&info.fdType, 4);
306 res = Py_BuildValue("OO", creator, type);
307 Py_DECREF(creator);
308 Py_DECREF(type);
309 return res;
310}
311
312static char setcrtp_doc[] = "Set MacOS 4-char creator and type for a file";
313
314static PyObject *
315MacOS_SetCreatorAndType(PyObject *self, PyObject *args)
316{
317 FSSpec fss;
318 ResType creator, type;
319 FInfo info;
320 OSErr err;
321
322 if (!PyArg_ParseTuple(args, "O&O&O&",
323 PyMac_GetFSSpec, &fss, PyMac_GetOSType, &creator, PyMac_GetOSType, &type))
324 return NULL;
325 if ((err = FSpGetFInfo(&fss, &info)) != noErr)
326 return PyErr_Mac(MacOS_Error, err);
327 info.fdCreator = creator;
328 info.fdType = type;
329 if ((err = FSpSetFInfo(&fss, &info)) != noErr)
330 return PyErr_Mac(MacOS_Error, err);
331 Py_INCREF(Py_None);
332 return Py_None;
333}
334
335
336static char geterr_doc[] = "Convert OSErr number to string";
337
338static PyObject *
339MacOS_GetErrorString(PyObject *self, PyObject *args)
340{
341 int err;
342 char buf[256];
343 Handle h;
344 char *str;
345 static int errors_loaded;
346
347 if (!PyArg_ParseTuple(args, "i", &err))
348 return NULL;
349
350 h = GetResource('Estr', err);
351 if (!h && !errors_loaded) {
352 /*
353 ** Attempt to open the resource file containing the
354 ** Estr resources. We ignore all errors. We also try
355 ** this only once.
356 */
357 PyObject *m, *rv;
358 errors_loaded = 1;
359
360 m = PyImport_ImportModule("macresource");
361 if (!m) {
362 if (Py_VerboseFlag)
363 PyErr_Print();
364 PyErr_Clear();
365 }
366 else {
367 rv = PyObject_CallMethod(m, "open_error_resource", "");
368 if (!rv) {
369 if (Py_VerboseFlag)
370 PyErr_Print();
371 PyErr_Clear();
372 }
373 else {
374 Py_DECREF(rv);
375 /* And try again... */
376 h = GetResource('Estr', err);
377 }
378 Py_DECREF(m);
379 }
380 }
381 /*
382 ** Whether the code above succeeded or not, we won't try
383 ** again.
384 */
385 errors_loaded = 1;
386
387 if (h) {
388 HLock(h);
389 str = (char *)*h;
390 memcpy(buf, str+1, (unsigned char)str[0]);
391 buf[(unsigned char)str[0]] = '\0';
392 HUnlock(h);
393 ReleaseResource(h);
394 }
395 else {
396 PyOS_snprintf(buf, sizeof(buf), "Mac OS error code %d", err);
397 }
398
399 return Py_BuildValue("s", buf);
400}
401
402static char splash_doc[] = "Open a splash-screen dialog by resource-id (0=close)";
403
404static PyObject *
405MacOS_splash(PyObject *self, PyObject *args)
406{
407 int resid = -1;
408 static DialogPtr curdialog = NULL;
409 DialogPtr olddialog;
410 WindowRef theWindow;
411 CGrafPtr thePort;
412#if 0
413 short xpos, ypos, width, height, swidth, sheight;
414#endif
415
416 if (!PyArg_ParseTuple(args, "|i", &resid))
417 return NULL;
418 olddialog = curdialog;
419 curdialog = NULL;
420
421 if ( resid != -1 ) {
422 curdialog = GetNewDialog(resid, NULL, (WindowPtr)-1);
423 if ( curdialog ) {
424 theWindow = GetDialogWindow(curdialog);
425 thePort = GetWindowPort(theWindow);
426#if 0
427 width = thePort->portRect.right - thePort->portRect.left;
428 height = thePort->portRect.bottom - thePort->portRect.top;
429 swidth = qd.screenBits.bounds.right - qd.screenBits.bounds.left;
430 sheight = qd.screenBits.bounds.bottom - qd.screenBits.bounds.top - LMGetMBarHeight();
431 xpos = (swidth-width)/2;
432 ypos = (sheight-height)/5 + LMGetMBarHeight();
433 MoveWindow(theWindow, xpos, ypos, 0);
434 ShowWindow(theWindow);
435#endif
436 DrawDialog(curdialog);
437 }
438 }
439 if (olddialog)
440 DisposeDialog(olddialog);
441 Py_INCREF(Py_None);
442 return Py_None;
443}
444
445static char DebugStr_doc[] = "Switch to low-level debugger with a message";
446
447static PyObject *
448MacOS_DebugStr(PyObject *self, PyObject *args)
449{
450 Str255 message;
451 PyObject *object = 0;
452
453 if (!PyArg_ParseTuple(args, "O&|O", PyMac_GetStr255, message, &object))
454 return NULL;
455 DebugStr(message);
456 Py_INCREF(Py_None);
457 return Py_None;
458}
459
460static char SysBeep_doc[] = "BEEEEEP!!!";
461
462static PyObject *
463MacOS_SysBeep(PyObject *self, PyObject *args)
464{
465 int duration = 6;
466
467 if (!PyArg_ParseTuple(args, "|i", &duration))
468 return NULL;
469 SysBeep(duration);
470 Py_INCREF(Py_None);
471 return Py_None;
472}
473
474static char WMAvailable_doc[] =
475 "True if this process can interact with the display."
476 "Will foreground the application on the first call as a side-effect."
477 ;
478
479static PyObject *
480MacOS_WMAvailable(PyObject *self, PyObject *args)
481{
482 static PyObject *rv = NULL;
483
484 if (!PyArg_ParseTuple(args, ""))
485 return NULL;
486 if (!rv) {
487 ProcessSerialNumber psn;
488
489 /*
490 ** This is a fairly innocuous call to make if we don't have a window
491 ** manager, or if we have no permission to talk to it. It will print
492 ** a message on stderr, but at least it won't abort the process.
493 ** It appears the function caches the result itself, and it's cheap, so
494 ** no need for us to cache.
495 */
496#ifdef kCGNullDirectDisplay
497 /* On 10.1 CGMainDisplayID() isn't available, and
498 ** kCGNullDirectDisplay isn't defined.
499 */
500 if (CGMainDisplayID() == 0) {
501 rv = Py_False;
502 } else {
503#else
504 {
505#endif
506 if (GetCurrentProcess(&psn) < 0 ||
507 SetFrontProcess(&psn) < 0) {
508 rv = Py_False;
509 } else {
510 rv = Py_True;
511 }
512 }
513 }
514 Py_INCREF(rv);
515 return rv;
516}
517
518static char GetTicks_doc[] = "Return number of ticks since bootup";
519
520static PyObject *
521MacOS_GetTicks(PyObject *self, PyObject *args)
522{
523 return Py_BuildValue("i", (int)TickCount());
524}
525
526static char openrf_doc[] = "Open resource fork of a file";
527
528static PyObject *
529MacOS_openrf(PyObject *self, PyObject *args)
530{
531 OSErr err;
532 char *mode = "r";
533 FSSpec fss;
534 SignedByte permission = 1;
535 rfobject *fp;
536
537 if (!PyArg_ParseTuple(args, "O&|s", PyMac_GetFSSpec, &fss, &mode))
538 return NULL;
539 while (*mode) {
540 switch (*mode++) {
541 case '*': break;
542 case 'r': permission = 1; break;
543 case 'w': permission = 2; break;
544 case 'b': break;
545 default:
546 PyErr_BadArgument();
547 return NULL;
548 }
549 }
550
551 if ( (fp = newrfobject()) == NULL )
552 return NULL;
553
554 err = HOpenRF(fss.vRefNum, fss.parID, fss.name, permission, &fp->fRefNum);
555
556 if ( err == fnfErr ) {
557 /* In stead of doing complicated things here to get creator/type
558 ** correct we let the standard i/o library handle it
559 */
560 FILE *tfp;
561 char pathname[PATHNAMELEN];
562
563 if ( (err=PyMac_GetFullPathname(&fss, pathname, PATHNAMELEN)) ) {
564 PyMac_Error(err);
565 Py_DECREF(fp);
566 return NULL;
567 }
568
569 if ( (tfp = fopen(pathname, "w")) == NULL ) {
570 PyMac_Error(fnfErr); /* What else... */
571 Py_DECREF(fp);
572 return NULL;
573 }
574 fclose(tfp);
575 err = HOpenRF(fss.vRefNum, fss.parID, fss.name, permission, &fp->fRefNum);
576 }
577 if ( err ) {
578 Py_DECREF(fp);
579 PyMac_Error(err);
580 return NULL;
581 }
582 fp->isclosed = 0;
583 return (PyObject *)fp;
584}
585
586
587static PyMethodDef MacOS_Methods[] = {
588 {"GetCreatorAndType", MacOS_GetCreatorAndType, 1, getcrtp_doc},
589 {"SetCreatorAndType", MacOS_SetCreatorAndType, 1, setcrtp_doc},
590 {"GetErrorString", MacOS_GetErrorString, 1, geterr_doc},
591 {"openrf", MacOS_openrf, 1, openrf_doc},
592 {"splash", MacOS_splash, 1, splash_doc},
593 {"DebugStr", MacOS_DebugStr, 1, DebugStr_doc},
594 {"GetTicks", MacOS_GetTicks, 1, GetTicks_doc},
595 {"SysBeep", MacOS_SysBeep, 1, SysBeep_doc},
596 {"WMAvailable", MacOS_WMAvailable, 1, WMAvailable_doc},
597 {NULL, NULL} /* Sentinel */
598};
599
600
601void
602initMacOS(void)
603{
604 PyObject *m, *d;
605
606 m = Py_InitModule("MacOS", MacOS_Methods);
607 d = PyModule_GetDict(m);
608
609 /* Initialize MacOS.Error exception */
610 MacOS_Error = PyMac_GetOSErrException();
611 if (MacOS_Error == NULL || PyDict_SetItemString(d, "Error", MacOS_Error) != 0)
612 return;
613 Rftype.ob_type = &PyType_Type;
614 Py_INCREF(&Rftype);
615 if (PyDict_SetItemString(d, "ResourceForkType", (PyObject *)&Rftype) != 0)
616 return;
617 /*
618 ** This is a hack: the following constant added to the id() of a string
619 ** object gives you the address of the data. Unfortunately, it is needed for
620 ** some of the image and sound processing interfaces on the mac:-(
621 */
622 {
623 PyStringObject *p = 0;
624 long off = (long)&(p->ob_sval[0]);
625
626 if( PyDict_SetItemString(d, "string_id_to_buffer", Py_BuildValue("i", off)) != 0)
627 return;
628 }
629#define PY_RUNTIMEMODEL "macho"
630 if (PyDict_SetItemString(d, "runtimemodel",
631 Py_BuildValue("s", PY_RUNTIMEMODEL)) != 0)
632 return;
633#if defined(WITH_NEXT_FRAMEWORK)
634#define PY_LINKMODEL "framework"
635#elif defined(Py_ENABLE_SHARED)
636#define PY_LINKMODEL "shared"
637#else
638#define PY_LINKMODEL "static"
639#endif
640 if (PyDict_SetItemString(d, "linkmodel",
641 Py_BuildValue("s", PY_LINKMODEL)) != 0)
642 return;
643
644}
Note: See TracBrowser for help on using the repository browser.