diff --git a/gramps/src/docgen/HtmlDoc.py b/gramps/src/docgen/HtmlDoc.py index 48a226a73..c54e58ded 100644 --- a/gramps/src/docgen/HtmlDoc.py +++ b/gramps/src/docgen/HtmlDoc.py @@ -3,6 +3,51 @@ # # Copyright (C) 2000 Donald N. Allingham # +# Modified August 2002 by Gary Shao +# +# Removed Gramps dependencies. +# +# Removed dependencies on Gnome UI. +# +# Moved call to build_style_declaration() out of __init__ method and +# into open method to allow cell table styles to get emitted in HTML. +# +# Added style entry for underlined text in HTML output +# +# Changed statements which constructed paths using "%s/%s" string +# formatting into ones using the os.path.join function to give better +# cross-platform compatibility. +# +# Allowed table width to default to 0, which causes output table +# to have column widths that are automatically sized to the length +# of their contents. +# +# Added support for start_bold() and end_bold() methods of TextDoc +# class for inline bolding of text. +# +# Modified open() and close() methods to allow the filename parameter +# passed to open() to be either a string containing a file name, or +# a Python file object. This allows the document generator to be more +# easily used with its output directed to stdout, as may be called for +# in a CGI script. +# +# Modified September 2002 by Gary Shao +# +# Changed implicit conversion of '\n' character to
command in +# write_text() to instead require an explicit call to line_break() +# for insertion of
into text. This makes the paragraph behavior +# a better match for that of other document generators. +# +# Added start_listing() and end_listing() methods to allow displaying +# text blocks without automatic filling and justification. Intended +# for printing things like source code and plain text graphics. +# +# Added support for start_italic() and end_italic() methods of TextDoc +# class for inline italicizing of text. +# +# Added method show_link() to display a link as an anchor. +# This method really only has an active role in the HTML generator. +# # 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 # the Free Software Foundation; either version 2 of the License, or @@ -23,20 +68,27 @@ import string import re import time -import gnome.ui -import Plugins import ImgManip import TarFile -import const from TextDoc import * -from intl import gettext -_ = gettext +try: + import gnome.ui + import Plugins + import const + from intl import gettext + _ = gettext +except: + withGramps = 0 + Version = "1.0" +else: + withGramps = 1 t_header_line_re = re.compile(r"(.*)(.*)(.*)", re.DOTALL|re.IGNORECASE|re.MULTILINE) + #------------------------------------------------------------------------ # # Default template @@ -85,10 +137,9 @@ class HtmlDoc(TextDoc): self.filename = None self.top = [] self.bottom = [] - self.base = "" + self.base = "." self.load_template() self.build_header() - self.build_style_declaration() self.image_dir = "images" else: self.owner = source.owner @@ -146,7 +197,11 @@ class HtmlDoc(TextDoc): if top_add == 1: mymsg = _("The marker '' was not in the template") - gnome.ui.GnomeErrorDialog(mymsg) + if withGramps: + gnome.ui.GnomeErrorDialog(mymsg) + else: + print mymsg + raise "TemplateError: No START marker" def load_html(self): start = re.compile(r"") @@ -171,7 +226,11 @@ class HtmlDoc(TextDoc): if top_add == 1: mymsg = _("The marker '' was not in the template") - gnome.ui.GnomeErrorDialog(mymsg) + if withGramps: + gnome.ui.GnomeErrorDialog(mymsg) + else: + print mymsg + raise "TemplateError: No START marker" def load_template(self): if self.template: @@ -184,13 +243,19 @@ class HtmlDoc(TextDoc): mymsg = _("Could not open %s\nUsing the default template") % \ self.template mymsg = "%s\n%s" % (mymsg,msg) - gnome.ui.GnomeWarningDialog(mymsg) + if withGramps: + gnome.ui.GnomeWarningDialog(mymsg) + else: + print mymsg self.bottom = _bottom self.top = _top except: mymsg = _("Could not open %s\nUsing the default template") % \ self.template - gnome.ui.GnomeWarningDialog(mymsg) + if withGramps: + gnome.ui.GnomeWarningDialog(mymsg) + else: + print mymsg self.bottom = _bottom self.top = _top else: @@ -198,20 +263,29 @@ class HtmlDoc(TextDoc): self.top = _top def process_line(self,line): - l = string.replace(line,'$VERSION',const.version) + if withGramps: + l = string.replace(line,'$VERSION',const.version) + else: + l = string.replace(line,'$VERSION',Version) return string.replace(l,'$COPYRIGHT',self.copyright) def open(self,filename): - (r,e) = os.path.splitext(filename) - if e == self.ext: - self.filename = filename - else: - self.filename = filename + self.ext + if type(filename) == type(""): + (r,e) = os.path.splitext(filename) + if e == self.ext: + self.filename = filename + else: + self.filename = filename + self.ext - self.base = os.path.dirname(self.filename) + self.base = os.path.dirname(self.filename) - self.f = open(self.filename,"w") + self.f = open(self.filename,"w") + self.alreadyOpen = 0 + elif hasattr(filename, "write"): + self.f = filename + self.alreadyOpen = 1 self.f.write(self.file_header) + self.build_style_declaration() self.f.write(self.style_declaration) def build_header(self): @@ -265,11 +339,13 @@ class HtmlDoc(TextDoc): if style.get_right_border(): right = 'thin solid #000000' - italic = bold = '' + italic = bold = underline = '' if font.get_italic(): italic = 'font-style:italic; ' if font.get_bold(): bold = 'font-weight:bold; ' + if font.get_underline(): + underline = 'text-decoration:underline; ' if font.get_type_face() == FONT_SANS_SERIF: family = '"Helvetica","Arial","sans-serif"' else: @@ -281,12 +357,12 @@ class HtmlDoc(TextDoc): '\tmargin-right: %scm; margin-left: %scm;\n' '\tborder-top:%s; border-bottom:%s;\n' '\tborder-left:%s; border-right:%s;\n' - '\t%s%sfont-family:%s;\n}' + '\t%s%s%sfont-family:%s;\n}' % (key, font_size, font_color, align, text_indent, right_margin, left_margin, top, bottom, left, right, - italic, bold, family)) + italic, bold, underline, family)) text.append('-->\n') self.style_declaration = string.join(text,'\n') @@ -294,14 +370,15 @@ class HtmlDoc(TextDoc): def close(self): for line in self.bottom: self.f.write(self.process_line(line)) - self.f.close() + if not self.alreadyOpen: + self.f.close() def write_support_files(self): if self.map: for name in self.map.keys(): if name == 'template.html': continue - fname = '%s/%s' % (self.base,name) + fname = '%s' % (os.path.join(self.base,name)) f = open(fname, 'wb') f.write(self.map[name].read()) f.close() @@ -312,7 +389,10 @@ class HtmlDoc(TextDoc): refname = "is%s" % os.path.basename(name) if self.image_dir: - imdir = "%s/%s" % (self.base,self.image_dir) + if self.base: + imdir = "%s" % (os.path.join(self.base,self.image_dir)) + else: + imdir = "%s" % (self.image_dir) else: imdir = self.base @@ -324,7 +404,7 @@ class HtmlDoc(TextDoc): try: img = ImgManip.ImgManip(name) - img.jpg_thumbnail("%s/%s" % (imdir,refname),size,size) + img.jpg_thumbnail("%s" % (os.path.join(imdir,refname)),size,size) except: return @@ -335,15 +415,23 @@ class HtmlDoc(TextDoc): else: xtra = '' + if pos == "center": + self.f.write('
') if self.image_dir: - self.f.write('\n' % \ - (self.image_dir,refname,xtra)) + self.f.write('' % \ + (os.path.join(self.image_dir,refname),xtra)) else: - self.f.write('\n' % (refname,xtra)) + self.f.write('' % (refname,xtra)) + if pos == "center": + self.f.write('
') + self.f.write('\n') def start_table(self,name,style): self.tbl = self.table_styles[style] - self.f.write('\n') def end_table(self): @@ -362,7 +450,7 @@ class HtmlDoc(TextDoc): if span > 1: self.f.write(' colspan="' + str(span) + '"') self.col = self.col + 1 - else: + elif self.tbl.get_column_width(self.col) > 0: self.f.write(' width="') self.f.write(str(self.tbl.get_column_width(self.col))) self.f.write('%"') @@ -374,6 +462,55 @@ class HtmlDoc(TextDoc): def end_cell(self): self.f.write('\n') + def start_listing(self,style_name): + style = self.style_list[style_name] + font = style.get_font() + font_size = font.get_size() + font_color = '#%02x%02x%02x' % font.get_color() + right_margin = "%.2f" % style.get_right_margin() + left_margin = "%.2f" % style.get_left_margin() + top = bottom = left = right = 'none' + pad = "%.3fcm" % style.get_padding() + if style.get_top_border(): + top = 'thin solid #000000' + if style.get_bottom_border(): + bottom = 'thin solid #000000' + if style.get_left_border(): + left = 'thin solid #000000' + if style.get_right_border(): + right = 'thin solid #000000' + + italic = bold = underline = '' + if font.get_italic(): + italic = 'font-style:italic; ' + if font.get_bold(): + bold = 'font-weight:bold; ' + if font.get_underline(): + underline = 'text-decoration:underline; ' + if font.get_type_face() == FONT_MONOSPACE: + family = 'Courier,monospace' + elif font.get_type_face() == FONT_SANS_SERIF: + family = 'Helvetica,Arial,sans-serif' + else: + family = 'Times New Roman,Times,serif' + + styleStr = '
\n' % \
+                     (italic, bold, underline, family)
+        self.f.write(styleStr)
+
+    def end_listing(self):
+        self.f.write('
\n') + def start_paragraph(self,style_name,leader=None): self.f.write('

') if leader != None: @@ -389,7 +526,37 @@ class HtmlDoc(TextDoc): def write_text(self,text): if text != "": self.empty = 0 - text = string.replace(text,'\n','
') + #text = string.replace(text,'\n','
') self.f.write(text) -Plugins.register_text_doc(_("HTML"),HtmlDoc,1,0,1) + def start_bold(self): + self.f.write('') + + def end_bold(self): + self.f.write('') + + def start_italic(self): + self.f.write('') + + def end_italic(self): + self.f.write('') + + def line_break(self): + self.f.write('
\n') + + def show_link(self, text, href): + self.write_text(' %s ' % (href, text)) + +#------------------------------------------------------------------------ +# +# Register the document generator with the system if in Gramps +# +#------------------------------------------------------------------------ +if withGramps: + Plugins.register_text_doc( + name=_("HTML"), + classref=HtmlDoc, + table=1, + paper=0, + style=1 + ) diff --git a/gramps/src/docgen/LaTeXDoc.py b/gramps/src/docgen/LaTeXDoc.py index b810a37e1..5068c4d0e 100644 --- a/gramps/src/docgen/LaTeXDoc.py +++ b/gramps/src/docgen/LaTeXDoc.py @@ -6,6 +6,57 @@ # Modifications and feature additions: # 2002 Donald A. Peterson # +# Modified August 2002 by Gary Shao +# +# Removed Gramps dependencies +# +# Added rightIndent, bottomBorder, and topBorder attributes to TexFont +# class in support of allowing these properties to be expressed when +# defining paragraphs. +# +# Completely changed the way paragraph margins are handled. Now use +# LaTeX \parbox command to create a paragraph region, and \hspace command +# to position it on the page. Old method ignored the right margin, +# and didn't seem to correctly handle left margins or first line +# indents. +# +# Replaced instances of \centerline command with use of \hspace*{\fill} +# to achieve centered text. This was particularly a problem inside +# tables, where LaTeX would occasionally reject the original output +# constructs. +# +# Enabled the use of underline font property. +# +# Enable the drawing of top and bottom paragraph borders using the +# LaTeX \rule command. +# +# Reworked the way table declarations were written to allow table +# width to be specified as a percentages of \textwidth and column +# widths as percentages of table width, in the spirit of how TextDoc +# intended. Table widths of 0 will result in tables that are sized +# automatically by LaTeX. +# +# Modified open() and close() methods to allow the filename parameter +# passed to open() to be either a string containing a file name, or +# a Python file object. This allows the document generator to be more +# easily used with its output directed to stdout, as may be called for +# in a CGI script. +# +# Modified August 2002 by Gary Shao +# +# Added line_break() and page_break() methods to LaTeXDoc class. +# +# Added two new methods (start_listing() and end_listing()) to +# enable writing a text block with no filling or justifying +# Implementation uses the fancyvrb package. +# +# Added new methods start_italic() and end_italic() to enable +# italicizing parts of text within a paragraph +# +# Added method show_link() to display in text the value of a link. +# This method really only has an active role in the HTML generator, +# but is provided here for interface consistency. +# # 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 # the Free Software Foundation; either version 2 of the License, or @@ -29,10 +80,15 @@ # #------------------------------------------------------------------------ from TextDoc import * -import Plugins import ImgManip -import intl -_ = intl.gettext +try: + import Plugins + import intl + _ = intl.gettext +except: + withGramps = 0 +else: + withGramps = 1 #------------------------------------------------------------------------ # @@ -45,12 +101,18 @@ class TexFont(TextDoc): self.font_beg = style.font_beg self.font_end = style.font_end self.leftIndent = style.left_indent + self.rightIndent = style.right_indent self.firstLineIndent = style.firstLineIndent + self.topBorder = style.topBorder + self.bottomBorder = style.bottomBorder else: self.font_beg = "" self.font_end = "" self.leftIndent = "" + self.rightIndent = "" self.firstLineIndent = "" + self.topBorder = 0 + self.bottomBorder = 0 #------------------------------------------------------------------------ # @@ -63,12 +125,16 @@ class LaTeXDoc(TextDoc): def open(self,filename): """Opens the specified file, making sure that it has the extension of .tex""" - - if filename[-4:] != ".tex": - self.filename = filename + ".tex" - else: - self.filename = filename - self.f = open(self.filename,"w") + if type(filename) == type(""): + if filename[-4:] != ".tex": + self.filename = filename + ".tex" + else: + self.filename = filename + self.f = open(self.filename,"w") + self.alreadyOpen = 0 + elif hasattr(filename, "write"): + self.f = filename + self.alreadyOpen = 1 # Font size control seems to be limited. For now, ignore # any style constraints, and use 12pt has the default @@ -102,29 +168,33 @@ class LaTeXDoc(TextDoc): self.f.write('\\usepackage{graphicx} % Extended graphics support\n') self.f.write('\\usepackage{longtable} % For multi-page tables\n') self.f.write('\\usepackage{calc} % For margin indents\n') + self.f.write('\\usepackage{fancyvrb} % For listing blocks\n') self.f.write('%\n% Depending on your LaTeX installation, the') self.f.write(' margins may be too\n% narrow. ') self.f.write(' This can be corrected by uncommenting the following\n') self.f.write('% two lines and adjusting the width appropriately.') - self.f.write(' The example\n% removes 0.5in from each margin.') - self.f.write(' (Adds 1 inch to the text)\n') - self.f.write('%\\addtolength{\\oddsidemargin}{-0.5in}\n') - self.f.write('%\\addtolength{\\textwidth}{1.0in}\n%\n') - self.f.write('% Create a margin-adjusting command that allows LaTeX\n') + self.f.write(' The example\n% removes 0.5in from the left margin.') + self.f.write(' (Adds 0.5 inch to the text)\n') + self.f.write('\\addtolength{\\oddsidemargin}{-0.5in}\n') + self.f.write('\\addtolength{\\textwidth}{0.5in}\n%\n') + self.f.write('\\setlength{\\parskip}{1.3ex plus0.5ex minus0.5ex}\n') + self.f.write('% Create a first indent-adjusting command that allows LaTeX\n') self.f.write('% to behave like the other gramps-supported output formats\n') - self.f.write('\\newlength{\\leftedge}\n') - self.f.write('\\setlength{\\leftedge}{\\parindent}\n') - self.f.write('\\newlength{\\grampstext}\n') - self.f.write('\\setlength{\\grampstext}{\\textwidth}\n') - self.f.write('\\newcommand{\\grampsindent}[1]{%\n') - self.f.write(' \\setlength{\\parindent}{\\leftedge + #1}%\n') - self.f.write(' \\setlength{\\textwidth}{\\grampstext - #1}%\n') + self.f.write('\\setlength{\\parindent}{0cm}\n') + self.f.write('\\newlength{\\newwidth}\n') + self.f.write('\\newcommand{\\grampsfirst}[1]{%\n') + self.f.write(' \\setlength{\\parindent}{#1}%\n') self.f.write('}\n\n') self.f.write('\\begin{document}\n\n') self.in_list = 0 self.in_table = 0 self.imagenum = 0 + self.in_cell = 0 + self.cell_header_written = 0 + self.last_indent = 0 + self.fix_first = 0 + self.in_listing = 0 #Establish some local styles for the report self.latexstyle = {} @@ -143,10 +213,11 @@ class LaTeXDoc(TextDoc): # Is there special alignment? (default is left) align = style.get_alignment_text() if align == "center": - thisstyle.font_beg = thisstyle.font_beg + "\\centerline{" - thisstyle.font_end = "}" + thisstyle.font_end + thisstyle.font_beg = thisstyle.font_beg + "\\hspace*{\\fill}" + #thisstyle.font_end = "}" + thisstyle.font_end + thisstyle.font_end = "\\hspace*{\\fill}" + thisstyle.font_end elif align == "right": - thisstyle.font_beg = thisstyle.font_beg + "\\hfill" + thisstyle.font_beg = thisstyle.font_beg + "\\hspace*{\\fill}" # Establish font face and shape if font.get_type_face() == FONT_SANS_SERIF: @@ -155,7 +226,7 @@ class LaTeXDoc(TextDoc): if font.get_bold(): thisstyle.font_beg = thisstyle.font_beg + "\\bfseries" thisstyle.font_end = "\\mdseries" + thisstyle.font_end - if font.get_italic() or font.get_underline(): + if font.get_italic(): thisstyle.font_beg = thisstyle.font_beg + "\\itshape" thisstyle.font_end = "\\upshape" + thisstyle.font_end @@ -189,15 +260,24 @@ class LaTeXDoc(TextDoc): if sflag == 1: thisstyle.font_end = thisstyle.font_end + "\\normalsize" + if font.get_underline(): + thisstyle.font_beg = thisstyle.font_beg + "\\underline{" + thisstyle.font_end = "}" + thisstyle.font_end + thisstyle.font_beg = thisstyle.font_beg + " " thisstyle.font_end = thisstyle.font_end + " " left = style.get_left_margin() right = style.get_right_margin() - first = style.get_first_indent() + left + first = style.get_first_indent() + topborder = style.get_top_border() + bottomborder = style.get_bottom_border() thisstyle.leftIndent = left + thisstyle.rightIndent = right thisstyle.firstLineIndent = first + thisstyle.topBorder = topborder + thisstyle.bottomBorder = bottomborder self.latexstyle[style_name] = thisstyle @@ -208,7 +288,8 @@ class LaTeXDoc(TextDoc): if self.in_list: self.f.write('\\end{enumerate}\n') self.f.write('\n\\end{document}\n') - self.f.close() + if not self.alreadyOpen: + self.f.close() def start_page(self,orientation=None): """Nothing needs to be done to start a page""" @@ -218,25 +299,129 @@ class LaTeXDoc(TextDoc): """Issue a new page command""" self.f.write('\\newpage') + def start_listing(self, style_name): + """Set up parameters for Verbatim environment of fancyvrb package""" + + style = self.style_list[style_name] + font = style.get_font() + size = font.get_size() + # Determine font family + if font.get_type_face() == FONT_MONOSPACE: + family = "courier" + elif font.get_type_face() == FONT_SANS_SERIF: + family = "helvetica" + else: + family = "tt" + # Now determine font size + if size >= 22: + size = "\\Huge" + elif size >= 20: + size = "\\huge" + elif size >= 18: + size = "\\LARGE" + elif size >= 16: + size = "\\Large" + elif size >= 14: + size = "\\large" + elif size < 8: + size = "\\scriptsize" + elif size < 10: + size = "\\footnotesize" + elif size < 12: + size = "\\small" + else: + size = "\\normalsize" + if font.get_bold(): + series = 'b' + else: + series = 'm' + if font.get_italic(): + shape = 'it' + else: + shape = 'n' + leftMargin = style.get_left_margin() + rightMargin = style.get_right_margin() + if style.get_top_border() and style.get_bottom_border(): + if style.get_left_border() and style.get_right_border(): + frame = "single" + else: + frame = "lines" + elif style.get_top_border(): + frame = "topline" + elif style.get_bottom_border(): + frame = "bottomline" + else: + frame = "" + + self.f.write("\\begin{Verbatim}%\n") + self.f.write(" [fontfamily=%s,\n" % family) + self.f.write(" fontsize=%s,\n" % size) + self.f.write(" fontshape=%s,\n" % shape) + self.f.write(" fontseries=%s,\n" % series) + if frame: + self.f.write(" frame=%s,\n" % frame) + self.f.write(" xleftmargin=%.2fcm,\n" % leftMargin) + self.f.write(" xrightmargin=%.2fcm]\n" % rightMargin) + self.last_char_written = '\n' + self.in_listing = 1 + + def end_listing(self): + if self.last_char_written != '\n': + self.f.write('\n') + self.f.write('\\end{Verbatim}\n') + self.in_listing = 0 + def start_paragraph(self,style_name,leader=None): """Paragraphs handling - A Gramps paragraph is any single body of text, from a single word, to several sentences. We assume a linebreak at the end of each paragraph.""" style = self.style_list[style_name] + # Patch to get alignment in table cells working properly + alignment = style.get_alignment() + if alignment == PARA_ALIGN_RIGHT: + self.cell_para_align = 'r' + elif alignment == PARA_ALIGN_CENTER: + self.cell_para_align = 'c' + else: + self.cell_para_align = 'l' + if self.in_cell and not self.cell_header_written: + if self.llist == 1: + cellfmt = "p{\linewidth-3cm}" + elif self.tablewidth: + width = 0.0 + for i in range(self.cell_span): + width = width + self.colwidths[self.cell_cnt + i] + cellfmt = "p{%.2f\\textwidth}" % (width * 0.95) + else: + cellfmt = self.cell_para_align + # Account for vertical rules + if self.lborder == 1: + cellfmt = '|' + cellfmt + if self.rborder == 1: + cellfmt = cellfmt + '|' + if self.tborder != 0 and self.cell_cnt == 0: + self.f.write('\\hline ') + self.f.write ('\\multicolumn{%d}{%s}{' % (self.cell_span,cellfmt)) + self.cell_header_written = 1 + ltxstyle = self.latexstyle[style_name] self.level = style.get_header_level() self.fbeg = ltxstyle.font_beg self.fend = ltxstyle.font_end self.indent = ltxstyle.leftIndent + self.rightmargin = ltxstyle.rightIndent self.FLindent = ltxstyle.firstLineIndent + self.TBorder = ltxstyle.topBorder + self.BBorder = ltxstyle.bottomBorder - - if self.indent != None and not self.in_table: - myspace = '%scm' % str(self.indent) - self.f.write('\\grampsindent{%s}\n' % myspace) - self.fix_indent = 1 + # Adjust the first line indent if needed + if self.FLindent != self.last_indent and not self.in_table: + self.last_indent = self.FLindent + myspace = '%scm' % str(self.FLindent) + self.f.write('\\grampsfirst{%s}\n' % myspace) + self.fix_first = 1 if leader != None and not self.in_list: self.f.write('\\begin{enumerate}\n') @@ -249,11 +434,31 @@ class LaTeXDoc(TextDoc): if leader == None and not self.in_list and not self.in_table: self.f.write('\n') - self.f.write('%s ' % self.fbeg) + # Patch for special handling of cell contents + font_begin = self.fbeg + if self.in_cell: + if not self.tablewidth and string.find(font_begin, '\\hspace*{\\fill}') == 0: + font_begin = font_begin[15:] + # Use parbox command to simulate left and right margins if needed + # Use rule element to make top border if needed + else: + boxcmd = "" + if self.indent or self.rightmargin: + boxcmd = "\\setlength{\\newwidth}{\\textwidth - %.2fcm}" % \ + float(self.indent + self.rightmargin) + boxcmd = boxcmd + "\\hspace*{%.2fcm}\n" % float(self.indent) + boxcmd = boxcmd + "\\parbox{\\newwidth}{" + if self.TBorder: + boxcmd = boxcmd + "\\vspace{0.5ex}\\rule{\\newwidth}{0.5pt}\\newline\n" + elif self.TBorder: + boxcmd = boxcmd + "\\rule{\\textwidth}{0.5pt}\\newline\n" + font_begin = boxcmd + font_begin + self.f.write('%s ' % font_begin) def end_paragraph(self): """End the current paragraph""" - newline = '\ \\newline\n' + #newline = '\ \\newline\n' + newline = '\n' if self.in_list: self.in_list = 0 @@ -263,10 +468,27 @@ class LaTeXDoc(TextDoc): elif self.in_table: newline = ('') - self.f.write('%s%s' % (self.fend,newline)) - if self.fix_indent == 1: - self.fix_indent = 0 - self.f.write('\\grampsindent{0cm}\n') + # Draw bottom border and close parbox command if needed + if not self.in_cell: + if self.BBorder: + if (self.indent or self.rightmargin): + newline = newline + "\\ \\newline\\rule[0.5\\baselineskip]{\\newwidth}{0.5pt}\n" + newline = newline + '}\n' + else: + newline = newline + "\\ \\newline\\rule[0.5\\baselineskip]{\\textwidth}{0.5pt}\n" + elif self.indent or self.rightmargin: + newline = newline + '}\n' + + # Patch for special handling of cell contents + font_end = self.fend + if self.in_cell: + if not self.tablewidth and string.find(font_end, '\\hspace*{\\fill}') == 0: + font_end = font_end[15:] + self.f.write('%s%s' % (font_end,newline)) + if self.fix_first == 1: + self.last_indent = 0 + self.fix_first = 0 + self.f.write('\\grampsfirst{0cm}\n') def start_bold(self): """Bold face""" @@ -276,16 +498,35 @@ class LaTeXDoc(TextDoc): """End bold face""" self.f.write('}') + def start_italic(self): + """Italic face""" + self.f.write('\\textit{') + + def end_italic(self): + """End italic face""" + self.f.write('}') + def start_table(self,name,style_name): """Begin new table""" + self.in_cell = 0 + self.cell_header_written = 0 self.in_table = 1 self.currow = 0 # We need to know a priori how many columns are in this table self.tblstyle = self.table_styles[style_name] self.numcols = self.tblstyle.get_columns() - - tblfmt = '*{%d}{l}' % self.numcols + self.tablewidth = self.tblstyle.get_width() + if self.tablewidth: + self.colwidths = [] + tblfmt = "" + for i in range(self.numcols): + width = self.tblstyle.get_column_width(i) + mult = float(width * self.tablewidth) / 10000.0 + self.colwidths.append(mult) + tblfmt = tblfmt + "p{%.2f\\textwidth}" % (mult * 0.95) + else: + tblfmt = '*{%d}{l}' % self.numcols self.f.write('\n\n\\begin{longtable}[l]{%s}\n' % tblfmt) def end_table(self): @@ -297,6 +538,7 @@ class LaTeXDoc(TextDoc): def start_row(self): """Begin a new row""" # doline/skipfirst are flags for adding hor. rules + self.cell_cnt = -1 self.doline = 0 self.skipfirst = 0 self.curcol = 0 @@ -317,6 +559,10 @@ class LaTeXDoc(TextDoc): """Add an entry to the table. We always place our data inside braces for safety of formatting.""" + self.cell_cnt = self.cell_cnt + 1 + self.in_cell = 1 + self.cell_span = span + self.cell_header_written = 0 self.colspan = span self.curcol = self.curcol + self.colspan @@ -327,16 +573,22 @@ class LaTeXDoc(TextDoc): self.tborder = self.cstyle.get_top_border() self.llist = self.cstyle.get_longlist() - if self.llist == 1: - cellfmt = "p{\linewidth-3cm}" - else: - cellfmt = "l" + # Patched out - functionality moved to start of paragraph + # because we have to wait until then to find out the + # alignment properties of the paragraph which is the + # contents of the cell + + ##if self.llist == 1: + ## cellfmt = "p{\linewidth-3cm}" + ##else: + ## cellfmt = self.cell_para_align + ##self.cellfmt = cellfmt - # Account for vertical rules - if self.lborder == 1: - cellfmt = '|' + cellfmt - if self.rborder == 1: - cellfmt = cellfmt + '|' + ## Account for vertical rules + ##if self.lborder == 1: + ## cellfmt = '|' + cellfmt + ##if self.rborder == 1: + ## cellfmt = cellfmt + '|' # and Horizontal rules if self.bborder == 1: @@ -344,12 +596,14 @@ class LaTeXDoc(TextDoc): elif self.curcol == 1: self.skipfirst = 1 - if self.tborder != 0: - self.f.write('\\hline\n') - self.f.write ('\\multicolumn{%d}{%s}{' % (span,cellfmt)) + ##if self.tborder != 0: + ## self.f.write('\\hline\n') + ##self.f.write ('\\multicolumn{%d}{%s}{' % (span,cellfmt)) def end_cell(self): """Prepares for next cell""" + self.in_cell = 0 + self.cell_header_written = 0 self.f.write('} ') if self.curcol < self.numcols: self.f.write('& ') @@ -364,29 +618,45 @@ class LaTeXDoc(TextDoc): # x and y will be maximum width OR height in units of cm mysize = 'width=%dcm,height=%dcm,keepaspectratio' % (x,y) if pos == "right": - self.f.write('\\hfill\\includegraphics[%s]{%s}\n' % (mysize,picf)) + self.f.write('\\hspace*{\\fill}\\includegraphics[%s]{%s}\n' % (mysize,picf)) elif pos == "left": - self.f.write('\\includegraphics[%s]{%s}\\hfill\n' % (mysize,picf)) + self.f.write('\\includegraphics[%s]{%s}\\hspace*{\\fill}\n' % (mysize,picf)) else: - self.f.write('\\centerline{\\includegraphics[%s]{%s}}\n' % (mysize,picf)) + self.f.write('\\hspace*{\\fill}\\includegraphics[%s]{%s}\hspace*{\\fill}\n' % (mysize,picf)) def write_text(self,text): """Write the text to the file""" - if text == '\n': - text = '\\newline\n' - text = string.replace(text,'#','\#') + if not self.in_listing: + if text == '\n': + text = '\\newline\n' + text = string.replace(text,'#','\#') self.f.write(text) + if text: + self.last_char_written = text[-1] + def line_break(self): + self.f.write('\\newline\n') + + def page_break(self): + self.f.write('\\newpage\n') + + def show_link(self, text, href): + self.write_text("%s (" % text) + self.start_italic() + self.write_text(href) + self.end_italic() + self.write_text(") ") #------------------------------------------------------------------------ # -# Register the document generator with the system +# Register the document generator with the system if in Gramps # #------------------------------------------------------------------------ -Plugins.register_text_doc( - name=_("LaTeX"), - classref=LaTeXDoc, - table=1, - paper=1, - style=0 - ) +if withGramps: + Plugins.register_text_doc( + name=_("LaTeX"), + classref=LaTeXDoc, + table=1, + paper=1, + style=1 + ) diff --git a/gramps/src/docgen/NroffDoc.py b/gramps/src/docgen/NroffDoc.py new file mode 100644 index 000000000..a1dcbbcae --- /dev/null +++ b/gramps/src/docgen/NroffDoc.py @@ -0,0 +1,620 @@ +# +# Copyright (C) 2002 Gary Shao +# +# 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 +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +"""nroff/groff document generator""" + +#------------------------------------------------------------------------ +# +# gramps modules +# +#------------------------------------------------------------------------ +from TextDoc import * +try: + import Plugins + import intl + _ = intl.gettext +except: + withGramps = 0 +else: + withGramps = 1 + +#------------------------------------------------------------------------ +# +# Paragraph Handling +# +#------------------------------------------------------------------------ +class RoffParastyle: + def __init__(self, style=None): + if style: + self.fontSize = style.fontSize + self.fontFamily = style.fontFamily + self.leftIndent = style.left_indent + self.rightIndent = style.right_indent + self.firstLineIndent = style.firstLineIndent + self.topBorder = style.topBorder + self.bottomBorder = style.bottomBorder + self.leftBorder = style.leftBorder + self.rightBorder = style.rightBorder + self.align = style.align + else: + self.fontSize = 12 + self.fontFamily = "R" + self.leftIndent = 0.0 + self.rightIndent = 0.0 + self.firstLineIndent = 0.0 + self.topBorder = 0 + self.bottomBorder = 0 + self.leftBorder = 0 + self.rightBorder = 0 + self.align = "left" + +# Standard paper sizes, width x height (cm) +PaperSizes = {"Letter" : (21.6,27.9), + "Legal" : (21.6,35.6), + "Executive" : (19.0,25.4), + "Ledger" : (27.9,43.2), + "A" : (21.6,27.9), + "B" : (27.9,43.2), + "C" : (43.2,55.9), + "D" : (55.9,86.4), + "E" : (86.4,111.8), + "A1" : (59.4,84.1), + "A2" : (42.0,59.4), + "A3" : (29.7,42.0), + "A4" : (21.0,29.7), + "A5" : (14.8,21.0), + "A6" : (10.5,14.8), + "A7" : (7.4,10.5), + "A8" : (5.2,7.4), + "B4" : (25.0,35.3), + "B5" : (17.6,25.0), + "B6" : (12.5,17.6), + } +#------------------------------------------------------------------------ +# +# NroffDoc +# +#------------------------------------------------------------------------ +class NroffDoc(TextDoc): + """Nroff document interface class. Derived from TextDoc""" + + def open(self,filename): + """Opens the specified file, making sure that it has the + extension of .rof""" + if type(filename) == type(""): + if filename[-4:] != ".rof": + self.filename = filename + ".rof" + else: + self.filename = filename + self.f = open(self.filename,"w") + self.alreadyOpen = 0 + elif hasattr(filename, "write"): + self.f = filename + self.alreadyOpen = 1 + + if self.orientation == PAPER_LANDSCAPE: + options = options + ",landscape" + + # If the user picks something not listed above, we'll just accept + # the default of American letter size. + if self.paper.name == "Terminal": + self.paperWidth = 80 + self.paperHeight = 24 + elif self.paper.name == "Text": + self.paperWidth, self.paperHeight = PaperSizes["Letter"] + elif self.paper.name in PaperSizes.keys(): + self.paperWidth, self.paperHeight = PaperSizes[self.paper.name] + else: + self.paperWidth, self.paperHeight = PaperSizes["Letter"] + + # Write any generator-supplied macros + # Macros and traps to set 1in. top and bottom page margins + self.f.write('.de hd\n') + self.f.write('\'sp 0.5i\n') + self.f.write('..\n') + self.f.write('\'bp\n') + self.f.write('..\n') + self.f.write('.wh 0 hd\n') + self.f.write('.wh -1i fo\n') + # Macros for drawing parts of paragraph border + # Top side + self.f.write('.de tb\n') + self.f.write('.nr b \\\\n(.lu-\\\\n(.iu\n') + self.f.write('.sp -1\n') + self.f.write('.nf\n') + self.f.write('\\h\'-.5n\'\\v\'|\\\\nau-1\'\\l\'\\\\nbu+1n\\(em\'\\v\'-|\\\\nau+1\'\\h\'|0u-.5n\'\n') + self.f.write('.fi\n') + self.f.write('..\n') + # Bottom side + self.f.write('.de bb\n') + self.f.write('.nr b \\\\n(.lu-\\\\n(.iu\n') + self.f.write('.nf\n') + self.f.write('\\h\'-.5n\'\\l\'\\\\nbu+1n\\(em\'\\h\'|0u-.5n\'\n') + self.f.write('.fi\n') + self.f.write('..\n') + # Macro for beginning a new paragraph + self.f.write('.de pg\n') + self.f.write('.br\n') + self.f.write('.ft \\\\$1\n') + self.f.write('.ps \\\\$2\n') + self.f.write('.vs \\\\$3\n') + self.f.write('.in \\\\$4\n') + self.f.write('.ti \\\\$5\n') + self.f.write('.ll \\\\$6\n') + self.f.write('.sp 0.9\n') + self.f.write('.ne 1+\\n(.Vu\n') + self.f.write('.ad \\\\$7\n') + self.f.write('..\n') + + # Set up an initial choice of font + self.f.write('.ft R\n') + self.f.write('.ps 12\n') + + # Set the page parameters + # Page length + if self.paper.name == "Terminal": + self.f.write('.pl %dv\n' % self.paperHeight) + else: + self.f.write('.pl %.2fc\n' % self.paperHeight) + # Start with a 1in. left and right margin unless targeting a terminal + self.origLineLength = self.paperWidth - 5.08 + if self.paper.name == "Terminal": + self.origLineLength = self.paperWidth + self.f.write('.po 0\n') + self.f.write('.ll %dm\n' % self.origLineLength) + else: + self.page_offset = 2.54 + self.right_offset = 2.54 + self.origLineLength = self.paperWidth - self.page_offset - self.right_offset + self.f.write('.po %.2fc\n' % self.page_offset) + self.f.write('.ll %.2fc\n' % (self.origLineLength)) + + self.in_list = 0 + self.in_paragraph = 0 + self.in_table = 0 + self.in_cell = 0 + self.cell_header_written = 0 + self.last_indent = 0 + self.fix_first = 0 + self.tabchar = '~' # separator for table cell data + + #Establish some local styles for the report + self.roffstyle = {} + + for style_name in self.style_list.keys(): + style = self.style_list[style_name] + font = style.get_font() + size = font.get_size() + + thisstyle = RoffParastyle() + + # Is there special alignment? (default is left) + align = style.get_alignment_text() + if align == "center": + thisstyle.align = "center" + elif align == "right": + thisstyle.align = "right" + else: + thisstyle.align = "left" + + # Establish font face and shape + if self.paper.name == "Terminal" or self.paper.name == "Text": + if font.get_bold(): + if font.get_italic(): + thisstyle.fontFamily = 'BI' + else: + thisstyle.fontFamily = 'B' + else: + if font.get_italic(): + thisstyle.fontFamily = 'I' + else: + thisstyle.fontFamily = 'R' + elif font.get_type_face() == FONT_MONOSPACE: + if font.get_bold(): + if font.get_italic(): + thisstyle.fontFamily = 'CBI' + else: + thisstyle.fontFamily = 'CB' + else: + if font.get_italic(): + thisstyle.fontFamily = 'CI' + else: + thisstyle.fontFamily = 'CR' + elif font.get_type_face() == FONT_SANS_SERIF: + if font.get_bold(): + if font.get_italic(): + thisstyle.fontFamily = 'HBI' + else: + thisstyle.fontFamily = 'HB' + else: + if font.get_italic(): + thisstyle.fontFamily = 'HI' + else: + thisstyle.fontFamily = 'HR' + else: + if font.get_bold(): + if font.get_italic(): + thisstyle.fontFamily = 'TBI' + else: + thisstyle.fontFamily = 'TB' + else: + if font.get_italic(): + thisstyle.fontFamily = 'TI' + else: + thisstyle.fontFamily = 'TR' + + # Now determine font size + thisstyle.fontSize = size + + # And add the other paragraph attributes + thisstyle.leftIndent = style.get_left_margin() + thisstyle.rightIndent = style.get_right_margin() + thisstyle.firstLineIndent = style.get_first_indent() + thisstyle.topBorder = style.get_top_border() + thisstyle.bottomBorder = style.get_bottom_border() + thisstyle.leftBorder = style.get_left_border() + thisstyle.rightBorder = style.get_right_border() + + self.roffstyle[style_name] = thisstyle + + def close(self): + """Close the document if needed""" + if not self.alreadyOpen: + self.f.close() + + def start_page(self,orientation=None): + """Nothing needs to be done to start a page""" + pass + + def end_page(self): + """Issue a new page command""" + self.f.write('.bp\n') + + def start_listing(self,style_name): + """Listing handling""" + + alignment = 'l' + self.current_style = style_name + style = self.roffstyle[style_name] + linelength = self.paperWidth - self.page_offset - self.right_offset + linelength = linelength - style.rightIndent + self.lineLength = linelength + self.f.write('.pg %s %d %d %.2fc %.2fc %.2fc %s\n' % \ + (style.fontFamily, style.fontSize, style.fontSize+2, + style.leftIndent, style.leftIndent, + linelength, alignment)) + if style.topBorder: + self.f.write('.sp 1\n') + self.f.write('.nf\n') + self.f.write('.na\n') + self.f.write('.mk a\n') + self.last_char_written = '\n' + + def end_listing(self): + if self.last_char_written != '\n': + self.f.write('\n') + style = self.roffstyle[self.current_style] + if style.topBorder: + self.f.write('.tb\n') + if style.bottomBorder: + self.f.write('.bb\n') + + def start_paragraph(self,style_name,leader=None): + """Paragraph handling - A Gramps paragraph is any + single body of text, from a single word, to several sentences.""" + + self.current_style = style_name + style = self.roffstyle[style_name] + # Calculate table cell alignment and spacing + if style.align == "right": + alignment = 'r' + elif style.align == "center": + alignment = 'c' + else: + alignment = 'l' + self.cell_para_align = alignment + if self.in_cell and not self.cell_header_written: + if self.tablewidth: + width = self.colwidths[self.cell_cnt] + cellfmt = "%sw(%.2fc-1.5m)" % (self.cell_para_align, width) + else: + cellfmt = self.cell_para_align + cellfmt = cellfmt + "p%d" % style.fontSize + cellfmt = cellfmt + "f%s " % style.fontFamily + if self.cell_span > 1: + for i in range(1, self.cell_span): + cellfmt = cellfmt + " s" + # Account for vertical rules + rowformat = self.row_formatstr + end = len(rowformat) - 1 + if end > -1: + lastformatchar = rowformat[end] + else: + lastformatchar = "" + if self.lborder == 1 and lastformatchar != '|': + cellfmt = '| ' + cellfmt + if self.rborder == 1: + cellfmt = cellfmt + ' |' + self.row_formatstr = self.row_formatstr + ' ' + cellfmt + self.cell_header_written = 1 + + if not self.in_cell: + linelength = self.paperWidth - self.page_offset - self.right_offset + linelength = linelength - style.rightIndent + self.lineLength = linelength + self.f.write('.pg %s %d %d %.2fc %.2fc %.2fc %s\n' % \ + (style.fontFamily, style.fontSize, style.fontSize+2, + style.leftIndent, style.leftIndent+style.firstLineIndent, + linelength, alignment)) + if style.topBorder: + self.f.write('.sp 1\n') + self.f.write('.fi\n') + self.f.write('.mk a\n') + self.last_char_written = '\n' + + self.current_fontfamily = style.fontFamily + self.in_paragraph = 1 + + def end_paragraph(self): + if not self.in_cell and self.last_char_written != '\n': + self.f.write('\n') + if not self.in_cell: + style = self.roffstyle[self.current_style] + if style.topBorder: + self.f.write('.tb\n') + if style.bottomBorder: + self.f.write('.bb\n') + self.in_paragraph = 0 + + def start_italic(self): + """Italic face inside a paragraph""" + if self.in_paragraph: + font = self.current_fontfamily + if 'I' not in font: + if font=='R': + newfont = 'I' + elif font =='B': + newfont = 'BI' + elif font[1]=='R': + newfont = font[0] + 'I' + else: + newfont = font[0] + 'BI' + if self.last_char_written != '\n': + self.f.write('\n.ft %s\n' % newfont) + else: + self.f.write('.ft %s\n' % newfont) + self.current_fontfamily = newfont + + def end_italic(self): + """End italic face inside a paragraph""" + if self.in_paragraph: + font = self.current_fontfamily + if 'I' in font: + if font=='I': + newfont = 'R' + elif font=='BI': + newfont = 'B' + elif len(font)==2 and font[1]=='I': + newfont = font[0] + 'R' + else: + newfont = font[0] + 'B' + if self.last_char_written != '\n': + self.f.write('\n.ft %s\n' % newfont) + else: + self.f.write('.ft %s\n' % newfont) + self.current_fontfamily = newfont + + def start_bold(self): + """Bold face inside a paragraph""" + if self.in_paragraph: + font = self.current_fontfamily + if 'B' not in font: + if font=='R': + newfont = 'B' + elif font =='I': + newfont = 'BI' + elif font[1]=='R': + newfont = font[0] + 'B' + else: + newfont = font[0] + 'BI' + if self.last_char_written != '\n': + self.f.write('\n.ft %s\n' % newfont) + else: + self.f.write('.ft %s\n' % newfont) + self.current_fontfamily = newfont + + def end_bold(self): + """End bold face inside a paragraph""" + if self.in_paragraph: + font = self.current_fontfamily + if 'B' in font: + if font=='B': + newfont = 'R' + elif font=='BI': + newfont = 'I' + elif len(font)==2 and font[1]=='B': + newfont = font[0] + 'R' + else: + newfont = font[0] + 'I' + if self.last_char_written != '\n': + self.f.write('\n.ft %s\n' % newfont) + else: + self.f.write('.ft %s\n' % newfont) + self.current_fontfamily = newfont + + def start_table(self,name,style_name): + """Begin new table""" + self.in_cell = 0 + self.cell_header_written = 0 + self.in_table = 1 + self.first_row = 1 + self.last_row_had_bottomborder = 0 + + # Reset the left indent and line length to original values + self.f.write('.in 0c\n') + self.f.write('.ll %.2fc\n' % self.origLineLength) + + # Make the column separator character be the tilde when specifying + # data in each table cell + optionstr = "tab(%s)" % self.tabchar + + # We need to know a priori how many columns are in this table + self.tblstyle = self.table_styles[style_name] + self.numcols = self.tblstyle.get_columns() + self.tablewidth = self.tblstyle.get_width() + if self.tablewidth: + self.colwidths = [] + for i in range(self.numcols): + width = self.tblstyle.get_column_width(i) + mult = self.origLineLength * float(width * self.tablewidth) / 10000.0 + self.colwidths.append(mult) + optionstr = optionstr + ";" + else: + optionstr = optionstr + ",center;" + self.f.write('.TS\n') + self.f.write('%s\n' % optionstr) + + def end_table(self): + """Close the table specification""" + self.in_table = 0 + self.f.write('.TE\n') + + def start_row(self): + """Begin a new row""" + self.cell_cnt = -1 + self.row_line_above = 1 + self.row_line_below = 1 + self.row_formatstr = "" + self.row_datastrs = [] + + def end_row(self): + """End the row (new line)""" + + # Write out the format string for the row if it is the first row, + # or make a continuation row specification if the format has changed + # from the last one + self.row_formatstr = self.row_formatstr + ".\n" + if self.first_row: + self.f.write(self.row_formatstr) + self.last_row_formatstr = self.row_formatstr + else: + if self.row_formatstr != self.last_row_formatstr: + self.f.write('.T&\n') + self.f.write(self.row_formatstr) + # Write a horizontal line if the row calls for a top border + # and any previous row did not already print a bottom border line + if self.row_line_above and not self.last_row_had_bottomborder: + self.f.write('_\n') + + # Write out the row data + datastr = self.row_datastrs.pop(0) + self.f.write(datastr) + while len(self.row_datastrs) > 0: + self.f.write("%s%s" % (self.tabchar, self.row_datastrs.pop(0))) + self.f.write('\n') + + # Write a horizontal line if the row calls for a bottom border + if self.row_line_below: + self.f.write('_\n') + self.last_row_had_bottomborder = 1 + else: + self.last_row_had_bottomborder = 0 + + if self.first_row: + self.first_row = 0 + + def start_cell(self,style_name,span=1): + """Add an entry to the table.""" + + self.cell_cnt = self.cell_cnt + 1 + self.in_cell = 1 + self.cell_span = span + self.cell_header_written = 0 + self.cell_string = "" + + self.cstyle = self.cell_styles[style_name] + self.lborder = self.cstyle.get_left_border() + self.rborder = self.cstyle.get_right_border() + self.bborder = self.cstyle.get_bottom_border() + if not self.bborder: + self.row_line_below = 0 + self.tborder = self.cstyle.get_top_border() + if not self.tborder: + self.row_line_above = 0 + + # Wait until paragraph start to get paragraph attributes so + # that we can apply them to the cell format + + def end_cell(self): + """Adds the cell data string to the row data""" + self.in_cell = 0 + self.cell_header_written = 0 + if self.tablewidth: + width = self.colwidths[self.cell_cnt] + for i in range(1, self.cell_span): + width = width + self.colwidths[self.cell_cnt + i] + if (0.254 * len(self.cell_string)) > width: + self.cell_string = 'T{\n' + self.cell_string + '\nT}' + self.row_datastrs.append(self.cell_string) + + def add_photo(self,name,pos,x,y): + pass + + def write_text(self,text): + """Write the text to the file""" + if self.in_cell: + self.cell_string = self.cell_string + text + else: + self.f.write(text) + if text: + self.last_char_written = text[-1] + + def line_break(self): + if self.in_paragraph and self.last_char_written != '\n': + self.f.write('\n.br\n') + else: + self.f.write('.br\n') + self.last_char_written = '\n' + + def page_break(self): + if self.in_paragraph and self.last_char_written != '\n': + self.f.write('\n.bp\n') + else: + self.f.write('.bp\n') + self.last_char_written = '\n' + + def show_link(self, text, href): + self.write_text("%s (" % text) + self.start_italic() + self.write_text(href) + self.end_italic() + self.write_text(") ") + +#------------------------------------------------------------------------ +# +# Register the document generator with the system if in Gramps +# +#------------------------------------------------------------------------ +if withGramps: + Plugins.register_text_doc( + name=_("nroff/groff"), + classref=NroffDoc, + table=1, + paper=1, + style=1 + ) diff --git a/gramps/src/docgen/PdfDoc.py b/gramps/src/docgen/PdfDoc.py index 5329f6d90..4856846dc 100644 --- a/gramps/src/docgen/PdfDoc.py +++ b/gramps/src/docgen/PdfDoc.py @@ -3,6 +3,45 @@ # # Copyright (C) 2000 Donald N. Allingham # +# Modified August 2002 by Gary Shao +# +# Removed Gramps dependencies. +# +# Finagled the import name of the TableStyle class from reportlab so +# that it doesn't conflict with TableStyle class name from TextDoc +# module. Reportlab version is now referenced as ReportlabTableStyle. +# +# Added two new derived classes (BoxedParagraphStyle, BoxedParagraph) +# to replace standard reportlab classes to allow for drawing a border +# around a Paragraph flowable. +# +# Added new derived class SpanTable to replace standard reportlab class +# Table. Allows for proper placement of text within a table cell which +# spans several columns. +# +# Modified open() and close() methods to allow the filename parameter +# passed to open() to be either a string containing a file name, or +# a Python file object. This allows the document generator to be more +# easily used with its output directed to stdout, as may be called for +# in a CGI script. +# +# Modified September 2002 by Gary Shao +# +# Added new derived class BoxedPreformatted to replace standard +# reportlab class Preformatted to allow for drawing a border around +# the flowable. +# +# Added new methods start_listing() and end_listing() for specifying +# a block of text that should be rendered without any filling or +# justification. +# +# Added new methods start_italic() and end_italic() to enable +# italicizing parts of text within a paragraph +# +# Added method show_link() to display in text the value of a link. +# This method really only has an active role in the HTML generator, +# but is provided here for interface consistency. +# # 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 # the Free Software Foundation; either version 2 of the License, or @@ -24,10 +63,20 @@ # #------------------------------------------------------------------------ from TextDoc import * -import Plugins +OldTableStyle = TableStyle #Make an alias for original TableStyle + #because reportlab.platypus.tables also + #has a TableStyle class whose name will + #cover up the one from the TextDoc module import ImgManip -import intl -_ = intl.gettext + +try: + import Plugins + import intl + _ = intl.gettext +except: + withGramps = 0 +else: + withGramps = 1 #------------------------------------------------------------------------ # @@ -38,12 +87,165 @@ _ = intl.gettext try: import reportlab.platypus.tables from reportlab.platypus import * + ReportlabTableStyle = reportlab.platypus.tables.TableStyle + TableStyle = OldTableStyle #Let TableStyle refer to the original class from reportlab.lib.units import cm - from reportlab.lib.colors import Color + from reportlab.lib.colors import Color,black,white from reportlab.lib.enums import TA_LEFT, TA_RIGHT, TA_CENTER, TA_JUSTIFY import reportlab.lib.styles except: - raise Plugins.MissingLibraries, _("The ReportLab modules are not installed") + if withGramps: + raise Plugins.MissingLibraries, _("The ReportLab modules are not installed") + else: + print "The ReportLab modules are not installed" + raise + +#------------------------------------------------------------------------ +# +# BoxedParagraphStyle +# +# Class derived from ParagraphStyle which adds four attributes +# (topBorder, bottomBorder, leftBorder, rightBorder). Allows +# for drawing border sides around a standard paragraph when using +# a BoxedParagraph flowable (see below). +# +#------------------------------------------------------------------------ +class BoxedParagraphStyle(reportlab.lib.styles.ParagraphStyle): + defaults = { + 'fontName':'Times-Roman', + 'fontSize':10, + 'leading':12, + 'leftIndent':0, + 'rightIndent':0, + 'firstLineIndent':0, + 'alignment':TA_LEFT, + 'spaceBefore':0, + 'spaceAfter':0, + 'bulletFontName':'Times-Roman', + 'bulletFontSize':10, + 'bulletIndent':0, + 'textColor': black, + 'backColor':None, + 'topBorder':0, + 'bottomBorder':0, + 'leftBorder':0, + 'rightBorder':0 + } + +#------------------------------------------------------------------------ +# +# BoxedParagraph +# +# Class derived from Paragraph which overrides the original drawing +# method with one which also allows for drawing the sides of a border +# around a Paragraph flowable. +# +#------------------------------------------------------------------------ +class BoxedParagraph(Paragraph): + def draw(self): + self.drawPara2(self.debug) + + def drawPara2(self, debug=0): + #call the original drawing method + self.drawPara(debug) + + #stash some key facts locally for speed + canvas = self.canv + style = self.style + + #if borders are called for, draw them + extra = 0.5 * style.leading + if style.bottomBorder: + canvas.line(style.leftIndent, 0.0-extra, self.width-style.rightIndent, 0.0-extra) + if style.topBorder: + canvas.line(style.leftIndent, self.height, self.width-style.rightIndent, self.height) + if style.leftBorder: + canvas.line(style.leftIndent, 0.0-extra, style.leftIndent, self.height) + if style.rightBorder: + canvas.line(self.width-style.rightIndent, 0.0-extra, self.width-style.rightIndent, self.height) + +#------------------------------------------------------------------------ +# +# BoxedPreformatted +# +# Class derived from Preformatted which overrides the original drawing +# method with one which also allows for drawing the sides of a border +# around a Preformatted flowable. +# +#------------------------------------------------------------------------ +class BoxedPreformatted(Preformatted): + def draw(self): + cur_x = self.style.leftIndent + cur_y = self.height - self.style.fontSize + self.canv.addLiteral('%PreformattedPara') + if self.style.textColor: + self.canv.setFillColor(self.style.textColor) + tx = self.canv.beginText(cur_x, cur_y) + #set up the font etc. + tx.setFont( self.style.fontName, + self.style.fontSize, + self.style.leading) + + for text in self.lines: + tx.textLine(text) + self.canv.drawText(tx) + #if borders are called for, draw them + style = self.style + canvas = self.canv + extra = 0.5 * style.leading + if style.bottomBorder: + canvas.line(style.leftIndent, 0.0-extra, self.width-style.rightIndent, 0.0-extra) + if style.topBorder: + canvas.line(style.leftIndent, self.height, self.width-style.rightIndent, self.height) + if style.leftBorder: + canvas.line(style.leftIndent, 0.0-extra, style.leftIndent, self.height) + if style.rightBorder: + canvas.line(self.width-style.rightIndent, 0.0-extra, self.width-style.rightIndent, self.height) + +#------------------------------------------------------------------------ +# +# SpanTable +# +# Class derived from Table which overrides the original __init__ method +# to allow one additional parameter (an array of integer values giving +# the span of each cell in a table), and overrides the draw method to +# adjust cell output when the cell spans several columns. +# +#------------------------------------------------------------------------ +class SpanTable(reportlab.platypus.tables.Table): + def __init__(self, data, spandata, colWidths=None, rowHeights=None, + style=None, repeatRows=0, repeatCols=0, splitByRow=1, + emptyTableAction=None): + reportlab.platypus.tables.Table.__init__(self, data, colWidths, + rowHeights, style, repeatRows, repeatCols, splitByRow, + emptyTableAction) + self.span_data = spandata + + def draw(self): + self._curweight = self._curcolor = self._curcellstyle = None + self._drawBkgrnd() + self._drawLines() + in_span = 0 + span_cnt = 0 + for row, rowstyle, rowpos, rowheight, rowspan in map(None, self._cellvalues, self._cellStyles, self._rowpositions[1:], self._rowHeights, self.span_data): + for cellval, cellstyle, colpos, colwidth, cellspan in map(None, row, rowstyle, self._colpositions[:-1], self._colWidths, rowspan): + if in_span: + span_cnt = span_cnt - 1 + span_width = span_width + colwidth + if span_cnt: + continue + else: + cellval, cellstyle, colpos, rowpos, rowheight = save_data + self._drawCell(cellval, cellstyle, (colpos, rowpos), (span_width, rowheight)) + in_span = 0 + continue + if cellspan > 1: + in_span = 1 + span_cnt = cellspan - 1 + span_width = colwidth + save_data = (cellval, cellstyle, colpos, rowpos, rowheight) + continue + self._drawCell(cellval, cellstyle, (colpos, rowpos), (colwidth, rowheight)) #------------------------------------------------------------------------ # @@ -67,10 +269,13 @@ class GrampsDocTemplate(BaseDocTemplate): class PdfDoc(TextDoc): def open(self,filename): - if filename[-4:] != ".pdf": - self.filename = "%s.pdf" % filename - else: - self.filename = filename + if type(filename) == type(""): + if filename[-4:] != ".pdf": + self.filename = "%s.pdf" % filename + else: + self.filename = filename + elif hasattr(filename, "write"): + self.filename = filename self.pagesize = (self.width*cm,self.height*cm) @@ -95,11 +300,23 @@ class PdfDoc(TextDoc): style = self.style_list[style_name] font = style.get_font() - pdf_style = reportlab.lib.styles.ParagraphStyle(name=style_name) + #pdf_style = reportlab.lib.styles.ParagraphStyle(name=style_name) + pdf_style = BoxedParagraphStyle(name=style_name) pdf_style.fontSize = font.get_size() pdf_style.bulletFontSize = font.get_size() - if font.get_type_face() == FONT_SERIF: + if font.get_type_face() == FONT_MONOSPACE: + if font.get_bold(): + if font.get_italic(): + pdf_style.fontName = "Courier-BoldOblique" + else: + pdf_style.fontName = "Courier-Bold" + else: + if font.get_italic(): + pdf_style.fontName = "Courier-Oblique" + else: + pdf_style.fontName = "Courier" + elif font.get_type_face() == FONT_SERIF: if font.get_bold(): if font.get_italic(): pdf_style.fontName = "Times-BoldItalic" @@ -126,7 +343,13 @@ class PdfDoc(TextDoc): right = style.get_right_margin()*cm left = style.get_left_margin()*cm - first = left + style.get_first_indent()*cm + #first = left + style.get_first_indent()*cm + first = style.get_first_indent()*cm + + pdf_style.topBorder = style.get_top_border() + pdf_style.bottomBorder = style.get_bottom_border() + pdf_style.leftBorder = style.get_left_border() + pdf_style.rightBorder = style.get_right_border() pdf_style.rightIndent = right pdf_style.leftIndent = left @@ -149,6 +372,7 @@ class PdfDoc(TextDoc): self.story = [] self.in_table = 0 + self.in_listing = 0 def close(self): self.doc.build(self.story) @@ -156,6 +380,28 @@ class PdfDoc(TextDoc): def end_page(self): self.story.append(PageBreak()) + def start_listing(self,style_name): + self.text = '' + self.current_para = self.pdfstyles[style_name] + self.in_listing = 1 + + def end_listing(self): + text = self.text + index = string.find(text, '\n') + if index > -1: + if index > 0 and text[index-1] == '\r': + eol = '\r\n' + else: + eol = '\n' + else: + eol = '' + text = ' ' + text + if eol: + text = string.replace(text,eol,eol+' '); + self.story.append(BoxedPreformatted(text,self.current_para)) + self.story.append(Spacer(1,0.5*cm)) + self.in_listing = 0 + def start_paragraph(self,style_name,leader=None): self.current_para = self.pdfstyles[style_name] self.my_para = self.style_list[style_name] @@ -167,7 +413,7 @@ class PdfDoc(TextDoc): def end_paragraph(self): if self.in_table == 0 and self.image == 0: - self.story.append(Paragraph(self.text,self.current_para)) + self.story.append(BoxedParagraph(self.text,self.current_para)) self.story.append(Spacer(1,0.5*cm)) else: self.image = 0 @@ -178,6 +424,12 @@ class PdfDoc(TextDoc): def end_bold(self): self.text = self.text + '' + def start_italic(self): + self.text = self.text + '' + + def end_italic(self): + self.text = self.text + '' + def start_table(self,name,style_name): self.in_table = 1 self.cur_table = self.table_styles[style_name] @@ -185,6 +437,7 @@ class PdfDoc(TextDoc): self.col = 0 self.cur_row = [] self.table_data = [] + self.span_data = [] self.tblstyle = [] self.cur_table_cols = [] @@ -194,23 +447,29 @@ class PdfDoc(TextDoc): self.cur_table_cols.append(int(width * percent * cm)) def end_table(self): - ts = reportlab.platypus.tables.TableStyle(self.tblstyle) - tbl = reportlab.platypus.tables.Table(data=self.table_data, - colWidths=self.cur_table_cols, - style=ts) + ts = ReportlabTableStyle(self.tblstyle) + #tbl = reportlab.platypus.tables.Table(data=self.table_data, + # colWidths=self.cur_table_cols, + # style=ts) + tbl = SpanTable(data=self.table_data, spandata=self.span_data, + colWidths=self.cur_table_cols, style=ts) self.story.append(tbl) + self.story.append(Spacer(1,0.5*cm)) self.in_table = 0 def start_row(self): self.row = self.row + 1 self.col = 0 self.cur_row = [] + self.cur_span_row = [] def end_row(self): self.table_data.append(self.cur_row) + self.span_data.append(self.cur_span_row) def start_cell(self,style_name,span=1): self.span = span + self.cur_span_row.append(span) self.my_table_style = self.cell_styles[style_name] pass @@ -218,7 +477,8 @@ class PdfDoc(TextDoc): if self.span == 1: self.cur_row.append(Paragraph(self.text,self.current_para)) else: - self.cur_row.append(self.text) + self.cur_row.append(Paragraph(self.text,self.current_para)) + #self.cur_row.append(self.text) for val in range(1,self.span): self.cur_row.append("") @@ -278,14 +538,22 @@ class PdfDoc(TextDoc): self.image = 1 def write_text(self,text): - text = string.replace(text,'&','&'); # Must be first - text = string.replace(text,'<','<'); - text = string.replace(text,'>','>'); + if not self.in_listing: + text = string.replace(text,'&','&'); # Must be first + text = string.replace(text,'<','<'); + text = string.replace(text,'>','>'); self.text = self.text + text + def show_link(self, text, href): + self.write_text("%s (" % text) + self.start_italic() + self.write_text(href) + self.end_italic() + self.write_text(") ") + #------------------------------------------------------------------------ # -# Convert an RGB color tulple to a Color instance +# Convert an RGB color tuple to a Color instance # #------------------------------------------------------------------------ def make_color(color): @@ -298,10 +566,11 @@ def make_color(color): # #------------------------------------------------------------------------ -Plugins.register_text_doc( - name=_("PDF"), - classref=PdfDoc, - table=1, - paper=1, - style=1 - ) +if withGramps: + Plugins.register_text_doc( + name=_("PDF"), + classref=PdfDoc, + table=1, + paper=1, + style=1 + ) diff --git a/gramps/src/docgen/RTFDoc.py b/gramps/src/docgen/RTFDoc.py index dc598c619..65c9f1e0c 100644 --- a/gramps/src/docgen/RTFDoc.py +++ b/gramps/src/docgen/RTFDoc.py @@ -3,6 +3,52 @@ # # Copyright (C) 2000 Donald N. Allingham # +# Modified August 2002 by Gary Shao +# +# Removed Gramps dependencies. +# +# Made a more explicit distinction of whether paragraph properties +# were being emitted in a table or not. Changing the location of +# \qc and \qr commands in cell text enabled text alignment in table +# cells to work properly. +# +# Improved the appearance of output by adding some default spacing +# before and after paragraphs using \sa and \sb commands. This lets +# the output more closely mimic that of the other document generators +# given the same document parameters. +# +# Improved the appearance of tables by adding some default cell +# padding using the \trgaph command. This causes the output to +# more closely resemble that of the other document generators. +# +# Removed unnecessary \par command at the end of embedded image. +# +# Removed self-test function in favor of a general testing program +# that can be run for all supported document generators. Simplifies +# testing when the test program only has to be changed in one location +# instead of in each document generator. +# +# Modified open() and close() methods to allow the filename parameter +# passed to open() to be either a string containing a file name, or +# a Python file object. This allows the document generator to be more +# easily used with its output directed to stdout, as may be called for +# in a CGI script. +# +# Modified September 2002 by Gary Shao +# +# Added start_listing() and end_listing() methods to allow showing +# text blocks without filling or justifying. +# +# Added line_break() method to allow forcing a line break in a text +# block. +# +# Added new methods start_italic() and end_italic() to enable +# italicizing parts of text within a paragraph +# +# Added method show_link() to display in text the value of a link. +# This method really only has an active role in the HTML generator, +# but is provided here for interface consistency. +# # 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 # the Free Software Foundation; either version 2 of the License, or @@ -24,11 +70,16 @@ # #------------------------------------------------------------------------ from TextDoc import * -import Plugins import ImgManip -import intl -_ = intl.gettext +try: + import Plugins + import intl + _ = intl.gettext +except: + withGramps = 0 +else: + withGramps = 1 #------------------------------------------------------------------------ # @@ -60,16 +111,22 @@ class RTFDoc(TextDoc): # #-------------------------------------------------------------------- def open(self,filename): - if filename[-4:] != ".rtf": - self.filename = filename + ".rtf" - else: - self.filename = filename + if type(filename) == type(""): + if filename[-4:] != ".rtf": + self.filename = filename + ".rtf" + else: + self.filename = filename - self.f = open(self.filename,"w") + self.f = open(self.filename,"w") + self.alreadyOpen = 0 + elif hasattr(filename, "write"): + self.f = filename + self.alreadyOpen = 1 self.f.write('{\\rtf1\\ansi\\ansicpg1252\\deff0\n') self.f.write('{\\fonttbl\n') self.f.write('{\\f0\\froman\\fcharset0\\fprq0 Times New Roman;}\n') - self.f.write('{\\f1\\fswiss\\fcharset0\\fprq0 Arial;}}\n') + self.f.write('{\\f1\\fswiss\\fcharset0\\fprq0 Arial;}\n') + self.f.write('{\\f2\\fmodern\\fcharset0\\fprq0 Courier New;}}\n') self.f.write('{\colortbl\n') self.color_map = {} index = 1 @@ -97,6 +154,7 @@ class RTFDoc(TextDoc): self.f.write('\\margb%d' % twips(self.bmargin)) self.f.write('\\widowctl\n') self.in_table = 0 + self.in_listing = 0 self.text = "" #-------------------------------------------------------------------- @@ -106,7 +164,8 @@ class RTFDoc(TextDoc): #-------------------------------------------------------------------- def close(self): self.f.write('}\n') - self.f.close() + if not self.alreadyOpen: + self.f.close() #-------------------------------------------------------------------- # @@ -116,6 +175,90 @@ class RTFDoc(TextDoc): def end_page(self): self.f.write('\\sbkpage\n') + #-------------------------------------------------------------------- + # + # Starts a listing. Instead of using a style sheet, generate the + # the style for each paragraph on the fly. Not the ideal, but it + # does work. + # + #-------------------------------------------------------------------- + def start_listing(self,style_name): + self.opened = 0 + p = self.style_list[style_name] + + # build font information + + f = p.get_font() + size = f.get_size()*2 + bgindex = self.color_map[p.get_background_color()] + fgindex = self.color_map[f.get_color()] + if f.get_type_face() == FONT_MONOSPACE: + self.font_type = '\\f2\\fs%d\\cf%d\\cb%d' % (size,fgindex,bgindex) + elif f.get_type_face() == FONT_SERIF: + self.font_type = '\\f0\\fs%d\\cf%d\\cb%d' % (size,fgindex,bgindex) + else: + self.font_type = '\\f1\\fs%d\\cf%d\\cb%d' % (size,fgindex,bgindex) + if f.get_bold(): + self.font_type = self.font_type + "\\b" + if f.get_underline(): + self.font_type = self.font_type + "\\ul" + if f.get_italic(): + self.font_type = self.font_type + "\\i" + + # build listing block information + + self.f.write('\\pard') + self.f.write('\\ql') + self.para_align = '\\ql' + self.f.write('\\nowidctlpar') + self.f.write('\\nowwrap') + self.f.write('\\nocwrap') + self.f.write('\\ri%d' % twips(p.get_right_margin())) + self.f.write('\\li%d' % twips(p.get_left_margin())) + self.f.write('\\fi%d' % twips(p.get_first_indent())) + if p.get_padding(): + self.f.write('\\sa%d' % twips((0.25 + p.get_padding())/2.0)) + self.f.write('\\sb%d' % twips((0.25 + p.get_padding())/2.0)) + else: + self.f.write('\\sa%d' % twips(0.125)) + self.f.write('\\sb%d' % twips(0.125)) + haveBorders = 0 + if p.get_top_border(): + self.f.write('\\brdrt\\brdrs') + haveBorders = 1 + if p.get_bottom_border(): + self.f.write('\\brdrb\\brdrs') + haveBorders = 1 + if p.get_left_border(): + self.f.write('\\brdrl\\brdrs') + haveBorders = 1 + if p.get_right_border(): + self.f.write('\\brdrr\\brdrs') + haveBorders = 1 + if haveBorders: + if p.get_padding(): + self.f.write('\\brsp%d' % twips(p.get_padding())) + else: + self.f.write('\\brsp%d' % twips(0.125)) + self.in_listing = 1 + + #-------------------------------------------------------------------- + # + # Ends a listing. Care has to be taken to make sure that the + # braces are closed properly. The self.opened flag is used to indicate + # if braces are currently open. If the last write was the end of + # a bold-faced phrase, braces may already be closed. + # + #-------------------------------------------------------------------- + def end_listing(self): + self.f.write(self.text) + if self.opened: + self.f.write('}') + self.opened = 0 + self.text = "" + self.f.write('\n\\par') + self.in_listing = 0 + #-------------------------------------------------------------------- # # Starts a paragraph. Instead of using a style sheet, generate the @@ -149,30 +292,54 @@ class RTFDoc(TextDoc): if not self.in_table: self.f.write('\\pard') if p.get_alignment() == PARA_ALIGN_RIGHT: - self.f.write('\\qr') + if not self.in_table: + self.f.write('\\qr') + self.para_align = '\\qr' elif p.get_alignment() == PARA_ALIGN_CENTER: - self.f.write('\\qc') + if not self.in_table: + self.f.write('\\qc') + self.para_align = '\\qc' + else: + self.para_align = '\\ql' self.f.write('\\ri%d' % twips(p.get_right_margin())) self.f.write('\\li%d' % twips(p.get_left_margin())) self.f.write('\\fi%d' % twips(p.get_first_indent())) if p.get_alignment() == PARA_ALIGN_JUSTIFY: self.f.write('\\qj') - if p.get_padding(): - self.f.write('\\sa%d' % twips(p.get_padding()/2.0)) - if p.get_top_border(): - self.f.write('\\brdrt\\brdrs') - if p.get_bottom_border(): - self.f.write('\\brdrb\\brdrs') - if p.get_left_border(): - self.f.write('\\brdrl\\brdrs') - if p.get_right_border(): - self.f.write('\\brdrr\\brdrs') - if p.get_first_indent(): - self.f.write('\\fi%d' % twips(p.get_first_indent())) - if p.get_left_margin(): - self.f.write('\\li%d' % twips(p.get_left_margin())) - if p.get_right_margin(): - self.f.write('\\ri%d' % twips(p.get_right_margin())) + if self.in_table: + self.f.write('\\trgaph80') + else: + if p.get_padding(): + self.f.write('\\sa%d' % twips((0.25 + p.get_padding())/2.0)) + self.f.write('\\sb%d' % twips((0.25 + p.get_padding())/2.0)) + else: + self.f.write('\\sa%d' % twips(0.125)) + self.f.write('\\sb%d' % twips(0.125)) + haveBorders = 0 + if p.get_top_border(): + self.f.write('\\brdrt\\brdrs') + haveBorders = 1 + if p.get_bottom_border(): + self.f.write('\\brdrb\\brdrs') + haveBorders = 1 + if p.get_left_border(): + self.f.write('\\brdrl\\brdrs') + haveBorders = 1 + if p.get_right_border(): + self.f.write('\\brdrr\\brdrs') + haveBorders = 1 + if haveBorders: + if p.get_padding(): + self.f.write('\\brsp%d' % twips(p.get_padding())) + else: + self.f.write('\\brsp%d' % twips(0.125)) + # This is redundant. Why was it here? + #if p.get_first_indent(): + # self.f.write('\\fi%d' % twips(p.get_first_indent())) + #if p.get_left_margin(): + # self.f.write('\\li%d' % twips(p.get_left_margin())) + #if p.get_right_margin(): + # self.f.write('\\ri%d' % twips(p.get_right_margin())) if leader: self.opened = 1 @@ -181,6 +348,9 @@ class RTFDoc(TextDoc): self.write_text(leader) self.f.write('\\tab}') self.opened = 0 + + self.bold_on = 0 + self.italic_on = 0 #-------------------------------------------------------------------- # @@ -195,23 +365,52 @@ class RTFDoc(TextDoc): self.f.write(self.text) if self.opened: self.f.write('}') - self.text = "" self.opened = 0 + self.text = "" self.f.write('\n\\par') else: if self.text == "": self.write_text(" ") self.text = self.text + '}' + #-------------------------------------------------------------------- + # + # Starts italicized text, enclosed the braces + # + #-------------------------------------------------------------------- + def start_italic(self): + self.italic_on = 1 + emph = '\\i' + if self.bold_on: + emph = emph + '\\b' + if self.opened: + self.text = self.text + '}' + self.text = self.text + '{%s%s ' % (self.font_type, emph) + self.opened = 1 + + #-------------------------------------------------------------------- + # + # Ends italicized text, closing the braces + # + #-------------------------------------------------------------------- + def end_italic(self): + self.italic_on = 0 + self.opened = 0 + self.text = self.text + '}' + #-------------------------------------------------------------------- # # Starts boldfaced text, enclosed the braces # #-------------------------------------------------------------------- def start_bold(self): + self.bold_on = 1 + emph = '\\b' + if self.italic_on: + emph = emph + '\\i' if self.opened: - self.f.write('}') - self.f.write('{%s\\b ' % self.font_type) + self.text = self.text + '}' + self.text = self.text + '{%s%s ' % (self.font_type, emph) self.opened = 1 #-------------------------------------------------------------------- @@ -220,8 +419,9 @@ class RTFDoc(TextDoc): # #-------------------------------------------------------------------- def end_bold(self): + self.bold_on = 0 self.opened = 0 - self.f.write('}') + self.text = self.text + '}' #-------------------------------------------------------------------- # @@ -342,7 +542,7 @@ class RTFDoc(TextDoc): if index%32==0: self.f.write('\n') index = index+1 - self.f.write('}}\\par\n') + self.f.write('}}\n') #-------------------------------------------------------------------- # @@ -354,163 +554,55 @@ class RTFDoc(TextDoc): #-------------------------------------------------------------------- def write_text(self,text): if self.opened == 0: + emph = '' + if self.bold_on: + emph = emph + '\\b' + if self.italic_on: + emph = emph + '\\i' self.opened = 1 - self.text = self.text + '{%s ' % self.font_type + if self.in_table: + self.text = self.text + self.para_align + self.text = self.text + '{%s%s ' % (self.font_type, emph) for i in text: if ord(i) > 127: self.text = self.text + '\\\'%2x' % ord(i) elif i == '{' or i == '}' : self.text = self.text + '\\%s' % i + elif self.in_listing and i == '\n': + self.text = self.text + '\\line\n' else: self.text = self.text + i + #-------------------------------------------------------------------- + # + # Inserts a required line break into the text. + # + #-------------------------------------------------------------------- + def line_break(self): + self.text = self.text + '\\line\n' -if __name__ == "__main__": + #-------------------------------------------------------------------- + # + # Shows link text. + # + #-------------------------------------------------------------------- + def show_link(self, text, href): + self.write_text("%s (" % text) + self.start_italic() + self.write_text(href) + self.end_italic() + self.write_text(") ") - paper = PaperStyle("Letter",27.94,21.59) - - styles = StyleSheet() - foo = FontStyle() - foo.set_type_face(FONT_SANS_SERIF) - foo.set_color((255,0,0)) - foo.set_size(24) - foo.set_underline(1) - foo.set_bold(1) - foo.set_italic(1) - - para = ParagraphStyle() - para.set_alignment(PARA_ALIGN_RIGHT) - para.set_font(foo) - styles.add_style("Title",para) - - foo = FontStyle() - foo.set_type_face(FONT_SERIF) - foo.set_size(12) - - para = ParagraphStyle() - para.set_font(foo) - styles.add_style("Normal",para) - - foo = FontStyle() - foo.set_type_face(FONT_SERIF) - foo.set_size(12) - - para = ParagraphStyle() - para.set_font(foo) - para.set_top_border(1) - para.set_left_border(1) - para.set_right_border(1) - para.set_bottom_border(1) - styles.add_style("Box",para) - - doc = RTFDoc(styles,paper,PAPER_PORTRAIT) - - cell = TableCellStyle() - cell.set_padding(0.2) - cell.set_top_border(1) - cell.set_bottom_border(1) - cell.set_right_border(1) - cell.set_left_border(1) - doc.add_cell_style('ParentHead',cell) - - cell = TableCellStyle() - cell.set_padding(0.1) - cell.set_bottom_border(1) - cell.set_left_border(1) - doc.add_cell_style('TextContents',cell) - - cell = TableCellStyle() - cell.set_padding(0.1) - cell.set_bottom_border(0) - cell.set_left_border(1) - cell.set_padding(0.1) - doc.add_cell_style('TextChild1',cell) - - cell = TableCellStyle() - cell.set_padding(0.1) - cell.set_bottom_border(1) - cell.set_left_border(1) - cell.set_padding(0.1) - doc.add_cell_style('TextChild2',cell) - - cell = TableCellStyle() - cell.set_padding(0.1) - cell.set_bottom_border(1) - cell.set_right_border(1) - cell.set_left_border(1) - doc.add_cell_style('TextContentsEnd',cell) - - cell = TableCellStyle() - cell.set_padding(0.2) - cell.set_bottom_border(1) - cell.set_right_border(1) - cell.set_left_border(1) - doc.add_cell_style('ChildName',cell) - - table = TableStyle() - table.set_width(100) - table.set_columns(3) - table.set_column_width(0,20) - table.set_column_width(1,40) - table.set_column_width(2,40) - doc.add_table_style('ParentTable',table) - - table = TableStyle() - table.set_width(100) - table.set_columns(4) - table.set_column_width(0,5) - table.set_column_width(1,15) - table.set_column_width(2,40) - table.set_column_width(3,40) - doc.add_table_style('ChildTable',table) - - doc.open("test") - - doc.start_paragraph("Title") - doc.write_text("My Title") - doc.end_paragraph() - - doc.start_paragraph("Normal") - doc.write_text("Hello there. This is fun") - doc.end_paragraph() - - doc.start_paragraph("Box") - doc.write_text("This is my box") - doc.end_paragraph() - - doc.start_paragraph("Normal") - doc.add_photo("foo.png",200,200) - doc.end_paragraph() - - doc.start_table(id,'ParentTable') - doc.start_row() - doc.start_cell('ParentHead',3) - doc.start_paragraph('Normal') - doc.write_text('Banana : Smith ') - doc.end_paragraph() - doc.end_cell() - doc.end_row() - - doc.start_row() - doc.start_cell("TextContents") - doc.start_paragraph('Normal') - doc.write_text("some event") - doc.end_paragraph() - doc.end_cell() - doc.start_cell("TextContents") - doc.start_paragraph('Normal') - doc.write_text("someday") - doc.end_paragraph() - doc.end_cell() - doc.start_cell("TextContentsEnd") - doc.start_paragraph('Normal') - doc.write_text("somewhere") - doc.end_paragraph() - doc.end_cell() - doc.end_row() - - doc.end_table() - - doc.close() - -Plugins.register_text_doc(_("Rich Text Format (RTF)"),RTFDoc,1,1,1) +#------------------------------------------------------------------------ +# +# Register the document generator with the system if in Gramps +# +#------------------------------------------------------------------------ +if withGramps: + Plugins.register_text_doc( + name=_("Rich Text Format (RTF)"), + classref=RTFDoc, + table=1, + paper=1, + style=1 + )