Allow comment characters (#) to be escaped:
[python/dscho.git] / Mac / Modules / qd / qdsupport.py
blob7f1db824fedac625541ba4848ffac72b8f26f519
1 # This script generates a Python interface for an Apple Macintosh Manager.
2 # It uses the "bgen" package to generate C code.
3 # The function specifications are generated by scanning the mamager's header file,
4 # using the "scantools" package (customized for this particular manager).
6 import string
8 # Declarations that change for each manager
9 MACHEADERFILE = 'QuickDraw.h' # The Apple header file
10 MODNAME = 'Qd' # The name of the module
11 OBJECTNAME = 'Graf' # The basic name of the objects used here
13 # The following is *usually* unchanged but may still require tuning
14 MODPREFIX = MODNAME # The prefix for module-wide routines
15 OBJECTTYPE = OBJECTNAME + 'Ptr' # The C type used to represent them
16 OBJECTPREFIX = MODPREFIX + 'Obj' # The prefix for object methods
17 INPUTFILE = string.lower(MODPREFIX) + 'gen.py' # The file generated by the scanner
18 EXTRAFILE = string.lower(MODPREFIX) + 'edit.py' # A similar file but hand-made
19 OUTPUTFILE = MODNAME + "module.c" # The file generated by this program
21 from macsupport import *
23 # Create the type objects
25 class TextThingieClass(FixedInputBufferType):
26 def getargsCheck(self, name):
27 pass
29 TextThingie = TextThingieClass(None)
31 # These are temporary!
32 RgnHandle = OpaqueByValueType("RgnHandle", "ResObj")
33 OptRgnHandle = OpaqueByValueType("RgnHandle", "OptResObj")
34 PicHandle = OpaqueByValueType("PicHandle", "ResObj")
35 PolyHandle = OpaqueByValueType("PolyHandle", "ResObj")
36 PixMapHandle = OpaqueByValueType("PixMapHandle", "ResObj")
37 PixPatHandle = OpaqueByValueType("PixPatHandle", "ResObj")
38 PatHandle = OpaqueByValueType("PatHandle", "ResObj")
39 CursHandle = OpaqueByValueType("CursHandle", "ResObj")
40 CCrsrHandle = OpaqueByValueType("CCrsrHandle", "ResObj")
41 CIconHandle = OpaqueByValueType("CIconHandle", "ResObj")
42 CTabHandle = OpaqueByValueType("CTabHandle", "ResObj")
43 ITabHandle = OpaqueByValueType("ITabHandle", "ResObj")
44 GDHandle = OpaqueByValueType("GDHandle", "ResObj")
45 CGrafPtr = OpaqueByValueType("CGrafPtr", "GrafObj")
46 GrafPtr = OpaqueByValueType("GrafPtr", "GrafObj")
47 BitMap_ptr = OpaqueByValueType("BitMapPtr", "BMObj")
48 RGBColor = OpaqueType('RGBColor', 'QdRGB')
49 RGBColor_ptr = RGBColor
50 FontInfo = OpaqueType('FontInfo', 'QdFI')
52 Cursor_ptr = StructInputBufferType('Cursor')
53 Pattern = StructOutputBufferType('Pattern')
54 Pattern_ptr = StructInputBufferType('Pattern')
55 PenState = StructOutputBufferType('PenState')
56 PenState_ptr = StructInputBufferType('PenState')
58 includestuff = includestuff + """
59 #include <%s>""" % MACHEADERFILE + """
61 #define resNotFound -192 /* Can't include <Errors.h> because of Python's "errors.h" */
64 ** Parse/generate RGB records
66 PyObject *QdRGB_New(itself)
67 RGBColorPtr itself;
70 return Py_BuildValue("lll", (long)itself->red, (long)itself->green, (long)itself->blue);
73 QdRGB_Convert(v, p_itself)
74 PyObject *v;
75 RGBColorPtr p_itself;
77 long red, green, blue;
79 if( !PyArg_ParseTuple(v, "lll", &red, &green, &blue) )
80 return 0;
81 p_itself->red = (unsigned short)red;
82 p_itself->green = (unsigned short)green;
83 p_itself->blue = (unsigned short)blue;
84 return 1;
88 ** Generate FontInfo records
90 static
91 PyObject *QdFI_New(itself)
92 FontInfo *itself;
95 return Py_BuildValue("hhhh", itself->ascent, itself->descent,
96 itself->widMax, itself->leading);
102 variablestuff = """
104 PyObject *o;
106 o = QDGA_New();
107 if (o == NULL || PyDict_SetItemString(d, "qd", o) != 0)
108 Py_FatalError("can't initialize Qd.qd");
112 ## not yet...
114 ##class Region_ObjectDefinition(GlobalObjectDefinition):
115 ## def outputCheckNewArg(self):
116 ## Output("if (itself == NULL) return PyMac_Error(resNotFound);")
117 ## def outputFreeIt(self, itselfname):
118 ## Output("DisposeRegion(%s);", itselfname)
120 ##class Polygon_ObjectDefinition(GlobalObjectDefinition):
121 ## def outputCheckNewArg(self):
122 ## Output("if (itself == NULL) return PyMac_Error(resNotFound);")
123 ## def outputFreeIt(self, itselfname):
124 ## Output("KillPoly(%s);", itselfname)
126 class MyGRObjectDefinition(GlobalObjectDefinition):
127 def outputCheckNewArg(self):
128 Output("if (itself == NULL) return PyMac_Error(resNotFound);")
129 def outputCheckConvertArg(self):
130 OutLbrace("if (DlgObj_Check(v) || WinObj_Check(v))")
131 Output("*p_itself = ((GrafPortObject *)v)->ob_itself;")
132 Output("return 1;")
133 OutRbrace()
134 def outputGetattrHook(self):
135 Output("""
136 { CGrafPtr itself_color = (CGrafPtr)self->ob_itself;
138 if ( strcmp(name, "data") == 0 )
139 return PyString_FromStringAndSize((char *)self->ob_itself, sizeof(GrafPort));
141 if ( (itself_color->portVersion&0xc000) == 0xc000 ) {
142 /* Color-only attributes */
144 if ( strcmp(name, "portBits") == 0 )
145 /* XXXX Do we need HLock() stuff here?? */
146 return BMObj_New((BitMapPtr)*itself_color->portPixMap);
147 if ( strcmp(name, "grafVars") == 0 )
148 return Py_BuildValue("O&", ResObj_New, (Handle)itself_color->visRgn);
149 if ( strcmp(name, "chExtra") == 0 )
150 return Py_BuildValue("h", itself_color->chExtra);
151 if ( strcmp(name, "pnLocHFrac") == 0 )
152 return Py_BuildValue("h", itself_color->pnLocHFrac);
153 if ( strcmp(name, "bkPixPat") == 0 )
154 return Py_BuildValue("O&", ResObj_New, (Handle)itself_color->bkPixPat);
155 if ( strcmp(name, "rgbFgColor") == 0 )
156 return Py_BuildValue("O&", QdRGB_New, &itself_color->rgbFgColor);
157 if ( strcmp(name, "rgbBkColor") == 0 )
158 return Py_BuildValue("O&", QdRGB_New, &itself_color->rgbBkColor);
159 if ( strcmp(name, "pnPixPat") == 0 )
160 return Py_BuildValue("O&", ResObj_New, (Handle)itself_color->pnPixPat);
161 if ( strcmp(name, "fillPixPat") == 0 )
162 return Py_BuildValue("O&", ResObj_New, (Handle)itself_color->fillPixPat);
163 } else {
164 /* Mono-only attributes */
165 if ( strcmp(name, "portBits") == 0 )
166 return BMObj_New(&self->ob_itself->portBits);
167 if ( strcmp(name, "bkPat") == 0 )
168 return Py_BuildValue("s#", (char *)&self->ob_itself->bkPat, sizeof(Pattern));
169 if ( strcmp(name, "fillPat") == 0 )
170 return Py_BuildValue("s#", (char *)&self->ob_itself->fillPat, sizeof(Pattern));
171 if ( strcmp(name, "pnPat") == 0 )
172 return Py_BuildValue("s#", (char *)&self->ob_itself->pnPat, sizeof(Pattern));
175 ** Accessible for both color/mono windows.
176 ** portVersion is really color-only, but we put it here
177 ** for convenience
179 if ( strcmp(name, "portVersion") == 0 )
180 return Py_BuildValue("h", itself_color->portVersion);
181 if ( strcmp(name, "device") == 0 )
182 return PyInt_FromLong((long)self->ob_itself->device);
183 if ( strcmp(name, "portRect") == 0 )
184 return Py_BuildValue("O&", PyMac_BuildRect, &self->ob_itself->portRect);
185 if ( strcmp(name, "visRgn") == 0 )
186 return Py_BuildValue("O&", ResObj_New, (Handle)self->ob_itself->visRgn);
187 if ( strcmp(name, "clipRgn") == 0 )
188 return Py_BuildValue("O&", ResObj_New, (Handle)self->ob_itself->clipRgn);
189 if ( strcmp(name, "pnLoc") == 0 )
190 return Py_BuildValue("O&", PyMac_BuildPoint, self->ob_itself->pnLoc);
191 if ( strcmp(name, "pnSize") == 0 )
192 return Py_BuildValue("O&", PyMac_BuildPoint, self->ob_itself->pnSize);
193 if ( strcmp(name, "pnMode") == 0 )
194 return Py_BuildValue("h", self->ob_itself->pnMode);
195 if ( strcmp(name, "pnVis") == 0 )
196 return Py_BuildValue("h", self->ob_itself->pnVis);
197 if ( strcmp(name, "txFont") == 0 )
198 return Py_BuildValue("h", self->ob_itself->txFont);
199 if ( strcmp(name, "txFace") == 0 )
200 return Py_BuildValue("h", (short)self->ob_itself->txFace);
201 if ( strcmp(name, "txMode") == 0 )
202 return Py_BuildValue("h", self->ob_itself->txMode);
203 if ( strcmp(name, "txSize") == 0 )
204 return Py_BuildValue("h", self->ob_itself->txSize);
205 if ( strcmp(name, "spExtra") == 0 )
206 return Py_BuildValue("O&", PyMac_BuildFixed, self->ob_itself->spExtra);
207 /* XXXX Add more, as needed */
208 /* This one is so we can compare grafports: */
209 if ( strcmp(name, "_id") == 0 )
210 return Py_BuildValue("l", (long)self->ob_itself);
211 }""")
213 class MyBMObjectDefinition(GlobalObjectDefinition):
214 def outputCheckNewArg(self):
215 Output("if (itself == NULL) return PyMac_Error(resNotFound);")
216 def outputStructMembers(self):
217 # We need to more items: a pointer to privately allocated data
218 # and a python object we're referring to.
219 Output("%s ob_itself;", self.itselftype)
220 Output("PyObject *referred_object;")
221 Output("BitMap *referred_bitmap;")
222 def outputInitStructMembers(self):
223 Output("it->ob_itself = %sitself;", self.argref)
224 Output("it->referred_object = NULL;")
225 Output("it->referred_bitmap = NULL;")
226 def outputCleanupStructMembers(self):
227 Output("Py_XDECREF(self->referred_object);")
228 Output("if (self->referred_bitmap) free(self->referred_bitmap);")
229 def outputGetattrHook(self):
230 Output("""if ( strcmp(name, "baseAddr") == 0 )
231 return PyInt_FromLong((long)self->ob_itself->baseAddr);
232 if ( strcmp(name, "rowBytes") == 0 )
233 return PyInt_FromLong((long)self->ob_itself->rowBytes);
234 if ( strcmp(name, "bounds") == 0 )
235 return Py_BuildValue("O&", PyMac_BuildRect, &self->ob_itself->bounds);
236 /* XXXX Add more, as needed */
237 if ( strcmp(name, "bitmap_data") == 0 )
238 return PyString_FromStringAndSize((char *)self->ob_itself, sizeof(BitMap));
239 if ( strcmp(name, "pixmap_data") == 0 )
240 return PyString_FromStringAndSize((char *)self->ob_itself, sizeof(PixMap));
241 """)
243 # This object is instanciated once, and will access qd globals.
244 class QDGlobalsAccessObjectDefinition(ObjectDefinition):
245 def outputStructMembers(self):
246 pass
247 def outputNew(self):
248 Output()
249 Output("%sPyObject *%s_New()", self.static, self.prefix)
250 OutLbrace()
251 Output("%s *it;", self.objecttype)
252 Output("it = PyObject_NEW(%s, &%s);", self.objecttype, self.typename)
253 Output("if (it == NULL) return NULL;")
254 Output("return (PyObject *)it;")
255 OutRbrace()
256 def outputConvert(self):
257 pass
258 def outputCleanupStructMembers(self):
259 pass
261 def outputGetattrHook(self):
262 Output("""
263 if ( strcmp(name, "arrow") == 0 )
264 return PyString_FromStringAndSize((char *)&qd.arrow, sizeof(qd.arrow));
265 if ( strcmp(name, "black") == 0 )
266 return PyString_FromStringAndSize((char *)&qd.black, sizeof(qd.black));
267 if ( strcmp(name, "white") == 0 )
268 return PyString_FromStringAndSize((char *)&qd.white, sizeof(qd.white));
269 if ( strcmp(name, "gray") == 0 )
270 return PyString_FromStringAndSize((char *)&qd.gray, sizeof(qd.gray));
271 if ( strcmp(name, "ltGray") == 0 )
272 return PyString_FromStringAndSize((char *)&qd.ltGray, sizeof(qd.ltGray));
273 if ( strcmp(name, "dkGray") == 0 )
274 return PyString_FromStringAndSize((char *)&qd.dkGray, sizeof(qd.dkGray));
275 if ( strcmp(name, "screenBits") == 0 )
276 return BMObj_New(&qd.screenBits);
277 if ( strcmp(name, "thePort") == 0 )
278 return GrafObj_New(qd.thePort);
279 if ( strcmp(name, "randSeed") == 0 )
280 return Py_BuildValue("l", &qd.randSeed);
281 """)
283 # Create the generator groups and link them
284 module = MacModule(MODNAME, MODPREFIX, includestuff, finalstuff, initstuff, variablestuff)
285 ##r_object = Region_ObjectDefinition('Region', 'QdRgn', 'RgnHandle')
286 ##po_object = Polygon_ObjectDefinition('Polygon', 'QdPgn', 'PolyHandle')
287 ##module.addobject(r_object)
288 ##module.addobject(po_object)
289 gr_object = MyGRObjectDefinition("GrafPort", "GrafObj", "GrafPtr")
290 module.addobject(gr_object)
291 bm_object = MyBMObjectDefinition("BitMap", "BMObj", "BitMapPtr")
292 module.addobject(bm_object)
293 qd_object = QDGlobalsAccessObjectDefinition("QDGlobalsAccess", "QDGA", "XXXX")
294 module.addobject(qd_object)
297 # Create the generator classes used to populate the lists
298 Function = OSErrFunctionGenerator
299 Method = OSErrMethodGenerator
301 # Create and populate the lists
302 functions = []
303 methods = []
304 execfile(INPUTFILE)
305 execfile(EXTRAFILE)
307 # add the populated lists to the generator groups
308 # (in a different wordl the scan program would generate this)
309 for f in functions: module.add(f)
310 ##for f in r_methods: r_object.add(f)
311 ##for f in po_methods: po_object.add(f)
314 # We manually generate a routine to create a BitMap from python data.
316 BitMap_body = """
317 BitMap *ptr;
318 PyObject *source;
319 Rect bounds;
320 int rowbytes;
321 char *data;
323 if ( !PyArg_ParseTuple(_args, "O!iO&", &PyString_Type, &source, &rowbytes, PyMac_GetRect,
324 &bounds) )
325 return NULL;
326 data = PyString_AsString(source);
327 if ((ptr=(BitMap *)malloc(sizeof(BitMap))) == NULL )
328 return PyErr_NoMemory();
329 ptr->baseAddr = (Ptr)data;
330 ptr->rowBytes = rowbytes;
331 ptr->bounds = bounds;
332 if ( (_res = BMObj_New(ptr)) == NULL ) {
333 free(ptr);
334 return NULL;
336 ((BitMapObject *)_res)->referred_object = source;
337 Py_INCREF(source);
338 ((BitMapObject *)_res)->referred_bitmap = ptr;
339 return _res;
342 f = ManualGenerator("BitMap", BitMap_body)
343 f.docstring = lambda: """Take (string, int, Rect) argument and create BitMap"""
344 module.add(f)
347 # And again, for turning a correctly-formatted structure into the object
349 RawBitMap_body = """
350 BitMap *ptr;
351 PyObject *source;
353 if ( !PyArg_ParseTuple(_args, "O!", &PyString_Type, &source) )
354 return NULL;
355 if ( PyString_Size(source) != sizeof(BitMap) && PyString_Size(source) != sizeof(PixMap) ) {
356 PyErr_BadArgument();
357 return NULL;
359 ptr = (BitMapPtr)PyString_AsString(source);
360 if ( (_res = BMObj_New(ptr)) == NULL ) {
361 return NULL;
363 ((BitMapObject *)_res)->referred_object = source;
364 Py_INCREF(source);
365 return _res;
368 f = ManualGenerator("RawBitMap", RawBitMap_body)
369 f.docstring = lambda: """Take string BitMap and turn into BitMap object"""
370 module.add(f)
372 # generate output (open the output file as late as possible)
373 SetOutputFileName(OUTPUTFILE)
374 module.generate()
375 SetOutputFile() # Close it