blob: 5e82e7e5ad5cb7e5f32adac95278fb31103d8ce2 [file] [log] [blame]
Guido van Rossumb3404661995-01-22 18:36:13 +00001/***********************************************************
2Copyright 1991-1995 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******************************************************************/
Jack Jansenf93c72a1994-12-14 14:07:50 +000024
25#include "Python.h"
26#include "macglue.h"
27
28#include <OSUtils.h> /* for Set(Current)A5 */
Jack Jansene8e8ae01995-01-26 16:36:45 +000029#include <Files.h>
Jack Jansenf93c72a1994-12-14 14:07:50 +000030#include <Resources.h>
31#include <Memory.h>
32#include <Events.h>
33#include <Windows.h>
34#include <Desk.h>
Jack Jansene8e8ae01995-01-26 16:36:45 +000035#include <Traps.h>
36
37#ifdef __MWERKS__
38#include <SIOUX.h>
39#endif /* __MWERKS__ */
40
41#include <signal.h>
Jack Jansenf93c72a1994-12-14 14:07:50 +000042
Guido van Rossumb3404661995-01-22 18:36:13 +000043/* XXX We should include Errors.h here, but it has a name conflict
Jack Jansen5f653091995-01-18 13:53:49 +000044** with the python errors.h. */
45#define fnfErr -43
46
Jack Jansene8e8ae01995-01-26 16:36:45 +000047/* Declared in macfsmodule.c: */
48extern FSSpec *mfs_GetFSSpecFSSpec();
49
50/*
51** We attempt to be a good citizen by giving up the CPU periodically.
52** When in the foreground we do this less often and for shorter periods
53** than when in the background. At this time we also check for events and
54** pass them off to stdwin (or SIOUX, if compiling with mwerks).
55** The counts here are in ticks of 1/60th second.
56** XXXX The initial values here are not based on anything.
57** FG-python gives up the cpu for 1/60th 5 times per second,
58** BG-python for .2 second 10 times per second.
59*/
60static long interval_fg = 12;
61static long interval_bg = 6;
62static long yield_fg = 1;
63static long yield_bg = 12;
64static long lastyield, in_background;
65
Jack Jansen5f653091995-01-18 13:53:49 +000066/* Convert C to Pascal string. Returns pointer to static buffer. */
67unsigned char *
68Pstring(char *str)
69{
70 static Str255 buf;
71 int len;
72
73 len = strlen(str);
Guido van Rossum9aa3d131995-01-21 13:46:04 +000074 if (len > 255)
75 len = 255;
Jack Jansen5f653091995-01-18 13:53:49 +000076 buf[0] = (unsigned char)len;
77 strncpy((char *)buf+1, str, len);
78 return buf;
79}
80
Jack Jansenf93c72a1994-12-14 14:07:50 +000081/* Replace strerror with something that might work */
82char *macstrerror(int err)
83{
84 static char buf[256];
85 Handle h;
86 char *str;
87
88 h = GetResource('Estr', err);
89 if ( h ) {
90 HLock(h);
91 str = (char *)*h;
92 memcpy(buf, str+1, (unsigned char)str[0]);
93 HUnlock(h);
94 ReleaseResource(h);
95 } else {
96 sprintf(buf, "Mac OS error code %d", err);
97 }
98 return buf;
99}
100
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000101/* Exception object shared by all Mac specific modules for Mac OS errors */
102PyObject *PyMac_OSErrException;
103
104/* Initialize and return PyMac_OSErrException */
105PyObject *
106PyMac_GetOSErrException()
107{
108 if (PyMac_OSErrException == NULL)
109 PyMac_OSErrException = PyString_FromString("Mac OS Error");
110 return PyMac_OSErrException;
111}
112
Jack Jansenf93c72a1994-12-14 14:07:50 +0000113/* Set a MAC-specific error from errno, and return NULL; return None if no error */
114PyObject *
Guido van Rossumfffb8bb1995-01-12 12:37:24 +0000115PyErr_Mac(PyObject *eobj, int err)
Jack Jansenf93c72a1994-12-14 14:07:50 +0000116{
117 char *msg;
118 PyObject *v;
Jack Jansenf93c72a1994-12-14 14:07:50 +0000119
Guido van Rossum8f691791995-01-18 23:57:26 +0000120 if (err == 0 && !PyErr_Occurred()) {
Jack Jansenf93c72a1994-12-14 14:07:50 +0000121 Py_INCREF(Py_None);
122 return Py_None;
123 }
Guido van Rossum8f691791995-01-18 23:57:26 +0000124 if (err == -1 && PyErr_Occurred())
125 return NULL;
Jack Jansenf93c72a1994-12-14 14:07:50 +0000126 msg = macstrerror(err);
127 v = Py_BuildValue("(is)", err, msg);
128 PyErr_SetObject(eobj, v);
129 Py_DECREF(v);
130 return NULL;
131}
132
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000133/* Call PyErr_Mac with PyMac_OSErrException */
134PyObject *
135PyMac_Error(OSErr err)
136{
137 return PyErr_Mac(PyMac_GetOSErrException(), err);
138}
139
Jack Jansenf93c72a1994-12-14 14:07:50 +0000140/*
Jack Jansene8e8ae01995-01-26 16:36:45 +0000141** Set yield timeouts
Jack Jansenf93c72a1994-12-14 14:07:50 +0000142*/
Jack Jansene8e8ae01995-01-26 16:36:45 +0000143void
144PyMac_SetYield(long fgi, long fgy, long bgi, long bgy)
145{
146 interval_fg = fgi;
147 yield_fg = fgy;
148 interval_bg = bgi;
149 yield_bg = bgy;
150}
151
152/*
153** Yield the CPU to other tasks.
154*/
155static
156PyMac_DoYield()
Jack Jansenf93c72a1994-12-14 14:07:50 +0000157{
158 EventRecord ev;
159 WindowPtr wp;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000160 long yield;
161 extern int StdwinIsActive;
162 static int no_waitnextevent = -1;
163 int gotone;
164
165 if ( no_waitnextevent < 0 ) {
166 no_waitnextevent = (NGetTrapAddress(_WaitNextEvent, ToolTrap) ==
167 NGetTrapAddress(_Unimplemented, ToolTrap));
168 }
Jack Jansenf93c72a1994-12-14 14:07:50 +0000169
Jack Jansene8e8ae01995-01-26 16:36:45 +0000170 if ( StdwinIsActive )
171 return;
172
173 if ( in_background )
174 yield = yield_bg;
175 else
176 yield = yield_fg;
177 while ( 1 ) {
178 if ( no_waitnextevent ) {
179 SystemTask();
180 gotone = GetNextEvent(0xffff, &ev);
181 } else {
182 gotone = WaitNextEvent(everyEvent, &ev, yield, NULL);
183 }
184 /* Get out quickly if nothing interesting is happening */
185 if ( !gotone || ev.what == nullEvent )
186 break;
187
188 /* Check whether we've moved to foreground or background */
189 if ( ev.what == osEvt &&
190 (ev.message & osEvtMessageMask) == (suspendResumeMessage<<24)) {
191 if ( ev.message & resumeFlag ) {
192 in_background = 0;
193 } else {
194 in_background = 1;
195 }
196 }
197#ifdef __MWERKS__
198 /* If SIOUX wants it we're done too */
199 (void)SIOUXHandleOneEvent(&ev);
200#else
201 /* Other compilers are just unlucky: we only weed out clicks in other applications */
Jack Jansenf93c72a1994-12-14 14:07:50 +0000202 if ( ev.what == mouseDown ) {
203 if ( FindWindow(ev.where, &wp) == inSysWindow )
204 SystemClick(&ev, wp);
205 }
Jack Jansene8e8ae01995-01-26 16:36:45 +0000206#endif /* !__MWERKS__ */
Jack Jansenf93c72a1994-12-14 14:07:50 +0000207 }
Jack Jansene8e8ae01995-01-26 16:36:45 +0000208 lastyield = TickCount();
209}
210
211/*
212** Yield the CPU to other tasks if opportune
213*/
214void
215PyMac_Yield() {
216 long iv;
217
218 if ( in_background )
219 iv = interval_bg;
220 else
221 iv = interval_fg;
222 if ( TickCount() > lastyield + iv )
223 PyMac_DoYield();
224}
225
226/*
227** Idle routine for busy-wait loops.
228** Gives up CPU, handles events and returns true if an interrupt is pending
229** (but not actually handled yet).
230*/
231int
232PyMac_Idle()
233{
234 PyMac_DoYield();
235 return intrpeek();
Jack Jansenf93c72a1994-12-14 14:07:50 +0000236}
237
Jack Jansen5f653091995-01-18 13:53:49 +0000238
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000239/* Convert a 4-char string object argument to an OSType value */
Jack Jansen5f653091995-01-18 13:53:49 +0000240int
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000241PyMac_GetOSType(PyObject *v, OSType *pr)
Jack Jansen5f653091995-01-18 13:53:49 +0000242{
243 if (!PyString_Check(v) || PyString_Size(v) != 4) {
244 PyErr_SetString(PyExc_TypeError,
245 "OSType arg must be string of 4 chars");
246 return 0;
247 }
248 memcpy((char *)pr, PyString_AsString(v), 4);
249 return 1;
250}
251
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000252/* Convert an OSType value to a 4-char string object */
253PyObject *
254PyMac_BuildOSType(OSType t)
255{
256 return PyString_FromStringAndSize((char *)&t, 4);
257}
258
259
260/* Convert a Python string object to a Str255 */
Jack Jansen5f653091995-01-18 13:53:49 +0000261int
Guido van Rossum8f691791995-01-18 23:57:26 +0000262PyMac_GetStr255(PyObject *v, Str255 pbuf)
Jack Jansen5f653091995-01-18 13:53:49 +0000263{
264 int len;
265 if (!PyString_Check(v) || (len = PyString_Size(v)) > 255) {
266 PyErr_SetString(PyExc_TypeError,
267 "Str255 arg must be string of at most 255 chars");
268 return 0;
269 }
270 pbuf[0] = len;
271 memcpy((char *)(pbuf+1), PyString_AsString(v), len);
272 return 1;
273}
274
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000275/* Convert a Str255 to a Python string object */
276PyObject *
277PyMac_BuildStr255(Str255 s)
278{
279 return PyString_FromStringAndSize((char *)&s[1], (int)s[0]);
280}
281
282
Jack Jansen5f653091995-01-18 13:53:49 +0000283/*
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000284** Convert a Python object to an FSSpec.
285** The object may either be a full pathname or a triple
286** (vrefnum, dirid, path).
Jack Jansen5f653091995-01-18 13:53:49 +0000287** NOTE: This routine will fail on pre-sys7 machines.
288** The caller is responsible for not calling this routine
289** in those cases (which is fine, since everyone calling
290** this is probably sys7 dependent anyway).
291*/
292int
Guido van Rossum8f691791995-01-18 23:57:26 +0000293PyMac_GetFSSpec(PyObject *v, FSSpec *fs)
Jack Jansen5f653091995-01-18 13:53:49 +0000294{
295 Str255 path;
296 short refnum;
297 long parid;
298 OSErr err;
Jack Jansene8e8ae01995-01-26 16:36:45 +0000299 FSSpec *fs2;
Jack Jansen5f653091995-01-18 13:53:49 +0000300
Jack Jansene8e8ae01995-01-26 16:36:45 +0000301 /* first check whether it already is an FSSpec */
302 fs2 = mfs_GetFSSpecFSSpec(v);
303 if ( fs2 ) {
304 fs = fs2;
305 return 1;
306 }
Jack Jansen5f653091995-01-18 13:53:49 +0000307 if ( PyString_Check(v) ) {
308 /* It's a pathname */
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000309 if( !PyArg_Parse(v, "O&", PyMac_GetStr255, &path) )
Jack Jansen5f653091995-01-18 13:53:49 +0000310 return 0;
311 refnum = 0; /* XXXX Should get CurWD here... */
312 parid = 0;
313 } else {
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000314 if( !PyArg_Parse(v, "(hlO&); FSSpec should be fullpath or (vrefnum,dirid,path)",
315 &refnum, &parid, PyMac_GetStr255, &path)) {
Jack Jansen5f653091995-01-18 13:53:49 +0000316 return 0;
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000317 }
Jack Jansen5f653091995-01-18 13:53:49 +0000318 }
319 err = FSMakeFSSpec(refnum, parid, path, fs);
320 if ( err && err != fnfErr ) {
Guido van Rossum9aa3d131995-01-21 13:46:04 +0000321 PyErr_Mac(PyExc_ValueError, err);
Jack Jansen5f653091995-01-18 13:53:49 +0000322 return 0;
323 }
324 return 1;
325}
326
Guido van Rossum8f691791995-01-18 23:57:26 +0000327
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000328
329/* Convert a Python object to a Rect.
Guido van Rossum5279ec61995-01-26 22:56:59 +0000330 The object must be a (left, top, right, bottom) tuple.
331 (This differs from the order in the struct but is consistent with
332 the arguments to SetRect(), and also with STDWIN). */
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000333int
334PyMac_GetRect(PyObject *v, Rect *r)
Guido van Rossum8f691791995-01-18 23:57:26 +0000335{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000336 return PyArg_Parse(v, "(hhhh)", &r->left, &r->top, &r->right, &r->bottom);
Guido van Rossum8f691791995-01-18 23:57:26 +0000337}
Guido van Rossumb3404661995-01-22 18:36:13 +0000338
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000339/* Convert a Rect to a Python object */
Guido van Rossumb3404661995-01-22 18:36:13 +0000340PyObject *
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000341PyMac_BuildRect(Rect *r)
Guido van Rossumb3404661995-01-22 18:36:13 +0000342{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000343 return Py_BuildValue("(hhhh)", r->left, r->top, r->right, r->bottom);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000344}
345
346
347/* Convert a Python object to a Point.
Guido van Rossum5279ec61995-01-26 22:56:59 +0000348 The object must be a (h, v) tuple.
349 (This differs from the order in the struct but is consistent with
350 the arguments to SetPoint(), and also with STDWIN). */
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000351int
352PyMac_GetPoint(PyObject *v, Point *p)
353{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000354 return PyArg_Parse(v, "(hh)", &p->h, &p->v);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000355}
356
357/* Convert a Point to a Python object */
358PyObject *
359PyMac_BuildPoint(Point p)
360{
Guido van Rossum5279ec61995-01-26 22:56:59 +0000361 return Py_BuildValue("(hh)", p.h, p.v);
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000362}
363
364
365/* Convert a Python object to an EventRecord.
366 The object must be a (what, message, when, (v, h), modifiers) tuple. */
367int
368PyMac_GetEventRecord(PyObject *v, EventRecord *e)
369{
370 return PyArg_Parse(v, "(hll(hh)h)",
371 &e->what,
372 &e->message,
373 &e->when,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000374 &e->where.h,
Guido van Rossum5279ec61995-01-26 22:56:59 +0000375 &e->where.v,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000376 &e->modifiers);
377}
378
379/* Convert a Rect to an EventRecord object */
380PyObject *
381PyMac_BuildEventRecord(EventRecord *e)
382{
383 return Py_BuildValue("(hll(hh)h)",
384 e->what,
385 e->message,
386 e->when,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000387 e->where.h,
Guido van Rossum5279ec61995-01-26 22:56:59 +0000388 e->where.v,
Guido van Rossumcf27c2d1995-01-25 23:06:44 +0000389 e->modifiers);
Guido van Rossumb3404661995-01-22 18:36:13 +0000390}