2 # flp - Module to load fl forms from fd files
4 # Jack Jansen, December 1991
6 from warnings
import warnpy3k
7 warnpy3k("the flp module has been removed in Python 3.0", stacklevel
=2)
15 SPLITLINE
= '--------------------'
16 FORMLINE
= '=============== FORM ==============='
17 ENDLINE
= '=============================='
19 class error(Exception):
22 ##################################################################
23 # Part 1 - The parsing routines #
24 ##################################################################
27 # Externally visible function. Load form.
29 def parse_form(filename
, formname
):
30 forms
= checkcache(filename
)
32 forms
= parse_forms(filename
)
33 if forms
.has_key(formname
):
34 return forms
[formname
]
36 raise error
, 'No such form in fd file'
39 # Externally visible function. Load all forms.
41 def parse_forms(filename
):
42 forms
= checkcache(filename
)
43 if forms
is not None: return forms
44 fp
= _open_formfile(filename
)
45 nforms
= _parse_fd_header(fp
)
47 for i
in range(nforms
):
48 form
= _parse_fd_form(fp
, None)
49 forms
[form
[0].Name
] = form
50 writecache(filename
, forms
)
54 # Internal: see if a cached version of the file exists
57 _internal_cache
= {} # Used by frozen scripts only
58 def checkcache(filename
):
59 if _internal_cache
.has_key(filename
):
60 altforms
= _internal_cache
[filename
]
61 return _unpack_cache(altforms
)
63 fp
, filename
= _open_formfile2(filename
)
65 cachename
= filename
+ 'c'
67 fp
= open(cachename
, 'r')
69 #print 'flp: no cache file', cachename
72 if fp
.read(4) != MAGIC
:
73 print 'flp: bad magic word in cache file', cachename
75 cache_mtime
= rdlong(fp
)
76 file_mtime
= getmtime(filename
)
77 if cache_mtime
!= file_mtime
:
78 #print 'flp: outdated cache file', cachename
80 #print 'flp: valid cache file', cachename
81 altforms
= marshal
.load(fp
)
82 return _unpack_cache(altforms
)
86 def _unpack_cache(altforms
):
88 for name
in altforms
.keys():
89 altobj
, altlist
= altforms
[name
]
93 for altobj
in altlist
:
97 forms
[name
] = obj
, list
102 if len(s
) != 4: return None
103 a
, b
, c
, d
= s
[0], s
[1], s
[2], s
[3]
104 return ord(a
)<<24 |
ord(b
)<<16 |
ord(c
)<<8 |
ord(d
)
107 a
, b
, c
, d
= (x
>>24)&0xff, (x
>>16)&0xff, (x
>>8)&0xff, x
&0xff
108 fp
.write(chr(a
) + chr(b
) + chr(c
) + chr(d
))
110 def getmtime(filename
):
112 from stat
import ST_MTIME
114 return os
.stat(filename
)[ST_MTIME
]
119 # Internal: write cached version of the form (parsing is too slow!)
121 def writecache(filename
, forms
):
123 fp
, filename
= _open_formfile2(filename
)
125 cachename
= filename
+ 'c'
127 fp
= open(cachename
, 'w')
129 print 'flp: can\'t create cache file', cachename
131 fp
.write('\0\0\0\0') # Seek back and write MAGIC when done
132 wrlong(fp
, getmtime(filename
))
133 altforms
= _pack_cache(forms
)
134 marshal
.dump(altforms
, fp
)
138 #print 'flp: wrote cache file', cachename
141 # External: print some statements that set up the internal cache.
142 # This is for use with the "freeze" script. You should call
143 # flp.freeze(filename) for all forms used by the script, and collect
144 # the output on a file in a module file named "frozenforms.py". Then
145 # in the main program of the script import frozenforms.
146 # (Don't forget to take this out when using the unfrozen version of
149 def freeze(filename
):
150 forms
= parse_forms(filename
)
151 altforms
= _pack_cache(forms
)
153 print 'flp._internal_cache[', repr(filename
), '] =', altforms
156 # Internal: create the data structure to be placed in the cache
158 def _pack_cache(forms
):
160 for name
in forms
.keys():
161 obj
, list = forms
[name
]
162 altobj
= obj
.__dict
__
164 for obj
in list: altlist
.append(obj
.__dict
__)
165 altforms
[name
] = altobj
, altlist
169 # Internal: Locate form file (using PYTHONPATH) and open file
171 def _open_formfile(filename
):
172 return _open_formfile2(filename
)[0]
174 def _open_formfile2(filename
):
175 if filename
[-3:] != '.fd':
176 filename
= filename
+ '.fd'
177 if filename
[0] == '/':
179 fp
= open(filename
,'r')
184 pn
= os
.path
.join(pc
, filename
)
192 raise error
, 'Cannot find forms file ' + filename
196 # Internal: parse the fd file header, return number of forms
198 def _parse_fd_header(file):
199 # First read the magic header line
200 datum
= _parse_1_line(file)
201 if datum
!= ('Magic', 12321):
202 raise error
, 'Not a forms definition file'
203 # Now skip until we know number of forms
205 datum
= _parse_1_line(file)
206 if type(datum
) == type(()) and datum
[0] == 'Numberofforms':
210 # Internal: parse fd form, or skip if name doesn't match.
211 # the special value None means 'always parse it'.
213 def _parse_fd_form(file, name
):
214 datum
= _parse_1_line(file)
215 if datum
!= FORMLINE
:
216 raise error
, 'Missing === FORM === line'
217 form
= _parse_object(file)
218 if form
.Name
== name
or name
is None:
220 for j
in range(form
.Numberofobjects
):
221 obj
= _parse_object(file)
225 for j
in range(form
.Numberofobjects
):
230 # Internal class: a convenient place to store object info fields
233 def add(self
, name
, value
):
234 self
.__dict
__[name
] = value
235 def make(self
, dict):
236 for name
in dict.keys():
237 self
.add(name
, dict[name
])
240 # Internal parsing routines.
242 def _parse_string(str):
244 s
= '\'' + str + '\''
254 def _parse_numlist(str):
255 slist
= string
.split(str)
258 nlist
.append(_parse_num(i
))
261 # This dictionary maps item names to parsing routines.
262 # If no routine is given '_parse_num' is default.
264 'Name': _parse_string
, \
265 'Box': _parse_numlist
, \
266 'Colors': _parse_numlist
, \
267 'Label': _parse_string
, \
268 'Name': _parse_string
, \
269 'Callback': _parse_string
, \
270 'Argument': _parse_string
}
272 # This function parses a line, and returns either
273 # a string or a tuple (name,value)
276 prog
= re
.compile('^([^:]*): *(.*)')
278 def _parse_line(line
):
279 match
= prog
.match(line
)
282 name
, value
= match
.group(1, 2)
284 name
= string
.join(string
.split(name
),'')
285 name
= string
.lower(name
)
286 name
= string
.capitalize(name
)
288 pf
= _parse_func
[name
]
295 line
= file.readline()
300 def _parse_1_line(file):
301 line
= _readline(file)
303 line
= _readline(file)
304 return _parse_line(line
)
306 def _skip_object(file):
308 while not line
in (SPLITLINE
, FORMLINE
, ENDLINE
):
310 line
= _readline(file)
314 def _parse_object(file):
318 datum
= _parse_1_line(file)
319 if datum
in (SPLITLINE
, FORMLINE
, ENDLINE
):
320 if datum
== FORMLINE
:
323 if type(datum
) is not type(()) or len(datum
) != 2:
324 raise error
, 'Parse error, illegal line in object: '+datum
325 obj
.add(datum
[0], datum
[1])
327 #################################################################
328 # Part 2 - High-level object/form creation routines #
329 #################################################################
332 # External - Create a form an link to an instance variable.
334 def create_full_form(inst
, (fdata
, odatalist
)):
335 form
= create_form(fdata
)
336 exec 'inst.'+fdata
.Name
+' = form\n'
337 for odata
in odatalist
:
338 create_object_instance(inst
, form
, odata
)
341 # External - Merge a form into an existing form in an instance
344 def merge_full_form(inst
, form
, (fdata
, odatalist
)):
345 exec 'inst.'+fdata
.Name
+' = form\n'
346 if odatalist
[0].Class
!= FL
.BOX
:
347 raise error
, 'merge_full_form() expects FL.BOX as first obj'
348 for odata
in odatalist
[1:]:
349 create_object_instance(inst
, form
, odata
)
352 #################################################################
353 # Part 3 - Low-level object/form creation routines #
354 #################################################################
357 # External Create_form - Create form from parameters
359 def create_form(fdata
):
361 return fl
.make_form(FL
.NO_BOX
, fdata
.Width
, fdata
.Height
)
364 # External create_object - Create an object. Make sure there are
365 # no callbacks. Returns the object created.
367 def create_object(form
, odata
):
368 obj
= _create_object(form
, odata
)
370 raise error
, 'Creating free object with callback'
373 # External create_object_instance - Create object in an instance.
375 def create_object_instance(inst
, form
, odata
):
376 obj
= _create_object(form
, odata
)
378 cbfunc
= eval('inst.'+odata
.Callback
)
379 obj
.set_call_back(cbfunc
, odata
.Argument
)
381 exec 'inst.' + odata
.Name
+ ' = obj\n'
383 # Internal _create_object: Create the object and fill options
385 def _create_object(form
, odata
):
386 crfunc
= _select_crfunc(form
, odata
.Class
)
387 obj
= crfunc(odata
.Type
, odata
.Box
[0], odata
.Box
[1], odata
.Box
[2], \
388 odata
.Box
[3], odata
.Label
)
389 if not odata
.Class
in (FL
.BEGIN_GROUP
, FL
.END_GROUP
):
390 obj
.boxtype
= odata
.Boxtype
391 obj
.col1
= odata
.Colors
[0]
392 obj
.col2
= odata
.Colors
[1]
393 obj
.align
= odata
.Alignment
394 obj
.lstyle
= odata
.Style
395 obj
.lsize
= odata
.Size
396 obj
.lcol
= odata
.Lcol
399 # Internal crfunc: helper function that returns correct create function
401 def _select_crfunc(fm
, cl
):
402 if cl
== FL
.BEGIN_GROUP
: return fm
.bgn_group
403 elif cl
== FL
.END_GROUP
: return fm
.end_group
404 elif cl
== FL
.BITMAP
: return fm
.add_bitmap
405 elif cl
== FL
.BOX
: return fm
.add_box
406 elif cl
== FL
.BROWSER
: return fm
.add_browser
407 elif cl
== FL
.BUTTON
: return fm
.add_button
408 elif cl
== FL
.CHART
: return fm
.add_chart
409 elif cl
== FL
.CHOICE
: return fm
.add_choice
410 elif cl
== FL
.CLOCK
: return fm
.add_clock
411 elif cl
== FL
.COUNTER
: return fm
.add_counter
412 elif cl
== FL
.DIAL
: return fm
.add_dial
413 elif cl
== FL
.FREE
: return fm
.add_free
414 elif cl
== FL
.INPUT
: return fm
.add_input
415 elif cl
== FL
.LIGHTBUTTON
: return fm
.add_lightbutton
416 elif cl
== FL
.MENU
: return fm
.add_menu
417 elif cl
== FL
.POSITIONER
: return fm
.add_positioner
418 elif cl
== FL
.ROUNDBUTTON
: return fm
.add_roundbutton
419 elif cl
== FL
.SLIDER
: return fm
.add_slider
420 elif cl
== FL
.VALSLIDER
: return fm
.add_valslider
421 elif cl
== FL
.TEXT
: return fm
.add_text
422 elif cl
== FL
.TIMER
: return fm
.add_timer
424 raise error
, 'Unknown object type: %r' % (cl
,)
430 if len(sys
.argv
) == 2:
431 forms
= parse_forms(sys
.argv
[1])
433 print 'parse time:', 0.001*(t1
-t0
), 'sec.'
438 elif len(sys
.argv
) == 3:
439 form
= parse_form(sys
.argv
[1], sys
.argv
[2])
441 print 'parse time:', round(t1
-t0
, 3), 'sec.'
444 print 'Usage: test fdfile [form]'
446 def _printform(form
):
449 print 'Form ', f
.Name
, ', size: ', f
.Width
, f
.Height
, ' Nobj ', f
.Numberofobjects
451 print ' Obj ', i
.Name
, ' type ', i
.Class
, i
.Type
452 print ' Box ', i
.Box
, ' btype ', i
.Boxtype
453 print ' Label ', i
.Label
, ' size/style/col/align ', i
.Size
,i
.Style
, i
.Lcol
, i
.Alignment
454 print ' cols ', i
.Colors
455 print ' cback ', i
.Callback
, i
.Argument