Home | History | Annotate | Download | only in qd
      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).
      5 
      6 import string
      7 
      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
     12 
     13 # The following is *usually* unchanged but may still require tuning
     14 MODPREFIX = 'Qd'                        # 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
     20 
     21 from macsupport import *
     22 
     23 # Create the type objects
     24 
     25 class TextThingieClass(FixedInputBufferType):
     26     def getargsCheck(self, name):
     27         Output("/* Fool compiler warnings */")
     28         Output("%s__in_len__ = %s__in_len__;", name, name)
     29 
     30     def declareSize(self, name):
     31         Output("int %s__in_len__;", name)
     32 
     33 TextThingie = TextThingieClass(None)
     34 
     35 # These are temporary!
     36 RgnHandle = OpaqueByValueType("RgnHandle", "ResObj")
     37 OptRgnHandle = OpaqueByValueType("RgnHandle", "OptResObj")
     38 PicHandle = OpaqueByValueType("PicHandle", "ResObj")
     39 PolyHandle = OpaqueByValueType("PolyHandle", "ResObj")
     40 PixMapHandle = OpaqueByValueType("PixMapHandle", "ResObj")
     41 PixPatHandle = OpaqueByValueType("PixPatHandle", "ResObj")
     42 PatHandle = OpaqueByValueType("PatHandle", "ResObj")
     43 CursHandle = OpaqueByValueType("CursHandle", "ResObj")
     44 CCrsrHandle = OpaqueByValueType("CCrsrHandle", "ResObj")
     45 CIconHandle = OpaqueByValueType("CIconHandle", "ResObj")
     46 CTabHandle = OpaqueByValueType("CTabHandle", "ResObj")
     47 ITabHandle = OpaqueByValueType("ITabHandle", "ResObj")
     48 GDHandle = OpaqueByValueType("GDHandle", "ResObj")
     49 CGrafPtr = OpaqueByValueType("CGrafPtr", "GrafObj")
     50 GrafPtr = OpaqueByValueType("GrafPtr", "GrafObj")
     51 BitMap_ptr = OpaqueByValueType("BitMapPtr", "BMObj")
     52 const_BitMap_ptr = OpaqueByValueType("const BitMap *", "BMObj")
     53 BitMap = OpaqueType("BitMap", "BMObj_NewCopied", "BUG")
     54 RGBColor = OpaqueType('RGBColor', 'QdRGB')
     55 RGBColor_ptr = RGBColor
     56 FontInfo = OpaqueType('FontInfo', 'QdFI')
     57 Component = OpaqueByValueType('Component', 'CmpObj')
     58 ComponentInstance = OpaqueByValueType('ComponentInstance', 'CmpInstObj')
     59 
     60 Cursor = StructOutputBufferType('Cursor')
     61 Cursor_ptr = StructInputBufferType('Cursor')
     62 Pattern = StructOutputBufferType('Pattern')
     63 Pattern_ptr = StructInputBufferType('Pattern')
     64 PenState = StructOutputBufferType('PenState')
     65 PenState_ptr = StructInputBufferType('PenState')
     66 TruncCode = Type("TruncCode", "h")
     67 
     68 includestuff = includestuff + """
     69 #include <Carbon/Carbon.h>
     70 
     71 #ifdef USE_TOOLBOX_OBJECT_GLUE
     72 extern PyObject *_GrafObj_New(GrafPtr);
     73 extern int _GrafObj_Convert(PyObject *, GrafPtr *);
     74 extern PyObject *_BMObj_New(BitMapPtr);
     75 extern int _BMObj_Convert(PyObject *, BitMapPtr *);
     76 extern PyObject *_QdRGB_New(RGBColorPtr);
     77 extern int _QdRGB_Convert(PyObject *, RGBColorPtr);
     78 
     79 #define GrafObj_New _GrafObj_New
     80 #define GrafObj_Convert _GrafObj_Convert
     81 #define BMObj_New _BMObj_New
     82 #define BMObj_Convert _BMObj_Convert
     83 #define QdRGB_New _QdRGB_New
     84 #define QdRGB_Convert _QdRGB_Convert
     85 #endif
     86 
     87 static PyObject *BMObj_NewCopied(BitMapPtr);
     88 
     89 /*
     90 ** Parse/generate RGB records
     91 */
     92 PyObject *QdRGB_New(RGBColorPtr itself)
     93 {
     94 
     95         return Py_BuildValue("lll", (long)itself->red, (long)itself->green, (long)itself->blue);
     96 }
     97 
     98 int QdRGB_Convert(PyObject *v, RGBColorPtr p_itself)
     99 {
    100         long red, green, blue;
    101 
    102         if( !PyArg_ParseTuple(v, "lll", &red, &green, &blue) )
    103                 return 0;
    104         p_itself->red = (unsigned short)red;
    105         p_itself->green = (unsigned short)green;
    106         p_itself->blue = (unsigned short)blue;
    107         return 1;
    108 }
    109 
    110 /*
    111 ** Generate FontInfo records
    112 */
    113 static
    114 PyObject *QdFI_New(FontInfo *itself)
    115 {
    116 
    117         return Py_BuildValue("hhhh", itself->ascent, itself->descent,
    118                         itself->widMax, itself->leading);
    119 }
    120 """
    121 
    122 finalstuff = finalstuff + """
    123 /* Like BMObj_New, but the original bitmap data structure is copied (and
    124 ** released when the object is released)
    125 */
    126 PyObject *BMObj_NewCopied(BitMapPtr itself)
    127 {
    128         BitMapObject *it;
    129         BitMapPtr itself_copy;
    130 
    131         if ((itself_copy=(BitMapPtr)malloc(sizeof(BitMap))) == NULL)
    132                 return PyErr_NoMemory();
    133         *itself_copy = *itself;
    134         it = (BitMapObject *)BMObj_New(itself_copy);
    135         it->referred_bitmap = itself_copy;
    136         return (PyObject *)it;
    137 }
    138 
    139 """
    140 
    141 variablestuff = ""
    142 
    143 initstuff = initstuff + """
    144         PyMac_INIT_TOOLBOX_OBJECT_NEW(BitMapPtr, BMObj_New);
    145         PyMac_INIT_TOOLBOX_OBJECT_CONVERT(BitMapPtr, BMObj_Convert);
    146         PyMac_INIT_TOOLBOX_OBJECT_NEW(GrafPtr, GrafObj_New);
    147         PyMac_INIT_TOOLBOX_OBJECT_CONVERT(GrafPtr, GrafObj_Convert);
    148         PyMac_INIT_TOOLBOX_OBJECT_NEW(RGBColorPtr, QdRGB_New);
    149         PyMac_INIT_TOOLBOX_OBJECT_CONVERT(RGBColor, QdRGB_Convert);
    150 """
    151 
    152 ## not yet...
    153 ##
    154 ##class Region_ObjectDefinition(GlobalObjectDefinition):
    155 ##      def outputCheckNewArg(self):
    156 ##              Output("if (itself == NULL) return PyMac_Error(resNotFound);")
    157 ##      def outputFreeIt(self, itselfname):
    158 ##              Output("DisposeRegion(%s);", itselfname)
    159 ##
    160 ##class Polygon_ObjectDefinition(GlobalObjectDefinition):
    161 ##      def outputCheckNewArg(self):
    162 ##              Output("if (itself == NULL) return PyMac_Error(resNotFound);")
    163 ##      def outputFreeIt(self, itselfname):
    164 ##              Output("KillPoly(%s);", itselfname)
    165 
    166 class MyGRObjectDefinition(PEP253Mixin, GlobalObjectDefinition):
    167     getsetlist = [
    168             ('visRgn',
    169             """RgnHandle h=NewRgn(); /* XXXX wrong dispose routine */
    170             return Py_BuildValue("O&", ResObj_New, (Handle)GetPortVisibleRegion(self->ob_itself, h));
    171             """,
    172             None,
    173             "Convenience attribute: return a copy of the visible region"
    174             ), (
    175             'clipRgn',
    176             """RgnHandle h=NewRgn(); /* XXXX wrong dispose routine */
    177             return Py_BuildValue("O&", ResObj_New, (Handle)GetPortClipRegion(self->ob_itself, h));
    178             """,
    179             None,
    180             "Convenience attribute: return a copy of the clipping region"
    181             )]
    182     def outputCheckNewArg(self):
    183         Output("if (itself == NULL) return PyMac_Error(resNotFound);")
    184     def outputCheckConvertArg(self):
    185         Output("#if 1")
    186         OutLbrace()
    187         Output("WindowRef win;")
    188         OutLbrace("if (WinObj_Convert(v, &win) && v)")
    189         Output("*p_itself = (GrafPtr)GetWindowPort(win);")
    190         Output("return 1;")
    191         OutRbrace()
    192         Output("PyErr_Clear();")
    193         OutRbrace()
    194         Output("#else")
    195         OutLbrace("if (DlgObj_Check(v))")
    196         Output("DialogRef dlg = (DialogRef)((GrafPortObject *)v)->ob_itself;")
    197         Output("*p_itself = (GrafPtr)GetWindowPort(GetDialogWindow(dlg));")
    198         Output("return 1;")
    199         OutRbrace()
    200         OutLbrace("if (WinObj_Check(v))")
    201         Output("WindowRef win = (WindowRef)((GrafPortObject *)v)->ob_itself;")
    202         Output("*p_itself = (GrafPtr)GetWindowPort(win);")
    203         Output("return 1;")
    204         OutRbrace()
    205         Output("#endif")
    206 
    207 class MyBMObjectDefinition(PEP253Mixin, GlobalObjectDefinition):
    208     getsetlist = [
    209     (
    210     'baseAddr',
    211     'return PyInt_FromLong((long)self->ob_itself->baseAddr);',
    212     None,
    213     None
    214     ), (
    215     'rowBytes',
    216     'return PyInt_FromLong((long)self->ob_itself->rowBytes);',
    217     None,
    218     None
    219     ), (
    220     'bounds',
    221     'return Py_BuildValue("O&", PyMac_BuildRect, &self->ob_itself->bounds);',
    222     None,
    223     None
    224     ), (
    225     'bitmap_data',
    226     'return PyString_FromStringAndSize((char *)self->ob_itself, sizeof(BitMap));',
    227     None,
    228     None
    229     ), (
    230     'pixmap_data',
    231     'return PyString_FromStringAndSize((char *)self->ob_itself, sizeof(PixMap));',
    232     None,
    233     None
    234     )]
    235     def outputCheckNewArg(self):
    236         Output("if (itself == NULL) return PyMac_Error(resNotFound);")
    237     def outputStructMembers(self):
    238         # We need to more items: a pointer to privately allocated data
    239         # and a python object we're referring to.
    240         Output("%s ob_itself;", self.itselftype)
    241         Output("PyObject *referred_object;")
    242         Output("BitMap *referred_bitmap;")
    243     def outputInitStructMembers(self):
    244         Output("it->ob_itself = %sitself;", self.argref)
    245         Output("it->referred_object = NULL;")
    246         Output("it->referred_bitmap = NULL;")
    247     def outputCleanupStructMembers(self):
    248         Output("Py_XDECREF(self->referred_object);")
    249         Output("if (self->referred_bitmap) free(self->referred_bitmap);")
    250 
    251 # Create the generator groups and link them
    252 module = MacModule(MODNAME, MODPREFIX, includestuff, finalstuff, initstuff, variablestuff)
    253 ##r_object = Region_ObjectDefinition('Region', 'QdRgn', 'RgnHandle')
    254 ##po_object = Polygon_ObjectDefinition('Polygon', 'QdPgn', 'PolyHandle')
    255 ##module.addobject(r_object)
    256 ##module.addobject(po_object)
    257 gr_object = MyGRObjectDefinition("GrafPort", "GrafObj", "GrafPtr")
    258 module.addobject(gr_object)
    259 bm_object = MyBMObjectDefinition("BitMap", "BMObj", "BitMapPtr")
    260 module.addobject(bm_object)
    261 
    262 
    263 # Create the generator classes used to populate the lists
    264 Function = OSErrWeakLinkFunctionGenerator
    265 Method = OSErrWeakLinkMethodGenerator
    266 
    267 # Create and populate the lists
    268 functions = []
    269 gr_methods = []
    270 bm_methods = []
    271 #methods = []
    272 execfile(INPUTFILE)
    273 execfile(EXTRAFILE)
    274 
    275 # add the populated lists to the generator groups
    276 # (in a different wordl the scan program would generate this)
    277 for f in functions: module.add(f)
    278 for f in gr_methods: gr_object.add(f)
    279 for f in bm_methods: bm_object.add(f)
    280 
    281 # Manual generator: get data out of a bitmap
    282 getdata_body = """
    283 int from, length;
    284 char *cp;
    285 
    286 if ( !PyArg_ParseTuple(_args, "ii", &from, &length) )
    287         return NULL;
    288 cp = _self->ob_itself->baseAddr+from;
    289 _res = PyString_FromStringAndSize(cp, length);
    290 return _res;
    291 """
    292 f = ManualGenerator("getdata", getdata_body)
    293 f.docstring = lambda: """(int start, int size) -> string. Return bytes from the bitmap"""
    294 bm_object.add(f)
    295 
    296 # Manual generator: store data in a bitmap
    297 putdata_body = """
    298 int from, length;
    299 char *cp, *icp;
    300 
    301 if ( !PyArg_ParseTuple(_args, "is#", &from, &icp, &length) )
    302         return NULL;
    303 cp = _self->ob_itself->baseAddr+from;
    304 memcpy(cp, icp, length);
    305 Py_INCREF(Py_None);
    306 _res = Py_None;
    307 return _res;
    308 """
    309 f = ManualGenerator("putdata", putdata_body)
    310 f.docstring = lambda: """(int start, string data). Store bytes into the bitmap"""
    311 bm_object.add(f)
    312 
    313 #
    314 # We manually generate a routine to create a BitMap from python data.
    315 #
    316 BitMap_body = """
    317 BitMap *ptr;
    318 PyObject *source;
    319 Rect bounds;
    320 int rowbytes;
    321 char *data;
    322 
    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;
    335 }
    336 ((BitMapObject *)_res)->referred_object = source;
    337 Py_INCREF(source);
    338 ((BitMapObject *)_res)->referred_bitmap = ptr;
    339 return _res;
    340 """
    341 
    342 f = ManualGenerator("BitMap", BitMap_body)
    343 f.docstring = lambda: """Take (string, int, Rect) argument and create BitMap"""
    344 module.add(f)
    345 
    346 #
    347 # And again, for turning a correctly-formatted structure into the object
    348 #
    349 RawBitMap_body = """
    350 BitMap *ptr;
    351 PyObject *source;
    352 
    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_Format(PyExc_TypeError,
    357                 "Argument size was %d, should be %d (sizeof BitMap) or %d (sizeof PixMap)",
    358                 PyString_Size(source), sizeof(BitMap), sizeof(PixMap));
    359         return NULL;
    360 }
    361 ptr = (BitMapPtr)PyString_AsString(source);
    362 if ( (_res = BMObj_New(ptr)) == NULL ) {
    363         return NULL;
    364 }
    365 ((BitMapObject *)_res)->referred_object = source;
    366 Py_INCREF(source);
    367 return _res;
    368 """
    369 
    370 f = ManualGenerator("RawBitMap", RawBitMap_body)
    371 f.docstring = lambda: """Take string BitMap and turn into BitMap object"""
    372 module.add(f)
    373 
    374 # generate output (open the output file as late as possible)
    375 SetOutputFileName(OUTPUTFILE)
    376 module.generate()
    377 SetOutputFile() # Close it
    378