Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / devtools / v9 / lib / python2.4 / lib-old / fmt.py
CommitLineData
920dae64
AT
1# Text formatting abstractions
2# Note -- this module is obsolete, it's too slow anyway
3
4
5import string
6import Para
7
8
9# A formatter back-end object has one method that is called by the formatter:
10# addpara(p), where p is a paragraph object. For example:
11
12
13# Formatter back-end to do nothing at all with the paragraphs
14class NullBackEnd:
15 #
16 def __init__(self):
17 pass
18 #
19 def addpara(self, p):
20 pass
21 #
22 def bgn_anchor(self, id):
23 pass
24 #
25 def end_anchor(self, id):
26 pass
27
28
29# Formatter back-end to collect the paragraphs in a list
30class SavingBackEnd(NullBackEnd):
31 #
32 def __init__(self):
33 self.paralist = []
34 #
35 def addpara(self, p):
36 self.paralist.append(p)
37 #
38 def hitcheck(self, h, v):
39 hits = []
40 for p in self.paralist:
41 if p.top <= v <= p.bottom:
42 for id in p.hitcheck(h, v):
43 if id not in hits:
44 hits.append(id)
45 return hits
46 #
47 def extract(self):
48 text = ''
49 for p in self.paralist:
50 text = text + (p.extract())
51 return text
52 #
53 def extractpart(self, long1, long2):
54 if long1 > long2: long1, long2 = long2, long1
55 para1, pos1 = long1
56 para2, pos2 = long2
57 text = ''
58 while para1 < para2:
59 ptext = self.paralist[para1].extract()
60 text = text + ptext[pos1:]
61 pos1 = 0
62 para1 = para1 + 1
63 ptext = self.paralist[para2].extract()
64 return text + ptext[pos1:pos2]
65 #
66 def whereis(self, d, h, v):
67 total = 0
68 for i in range(len(self.paralist)):
69 p = self.paralist[i]
70 result = p.whereis(d, h, v)
71 if result is not None:
72 return i, result
73 return None
74 #
75 def roundtowords(self, long1, long2):
76 i, offset = long1
77 text = self.paralist[i].extract()
78 while offset > 0 and text[offset-1] != ' ': offset = offset-1
79 long1 = i, offset
80 #
81 i, offset = long2
82 text = self.paralist[i].extract()
83 n = len(text)
84 while offset < n-1 and text[offset] != ' ': offset = offset+1
85 long2 = i, offset
86 #
87 return long1, long2
88 #
89 def roundtoparagraphs(self, long1, long2):
90 long1 = long1[0], 0
91 long2 = long2[0], len(self.paralist[long2[0]].extract())
92 return long1, long2
93
94
95# Formatter back-end to send the text directly to the drawing object
96class WritingBackEnd(NullBackEnd):
97 #
98 def __init__(self, d, width):
99 self.d = d
100 self.width = width
101 self.lineno = 0
102 #
103 def addpara(self, p):
104 self.lineno = p.render(self.d, 0, self.lineno, self.width)
105
106
107# A formatter receives a stream of formatting instructions and assembles
108# these into a stream of paragraphs on to a back-end. The assembly is
109# parametrized by a text measurement object, which must match the output
110# operations of the back-end. The back-end is responsible for splitting
111# paragraphs up in lines of a given maximum width. (This is done because
112# in a windowing environment, when the window size changes, there is no
113# need to redo the assembly into paragraphs, but the splitting into lines
114# must be done taking the new window size into account.)
115
116
117# Formatter base class. Initialize it with a text measurement object,
118# which is used for text measurements, and a back-end object,
119# which receives the completed paragraphs. The formatting methods are:
120# setfont(font)
121# setleftindent(nspaces)
122# setjust(type) where type is 'l', 'c', 'r', or 'lr'
123# flush()
124# vspace(nlines)
125# needvspace(nlines)
126# addword(word, nspaces)
127class BaseFormatter:
128 #
129 def __init__(self, d, b):
130 # Drawing object used for text measurements
131 self.d = d
132 #
133 # BackEnd object receiving completed paragraphs
134 self.b = b
135 #
136 # Parameters of the formatting model
137 self.leftindent = 0
138 self.just = 'l'
139 self.font = None
140 self.blanklines = 0
141 #
142 # Parameters derived from the current font
143 self.space = d.textwidth(' ')
144 self.line = d.lineheight()
145 self.ascent = d.baseline()
146 self.descent = self.line - self.ascent
147 #
148 # Parameter derived from the default font
149 self.n_space = self.space
150 #
151 # Current paragraph being built
152 self.para = None
153 self.nospace = 1
154 #
155 # Font to set on the next word
156 self.nextfont = None
157 #
158 def newpara(self):
159 return Para.Para()
160 #
161 def setfont(self, font):
162 if font is None: return
163 self.font = self.nextfont = font
164 d = self.d
165 d.setfont(font)
166 self.space = d.textwidth(' ')
167 self.line = d.lineheight()
168 self.ascent = d.baseline()
169 self.descent = self.line - self.ascent
170 #
171 def setleftindent(self, nspaces):
172 self.leftindent = int(self.n_space * nspaces)
173 if self.para:
174 hang = self.leftindent - self.para.indent_left
175 if hang > 0 and self.para.getlength() <= hang:
176 self.para.makehangingtag(hang)
177 self.nospace = 1
178 else:
179 self.flush()
180 #
181 def setrightindent(self, nspaces):
182 self.rightindent = int(self.n_space * nspaces)
183 if self.para:
184 self.para.indent_right = self.rightindent
185 self.flush()
186 #
187 def setjust(self, just):
188 self.just = just
189 if self.para:
190 self.para.just = self.just
191 #
192 def flush(self):
193 if self.para:
194 self.b.addpara(self.para)
195 self.para = None
196 if self.font is not None:
197 self.d.setfont(self.font)
198 self.nospace = 1
199 #
200 def vspace(self, nlines):
201 self.flush()
202 if nlines > 0:
203 self.para = self.newpara()
204 tuple = None, '', 0, 0, 0, int(nlines*self.line), 0
205 self.para.words.append(tuple)
206 self.flush()
207 self.blanklines = self.blanklines + nlines
208 #
209 def needvspace(self, nlines):
210 self.flush() # Just to be sure
211 if nlines > self.blanklines:
212 self.vspace(nlines - self.blanklines)
213 #
214 def addword(self, text, space):
215 if self.nospace and not text:
216 return
217 self.nospace = 0
218 self.blanklines = 0
219 if not self.para:
220 self.para = self.newpara()
221 self.para.indent_left = self.leftindent
222 self.para.just = self.just
223 self.nextfont = self.font
224 space = int(space * self.space)
225 self.para.words.append((self.nextfont, text,
226 self.d.textwidth(text), space, space,
227 self.ascent, self.descent))
228 self.nextfont = None
229 #
230 def bgn_anchor(self, id):
231 if not self.para:
232 self.nospace = 0
233 self.addword('', 0)
234 self.para.bgn_anchor(id)
235 #
236 def end_anchor(self, id):
237 if not self.para:
238 self.nospace = 0
239 self.addword('', 0)
240 self.para.end_anchor(id)
241
242
243# Measuring object for measuring text as viewed on a tty
244class NullMeasurer:
245 #
246 def __init__(self):
247 pass
248 #
249 def setfont(self, font):
250 pass
251 #
252 def textwidth(self, text):
253 return len(text)
254 #
255 def lineheight(self):
256 return 1
257 #
258 def baseline(self):
259 return 0
260
261
262# Drawing object for writing plain ASCII text to a file
263class FileWriter:
264 #
265 def __init__(self, fp):
266 self.fp = fp
267 self.lineno, self.colno = 0, 0
268 #
269 def setfont(self, font):
270 pass
271 #
272 def text(self, (h, v), str):
273 if not str: return
274 if '\n' in str:
275 raise ValueError, 'can\'t write \\n'
276 while self.lineno < v:
277 self.fp.write('\n')
278 self.colno, self.lineno = 0, self.lineno + 1
279 while self.lineno > v:
280 # XXX This should never happen...
281 self.fp.write('\033[A') # ANSI up arrow
282 self.lineno = self.lineno - 1
283 if self.colno < h:
284 self.fp.write(' ' * (h - self.colno))
285 elif self.colno > h:
286 self.fp.write('\b' * (self.colno - h))
287 self.colno = h
288 self.fp.write(str)
289 self.colno = h + len(str)
290
291
292# Formatting class to do nothing at all with the data
293class NullFormatter(BaseFormatter):
294 #
295 def __init__(self):
296 d = NullMeasurer()
297 b = NullBackEnd()
298 BaseFormatter.__init__(self, d, b)
299
300
301# Formatting class to write directly to a file
302class WritingFormatter(BaseFormatter):
303 #
304 def __init__(self, fp, width):
305 dm = NullMeasurer()
306 dw = FileWriter(fp)
307 b = WritingBackEnd(dw, width)
308 BaseFormatter.__init__(self, dm, b)
309 self.blanklines = 1
310 #
311 # Suppress multiple blank lines
312 def needvspace(self, nlines):
313 BaseFormatter.needvspace(self, min(1, nlines))
314
315
316# A "FunnyFormatter" writes ASCII text with a twist: *bold words*,
317# _italic text_ and _underlined words_, and `quoted text'.
318# It assumes that the fonts are 'r', 'i', 'b', 'u', 'q': (roman,
319# italic, bold, underline, quote).
320# Moreover, if the font is in upper case, the text is converted to
321# UPPER CASE.
322class FunnyFormatter(WritingFormatter):
323 #
324 def flush(self):
325 if self.para: finalize(self.para)
326 WritingFormatter.flush(self)
327
328
329# Surrounds *bold words* and _italic text_ in a paragraph with
330# appropriate markers, fixing the size (assuming these characters'
331# width is 1).
332openchar = \
333 {'b':'*', 'i':'_', 'u':'_', 'q':'`', 'B':'*', 'I':'_', 'U':'_', 'Q':'`'}
334closechar = \
335 {'b':'*', 'i':'_', 'u':'_', 'q':'\'', 'B':'*', 'I':'_', 'U':'_', 'Q':'\''}
336def finalize(para):
337 oldfont = curfont = 'r'
338 para.words.append(('r', '', 0, 0, 0, 0)) # temporary, deleted at end
339 for i in range(len(para.words)):
340 fo, te, wi = para.words[i][:3]
341 if fo is not None: curfont = fo
342 if curfont != oldfont:
343 if closechar.has_key(oldfont):
344 c = closechar[oldfont]
345 j = i-1
346 while j > 0 and para.words[j][1] == '': j = j-1
347 fo1, te1, wi1 = para.words[j][:3]
348 te1 = te1 + c
349 wi1 = wi1 + len(c)
350 para.words[j] = (fo1, te1, wi1) + \
351 para.words[j][3:]
352 if openchar.has_key(curfont) and te:
353 c = openchar[curfont]
354 te = c + te
355 wi = len(c) + wi
356 para.words[i] = (fo, te, wi) + \
357 para.words[i][3:]
358 if te: oldfont = curfont
359 else: oldfont = 'r'
360 if curfont in string.uppercase:
361 te = string.upper(te)
362 para.words[i] = (fo, te, wi) + para.words[i][3:]
363 del para.words[-1]
364
365
366# Formatter back-end to draw the text in a window.
367# This has an option to draw while the paragraphs are being added,
368# to minimize the delay before the user sees anything.
369# This manages the entire "document" of the window.
370class StdwinBackEnd(SavingBackEnd):
371 #
372 def __init__(self, window, drawnow):
373 self.window = window
374 self.drawnow = drawnow
375 self.width = window.getwinsize()[0]
376 self.selection = None
377 self.height = 0
378 window.setorigin(0, 0)
379 window.setdocsize(0, 0)
380 self.d = window.begindrawing()
381 SavingBackEnd.__init__(self)
382 #
383 def finish(self):
384 self.d.close()
385 self.d = None
386 self.window.setdocsize(0, self.height)
387 #
388 def addpara(self, p):
389 self.paralist.append(p)
390 if self.drawnow:
391 self.height = \
392 p.render(self.d, 0, self.height, self.width)
393 else:
394 p.layout(self.width)
395 p.left = 0
396 p.top = self.height
397 p.right = self.width
398 p.bottom = self.height + p.height
399 self.height = p.bottom
400 #
401 def resize(self):
402 self.window.change((0, 0), (self.width, self.height))
403 self.width = self.window.getwinsize()[0]
404 self.height = 0
405 for p in self.paralist:
406 p.layout(self.width)
407 p.left = 0
408 p.top = self.height
409 p.right = self.width
410 p.bottom = self.height + p.height
411 self.height = p.bottom
412 self.window.change((0, 0), (self.width, self.height))
413 self.window.setdocsize(0, self.height)
414 #
415 def redraw(self, area):
416 d = self.window.begindrawing()
417 (left, top), (right, bottom) = area
418 d.erase(area)
419 d.cliprect(area)
420 for p in self.paralist:
421 if top < p.bottom and p.top < bottom:
422 v = p.render(d, p.left, p.top, p.right)
423 if self.selection:
424 self.invert(d, self.selection)
425 d.close()
426 #
427 def setselection(self, new):
428 if new:
429 long1, long2 = new
430 pos1 = long1[:3]
431 pos2 = long2[:3]
432 new = pos1, pos2
433 if new != self.selection:
434 d = self.window.begindrawing()
435 if self.selection:
436 self.invert(d, self.selection)
437 if new:
438 self.invert(d, new)
439 d.close()
440 self.selection = new
441 #
442 def getselection(self):
443 return self.selection
444 #
445 def extractselection(self):
446 if self.selection:
447 a, b = self.selection
448 return self.extractpart(a, b)
449 else:
450 return None
451 #
452 def invert(self, d, region):
453 long1, long2 = region
454 if long1 > long2: long1, long2 = long2, long1
455 para1, pos1 = long1
456 para2, pos2 = long2
457 while para1 < para2:
458 self.paralist[para1].invert(d, pos1, None)
459 pos1 = None
460 para1 = para1 + 1
461 self.paralist[para2].invert(d, pos1, pos2)
462 #
463 def search(self, prog):
464 import re, string
465 if type(prog) is type(''):
466 prog = re.compile(string.lower(prog))
467 if self.selection:
468 iold = self.selection[0][0]
469 else:
470 iold = -1
471 hit = None
472 for i in range(len(self.paralist)):
473 if i == iold or i < iold and hit:
474 continue
475 p = self.paralist[i]
476 text = string.lower(p.extract())
477 match = prog.search(text)
478 if match:
479 a, b = match.group(0)
480 long1 = i, a
481 long2 = i, b
482 hit = long1, long2
483 if i > iold:
484 break
485 if hit:
486 self.setselection(hit)
487 i = hit[0][0]
488 p = self.paralist[i]
489 self.window.show((p.left, p.top), (p.right, p.bottom))
490 return 1
491 else:
492 return 0
493 #
494 def showanchor(self, id):
495 for i in range(len(self.paralist)):
496 p = self.paralist[i]
497 if p.hasanchor(id):
498 long1 = i, 0
499 long2 = i, len(p.extract())
500 hit = long1, long2
501 self.setselection(hit)
502 self.window.show(
503 (p.left, p.top), (p.right, p.bottom))
504 break
505
506
507# GL extensions
508
509class GLFontCache:
510 #
511 def __init__(self):
512 self.reset()
513 self.setfont('')
514 #
515 def reset(self):
516 self.fontkey = None
517 self.fonthandle = None
518 self.fontinfo = None
519 self.fontcache = {}
520 #
521 def close(self):
522 self.reset()
523 #
524 def setfont(self, fontkey):
525 if fontkey == '':
526 fontkey = 'Times-Roman 12'
527 elif ' ' not in fontkey:
528 fontkey = fontkey + ' 12'
529 if fontkey == self.fontkey:
530 return
531 if self.fontcache.has_key(fontkey):
532 handle = self.fontcache[fontkey]
533 else:
534 import string
535 i = string.index(fontkey, ' ')
536 name, sizestr = fontkey[:i], fontkey[i:]
537 size = eval(sizestr)
538 key1 = name + ' 1'
539 key = name + ' ' + `size`
540 # NB key may differ from fontkey!
541 if self.fontcache.has_key(key):
542 handle = self.fontcache[key]
543 else:
544 if self.fontcache.has_key(key1):
545 handle = self.fontcache[key1]
546 else:
547 import fm
548 handle = fm.findfont(name)
549 self.fontcache[key1] = handle
550 handle = handle.scalefont(size)
551 self.fontcache[fontkey] = \
552 self.fontcache[key] = handle
553 self.fontkey = fontkey
554 if self.fonthandle != handle:
555 self.fonthandle = handle
556 self.fontinfo = handle.getfontinfo()
557 handle.setfont()
558
559
560class GLMeasurer(GLFontCache):
561 #
562 def textwidth(self, text):
563 return self.fonthandle.getstrwidth(text)
564 #
565 def baseline(self):
566 return self.fontinfo[6] - self.fontinfo[3]
567 #
568 def lineheight(self):
569 return self.fontinfo[6]
570
571
572class GLWriter(GLFontCache):
573 #
574 # NOTES:
575 # (1) Use gl.ortho2 to use X pixel coordinates!
576 #
577 def text(self, (h, v), text):
578 import gl, fm
579 gl.cmov2i(h, v + self.fontinfo[6] - self.fontinfo[3])
580 fm.prstr(text)
581 #
582 def setfont(self, fontkey):
583 oldhandle = self.fonthandle
584 GLFontCache.setfont(fontkey)
585 if self.fonthandle != oldhandle:
586 handle.setfont()
587
588
589class GLMeasurerWriter(GLMeasurer, GLWriter):
590 pass
591
592
593class GLBackEnd(SavingBackEnd):
594 #
595 def __init__(self, wid):
596 import gl
597 gl.winset(wid)
598 self.wid = wid
599 self.width = gl.getsize()[1]
600 self.height = 0
601 self.d = GLMeasurerWriter()
602 SavingBackEnd.__init__(self)
603 #
604 def finish(self):
605 pass
606 #
607 def addpara(self, p):
608 self.paralist.append(p)
609 self.height = p.render(self.d, 0, self.height, self.width)
610 #
611 def redraw(self):
612 import gl
613 gl.winset(self.wid)
614 width = gl.getsize()[1]
615 if width != self.width:
616 setdocsize = 1
617 self.width = width
618 for p in self.paralist:
619 p.top = p.bottom = None
620 d = self.d
621 v = 0
622 for p in self.paralist:
623 v = p.render(d, 0, v, width)