# Text formatting abstractions
# Note -- this module is obsolete, it's too slow anyway


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)
