blob: 77675150c5b728e4aead39cb41b7bb0eec9b4340 [file] [log] [blame]
Jack Jansenf93c72a1994-12-14 14:07:50 +00001/*
2** macglue - A couple of mac-specific routines often needed.
3**
4** Jack Jansen, CWI, 1994.
Jack Jansen5f653091995-01-18 13:53:49 +00005** Some routines by Guido, moved here from macosmodule.c
6** (since they are useable by other modules as well).
Jack Jansenf93c72a1994-12-14 14:07:50 +00007*/
Jack Jansenf93c72a1994-12-14 14:07:50 +00008#ifdef HAVE_CONFIG_H
9#include "config.h"
10#endif
11
12#include "Python.h"
13#include "macglue.h"
14
15#include <OSUtils.h> /* for Set(Current)A5 */
16#include <Resources.h>
17#include <Memory.h>
18#include <Events.h>
19#include <Windows.h>
20#include <Desk.h>
21
Jack Jansen5f653091995-01-18 13:53:49 +000022/* We should include Errors.h here, but it has a name conflict
23** with the python errors.h. */
24#define fnfErr -43
25
26/* Convert C to Pascal string. Returns pointer to static buffer. */
27unsigned char *
28Pstring(char *str)
29{
30 static Str255 buf;
31 int len;
32
33 len = strlen(str);
Guido van Rossum9aa3d131995-01-21 13:46:04 +000034 if (len > 255)
35 len = 255;
Jack Jansen5f653091995-01-18 13:53:49 +000036 buf[0] = (unsigned char)len;
37 strncpy((char *)buf+1, str, len);
38 return buf;
39}
40
Jack Jansenf93c72a1994-12-14 14:07:50 +000041/* Replace strerror with something that might work */
42char *macstrerror(int err)
43{
44 static char buf[256];
45 Handle h;
46 char *str;
47
48 h = GetResource('Estr', err);
49 if ( h ) {
50 HLock(h);
51 str = (char *)*h;
52 memcpy(buf, str+1, (unsigned char)str[0]);
53 HUnlock(h);
54 ReleaseResource(h);
55 } else {
56 sprintf(buf, "Mac OS error code %d", err);
57 }
58 return buf;
59}
60
61/* Set a MAC-specific error from errno, and return NULL; return None if no error */
62PyObject *
Guido van Rossumfffb8bb1995-01-12 12:37:24 +000063PyErr_Mac(PyObject *eobj, int err)
Jack Jansenf93c72a1994-12-14 14:07:50 +000064{
65 char *msg;
66 PyObject *v;
Jack Jansenf93c72a1994-12-14 14:07:50 +000067
Guido van Rossum8f691791995-01-18 23:57:26 +000068 if (err == 0 && !PyErr_Occurred()) {
Jack Jansenf93c72a1994-12-14 14:07:50 +000069 Py_INCREF(Py_None);
70 return Py_None;
71 }
Guido van Rossum8f691791995-01-18 23:57:26 +000072 if (err == -1 && PyErr_Occurred())
73 return NULL;
Jack Jansenf93c72a1994-12-14 14:07:50 +000074 msg = macstrerror(err);
75 v = Py_BuildValue("(is)", err, msg);
76 PyErr_SetObject(eobj, v);
77 Py_DECREF(v);
78 return NULL;
79}
80
81/*
82** Idle routine for busy-wait loops.
83** This is rather tricky: if we see an event we check whether it is
84** for somebody else (i.e. a click outside our windows) and, if so,
85** we pass the event on (so the user can switch processes). However,
86** by doing this we loose events meant for our windows. Too bad, I guess...
87*/
88int
89PyMac_Idle()
90{
91 EventRecord ev;
92 WindowPtr wp;
93
Jack Jansenf93c72a1994-12-14 14:07:50 +000094 SystemTask();
Jack Jansen5f653091995-01-18 13:53:49 +000095 if ( intrpeek() )
Jack Jansenf93c72a1994-12-14 14:07:50 +000096 return 0;
97 if ( GetNextEvent(0xffff, &ev) ) {
98 if ( ev.what == mouseDown ) {
99 if ( FindWindow(ev.where, &wp) == inSysWindow )
100 SystemClick(&ev, wp);
101 }
102 }
Jack Jansenf93c72a1994-12-14 14:07:50 +0000103 return 1;
104}
105
Jack Jansen5f653091995-01-18 13:53:49 +0000106
107/* Convert a ResType argument */
108int
Guido van Rossum8f691791995-01-18 23:57:26 +0000109PyMac_GetOSType(PyObject *v, ResType *pr)
Jack Jansen5f653091995-01-18 13:53:49 +0000110{
111 if (!PyString_Check(v) || PyString_Size(v) != 4) {
112 PyErr_SetString(PyExc_TypeError,
113 "OSType arg must be string of 4 chars");
114 return 0;
115 }
116 memcpy((char *)pr, PyString_AsString(v), 4);
117 return 1;
118}
119
120/* Convert a Str255 argument */
121int
Guido van Rossum8f691791995-01-18 23:57:26 +0000122PyMac_GetStr255(PyObject *v, Str255 pbuf)
Jack Jansen5f653091995-01-18 13:53:49 +0000123{
124 int len;
125 if (!PyString_Check(v) || (len = PyString_Size(v)) > 255) {
126 PyErr_SetString(PyExc_TypeError,
127 "Str255 arg must be string of at most 255 chars");
128 return 0;
129 }
130 pbuf[0] = len;
131 memcpy((char *)(pbuf+1), PyString_AsString(v), len);
132 return 1;
133}
134
135/*
136** Convert anything resembling an FSSpec argument
137** NOTE: This routine will fail on pre-sys7 machines.
138** The caller is responsible for not calling this routine
139** in those cases (which is fine, since everyone calling
140** this is probably sys7 dependent anyway).
141*/
142int
Guido van Rossum8f691791995-01-18 23:57:26 +0000143PyMac_GetFSSpec(PyObject *v, FSSpec *fs)
Jack Jansen5f653091995-01-18 13:53:49 +0000144{
145 Str255 path;
146 short refnum;
147 long parid;
148 OSErr err;
149
150 if ( PyString_Check(v) ) {
151 /* It's a pathname */
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000152 if( !PyArg_Parse(v, "O&", PyMac_GetStr255, &path) )
Jack Jansen5f653091995-01-18 13:53:49 +0000153 return 0;
154 refnum = 0; /* XXXX Should get CurWD here... */
155 parid = 0;
156 } else {
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000157 if( !PyArg_Parse(v, "(hlO&); FSSpec should be fullpath or (vrefnum,dirid,path)",
158 &refnum, &parid, PyMac_GetStr255, &path)) {
Jack Jansen5f653091995-01-18 13:53:49 +0000159 return 0;
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000160 }
Jack Jansen5f653091995-01-18 13:53:49 +0000161 }
162 err = FSMakeFSSpec(refnum, parid, path, fs);
163 if ( err && err != fnfErr ) {
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000164 PyErr_Mac(PyExc_ValueError, err);
Jack Jansen5f653091995-01-18 13:53:49 +0000165 return 0;
166 }
167 return 1;
168}
169
170/*
171** Return a python object that describes an FSSpec
172*/
173PyObject *
174PyMac_BuildFSSpec(FSSpec *fs)
175{
176 return Py_BuildValue("(iis#)", fs->vRefNum, fs->parID, &fs->name[1], fs->name[0]);
177}
Guido van Rossum8f691791995-01-18 23:57:26 +0000178
179/* Convert an OSType value to a 4-char string object */
180PyObject *
181PyMac_BuildOSType(OSType t)
182{
183 return PyString_FromStringAndSize((char *)&t, 4);
184}