Apparently the code to forestall Tk eating events was too aggressive (Tk user input...
[python/dscho.git] / Mac / Modules / macosmodule.c
blob6fe0bd0904415e5420f0cefc95c63d3ec47785c7
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"
29 #include "pythonresources.h"
31 #include <Windows.h>
32 #include <Files.h>
33 #include <LowMem.h>
34 #include <Sound.h>
35 #include <Events.h>
37 static PyObject *MacOS_Error; /* Exception MacOS.Error */
39 #ifdef MPW
40 #define bufferIsSmall -607 /*error returns from Post and Accept */
41 #endif
43 static PyObject *ErrorObject;
45 /* ----------------------------------------------------- */
47 /* Declarations for objects of type Resource fork */
49 typedef struct {
50 PyObject_HEAD
51 short fRefNum;
52 int isclosed;
53 } rfobject;
55 staticforward PyTypeObject Rftype;
59 /* ---------------------------------------------------------------- */
61 static void
62 do_close(self)
63 rfobject *self;
65 if (self->isclosed ) return;
66 (void)FSClose(self->fRefNum);
67 self->isclosed = 1;
70 static char rf_read__doc__[] =
71 "Read data from resource fork"
74 static PyObject *
75 rf_read(self, args)
76 rfobject *self;
77 PyObject *args;
79 long n;
80 PyObject *v;
81 OSErr err;
83 if (self->isclosed) {
84 PyErr_SetString(PyExc_ValueError, "Operation on closed file");
85 return NULL;
88 if (!PyArg_ParseTuple(args, "l", &n))
89 return NULL;
91 v = PyString_FromStringAndSize((char *)NULL, n);
92 if (v == NULL)
93 return NULL;
95 err = FSRead(self->fRefNum, &n, PyString_AsString(v));
96 if (err && err != eofErr) {
97 PyMac_Error(err);
98 Py_DECREF(v);
99 return NULL;
101 _PyString_Resize(&v, n);
102 return v;
106 static char rf_write__doc__[] =
107 "Write to resource fork"
110 static PyObject *
111 rf_write(self, args)
112 rfobject *self;
113 PyObject *args;
115 char *buffer;
116 long size;
117 OSErr err;
119 if (self->isclosed) {
120 PyErr_SetString(PyExc_ValueError, "Operation on closed file");
121 return NULL;
123 if (!PyArg_ParseTuple(args, "s#", &buffer, &size))
124 return NULL;
125 err = FSWrite(self->fRefNum, &size, buffer);
126 if (err) {
127 PyMac_Error(err);
128 return NULL;
130 Py_INCREF(Py_None);
131 return Py_None;
135 static char rf_seek__doc__[] =
136 "Set file position"
139 static PyObject *
140 rf_seek(self, args)
141 rfobject *self;
142 PyObject *args;
144 long amount, pos;
145 int whence = SEEK_SET;
146 long eof;
147 OSErr err;
149 if (self->isclosed) {
150 PyErr_SetString(PyExc_ValueError, "Operation on closed file");
151 return NULL;
153 if (!PyArg_ParseTuple(args, "l|i", &amount, &whence))
154 return NULL;
156 if ( err = GetEOF(self->fRefNum, &eof))
157 goto ioerr;
159 switch (whence) {
160 case SEEK_CUR:
161 if (err = GetFPos(self->fRefNum, &pos))
162 goto ioerr;
163 break;
164 case SEEK_END:
165 pos = eof;
166 break;
167 case SEEK_SET:
168 pos = 0;
169 break;
170 default:
171 PyErr_BadArgument();
172 return NULL;
175 pos += amount;
177 /* Don't bother implementing seek past EOF */
178 if (pos > eof || pos < 0) {
179 PyErr_BadArgument();
180 return NULL;
183 if ( err = SetFPos(self->fRefNum, fsFromStart, pos) ) {
184 ioerr:
185 PyMac_Error(err);
186 return NULL;
188 Py_INCREF(Py_None);
189 return Py_None;
193 static char rf_tell__doc__[] =
194 "Get file position"
197 static PyObject *
198 rf_tell(self, args)
199 rfobject *self;
200 PyObject *args;
202 long where;
203 OSErr err;
205 if (self->isclosed) {
206 PyErr_SetString(PyExc_ValueError, "Operation on closed file");
207 return NULL;
209 if (!PyArg_ParseTuple(args, ""))
210 return NULL;
211 if ( err = GetFPos(self->fRefNum, &where) ) {
212 PyMac_Error(err);
213 return NULL;
215 return PyInt_FromLong(where);
218 static char rf_close__doc__[] =
219 "Close resource fork"
222 static PyObject *
223 rf_close(self, args)
224 rfobject *self;
225 PyObject *args;
227 if (!PyArg_ParseTuple(args, ""))
228 return NULL;
229 do_close(self);
230 Py_INCREF(Py_None);
231 return Py_None;
235 static struct PyMethodDef rf_methods[] = {
236 {"read", rf_read, 1, rf_read__doc__},
237 {"write", rf_write, 1, rf_write__doc__},
238 {"seek", rf_seek, 1, rf_seek__doc__},
239 {"tell", rf_tell, 1, rf_tell__doc__},
240 {"close", rf_close, 1, rf_close__doc__},
242 {NULL, NULL} /* sentinel */
245 /* ---------- */
248 static rfobject *
249 newrfobject()
251 rfobject *self;
253 self = PyObject_NEW(rfobject, &Rftype);
254 if (self == NULL)
255 return NULL;
256 self->isclosed = 1;
257 return self;
261 static void
262 rf_dealloc(self)
263 rfobject *self;
265 do_close(self);
266 PyMem_DEL(self);
269 static PyObject *
270 rf_getattr(self, name)
271 rfobject *self;
272 char *name;
274 return Py_FindMethod(rf_methods, (PyObject *)self, name);
277 static char Rftype__doc__[] =
278 "Resource fork file object"
281 static PyTypeObject Rftype = {
282 PyObject_HEAD_INIT(&PyType_Type)
283 0, /*ob_size*/
284 "ResourceFork", /*tp_name*/
285 sizeof(rfobject), /*tp_basicsize*/
286 0, /*tp_itemsize*/
287 /* methods */
288 (destructor)rf_dealloc, /*tp_dealloc*/
289 (printfunc)0, /*tp_print*/
290 (getattrfunc)rf_getattr, /*tp_getattr*/
291 (setattrfunc)0, /*tp_setattr*/
292 (cmpfunc)0, /*tp_compare*/
293 (reprfunc)0, /*tp_repr*/
294 0, /*tp_as_number*/
295 0, /*tp_as_sequence*/
296 0, /*tp_as_mapping*/
297 (hashfunc)0, /*tp_hash*/
298 (ternaryfunc)0, /*tp_call*/
299 (reprfunc)0, /*tp_str*/
301 /* Space for future expansion */
302 0L,0L,0L,0L,
303 Rftype__doc__ /* Documentation string */
306 /* End of code for Resource fork objects */
307 /* -------------------------------------------------------- */
309 /*----------------------------------------------------------------------*/
310 /* Miscellaneous File System Operations */
312 static char getcrtp_doc[] = "Obsolete, use macfs module";
314 static PyObject *
315 MacOS_GetCreatorAndType(PyObject *self, PyObject *args)
317 FSSpec fss;
318 FInfo info;
319 PyObject *creator, *type, *res;
320 OSErr err;
322 if (!PyArg_ParseTuple(args, "O&", PyMac_GetFSSpec, &fss))
323 return NULL;
324 if ((err = FSpGetFInfo(&fss, &info)) != noErr)
325 return PyErr_Mac(MacOS_Error, err);
326 creator = PyString_FromStringAndSize((char *)&info.fdCreator, 4);
327 type = PyString_FromStringAndSize((char *)&info.fdType, 4);
328 res = Py_BuildValue("OO", creator, type);
329 Py_DECREF(creator);
330 Py_DECREF(type);
331 return res;
334 static char setcrtp_doc[] = "Obsolete, use macfs module";
336 static PyObject *
337 MacOS_SetCreatorAndType(PyObject *self, PyObject *args)
339 FSSpec fss;
340 ResType creator, type;
341 FInfo info;
342 OSErr err;
344 if (!PyArg_ParseTuple(args, "O&O&O&",
345 PyMac_GetFSSpec, &fss, PyMac_GetOSType, &creator, PyMac_GetOSType, &type))
346 return NULL;
347 if ((err = FSpGetFInfo(&fss, &info)) != noErr)
348 return PyErr_Mac(MacOS_Error, err);
349 info.fdCreator = creator;
350 info.fdType = type;
351 if ((err = FSpSetFInfo(&fss, &info)) != noErr)
352 return PyErr_Mac(MacOS_Error, err);
353 Py_INCREF(Py_None);
354 return Py_None;
357 /*----------------------------------------------------------------------*/
358 /* STDWIN High Level Event interface */
360 #include <EPPC.h>
361 #include <Events.h>
363 #if !TARGET_API_MAC_CARBON
364 static char accepthle_doc[] = "Get arguments of pending high-level event";
366 static PyObject *
367 MacOS_AcceptHighLevelEvent(self, args)
368 PyObject *self;
369 PyObject *args;
371 TargetID sender;
372 unsigned long refcon;
373 Ptr buf;
374 unsigned long len;
375 OSErr err;
376 PyObject *res;
378 buf = NULL;
379 len = 0;
380 err = AcceptHighLevelEvent(&sender, &refcon, buf, &len);
381 if (err == bufferIsSmall) {
382 buf = malloc(len);
383 if (buf == NULL)
384 return PyErr_NoMemory();
385 err = AcceptHighLevelEvent(&sender, &refcon, buf, &len);
386 if (err != noErr) {
387 free(buf);
388 return PyErr_Mac(MacOS_Error, (int)err);
391 else if (err != noErr)
392 return PyErr_Mac(MacOS_Error, (int)err);
393 res = Py_BuildValue("s#ls#",
394 (char *)&sender, (int)(sizeof sender), refcon, (char *)buf, (int)len);
395 free(buf);
396 return res;
398 #endif
399 static char schedparams_doc[] = "Set/return mainloop interrupt check flag, etc";
402 ** Set scheduler parameters
404 static PyObject *
405 MacOS_SchedParams(PyObject *self, PyObject *args)
407 PyMacSchedParams old, new;
409 PyMac_GetSchedParams(&old);
410 new = old;
411 if (!PyArg_ParseTuple(args, "|iiidd", &new.check_interrupt, &new.process_events,
412 &new.besocial, &new.check_interval, &new.bg_yield))
413 return NULL;
414 PyMac_SetSchedParams(&new);
415 return Py_BuildValue("iiidd", old.check_interrupt, old.process_events,
416 old.besocial, old.check_interval, old.bg_yield);
419 static char appswitch_doc[] = "Obsolete, use SchedParams";
421 /* Obsolete, for backward compatability */
422 static PyObject *
423 MacOS_EnableAppswitch(PyObject *self, PyObject *args)
425 int new, old;
426 PyMacSchedParams schp;
428 if (!PyArg_ParseTuple(args, "i", &new))
429 return NULL;
430 PyMac_GetSchedParams(&schp);
431 if ( schp.process_events )
432 old = 1;
433 else if ( schp.check_interrupt )
434 old = 0;
435 else
436 old = -1;
437 if ( new > 0 ) {
438 schp.process_events = mDownMask|keyDownMask|osMask;
439 schp.check_interrupt = 1;
440 } else if ( new == 0 ) {
441 schp.process_events = 0;
442 schp.check_interrupt = 1;
443 } else {
444 schp.process_events = 0;
445 schp.check_interrupt = 0;
447 PyMac_SetSchedParams(&schp);
448 return Py_BuildValue("i", old);
451 static char setevh_doc[] = "Set python event handler to be called in mainloop";
453 static PyObject *
454 MacOS_SetEventHandler(self, args)
455 PyObject *self;
456 PyObject *args;
458 PyObject *evh = NULL;
460 if (!PyArg_ParseTuple(args, "|O", &evh))
461 return NULL;
462 if (evh == Py_None)
463 evh = NULL;
464 if ( evh && !PyCallable_Check(evh) ) {
465 PyErr_SetString(PyExc_ValueError, "SetEventHandler argument must be callable");
466 return NULL;
468 if ( !PyMac_SetEventHandler(evh) )
469 return NULL;
470 Py_INCREF(Py_None);
471 return Py_None;
474 static char handleev_doc[] = "Pass event to other interested parties like sioux";
476 static PyObject *
477 MacOS_HandleEvent(PyObject *self, PyObject *args)
479 EventRecord ev;
481 if (!PyArg_ParseTuple(args, "O&", PyMac_GetEventRecord, &ev))
482 return NULL;
483 PyMac_HandleEventIntern(&ev);
484 Py_INCREF(Py_None);
485 return Py_None;
488 static char geterr_doc[] = "Convert OSErr number to string";
490 static PyObject *
491 MacOS_GetErrorString(PyObject *self, PyObject *args)
493 int errn;
495 if (!PyArg_ParseTuple(args, "i", &errn))
496 return NULL;
497 return Py_BuildValue("s", PyMac_StrError(errn));
500 static char splash_doc[] = "Open a splash-screen dialog by resource-id (0=close)";
502 static PyObject *
503 MacOS_splash(PyObject *self, PyObject *args)
505 int resid = -1;
506 static DialogPtr curdialog = NULL;
507 DialogPtr olddialog;
508 WindowRef theWindow;
509 CGrafPtr thePort;
510 #if 0
511 short xpos, ypos, width, height, swidth, sheight;
512 #endif
514 if (!PyArg_ParseTuple(args, "|i", &resid))
515 return NULL;
516 olddialog = curdialog;
517 curdialog = NULL;
519 if ( resid != -1 ) {
520 curdialog = GetNewDialog(resid, NULL, (WindowPtr)-1);
521 if ( curdialog ) {
522 theWindow = GetDialogWindow(curdialog);
523 thePort = GetWindowPort(theWindow);
524 #if 0
525 width = thePort->portRect.right - thePort->portRect.left;
526 height = thePort->portRect.bottom - thePort->portRect.top;
527 swidth = qd.screenBits.bounds.right - qd.screenBits.bounds.left;
528 sheight = qd.screenBits.bounds.bottom - qd.screenBits.bounds.top - LMGetMBarHeight();
529 xpos = (swidth-width)/2;
530 ypos = (sheight-height)/5 + LMGetMBarHeight();
531 MoveWindow(theWindow, xpos, ypos, 0);
532 ShowWindow(theWindow);
533 #endif
534 DrawDialog(curdialog);
537 if (olddialog)
538 DisposeDialog(olddialog);
539 Py_INCREF(Py_None);
540 return Py_None;
543 static char DebugStr_doc[] = "Switch to low-level debugger with a message";
545 static PyObject *
546 MacOS_DebugStr(PyObject *self, PyObject *args)
548 Str255 message;
549 PyObject *object = 0;
551 if (!PyArg_ParseTuple(args, "O&|O", PyMac_GetStr255, message, &object))
552 return NULL;
553 DebugStr(message);
554 Py_INCREF(Py_None);
555 return Py_None;
558 static char SysBeep_doc[] = "BEEEEEP!!!";
560 static PyObject *
561 MacOS_SysBeep(PyObject *self, PyObject *args)
563 int duration = 6;
565 if (!PyArg_ParseTuple(args, "|i", &duration))
566 return NULL;
567 SysBeep(duration);
568 Py_INCREF(Py_None);
569 return Py_None;
572 static char GetTicks_doc[] = "Return number of ticks since bootup";
574 static PyObject *
575 MacOS_GetTicks(PyObject *self, PyObject *args)
577 return Py_BuildValue("i", (int)TickCount());
580 static char openrf_doc[] = "Open resource fork of a file";
582 static PyObject *
583 MacOS_openrf(PyObject *self, PyObject *args)
585 OSErr err;
586 char *mode = "r";
587 FSSpec fss;
588 SignedByte permission = 1;
589 rfobject *fp;
591 if (!PyArg_ParseTuple(args, "O&|s", PyMac_GetFSSpec, &fss, &mode))
592 return NULL;
593 while (*mode) {
594 switch (*mode++) {
595 case '*': break;
596 case 'r': permission = 1; break;
597 case 'w': permission = 2; break;
598 case 'b': break;
599 default:
600 PyErr_BadArgument();
601 return NULL;
605 if ( (fp = newrfobject()) == NULL )
606 return NULL;
608 err = HOpenRF(fss.vRefNum, fss.parID, fss.name, permission, &fp->fRefNum);
610 if ( err == fnfErr ) {
611 /* In stead of doing complicated things here to get creator/type
612 ** correct we let the standard i/o library handle it
614 FILE *tfp;
615 char pathname[257];
617 if ( err=PyMac_GetFullPath(&fss, pathname) ) {
618 PyMac_Error(err);
619 Py_DECREF(fp);
620 return NULL;
623 if ( (tfp = fopen(pathname, "w")) == NULL ) {
624 PyMac_Error(fnfErr); /* What else... */
625 Py_DECREF(fp);
626 return NULL;
628 fclose(tfp);
629 err = HOpenRF(fss.vRefNum, fss.parID, fss.name, permission, &fp->fRefNum);
631 if ( err ) {
632 Py_DECREF(fp);
633 PyMac_Error(err);
634 return NULL;
636 fp->isclosed = 0;
637 return (PyObject *)fp;
640 static char FreeMem_doc[] = "Return the total amount of free space in the heap";
642 static PyObject *
643 MacOS_FreeMem(PyObject *self, PyObject *args)
645 long rv;
647 if (!PyArg_ParseTuple(args, ""))
648 return NULL;
649 rv = FreeMem();
650 return Py_BuildValue("l", rv);
653 static char MaxBlock_doc[] = "Return the largest contiguous block of free space in the heap";
655 static PyObject *
656 MacOS_MaxBlock(PyObject *self, PyObject *args)
658 long rv;
660 if (!PyArg_ParseTuple(args, ""))
661 return NULL;
662 rv = MaxBlock();
663 return Py_BuildValue("l", rv);
666 static char CompactMem_doc[] = "(wanted size)->actual largest block after compacting";
668 static PyObject *
669 MacOS_CompactMem(PyObject *self, PyObject *args)
671 long value;
672 long rv;
674 if (!PyArg_ParseTuple(args, "l", &value))
675 return NULL;
676 rv = CompactMem(value);
677 return Py_BuildValue("l", rv);
680 static char KeepConsole_doc[] = "(flag) Keep console open 0:never, 1:on output 2:on error, 3:always";
682 static PyObject *
683 MacOS_KeepConsole(PyObject *self, PyObject *args)
685 int value;
687 if (!PyArg_ParseTuple(args, "i", &value))
688 return NULL;
689 PyMac_options.keep_console = value;
690 Py_INCREF(Py_None);
691 return Py_None;
694 static char OutputSeen_doc[] = "Call to reset the 'unseen output' flag for the keep-console-open option";
696 static PyObject *
697 MacOS_OutputSeen(PyObject *self, PyObject *args)
699 if (!PyArg_ParseTuple(args, ""))
700 return NULL;
701 PyMac_OutputSeen();
702 Py_INCREF(Py_None);
703 return Py_None;
706 static PyMethodDef MacOS_Methods[] = {
707 #if !TARGET_API_MAC_CARBON
708 {"AcceptHighLevelEvent", MacOS_AcceptHighLevelEvent, 1, accepthle_doc},
709 #endif
710 {"GetCreatorAndType", MacOS_GetCreatorAndType, 1, getcrtp_doc},
711 {"SetCreatorAndType", MacOS_SetCreatorAndType, 1, setcrtp_doc},
712 {"SchedParams", MacOS_SchedParams, 1, schedparams_doc},
713 {"EnableAppswitch", MacOS_EnableAppswitch, 1, appswitch_doc},
714 {"SetEventHandler", MacOS_SetEventHandler, 1, setevh_doc},
715 {"HandleEvent", MacOS_HandleEvent, 1, handleev_doc},
716 {"GetErrorString", MacOS_GetErrorString, 1, geterr_doc},
717 {"openrf", MacOS_openrf, 1, openrf_doc},
718 {"splash", MacOS_splash, 1, splash_doc},
719 {"DebugStr", MacOS_DebugStr, 1, DebugStr_doc},
720 {"GetTicks", MacOS_GetTicks, 1, GetTicks_doc},
721 {"SysBeep", MacOS_SysBeep, 1, SysBeep_doc},
722 {"FreeMem", MacOS_FreeMem, 1, FreeMem_doc},
723 {"MaxBlock", MacOS_MaxBlock, 1, MaxBlock_doc},
724 {"CompactMem", MacOS_CompactMem, 1, CompactMem_doc},
725 {"KeepConsole", MacOS_KeepConsole, 1, KeepConsole_doc},
726 {"OutputSeen", MacOS_OutputSeen, 1, OutputSeen_doc},
727 {NULL, NULL} /* Sentinel */
731 void
732 initMacOS()
734 PyObject *m, *d;
736 m = Py_InitModule("MacOS", MacOS_Methods);
737 d = PyModule_GetDict(m);
739 /* Initialize MacOS.Error exception */
740 MacOS_Error = PyMac_GetOSErrException();
741 if (MacOS_Error == NULL || PyDict_SetItemString(d, "Error", MacOS_Error) != 0)
742 return;
743 Rftype.ob_type = &PyType_Type;
744 Py_INCREF(&Rftype);
745 if (PyDict_SetItemString(d, "ResourceForkType", (PyObject *)&Rftype) != 0)
746 return;
748 ** This is a hack: the following constant added to the id() of a string
749 ** object gives you the address of the data. Unfortunately, it is needed for
750 ** some of the image and sound processing interfaces on the mac:-(
753 PyStringObject *p = 0;
754 long off = (long)&(p->ob_sval[0]);
756 if( PyDict_SetItemString(d, "string_id_to_buffer", Py_BuildValue("i", off)) != 0)
757 return;
759 if (PyDict_SetItemString(d, "AppearanceCompliant",
760 Py_BuildValue("i", PyMac_AppearanceCompliant)) != 0)
761 return;
762 #if TARGET_API_MAC_CARBON
763 /* Will need a different name for MachO-carbon later (macho?) */
764 #define PY_RUNTIMEMODEL "carbon"
765 #else
766 #define PY_RUNTIMEMODEL "ppc"
767 #endif
768 if (PyDict_SetItemString(d, "runtimemodel",
769 Py_BuildValue("s", PY_RUNTIMEMODEL)) != 0)
770 return;