0004605: Multiple improvements for LaTeX output (patch from Harald Rosemann)
svn: r18035
This commit is contained in:
parent
fe4df17781
commit
603238aeb0
@ -1,4 +1,6 @@
|
|||||||
#
|
#
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
# Gramps - a GTK+/GNOME based genealogy program
|
# Gramps - a GTK+/GNOME based genealogy program
|
||||||
#
|
#
|
||||||
# Copyright (C) 2000-2006 Donald N. Allingham
|
# Copyright (C) 2000-2006 Donald N. Allingham
|
||||||
@ -9,6 +11,7 @@
|
|||||||
# 2009 Benny Malengier
|
# 2009 Benny Malengier
|
||||||
# 2010 Peter Landgren
|
# 2010 Peter Landgren
|
||||||
# Copyright (C) 2011 Adam Stein <adam@csh.rit.edu>
|
# Copyright (C) 2011 Adam Stein <adam@csh.rit.edu>
|
||||||
|
# 2011 Harald Rosemann
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or modify
|
# This program is free software; you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
@ -38,7 +41,7 @@ from gen.ggettext import gettext as _
|
|||||||
from bisect import bisect
|
from bisect import bisect
|
||||||
import re
|
import re
|
||||||
|
|
||||||
#------------------------------------------------------------------------
|
#----------------------------------------------------------------------- -
|
||||||
#
|
#
|
||||||
# gramps modules
|
# gramps modules
|
||||||
#
|
#
|
||||||
@ -51,6 +54,34 @@ import Utils
|
|||||||
|
|
||||||
_CLICKABLE = r'''\url{\1}'''
|
_CLICKABLE = r'''\url{\1}'''
|
||||||
|
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# Special settings for LaTeX output
|
||||||
|
#
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
# If there is one overwide column consuming too much space of paperwidth its
|
||||||
|
# line(s) must be broken and wrapped in a 'minipage' with appropriate width.
|
||||||
|
# The table construction beneath does this job but for now must know which
|
||||||
|
# column. (Later it shall be determined in another way)
|
||||||
|
# As to gramps in most cases it is the last column, hence:
|
||||||
|
|
||||||
|
MINIPAGE_COL = -1 # Python indexing: last one
|
||||||
|
|
||||||
|
# In trunk there is a 'LastChangeReport' where the last but one
|
||||||
|
# is such a column. If you like, you can instead choose this setting:
|
||||||
|
|
||||||
|
# MINIPAGE_COL = -2 # Python indexing: last but one
|
||||||
|
|
||||||
|
# ----------------------------------
|
||||||
|
# For an interim mark of an intended linebreak I use a special pattern. It
|
||||||
|
# shouldn't interfere with normal text. The charackter '&' is used in LaTeX
|
||||||
|
# for column separation in tables and may occur there in series. The pattern
|
||||||
|
# is used here before column separation is set. On the other hand incoming
|
||||||
|
# text can't show this pattern for it would have been replaced by '\&\&'.
|
||||||
|
# So the choosen pattern will do the job without confusion:
|
||||||
|
|
||||||
|
PAT_FOR_LINE_BREAK = '&&'
|
||||||
|
|
||||||
#------------------------------------------------------------------------
|
#------------------------------------------------------------------------
|
||||||
#
|
#
|
||||||
# Latex Article Template
|
# Latex Article Template
|
||||||
@ -58,7 +89,29 @@ _CLICKABLE = r'''\url{\1}'''
|
|||||||
#------------------------------------------------------------------------
|
#------------------------------------------------------------------------
|
||||||
|
|
||||||
_LATEX_TEMPLATE_1 = '\\documentclass[%s]{article}\n'
|
_LATEX_TEMPLATE_1 = '\\documentclass[%s]{article}\n'
|
||||||
_LATEX_TEMPLATE = '''\\usepackage[T1]{fontenc}
|
_LATEX_TEMPLATE = '''%
|
||||||
|
%
|
||||||
|
% Vertical spacing between paragraphs:
|
||||||
|
% take one of three possibilities or modify to your taste:
|
||||||
|
%\\setlength{\\parskip}{1.0ex plus0.2ex minus0.2ex}
|
||||||
|
\\setlength{\\parskip}{1.5ex plus0.3ex minus0.3ex}
|
||||||
|
%\\setlength{\\parskip}{2.0ex plus0.4ex minus0.4ex}
|
||||||
|
%
|
||||||
|
% Vertical spacing between lines:
|
||||||
|
% take one of three possibilities or modify to your taste:
|
||||||
|
\\renewcommand{\\baselinestretch}{1.0}
|
||||||
|
%\\renewcommand{\\baselinestretch}{1.1}
|
||||||
|
%\\renewcommand{\\baselinestretch}{1.2}
|
||||||
|
%
|
||||||
|
% Indentation; substitute for '1cm' of gramps
|
||||||
|
% take one of three possibilities or modify to your taste:
|
||||||
|
\\newlength{\\grbaseindent}%
|
||||||
|
\\setlength{\\grbaseindent}{3.0em}
|
||||||
|
%\\setlength{\\grbaseindent}{2.5em}
|
||||||
|
%\\setlength{\\grbaseindent}{2.0em}
|
||||||
|
%
|
||||||
|
%
|
||||||
|
\\usepackage[T1]{fontenc}
|
||||||
%
|
%
|
||||||
% We use latin1 encoding at a minimum by default.
|
% We use latin1 encoding at a minimum by default.
|
||||||
% GRAMPS uses unicode UTF-8 encoding for its
|
% GRAMPS uses unicode UTF-8 encoding for its
|
||||||
@ -75,7 +128,8 @@ _LATEX_TEMPLATE = '''\\usepackage[T1]{fontenc}
|
|||||||
%\\usepackage[latin1,utf8]{inputenc}
|
%\\usepackage[latin1,utf8]{inputenc}
|
||||||
\\usepackage{graphicx} % Extended graphics support
|
\\usepackage{graphicx} % Extended graphics support
|
||||||
\\usepackage{longtable} % For multi-page tables
|
\\usepackage{longtable} % For multi-page tables
|
||||||
\\usepackage{calc} % For margin indents
|
\\usepackage{calc} % For some calculations
|
||||||
|
\\usepackage{ifthen} % For table width calculations
|
||||||
%
|
%
|
||||||
% Depending on your LaTeX installation, the margins may be too
|
% Depending on your LaTeX installation, the margins may be too
|
||||||
% narrow. This can be corrected by uncommenting the following
|
% narrow. This can be corrected by uncommenting the following
|
||||||
@ -84,19 +138,50 @@ _LATEX_TEMPLATE = '''\\usepackage[T1]{fontenc}
|
|||||||
%\\addtolength{\\oddsidemargin}{-0.5in}
|
%\\addtolength{\\oddsidemargin}{-0.5in}
|
||||||
%\\addtolength{\\textwidth}{1.0in}
|
%\\addtolength{\\textwidth}{1.0in}
|
||||||
%
|
%
|
||||||
% Create a margin-adjusting command that allows LaTeX
|
%
|
||||||
% to behave like the other gramps-supported output formats
|
% New lengths and commands
|
||||||
\\newlength{\\leftedge}
|
% for calculating widths and struts in tables
|
||||||
\\setlength{\\leftedge}{\\parindent}
|
%
|
||||||
\\newlength{\\grampstext}
|
\\newlength{\\grtempint}%
|
||||||
\\setlength{\\grampstext}{\\textwidth}
|
\\newlength{\\grminpgwidth}%
|
||||||
\\newcommand{\\grampsindent}[1]{%
|
\\setlength{\\grminpgwidth}{0.8\\textwidth}
|
||||||
\\setlength{\\parindent}{\\leftedge + #1}%
|
%
|
||||||
\\setlength{\\textwidth}{\\grampstext - #1}%
|
\\newcommand{\\inittabvars}[2]{%
|
||||||
}
|
\\ifthenelse{\\isundefined{#1}}%
|
||||||
|
{\\newlength{#1}}{}%
|
||||||
|
\\setlength{#1}{#2}%
|
||||||
|
}%
|
||||||
|
%
|
||||||
|
\\newcommand{\\grcalctextwidth}[2]{%
|
||||||
|
\\settowidth{\\grtempint}{#1}% #1: text
|
||||||
|
\\ifthenelse{\\lengthtest{\\grtempint > #2}}% #2: grcolwidth_
|
||||||
|
{\\setlength{#2}{\\grtempint}}{}%
|
||||||
|
}%
|
||||||
|
%
|
||||||
|
\\newcommand{\\grminvaltofirst}[2]{%
|
||||||
|
\\setlength{\\grtempint}{#2}%
|
||||||
|
\\ifthenelse{\\lengthtest{#1 > \\grtempint}}%
|
||||||
|
{\\setlength{#1}{\\grtempint}}{}%
|
||||||
|
}%
|
||||||
|
%
|
||||||
|
\\newcommand{\\grmaxvaltofirst}[2]{%
|
||||||
|
\\setlength{\\grtempint}{#2}%
|
||||||
|
\\ifthenelse{\\lengthtest{#1 < \\grtempint}}%
|
||||||
|
{\\setlength{#1}{\\grtempint}}{}%
|
||||||
|
}%
|
||||||
|
%
|
||||||
|
% lift width heigh
|
||||||
|
\\newcommand{\\tabheadstrutceil}{%
|
||||||
|
\\rule[0.0ex]{0.00em}{3.5ex}}%
|
||||||
|
\\newcommand{\\tabheadstrutfloor}{%
|
||||||
|
\\rule[-2.0ex]{0.00em}{2.5ex}}%
|
||||||
|
\\newcommand{\\tabrowstrutceil}{%
|
||||||
|
\\rule[0.0ex]{0.00em}{3.0ex}}%
|
||||||
|
\\newcommand{\\tabrowstrutfloor}{%
|
||||||
|
\\rule[-1.0ex]{0.00em}{3.0ex}}%
|
||||||
|
%
|
||||||
|
%
|
||||||
\\begin{document}
|
\\begin{document}
|
||||||
|
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
|
||||||
@ -106,7 +191,7 @@ _LATEX_TEMPLATE = '''\\usepackage[T1]{fontenc}
|
|||||||
#
|
#
|
||||||
#------------------------------------------------------------------------
|
#------------------------------------------------------------------------
|
||||||
|
|
||||||
# These tables coorelate font sizes to Latex. The first table contains
|
# These tables correlate font sizes to Latex. The first table contains
|
||||||
# typical font sizes in points. The second table contains the standard
|
# typical font sizes in points. The second table contains the standard
|
||||||
# Latex font size names. Since we use bisect to map the first table to the
|
# Latex font size names. Since we use bisect to map the first table to the
|
||||||
# second, we are guaranteed that any font less than 6 points is 'tiny', fonts
|
# second, we are guaranteed that any font less than 6 points is 'tiny', fonts
|
||||||
@ -121,6 +206,90 @@ _FONT_NAMES = ['tiny', 'scriptsize', 'footnotesize', 'small', '',
|
|||||||
def map_font_size(fontsize):
|
def map_font_size(fontsize):
|
||||||
""" Map font size in points to Latex font size """
|
""" Map font size in points to Latex font size """
|
||||||
return _FONT_NAMES[bisect(_FONT_SIZES, fontsize)]
|
return _FONT_NAMES[bisect(_FONT_SIZES, fontsize)]
|
||||||
|
|
||||||
|
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# auxiliaries to facilitate table construction
|
||||||
|
#
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# patterns for regular expressions, module re:
|
||||||
|
TBLFMT_PAT = re.compile(r'({\|?)l(\|?})')
|
||||||
|
|
||||||
|
# constants for routing in table construction:
|
||||||
|
(CELL_BEG, CELL_TEXT, CELL_END,
|
||||||
|
ROW_BEG, ROW_END, TAB_BEG, TAB_END,
|
||||||
|
NESTED_MINPG) = range(8)
|
||||||
|
FIRST_ROW, SUBSEQ_ROW = range(2)
|
||||||
|
|
||||||
|
|
||||||
|
def get_charform(col_num):
|
||||||
|
"""
|
||||||
|
Transfer column number to column charakter,
|
||||||
|
limited to letters within a-z;
|
||||||
|
26, there is no need for more.
|
||||||
|
early test of column count in start_table()
|
||||||
|
"""
|
||||||
|
if col_num > ord('z') - ord('a'):
|
||||||
|
raise ValueError, ''.join((
|
||||||
|
'\n number of table columns is ', repr(col_num),
|
||||||
|
'\n should be <= ', repr(ord('z') - ord('a'))))
|
||||||
|
return chr(ord('a') + col_num)
|
||||||
|
|
||||||
|
def get_numform(col_char):
|
||||||
|
return ord(col_char) - ord('a')
|
||||||
|
|
||||||
|
|
||||||
|
#------------------------------------------
|
||||||
|
# 'aa' is sufficient for up to 676 table-rows in each table;
|
||||||
|
# do you need more?
|
||||||
|
# uncomment one of the two lines
|
||||||
|
ROW_COUNT_BASE = 'aa'
|
||||||
|
# ROW_COUNT_BASE = 'aaa'
|
||||||
|
#------------------------------------------
|
||||||
|
def str_incr(str_counter):
|
||||||
|
""" for counting table rows """
|
||||||
|
lili = list(str_counter)
|
||||||
|
while 1:
|
||||||
|
yield ''.join(lili)
|
||||||
|
if ''.join(lili) == len(lili)*'z':
|
||||||
|
raise ValueError, ''.join((
|
||||||
|
'\n can\'t increment string ', ''.join(lili),
|
||||||
|
' of length ', str(len(lili))))
|
||||||
|
for i in range(len(lili)-1, -1, -1):
|
||||||
|
if lili[i] < 'z':
|
||||||
|
lili[i] = chr(ord(lili[i])+1)
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
lili[i] = 'a'
|
||||||
|
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# Structure of Table-Memory
|
||||||
|
#
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class Tab_Cell():
|
||||||
|
def __init__(self, colchar, span, head):
|
||||||
|
self.colchar = colchar
|
||||||
|
self.span = span
|
||||||
|
self.head = head
|
||||||
|
self.content = ''
|
||||||
|
self.nested_minpg = False
|
||||||
|
class Tab_Row():
|
||||||
|
def __init__(self):
|
||||||
|
self.cells =[]
|
||||||
|
self.tail = ''
|
||||||
|
self.addit = '' # for: \\hline, \\cline{}
|
||||||
|
self.spec_var_cell_width = ''
|
||||||
|
self.total_width = ''
|
||||||
|
class Tab_Mem():
|
||||||
|
def __init__(self, head):
|
||||||
|
self.head = head
|
||||||
|
self.tail =''
|
||||||
|
self.rows =[]
|
||||||
|
|
||||||
#------------------------------------------------------------------------
|
#------------------------------------------------------------------------
|
||||||
#
|
#
|
||||||
# Functions for docbackend
|
# Functions for docbackend
|
||||||
@ -154,10 +323,11 @@ def latexescapeverbatim(text):
|
|||||||
text = text.replace('{', '\\{')
|
text = text.replace('{', '\\{')
|
||||||
text = text.replace('}', '\\}')
|
text = text.replace('}', '\\}')
|
||||||
text = text.replace(' ', '\\ ')
|
text = text.replace(' ', '\\ ')
|
||||||
text = text.replace('\n', '\\newline\n')
|
text = text.replace('\n', '~\\newline\n')
|
||||||
#spaces at begin are normally ignored, make sure they are not.
|
#spaces at begin are normally ignored, make sure they are not.
|
||||||
#due to above a space at begin is now \newline\n\
|
#due to above a space at begin is now \newline\n\
|
||||||
text = text.replace('\\newline\n\\ ', '\\newline\n\\hspace*{0.1cm}\\ ')
|
text = text.replace('\\newline\n\\ ',
|
||||||
|
'\\newline\n\\hspace*{0.1\\grbaseindent}\\ ')
|
||||||
return text
|
return text
|
||||||
|
|
||||||
#------------------------------------------------------------------------
|
#------------------------------------------------------------------------
|
||||||
@ -229,73 +399,16 @@ class LateXBackend(DocBackend):
|
|||||||
"""
|
"""
|
||||||
Check to make sure filename satisfies the standards for this filetype
|
Check to make sure filename satisfies the standards for this filetype
|
||||||
"""
|
"""
|
||||||
if self._filename[-4:] != ".tex":
|
if not self._filename.endswith(".tex"):
|
||||||
self._filename = self._filename + ".tex"
|
self._filename = self._filename + ".tex"
|
||||||
|
|
||||||
#------------------------------------------------------------------------
|
|
||||||
#
|
|
||||||
# Convert from roman to arabic numbers
|
|
||||||
#
|
|
||||||
#------------------------------------------------------------------------
|
|
||||||
def roman2arabic(strval):
|
|
||||||
"""
|
|
||||||
Roman to arabic converter for 0 < num < 4000.
|
|
||||||
|
|
||||||
Always returns an integer.
|
|
||||||
On an invalid input zero is returned.
|
|
||||||
"""
|
|
||||||
# Return zero if the type is not str
|
|
||||||
try:
|
|
||||||
strval = str(strval).upper()
|
|
||||||
if not strval:
|
|
||||||
return 0
|
|
||||||
except:
|
|
||||||
return 0
|
|
||||||
|
|
||||||
# Return None if there are chars outside of valid roman numerals
|
|
||||||
if not all(char in 'MDCLXVI' for char in strval):
|
|
||||||
return 0
|
|
||||||
|
|
||||||
vals2 = ['CM', 'CD', 'XC', 'XL', 'IX', 'IV']
|
|
||||||
nums2 = ( 900, 400, 90, 40, 9, 4)
|
|
||||||
|
|
||||||
vals1 = [ 'M', 'D', 'C', 'L', 'X', 'V', 'I']
|
|
||||||
nums1 = (1000, 500, 100, 50, 10, 5, 1)
|
|
||||||
|
|
||||||
ret = 0
|
|
||||||
max_num = 1000
|
|
||||||
# Start unrolling strval from left to right,
|
|
||||||
# up to the penultimate char
|
|
||||||
i = 0
|
|
||||||
while i < len(strval):
|
|
||||||
first_index = vals1.index(strval[i])
|
|
||||||
|
|
||||||
if i+1 < len(strval) and strval[i:i+2] in vals2:
|
|
||||||
this_num = nums2[vals2.index(strval[i:i+2])]
|
|
||||||
if first_index+1 < len(nums1):
|
|
||||||
new_max_num = nums1[first_index+1]
|
|
||||||
else:
|
|
||||||
new_max_num = 0
|
|
||||||
i += 2
|
|
||||||
else:
|
|
||||||
this_num = nums1[first_index]
|
|
||||||
new_max_num = this_num
|
|
||||||
i += 1
|
|
||||||
|
|
||||||
# prohibit larger numbers following smaller ones,
|
|
||||||
# except for the above 2-char combinations
|
|
||||||
if this_num > max_num:
|
|
||||||
return 0
|
|
||||||
ret += this_num
|
|
||||||
max_num = new_max_num
|
|
||||||
|
|
||||||
return ret
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------
|
#------------------------------------------------------------------------
|
||||||
#
|
#
|
||||||
# Paragraph Handling
|
# Paragraph Handling
|
||||||
#
|
#
|
||||||
#------------------------------------------------------------------------
|
#------------------------------------------------------------------------
|
||||||
|
|
||||||
class TexFont(object):
|
class TexFont(object):
|
||||||
def __init__(self, style=None):
|
def __init__(self, style=None):
|
||||||
if style:
|
if style:
|
||||||
@ -309,6 +422,7 @@ class TexFont(object):
|
|||||||
self.leftIndent = ""
|
self.leftIndent = ""
|
||||||
self.firstLineIndent = ""
|
self.firstLineIndent = ""
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------
|
#------------------------------------------------------------------------
|
||||||
#
|
#
|
||||||
# LaTeXDoc
|
# LaTeXDoc
|
||||||
@ -318,9 +432,252 @@ class TexFont(object):
|
|||||||
class LaTeXDoc(BaseDoc, TextDoc):
|
class LaTeXDoc(BaseDoc, TextDoc):
|
||||||
"""LaTeX document interface class. Derived from BaseDoc"""
|
"""LaTeX document interface class. Derived from BaseDoc"""
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------
|
||||||
|
# some additional variables
|
||||||
|
# -------------------------------------------------------------------------
|
||||||
|
in_table = False
|
||||||
|
spec_var_col = 0
|
||||||
|
textmem = []
|
||||||
|
in_title = True
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------
|
||||||
|
# begin of table special treatment
|
||||||
|
# -------------------------------------------------------------------------
|
||||||
|
def emit(self, text, tab_state=CELL_TEXT, span=1):
|
||||||
|
"""
|
||||||
|
Hand over all text but tables to self._backend.write(), (line 1-2).
|
||||||
|
In case of tables pass to specal treatment below.
|
||||||
|
"""
|
||||||
|
if not self.in_table: # all stuff but table
|
||||||
|
self._backend.write(text)
|
||||||
|
else:
|
||||||
|
self.handle_table(text, tab_state, span)
|
||||||
|
|
||||||
|
|
||||||
|
def handle_table(self, text, tab_state, span):
|
||||||
|
"""
|
||||||
|
Collect tables elements in an adequate cell/row/table structure and
|
||||||
|
call for LaTeX width calculations and writing out
|
||||||
|
"""
|
||||||
|
if tab_state == CELL_BEG:
|
||||||
|
# here text is head
|
||||||
|
self.textmem = []
|
||||||
|
self.curcol_char = get_charform(self.curcol-1)
|
||||||
|
if span > 1: # phantom columns prior to multicolumns
|
||||||
|
for col in range(self.curcol - span, self.curcol - 1):
|
||||||
|
col_char = get_charform(col)
|
||||||
|
phantom = Tab_Cell(col_char, 0, '')
|
||||||
|
self.tabrow.cells.append(phantom)
|
||||||
|
if not self.tabrow.cells and text.rfind('{|l') != -1:
|
||||||
|
self.leftmost_vrule = True
|
||||||
|
if (self.leftmost_vrule and
|
||||||
|
self.curcol == self.numcols and
|
||||||
|
text.endswith('l}')):
|
||||||
|
text = text.replace('l}', 'l|}')
|
||||||
|
self.tabcell = Tab_Cell(self.curcol_char, span, text)
|
||||||
|
elif tab_state == CELL_TEXT:
|
||||||
|
self.textmem.append(text)
|
||||||
|
elif tab_state == CELL_END: # text == ''
|
||||||
|
self.tabcell.content = ''.join(self.textmem)
|
||||||
|
if self.tabcell.content.find('\\centering') != -1:
|
||||||
|
self.tabcell.content = self.tabcell.content.replace(
|
||||||
|
'\\centering', '')
|
||||||
|
self.tabcell.head = re.sub(
|
||||||
|
TBLFMT_PAT, '\\1c\\2', self.tabcell.head)
|
||||||
|
self.tabcell.content = self.tabcell.content.replace('\n\n}', '}')
|
||||||
|
self.tabrow.cells.append(self.tabcell)
|
||||||
|
self.textmem = []
|
||||||
|
elif tab_state == ROW_BEG:
|
||||||
|
self.tabrow = Tab_Row()
|
||||||
|
self.leftmost_vrule = False
|
||||||
|
elif tab_state == ROW_END:
|
||||||
|
self.tabrow.tail = ''.join(self.textmem)
|
||||||
|
self.tabrow.addit = text # text: \\hline, \\cline{}
|
||||||
|
self.tabmem.rows.append(self.tabrow)
|
||||||
|
elif tab_state == TAB_BEG: # text: \\begin{longtable}[l]{<tblfmt>}
|
||||||
|
self.tabmem = Tab_Mem(text)
|
||||||
|
elif tab_state == NESTED_MINPG:
|
||||||
|
self.tabcell.nested_minpg = True
|
||||||
|
self.tabcell.content.append(text)
|
||||||
|
elif tab_state == TAB_END: # text: \\end{longtable}
|
||||||
|
self.tabmem.tail = text
|
||||||
|
|
||||||
|
# table completed, calc widths and write out
|
||||||
|
self.calc_latex_widths()
|
||||||
|
self.write_table()
|
||||||
|
|
||||||
|
|
||||||
|
def calc_latex_widths(self):
|
||||||
|
"""
|
||||||
|
In tab-cells LaTeX needs fixed width for minipages.
|
||||||
|
Evaluations are set up here and passed to LaTeX:
|
||||||
|
Calculate needed/usable widths (lengths),
|
||||||
|
adjust rows to equal widths (lengths), thus prepared to put something
|
||||||
|
like hints as '→ ...' in the FamilySheet at rightmost position.
|
||||||
|
??? Can all this be done exclusively in TeX? Don't know how.
|
||||||
|
"""
|
||||||
|
self._backend.write('\\inittabvars{\\grwidthused}{\\tabcolsep}%\n')
|
||||||
|
width_used = ['\\tabcolsep']
|
||||||
|
|
||||||
|
for col_num in range(self.numcols):
|
||||||
|
col_char = get_charform(col_num)
|
||||||
|
|
||||||
|
if MINIPAGE_COL < 0:
|
||||||
|
self.spec_var_col = self.numcols + MINIPAGE_COL
|
||||||
|
else:
|
||||||
|
self.spec_var_col = MINIPAGE_COL
|
||||||
|
|
||||||
|
# for all columns but spec_var_col: calculate needed col width
|
||||||
|
if col_num == self.spec_var_col:
|
||||||
|
continue
|
||||||
|
self._backend.write(''.join(('\\inittabvars{\\grcolwidth',
|
||||||
|
col_char, '}{0.0em}%\n')))
|
||||||
|
for row in self.tabmem.rows:
|
||||||
|
cell = row.cells[col_num]
|
||||||
|
if cell.span:
|
||||||
|
for part in cell.content.split(PAT_FOR_LINE_BREAK):
|
||||||
|
self._backend.write(''.join(('\\grcalctextwidth{',
|
||||||
|
part, '}{\\grcolwidth', col_char, '}%\n')))
|
||||||
|
row.cells[col_num].content = cell.content.replace(
|
||||||
|
PAT_FOR_LINE_BREAK, '~\\newline %\n')
|
||||||
|
self._backend.write(''.join(('\\addtolength{\\grwidthused}{',
|
||||||
|
'\\grcolwidth', col_char, '+\\tabcolsep}%\n')))
|
||||||
|
self._backend.write(''.join(('\\inittabvars{',
|
||||||
|
'\\grwidthusedtill', col_char, '}{ \\grwidthused}%\n')))
|
||||||
|
width_used.append('\\grwidthusedtill' + col_char)
|
||||||
|
self._backend.write(''.join(('\\inittabvars{\\grwidthavailable}{',
|
||||||
|
'\\textwidth-\\grwidthused}%\n')))
|
||||||
|
|
||||||
|
# spec_var_col
|
||||||
|
self._backend.write('\\inittabvars{\\grmaxrowwidth}{0.0em}%\n')
|
||||||
|
row_alph_counter = str_incr(ROW_COUNT_BASE)
|
||||||
|
for row in self.tabmem.rows:
|
||||||
|
row_alph_id = row_alph_counter.next()
|
||||||
|
row.spec_var_cell_width = ''.join(('\\grcellwidth', row_alph_id))
|
||||||
|
|
||||||
|
cell = row.cells[self.spec_var_col]
|
||||||
|
self._backend.write(''.join(('\\inittabvars{',
|
||||||
|
row.spec_var_cell_width, '}{0.0em}%\n')))
|
||||||
|
|
||||||
|
lines = cell.content.split(PAT_FOR_LINE_BREAK)
|
||||||
|
for part in lines:
|
||||||
|
self._backend.write(''.join(('\\grcalctextwidth{', part, '}{',
|
||||||
|
row.spec_var_cell_width, '}%\n')))
|
||||||
|
row.cells[self.spec_var_col].content = '~\\newline %\n'.join(lines)
|
||||||
|
|
||||||
|
# shorten cells too long, calc row-length, search max row width
|
||||||
|
self._backend.write('\\inittabvars{\\grspangain}{0.0em}')
|
||||||
|
if cell.span > 1:
|
||||||
|
self._backend.write(''.join(('\\inittabvars{\\grspangain}{',
|
||||||
|
width_used[self.spec_var_col], '-',
|
||||||
|
width_used[self.spec_var_col - cell.span + 1], '}%\n')))
|
||||||
|
self._backend.write(''.join(('\\inittabvars{\\grspecavailable}{',
|
||||||
|
'\\grwidthavailable+\\grspangain}%\n')))
|
||||||
|
self._backend.write(''.join(('\\grminvaltofirst{',
|
||||||
|
row.spec_var_cell_width, '}{\\grspecavailable}%\n')))
|
||||||
|
row.total_width = ''.join(('\\grrowwidth', row_alph_id))
|
||||||
|
self._backend.write(''.join(('\\inittabvars{', row.total_width,
|
||||||
|
'}{\\grwidthused +', row.spec_var_cell_width,
|
||||||
|
'-\\grspangain}%\n')))
|
||||||
|
self._backend.write(''.join(('\\grmaxvaltofirst{\\grmaxrowwidth}{',
|
||||||
|
row.total_width, '}%\n')))
|
||||||
|
|
||||||
|
# widen spec_var cell:
|
||||||
|
# (special feature; allows text to be placed at the right border.
|
||||||
|
# for later use, doesn't matter here)
|
||||||
|
for row in self.tabmem.rows:
|
||||||
|
self._backend.write(''.join(('\\grmaxvaltofirst{',
|
||||||
|
row.spec_var_cell_width, '}{', row.spec_var_cell_width,
|
||||||
|
'+\\grmaxrowwidth-\\grspangain-', row.total_width, '}%\n')))
|
||||||
|
|
||||||
|
|
||||||
|
def write_table(self):
|
||||||
|
# open table with '\\begin{longtable}':
|
||||||
|
self._backend.write(''.join(self.tabmem.head))
|
||||||
|
|
||||||
|
# special treatment at begin of longtable for heading and
|
||||||
|
# closing at top and bottom of table
|
||||||
|
# and parts of it at pagebreak separating
|
||||||
|
(separate,
|
||||||
|
complete_row) = self.mk_first_row(self.tabmem.rows[FIRST_ROW])
|
||||||
|
self._backend.write(separate)
|
||||||
|
self._backend.write('\\endhead%\n')
|
||||||
|
self._backend.write(separate.replace('raisebox{+1ex}',
|
||||||
|
'raisebox{-2ex}'))
|
||||||
|
self._backend.write('\\endfoot%\n')
|
||||||
|
if self.head_line:
|
||||||
|
self._backend.write('\\hline%\n')
|
||||||
|
self.head_line= False
|
||||||
|
else:
|
||||||
|
self._backend.write('%\n')
|
||||||
|
self._backend.write(complete_row)
|
||||||
|
self._backend.write('\\endfirsthead%\n')
|
||||||
|
self._backend.write('\\endlastfoot%\n')
|
||||||
|
|
||||||
|
# now hand over subsequent rows
|
||||||
|
for row in self.tabmem.rows[SUBSEQ_ROW:]:
|
||||||
|
complete_row = self.mk_subseq_rows(row)
|
||||||
|
self._backend.write(complete_row)
|
||||||
|
|
||||||
|
# close table with '\\end{longtable}':
|
||||||
|
self._backend.write(''.join(self.tabmem.tail))
|
||||||
|
|
||||||
|
|
||||||
|
def mk_first_row(self, first_row):
|
||||||
|
complete =[]
|
||||||
|
separate =[]
|
||||||
|
add_vdots = ''
|
||||||
|
for cell in first_row.cells:
|
||||||
|
if cell.span == 0: # phantom columns prior to multicolumns
|
||||||
|
continue
|
||||||
|
leading = '{'
|
||||||
|
closing = '} & %\n'
|
||||||
|
if get_numform(cell.colchar) == self.spec_var_col:
|
||||||
|
leading = ''.join(('{\\tabheadstrutceil\\begin{minipage}[t]{',
|
||||||
|
first_row.spec_var_cell_width, '}{'))
|
||||||
|
closing = '\\tabheadstrutfloor}\\end{minipage}} & %\n'
|
||||||
|
if (not separate and
|
||||||
|
get_numform(cell.colchar) == self.numcols - 1):
|
||||||
|
add_vdots = ''.join(('\\hspace*{\\fill}\\hspace*{\\fill}',
|
||||||
|
'\\raisebox{+1ex}{\\vdots}'))
|
||||||
|
complete.append(''.join((cell.head, leading,
|
||||||
|
cell.content, closing)))
|
||||||
|
separate.append(''.join((cell.head, leading,
|
||||||
|
'\\hspace*{\\fill}\\raisebox{+1ex}{\\vdots}',
|
||||||
|
add_vdots, '\\hspace*{\\fill}', closing)))
|
||||||
|
return (''.join((''.join(separate)[:-4], '%\n', first_row.tail)),
|
||||||
|
''.join((''.join(complete)[:-4], '%\n', first_row.tail,
|
||||||
|
first_row.addit)))
|
||||||
|
|
||||||
|
|
||||||
|
def mk_subseq_rows(self, row):
|
||||||
|
complete =[]
|
||||||
|
for cell in row.cells:
|
||||||
|
if cell.span == 0: # phantom columns prior to multicolumns
|
||||||
|
continue
|
||||||
|
leading = '{'
|
||||||
|
closing = '} & %\n'
|
||||||
|
if get_numform(cell.colchar) == self.spec_var_col: # last col
|
||||||
|
if cell.nested_minpg:
|
||||||
|
cell.content.replace('\\begin{minipage}{\\grminpgwidth}',
|
||||||
|
''.join(('\\begin{minipage}{0.8',
|
||||||
|
row.spec_var_cell_width, '}')))
|
||||||
|
leading = ''.join(('{\\tabrowstrutceil\\begin{minipage}[t]{',
|
||||||
|
row.spec_var_cell_width, '}{'))
|
||||||
|
closing = '}\\end{minipage}} & %\n'
|
||||||
|
complete.append(''.join((cell.head, leading,
|
||||||
|
cell.content, closing)))
|
||||||
|
return ''.join((''.join(complete)[:-4], '%\n', row.tail, row.addit))
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------
|
||||||
|
# end of special table treatment
|
||||||
|
# ---------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
def page_break(self):
|
def page_break(self):
|
||||||
"Forces a page break, creating a new page"
|
"Forces a page break, creating a new page"
|
||||||
self._backend.write('\\newpage ')
|
self.emit('\\newpage%\n')
|
||||||
|
|
||||||
def open(self, filename):
|
def open(self, filename):
|
||||||
"""Opens the specified file, making sure that it has the
|
"""Opens the specified file, making sure that it has the
|
||||||
@ -345,11 +702,12 @@ class LaTeXDoc(BaseDoc, TextDoc):
|
|||||||
|
|
||||||
# Use the article template, T1 font encodings, and specify
|
# Use the article template, T1 font encodings, and specify
|
||||||
# that we should use Latin1 and unicode character encodings.
|
# that we should use Latin1 and unicode character encodings.
|
||||||
self._backend.write(_LATEX_TEMPLATE_1 % options)
|
self.emit(_LATEX_TEMPLATE_1 % options)
|
||||||
self._backend.write(_LATEX_TEMPLATE)
|
self.emit(_LATEX_TEMPLATE)
|
||||||
|
|
||||||
self.in_list = 0
|
self.in_list = False
|
||||||
self.in_table = 0
|
self.in_table = False
|
||||||
|
self.head_line = False
|
||||||
self.imagenum = 0
|
self.imagenum = 0
|
||||||
|
|
||||||
#Establish some local styles for the report
|
#Establish some local styles for the report
|
||||||
@ -370,8 +728,8 @@ class LaTeXDoc(BaseDoc, TextDoc):
|
|||||||
# Is there special alignment? (default is left)
|
# Is there special alignment? (default is left)
|
||||||
align = style.get_alignment_text()
|
align = style.get_alignment_text()
|
||||||
if align == "center":
|
if align == "center":
|
||||||
thisstyle.font_beg += "\\centerline{"
|
thisstyle.font_beg += "{\\centering"
|
||||||
thisstyle.font_end = "}" + thisstyle.font_end
|
thisstyle.font_end = ''.join(("\n\n}", thisstyle.font_end))
|
||||||
elif align == "right":
|
elif align == "right":
|
||||||
thisstyle.font_beg += "\\hfill"
|
thisstyle.font_beg += "\\hfill"
|
||||||
|
|
||||||
@ -404,15 +762,15 @@ class LaTeXDoc(BaseDoc, TextDoc):
|
|||||||
def close(self):
|
def close(self):
|
||||||
"""Clean up and close the document"""
|
"""Clean up and close the document"""
|
||||||
if self.in_list:
|
if self.in_list:
|
||||||
self._backend.write('\\end{enumerate}\n')
|
self.emit('\\end{list}\n')
|
||||||
self._backend.write('\n\\end{document}\n')
|
self.emit('\\end{document}\n')
|
||||||
self._backend.close()
|
self._backend.close()
|
||||||
|
|
||||||
def end_page(self):
|
def end_page(self):
|
||||||
"""Issue a new page command"""
|
"""Issue a new page command"""
|
||||||
self._backend.write('\\newpage')
|
self.emit('\\newpage')
|
||||||
|
|
||||||
def start_paragraph(self,style_name,leader=None):
|
def start_paragraph(self, style_name, leader=None):
|
||||||
"""Paragraphs handling - A Gramps paragraph is any
|
"""Paragraphs handling - A Gramps paragraph is any
|
||||||
single body of text from a single word to several sentences.
|
single body of text from a single word to several sentences.
|
||||||
We assume a linebreak at the end of each paragraph."""
|
We assume a linebreak at the end of each paragraph."""
|
||||||
@ -424,78 +782,86 @@ class LaTeXDoc(BaseDoc, TextDoc):
|
|||||||
|
|
||||||
self.fbeg = ltxstyle.font_beg
|
self.fbeg = ltxstyle.font_beg
|
||||||
self.fend = ltxstyle.font_end
|
self.fend = ltxstyle.font_end
|
||||||
|
|
||||||
self.indent = ltxstyle.leftIndent
|
self.indent = ltxstyle.leftIndent
|
||||||
self.FLindent = ltxstyle.firstLineIndent
|
self.FLindent = ltxstyle.firstLineIndent
|
||||||
#firstLineIndent is not used, subtract from indent.
|
if self.indent == 0:
|
||||||
self.indent -= self.FLindent
|
self.indent = self.FLindent
|
||||||
|
|
||||||
|
# For additional vertical space beneath title line(s)
|
||||||
|
# i.e. when the first centering ended:
|
||||||
|
if self.in_title and ltxstyle.font_beg.find('centering') == -1:
|
||||||
|
self.in_title = False
|
||||||
|
self._backend.write('\\vspace{5ex}%\n')
|
||||||
|
|
||||||
|
self._backend.write('\\inittabvars{\\grleadinglabelwidth}{0.0em}%\n')
|
||||||
|
if leader:
|
||||||
|
self._backend.write(''.join((
|
||||||
|
'\\grcalctextwidth{', leader, '}{\\grleadinglabelwidth}%\n')))
|
||||||
|
self._backend.write(
|
||||||
|
'\\inittabvars{\\grlistbacksp}{\\grleadinglabelwidth +1em}%\n')
|
||||||
|
else:
|
||||||
|
self._backend.write(
|
||||||
|
'\\inittabvars{\\grlistbacksp}{0em}%\n')
|
||||||
|
|
||||||
|
# -------------------------------------------------------------------
|
||||||
|
# Gramps presumes 'cm' as units; here '\\grbaseindent' is used
|
||||||
|
# as equivalent, set in '_LATEX_TEMPLATE' above to '3em';
|
||||||
|
# there another value might be choosen.
|
||||||
|
# -------------------------------------------------------------------
|
||||||
if self.indent is not None and not self.in_table:
|
if self.indent is not None and not self.in_table:
|
||||||
myspace = '%scm' % str(self.indent)
|
self.emit(''.join(('\\inittabvars{'
|
||||||
self._backend.write('\\grampsindent{%s}\n' % myspace)
|
'\\grminpgindent}{%s\\grbaseindent-\\grlistbacksp}' %
|
||||||
self.fix_indent = 1
|
repr(self.indent), '%\n\\hspace*{\\grminpgindent}%\n',
|
||||||
|
'\\begin{minipage}[t]{\\textwidth-\\grminpgindent}',
|
||||||
|
'%\n')))
|
||||||
|
self.fix_indent = True
|
||||||
|
|
||||||
if leader is not None and not self.in_list:
|
if leader is not None and not self.in_list:
|
||||||
self._backend.write('\\begin{enumerate}\n')
|
self.in_list = True
|
||||||
self.in_list = 1
|
self._backend.write(''.join(('\\begin{list}{%\n', leader,
|
||||||
if leader is not None:
|
'}{%\n', '\\labelsep0.5em %\n',
|
||||||
# try obtaining integer
|
'\\setlength{\\labelwidth}{\\grleadinglabelwidth}%\n',
|
||||||
leader_1 = leader[:-1]
|
'\\setlength{\\leftmargin}{\\grlistbacksp}}%\n',
|
||||||
num = roman2arabic(leader_1)
|
'\\item%\n')))
|
||||||
if num == 0:
|
|
||||||
# Not roman, try arabic or fallback to 1
|
|
||||||
try:
|
|
||||||
num = int(leader_1)
|
|
||||||
except ValueError:
|
|
||||||
num = 1
|
|
||||||
self._backend.write(' \\renewcommand\\theenumi{\\arabic{enumi}}')
|
|
||||||
else:
|
|
||||||
# roman, set the case correctly
|
|
||||||
self._backend.write(' \\renewcommand\\theenumi{\\%soman{enumi}}'
|
|
||||||
% ('r' if leader_1.islower() else 'R'))
|
|
||||||
|
|
||||||
self._backend.write(' \\setcounter{enumi}{%d} ' % num)
|
|
||||||
self._backend.write(' \\addtocounter{enumi}{-1}\n')
|
|
||||||
self._backend.write(' \\item ')
|
|
||||||
|
|
||||||
if leader is None and not self.in_list and not self.in_table:
|
if leader is None:
|
||||||
self._backend.write('\n')
|
self.emit('\n')
|
||||||
|
self.emit('%s ' % self.fbeg)
|
||||||
self._backend.write('%s ' % self.fbeg)
|
|
||||||
|
|
||||||
def end_paragraph(self):
|
def end_paragraph(self):
|
||||||
"""End the current paragraph"""
|
"""End the current paragraph"""
|
||||||
newline = '\ \\newline\n'
|
newline = '%\n\n'
|
||||||
|
|
||||||
if self.in_list:
|
if self.in_list:
|
||||||
self.in_list = 0
|
self.in_list = False
|
||||||
self._backend.write('\n\\end{enumerate}\n')
|
self.emit('\n\\end{list}\n')
|
||||||
|
newline = ''
|
||||||
|
elif self.in_table:
|
||||||
newline = ''
|
newline = ''
|
||||||
|
|
||||||
elif self.in_table:
|
self.emit('%s%s' % (self.fend, newline))
|
||||||
newline = ('')
|
if self.fix_indent:
|
||||||
|
self.emit('\\end{minipage}\\parindent0em%\n\n')
|
||||||
self._backend.write('%s%s' % (self.fend, newline))
|
self.fix_indent = False
|
||||||
if self.fix_indent == 1:
|
|
||||||
self.fix_indent = 0
|
|
||||||
self._backend.write('\\grampsindent{0cm}\n')
|
|
||||||
|
|
||||||
def start_bold(self):
|
def start_bold(self):
|
||||||
"""Bold face"""
|
"""Bold face"""
|
||||||
self._backend.write('\\textbf{')
|
self.emit('\\textbf{')
|
||||||
|
|
||||||
def end_bold(self):
|
def end_bold(self):
|
||||||
"""End bold face"""
|
"""End bold face"""
|
||||||
self._backend.write('}')
|
self.emit('}')
|
||||||
|
|
||||||
def start_superscript(self):
|
def start_superscript(self):
|
||||||
self._backend.write('\\textsuperscript{')
|
self.emit('\\textsuperscript{')
|
||||||
|
|
||||||
def end_superscript(self):
|
def end_superscript(self):
|
||||||
self._backend.write('}')
|
self.emit('}')
|
||||||
|
|
||||||
def start_table(self, name,style_name):
|
def start_table(self, name,style_name):
|
||||||
"""Begin new table"""
|
"""Begin new table"""
|
||||||
self.in_table = 1
|
self.in_table = True
|
||||||
self.currow = 0
|
self.currow = 0
|
||||||
|
|
||||||
# We need to know a priori how many columns are in this table
|
# We need to know a priori how many columns are in this table
|
||||||
@ -503,33 +869,41 @@ class LaTeXDoc(BaseDoc, TextDoc):
|
|||||||
self.tblstyle = styles.get_table_style(style_name)
|
self.tblstyle = styles.get_table_style(style_name)
|
||||||
self.numcols = self.tblstyle.get_columns()
|
self.numcols = self.tblstyle.get_columns()
|
||||||
|
|
||||||
|
# early test of column count:
|
||||||
|
z = get_charform(self.numcols-1)
|
||||||
|
|
||||||
tblfmt = '*{%d}{l}' % self.numcols
|
tblfmt = '*{%d}{l}' % self.numcols
|
||||||
self._backend.write('\n\n\\begin{longtable}[l]{%s}\n' % tblfmt)
|
self.emit(
|
||||||
|
'\\begin{longtable}[l]{%s}\n' % (tblfmt), TAB_BEG)
|
||||||
|
|
||||||
def end_table(self):
|
def end_table(self):
|
||||||
"""Close the table environment"""
|
"""Close the table environment"""
|
||||||
self.in_table = 0
|
|
||||||
# Create a paragraph separation below the table.
|
# Create a paragraph separation below the table.
|
||||||
self._backend.write('\\end{longtable}\n\\par\n')
|
self.emit(
|
||||||
|
'%\n\\end{longtable}%\n\\par%\n', TAB_END)
|
||||||
|
self.in_table = False
|
||||||
|
|
||||||
def start_row(self):
|
def start_row(self):
|
||||||
"""Begin a new row"""
|
"""Begin a new row"""
|
||||||
|
self.emit('', ROW_BEG)
|
||||||
# doline/skipfirst are flags for adding hor. rules
|
# doline/skipfirst are flags for adding hor. rules
|
||||||
self.doline = 0
|
self.doline = False
|
||||||
self.skipfirst = 0
|
self.skipfirst = False
|
||||||
self.curcol = 0
|
self.curcol = 0
|
||||||
self.currow = self.currow + 1
|
self.currow = self.currow + 1
|
||||||
|
|
||||||
def end_row(self):
|
def end_row(self):
|
||||||
"""End the row (new line)"""
|
"""End the row (new line)"""
|
||||||
self._backend.write('\\\\ ')
|
self.emit('\\\\ ')
|
||||||
if self.doline == 1:
|
if self.doline:
|
||||||
if self.skipfirst == 1:
|
if self.skipfirst:
|
||||||
self._backend.write('\\cline{2-%d}\n' % self.numcols)
|
self.emit(''.join((('\\cline{2-%d}' %
|
||||||
|
self.numcols), '%\n')), ROW_END)
|
||||||
else:
|
else:
|
||||||
self._backend.write('\\hline \\\\ \n')
|
self.emit('\\hline %\n', ROW_END)
|
||||||
else:
|
else:
|
||||||
self._backend.write('\n')
|
self.emit('%\n', ROW_END)
|
||||||
|
self.emit('%\n')
|
||||||
|
|
||||||
def start_cell(self,style_name,span=1):
|
def start_cell(self,style_name,span=1):
|
||||||
"""Add an entry to the table.
|
"""Add an entry to the table.
|
||||||
@ -540,40 +914,51 @@ class LaTeXDoc(BaseDoc, TextDoc):
|
|||||||
|
|
||||||
styles = self.get_style_sheet()
|
styles = self.get_style_sheet()
|
||||||
self.cstyle = styles.get_cell_style(style_name)
|
self.cstyle = styles.get_cell_style(style_name)
|
||||||
self.lborder = self.cstyle.get_left_border()
|
|
||||||
self.rborder = self.cstyle.get_right_border()
|
|
||||||
self.bborder = self.cstyle.get_bottom_border()
|
|
||||||
self.tborder = self.cstyle.get_top_border()
|
|
||||||
self.llist = self.cstyle.get_longlist()
|
|
||||||
|
|
||||||
if self.llist == 1:
|
# ------------------------------------------------------------------
|
||||||
cellfmt = "p{\linewidth-3cm}"
|
# begin special modification for boolean values
|
||||||
else:
|
# values imported here are used for test '==1' and '!=0'. To get
|
||||||
cellfmt = "l"
|
# local boolean values the tests are now transfered to the import lines
|
||||||
|
# ------------------------------------------------------------------
|
||||||
|
self.lborder = 1 == self.cstyle.get_left_border()
|
||||||
|
self.rborder = 1 == self.cstyle.get_right_border()
|
||||||
|
self.bborder = 1 == self.cstyle.get_bottom_border()
|
||||||
|
self.tborder = 0 != self.cstyle.get_top_border()
|
||||||
|
|
||||||
|
# self.llist not needed, LaTeX has to decide on its own
|
||||||
|
# wether a line fits or not. See comment in calc_latex_widths() above.
|
||||||
|
# self.llist = 1 == self.cstyle.get_longlist()
|
||||||
|
|
||||||
|
cellfmt = "l"
|
||||||
# Account for vertical rules
|
# Account for vertical rules
|
||||||
if self.lborder == 1:
|
if self.lborder:
|
||||||
cellfmt = '|' + cellfmt
|
cellfmt = '|' + cellfmt
|
||||||
if self.rborder == 1:
|
if self.rborder:
|
||||||
cellfmt = cellfmt + '|'
|
cellfmt = cellfmt + '|'
|
||||||
|
|
||||||
# and Horizontal rules
|
# and Horizontal rules
|
||||||
if self.bborder == 1:
|
if self.bborder:
|
||||||
self.doline = 1
|
self.doline = True
|
||||||
elif self.curcol == 1:
|
elif self.curcol == 1:
|
||||||
self.skipfirst = 1
|
self.skipfirst = True
|
||||||
|
if self.tborder:
|
||||||
|
self.head_line = True
|
||||||
|
# ------------------------------------------------------------------
|
||||||
|
# end special modification for boolean values
|
||||||
|
# ------------------------------------------------------------------
|
||||||
|
|
||||||
|
self.emit(
|
||||||
|
''.join(('%\n', '\\multicolumn{%d}{%s}' % (span, cellfmt))),
|
||||||
|
CELL_BEG, span)
|
||||||
|
|
||||||
if self.tborder != 0:
|
|
||||||
self._backend.write('\\hline\n')
|
|
||||||
self._backend.write ('\\multicolumn{%d}{%s}{' % (span,cellfmt))
|
|
||||||
|
|
||||||
def end_cell(self):
|
def end_cell(self):
|
||||||
"""Prepares for next cell"""
|
"""Prepares for next cell"""
|
||||||
self._backend.write('} ')
|
self.emit('', CELL_END)
|
||||||
if self.curcol < self.numcols:
|
|
||||||
self._backend.write('& ')
|
|
||||||
|
|
||||||
def add_media_object(self, name, pos, x, y, alt='', style_name=None, crop=None):
|
|
||||||
|
def add_media_object(self, name, pos, x, y, alt='',
|
||||||
|
style_name=None, crop=None):
|
||||||
"""Add photo to report"""
|
"""Add photo to report"""
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -586,27 +971,34 @@ class LaTeXDoc(BaseDoc, TextDoc):
|
|||||||
picf = self.filename[:-4] + '_img' + str(self.imagenum) + '.eps'
|
picf = self.filename[:-4] + '_img' + str(self.imagenum) + '.eps'
|
||||||
pic.eps_convert(picf)
|
pic.eps_convert(picf)
|
||||||
|
|
||||||
|
# -------------------------------------------------------------------
|
||||||
# x and y will be maximum width OR height in units of cm
|
# x and y will be maximum width OR height in units of cm
|
||||||
mysize = 'width=%dcm, height=%dcm,keepaspectratio' % (x,y)
|
# here '\\grbaseindent' is used as equivalent, see above
|
||||||
|
# -------------------------------------------------------------------
|
||||||
|
mysize = ''.join(('width=%d\\grbaseindent, ',
|
||||||
|
'height=%d\\grbaseindent,keepaspectratio' % (x,y)))
|
||||||
if pos == "right":
|
if pos == "right":
|
||||||
self._backend.write('\\hfill\\includegraphics[%s]{%s}\n' % (mysize,picf))
|
self.emit((
|
||||||
|
'\\hfill\\includegraphics[%s]{%s}\n' % (mysize,picf)))
|
||||||
elif pos == "left":
|
elif pos == "left":
|
||||||
self._backend.write('\\includegraphics[%s]{%s}\\hfill\n' % (mysize,picf))
|
self.emit((
|
||||||
|
'\\includegraphics[%s]{%s}\\hfill\n' % (mysize,picf)))
|
||||||
else:
|
else:
|
||||||
self._backend.write('\\centerline{\\includegraphics[%s]{%s}}\n' % (mysize,picf))
|
self.emit((
|
||||||
|
'\\centering{\\includegraphics[%s]{%s}}\n' % (mysize,picf)))
|
||||||
|
|
||||||
def write_text(self,text,mark=None,links=False):
|
def write_text(self,text,mark=None,links=False):
|
||||||
"""Write the text to the file"""
|
"""Write the text to the file"""
|
||||||
if text == '\n':
|
if text == '\n':
|
||||||
text = '\\newline\n'
|
text = ''
|
||||||
text = latexescape(text)
|
text = latexescape(text)
|
||||||
|
|
||||||
if links == True:
|
if links == True:
|
||||||
text = re.sub(URL_PATTERN, _CLICKABLE, text)
|
text = re.sub(URL_PATTERN, _CLICKABLE, text)
|
||||||
|
|
||||||
#hard coded replace of the underline used for missing names/data
|
#hard coded replace of the underline used for missing names/data
|
||||||
text = text.replace('\\_'*13, '\\underline{\hspace{3cm}}')
|
text = text.replace('\\_'*13, '\\underline{\hspace{3\\grbaseindent}}')
|
||||||
self._backend.write(text)
|
self.emit(text + ' ')
|
||||||
|
|
||||||
def write_styled_note(self, styledtext, format, style_name,
|
def write_styled_note(self, styledtext, format, style_name,
|
||||||
contains_html=False, links=False):
|
contains_html=False, links=False):
|
||||||
@ -618,7 +1010,7 @@ class LaTeXDoc(BaseDoc, TextDoc):
|
|||||||
contains_html: bool, the backend should not check if html is present.
|
contains_html: bool, the backend should not check if html is present.
|
||||||
If contains_html=True, then the textdoc is free to handle that in
|
If contains_html=True, then the textdoc is free to handle that in
|
||||||
some way. Eg, a textdoc could remove all tags, or could make sure
|
some way. Eg, a textdoc could remove all tags, or could make sure
|
||||||
a link is clickable. LatexDoc ignores notes that contain html
|
a link is clickable. self ignores notes that contain html
|
||||||
links: bool, make URLs clickable if True
|
links: bool, make URLs clickable if True
|
||||||
"""
|
"""
|
||||||
if contains_html:
|
if contains_html:
|
||||||
@ -640,18 +1032,21 @@ class LaTeXDoc(BaseDoc, TextDoc):
|
|||||||
# A good solution for this ???
|
# A good solution for this ???
|
||||||
# A quick solution: create a minipage for the note and add that always
|
# A quick solution: create a minipage for the note and add that always
|
||||||
# hoping that the user will have left sufficient room for the page
|
# hoping that the user will have left sufficient room for the page
|
||||||
self._backend.write("\\begin{minipage}{{0.8\\linewidth}}\n")
|
#
|
||||||
|
# now solved by postprocessing in emit()
|
||||||
|
# by explicitely calculating column widths
|
||||||
|
#
|
||||||
if format:
|
if format:
|
||||||
self.start_paragraph(style_name)
|
self.start_paragraph(style_name)
|
||||||
self._backend.write(markuptext)
|
self.emit(markuptext)
|
||||||
self.end_paragraph()
|
self.end_paragraph()
|
||||||
#preformatted finished, go back to normal escape function
|
#preformatted finished, go back to normal escape function
|
||||||
self._backend.setescape(False)
|
self._backend.setescape(False)
|
||||||
else:
|
else:
|
||||||
for line in markuptext.split('\n\n'):
|
for line in markuptext.split('%\n%\n'):
|
||||||
self.start_paragraph(style_name)
|
self.start_paragraph(style_name)
|
||||||
for realline in line.split('\n'):
|
for realline in line.split('\n'):
|
||||||
self._backend.write(realline)
|
self.emit(realline)
|
||||||
self._backend.write("\\newline\n")
|
self.emit("~\\newline%\n")
|
||||||
self.end_paragraph()
|
self.end_paragraph()
|
||||||
self._backend.write("\n\\vspace*{0.5cm} \n\\end{minipage}\n\n")
|
|
||||||
|
Loading…
Reference in New Issue
Block a user