append(): Fixing the test for convertability after consultation with
[python/dscho.git] / Mac / Modules / macosmodule.c
blobdc9a94ff383636272bed1c02df548d44818330c1
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 #ifdef WITHOUT_FRAMEWORKS
32 #include <Windows.h>
33 #include <Files.h>
34 #include <LowMem.h>
35 #include <Sound.h>
36 #include <Events.h>
37 #else
38 #include <Carbon/Carbon.h>
39 #endif
41 static PyObject *MacOS_Error; /* Exception MacOS.Error */
43 #ifdef TARGET_API_MAC_OSX
44 #define PATHNAMELEN 1024
45 #else
46 #define PATHNAMELEN 256
47 #endif
49 #ifdef MPW
50 #define bufferIsSmall -607 /*error returns from Post and Accept */
51 #endif
53 /* ----------------------------------------------------- */
55 /* Declarations for objects of type Resource fork */
57 typedef struct {
58 PyObject_HEAD
59 short fRefNum;
60 int isclosed;
61 } rfobject;
63 static PyTypeObject Rftype;
67 /* ---------------------------------------------------------------- */
69 static void
70 do_close(rfobject *self)
72 if (self->isclosed ) return;
73 (void)FSClose(self->fRefNum);
74 self->isclosed = 1;
77 static char rf_read__doc__[] =
78 "Read data from resource fork"
81 static PyObject *
82 rf_read(rfobject *self, PyObject *args)
84 long n;
85 PyObject *v;
86 OSErr err;
88 if (self->isclosed) {
89 PyErr_SetString(PyExc_ValueError, "Operation on closed file");
90 return NULL;
93 if (!PyArg_ParseTuple(args, "l", &n))
94 return NULL;
96 v = PyString_FromStringAndSize((char *)NULL, n);
97 if (v == NULL)
98 return NULL;
100 err = FSRead(self->fRefNum, &n, PyString_AsString(v));
101 if (err && err != eofErr) {
102 PyMac_Error(err);
103 Py_DECREF(v);
104 return NULL;
106 _PyString_Resize(&v, n);
107 return v;
111 static char rf_write__doc__[] =
112 "Write to resource fork"
115 static PyObject *
116 rf_write(rfobject *self, PyObject *args)
118 char *buffer;
119 long size;
120 OSErr err;
122 if (self->isclosed) {
123 PyErr_SetString(PyExc_ValueError, "Operation on closed file");
124 return NULL;
126 if (!PyArg_ParseTuple(args, "s#", &buffer, &size))
127 return NULL;
128 err = FSWrite(self->fRefNum, &size, buffer);
129 if (err) {
130 PyMac_Error(err);
131 return NULL;
133 Py_INCREF(Py_None);
134 return Py_None;
138 static char rf_seek__doc__[] =
139 "Set file position"
142 static PyObject *
143 rf_seek(rfobject *self, PyObject *args)
145 long amount, pos;
146 int whence = SEEK_SET;
147 long eof;
148 OSErr err;
150 if (self->isclosed) {
151 PyErr_SetString(PyExc_ValueError, "Operation on closed file");
152 return NULL;
154 if (!PyArg_ParseTuple(args, "l|i", &amount, &whence))
155 return NULL;
157 if ((err = GetEOF(self->fRefNum, &eof)))
158 goto ioerr;
160 switch (whence) {
161 case SEEK_CUR:
162 if ((err = GetFPos(self->fRefNum, &pos)))
163 goto ioerr;
164 break;
165 case SEEK_END:
166 pos = eof;
167 break;
168 case SEEK_SET:
169 pos = 0;
170 break;
171 default:
172 PyErr_BadArgument();
173 return NULL;
176 pos += amount;
178 /* Don't bother implementing seek past EOF */
179 if (pos > eof || pos < 0) {
180 PyErr_BadArgument();
181 return NULL;
184 if ((err = SetFPos(self->fRefNum, fsFromStart, pos)) ) {
185 ioerr:
186 PyMac_Error(err);
187 return NULL;
189 Py_INCREF(Py_None);
190 return Py_None;
194 static char rf_tell__doc__[] =
195 "Get file position"
198 static PyObject *
199 rf_tell(rfobject *self, 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(rfobject *self, PyObject *args)
224 if (!PyArg_ParseTuple(args, ""))
225 return NULL;
226 do_close(self);
227 Py_INCREF(Py_None);
228 return Py_None;
232 static struct PyMethodDef rf_methods[] = {
233 {"read", (PyCFunction)rf_read, 1, rf_read__doc__},
234 {"write", (PyCFunction)rf_write, 1, rf_write__doc__},
235 {"seek", (PyCFunction)rf_seek, 1, rf_seek__doc__},
236 {"tell", (PyCFunction)rf_tell, 1, rf_tell__doc__},
237 {"close", (PyCFunction)rf_close, 1, rf_close__doc__},
239 {NULL, NULL} /* sentinel */
242 /* ---------- */
245 static rfobject *
246 newrfobject(void)
248 rfobject *self;
250 self = PyObject_NEW(rfobject, &Rftype);
251 if (self == NULL)
252 return NULL;
253 self->isclosed = 1;
254 return self;
258 static void
259 rf_dealloc(rfobject *self)
261 do_close(self);
262 PyObject_DEL(self);
265 static PyObject *
266 rf_getattr(rfobject *self, char *name)
268 return Py_FindMethod(rf_methods, (PyObject *)self, name);
271 static char Rftype__doc__[] =
272 "Resource fork file object"
275 static PyTypeObject Rftype = {
276 PyObject_HEAD_INIT(&PyType_Type)
277 0, /*ob_size*/
278 "MacOS.ResourceFork", /*tp_name*/
279 sizeof(rfobject), /*tp_basicsize*/
280 0, /*tp_itemsize*/
281 /* methods */
282 (destructor)rf_dealloc, /*tp_dealloc*/
283 (printfunc)0, /*tp_print*/
284 (getattrfunc)rf_getattr, /*tp_getattr*/
285 (setattrfunc)0, /*tp_setattr*/
286 (cmpfunc)0, /*tp_compare*/
287 (reprfunc)0, /*tp_repr*/
288 0, /*tp_as_number*/
289 0, /*tp_as_sequence*/
290 0, /*tp_as_mapping*/
291 (hashfunc)0, /*tp_hash*/
292 (ternaryfunc)0, /*tp_call*/
293 (reprfunc)0, /*tp_str*/
295 /* Space for future expansion */
296 0L,0L,0L,0L,
297 Rftype__doc__ /* Documentation string */
300 /* End of code for Resource fork objects */
301 /* -------------------------------------------------------- */
303 /*----------------------------------------------------------------------*/
304 /* Miscellaneous File System Operations */
306 static char getcrtp_doc[] = "Obsolete, use macfs module";
308 static PyObject *
309 MacOS_GetCreatorAndType(PyObject *self, PyObject *args)
311 FSSpec fss;
312 FInfo info;
313 PyObject *creator, *type, *res;
314 OSErr err;
316 if (!PyArg_ParseTuple(args, "O&", PyMac_GetFSSpec, &fss))
317 return NULL;
318 if ((err = FSpGetFInfo(&fss, &info)) != noErr)
319 return PyErr_Mac(MacOS_Error, err);
320 creator = PyString_FromStringAndSize((char *)&info.fdCreator, 4);
321 type = PyString_FromStringAndSize((char *)&info.fdType, 4);
322 res = Py_BuildValue("OO", creator, type);
323 Py_DECREF(creator);
324 Py_DECREF(type);
325 return res;
328 static char setcrtp_doc[] = "Obsolete, use macfs module";
330 static PyObject *
331 MacOS_SetCreatorAndType(PyObject *self, PyObject *args)
333 FSSpec fss;
334 ResType creator, type;
335 FInfo info;
336 OSErr err;
338 if (!PyArg_ParseTuple(args, "O&O&O&",
339 PyMac_GetFSSpec, &fss, PyMac_GetOSType, &creator, PyMac_GetOSType, &type))
340 return NULL;
341 if ((err = FSpGetFInfo(&fss, &info)) != noErr)
342 return PyErr_Mac(MacOS_Error, err);
343 info.fdCreator = creator;
344 info.fdType = type;
345 if ((err = FSpSetFInfo(&fss, &info)) != noErr)
346 return PyErr_Mac(MacOS_Error, err);
347 Py_INCREF(Py_None);
348 return Py_None;
351 #if TARGET_API_MAC_OS8
352 /*----------------------------------------------------------------------*/
353 /* STDWIN High Level Event interface */
355 #include <EPPC.h>
356 #include <Events.h>
358 static char accepthle_doc[] = "Get arguments of pending high-level event";
360 static PyObject *
361 MacOS_AcceptHighLevelEvent(self, args)
362 PyObject *self;
363 PyObject *args;
365 TargetID sender;
366 unsigned long refcon;
367 Ptr buf;
368 unsigned long len;
369 OSErr err;
370 PyObject *res;
372 buf = NULL;
373 len = 0;
374 err = AcceptHighLevelEvent(&sender, &refcon, buf, &len);
375 if (err == bufferIsSmall) {
376 buf = malloc(len);
377 if (buf == NULL)
378 return PyErr_NoMemory();
379 err = AcceptHighLevelEvent(&sender, &refcon, buf, &len);
380 if (err != noErr) {
381 free(buf);
382 return PyErr_Mac(MacOS_Error, (int)err);
385 else if (err != noErr)
386 return PyErr_Mac(MacOS_Error, (int)err);
387 res = Py_BuildValue("s#ls#",
388 (char *)&sender, (int)(sizeof sender), refcon, (char *)buf, (int)len);
389 free(buf);
390 return res;
392 #endif
394 #if !TARGET_API_MAC_OSX
395 static char schedparams_doc[] = "Set/return mainloop interrupt check flag, etc";
398 ** Set scheduler parameters
400 static PyObject *
401 MacOS_SchedParams(PyObject *self, PyObject *args)
403 PyMacSchedParams old, new;
405 PyMac_GetSchedParams(&old);
406 new = old;
407 if (!PyArg_ParseTuple(args, "|iiidd", &new.check_interrupt, &new.process_events,
408 &new.besocial, &new.check_interval, &new.bg_yield))
409 return NULL;
410 PyMac_SetSchedParams(&new);
411 return Py_BuildValue("iiidd", old.check_interrupt, old.process_events,
412 old.besocial, old.check_interval, old.bg_yield);
415 static char appswitch_doc[] = "Obsolete, use SchedParams";
417 /* Obsolete, for backward compatability */
418 static PyObject *
419 MacOS_EnableAppswitch(PyObject *self, PyObject *args)
421 int new, old;
422 PyMacSchedParams schp;
424 if (!PyArg_ParseTuple(args, "i", &new))
425 return NULL;
426 PyMac_GetSchedParams(&schp);
427 if ( schp.process_events )
428 old = 1;
429 else if ( schp.check_interrupt )
430 old = 0;
431 else
432 old = -1;
433 if ( new > 0 ) {
434 schp.process_events = mDownMask|keyDownMask|osMask;
435 schp.check_interrupt = 1;
436 } else if ( new == 0 ) {
437 schp.process_events = 0;
438 schp.check_interrupt = 1;
439 } else {
440 schp.process_events = 0;
441 schp.check_interrupt = 0;
443 PyMac_SetSchedParams(&schp);
444 return Py_BuildValue("i", old);
447 static char setevh_doc[] = "Set python event handler to be called in mainloop";
449 static PyObject *
450 MacOS_SetEventHandler(PyObject *self, PyObject *args)
452 PyObject *evh = NULL;
454 if (!PyArg_ParseTuple(args, "|O", &evh))
455 return NULL;
456 if (evh == Py_None)
457 evh = NULL;
458 if ( evh && !PyCallable_Check(evh) ) {
459 PyErr_SetString(PyExc_ValueError, "SetEventHandler argument must be callable");
460 return NULL;
462 if ( !PyMac_SetEventHandler(evh) )
463 return NULL;
464 Py_INCREF(Py_None);
465 return Py_None;
468 static char handleev_doc[] = "Pass event to other interested parties like sioux";
470 static PyObject *
471 MacOS_HandleEvent(PyObject *self, PyObject *args)
473 EventRecord ev;
475 if (!PyArg_ParseTuple(args, "O&", PyMac_GetEventRecord, &ev))
476 return NULL;
477 PyMac_HandleEventIntern(&ev);
478 Py_INCREF(Py_None);
479 return Py_None;
481 #endif /* !TARGET_API_MAC_OSX */
483 static char geterr_doc[] = "Convert OSErr number to string";
485 static PyObject *
486 MacOS_GetErrorString(PyObject *self, PyObject *args)
488 int errn;
490 if (!PyArg_ParseTuple(args, "i", &errn))
491 return NULL;
492 return Py_BuildValue("s", PyMac_StrError(errn));
495 static char splash_doc[] = "Open a splash-screen dialog by resource-id (0=close)";
497 static PyObject *
498 MacOS_splash(PyObject *self, PyObject *args)
500 int resid = -1;
501 static DialogPtr curdialog = NULL;
502 DialogPtr olddialog;
503 WindowRef theWindow;
504 CGrafPtr thePort;
505 #if 0
506 short xpos, ypos, width, height, swidth, sheight;
507 #endif
509 if (!PyArg_ParseTuple(args, "|i", &resid))
510 return NULL;
511 olddialog = curdialog;
512 curdialog = NULL;
514 if ( resid != -1 ) {
515 curdialog = GetNewDialog(resid, NULL, (WindowPtr)-1);
516 if ( curdialog ) {
517 theWindow = GetDialogWindow(curdialog);
518 thePort = GetWindowPort(theWindow);
519 #if 0
520 width = thePort->portRect.right - thePort->portRect.left;
521 height = thePort->portRect.bottom - thePort->portRect.top;
522 swidth = qd.screenBits.bounds.right - qd.screenBits.bounds.left;
523 sheight = qd.screenBits.bounds.bottom - qd.screenBits.bounds.top - LMGetMBarHeight();
524 xpos = (swidth-width)/2;
525 ypos = (sheight-height)/5 + LMGetMBarHeight();
526 MoveWindow(theWindow, xpos, ypos, 0);
527 ShowWindow(theWindow);
528 #endif
529 DrawDialog(curdialog);
532 if (olddialog)
533 DisposeDialog(olddialog);
534 Py_INCREF(Py_None);
535 return Py_None;
538 static char DebugStr_doc[] = "Switch to low-level debugger with a message";
540 static PyObject *
541 MacOS_DebugStr(PyObject *self, PyObject *args)
543 Str255 message;
544 PyObject *object = 0;
546 if (!PyArg_ParseTuple(args, "O&|O", PyMac_GetStr255, message, &object))
547 return NULL;
548 DebugStr(message);
549 Py_INCREF(Py_None);
550 return Py_None;
553 static char SysBeep_doc[] = "BEEEEEP!!!";
555 static PyObject *
556 MacOS_SysBeep(PyObject *self, PyObject *args)
558 int duration = 6;
560 if (!PyArg_ParseTuple(args, "|i", &duration))
561 return NULL;
562 SysBeep(duration);
563 Py_INCREF(Py_None);
564 return Py_None;
567 static char GetTicks_doc[] = "Return number of ticks since bootup";
569 static PyObject *
570 MacOS_GetTicks(PyObject *self, PyObject *args)
572 return Py_BuildValue("i", (int)TickCount());
575 static char openrf_doc[] = "Open resource fork of a file";
577 static PyObject *
578 MacOS_openrf(PyObject *self, PyObject *args)
580 OSErr err;
581 char *mode = "r";
582 FSSpec fss;
583 SignedByte permission = 1;
584 rfobject *fp;
586 if (!PyArg_ParseTuple(args, "O&|s", PyMac_GetFSSpec, &fss, &mode))
587 return NULL;
588 while (*mode) {
589 switch (*mode++) {
590 case '*': break;
591 case 'r': permission = 1; break;
592 case 'w': permission = 2; break;
593 case 'b': break;
594 default:
595 PyErr_BadArgument();
596 return NULL;
600 if ( (fp = newrfobject()) == NULL )
601 return NULL;
603 err = HOpenRF(fss.vRefNum, fss.parID, fss.name, permission, &fp->fRefNum);
605 if ( err == fnfErr ) {
606 /* In stead of doing complicated things here to get creator/type
607 ** correct we let the standard i/o library handle it
609 FILE *tfp;
610 char pathname[PATHNAMELEN];
612 if ( err=PyMac_GetFullPathname(&fss, pathname, PATHNAMELEN) ) {
613 PyMac_Error(err);
614 Py_DECREF(fp);
615 return NULL;
618 if ( (tfp = fopen(pathname, "w")) == NULL ) {
619 PyMac_Error(fnfErr); /* What else... */
620 Py_DECREF(fp);
621 return NULL;
623 fclose(tfp);
624 err = HOpenRF(fss.vRefNum, fss.parID, fss.name, permission, &fp->fRefNum);
626 if ( err ) {
627 Py_DECREF(fp);
628 PyMac_Error(err);
629 return NULL;
631 fp->isclosed = 0;
632 return (PyObject *)fp;
635 #if !TARGET_API_MAC_OSX
636 static char FreeMem_doc[] = "Return the total amount of free space in the heap";
638 static PyObject *
639 MacOS_FreeMem(PyObject *self, PyObject *args)
641 long rv;
643 if (!PyArg_ParseTuple(args, ""))
644 return NULL;
645 rv = FreeMem();
646 return Py_BuildValue("l", rv);
649 static char MaxBlock_doc[] = "Return the largest contiguous block of free space in the heap";
651 static PyObject *
652 MacOS_MaxBlock(PyObject *self, PyObject *args)
654 long rv;
656 if (!PyArg_ParseTuple(args, ""))
657 return NULL;
658 rv = MaxBlock();
659 return Py_BuildValue("l", rv);
662 static char CompactMem_doc[] = "(wanted size)->actual largest block after compacting";
664 static PyObject *
665 MacOS_CompactMem(PyObject *self, PyObject *args)
667 long value;
668 long rv;
670 if (!PyArg_ParseTuple(args, "l", &value))
671 return NULL;
672 rv = CompactMem(value);
673 return Py_BuildValue("l", rv);
676 static char KeepConsole_doc[] = "(flag) Keep console open 0:never, 1:on output 2:on error, 3:always";
678 static PyObject *
679 MacOS_KeepConsole(PyObject *self, PyObject *args)
681 int value;
683 if (!PyArg_ParseTuple(args, "i", &value))
684 return NULL;
685 PyMac_options.keep_console = value;
686 Py_INCREF(Py_None);
687 return Py_None;
690 static char OutputSeen_doc[] = "Call to reset the 'unseen output' flag for the keep-console-open option";
692 static PyObject *
693 MacOS_OutputSeen(PyObject *self, PyObject *args)
695 if (!PyArg_ParseTuple(args, ""))
696 return NULL;
697 PyMac_OutputSeen();
698 Py_INCREF(Py_None);
699 return Py_None;
701 #endif /* !TARGET_API_MAC_OSX */
703 static PyMethodDef MacOS_Methods[] = {
704 #if TARGET_API_MAC_OS8
705 {"AcceptHighLevelEvent", MacOS_AcceptHighLevelEvent, 1, accepthle_doc},
706 #endif
707 {"GetCreatorAndType", MacOS_GetCreatorAndType, 1, getcrtp_doc},
708 {"SetCreatorAndType", MacOS_SetCreatorAndType, 1, setcrtp_doc},
709 #if !TARGET_API_MAC_OSX
710 {"SchedParams", MacOS_SchedParams, 1, schedparams_doc},
711 {"EnableAppswitch", MacOS_EnableAppswitch, 1, appswitch_doc},
712 {"SetEventHandler", MacOS_SetEventHandler, 1, setevh_doc},
713 {"HandleEvent", MacOS_HandleEvent, 1, handleev_doc},
714 #endif
715 {"GetErrorString", MacOS_GetErrorString, 1, geterr_doc},
716 {"openrf", MacOS_openrf, 1, openrf_doc},
717 {"splash", MacOS_splash, 1, splash_doc},
718 {"DebugStr", MacOS_DebugStr, 1, DebugStr_doc},
719 {"GetTicks", MacOS_GetTicks, 1, GetTicks_doc},
720 {"SysBeep", MacOS_SysBeep, 1, SysBeep_doc},
721 #if !TARGET_API_MAC_OSX
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 #endif
728 {NULL, NULL} /* Sentinel */
732 void
733 initMacOS(void)
735 PyObject *m, *d;
737 m = Py_InitModule("MacOS", MacOS_Methods);
738 d = PyModule_GetDict(m);
740 /* Initialize MacOS.Error exception */
741 MacOS_Error = PyMac_GetOSErrException();
742 if (MacOS_Error == NULL || PyDict_SetItemString(d, "Error", MacOS_Error) != 0)
743 return;
744 Rftype.ob_type = &PyType_Type;
745 Py_INCREF(&Rftype);
746 if (PyDict_SetItemString(d, "ResourceForkType", (PyObject *)&Rftype) != 0)
747 return;
749 ** This is a hack: the following constant added to the id() of a string
750 ** object gives you the address of the data. Unfortunately, it is needed for
751 ** some of the image and sound processing interfaces on the mac:-(
754 PyStringObject *p = 0;
755 long off = (long)&(p->ob_sval[0]);
757 if( PyDict_SetItemString(d, "string_id_to_buffer", Py_BuildValue("i", off)) != 0)
758 return;
760 #if TARGET_API_MAC_OSX
761 #define PY_RUNTIMEMODEL "macho"
762 #elif TARGET_API_MAC_OS8
763 #define PY_RUNTIMEMODEL "ppc"
764 #elif TARGET_API_MAC_CARBON
765 #define PY_RUNTIMEMODEL "carbon"
766 #else
767 #error "None of the TARGET_API_MAC_XXX I know about is set"
768 #endif
769 if (PyDict_SetItemString(d, "runtimemodel",
770 Py_BuildValue("s", PY_RUNTIMEMODEL)) != 0)
771 return;