diff --git a/Lib/fmt.py b/Lib/fmt.py
new file mode 100644
index 0000000..c096306
--- /dev/null
+++ b/Lib/fmt.py
@@ -0,0 +1,621 @@
+# Text formatting abstractions
+
+
+import string
+import Para
+
+
+# A formatter back-end object has one method that is called by the formatter:
+# addpara(p), where p is a paragraph object.  For example:
+
+
+# Formatter back-end to do nothing at all with the paragraphs
+class NullBackEnd:
+	#
+	def __init__(self):
+		pass
+	#
+	def addpara(self, p):
+		pass
+	#
+	def bgn_anchor(self, id):
+		pass
+	#
+	def end_anchor(self, id):
+		pass
+
+
+# Formatter back-end to collect the paragraphs in a list
+class SavingBackEnd(NullBackEnd):
+	#
+	def __init__(self):
+		self.paralist = []
+	#
+	def addpara(self, p):
+		self.paralist.append(p)
+	#
+	def hitcheck(self, h, v):
+		hits = []
+		for p in self.paralist:
+			if p.top <= v <= p.bottom:
+				for id in p.hitcheck(h, v):
+					if id not in hits:
+						hits.append(id)
+		return hits
+	#
+	def extract(self):
+		text = ''
+		for p in self.paralist:
+			text = text + (p.extract())
+		return text
+	#
+	def extractpart(self, long1, long2):
+		if long1 > long2: long1, long2 = long2, long1
+		para1, pos1 = long1
+		para2, pos2 = long2
+		text = ''
+		while para1 < para2:
+			ptext = self.paralist[para1].extract()
+			text = text + ptext[pos1:]
+			pos1 = 0
+			para1 = para1 + 1
+		ptext = self.paralist[para2].extract()
+		return text + ptext[pos1:pos2]
+	#
+	def whereis(self, d, h, v):
+		total = 0
+		for i in range(len(self.paralist)):
+			p = self.paralist[i]
+			result = p.whereis(d, h, v)
+			if result <> None:
+				return i, result
+		return None
+	#
+	def roundtowords(self, long1, long2):
+		i, offset = long1
+		text = self.paralist[i].extract()
+		while offset > 0 and text[offset-1] <> ' ': offset = offset-1
+		long1 = i, offset
+		#
+		i, offset = long2
+		text = self.paralist[i].extract()
+		n = len(text)
+		while offset < n-1 and text[offset] <> ' ': offset = offset+1
+		long2 = i, offset
+		#
+		return long1, long2
+	#
+	def roundtoparagraphs(self, long1, long2):
+		long1 = long1[0], 0
+		long2 = long2[0], len(self.paralist[long2[0]].extract())
+		return long1, long2
+
+
+# Formatter back-end to send the text directly to the drawing object
+class WritingBackEnd(NullBackEnd):
+	#
+	def __init__(self, d, width):
+		self.d = d
+		self.width = width
+		self.lineno = 0
+	#
+	def addpara(self, p):
+		self.lineno = p.render(self.d, 0, self.lineno, self.width)
+
+
+# A formatter receives a stream of formatting instructions and assembles
+# these into a stream of paragraphs on to a back-end.  The assembly is
+# parametrized by a text measurement object, which must match the output
+# operations of the back-end.  The back-end is responsible for splitting
+# paragraphs up in lines of a given maximum width.  (This is done because
+# in a windowing environment, when the window size changes, there is no
+# need to redo the assembly into paragraphs, but the splitting into lines
+# must be done taking the new window size into account.)
+
+
+# Formatter base class.  Initialize it with a text measurement object,
+# which is used for text measurements, and a back-end object,
+# which receives the completed paragraphs.  The formatting methods are:
+# setfont(font)
+# setleftindent(nspaces)
+# setjust(type) where type is 'l', 'c', 'r', or 'lr'
+# flush()
+# vspace(nlines)
+# needvspace(nlines)
+# addword(word, nspaces)
+class BaseFormatter:
+	#
+	def __init__(self, d, b):
+		# Drawing object used for text measurements
+		self.d = d
+		#
+		# BackEnd object receiving completed paragraphs
+		self.b = b
+		#
+		# Parameters of the formatting model
+		self.leftindent = 0
+		self.just = 'l'
+		self.font = None
+		self.blanklines = 0
+		#
+		# Parameters derived from the current font
+		self.space = d.textwidth(' ')
+		self.line = d.lineheight()
+		self.ascent = d.baseline()
+		self.descent = self.line - self.ascent
+		#
+		# Parameter derived from the default font
+		self.n_space = self.space
+		#
+		# Current paragraph being built
+		self.para = None
+		self.nospace = 1
+		#
+		# Font to set on the next word
+		self.nextfont = None
+	#
+	def newpara(self):
+		return Para.Para()
+	#
+	def setfont(self, font):
+		if font == None: return
+		self.font = self.nextfont = font
+		d = self.d
+		d.setfont(font)
+		self.space = d.textwidth(' ')
+		self.line = d.lineheight()
+		self.ascent = d.baseline()
+		self.descent = self.line - self.ascent
+	#
+	def setleftindent(self, nspaces):
+		self.leftindent = int(self.n_space * nspaces)
+		if self.para:
+			hang = self.leftindent - self.para.indent_left
+			if hang > 0 and self.para.getlength() <= hang:
+				self.para.makehangingtag(hang)
+				self.nospace = 1
+			else:
+				self.flush()
+	#
+	def setrightindent(self, nspaces):
+		self.rightindent = int(self.n_space * nspaces)
+		if self.para:
+			self.para.indent_right = self.rightindent
+			self.flush()
+	#
+	def setjust(self, just):
+		self.just = just
+		if self.para:
+			self.para.just = self.just
+	#
+	def flush(self):
+		if self.para:
+			self.b.addpara(self.para)
+			self.para = None
+			if self.font <> None:
+				self.d.setfont(self.font)
+		self.nospace = 1
+	#
+	def vspace(self, nlines):
+		self.flush()
+		if nlines > 0:
+			self.para = self.newpara()
+			tuple = None, '', 0, 0, 0, int(nlines*self.line), 0
+			self.para.words.append(tuple)
+			self.flush()
+			self.blanklines = self.blanklines + nlines
+	#
+	def needvspace(self, nlines):
+		self.flush() # Just to be sure
+		if nlines > self.blanklines:
+			self.vspace(nlines - self.blanklines)
+	#
+	def addword(self, text, space):
+		if self.nospace and not text:
+			return
+		self.nospace = 0
+		self.blanklines = 0
+		if not self.para:
+			self.para = self.newpara()
+			self.para.indent_left = self.leftindent
+			self.para.just = self.just
+			self.nextfont = self.font
+		space = int(space * self.space)
+		self.para.words.append(self.nextfont, text, \
+			self.d.textwidth(text), space, space, \
+			self.ascent, self.descent)
+		self.nextfont = None
+	#
+	def bgn_anchor(self, id):
+		if not self.para:
+			self.nospace = 0
+			self.addword('', 0)
+		self.para.bgn_anchor(id)
+	#
+	def end_anchor(self, id):
+		if not self.para:
+			self.nospace = 0
+			self.addword('', 0)
+		self.para.end_anchor(id)
+
+
+# Measuring object for measuring text as viewed on a tty
+class NullMeasurer:
+	#
+	def __init__(self):
+		pass
+	#
+	def setfont(self, font):
+		pass
+	#
+	def textwidth(self, text):
+		return len(text)
+	#
+	def lineheight(self):
+		return 1
+	#
+	def baseline(self):
+		return 0
+
+
+# Drawing object for writing plain ASCII text to a file
+class FileWriter:
+	#
+	def __init__(self, fp):
+		self.fp = fp
+		self.lineno, self.colno = 0, 0
+	#
+	def setfont(self, font):
+		pass
+	#
+	def text(self, (h, v), str):
+		if not str: return
+		if '\n' in str:
+			raise ValueError, 'can\'t write \\n'
+		while self.lineno < v:
+			self.fp.write('\n')
+			self.colno, self.lineno = 0, self.lineno + 1
+		while self.lineno > v:
+			# XXX This should never happen...
+			self.fp.write('\033[A') # ANSI up arrow
+			self.lineno = self.lineno - 1
+		if self.colno < h:
+			self.fp.write(' ' * (h - self.colno))
+		elif self.colno > h:
+			self.fp.write('\b' * (self.colno - h))
+		self.colno = h
+		self.fp.write(str)
+		self.colno = h + len(str)
+
+
+# Formatting class to do nothing at all with the data
+class NullFormatter(BaseFormatter):
+	#
+	def __init__(self):
+		d = NullMeasurer()
+		b = NullBackEnd()
+		BaseFormatter.__init__(self, d, b)
+
+
+# Formatting class to write directly to a file
+class WritingFormatter(BaseFormatter):
+	#
+	def __init__(self, fp, width):
+		dm = NullMeasurer()
+		dw = FileWriter(fp)
+		b = WritingBackEnd(dw, width)
+		BaseFormatter.__init__(self, dm, b)
+		self.blanklines = 1
+	#
+	# Suppress multiple blank lines
+	def needvspace(self, nlines):
+		BaseFormatter.needvspace(self, min(1, nlines))
+
+
+# A "FunnyFormatter" writes ASCII text with a twist: *bold words*,
+# _italic text_ and _underlined words_, and `quoted text'.
+# It assumes that the fonts are 'r', 'i', 'b', 'u', 'q': (roman,
+# italic, bold, underline, quote).
+# Moreover, if the font is in upper case, the text is converted to
+# UPPER CASE.
+class FunnyFormatter(WritingFormatter):
+	#
+	def flush(self):
+		if self.para: finalize(self.para)
+		WritingFormatter.flush(self)
+
+
+# Surrounds *bold words* and _italic text_ in a paragraph with
+# appropriate markers, fixing the size (assuming these characters'
+# width is 1).
+openchar = \
+    {'b':'*', 'i':'_', 'u':'_', 'q':'`', 'B':'*', 'I':'_', 'U':'_', 'Q':'`'}
+closechar = \
+    {'b':'*', 'i':'_', 'u':'_', 'q':'\'', 'B':'*', 'I':'_', 'U':'_', 'Q':'\''}
+def finalize(para):
+	oldfont = curfont = 'r'
+	para.words.append('r', '', 0, 0, 0, 0) # temporary, deleted at end
+	for i in range(len(para.words)):
+		fo, te, wi = para.words[i][:3]
+		if fo <> None: curfont = fo
+		if curfont <> oldfont:
+			if closechar.has_key(oldfont):
+				c = closechar[oldfont]
+				j = i-1
+				while j > 0 and para.words[j][1] == '': j = j-1
+				fo1, te1, wi1 = para.words[j][:3]
+				te1 = te1 + c
+				wi1 = wi1 + len(c)
+				para.words[j] = (fo1, te1, wi1) + \
+					para.words[j][3:]
+			if openchar.has_key(curfont) and te:
+				c = openchar[curfont]
+				te = c + te
+				wi = len(c) + wi
+				para.words[i] = (fo, te, wi) + \
+					para.words[i][3:]
+			if te: oldfont = curfont
+			else: oldfont = 'r'
+		if curfont in string.uppercase:
+			te = string.upper(te)
+			para.words[i] = (fo, te, wi) + para.words[i][3:]
+	del para.words[-1]
+
+
+# Formatter back-end to draw the text in a window.
+# This has an option to draw while the paragraphs are being added,
+# to minimize the delay before the user sees anything.
+# This manages the entire "document" of the window.
+class StdwinBackEnd(SavingBackEnd):
+	#
+	def __init__(self, window, drawnow):
+		self.window = window
+		self.drawnow = drawnow
+		self.width = window.getwinsize()[0]
+		self.selection = None
+		self.height = 0
+		window.setorigin(0, 0)
+		window.setdocsize(0, 0)
+		self.d = window.begindrawing()
+		SavingBackEnd.__init__(self)
+	#
+	def finish(self):
+		self.d.close()
+		self.d = None
+		self.window.setdocsize(0, self.height)
+	#
+	def addpara(self, p):
+		self.paralist.append(p)
+		if self.drawnow:
+			self.height = \
+				p.render(self.d, 0, self.height, self.width)
+		else:
+			p.layout(self.width)
+			p.left = 0
+			p.top = self.height
+			p.right = self.width
+			p.bottom = self.height + p.height
+			self.height = p.bottom
+	#
+	def resize(self):
+		self.window.change((0, 0), (self.width, self.height))
+		self.width = self.window.getwinsize()[0]
+		self.height = 0
+		for p in self.paralist:
+			p.layout(self.width)
+			p.left = 0
+			p.top = self.height
+			p.right = self.width
+			p.bottom = self.height + p.height
+			self.height = p.bottom
+		self.window.change((0, 0), (self.width, self.height))
+		self.window.setdocsize(0, self.height)
+	#
+	def redraw(self, area):
+		d = self.window.begindrawing()
+		(left, top), (right, bottom) = area
+		d.erase(area)
+		d.cliprect(area)
+		for p in self.paralist:
+			if top < p.bottom and p.top < bottom:
+				v = p.render(d, p.left, p.top, p.right)
+		if self.selection:
+			self.invert(d, self.selection)
+		d.close()
+	#
+	def setselection(self, new):
+		if new:
+			long1, long2 = new
+			pos1 = long1[:3]
+			pos2 = long2[:3]
+			new = pos1, pos2
+		if new <> self.selection:
+			d = self.window.begindrawing()
+			if self.selection:
+				self.invert(d, self.selection)
+			if new:
+				self.invert(d, new)
+			d.close()
+			self.selection = new
+	#
+	def getselection(self):
+		return self.selection
+	#
+	def extractselection(self):
+		if self.selection:
+			a, b = self.selection
+			return self.extractpart(a, b)
+		else:
+			return None
+	#
+	def invert(self, d, region):
+		long1, long2 = region
+		if long1 > long2: long1, long2 = long2, long1
+		para1, pos1 = long1
+		para2, pos2 = long2
+		while para1 < para2:
+			self.paralist[para1].invert(d, pos1, None)
+			pos1 = None
+			para1 = para1 + 1
+		self.paralist[para2].invert(d, pos1, pos2)
+	#
+	def search(self, prog):
+		import regex, string
+		if type(prog) == type(''):
+			prog = regex.compile(string.lower(prog))
+		if self.selection:
+			iold = self.selection[0][0]
+		else:
+			iold = -1
+		hit = None
+		for i in range(len(self.paralist)):
+			if i == iold or i < iold and hit:
+				continue
+			p = self.paralist[i]
+			text = string.lower(p.extract())
+			if prog.search(text) >= 0:
+				a, b = prog.regs[0]
+				long1 = i, a
+				long2 = i, b
+				hit = long1, long2
+				if i > iold:
+					break
+		if hit:
+			self.setselection(hit)
+			i = hit[0][0]
+			p = self.paralist[i]
+			self.window.show((p.left, p.top), (p.right, p.bottom))
+			return 1
+		else:
+			return 0
+	#
+	def showanchor(self, id):
+		for i in range(len(self.paralist)):
+			p = self.paralist[i]
+			if p.hasanchor(id):
+				long1 = i, 0
+				long2 = i, len(p.extract())
+				hit = long1, long2
+				self.setselection(hit)
+				self.window.show( \
+					(p.left, p.top), (p.right, p.bottom))
+				break
+
+
+# GL extensions
+
+class GLFontCache:
+	#
+	def __init__(self):
+		self.reset()
+		self.setfont('')
+	#
+	def reset(self):
+		self.fontkey = None
+		self.fonthandle = None
+		self.fontinfo = None
+		self.fontcache = {}
+	#
+	def close(self):
+		self.reset()
+	#
+	def setfont(self, fontkey):
+		if fontkey == '':
+			fontkey = 'Times-Roman 12'
+		elif ' ' not in fontkey:
+			fontkey = fontkey + ' 12'
+		if fontkey == self.fontkey:
+			return
+		if self.fontcache.has_key(fontkey):
+			handle = self.fontcache[fontkey]
+		else:
+			import string
+			i = string.index(fontkey, ' ')
+			name, sizestr = fontkey[:i], fontkey[i:]
+			size = eval(sizestr)
+			key1 = name + ' 1'
+			key = name + ' ' + `size`
+			# NB key may differ from fontkey!
+			if self.fontcache.has_key(key):
+				handle = self.fontcache[key]
+			else:
+				if self.fontcache.has_key(key1):
+					handle = self.fontcache[key1]
+				else:
+					import fm
+					handle = fm.findfont(name)
+					self.fontcache[key1] = handle
+				handle = handle.scalefont(size)
+				self.fontcache[fontkey] = \
+					self.fontcache[key] = handle
+		self.fontkey = fontkey
+		if self.fonthandle <> handle:
+			self.fonthandle = handle
+			self.fontinfo = handle.getfontinfo()
+			handle.setfont()
+
+
+class GLMeasurer(GLFontCache):
+	#
+	def textwidth(self, text):
+		return self.fonthandle.getstrwidth(text)
+	#
+	def baseline(self):
+		return self.fontinfo[6] - self.fontinfo[3]
+	#
+	def lineheight(self):
+		return self.fontinfo[6]
+
+
+class GLWriter(GLFontCache):
+	#
+	# NOTES:
+	# (1) Use gl.ortho2 to use X pixel coordinates!
+	#
+	def text(self, (h, v), text):
+		import gl, fm
+		gl.cmov2i(h, v + self.fontinfo[6] - self.fontinfo[3])
+		fm.prstr(text)
+	#
+	def setfont(self, fontkey):
+		oldhandle = self.fonthandle
+		GLFontCache.setfont(fontkey)
+		if self.fonthandle <> oldhandle:
+			handle.setfont()
+
+
+class GLMeasurerWriter(GLMeasurer, GLWriter):
+	pass
+
+
+class GLBackEnd(SavingBackEnd):
+	#
+	def __init__(self, wid):
+		import gl
+		gl.winset(wid)
+		self.wid = wid
+		self.width = gl.getsize()[1]
+		self.height = 0
+		self.d = GLMeasurerWriter()
+		SavingBackEnd.__init__(self)
+	#
+	def finish(self):
+		pass
+	#
+	def addpara(self, p):
+		self.paralist.append(p)
+		self.height = p.render(self.d, 0, self.height, self.width)
+	#
+	def redraw(self):
+		import gl
+		gl.winset(self.wid)
+		width = gl.getsize()[1]
+		if width <> self.width:
+			setdocsize = 1
+			self.width = width
+			for p in self.paralist:
+				p.top = p.bottom = None
+		d = self.d
+		v = 0
+		for p in self.paralist:
+			v = p.render(d, 0, v, width)
