# 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 is not 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 is 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 is not 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 is not 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 re, string
		if type(prog) is type(''):
			prog = re.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())
			match = prog.search(text)
			if match:
				a, b = match.group(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)
