blob: 76e96a8a01ed8656832e82c07ad33d1ded4700d4 [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);
34 buf[0] = (unsigned char)len;
35 strncpy((char *)buf+1, str, len);
36 return buf;
37}
38
Jack Jansenf93c72a1994-12-14 14:07:50 +000039/* Replace strerror with something that might work */
40char *macstrerror(int err)
41{
42 static char buf[256];
43 Handle h;
44 char *str;
45
46 h = GetResource('Estr', err);
47 if ( h ) {
48 HLock(h);
49 str = (char *)*h;
50 memcpy(buf, str+1, (unsigned char)str[0]);
51 HUnlock(h);
52 ReleaseResource(h);
53 } else {
54 sprintf(buf, "Mac OS error code %d", err);
55 }
56 return buf;
57}
58
59/* Set a MAC-specific error from errno, and return NULL; return None if no error */
60PyObject *
Guido van Rossumfffb8bb1995-01-12 12:37:24 +000061PyErr_Mac(PyObject *eobj, int err)
Jack Jansenf93c72a1994-12-14 14:07:50 +000062{
63 char *msg;
64 PyObject *v;
Jack Jansenf93c72a1994-12-14 14:07:50 +000065
66 if (err == 0) {
67 Py_INCREF(Py_None);
68 return Py_None;
69 }
70 msg = macstrerror(err);
71 v = Py_BuildValue("(is)", err, msg);
72 PyErr_SetObject(eobj, v);
73 Py_DECREF(v);
74 return NULL;
75}
76
77/*
78** Idle routine for busy-wait loops.
79** This is rather tricky: if we see an event we check whether it is
80** for somebody else (i.e. a click outside our windows) and, if so,
81** we pass the event on (so the user can switch processes). However,
82** by doing this we loose events meant for our windows. Too bad, I guess...
83*/
84int
85PyMac_Idle()
86{
87 EventRecord ev;
88 WindowPtr wp;
89
Jack Jansenf93c72a1994-12-14 14:07:50 +000090 SystemTask();
Jack Jansen5f653091995-01-18 13:53:49 +000091 if ( intrpeek() )
Jack Jansenf93c72a1994-12-14 14:07:50 +000092 return 0;
93 if ( GetNextEvent(0xffff, &ev) ) {
94 if ( ev.what == mouseDown ) {
95 if ( FindWindow(ev.where, &wp) == inSysWindow )
96 SystemClick(&ev, wp);
97 }
98 }
Jack Jansenf93c72a1994-12-14 14:07:50 +000099 return 1;
100}
101
Jack Jansen5f653091995-01-18 13:53:49 +0000102
103/* Convert a ResType argument */
104int
105GetOSType(PyObject *v, ResType *pr)
106{
107 if (!PyString_Check(v) || PyString_Size(v) != 4) {
108 PyErr_SetString(PyExc_TypeError,
109 "OSType arg must be string of 4 chars");
110 return 0;
111 }
112 memcpy((char *)pr, PyString_AsString(v), 4);
113 return 1;
114}
115
116/* Convert a Str255 argument */
117int
118GetStr255(PyObject *v, Str255 pbuf)
119{
120 int len;
121 if (!PyString_Check(v) || (len = PyString_Size(v)) > 255) {
122 PyErr_SetString(PyExc_TypeError,
123 "Str255 arg must be string of at most 255 chars");
124 return 0;
125 }
126 pbuf[0] = len;
127 memcpy((char *)(pbuf+1), PyString_AsString(v), len);
128 return 1;
129}
130
131/*
132** Convert anything resembling an FSSpec argument
133** NOTE: This routine will fail on pre-sys7 machines.
134** The caller is responsible for not calling this routine
135** in those cases (which is fine, since everyone calling
136** this is probably sys7 dependent anyway).
137*/
138int
139GetFSSpec(PyObject *v, FSSpec *fs)
140{
141 Str255 path;
142 short refnum;
143 long parid;
144 OSErr err;
145
146 if ( PyString_Check(v) ) {
147 /* It's a pathname */
148 if( !PyArg_Parse(v, "O&", GetStr255, &path) )
149 return 0;
150 refnum = 0; /* XXXX Should get CurWD here... */
151 parid = 0;
152 } else {
153 PyErr_Clear();
154 if( !PyArg_Parse(v, "(hlO&); FSSpec should be fullpath or (int,int,string)",
155 &refnum, &parid, GetStr255, &path))
156 return 0;
157 }
158 err = FSMakeFSSpec(refnum, parid, path, fs);
159 if ( err && err != fnfErr ) {
160 PyErr_SetString(PyExc_TypeError,
161 "FSMakeFSSpec error");
162 return 0;
163 }
164 return 1;
165}
166
167/*
168** Return a python object that describes an FSSpec
169*/
170PyObject *
171PyMac_BuildFSSpec(FSSpec *fs)
172{
173 return Py_BuildValue("(iis#)", fs->vRefNum, fs->parID, &fs->name[1], fs->name[0]);
174}