Bump version to 1.0.
[python/dscho.git] / Mac / Modules / macosmodule.c
blobec52da4e8eefc0bb7aec719ffd5cb22fe7598a2e
1 /***********************************************************
2 Copyright 1991-1997 by Stichting Mathematisch Centrum, Amsterdam,
3 The Netherlands.
5 All Rights Reserved
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 */
27 #include "Python.h"
28 #include "macglue.h"
30 #include <Windows.h>
31 #include <Files.h>
32 #include <LowMem.h>
33 #include <Sound.h>
34 #include <Events.h>
36 static PyObject *MacOS_Error; /* Exception MacOS.Error */
38 #ifdef MPW
39 #define bufferIsSmall -607 /*error returns from Post and Accept */
40 #endif
42 static PyObject *ErrorObject;
44 /* ----------------------------------------------------- */
46 /* Declarations for objects of type Resource fork */
48 typedef struct {
49 PyObject_HEAD
50 short fRefNum;
51 int isclosed;
52 } rfobject;
54 staticforward PyTypeObject Rftype;
58 /* ---------------------------------------------------------------- */
60 static void
61 do_close(self)
62 rfobject *self;
64 if (self->isclosed ) return;
65 (void)FSClose(self->fRefNum);
66 self->isclosed = 1;
69 static char rf_read__doc__[] =
70 "Read data from resource fork"
73 static PyObject *
74 rf_read(self, args)
75 rfobject *self;
76 PyObject *args;
78 long n;
79 PyObject *v;
80 OSErr err;
82 if (self->isclosed) {
83 PyErr_SetString(PyExc_ValueError, "Operation on closed file");
84 return NULL;
87 if (!PyArg_ParseTuple(args, "l", &n))
88 return NULL;
90 v = PyString_FromStringAndSize((char *)NULL, n);
91 if (v == NULL)
92 return NULL;
94 err = FSRead(self->fRefNum, &n, PyString_AsString(v));
95 if (err && err != eofErr) {
96 PyMac_Error(err);
97 Py_DECREF(v);
98 return NULL;
100 _PyString_Resize(&v, n);
101 return v;
105 static char rf_write__doc__[] =
106 "Write to resource fork"
109 static PyObject *
110 rf_write(self, args)
111 rfobject *self;
112 PyObject *args;
114 char *buffer;
115 long size;
116 OSErr err;
118 if (self->isclosed) {
119 PyErr_SetString(PyExc_ValueError, "Operation on closed file");
120 return NULL;
122 if (!PyArg_ParseTuple(args, "s#", &buffer, &size))
123 return NULL;
124 err = FSWrite(self->fRefNum, &size, buffer);
125 if (err) {
126 PyMac_Error(err);
127 return NULL;
129 Py_INCREF(Py_None);
130 return Py_None;
134 static char rf_seek__doc__[] =
135 "Set file position"
138 static PyObject *
139 rf_seek(self, args)
140 rfobject *self;
141 PyObject *args;
143 long amount, pos;
144 int whence = SEEK_SET;
145 long eof;
146 OSErr err;
148 if (self->isclosed) {
149 PyErr_SetString(PyExc_ValueError, "Operation on closed file");
150 return NULL;
152 if (!PyArg_ParseTuple(args, "l|i", &amount, &whence))
153 return NULL;
155 if ( err = GetEOF(self->fRefNum, &eof))
156 goto ioerr;
158 switch (whence) {
159 case SEEK_CUR:
160 if (err = GetFPos(self->fRefNum, &pos))
161 goto ioerr;
162 break;
163 case SEEK_END:
164 pos = eof;
165 break;
166 case SEEK_SET:
167 pos = 0;
168 break;
169 default:
170 PyErr_BadArgument();
171 return NULL;
174 pos += amount;
176 /* Don't bother implementing seek past EOF */
177 if (pos > eof || pos < 0) {
178 PyErr_BadArgument();
179 return NULL;
182 if ( err = SetFPos(self->fRefNum, fsFromStart, pos) ) {
183 ioerr:
184 PyMac_Error(err);
185 return NULL;
187 Py_INCREF(Py_None);
188 return Py_None;
192 static char rf_tell__doc__[] =
193 "Get file position"
196 static PyObject *
197 rf_tell(self, args)
198 rfobject *self;
199 PyObject *args;
201 long where;
202 OSErr err;
204 if (self->isclosed) {
205 PyErr_SetString(PyExc_ValueError, "Operation on closed file");
206 return NULL;
208 if (!PyArg_ParseTuple(args, ""))
209 return NULL;
210 if ( err = GetFPos(self->fRefNum, &where) ) {
211 PyMac_Error(err);
212 return NULL;
214 return PyInt_FromLong(where);
217 static char rf_close__doc__[] =
218 "Close resource fork"
221 static PyObject *
222 rf_close(self, args)
223 rfobject *self;
224 PyObject *args;
226 if (!PyArg_ParseTuple(args, ""))
227 return NULL;
228 do_close(self);
229 Py_INCREF(Py_None);
230 return Py_None;
234 static struct PyMethodDef rf_methods[] = {
235 {"read", rf_read, 1, rf_read__doc__},
236 {"write", rf_write, 1, rf_write__doc__},
237 {"seek", rf_seek, 1, rf_seek__doc__},
238 {"tell", rf_tell, 1, rf_tell__doc__},
239 {"close", rf_close, 1, rf_close__doc__},
241 {NULL, NULL} /* sentinel */
244 /* ---------- */
247 static rfobject *
248 newrfobject()
250 rfobject *self;
252 self = PyObject_NEW(rfobject, &Rftype);
253 if (self == NULL)
254 return NULL;
255 self->isclosed = 1;
256 return self;
260 static void
261 rf_dealloc(self)
262 rfobject *self;
264 do_close(self);
265 PyMem_DEL(self);
268 static PyObject *
269 rf_getattr(self, name)
270 rfobject *self;
271 char *name;
273 return Py_FindMethod(rf_methods, (PyObject *)self, name);
276 static char Rftype__doc__[] =
277 "Resource fork file object"
280 static PyTypeObject Rftype = {
281 PyObject_HEAD_INIT(&PyType_Type)
282 0, /*ob_size*/
283 "ResourceFork", /*tp_name*/
284 sizeof(rfobject), /*tp_basicsize*/
285 0, /*tp_itemsize*/
286 /* methods */
287 (destructor)rf_dealloc, /*tp_dealloc*/
288 (printfunc)0, /*tp_print*/
289 (getattrfunc)rf_getattr, /*tp_getattr*/
290 (setattrfunc)0, /*tp_setattr*/
291 (cmpfunc)0, /*tp_compare*/
292 (reprfunc)0, /*tp_repr*/
293 0, /*tp_as_number*/
294 0, /*tp_as_sequence*/
295 0, /*tp_as_mapping*/
296 (hashfunc)0, /*tp_hash*/
297 (ternaryfunc)0, /*tp_call*/
298 (reprfunc)0, /*tp_str*/
300 /* Space for future expansion */
301 0L,0L,0L,0L,
302 Rftype__doc__ /* Documentation string */
305 /* End of code for Resource fork objects */
306 /* -------------------------------------------------------- */
308 /*----------------------------------------------------------------------*/
309 /* Miscellaneous File System Operations */
311 static char getcrtp_doc[] = "Obsolete, use macfs module";
313 static PyObject *
314 MacOS_GetCreatorAndType(PyObject *self, PyObject *args)
316 FSSpec fss;
317 FInfo info;
318 PyObject *creator, *type, *res;
319 OSErr err;
321 if (!PyArg_ParseTuple(args, "O&", PyMac_GetFSSpec, &fss))
322 return NULL;
323 if ((err = FSpGetFInfo(&fss, &info)) != noErr)
324 return PyErr_Mac(MacOS_Error, err);
325 creator = PyString_FromStringAndSize((char *)&info.fdCreator, 4);
326 type = PyString_FromStringAndSize((char *)&info.fdType, 4);
327 res = Py_BuildValue("OO", creator, type);
328 Py_DECREF(creator);
329 Py_DECREF(type);
330 return res;
333 static char setcrtp_doc[] = "Obsolete, use macfs module";
335 static PyObject *
336 MacOS_SetCreatorAndType(PyObject *self, PyObject *args)
338 FSSpec fss;
339 ResType creator, type;
340 FInfo info;
341 OSErr err;
343 if (!PyArg_ParseTuple(args, "O&O&O&",
344 PyMac_GetFSSpec, &fss, PyMac_GetOSType, &creator, PyMac_GetOSType, &type))
345 return NULL;
346 if ((err = FSpGetFInfo(&fss, &info)) != noErr)
347 return PyErr_Mac(MacOS_Error, err);
348 info.fdCreator = creator;
349 info.fdType = type;
350 if ((err = FSpSetFInfo(&fss, &info)) != noErr)
351 return PyErr_Mac(MacOS_Error, err);
352 Py_INCREF(Py_None);
353 return Py_None;
356 /*----------------------------------------------------------------------*/
357 /* STDWIN High Level Event interface */
359 #include <EPPC.h>
360 #include <Events.h>
362 #if !TARGET_API_MAC_CARBON
363 static char accepthle_doc[] = "Get arguments of pending high-level event";
365 static PyObject *
366 MacOS_AcceptHighLevelEvent(self, args)
367 PyObject *self;
368 PyObject *args;
370 TargetID sender;
371 unsigned long refcon;
372 Ptr buf;
373 unsigned long len;
374 OSErr err;
375 PyObject *res;
377 buf = NULL;
378 len = 0;
379 err = AcceptHighLevelEvent(&sender, &refcon, buf, &len);
380 if (err == bufferIsSmall) {
381 buf = malloc(len);
382 if (buf == NULL)
383 return PyErr_NoMemory();
384 err = AcceptHighLevelEvent(&sender, &refcon, buf, &len);
385 if (err != noErr) {
386 free(buf);
387 return PyErr_Mac(MacOS_Error, (int)err);
390 else if (err != noErr)
391 return PyErr_Mac(MacOS_Error, (int)err);
392 res = Py_BuildValue("s#ls#",
393 (char *)&sender, (int)(sizeof sender), refcon, (char *)buf, (int)len);
394 free(buf);
395 return res;
397 #endif
398 static char schedparams_doc[] = "Set/return mainloop interrupt check flag, etc";
401 ** Set scheduler parameters
403 static PyObject *
404 MacOS_SchedParams(PyObject *self, PyObject *args)
406 PyMacSchedParams old, new;
408 PyMac_GetSchedParams(&old);
409 new = old;
410 if (!PyArg_ParseTuple(args, "|iiidd", &new.check_interrupt, &new.process_events,
411 &new.besocial, &new.check_interval, &new.bg_yield))
412 return NULL;
413 PyMac_SetSchedParams(&new);
414 return Py_BuildValue("iiidd", old.check_interrupt, old.process_events,
415 old.besocial, old.check_interval, old.bg_yield);
418 static char appswitch_doc[] = "Obsolete, use SchedParams";
420 /* Obsolete, for backward compatability */
421 static PyObject *
422 MacOS_EnableAppswitch(PyObject *self, PyObject *args)
424 int new, old;
425 PyMacSchedParams schp;
427 if (!PyArg_ParseTuple(args, "i", &new))
428 return NULL;
429 PyMac_GetSchedParams(&schp);
430 if ( schp.process_events )
431 old = 1;
432 else if ( schp.check_interrupt )
433 old = 0;
434 else
435 old = -1;
436 if ( new > 0 ) {
437 schp.process_events = mDownMask|keyDownMask|osMask;
438 schp.check_interrupt = 1;
439 } else if ( new == 0 ) {
440 schp.process_events = 0;
441 schp.check_interrupt = 1;
442 } else {
443 schp.process_events = 0;
444 schp.check_interrupt = 0;
446 PyMac_SetSchedParams(&schp);
447 return Py_BuildValue("i", old);
450 static char setevh_doc[] = "Set python event handler to be called in mainloop";
452 static PyObject *
453 MacOS_SetEventHandler(self, args)
454 PyObject *self;
455 PyObject *args;
457 PyObject *evh = NULL;
459 if (!PyArg_ParseTuple(args, "|O", &evh))
460 return NULL;
461 if (evh == Py_None)
462 evh = NULL;
463 if ( evh && !PyCallable_Check(evh) ) {
464 PyErr_SetString(PyExc_ValueError, "SetEventHandler argument must be callable");
465 return NULL;
467 if ( !PyMac_SetEventHandler(evh) )
468 return NULL;
469 Py_INCREF(Py_None);
470 return Py_None;
473 static char handleev_doc[] = "Pass event to other interested parties like sioux";
475 static PyObject *
476 MacOS_HandleEvent(PyObject *self, PyObject *args)
478 EventRecord ev;
480 if (!PyArg_ParseTuple(args, "O&", PyMac_GetEventRecord, &ev))
481 return NULL;
482 PyMac_HandleEventIntern(&ev);
483 Py_INCREF(Py_None);
484 return Py_None;
487 static char geterr_doc[] = "Convert OSErr number to string";
489 static PyObject *
490 MacOS_GetErrorString(PyObject *self, PyObject *args)
492 int errn;
494 if (!PyArg_ParseTuple(args, "i", &errn))
495 return NULL;
496 return Py_BuildValue("s", PyMac_StrError(errn));
499 static char splash_doc[] = "Open a splash-screen dialog by resource-id (0=close)";
501 static PyObject *
502 MacOS_splash(PyObject *self, PyObject *args)
504 int resid = -1;
505 static DialogPtr curdialog = NULL;
506 DialogPtr olddialog;
507 WindowRef theWindow;
508 CGrafPtr thePort;
509 #if 0
510 short xpos, ypos, width, height, swidth, sheight;
511 #endif
513 if (!PyArg_ParseTuple(args, "|i", &resid))
514 return NULL;
515 olddialog = curdialog;
516 curdialog = NULL;
518 if ( resid != -1 ) {
519 curdialog = GetNewDialog(resid, NULL, (WindowPtr)-1);
520 if ( curdialog ) {
521 theWindow = GetDialogWindow(curdialog);
522 thePort = GetWindowPort(theWindow);
523 #if 0
524 width = thePort->portRect.right - thePort->portRect.left;
525 height = thePort->portRect.bottom - thePort->portRect.top;
526 swidth = qd.screenBits.bounds.right - qd.screenBits.bounds.left;
527 sheight = qd.screenBits.bounds.bottom - qd.screenBits.bounds.top - LMGetMBarHeight();
528 xpos = (swidth-width)/2;
529 ypos = (sheight-height)/5 + LMGetMBarHeight();
530 MoveWindow(theWindow, xpos, ypos, 0);
531 ShowWindow(theWindow);
532 #endif
533 DrawDialog(curdialog);
536 if (olddialog)
537 DisposeDialog(olddialog);
538 Py_INCREF(Py_None);
539 return Py_None;
542 static char DebugStr_doc[] = "Switch to low-level debugger with a message";
544 static PyObject *
545 MacOS_DebugStr(PyObject *self, PyObject *args)
547 Str255 message;
548 PyObject *object = 0;
550 if (!PyArg_ParseTuple(args, "O&|O", PyMac_GetStr255, message, &object))
551 return NULL;
552 DebugStr(message);
553 Py_INCREF(Py_None);
554 return Py_None;
557 static char SysBeep_doc[] = "BEEEEEP!!!";
559 static PyObject *
560 MacOS_SysBeep(PyObject *self, PyObject *args)
562 int duration = 6;
564 if (!PyArg_ParseTuple(args, "|i", &duration))
565 return NULL;
566 SysBeep(duration);
567 Py_INCREF(Py_None);
568 return Py_None;
571 static char GetTicks_doc[] = "Return number of ticks since bootup";
573 static PyObject *
574 MacOS_GetTicks(PyObject *self, PyObject *args)
576 return Py_BuildValue("i", (int)TickCount());
579 static char openrf_doc[] = "Open resource fork of a file";
581 static PyObject *
582 MacOS_openrf(PyObject *self, PyObject *args)
584 OSErr err;
585 char *mode = "r";
586 FSSpec fss;
587 SignedByte permission = 1;
588 rfobject *fp;
590 if (!PyArg_ParseTuple(args, "O&|s", PyMac_GetFSSpec, &fss, &mode))
591 return NULL;
592 while (*mode) {
593 switch (*mode++) {
594 case '*': break;
595 case 'r': permission = 1; break;
596 case 'w': permission = 2; break;
597 case 'b': break;
598 default:
599 PyErr_BadArgument();
600 return NULL;
604 if ( (fp = newrfobject()) == NULL )
605 return NULL;
607 err = HOpenRF(fss.vRefNum, fss.parID, fss.name, permission, &fp->fRefNum);
609 if ( err == fnfErr ) {
610 /* In stead of doing complicated things here to get creator/type
611 ** correct we let the standard i/o library handle it
613 FILE *tfp;
614 char pathname[257];
616 if ( err=PyMac_GetFullPath(&fss, pathname) ) {
617 PyMac_Error(err);
618 Py_DECREF(fp);
619 return NULL;
622 if ( (tfp = fopen(pathname, "w")) == NULL ) {
623 PyMac_Error(fnfErr); /* What else... */
624 Py_DECREF(fp);
625 return NULL;
627 fclose(tfp);
628 err = HOpenRF(fss.vRefNum, fss.parID, fss.name, permission, &fp->fRefNum);
630 if ( err ) {
631 Py_DECREF(fp);
632 PyMac_Error(err);
633 return NULL;
635 fp->isclosed = 0;
636 return (PyObject *)fp;
639 static char FreeMem_doc[] = "Return the total amount of free space in the heap";
641 static PyObject *
642 MacOS_FreeMem(PyObject *self, PyObject *args)
644 long rv;
646 if (!PyArg_ParseTuple(args, ""))
647 return NULL;
648 rv = FreeMem();
649 return Py_BuildValue("l", rv);
652 static char MaxBlock_doc[] = "Return the largest contiguous block of free space in the heap";
654 static PyObject *
655 MacOS_MaxBlock(PyObject *self, PyObject *args)
657 long rv;
659 if (!PyArg_ParseTuple(args, ""))
660 return NULL;
661 rv = MaxBlock();
662 return Py_BuildValue("l", rv);
665 static char CompactMem_doc[] = "(wanted size)->actual largest block after compacting";
667 static PyObject *
668 MacOS_CompactMem(PyObject *self, PyObject *args)
670 long value;
671 long rv;
673 if (!PyArg_ParseTuple(args, "l", &value))
674 return NULL;
675 rv = CompactMem(value);
676 return Py_BuildValue("l", rv);
679 static PyMethodDef MacOS_Methods[] = {
680 #if !TARGET_API_MAC_CARBON
681 {"AcceptHighLevelEvent", MacOS_AcceptHighLevelEvent, 1, accepthle_doc},
682 #endif
683 {"GetCreatorAndType", MacOS_GetCreatorAndType, 1, getcrtp_doc},
684 {"SetCreatorAndType", MacOS_SetCreatorAndType, 1, setcrtp_doc},
685 {"SchedParams", MacOS_SchedParams, 1, schedparams_doc},
686 {"EnableAppswitch", MacOS_EnableAppswitch, 1, appswitch_doc},
687 {"SetEventHandler", MacOS_SetEventHandler, 1, setevh_doc},
688 {"HandleEvent", MacOS_HandleEvent, 1, handleev_doc},
689 {"GetErrorString", MacOS_GetErrorString, 1, geterr_doc},
690 {"openrf", MacOS_openrf, 1, openrf_doc},
691 {"splash", MacOS_splash, 1, splash_doc},
692 {"DebugStr", MacOS_DebugStr, 1, DebugStr_doc},
693 {"GetTicks", MacOS_GetTicks, 1, GetTicks_doc},
694 {"SysBeep", MacOS_SysBeep, 1, SysBeep_doc},
695 {"FreeMem", MacOS_FreeMem, 1, FreeMem_doc},
696 {"MaxBlock", MacOS_MaxBlock, 1, MaxBlock_doc},
697 {"CompactMem", MacOS_CompactMem, 1, CompactMem_doc},
698 {NULL, NULL} /* Sentinel */
702 void
703 initMacOS()
705 PyObject *m, *d;
707 m = Py_InitModule("MacOS", MacOS_Methods);
708 d = PyModule_GetDict(m);
710 /* Initialize MacOS.Error exception */
711 MacOS_Error = PyMac_GetOSErrException();
712 if (MacOS_Error == NULL || PyDict_SetItemString(d, "Error", MacOS_Error) != 0)
713 return;
714 Rftype.ob_type = &PyType_Type;
715 Py_INCREF(&Rftype);
716 if (PyDict_SetItemString(d, "ResourceForkType", (PyObject *)&Rftype) != 0)
717 return;
719 ** This is a hack: the following constant added to the id() of a string
720 ** object gives you the address of the data. Unfortunately, it is needed for
721 ** some of the image and sound processing interfaces on the mac:-(
724 PyStringObject *p = 0;
725 long off = (long)&(p->ob_sval[0]);
727 if( PyDict_SetItemString(d, "string_id_to_buffer", Py_BuildValue("i", off)) != 0)
728 return;
730 if (PyDict_SetItemString(d, "AppearanceCompliant",
731 Py_BuildValue("i", PyMac_AppearanceCompliant)) != 0)
732 return;