home *** CD-ROM | disk | FTP | other *** search
/ linuxmafia.com 2016 / linuxmafia.com.tar / linuxmafia.com / pub / palmos / pippy-0.6beta-src.tar.gz / pippy-0.6beta-src.tar / pippy-0.6beta-src / src / Lib / plat-irix6 / flp.py < prev    next >
Text File  |  2000-12-21  |  13KB  |  451 lines

  1. #
  2. # flp - Module to load fl forms from fd files
  3. #
  4. # Jack Jansen, December 1991
  5. #
  6. import string
  7. import os
  8. import sys
  9. import FL
  10.  
  11. SPLITLINE = '--------------------'
  12. FORMLINE = '=============== FORM ==============='
  13. ENDLINE = '=============================='
  14.  
  15. error = 'flp.error'
  16.  
  17. ##################################################################
  18. #    Part 1 - The parsing routines                               #
  19. ##################################################################
  20.  
  21. #
  22. # Externally visible function. Load form.
  23. #
  24. def parse_form(filename, formname):
  25.     forms = checkcache(filename)
  26.     if forms is None:
  27.         forms = parse_forms(filename)
  28.     if forms.has_key(formname):
  29.         return forms[formname]
  30.     else:
  31.         raise error, 'No such form in fd file'
  32.  
  33. #
  34. # Externally visible function. Load all forms.
  35. #
  36. def parse_forms(filename):
  37.     forms = checkcache(filename)
  38.     if forms != None: return forms
  39.     fp = _open_formfile(filename)
  40.     nforms = _parse_fd_header(fp)
  41.     forms = {}
  42.     for i in range(nforms):
  43.         form = _parse_fd_form(fp, None)
  44.         forms[form[0].Name] = form
  45.     writecache(filename, forms)
  46.     return forms
  47.  
  48. #
  49. # Internal: see if a cached version of the file exists
  50. #
  51. MAGIC = '.fdc'
  52. _internal_cache = {}                    # Used by frozen scripts only
  53. def checkcache(filename):
  54.     if _internal_cache.has_key(filename):
  55.         altforms = _internal_cache[filename]
  56.         return _unpack_cache(altforms)
  57.     import marshal
  58.     fp, filename = _open_formfile2(filename)
  59.     fp.close()
  60.     cachename = filename + 'c'
  61.     try:
  62.         fp = open(cachename, 'r')
  63.     except IOError:
  64.         #print 'flp: no cache file', cachename
  65.         return None
  66.     try:
  67.         if fp.read(4) != MAGIC:
  68.             print 'flp: bad magic word in cache file', cachename
  69.             return None
  70.         cache_mtime = rdlong(fp)
  71.         file_mtime = getmtime(filename)
  72.         if cache_mtime != file_mtime:
  73.             #print 'flp: outdated cache file', cachename
  74.             return None
  75.         #print 'flp: valid cache file', cachename
  76.         altforms = marshal.load(fp)
  77.         return _unpack_cache(altforms)
  78.     finally:
  79.         fp.close()
  80.  
  81. def _unpack_cache(altforms):
  82.         forms = {}
  83.         for name in altforms.keys():
  84.             altobj, altlist = altforms[name]
  85.             obj = _newobj()
  86.             obj.make(altobj)
  87.             list = []
  88.             for altobj in altlist:
  89.                 nobj = _newobj()
  90.                 nobj.make(altobj)
  91.                 list.append(nobj)
  92.             forms[name] = obj, list
  93.         return forms
  94.  
  95. def rdlong(fp):
  96.     s = fp.read(4)
  97.     if len(s) != 4: return None
  98.     a, b, c, d = s[0], s[1], s[2], s[3]
  99.     return ord(a)<<24 | ord(b)<<16 | ord(c)<<8 | ord(d)
  100.  
  101. def wrlong(fp, x):
  102.     a, b, c, d = (x>>24)&0xff, (x>>16)&0xff, (x>>8)&0xff, x&0xff
  103.     fp.write(chr(a) + chr(b) + chr(c) + chr(d))
  104.  
  105. def getmtime(filename):
  106.     import os
  107.     from stat import ST_MTIME
  108.     try:
  109.         return os.stat(filename)[ST_MTIME]
  110.     except os.error:
  111.         return None
  112.  
  113. #
  114. # Internal: write cached version of the form (parsing is too slow!)
  115. #
  116. def writecache(filename, forms):
  117.     import marshal
  118.     fp, filename = _open_formfile2(filename)
  119.     fp.close()
  120.     cachename = filename + 'c'
  121.     try:
  122.         fp = open(cachename, 'w')
  123.     except IOError:
  124.         print 'flp: can\'t create cache file', cachename
  125.         return # Never mind
  126.     fp.write('\0\0\0\0') # Seek back and write MAGIC when done
  127.     wrlong(fp, getmtime(filename))
  128.     altforms = _pack_cache(forms)
  129.     marshal.dump(altforms, fp)
  130.     fp.seek(0)
  131.     fp.write(MAGIC)
  132.     fp.close()
  133.     #print 'flp: wrote cache file', cachename
  134.  
  135. #
  136. # External: print some statements that set up the internal cache.
  137. # This is for use with the "freeze" script.  You should call
  138. # flp.freeze(filename) for all forms used by the script, and collect
  139. # the output on a file in a module file named "frozenforms.py".  Then
  140. # in the main program of the script import frozenforms.
  141. # (Don't forget to take this out when using the unfrozen version of
  142. # the script!)
  143. #
  144. def freeze(filename):
  145.     forms = parse_forms(filename)
  146.     altforms = _pack_cache(forms)
  147.     print 'import flp'
  148.     print 'flp._internal_cache[', `filename`, '] =', altforms
  149.  
  150. #
  151. # Internal: create the data structure to be placed in the cache
  152. #
  153. def _pack_cache(forms):
  154.     altforms = {}
  155.     for name in forms.keys():
  156.         obj, list = forms[name]
  157.         altobj = obj.__dict__
  158.         altlist = []
  159.         for obj in list: altlist.append(obj.__dict__)
  160.         altforms[name] = altobj, altlist
  161.     return altforms
  162.  
  163. #
  164. # Internal: Locate form file (using PYTHONPATH) and open file
  165. #
  166. def _open_formfile(filename):
  167.     return _open_formfile2(filename)[0]
  168.  
  169. def _open_formfile2(filename):
  170.     if filename[-3:] <> '.fd':
  171.         filename = filename + '.fd'
  172.     if filename[0] == '/':
  173.         try:
  174.             fp = open(filename,'r')
  175.         except IOError:
  176.             fp = None
  177.     else:
  178.         for pc in sys.path:
  179.             pn = os.path.join(pc, filename)
  180.             try:
  181.                 fp = open(pn, 'r')
  182.                 filename = pn
  183.                 break
  184.             except IOError:
  185.                 fp = None
  186.     if fp == None:
  187.         raise error, 'Cannot find forms file ' + filename
  188.     return fp, filename
  189.  
  190. #
  191. # Internal: parse the fd file header, return number of forms
  192. #
  193. def _parse_fd_header(file):
  194.     # First read the magic header line
  195.     datum = _parse_1_line(file)
  196.     if datum <> ('Magic', 12321):
  197.         raise error, 'Not a forms definition file'
  198.     # Now skip until we know number of forms
  199.     while 1:
  200.         datum = _parse_1_line(file)
  201.         if type(datum) == type(()) and datum[0] == 'Numberofforms':
  202.             break
  203.     return datum[1]
  204. #
  205. # Internal: parse fd form, or skip if name doesn't match.
  206. # the special value None means 'allways parse it'.
  207. #
  208. def _parse_fd_form(file, name):
  209.     datum = _parse_1_line(file)
  210.     if datum <> FORMLINE:
  211.         raise error, 'Missing === FORM === line'
  212.     form = _parse_object(file)
  213.     if form.Name == name or name == None:
  214.         objs = []
  215.         for j in range(form.Numberofobjects):
  216.             obj = _parse_object(file)
  217.             objs.append(obj)
  218.         return (form, objs)
  219.     else:
  220.         for j in range(form.Numberofobjects):
  221.             _skip_object(file)
  222.     return None
  223.  
  224. #
  225. # Internal class: a convient place to store object info fields
  226. #
  227. class _newobj:
  228.     def add(self, name, value):
  229.         self.__dict__[name] = value
  230.     def make(self, dict):
  231.         for name in dict.keys():
  232.             self.add(name, dict[name])
  233.  
  234. #
  235. # Internal parsing routines.
  236. #
  237. def _parse_string(str):
  238.     if '\\' in str:
  239.         s = '\'' + str + '\''
  240.         try:
  241.             return eval(s)
  242.         except:
  243.             pass
  244.     return str
  245.  
  246. def _parse_num(str):
  247.     return eval(str)
  248.  
  249. def _parse_numlist(str):
  250.     slist = string.split(str)
  251.     nlist = []
  252.     for i in slist:
  253.         nlist.append(_parse_num(i))
  254.     return nlist
  255.  
  256. # This dictionary maps item names to parsing routines.
  257. # If no routine is given '_parse_num' is default.
  258. _parse_func = { \
  259.         'Name':         _parse_string, \
  260.         'Box':          _parse_numlist, \
  261.         'Colors':       _parse_numlist, \
  262.         'Label':        _parse_string, \
  263.         'Name':         _parse_string, \
  264.         'Callback':     _parse_string, \
  265.         'Argument':     _parse_string }
  266.  
  267. # This function parses a line, and returns either
  268. # a string or a tuple (name,value)
  269.  
  270. import re
  271. prog = re.compile('^([^:]*): *(.*)')
  272.  
  273. def _parse_line(line):
  274.     match = prog.match(line)
  275.     if not match:
  276.         return line
  277.     name, value = match.group(1, 2)
  278.     if name[0] == 'N':
  279.             name = string.join(string.split(name),'')
  280.             name = string.lower(name)
  281.     name = string.capitalize(name)
  282.     try:
  283.         pf = _parse_func[name]
  284.     except KeyError:
  285.         pf = _parse_num
  286.     value = pf(value)
  287.     return (name, value)
  288.  
  289. def _readline(file):
  290.     line = file.readline()
  291.     if not line:
  292.         raise EOFError
  293.     return line[:-1]
  294.         
  295. def _parse_1_line(file):
  296.     line = _readline(file)
  297.     while line == '':
  298.         line = _readline(file)
  299.     return _parse_line(line)
  300.  
  301. def _skip_object(file):
  302.     line = ''
  303.     while not line in (SPLITLINE, FORMLINE, ENDLINE):
  304.         pos = file.tell()
  305.         line = _readline(file)
  306.     if line == FORMLINE:
  307.         file.seek(pos)
  308.  
  309. def _parse_object(file):
  310.     obj = _newobj()
  311.     while 1:
  312.         pos = file.tell()
  313.         datum = _parse_1_line(file)
  314.         if datum in (SPLITLINE, FORMLINE, ENDLINE):
  315.             if datum == FORMLINE:
  316.                 file.seek(pos)
  317.             return obj
  318.         if type(datum) <> type(()) or len(datum) <> 2:
  319.             raise error, 'Parse error, illegal line in object: '+datum
  320.         obj.add(datum[0], datum[1])
  321.  
  322. #################################################################
  323. #   Part 2 - High-level object/form creation routines            #
  324. #################################################################
  325.  
  326. #
  327. # External - Create a form an link to an instance variable.
  328. #
  329. def create_full_form(inst, (fdata, odatalist)):
  330.     form = create_form(fdata)
  331.     exec 'inst.'+fdata.Name+' = form\n'
  332.     for odata in odatalist:
  333.         create_object_instance(inst, form, odata)
  334.  
  335. #
  336. # External - Merge a form into an existing form in an instance
  337. # variable.
  338. #
  339. def merge_full_form(inst, form, (fdata, odatalist)):
  340.     exec 'inst.'+fdata.Name+' = form\n'
  341.     if odatalist[0].Class <> FL.BOX:
  342.         raise error, 'merge_full_form() expects FL.BOX as first obj'
  343.     for odata in odatalist[1:]:
  344.         create_object_instance(inst, form, odata)
  345.  
  346.  
  347. #################################################################
  348. #   Part 3 - Low-level object/form creation routines            #
  349. #################################################################
  350.  
  351. #
  352. # External Create_form - Create form from parameters
  353. #
  354. def create_form(fdata):
  355.     import fl
  356.     return fl.make_form(FL.NO_BOX, fdata.Width, fdata.Height)
  357.  
  358. #
  359. # External create_object - Create an object. Make sure there are
  360. # no callbacks. Returns the object created.
  361. #
  362. def create_object(form, odata):
  363.     obj = _create_object(form, odata)
  364.     if odata.Callback:
  365.         raise error, 'Creating free object with callback'
  366.     return obj
  367. #
  368. # External create_object_instance - Create object in an instance.
  369. #
  370. def create_object_instance(inst, form, odata):
  371.     obj = _create_object(form, odata)
  372.     if odata.Callback:
  373.         cbfunc = eval('inst.'+odata.Callback)
  374.         obj.set_call_back(cbfunc, odata.Argument)
  375.     if odata.Name:
  376.         exec 'inst.' + odata.Name + ' = obj\n'
  377. #
  378. # Internal _create_object: Create the object and fill options
  379. #
  380. def _create_object(form, odata):
  381.     crfunc = _select_crfunc(form, odata.Class)
  382.     obj = crfunc(odata.Type, odata.Box[0], odata.Box[1], odata.Box[2], \
  383.             odata.Box[3], odata.Label)
  384.     if not odata.Class in (FL.BEGIN_GROUP, FL.END_GROUP):
  385.         obj.boxtype = odata.Boxtype
  386.         obj.col1 = odata.Colors[0]
  387.         obj.col2 = odata.Colors[1]
  388.         obj.align = odata.Alignment
  389.         obj.lstyle = odata.Style
  390.         obj.lsize = odata.Size
  391.         obj.lcol = odata.Lcol
  392.     return obj
  393. #
  394. # Internal crfunc: helper function that returns correct create function
  395. #
  396. def _select_crfunc(fm, cl):
  397.     if cl == FL.BEGIN_GROUP: return fm.bgn_group
  398.     elif cl == FL.END_GROUP: return fm.end_group
  399.     elif cl == FL.BITMAP: return fm.add_bitmap
  400.     elif cl == FL.BOX: return fm.add_box
  401.     elif cl == FL.BROWSER: return fm.add_browser
  402.     elif cl == FL.BUTTON: return fm.add_button
  403.     elif cl == FL.CHART: return fm.add_chart
  404.     elif cl == FL.CHOICE: return fm.add_choice
  405.     elif cl == FL.CLOCK: return fm.add_clock
  406.     elif cl == FL.COUNTER: return fm.add_counter
  407.     elif cl == FL.DIAL: return fm.add_dial
  408.     elif cl == FL.FREE: return fm.add_free
  409.     elif cl == FL.INPUT: return fm.add_input
  410.     elif cl == FL.LIGHTBUTTON: return fm.add_lightbutton
  411.     elif cl == FL.MENU: return fm.add_menu
  412.     elif cl == FL.POSITIONER: return fm.add_positioner
  413.     elif cl == FL.ROUNDBUTTON: return fm.add_roundbutton
  414.     elif cl == FL.SLIDER: return fm.add_slider
  415.     elif cl == FL.VALSLIDER: return fm.add_valslider
  416.     elif cl == FL.TEXT: return fm.add_text
  417.     elif cl == FL.TIMER: return fm.add_timer
  418.     else:
  419.         raise error, 'Unknown object type: ' + `cl`
  420.  
  421.  
  422. def test():
  423.     import time
  424.     t0 = time.time()
  425.     if len(sys.argv) == 2:
  426.         forms = parse_forms(sys.argv[1])
  427.         t1 = time.time()
  428.         print 'parse time:', 0.001*(t1-t0), 'sec.'
  429.         keys = forms.keys()
  430.         keys.sort()
  431.         for i in keys:
  432.             _printform(forms[i])
  433.     elif len(sys.argv) == 3:
  434.         form = parse_form(sys.argv[1], sys.argv[2])
  435.         t1 = time.time()
  436.         print 'parse time:', round(t1-t0, 3), 'sec.'
  437.         _printform(form)
  438.     else:
  439.         print 'Usage: test fdfile [form]'
  440.  
  441. def _printform(form):
  442.     f = form[0]
  443.     objs = form[1]
  444.     print 'Form ', f.Name, ', size: ', f.Width, f.Height, ' Nobj ', f.Numberofobjects
  445.     for i in objs:
  446.         print '  Obj ', i.Name, ' type ', i.Class, i.Type
  447.         print '    Box ', i.Box, ' btype ', i.Boxtype
  448.         print '    Label ', i.Label, ' size/style/col/align ', i.Size,i.Style, i.Lcol, i.Alignment
  449.         print '    cols ', i.Colors
  450.         print '    cback ', i.Callback, i.Argument
  451.