#!/usr/bin/env python

""" 
	Copyright (C) 2001-2003 PimenTech SARL (http://www.pimentech.net)

	This library is free software; you can redistribute it and/or
	modify it under the terms of the GNU Library General Public License as
	published by the Free Software Foundation; either version 2 of the
	License, or (at your option) any later version.

	This library is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
	Library General Public License for more details.

	You should have received a copy of the GNU Library General Public
	License along with this library; see the file COPYING.LIB.  If not,
	write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
	Boston, MA 02111-1307, USA.  
"""

from libcommon.common import *
from libcommon.map import *
from libcommon.set import *
from libcommon.sax import *
from string import *
import getopt
import sys


class XTeX:
	"XTex Parser. Produce latex output"
	
	latex_size = {'1':'tiny', '2':'small', '3':'normalsize', '4':'large', '5':'Large', '6':'huge', '7':'Huge'}
	
	def __init__(self, name = 'XTeX', debug = None, header='', footer=''):
		self.header = header
		self.footer = footer
		if debug:
			self.stderr = stderr
		else:
			self.stderr = open('/dev/null','w')
		self.table_colsep = ''
		self.table_linesep = ''
		self.in_table = 0
		self.hidden = 0
		self.curtag = ''
		self.curcontent = ''
		
	def read(self, filename, output):
		self.output = output
		pf=saxexts.ParserFactory()
		p=pf.make_parser('xml.sax.drivers.drv_xmlproc')
		p.setDocumentHandler(self.XTeXHandler('doc_handler', self))
		p.setDTDHandler(self.XTeXHandler('dtd_handler', self))
		p.setErrorHandler(self.XTeXHandler('err_handler', self))
		p.setEntityResolver(self.XTeXHandler('ent_handler', self))
		p.parse(filename)


	class XTeXHandler(CommonHandler):
		def __init__(self, name, xtex):
			CommonHandler.__init__(self, name)
			self.xtex = xtex
			self.currentTable = None
			self.currentRelation = None
			self.output = self.xtex.output
			
		def startElement(self, name, attrs):
			CommonHandler.startElement(self, name, attrs)
			self.xtex.lasttag = self.xtex.curtag
			self.xtex.curtag = name # for characters method
			valueOf = Map("ValueOf")
			for attr in attrs:
				valueOf[attr]=attrs[attr]

			if name == 'body':
				if valueOf['header']:
					input = open(valueOf['header'], 'r')
					for line in input.readlines():
						self.output.write('%s\n' % line)
					input.close()
				else:
					self.output.write(self.xtex.header)
			elif name == 'hidden': # Pour ne pas faire le rendu de la portion
				self.xtex.hidden = self.xtex.hidden + 1
				
			elif name == 'table':
				self.xtex.in_table = self.xtex.in_table + 1
				self.xtex.table_nbcols = eval(valueOf['cols'])
				self.xtex.table_align = 'l'
				if valueOf['border'] == '1':
					self.xtex.table_colsep = '|'
					self.xtex.table_linesep = '\\hline'
				else:
					self.xtex.table_colsep = ''
					self.xtex.table_linesep = ''
				if valueOf['xtex_cols']:
					args = valueOf['xtex_cols']
				else:
					args = ("%s%s" % (self.xtex.table_colsep, self.xtex.table_align) ) * self.xtex.table_nbcols
					args = args + self.xtex.table_colsep
				self.output.write('\\begin{longtable}{%s}\n' % args)
				self.xtex.table_beginline = 1

			elif name == 'tr':
				self.xtex.table_line = []
			elif name == 'td':
				if self.xtex.lasttag != 'tr':
					self.output.write(' & ')

			elif name == 'b':
				self.xtex.curcontent = self.xtex.curcontent + '{\\bf '

			elif name == 'center':
				self.xtex.curcontent = self.xtex.curcontent + '{\\center '

			elif name == 'i':
				self.xtex.curcontent = self.xtex.curcontent + '{\\em '

			elif name == 'font':
				size = valueOf['size']
				self.xtex.curcontent = self.xtex.curcontent + \
									   '{\\%s ' % self.xtex.latex_size[size]
				
			elif name == 'newpage' or name == 'vfill':
				self.output.write('\\%s\n' % name)
				

		def characters(self,data,start,length):
			if not strip(data[start:start+length]) or self.xtex.hidden:
				return
			content = data[start:start+length]
			content = replace(content, '_', '\\_')
			curtag = self.xtex.curtag
			
			#if curtag == 'th':
			#	self.xtex.table_line.append('{\\bf %s}' % content)
			if curtag == 'noembed': # Pour incorporer du code LaTeX sans qu'il se voie dans le browser HTML
				self.xtex.curcontent = '%s {%s}' % (self.xtex.curcontent, content)
			elif curtag not in ('title','head','script'):
				self.xtex.curcontent = self.xtex.curcontent + content

		def endElement(self, name):
			CommonHandler.endElement(self, name)
			linesep = self.xtex.table_linesep
			colsep = self.xtex.table_colsep

			if name == 'hidden': 
				self.xtex.hidden = self.xtex.hidden - 1
				self.xtex.curcontent = ''
			elif name == 'th':
				self.xtex.table_line.append(self.xtex.curcontent)
				self.xtex.curcontent = ''
			elif name == 'tr':
				line = join(self.xtex.table_line,' & ')
				if self.xtex.table_beginline: # First line : output table header
					self.output.write('''%s
%s \\\\ %s \\endfirsthead
%s
%s \\\\
%s
\\multicolumn{%s}{%sc%s}{\\textit{ Suite...}}\\\\\\endhead
\\multicolumn{%s}{%sc%s}{\\textit{ Suite...}} \\\\
%s \\endfoot
%s \\endlastfoot
''' %
									  (linesep,
									   line, linesep,
									   linesep,
									   line,
									   linesep,
									   self.xtex.table_nbcols, colsep, colsep,
									   self.xtex.table_nbcols, colsep, colsep,
									   linesep,
									   linesep))
					self.xtex.table_beginline = 0
				else:
					# Flush curcontent
					self.output.write('\\\\%s\n' % linesep)
					self.xtex.curcontent = ''

			elif name == 'td':
				# Flush curcontent
				self.output.write('%s' % self.xtex.curcontent)
				self.xtex.curcontent = ''
			elif name == 'table':
				self.xtex.in_table = self.xtex.in_table - 1
				self.output.write('\\end{longtable}\n')
				self.xtex.table_colsep = ''
				self.xtex.table_linesep = ''
			elif name == 'b' or name == 'i' or name == 'font' or name=='center':
				self.xtex.curcontent = self.xtex.curcontent + '}'
			elif name == 'p':
				# Flush curcontent
				self.output.write('%s \\\\\n' % self.xtex.curcontent)
				self.xtex.curcontent = ''
			elif name == 'body':
				self.output.write(self.xtex.footer)
				
			if self.xtex.in_table == 0:
				self.output.write('%s\n' % self.xtex.curcontent)
				self.xtex.curcontent = ''



def main():
	"""
	xtex2latex.py output latex from xtex...

	usage: xtex2latex.py -f <xtex file> [-h] 
	-h : this help
	-f : xtex file
	-s : latex header file (start)
	-e : latex footer file (end)
	-o : latex output
	-d : debug

	example : xtex2latex.py -f test.xtex -o test.tex
	"""
	
	try:
		opts, args = getopt.getopt(sys.argv[1:], 'o:f:s:e:hd')
	except getopt.error, msg:
		usage(msg)

	debug = PYTHONDEBUG
	latexFilename = xtexFilename = latexHeaderFilename = latexFooterFilename = None
	for o, a in opts:
		if o == '-f': xtexFilename = a
		if o == '-h': usage(main.__doc__)
		if o == '-o': latexFilename = a
		if o == '-s': latexHeaderFilename = a
		if o == '-e': latexFooterFilename = a
		if o == '-d': debug = 1

	if not xtexFilename: usage(main.__doc__,'error : missing xtex file')

	if latexHeaderFilename:
		file = open(latexHeaderFilename, 'r')
		headerLatex = file.read()
		file.close()
	else:
		headerLatex = """\\documentclass[french,12pt]{article} 
		\\usepackage[T1]{fontenc}
		\\usepackage{times} 
		\\usepackage{a4} 
		\\usepackage{babel}
		\\usepackage{eurosym}
		\\usepackage{longtable}
		\\pagestyle{empty}
		\\begin{document}
		"""

	if latexFooterFilename:
		file = open(latexFooterFilename, 'r')
		footerLatex = file.read()
		file.close()
	else:
		footerLatex = '\n\\end{document}\n'
		
	if latexFilename:
		output = open(latexFilename,'w')
	else:
		output = stdout

	x = XTeX('Xtex', debug, headerLatex, footerLatex)
	x.read(xtexFilename, output)

if __name__ == '__main__':
	main()

