summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog129
-rw-r--r--NEWS27
-rw-r--r--doc/groff.texinfo215
-rw-r--r--man/groff_font.man31
-rw-r--r--src/devices/grohtml/grohtml.man54
-rw-r--r--src/devices/grohtml/html-table.cpp128
-rw-r--r--src/devices/grohtml/html-table.h6
-rw-r--r--src/devices/grohtml/html-text.cpp35
-rw-r--r--src/devices/grohtml/html-text.h11
-rw-r--r--src/devices/grohtml/post-html.cpp371
-rw-r--r--src/preproc/eqn/box.cpp9
-rw-r--r--src/preproc/eqn/eqn.h1
-rw-r--r--src/preproc/eqn/main.cpp14
-rw-r--r--src/preproc/eqn/text.cpp2
-rw-r--r--src/preproc/html/pre-html.cpp168
-rw-r--r--src/roff/groff/groff.cpp47
-rw-r--r--src/roff/troff/input.cpp1
-rw-r--r--tmac/s.tmac63
-rw-r--r--tmac/troffrc-end21
-rw-r--r--tmac/www.tmac171
20 files changed, 1174 insertions, 330 deletions
diff --git a/ChangeLog b/ChangeLog
index d97a02ce..504ef137 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,132 @@
+2007-09-19 Gaius Mulley <gaius@glam.ac.uk>
+
+ * doc/groff.texinfo: Document new .O register and add cross
+ reference entries.
+
+ * NEWS: Updated.
+
+ * src/devices/grohtml/grohtml.man: Document new -V and -y options.
+
+ * src/devices/grohtml/html-table.cpp: Add support for XHTML 1.1.
+ (html_table:: emit_colspan, html_table::emit_td): New methods.
+ (html_table::emit_col): Use html_table::emit_td.
+ (html_table::emit_table_header): Use html_table::emit_colspan if
+ dialect xhtml is specified.
+ (html_table::finish_row): Updated.
+
+ * src/devices/grohtml/html-table.h (html_table): Declare
+ emit_colspan, emit_td.
+
+ * src/devices/grohtml/html-text.cpp: Modified tags to comply with
+ xhtml if this dialect was requested.
+
+ * src/devices/grohtml/html-text.h (html_dialect): New enumeration.
+ (html_text): Add new variable `dialect'.
+
+ * src/devices/grohtml/post-html.cpp: Modify header tags to be XHTML
+ compliant.
+ (valid_flag, groff_sig, dialect): New global variables.
+ (html_printer::handle_valid_flag, html_printer::do_math,
+ html_printer::write_html_anchor, html_printer::write_xhtml_anchor,
+ html_printer::do_math, html_printer::handle_valid_flag): New
+ methods.
+ (html_printer::emit_line, html_printer::emit_raw,
+ html_printer::do_check_center, html_printer::write_title,
+ write_rule, html_printer::writeHeadMetaStyle, generate_img_src,
+ html_printer::begin_page): Altered to be XHTML compliant.
+ (html_printer::write_header): Updated.
+ (html_printer::troff_tag): Call do_math.
+ (html_printer::insert_split_file, html_printer::do_file_components,
+ html_printer::write_navigation): Create XHTML file components if
+ necessary and also produces a groff signature if requested.
+ (~html_printer): Call writeHeadMetaStyle at appropriate places
+ depending upon html_dialect.
+ (html_printer::special): Handle new tags `html<?p>' and `math<?p>'.
+ (main): Added options -x, -V, and -y.
+ (usage): Updated.
+
+ * src/preproc/eqn/box.cpp: Create a distinction between
+ the MathML device and the XHTML device.
+ (do_text): Issue a newline at the end of the equation if XHTML was
+ specified.
+ (box::top_level): Prefix the output of an equation by the .MATHML
+ macro.
+ (output_string): Suppress \n if XHTML was specified.
+
+ * src/preproc/eqn/main.cpp (xhtml): New global flag.
+ (inline_equation): Skip leading spaces after inline equation for
+ XHTML device.
+ (main): Set `xhtml' flag if `-Tmathml:xhtml' is specified.
+
+ * src/preproc/eqn/eqn.h (xhtml): New external flag.
+
+ * src/preproc/eqn/text.cpp (entity_table): Fix typo.
+
+ * src/preproc/html/pre-html.cpp (html_dialect): New enumeration.
+ (dialect, eqn_flag): New global variables.
+ (html_system): Improve debugging support.
+ (alterDeviceTo): Test for -Txhtml when altering device to the image
+ device and reset to -Txhtml.
+ (addZ): Renamed to...
+ (addArg): This.
+ Introducea a general parameter.
+ (print_args): New debugging function.
+ (char_buffer::run_output_filter): Use print_args and addArg rather
+ than addZ.
+ (char_buffer::do_html, char_buffer::do_image): Add -rxhtml=1 command
+ line parameter as an argument to the html generation of text when
+ xhtml is needed. Include -e on the command line if mathml is
+ required.
+ (scanArguments): Allow -e, -V, -y and -x options.
+ -V, -y are handled by the back end. -e sets `eqn_flag'.
+ -x determines HTML dialect.
+
+ * src/roff/groff/groff.cpp (possible_command): New method
+ `clear_name'.
+ (main): Set eflag if -e is present on command line.
+ Set is_xhtml if -Txhtml is present.
+ Pass `-x x' to the HTML pre and post processors.
+ Pass `-e' to the HTML pre processor if required.
+ Pass `-Tmathml:xhtml' to eqn if XHTML is requested.
+
+ * src/roff/troff/input.cpp (init_input_requests): Introduce new
+ number register `\n[.O]'.
+
+ * tmac/s.tmac: (LP): Use .nop for semantic sugar.
+ (cov*ab-init) reformat.
+ (@EQ): Use EQN-HTML-IMAGE and friends rather than HTML-IMAGE.
+ (CHECK-FOOTER-AND-KEEP): Define FS, FE such that they use
+ <cite></cite> for the html device rather than generate images for
+ footnotes.
+
+ * tmac/troffrc-end: Define EQN-HTML-IMAGE,
+ EQN-HTML-IMAGE-END, EQN-HTML-IMAGE-RIGHT,
+ EQN-HTML-IMAGE-LEFT, EQN-HTML-IMAGE-INLINE,
+ EQN-HTML-DO-IMAGE, EQN-HTML-IMAGE-END as null strings.
+
+ * tmac/www.tmac: (HTML<?p>): New macro.
+ (MATH<?p>): New macro.
+ (IMG, PIMG, MPIMG, HR): Use XHTML compliant syntax.
+ (www-emit-ltag): New macro.
+ (www-push-li): Updated.
+ (ULS): Ensure that tags are balanced in order by use of
+ www-emit-ltag.
+ (ULE): Likewise: Use www-emit-ltag and shut down paragraphs in
+ order.
+ (OLS, OLE, DLS, DLE): Ditto.
+ <global>: Define EQ and EN to EQN-HTML-IMAGE and EQN-HTML-IMAGE-END
+ respectively.
+ (www-li-ul, www-li-ol, www-li-dl): Updated.
+ (EQN-HTML-IMAGE, EQN-HTML-IMAGE-RIGHT, EQN-HTML-IMAGE-LEFT,
+ EQN-HTML-IMAGE-INLINE, EQN-HTML-DO-IMAGE, EQN-HTML-IMAGE-END,
+ MATHML): New macros.
+
+2007-09-17 Werner LEMBERG <wl@gnu.org>
+
+ * man/groff_font.man: Document `unicode' keyword.
+ * doc/groff.texinfo (DESC File Format): Synchronize with
+ groff_font.man.
+
2007-09-15 Werner LEMBERG <wl@nu.org>
* man/groff.man: Document `\_'.
diff --git a/NEWS b/NEWS
index 68767917..889b0dc4 100644
--- a/NEWS
+++ b/NEWS
@@ -14,6 +14,16 @@ VERSION 1.19.3
Groff
-----
+o XHTML support has been added to grohtml and can be specified by
+ -Txhtml. This option also utilizes the MathML capability of
+ eqn and combine the outputs of both in the final XHTML file.
+ Users can also specify the `-P-V' option together with `-Txhtml'
+ in groff. This has the effect of creating an XHTML' validator
+ button at the bottom of each page.
+
+Troff
+-----
+
o Two new requests `device' and `devicem' have been added which are
equivalents to the \X and \Y escapes, respectively.
@@ -63,6 +73,9 @@ o The PS font definition files have been regenerated with newer AFM versions
For backwards compatibility, the old set of font definition files is still
available; for details please read the man page of `grops(1)'.
+
+o A new read-only number register `.O' is available which returns the
+ current suppression level as set by the `\O' escape.
Pic
---
@@ -79,7 +92,7 @@ Eqn
o Eric S. Raymond has added a new device type to eqn, MathML. When
-TMathML is enabled, eqn now emits MathML formula markup rather than
- groff commands.
+ groff commands. The new groff -Txhtml device uses this.
Chem
----
@@ -93,6 +106,18 @@ Grotty
o \D'p...' is now supported if the polygon consists entirely of horizontal
and vertical lines.
+Grohtml
+-------
+
+o XHTML support has been added.
+
+o New command line option `-V' (to be used in XHTML mode) to produce an
+ XHTML validator button.
+
+o New command line option `-y' to produce a right-justified groff signature
+ at the end of the document (in combination with option `-V').
+
+
Gxditview
---------
diff --git a/doc/groff.texinfo b/doc/groff.texinfo
index 06b43c42..a883be17 100644
--- a/doc/groff.texinfo
+++ b/doc/groff.texinfo
@@ -26,7 +26,8 @@
@copying
This manual documents GNU @code{troff} version 1.19.2.
-Copyright @copyright{} 1994-2000, 2001, 2002, 2003, 2004, 2005, 2006
+Copyright @copyright{} 1994-2000, 2001, 2002, 2003, 2004, 2005, 2006,
+2007
Free Software Foundation, Inc.
@quotation
@@ -472,7 +473,7 @@ Software Foundation raise funds for GNU development.''
@title groff
@subtitle The GNU implementation of @code{troff}
@subtitle Edition 1.19.3
-@subtitle Summer 2006
+@subtitle Autumn 2007
@author by Trent A.@tie{}Fisher
@author and Werner Lemberg (@email{bug-groff@@gnu.org})
@@ -553,7 +554,7 @@ Software Foundation raise funds for GNU development.''
@chapter Introduction
@cindex introduction
-GNU @code{troff} (or @code{groff}) is a system for typesetting documents.
+GNU @code{troff} (or @code{groff}) is a system for typesetting documents.
@code{troff} is very flexible and has been used extensively for some thirty
years. It is well entrenched in the @acronym{UNIX} community.
@@ -4019,7 +4020,7 @@ The @code{PT} macro defines a custom header;
the @code{BT} macro defines a custom footer. These macros must
handle odd/even/first page differences if necessary.
-The @code{HD} macro defines additional header processing
+The @code{HD} macro defines additional header processing
to take place after executing the @code{PT} macro.
@endDefmac
@@ -4386,7 +4387,7 @@ number register.
Emulations of a few ancient Bell Labs macros can be re-enabled by calling
the otherwise undocumented @code{SC} section-header macro. Calling @code{SC}
-enables @code{UC} for marking up a product or application name, and the pair
+enables @code{UC} for marking up a product or application name, and the pair
@code{P1}/@code{P2} for surrounding code example displays.
These are not enabled by default because (a)@tie{}they were not documented,
@@ -6472,6 +6473,11 @@ If the command line option @option{-a} is used to produce an
@acronym{ASCII} approximation of the output, this is set to@tie{}1, zero
otherwise. @xref{Groff Options}.
+@item \n[.O]
+@vindex .O
+This read-only register is set to the suppression nesting level (see
+escapes @code{\O}). @xref{Suppressing output}.
+
@item \n[.P]
@vindex .P
This register is set to@tie{}1 (and to@tie{}0 otherwise) if the current
@@ -7187,7 +7193,7 @@ page:
@endExample
@noindent
-A call to @samp{.y-from-bot-up 10c} means that the bottom of the next line
+A call to @samp{.y-from-bot-up 10c} means that the bottom of the next line
will be at 10@dmn{cm} from the paper edge at the bottom.
If a vertical trap is sprung during execution of @code{sp}, the amount of
@@ -12854,9 +12860,13 @@ to @code{\O}.
@item \O3
Begin a nesting level. At start-up, @code{gtroff} is at outer level.
+The current level is contained within the read-only register @code{.O}.
+@xref{Built-in Registers}.
@item \O4
End a nesting level.
+The current level is contained within the read-only register @code{.O}.
+@xref{Built-in Registers}.
@item \O[5@var{P}@var{filename}]
This escape is @code{grohtml} specific. Provided that this escape
@@ -15670,14 +15680,25 @@ called@tie{}@file{@var{f}}.
The @file{DESC} file can contain the following types of line. Except
for the @code{charset} keyword which must comes last (if at all), the
-order of the lines is not important.
+order of the lines is not important. Later entries in the file, however,
+override previous values.
@table @code
-@item res @var{n}
-@kindex res
-@cindex device resolution
-@cindex resolution, device
-There are @var{n}@tie{}machine units per inch.
+@item charset
+@kindex charset
+This line and everything following in the file are ignored. It is
+allowed for the sake of backwards compatibility.
+
+@item family @var{fam}
+@kindex family
+The default font family is @var{fam}.
+
+@item fonts @var{n} @var{F1} @var{F2} @var{F3} @dots{} @var{Fn}
+@kindex fonts
+Fonts @var{F1} @dots{} @var{Fn} are mounted in the font positions
+@var{m}+1, @dots{}, @var{m}+@var{n} where @var{m} is the number of
+styles. This command may extend over more than one line. A font name
+of@tie{}0 means no font is mounted on the corresponding font position.
@item hor @var{n}
@kindex hor
@@ -15686,29 +15707,54 @@ There are @var{n}@tie{}machine units per inch.
The horizontal resolution is @var{n}@tie{}machine units. All horizontal
quantities are rounded to be multiples of this value.
-@item vert @var{n}
-@kindex vert
-@cindex vertical resolution
-@cindex resolution, vertical
-The vertical resolution is @var{n}@tie{}machine units. All vertical
-quantities are rounded to be multiples of this value.
+@item image_generator @var{string}
+@kindex image_generator
+@cindex PostScript, PNG image generation
+@cindex PNG image generation from PostScript
+Needed for @code{grohtml} only. It specifies the program to generate
+PNG images from PostScript input. Under GNU/Linux this is usually
+@code{gs} but under other systems (notably cygwin) it might be set to
+another name.
+
+@item paperlength @var{n}
+@kindex paperlength
+The physical vertical dimension of the output medium in machine units.
+This isn't used by @code{troff} itself but by output devices.
+Deprecated. Use @code{papersize} instead.
-@item sizescale @var{n}
-@kindex sizescale
-The scale factor for point sizes. By default this has a value of@tie{}1.
-One scaled point is equal to one point/@var{n}. The arguments to the
-@code{unitwidth} and @code{sizes} commands are given in scaled points.
-@xref{Fractional Type Sizes}, for more information.
+@item papersize @var{string} @dots{}
+@kindex papersize
+Select a paper size. Valid values for @var{string} are the ISO paper
+types @code{A0}-@code{A7}, @code{B0}-@code{B7}, @code{C0}-@code{C7},
+@code{D0}-@code{D7}, @code{DL}, and the US paper types @code{letter},
+@code{legal}, @code{tabloid}, @code{ledger}, @code{statement},
+@code{executive}, @code{com10}, and @code{monarch}. Case is not significant
+for @var{string} if it holds predefined paper types. Alternatively,
+@var{string} can be a file name (e.g.@: @file{/etc/papersize}); if the file
+can be opened, @code{groff} reads the first line and tests for the above
+paper sizes. Finally, @var{string} can be a custom paper size in the format
+@code{@var{length},@var{width}} (no spaces before and after the comma).
+Both @var{length} and @var{width} must have a unit appended; valid values
+are @samp{i} for inches, @samp{C} for centimeters, @samp{p} for points, and
+@samp{P} for picas. Example: @code{12c,235p}. An argument which starts
+with a digit is always treated as a custom paper format. @code{papersize}
+sets both the vertical and horizontal dimension of the output medium.
-@item unitwidth @var{n}
-@kindex unitwidth
-Quantities in the font files are given in machine units for fonts whose
-point size is @var{n}@tie{}scaled points.
+More than one argument can be specified; @code{groff} scans from left to
+right and uses the first valid paper specification.
-@item prepro @var{program}
-@kindex prepro
-Call @var{program} as a preprocessor. Currently, this keyword is used
-by @code{groff} with option @option{-Thtml} only.
+@item paperwidth @var{n}
+@kindex paperwidth
+The physical horizontal dimension of the output medium in machine units.
+This isn't used by @code{troff} itself but by output devices.
+Deprecated. Use @code{papersize} instead.
+
+@item pass_filenames
+@kindex pass_filenames
+Tell @code{gtroff} to emit the name of the source file currently
+being processed. This is achieved by the intermediate output command
+@samp{F}. Currently, this is only used by the @acronym{HTML} output
+device.
@item postpro @var{program}
@kindex postpro
@@ -15722,10 +15768,21 @@ postpro grodvi
in the file @file{devdvi/DESC} makes @code{groff} call @code{grodvi}
if option @option{-Tdvi} is given (and @option{-Z} isn't used).
-@item tcommand
-@kindex tcommand
-This means that the postprocessor can handle the @samp{t} and @samp{u}
-intermediate output commands.
+@item prepro @var{program}
+@kindex prepro
+Call @var{program} as a preprocessor. Currently, this keyword is used
+by @code{groff} with option @option{-Thtml} only.
+
+@item print @var{program}
+@kindex print
+Use @var{program} as a spooler program for printing. If omitted,
+the @option{-l} and @option{-L} options of @code{groff} are ignored.
+
+@item res @var{n}
+@kindex res
+@cindex device resolution
+@cindex resolution, device
+There are @var{n}@tie{}machine units per inch.
@item sizes @var{s1} @var{s2} @dots{} @var{sn} 0
@kindex sizes
@@ -15734,65 +15791,59 @@ This means that the device has fonts at @var{s1}, @var{s2}, @dots{}
(this is digit zero). Each @var{si} can also be a range of sizes
@var{m}-@var{n}. The list can extend over more than one line.
+@item sizescale @var{n}
+@kindex sizescale
+The scale factor for point sizes. By default this has a value of@tie{}1.
+One scaled point is equal to one point/@var{n}. The arguments to the
+@code{unitwidth} and @code{sizes} commands are given in scaled points.
+@xref{Fractional Type Sizes}, for more information.
+
@item styles @var{S1} @var{S2} @dots{} @var{Sm}
@kindex styles
The first @var{m}@tie{}font positions are associated with styles
@var{S1} @dots{} @var{Sm}.
-@item fonts @var{n} @var{F1} @var{F2} @var{F3} @dots{} @var{Fn}
-@kindex fonts
-Fonts @var{F1} @dots{} @var{Fn} are mounted in the font positions
-@var{m}+1, @dots{}, @var{m}+@var{n} where @var{m} is the number of
-styles. This command may extend over more than one line. A font name
-of@tie{}0 means no font is mounted on the corresponding font position.
+@item tcommand
+@kindex tcommand
+This means that the postprocessor can handle the @samp{t} and @samp{u}
+intermediate output commands.
-@item family @var{fam}
-@kindex family
-The default font family is @var{fam}.
+@item unicode
+@kindex unicode
+Indicate that the output device supports the complete Unicode
+repertoire. Useful only for devices which produce @emph{character
+entities} instead of glyphs.
+
+If @code{unicode} is present, no @code{charset} section is required
+in the font description files since the Unicode handling built into
+@code{groff} is used. However, if there are entries in a
+@code{charset} section, they either override the default mappings for
+those particular characters or add new mappings (normally for composite
+characters).
+
+This is used for @option{-Tutf8} and @option{-Thtml}.
+@item unitwidth @var{n}
+@kindex unitwidth
+Quantities in the font files are given in machine units for fonts whose
+point size is @var{n}@tie{}scaled points.
+
+@item unscaled_charwidths
+@kindex unscaled_charwidths
+Make the font handling module always return unscaled character widths.
+Needed for the @code{grohtml} device.
@item use_charnames_in_special
@kindex use_charnames_in_special
This command indicates that @code{gtroff} should encode special
characters inside special commands. Currently, this is only used
by the @acronym{HTML} output device. @xref{Postprocessor Access}.
-@item papersize @var{string} @dots{}
-@kindex papersize
-Select a paper size. Valid values for @var{string} are the ISO paper
-types @code{A0}-@code{A7}, @code{B0}-@code{B7}, @code{C0}-@code{C7},
-@code{D0}-@code{D7}, @code{DL}, and the US paper types @code{letter},
-@code{legal}, @code{tabloid}, @code{ledger}, @code{statement},
-@code{executive}, @code{com10}, and @code{monarch}. Case is not significant
-for @var{string} if it holds predefined paper types. Alternatively,
-@var{string} can be a file name (e.g.@: @file{/etc/papersize}); if the file
-can be opened, @code{groff} reads the first line and tests for the above
-paper sizes. Finally, @var{string} can be a custom paper size in the format
-@code{@var{length},@var{width}} (no spaces before and after the comma).
-Both @var{length} and @var{width} must have a unit appended; valid values
-are @samp{i} for inches, @samp{C} for centimeters, @samp{p} for points, and
-@samp{P} for picas. Example: @code{12c,235p}. An argument which starts
-with a digit is always treated as a custom paper format. @code{papersize}
-sets both the vertical and horizontal dimension of the output medium.
-
-More than one argument can be specified; @code{groff} scans from left to
-right and uses the first valid paper specification.
-
-@item pass_filenames
-@kindex pass_filenames
-Tell @code{gtroff} to emit the name of the source file currently
-being processed. This is achieved by the intermediate output command
-@samp{F}. Currently, this is only used by the @acronym{HTML} output
-device.
-
-@item print @var{program}
-@kindex print
-Use @var{program} as a spooler program for printing. If omitted,
-the @option{-l} and @option{-L} options of @code{groff} are ignored.
-
-@item charset
-@kindex charset
-This line and everything following in the file are ignored. It is
-allowed for the sake of backwards compatibility.
+@item vert @var{n}
+@kindex vert
+@cindex vertical resolution
+@cindex resolution, vertical
+The vertical resolution is @var{n}@tie{}machine units. All vertical
+quantities are rounded to be multiples of this value.
@end table
The @code{res}, @code{unitwidth}, @code{fonts}, and @code{sizes} lines
diff --git a/man/groff_font.man b/man/groff_font.man
index e6ef8d38..679bf7ab 100644
--- a/man/groff_font.man
+++ b/man/groff_font.man
@@ -287,6 +287,37 @@ and
output commands.
.
.TP
+.B unicode
+Indicate that the output device supports the complete Unicode
+repertoire.
+.
+Useful only for devices which produce
+.I character entities
+instead of glyphs.
+.
+.IP
+If
+.B unicode
+is present, no
+.B charset
+section is required in the font description files since the Unicode
+handling built into
+.B groff
+is used.
+.
+However, if there are entries in a
+.B charset
+section, they either override the default mappings for those
+particular characters or add new mappings (normally for composite
+characters).
+.
+.IP
+This is used for
+.B \-Tutf8
+and
+.BR \-Thtml .
+.
+.TP
.BI unitwidth\ n
Quantities in the font files are given in machine units
for fonts whose point size is
diff --git a/src/devices/grohtml/grohtml.man b/src/devices/grohtml/grohtml.man
index a4d4ece0..d1c6d28c 100644
--- a/src/devices/grohtml/grohtml.man
+++ b/src/devices/grohtml/grohtml.man
@@ -1,5 +1,5 @@
.ig
-Copyright (C) 1999-2000, 2001, 2002, 2003, 2004, 2006
+Copyright (C) 1999-2000, 2001, 2002, 2003, 2004, 2006, 2007
Free Software Foundation, Inc.
Permission is granted to make and distribute verbatim copies of this
@@ -58,6 +58,7 @@ grohtml \- html driver for groff
.OP \-o \%image-vertical-offset
.OP \-s size
.OP \-S level
+.OP \-x \%html-dialect
.RI "[\ " files\|.\|.\|. "\ ]"
.br
.ad \na
@@ -130,6 +131,24 @@ to place all image files into directory
.IR dir .
.
.TP
+.B \-e
+This option should not be directly invoked by the user as it is
+an internal option utilized by
+.B groff
+when
+.B \-Thtml
+or
+.B \-Txhtml
+is specified.
+It is used by the
+.B grohtml
+preprocessor to determine whether
+.B eqn
+should attempt to produce MathML (if
+.B \-Txhtml
+is specified).
+.
+.TP
.BI \-F dir
Prepend directory
.IB dir /dev name
@@ -241,6 +260,39 @@ split at the heading level (or higher) defined by
.B \-v
Print the version number.
.
+.TP
+.B \-V
+Create an XHTML validator button at the bottom of each page of
+the document.
+.
+.TP
+.BI \-x dialect
+Select HTML dialect.
+Currently,
+.I dialect
+should be either the digit\~\c
+.B 4
+or the letter\~\c
+.B x
+which indicates whether
+.B grohtml
+should generate HTML\~4 or XHTML, respectively.
+This option should not be directly invoked by the user as it is
+an internal option utilized by
+.B groff
+when
+.B \-Thtml
+or
+.B \-Txhtml
+is specified.
+.
+.TP
+.B \-y
+Produce a right-justified groff signature at the end of the document.
+This is only generated if the
+.B \-V
+flag is also specified.
+.
.
.SH USAGE
There are styles called
diff --git a/src/devices/grohtml/html-table.cpp b/src/devices/grohtml/html-table.cpp
index 7e5b2dc5..c752b766 100644
--- a/src/devices/grohtml/html-table.cpp
+++ b/src/devices/grohtml/html-table.cpp
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
*
* Gaius Mulley (gaius@glam.ac.uk) wrote html-table.cpp
*
@@ -41,6 +41,9 @@ Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */
# define FALSE (1==0)
#endif
+extern html_dialect dialect;
+
+
tabs::tabs ()
: tab(NULL)
{
@@ -294,7 +297,7 @@ void html_table::set_linelength (int linelen)
}
p = c;
}
- if (p != NULL && p->right > 0)
+ if (p != NULL && p->right > 0 && linelength > p->right)
add_column(p->no+1, p->right, linelength, 'L');
}
@@ -337,10 +340,12 @@ void html_table::emit_table_header (int space)
out->nl();
out->put_string("<table width=\"100%\"")
- .put_string(" border=0 rules=\"none\" frame=\"void\"\n")
+ .put_string(" border=\"0\" rules=\"none\" frame=\"void\"\n")
.put_string(" cellspacing=\"0\" cellpadding=\"0\"");
out->put_string(">")
.nl();
+ if (dialect == xhtml)
+ emit_colspan();
out->put_string("<tr valign=\"top\" align=\"left\"");
if (space) {
out->put_string(" style=\"margin-top: ");
@@ -375,6 +380,82 @@ void html_table::set_space (int space)
}
/*
+ * emit_colspan - emits a series of colspan entries defining the
+ * table columns.
+ */
+
+void html_table::emit_colspan (void)
+{
+ cols *b = columns;
+ cols *c = columns;
+ int width = 0;
+
+ out->put_string("<colgroup>");
+ while (c != NULL) {
+ if (b != NULL && b != c && is_gap(b))
+ /*
+ * blank column for gap
+ */
+ out->put_string("<col width=\"")
+ .put_number(is_gap(b))
+ .put_string("%\" class=\"center\"></col>")
+ .nl();
+
+ width = (get_right(c)*100 + get_effective_linelength()/2)
+ / get_effective_linelength()
+ - (c->left*100 + get_effective_linelength()/2)
+ /get_effective_linelength();
+ switch (c->alignment) {
+ case 'C':
+ out->put_string("<col width=\"")
+ .put_number(width)
+ .put_string("%\" class=\"center\"></col>")
+ .nl();
+ break;
+ case 'R':
+ out->put_string("<col width=\"")
+ .put_number(width)
+ .put_string("%\" class=\"right\"></col>")
+ .nl();
+ break;
+ default:
+ out->put_string("<col width=\"")
+ .put_number(width)
+ .put_string("%\"></col>")
+ .nl();
+ }
+ b = c;
+ c = c->next;
+ }
+ out->put_string("</colgroup>").nl();
+}
+
+/*
+ * emit_td - writes out a <td> tag with a corresponding width
+ * if the dialect is html4.
+ */
+
+void html_table::emit_td (int percentage, const char *s)
+{
+ if (percentage) {
+ if (dialect == html4) {
+ out->put_string("<td width=\"")
+ .put_number(percentage)
+ .put_string("%\"");
+ if (s != NULL)
+ out->put_string(s);
+ out->nl();
+ }
+ else {
+ out->put_string("<td");
+ if (s != NULL)
+ out->put_string(s);
+ out->nl();
+ }
+ }
+}
+
+/*
* emit_col - moves onto column, n.
*/
@@ -405,11 +486,7 @@ void html_table::emit_col (int n)
// have we a gap?
if (last_col != NULL) {
- if (is_gap(b))
- out->put_string("<td width=\"")
- .put_number(is_gap(b))
- .put_string("%\"></td>")
- .nl();
+ emit_td(is_gap(b), "></td>");
b = b->next;
}
@@ -421,17 +498,9 @@ void html_table::emit_col (int n)
/ get_effective_linelength()
- (b->left*100 + get_effective_linelength()/2)
/get_effective_linelength();
- if (width)
- out->put_string("<td width=\"")
- .put_number(width)
- .put_string("%\"></td>")
- .nl();
+ emit_td(width, "></td>");
// have we a gap?
- if (is_gap(b))
- out->put_string("<td width=\"")
- .put_number(is_gap(b))
- .put_string("%\"></td>")
- .nl();
+ emit_td(is_gap(b), "></td>");
b = b->next;
}
width = (get_right(b)*100 + get_effective_linelength()/2)
@@ -440,22 +509,13 @@ void html_table::emit_col (int n)
/get_effective_linelength();
switch (b->alignment) {
case 'C':
- out->put_string("<td width=\"")
- .put_number(width)
- .put_string("%\" align=center>")
- .nl();
+ emit_td(width, " align=center>");
break;
case 'R':
- out->put_string("<td width=\"")
- .put_number(width)
- .put_string("%\" align=right>")
- .nl();
+ emit_td(width, " align=right>");
break;
default:
- out->put_string("<td width=\"")
- .put_number(width)
- .put_string("%\">")
- .nl();
+ emit_td(width);
}
// remember column, b
last_col = b;
@@ -477,7 +537,13 @@ void html_table::finish_row (void)
if (n > 0)
emit_col(n);
- out->put_string("</td>").nl();
+#if 1
+ if (last_col != NULL) {
+ out->put_string("</td>");
+ last_col = NULL;
+ }
+#endif
+ out->put_string("</tr>").nl();
}
}
diff --git a/src/devices/grohtml/html-table.h b/src/devices/grohtml/html-table.h
index dc6cebe2..5f1cfe56 100644
--- a/src/devices/grohtml/html-table.h
+++ b/src/devices/grohtml/html-table.h
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
*
* Gaius Mulley (gaius@glam.ac.uk) wrote html-table.h
*
@@ -93,6 +93,8 @@ public:
void finish_row (void);
int get_effective_linelength (void);
void set_space (int space);
+ void emit_colspan (void);
+ void emit_td (int percentage, const char *s = ">");
tabs *tab_stops; /* tab stop positions */
simple_output *out;
@@ -121,7 +123,7 @@ public:
// the indent is shutdown when it is deleted
private:
- void end (void);
+ void end (void);
int is_used;
int pg; // values of the registers as passed via initialization
int ll;
diff --git a/src/devices/grohtml/html-text.cpp b/src/devices/grohtml/html-text.cpp
index b58d5e4a..f2b36025 100644
--- a/src/devices/grohtml/html-text.cpp
+++ b/src/devices/grohtml/html-text.cpp
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005
+/* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007
* Free Software Foundation, Inc.
*
* Gaius Mulley (gaius@glam.ac.uk) wrote html-text.cpp
@@ -44,10 +44,11 @@ Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */
#undef DEBUGGING
// #define DEBUGGING
-html_text::html_text (simple_output *op) :
- stackptr(NULL), lastptr(NULL), out(op), space_emitted(TRUE),
- current_indentation(-1), pageoffset(-1), linelength(-1),
- blank_para(TRUE), start_space(FALSE)
+html_text::html_text (simple_output *op, html_dialect d) :
+ stackptr(NULL), lastptr(NULL), out(op), dialect(d),
+ space_emitted(TRUE), current_indentation(-1),
+ pageoffset(-1), linelength(-1), blank_para(TRUE),
+ start_space(FALSE)
{
}
@@ -165,8 +166,12 @@ void html_text::end_tag (tag_definition *t)
delete t->indent;
t->indent = NULL;
break;
- case SMALL_TAG: out->put_string("</small>"); break;
- case BIG_TAG: out->put_string("</big>"); break;
+ case SMALL_TAG: if (dialect != xhtml || (! is_in_pre ()))
+ out->put_string("</small>");
+ break;
+ case BIG_TAG: if (dialect != xhtml || (! is_in_pre ()))
+ out->put_string("</big>");
+ break;
case COLOR_TAG: out->put_string("</font>"); break;
default:
@@ -196,8 +201,10 @@ void html_text::issue_tag (const char *tagname, const char *arg,
out->put_string(STYLE_VERTICAL_SPACE);
out->put_string("\"");
}
+#if 0
if (space == TRUE || space == FALSE)
out->put_string(" valign=\"top\"");
+#endif
out->put_string(">");
}
@@ -258,8 +265,12 @@ void html_text::start_tag (tag_definition *t)
issue_tag("", (char *)t->arg1);
}
out->enable_newlines(FALSE); break;
- case SMALL_TAG: issue_tag("<small", (char *)t->arg1); break;
- case BIG_TAG: issue_tag("<big", (char *)t->arg1); break;
+ case SMALL_TAG: if (dialect != xhtml || (! is_in_pre ()))
+ issue_tag("<small", (char *)t->arg1);
+ break;
+ case BIG_TAG: if (dialect != xhtml || (! is_in_pre ()))
+ issue_tag("<big", (char *)t->arg1);
+ break;
case BREAK_TAG: break;
case COLOR_TAG: issue_color_begin(&t->col); break;
@@ -652,9 +663,11 @@ void html_text::do_emittext (const char *s, int length)
int text = remove_break();
check_emit_text(stackptr);
if (text) {
- if (is_present(PRE_TAG)) {
+ if (is_present(PRE_TAG))
out->nl();
- } else
+ else if (dialect == xhtml)
+ out->put_string("<br/>").nl();
+ else
out->put_string("<br>").nl();
}
} else
diff --git a/src/devices/grohtml/html-text.h b/src/devices/grohtml/html-text.h
index e0e3cc75..d6e11cd8 100644
--- a/src/devices/grohtml/html-text.h
+++ b/src/devices/grohtml/html-text.h
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005
+/* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007
* Free Software Foundation, Inc.
*
* Gaius Mulley (gaius@glam.ac.uk) wrote html-text.h
@@ -32,6 +32,12 @@ Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */
#define STYLE_VERTICAL_SPACE "1em"
/*
+ * supported html dialects.
+ */
+
+typedef enum {xhtml, html4} html_dialect;
+
+/*
* html tags
*/
@@ -56,7 +62,7 @@ typedef struct tag_definition {
class html_text {
public:
- html_text (simple_output *op);
+ html_text (simple_output *op, html_dialect d);
~html_text (void);
void flush_text (void);
void do_emittext (const char *s, int length);
@@ -105,6 +111,7 @@ private:
tag_definition *stackptr; /* the current paragraph state */
tag_definition *lastptr; /* the end of the stack */
simple_output *out;
+ html_dialect dialect; /* which dialect of html? */
int space_emitted; /* just emitted a space? */
int current_indentation; /* current .in value */
int pageoffset; /* .po value */
diff --git a/src/devices/grohtml/post-html.cpp b/src/devices/grohtml/post-html.cpp
index 3d93dc72..4a6e0cbc 100644
--- a/src/devices/grohtml/post-html.cpp
+++ b/src/devices/grohtml/post-html.cpp
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006
+/* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
* Free Software Foundation, Inc.
*
* Gaius Mulley (gaius@glam.ac.uk) wrote post-html.cpp
@@ -90,6 +90,10 @@ static int base_point_size = 0; /* which troff font size ma
static int split_level = 2; /* what heading level to split at? */
static string head_info; /* user supplied information to be placed */
/* into <head> </head> */
+static int valid_flag = FALSE; /* has user requested a valid flag at the */
+ /* end of each page? */
+static int groff_sig = FALSE; /* "This document was produced using" */
+html_dialect dialect = html4; /* which html dialect should grohtml output */
/*
@@ -1570,6 +1574,8 @@ void header_desc::write_headings (FILE *f, int force)
headers.start_from_head();
header_filename.start_from_head();
+ if (dialect == xhtml)
+ fputs("<p>", f);
do {
g = headers.get_data();
fputs("<a href=\"", f);
@@ -1589,12 +1595,18 @@ void header_desc::write_headings (FILE *f, int force)
h++;
fputs("\">", f);
fputs(g->text_string, f);
- fputs("</a><br>\n", f);
+ fputs("</a>", f);
+ if (dialect == xhtml)
+ fputs("<br/>\n", f);
+ else
+ fputs("<br>\n", f);
headers.move_right();
if (multiple_files && (! header_filename.is_empty()))
header_filename.move_right();
} while (! headers.is_equal_to_head());
fputs("\n", f);
+ if (dialect == xhtml)
+ fputs("</p>\n", f);
}
}
}
@@ -2091,6 +2103,10 @@ class html_printer : public printer {
int round_width (int x);
void handle_tag_within_title (text_glob *g);
void writeHeadMetaStyle (void);
+ void handle_valid_flag (void);
+ void do_math (text_glob *g);
+ void write_html_anchor (text_glob *h);
+ void write_xhtml_anchor (text_glob *h);
// ADD HERE
public:
@@ -2167,7 +2183,10 @@ void html_printer::end_of_line()
void html_printer::emit_line (text_glob *)
{
// --fixme-- needs to know the length in percentage
- html.put_string("<hr>");
+ if (dialect == xhtml)
+ html.put_string("<hr/>");
+ else
+ html.put_string("<hr>");
}
/*
@@ -2206,13 +2225,22 @@ void html_printer::emit_raw (text_glob *g)
switch (next_tag) {
case CENTERED:
- current_paragraph->do_para("align=center", space);
+ if (dialect == html4)
+ current_paragraph->do_para("align=\"center\"", space);
+ else
+ current_paragraph->do_para("class=\"center\"", space);
break;
case LEFT:
- current_paragraph->do_para(&html, "align=left", get_troff_indent(), pageoffset, linelength, space);
+ if (dialect == html4)
+ current_paragraph->do_para(&html, "align=\"left\"", get_troff_indent(), pageoffset, linelength, space);
+ else
+ current_paragraph->do_para(&html, "class=\"left\"", get_troff_indent(), pageoffset, linelength, space);
break;
case RIGHT:
- current_paragraph->do_para(&html, "align=right", get_troff_indent(), pageoffset, linelength, space);
+ if (dialect == html4)
+ current_paragraph->do_para(&html, "align=\"right\"", get_troff_indent(), pageoffset, linelength, space);
+ else
+ current_paragraph->do_para(&html, "class=\"right\"", get_troff_indent(), pageoffset, linelength, space);
break;
default:
fatal("unknown enumeration");
@@ -2308,9 +2336,12 @@ static string &generate_img_src (const char *filename)
while (filename && (filename[0] == ' ')) {
filename++;
}
- if (exists(filename))
+ if (exists(filename)) {
*s += string("<img src=\"") + filename + "\" "
+ "alt=\"Image " + filename + "\">";
+ if (dialect == xhtml)
+ *s += "</img>";
+ }
return *s;
}
@@ -2409,14 +2440,60 @@ void html_printer::do_title (void)
}
}
+/*
+ * write_html_anchor - writes out an anchor. The style of the anchor
+ * dependent upon simple_anchor.
+ */
+
+void html_printer::write_html_anchor (text_glob *h)
+{
+ if (dialect == html4) {
+ if (h != NULL) {
+ html.put_string("<a name=\"");
+ if (simple_anchors) {
+ string buffer(ANCHOR_TEMPLATE);
+
+ buffer += as_string(header.no_of_headings);
+ buffer += '\0';
+ html.put_string(buffer.contents());
+ } else
+ html.put_string(header.header_buffer);
+ html.put_string("\"></a>").nl();
+ }
+ }
+}
+
+/*
+ * write_xhtml_anchor - writes out an anchor. The style of the anchor
+ * dependent upon simple_anchor.
+ */
+
+void html_printer::write_xhtml_anchor (text_glob *h)
+{
+ if (dialect == xhtml) {
+ if (h != NULL) {
+ html.put_string(" id=\"");
+ if (simple_anchors) {
+ string buffer(ANCHOR_TEMPLATE);
+
+ buffer += as_string(header.no_of_headings);
+ buffer += '\0';
+ html.put_string(buffer.contents());
+ } else
+ html.put_string(header.header_buffer);
+ html.put_string("\"");
+ }
+ }
+}
+
void html_printer::write_header (void)
{
if (! header.header_buffer.empty()) {
+ text_glob *a = NULL;
int space = current_paragraph->retrieve_para_space() || seen_space;
- if (header.header_level > 7) {
+ if (header.header_level > 7)
header.header_level = 7;
- }
// firstly we must terminate any font and type faces
current_paragraph->done_para();
@@ -2427,33 +2504,22 @@ void html_printer::write_header (void)
header.no_of_headings++;
style st;
- text_glob *h=new text_glob();
- h->text_glob_html(&st,
+ a = new text_glob();
+ a->text_glob_html(&st,
header.headings.add_string(header.header_buffer),
header.header_buffer.length(),
header.no_of_headings, header.header_level,
header.no_of_headings, header.header_level);
- header.headers.add(h,
+ // and add this header to the header list
+ header.headers.add(a,
header.no_of_headings,
header.no_of_headings, header.no_of_headings,
- header.no_of_headings, header.no_of_headings); // and add this header to the header list
-
- // lastly we generate a tag
-
- html.nl().nl().put_string("<a name=\"");
- if (simple_anchors) {
- string buffer(ANCHOR_TEMPLATE);
-
- buffer += as_string(header.no_of_headings);
- buffer += '\0';
- html.put_string(buffer.contents());
- } else {
- html.put_string(header.header_buffer);
- }
- html.put_string("\"></a>").nl();
+ header.no_of_headings, header.no_of_headings);
}
+ html.nl().nl();
+
if (manufacture_headings) {
// line break before a header
if (!current_paragraph->emitted_text())
@@ -2462,11 +2528,14 @@ void html_printer::write_header (void)
if (header.header_level<4) {
html.put_string("<b><font size=\"+1\">");
html.put_string(header.header_buffer);
- html.put_string("</font></b>").nl();
+ html.put_string("</font>").nl();
+ write_html_anchor(a);
+ html.put_string("</b>").nl();
}
else {
html.put_string("<b>");
- html.put_string(header.header_buffer);
+ html.put_string(header.header_buffer).nl();
+ write_html_anchor(a);
html.put_string("</b>").nl();
}
}
@@ -2474,8 +2543,10 @@ void html_printer::write_header (void)
// and now we issue the real header
html.put_string("<h");
html.put_number(header.header_level);
+ write_xhtml_anchor(a);
html.put_string(">");
- html.put_string(header.header_buffer);
+ html.put_string(header.header_buffer).nl();
+ write_html_anchor(a);
html.put_string("</h");
html.put_number(header.header_level);
html.put_string(">").nl();
@@ -2810,10 +2881,15 @@ void html_printer::do_check_center(void)
int space = current_paragraph->retrieve_para_space() || seen_space;
current_paragraph->done_para();
supress_sub_sup = TRUE;
- current_paragraph->do_para("align=center", space);
+ if (dialect == html4)
+ current_paragraph->do_para("align=\"center\"", space);
+ else
+ current_paragraph->do_para("class=\"center\"", space);
} else
- if (strcmp("align=center",
- current_paragraph->get_alignment()) != 0) {
+ if ((strcmp("align=\"center\"",
+ current_paragraph->get_alignment()) != 0) &&
+ (strcmp("class=\"center\"",
+ current_paragraph->get_alignment()) != 0)) {
/*
* different alignment, so shutdown paragraph and open
* a new one.
@@ -2821,7 +2897,10 @@ void html_printer::do_check_center(void)
int space = current_paragraph->retrieve_para_space() || seen_space;
current_paragraph->done_para();
supress_sub_sup = TRUE;
- current_paragraph->do_para("align=center", space);
+ if (dialect == html4)
+ current_paragraph->do_para("align=\"center\"", space);
+ else
+ current_paragraph->do_para("class=\"center\"", space);
} else
/*
* same alignment, if we have emitted text then issue a break.
@@ -2898,7 +2977,10 @@ void html_printer::insert_split_file (void)
split_file += string("-");
split_file += as_string(header.no_of_level_one_headings);
- split_file += string(".html");
+ if (dialect == xhtml)
+ split_file += string(".xhtml");
+ else
+ split_file += string(".html");
split_file += '\0';
file_list.set_file_name(split_file);
@@ -3092,9 +3174,15 @@ void html_printer::troff_tag (text_glob *g)
* firstly skip over devtag:
*/
char *t=(char *)g->text_string+strlen("devtag:");
-
if (strncmp(g->text_string, "html</p>:", strlen("html</p>:")) == 0) {
do_end_para(g);
+ } else if (strncmp(g->text_string, "html<?p>:", strlen("html<?p>:")) == 0) {
+ if (current_paragraph->emitted_text())
+ html.put_string(g->text_string+9);
+ else
+ do_end_para(g);
+ } else if (strncmp(g->text_string, "math<?p>:", strlen("math<?p>:")) == 0) {
+ do_math(g);
} else if (g->is_eol()) {
do_eol();
} else if (g->is_eol_ce()) {
@@ -3177,6 +3265,19 @@ void html_printer::troff_tag (text_glob *g)
}
/*
+ * do_math - prints out the equation
+ */
+
+void html_printer::do_math (text_glob *g)
+{
+ do_font(g);
+ if (current_paragraph->emitted_text())
+ html.put_string(g->text_string+9);
+ else
+ do_end_para(g);
+}
+
+/*
* is_in_middle - returns TRUE if the positions left..right are in the center of the page.
*/
@@ -4720,7 +4821,10 @@ void html_printer::write_title (int in_head)
} else {
title.has_been_written = TRUE;
if (title.with_h1) {
- html.put_string("<h1 align=center>");
+ if (dialect == xhtml)
+ html.put_string("<h1>");
+ else
+ html.put_string("<h1 align=\"center\">");
html.put_string(title.text);
html.put_string("</h1>").nl().nl();
}
@@ -4737,8 +4841,12 @@ void html_printer::write_title (int in_head)
static void write_rule (void)
{
- if (auto_rule)
- fputs("<hr>\n", stdout);
+ if (auto_rule) {
+ if (dialect == xhtml)
+ fputs("<hr/>\n", stdout);
+ else
+ fputs("<hr>\n", stdout);
+ }
}
void html_printer::begin_page(int n)
@@ -4757,7 +4865,7 @@ void html_printer::begin_page(int n)
output_hpos = -1;
output_vpos = -1;
output_vpos_max = -1;
- current_paragraph = new html_text(&html);
+ current_paragraph = new html_text(&html, dialect);
do_indent(get_troff_indent(), pageoffset, linelength);
current_paragraph->do_para("", FALSE);
}
@@ -4815,7 +4923,13 @@ void html_printer::write_navigation (const string &top, const string &prev,
int need_bar = FALSE;
if (multiple_files) {
+ current_paragraph->done_para();
write_rule();
+ if (groff_sig)
+ fputs("\n\n<table width=\"100%\" border=\"0\" rules=\"none\"\n"
+ "frame=\"void\" cellspacing=\"1\" cellpadding=\"0\">\n"
+ "<colgroup><col class=\"left\"></col><col class=\"right\"></col></colgroup>\n"
+ "<tr><td class=\"left\">", stdout);
fputs("[ ", stdout);
if ((strcmp(prev.contents(), "") != 0) && prev != top && prev != current) {
emit_link(prev, "prev");
@@ -4833,6 +4947,16 @@ void html_printer::write_navigation (const string &top, const string &prev,
emit_link(top, "top");
}
fputs(" ]\n", stdout);
+ handle_valid_flag();
+
+ if (groff_sig) {
+ fputs("</td><td class=\"right\"><i><small>"
+ "This document was produced using "
+ "<a href=\"http://www.gnu.org/software/groff/\">"
+ "groff-", stdout);
+ fputs(Version_string, stdout);
+ fputs("</a>.</small></i></td></tr></table>\n", stdout);
+ }
write_rule();
}
}
@@ -4857,7 +4981,10 @@ void html_printer::do_file_components (void)
file_list.start_of_list();
top = string(job_name);
- top += string(".html");
+ if (dialect == xhtml)
+ top += string(".xhtml");
+ else
+ top += string(".html");
top += '\0';
next = file_list.next_file_name();
next += '\0';
@@ -4870,6 +4997,12 @@ void html_printer::do_file_components (void)
file_list.move_next();
if (file_list.is_new_output_file()) {
+#ifdef LONG_FOR_TIME_T
+ long t;
+#else
+ time_t t;
+#endif
+
if (fragment_no > 1)
write_navigation(top, prev, next, current);
prev = current;
@@ -4881,7 +5014,27 @@ void html_printer::do_file_components (void)
fflush(stdout);
freopen(split_file.contents(), "w", stdout);
fragment_no++;
- writeHeadMetaStyle();
+ if (dialect == xhtml)
+ writeHeadMetaStyle();
+
+ html.begin_comment("Creator : ")
+ .put_string("groff ")
+ .put_string("version ")
+ .put_string(Version_string)
+ .end_comment();
+
+ t = time(0);
+ html.begin_comment("CreationDate: ")
+ .put_string(ctime(&t), strlen(ctime(&t))-1)
+ .end_comment();
+
+ if (dialect == html4)
+ writeHeadMetaStyle();
+
+ html.put_string("<title>");
+ html.put_string(split_file.contents());
+ html.put_string("</title>").nl().nl();
+
fputs(head_info.contents(), stdout);
fputs("</head>\n", stdout);
write_navigation(top, prev, next, current);
@@ -4891,8 +5044,27 @@ void html_printer::do_file_components (void)
}
if (fragment_no > 1)
write_navigation(top, prev, next, current);
- else
+ else {
+ current_paragraph->done_para();
write_rule();
+ if (valid_flag && dialect == xhtml) {
+ if (groff_sig)
+ fputs("\n\n<table width=\"100%\" border=\"0\" rules=\"none\"\n"
+ "frame=\"void\" cellspacing=\"1\" cellpadding=\"0\">\n"
+ "<colgroup><col class=\"left\"></col><col class=\"right\"></col></colgroup>\n"
+ "<tr><td class=\"left\">", stdout);
+ handle_valid_flag();
+ if (groff_sig) {
+ fputs("</td><td class=\"right\"><i><small>"
+ "This document was produced using "
+ "<a href=\"http://www.gnu.org/software/groff/\">"
+ "groff-", stdout);
+ fputs(Version_string, stdout);
+ fputs("</a>.</small></i></td></tr></table>\n", stdout);
+ }
+ write_rule();
+ }
+ }
}
/*
@@ -4902,21 +5074,43 @@ void html_printer::do_file_components (void)
void html_printer::writeHeadMetaStyle (void)
{
- fputs("<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\n", stdout);
- fputs("\"http://www.w3.org/TR/html4/loose.dtd\">\n", stdout);
-
- fputs("<html>\n", stdout);
- fputs("<head>\n", stdout);
- fputs("<meta name=\"generator\" "
- "content=\"groff -Thtml, see www.gnu.org\">\n", stdout);
- fputs("<meta http-equiv=\"Content-Type\" "
- "content=\"text/html; charset=US-ASCII\">\n", stdout);
- fputs("<meta name=\"Content-Style\" content=\"text/css\">\n", stdout);
-
- fputs("<style type=\"text/css\">\n", stdout);
- fputs(" p { margin-top: 0; margin-bottom: 0; }\n", stdout);
- fputs(" pre { margin-top: 0; margin-bottom: 0; }\n", stdout);
- fputs(" table { margin-top: 0; margin-bottom: 0; }\n", stdout);
+ if (dialect == html4) {
+ fputs("<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\n", stdout);
+ fputs("\"http://www.w3.org/TR/html4/loose.dtd\">\n", stdout);
+ fputs("<html>\n", stdout);
+ fputs("<head>\n", stdout);
+ fputs("<meta name=\"generator\" "
+ "content=\"groff -Thtml, see www.gnu.org\">\n", stdout);
+ fputs("<meta http-equiv=\"Content-Type\" "
+ "content=\"text/html; charset=US-ASCII\">\n", stdout);
+ fputs("<meta name=\"Content-Style\" content=\"text/css\">\n", stdout);
+ fputs("<style type=\"text/css\">\n", stdout);
+ }
+ else {
+ fputs("<?xml version=\"1.0\" encoding=\"us-ascii\"?>\n", stdout);
+ fputs("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1 plus MathML 2.0//EN\"\n", stdout);
+ fputs(" \"http://www.w3.org/TR/MathML2/dtd/xhtml-math11-f.dtd\"\n", stdout);
+ fputs(" [<!ENTITY mathml \"http://www.w3.org/1998/Math/MathML\">]>\n", stdout);
+
+ fputs("<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\">\n",
+ stdout);
+ fputs("<head>\n", stdout);
+ fputs("<meta name=\"generator\" "
+ "content=\"groff -Txhtml, see www.gnu.org\"/>\n", stdout);
+ fputs("<meta http-equiv=\"Content-Type\" "
+ "content=\"text/html; charset=US-ASCII\"/>\n", stdout);
+ fputs("<meta name=\"Content-Style\" content=\"text/css\"/>\n", stdout);
+ fputs("<style type=\"text/css\">\n", stdout);
+ fputs(" .center { text-align: center }\n", stdout);
+ fputs(" .right { text-align: right }\n", stdout);
+ }
+ fputs(" p { margin-top: 0; margin-bottom: 0; "
+ "vertical-align=\"top\" }\n", stdout);
+ fputs(" pre { margin-top: 0; margin-bottom: 0; "
+ "vertical-align=\"top\" }\n", stdout);
+ fputs(" table { margin-top: 0; margin-bottom: 0; "
+ "vertical-align=\"top\" }\n", stdout);
+ fputs(" h1 { text-align: center }\n", stdout);
fputs("</style>\n", stdout);
}
@@ -4932,6 +5126,10 @@ html_printer::~html_printer()
current_paragraph->flush_text();
html.end_line();
html.set_file(stdout);
+
+ if (dialect == xhtml)
+ writeHeadMetaStyle();
+
html.begin_comment("Creator : ")
.put_string("groff ")
.put_string("version ")
@@ -4943,7 +5141,8 @@ html_printer::~html_printer()
.put_string(ctime(&t), strlen(ctime(&t))-1)
.end_comment();
- writeHeadMetaStyle();
+ if (dialect == html4)
+ writeHeadMetaStyle();
write_title(TRUE);
head_info += '\0';
@@ -5123,9 +5322,12 @@ void html_printer::special(char *s, const environment *env, char type)
* requesting that the formatting move right by the appropriate
* amount.
*/
- } else if (strncmp(s, "html</p>:", 9) == 0) {
+ } else if ((strncmp(s, "html</p>:", 9) == 0) ||
+ (strncmp(s, "html<?p>:", 9) == 0) ||
+ (strncmp(s, "math<?p>:", 9) == 0)) {
int r=font::res; /* resolution of the device */
font *f=sbuf_style.f;
+ string t;
if (f == NULL) {
int found=FALSE;
@@ -5133,6 +5335,17 @@ void html_printer::special(char *s, const environment *env, char type)
f = font::load_font("TR", &found);
}
+ if (strncmp(s, "math<?p>:", 9) == 0) {
+ if (strncmp((char *)&s[9], "<math>", 6) == 0) {
+ s[9] = '\0';
+ t = s;
+ t += "<math xmlns=\"http://www.w3.org/1998/Math/MathML\">";
+ t += (char *)&s[15];
+ t += '\0';
+ s = (char *)&t[0];
+ }
+ }
+
/*
* need to pass all of string through to html output during flush
*/
@@ -5148,6 +5361,7 @@ void html_printer::special(char *s, const environment *env, char type)
* requesting that the formatting move right by the appropriate
* amount.
*/
+
} else if (strncmp(s, "index:", 6) == 0) {
cutoff_heading = atoi(&s[6]);
} else if (strncmp(s, "assertion:[", 11) == 0) {
@@ -5211,6 +5425,21 @@ int html_printer::round_width(int x)
return n * r;
}
+/*
+ * handle_valid_flag - emits a valid xhtml 1.1 button, provided -V and -x
+ * were supplied on the command line.
+ */
+
+void html_printer::handle_valid_flag (void)
+{
+ if (valid_flag && dialect == xhtml)
+ fputs("<p>"
+ "<a href=\"http://validator.w3.org/check?uri=referer\"><img "
+ "src=\"http://www.w3.org/Icons/valid-xhtml11\" "
+ "alt=\"Valid XHTML 1.1 Transitional\" height=\"31\" width=\"88\" /></a>\n"
+ "</p>\n", stdout);
+}
+
int main(int argc, char **argv)
{
program_name = argv[0];
@@ -5222,7 +5451,7 @@ int main(int argc, char **argv)
{ "version", no_argument, 0, 'v' },
{ NULL, 0, 0, 0 }
};
- while ((c = getopt_long(argc, argv, "a:bdD:F:g:hi:I:j:lno:prs:S:v",
+ while ((c = getopt_long(argc, argv, "a:bdD:eF:g:hi:I:j:lno:prs:S:vVx:y",
long_options, NULL))
!= EOF)
switch(c) {
@@ -5240,6 +5469,9 @@ int main(int argc, char **argv)
case 'D':
/* handled by pre-html */
break;
+ case 'e':
+ /* handled by pre-html */
+ break;
case 'F':
font::command_line_font_dir(optarg);
break;
@@ -5285,6 +5517,21 @@ int main(int argc, char **argv)
printf("GNU post-grohtml (groff) version %s\n", Version_string);
exit(0);
break;
+ case 'V':
+ valid_flag = TRUE;
+ break;
+ case 'x':
+ if (strcmp(optarg, "x") == 0) {
+ dialect = xhtml;
+ simple_anchors = TRUE;
+ } else if (strcmp(optarg, "4") == 0)
+ dialect = html4;
+ else
+ printf("unsupported html dialect %s (defaulting to html4)\n", optarg);
+ break;
+ case 'y':
+ groff_sig = TRUE;
+ break;
case CHAR_MAX + 1: // --help
usage(stdout);
exit(0);
@@ -5307,6 +5554,6 @@ int main(int argc, char **argv)
static void usage(FILE *stream)
{
- fprintf(stream, "usage: %s [-vblnh] [-D dir] [-I image_stem] [-F dir] [files ...]\n",
+ fprintf(stream, "usage: %s [-vbelnhVy] [-D dir] [-I image_stem] [-F dir] [-x x] [files ...]\n",
program_name);
}
diff --git a/src/preproc/eqn/box.cpp b/src/preproc/eqn/box.cpp
index 9067302b..6ca528a5 100644
--- a/src/preproc/eqn/box.cpp
+++ b/src/preproc/eqn/box.cpp
@@ -237,7 +237,7 @@ void output_string()
{
if (output_format == troff)
printf("\\*(" LINE_STRING "\n");
- else if (output_format == mathml)
+ else if (output_format == mathml && !xhtml)
putchar('\n');
}
@@ -254,8 +254,11 @@ void do_text(const char *s)
printf(".as " LINE_STRING " \"%s\n", s);
printf(".ec\n");
}
- else if (output_format == mathml)
+ else if (output_format == mathml) {
fputs(s, stdout);
+ if (xhtml && strlen(s) > 0)
+ printf("\n");
+ }
}
void set_minimum_size(int n)
@@ -349,6 +352,8 @@ void box::top_level()
b->uid, body_height, b->uid, body_depth);
}
else if (output_format == mathml) {
+ if (xhtml)
+ printf(".MATHML ");
printf("<math>");
b->output();
printf("</math>");
diff --git a/src/preproc/eqn/eqn.h b/src/preproc/eqn/eqn.h
index 8d655b38..e9eed1c1 100644
--- a/src/preproc/eqn/eqn.h
+++ b/src/preproc/eqn/eqn.h
@@ -41,6 +41,7 @@ extern int one_size_reduction_flag;
extern int compatible_flag;
extern int nroff;
extern eqnmode_t output_format;
+extern int xhtml;
void init_lex(const char *str, const char *filename, int lineno);
void lex_error(const char *message,
diff --git a/src/preproc/eqn/main.cpp b/src/preproc/eqn/main.cpp
index 9bd3ce3b..9794943c 100644
--- a/src/preproc/eqn/main.cpp
+++ b/src/preproc/eqn/main.cpp
@@ -45,6 +45,7 @@ int one_size_reduction_flag = 0;
int compatible_flag = 0;
int no_newline_in_delim_flag = 0;
int html = 0;
+int xhtml = 0;
eqnmode_t output_format;
int read_line(FILE *fp, string *p)
@@ -188,6 +189,13 @@ static int inline_equation(FILE *fp, string &linebuf, string &str)
html_end_suppress();
printf("\n");
}
+ if (output_format == mathml)
+ printf("\n");
+ if (xhtml) {
+ /* skip leading spaces */
+ while ((*ptr != '\0') && (*ptr == ' '))
+ ptr++;
+ }
start = delim_search(ptr, start_delim);
if (start == 0) {
char *nl = strchr(ptr, '\n');
@@ -314,6 +322,12 @@ int main(int argc, char **argv)
output_format = mathml;
load_startup_file = 0;
}
+ else if (strcmp(device, "mathml:xhtml") == 0) {
+ device = "MathML";
+ output_format = mathml;
+ load_startup_file = 0;
+ xhtml = 1;
+ }
break;
case 's':
if (!set_gsize(optarg))
diff --git a/src/preproc/eqn/text.cpp b/src/preproc/eqn/text.cpp
index 84dc873f..8563199a 100644
--- a/src/preproc/eqn/text.cpp
+++ b/src/preproc/eqn/text.cpp
@@ -57,7 +57,7 @@ struct map entity_table[] = {
{"*L", "&Lambda;"}, // ISOgrk3
{"*m", "&mu;"}, // ISOgrk3
{"*M", "M"},
- {"*n", "&nu"}, // ISOgrk3
+ {"*n", "&nu;"}, // ISOgrk3
{"*N", "N"},
{"*o", "o"},
{"*O", "O"},
diff --git a/src/preproc/html/pre-html.cpp b/src/preproc/html/pre-html.cpp
index ec5c29b6..1b7112fc 100644
--- a/src/preproc/html/pre-html.cpp
+++ b/src/preproc/html/pre-html.cpp
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 2000, 2001, 2002, 2003, 2004
+/* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2007
* Free Software Foundation, Inc.
* Written by Gaius Mulley (gaius@glam.ac.uk).
*
@@ -56,6 +56,10 @@
#include "nonposix.h"
+#if 0
+# define DEBUGGING
+#endif
+
/* Establish some definitions to facilitate discrimination between
differing runtime environments. */
@@ -162,10 +166,6 @@ extern "C" const char *Version_string;
#define REGION_TEMPLATE_SHORT "rg"
#define REGION_TEMPLATE_LONG "-regions-"
-#if 0
-# define DEBUGGING
-#endif
-
#if !defined(TRUE)
# define TRUE (1==1)
#endif
@@ -177,6 +177,8 @@ typedef enum {
CENTERED, LEFT, RIGHT, INLINE
} IMAGE_ALIGNMENT;
+typedef enum {xhtml, html4} html_dialect;
+
static int postscriptRes = -1; // postscript resolution,
// dots per inch
static int stdoutfd = 1; // output file descriptor -
@@ -210,6 +212,7 @@ static char *troffFileName = NULL; // output of pre-html output which
static char *htmlFileName = NULL; // output of pre-html output which
// is sent to troff -Thtml
#endif
+static int eqn_flag = FALSE; // must we preprocess via eqn?
static char *linebuf = NULL; // for scanning devps/DESC
static int linebufsize = 0;
@@ -217,6 +220,7 @@ static const char *image_gen = NULL; // the `gs' program
const char *const FONT_ENV_VAR = "GROFF_FONT_PATH";
static search_path font_path(FONT_ENV_VAR, FONTPATH, 0, 0);
+static html_dialect dialect = html4;
/*
@@ -313,28 +317,37 @@ static unsigned int get_resolution(void)
void html_system(const char *s, int redirect_stdout)
{
- // Redirect standard error to the null device. This is more
- // portable than using "2> /dev/null", since it doesn't require a
- // Unixy shell.
- int save_stderr = dup(2);
- int save_stdout = dup(1);
- int fdnull = open(NULL_DEV, O_WRONLY|O_BINARY, 0666);
- if (save_stderr > 2 && fdnull > 2)
- dup2(fdnull, 2);
- if (redirect_stdout && save_stdout > 1 && fdnull > 1)
- dup2(fdnull, 1);
- if (fdnull >= 0)
- close(fdnull);
- int status = system(s);
- dup2(save_stderr, 2);
- if (redirect_stdout)
- dup2(save_stdout, 1);
- if (status == -1)
- fprintf(stderr, "Calling `%s' failed\n", s);
- else if (status)
- fprintf(stderr, "Calling `%s' returned status %d\n", s, status);
- close(save_stderr);
- close(save_stdout);
+#if defined(DEBUGGING)
+ if (debug) {
+ fprintf(stderr, "executing: ");
+ fwrite(s, sizeof(char), strlen(s), stderr);
+ fflush(stderr);
+ }
+#endif
+ {
+ // Redirect standard error to the null device. This is more
+ // portable than using "2> /dev/null", since it doesn't require a
+ // Unixy shell.
+ int save_stderr = dup(2);
+ int save_stdout = dup(1);
+ int fdnull = open(NULL_DEV, O_WRONLY|O_BINARY, 0666);
+ if (save_stderr > 2 && fdnull > 2)
+ dup2(fdnull, 2);
+ if (redirect_stdout && save_stdout > 1 && fdnull > 1)
+ dup2(fdnull, 1);
+ if (fdnull >= 0)
+ close(fdnull);
+ int status = system(s);
+ dup2(save_stderr, 2);
+ if (redirect_stdout)
+ dup2(save_stdout, 1);
+ if (status == -1)
+ fprintf(stderr, "Calling `%s' failed\n", s);
+ else if (status)
+ fprintf(stderr, "Calling `%s' returned status %d\n", s, status);
+ close(save_stderr);
+ close(save_stdout);
+ }
}
/*
@@ -921,12 +934,6 @@ int imageList::createPage(int pageno)
if (s == NULL)
sys_fatal("make_message");
-#if defined(DEBUGGING)
- if (debug) {
- fwrite(s, sizeof(char), strlen(s), stderr);
- fflush(stderr);
- }
-#endif
html_system(s, 1);
s = make_message("echo showpage | "
@@ -945,12 +952,6 @@ int imageList::createPage(int pageno)
psPageName);
if (s == NULL)
sys_fatal("make_message");
-#if defined(DEBUGGING)
- if (debug) {
- fwrite(s, sizeof(char), strlen(s), stderr);
- fflush(stderr);
- }
-#endif
html_system(s, 1);
free(s);
currentPageNo = pageno;
@@ -1031,12 +1032,6 @@ void imageList::createImage(imageItem *i)
if (s == NULL)
sys_fatal("make_message");
-#if defined(DEBUGGING)
- if (debug) {
- fprintf(stderr, s);
- fflush(stderr);
- }
-#endif
html_system(s, 0);
free(s);
}
@@ -1201,7 +1196,8 @@ static void alterDeviceTo(int argc, char *argv[], int toImage)
if (toImage) {
while (i < argc) {
- if (strcmp(argv[i], "-Thtml") == 0)
+ if ((strcmp(argv[i], "-Thtml") == 0) ||
+ (strcmp(argv[i], "-Txhtml") == 0))
argv[i] = (char *)IMAGE_DEVICE;
i++;
}
@@ -1210,7 +1206,10 @@ static void alterDeviceTo(int argc, char *argv[], int toImage)
else {
while (i < argc) {
if (strcmp(argv[i], IMAGE_DEVICE) == 0)
- argv[i] = (char *)"-Thtml";
+ if (dialect == xhtml)
+ argv[i] = (char *)"-Txhtml";
+ else
+ argv[i] = (char *)"-Thtml";
i++;
}
argv[troff_arg] = (char *)"groff"; /* use groff -Z */
@@ -1218,10 +1217,10 @@ static void alterDeviceTo(int argc, char *argv[], int toImage)
}
/*
- * addZ - Append -Z onto the command list for groff.
+ * addArg - Append newarg onto the command list for groff.
*/
-char **addZ(int argc, char *argv[])
+char **addArg(int argc, char *argv[], char *newarg)
{
char **new_argv = (char **)malloc((argc + 2) * sizeof(char *));
int i = 0;
@@ -1233,7 +1232,7 @@ char **addZ(int argc, char *argv[])
new_argv[i] = argv[i];
i++;
}
- new_argv[i] = (char *)"-Z";
+ new_argv[i] = newarg;
while (i < argc) {
new_argv[i + 1] = argv[i];
i++;
@@ -1278,12 +1277,37 @@ void dump_args(int argc, char *argv[])
fprintf(stderr, "\n");
}
-int char_buffer::run_output_filter(int filter, int /* argc */, char **argv)
+/*
+ * print_args - print arguments as if they were issued on the command line.
+ */
+
+#if defined(DEBUGGING)
+
+void print_args(int argc, char *argv[])
+{
+ if (debug) {
+ fprintf(stderr, "executing: ");
+ for (int i = 0; i < argc; i++)
+ fprintf(stderr, "%s ", argv[i]);
+ fprintf(stderr, "\n");
+ }
+}
+
+#else
+
+void print_args(int, char **)
+{
+}
+
+#endif
+
+int char_buffer::run_output_filter(int filter, int argc, char **argv)
{
int pipedes[2];
PID_T child_pid;
int status;
+ print_args(argc, argv);
if (pipe(pipedes) < 0)
sys_fatal("pipe");
@@ -1441,16 +1465,25 @@ int char_buffer::do_html(int argc, char *argv[])
alterDeviceTo(argc, argv, 0);
argv += troff_arg; // skip all arguments up to groff
argc -= troff_arg;
- argv = addZ(argc, argv);
+ argv = addArg(argc, argv, (char *)"-Z");
argc++;
- s = "-dwww-image-template=";
+ s = (char *)"-dwww-image-template=";
s += macroset_template; // do not combine these statements,
// otherwise they will not work
s += '\0'; // the trailing `\0' is ignored
argv = addRegDef(argc, argv, s.contents());
argc++;
+ if (dialect == xhtml) {
+ argv = addRegDef(argc, argv, "-rxhtml=1");
+ argc++;
+ if (eqn_flag) {
+ argv = addRegDef(argc, argv, "-e");
+ argc++;
+ }
+ }
+
#if defined(DEBUGGING)
# define HTML_DEBUG_STREAM OUTPUT_STREAM(htmlFileName)
// slight security risk so only enabled if compiled with defined(DEBUGGING)
@@ -1488,6 +1521,15 @@ int char_buffer::do_image(int argc, char *argv[])
argv = addRegDef(argc, argv, "-P-pletter");
argc++;
+ if (dialect == xhtml) {
+ if (eqn_flag) {
+ argv = addRegDef(argc, argv, "-rxhtml=1");
+ argc++;
+ }
+ argv = addRegDef(argc, argv, "-e");
+ argc++;
+ }
+
#if defined(DEBUGGING)
# define IMAGE_DEBUG_STREAM OUTPUT_STREAM(troffFileName)
// slight security risk so only enabled if compiled with defined(DEBUGGING)
@@ -1547,7 +1589,7 @@ static int scanArguments(int argc, char **argv)
{ "version", no_argument, 0, 'v' },
{ NULL, 0, 0, 0 }
};
- while ((c = getopt_long(argc, argv, "+a:bdD:F:g:hi:I:j:lno:prs:S:v",
+ while ((c = getopt_long(argc, argv, "+a:bdD:eF:g:hi:I:j:lno:prs:S:vVx:y",
long_options, NULL))
!= EOF)
switch(c) {
@@ -1570,6 +1612,9 @@ static int scanArguments(int argc, char **argv)
case 'D':
image_dir = optarg;
break;
+ case 'e':
+ eqn_flag = TRUE;
+ break;
case 'F':
font_path.command_line_dir(optarg);
break;
@@ -1617,6 +1662,21 @@ static int scanArguments(int argc, char **argv)
case 'v':
printf("GNU pre-grohtml (groff) version %s\n", Version_string);
exit(0);
+ case 'V':
+ // handled by post-grohtml (create validator button)
+ break;
+ case 'x':
+ // html dialect
+ if (strcmp(optarg, "x") == 0)
+ dialect = xhtml;
+ else if (strcmp(optarg, "4") == 0)
+ dialect = html4;
+ else
+ printf("unsupported html dialect %s (defaulting to html4)\n", optarg);
+ break;
+ case 'y':
+ // handled by post-grohtml (create groff signature)
+ break;
case CHAR_MAX + 1: // --help
usage(stdout);
exit(0);
diff --git a/src/roff/groff/groff.cpp b/src/roff/groff/groff.cpp
index 748715c7..2930ebee 100644
--- a/src/roff/groff/groff.cpp
+++ b/src/roff/groff/groff.cpp
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 1989-2000, 2001, 2002, 2003, 2004, 2005, 2006
+/* Copyright (C) 1989-2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
@@ -74,6 +74,7 @@ class possible_command {
public:
possible_command();
~possible_command();
+ void clear_name();
void set_name(const char *);
void set_name(const char *, const char *);
const char *get_name();
@@ -119,6 +120,8 @@ int main(int argc, char **argv)
int Xflag = 0;
int oflag = 0;
int safer_flag = 1;
+ int is_xhtml = 0;
+ int eflag = 0;
int opt;
const char *command_prefix = getenv("GROFF_COMMAND_PREFIX");
const char *encoding = getenv("GROFF_ENCODING");
@@ -173,6 +176,7 @@ int main(int argc, char **argv)
commands[GRAP_INDEX].set_name(command_prefix, "grap");
break;
case 'e':
+ eflag = 1;
commands[EQN_INDEX].set_name(command_prefix, "eqn");
break;
case 's':
@@ -237,10 +241,21 @@ int main(int argc, char **argv)
safer_flag = 0;
break;
case 'T':
- if (strcmp(optarg, "html") == 0) {
+ if (strcmp(optarg, "xhtml") == 0) {
// force soelim to aid the html preprocessor
commands[SOELIM_INDEX].set_name(command_prefix, "soelim");
+ Pargs += "-x";
+ Pargs += '\0';
+ Pargs += 'x';
+ Pargs += '\0';
+ is_xhtml = 1;
+ device = "html";
+ break;
}
+ if (strcmp(optarg, "html") == 0)
+ // force soelim to aid the html preprocessor
+ commands[SOELIM_INDEX].set_name(command_prefix, "soelim");
+
if (strcmp(optarg, "Xps") == 0) {
warning("-TXps option is obsolete: use -X -Tps instead");
device = "ps";
@@ -313,6 +328,8 @@ int main(int argc, char **argv)
commands[TROFF_INDEX].set_name(predriver);
// pass the device arguments to the predrivers as well
commands[TROFF_INDEX].insert_args(Pargs);
+ if (eflag && is_xhtml)
+ commands[TROFF_INDEX].insert_arg("-e");
if (vflag)
commands[TROFF_INDEX].insert_arg("-v");
}
@@ -371,11 +388,21 @@ int main(int argc, char **argv)
commands[SPOOL_INDEX].set_name(0);
}
commands[TROFF_INDEX].append_arg("-T", device);
- // html renders equations as images via ps
if (strcmp(device, "html") == 0) {
- if (oflag)
- fatal("`-o' option is invalid with device `html'");
- commands[EQN_INDEX].append_arg("-Tps:html");
+ if (is_xhtml) {
+ if (oflag)
+ fatal("`-o' option is invalid with device `xhtml'");
+ if (zflag)
+ commands[EQN_INDEX].append_arg("-Tmathml:xhtml");
+ else if (eflag)
+ commands[EQN_INDEX].clear_name();
+ }
+ else {
+ if (oflag)
+ fatal("`-o' option is invalid with device `html'");
+ // html renders equations as images via ps
+ commands[EQN_INDEX].append_arg("-Tps:html");
+ }
}
else
commands[EQN_INDEX].append_arg("-T", device);
@@ -542,6 +569,14 @@ void possible_command::set_name(const char *s)
name = strsave(s);
}
+void possible_command::clear_name()
+{
+ a_delete name;
+ a_delete argv;
+ name = NULL;
+ argv = NULL;
+}
+
void possible_command::set_name(const char *s1, const char *s2)
{
a_delete name;
diff --git a/src/roff/troff/input.cpp b/src/roff/troff/input.cpp
index 397f2ba4..414bad8b 100644
--- a/src/roff/troff/input.cpp
+++ b/src/roff/troff/input.cpp
@@ -7757,6 +7757,7 @@ void init_input_requests()
number_reg_dictionary.define(".$", new nargs_reg);
number_reg_dictionary.define(".br", new break_flag_reg);
number_reg_dictionary.define(".C", new constant_int_reg(&compatible_flag));
+ number_reg_dictionary.define(".O", new variable_reg(&begin_level));
number_reg_dictionary.define(".c", new lineno_reg);
number_reg_dictionary.define(".color", new constant_int_reg(&color_flag));
number_reg_dictionary.define(".F", new filename_reg);
diff --git a/tmac/s.tmac b/tmac/s.tmac
index ba392797..c873e158 100644
--- a/tmac/s.tmac
+++ b/tmac/s.tmac
@@ -221,6 +221,7 @@ Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA.
. ps \\n[PS]
.\}
..
+.
.de LP
.if !'\\n[.z]'' \{\
. br
@@ -229,8 +230,9 @@ Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA.
.br
.cov*ab-init
.cov*print
-\\*[\\$0]\\
+.nop \\*[\\$0]\\
..
+.
.als IP LP
.als PP LP
.als XP LP
@@ -241,6 +243,7 @@ Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA.
.als MC LP
.als RT LP
.als XS LP
+.
.de cov*ab-init
.als cov*ab-init @nop
.als LP @LP
@@ -265,6 +268,7 @@ Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA.
.als AI par@AI
.als TL par@TL
..
+.
.de @AB
.if !'\\n(.z'' \{\
. br
@@ -342,7 +346,7 @@ Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA.
.cov*tl-au-print
.sp 3
.if d cov*ab-div \{\
-. if !'\*(.T'html' . nf
+. if !'\*(.T'html' .nf
. cov*ab-div
.\}
.sp 3
@@ -1691,12 +1695,12 @@ Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA.
.\}
.di eqn*div
.in 0
-.if \\n[eqn*type]=0 .HTML-IMAGE-LEFT
+.if \\n[eqn*type]=0 .EQN-HTML-IMAGE-LEFT
.if \\n[eqn*type]=1 \{\
. if '\*(.T'html' .RS
-. HTML-IMAGE-INLINE
+.EQN-HTML-IMAGE-INLINE
.\}
-.if \\n[eqn*type]=2 .HTML-IMAGE
+.if \\n[eqn*type]=2 .EQN-HTML-IMAGE
.nf
..
.de @div-end!eqn*div
@@ -1744,20 +1748,21 @@ Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA.
. \}
. el \{
.\" must terminate empty equations in html and ps4html as they contain
-.\" the HTML-IMAGE-END suppression nodes
+.\" the EQN-HTML-IMAGE-END suppression nodes
. if \\n[dl] .chop eqn*div
. if '\*(.T'html' \\*[eqn*div]
. if r ps4html \\*[eqn*div]
. \}
. if !'\*(.T'html' .fi
-. if \\n[eqn*type]=0 .HTML-IMAGE-END
+. if \\n[eqn*type]=0 .EQN-HTML-IMAGE-END
. if \\n[eqn*type]=1 \{\
-. HTML-IMAGE-END
+. EQN-HTML-IMAGE-END
. if '\*(.T'html' .RE
. \}
-. if \\n[eqn*type]=2 .HTML-IMAGE-END
+. if \\n[eqn*type]=2 .EQN-HTML-IMAGE-END
.\}
..
+.
.\" ****************************
.\" ******** module tbl ********
.\" ****************************
@@ -2065,35 +2070,21 @@ Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA.
.ds ! \(r!\" upside down !
..
.de CHECK-FOOTER-AND-KEEP
-.\" it might be better to als FS -> B1 and FE -> B2
-.\" however this produced wierd results, so I've moved back to a more reliable
-.\" but less interesting solution --fixme--
-. if '\*(.T'html' \{\
-. rm KF
-. als KF KS
-. rm FS
-. de FS
-. br
-. HTML-IMAGE
-\\..
-. rm FE
-. de FE
-. br
-. HTML-IMAGE-END
-\\..
-. \}
-. if r ps4html \{\
-. rm FS
-. de FS
-. br
-. HTML-IMAGE
+.if '\*(.T'html' \{\
+. rm KF
+. als KF KS
+.
+. rm FS
+. de FS
+. sp
+. HTML-NS <cite>
\\..
-. rm FE
-. de FE
-. br
-. HTML-IMAGE-END
+. rm FE
+. de FE
+. HTML-NS </cite>
+. sp
\\..
-. \}
+.\}
..
.par@load-init
.\" ****************************
diff --git a/tmac/troffrc-end b/tmac/troffrc-end
index 53f1bef5..d8ff8b0d 100644
--- a/tmac/troffrc-end
+++ b/tmac/troffrc-end
@@ -8,12 +8,19 @@
.do if r ps4html .do mso www.tmac
.
.\" for all other devices blank out these macros
-.do if !d HTML-IMAGE-INLINE .do ds HTML-IMAGE-INLINE
-.do if !d HTML-IMAGE .do ds HTML-IMAGE
-.do if !d HTML-IMAGE-RIGHT .do ds HTML-IMAGE-RIGHT
-.do if !d HTML-IMAGE-LEFT .do ds HTML-IMAGE-LEFT
-.do if !d HTML-IMAGE-END .do ds HTML-IMAGE-END
-.do if !d DEVTAG .do ds DEVTAG
-.do if !d HTML-DO-IMAGE .do ds HTML-DO-IMAGE
+.do if !d HTML-IMAGE-INLINE .do ds HTML-IMAGE-INLINE
+.do if !d HTML-IMAGE .do ds HTML-IMAGE
+.do if !d HTML-IMAGE-RIGHT .do ds HTML-IMAGE-RIGHT
+.do if !d HTML-IMAGE-LEFT .do ds HTML-IMAGE-LEFT
+.do if !d HTML-IMAGE-END .do ds HTML-IMAGE-END
+.do if !d DEVTAG .do ds DEVTAG
+.do if !d HTML-DO-IMAGE .do ds HTML-DO-IMAGE
+.do if !d EQN-HTML-IMAGE-END .do ds EQN-HTML-IMAGE-END
+.do if !d EQN-HTML-IMAGE .do ds EQN-HTML-IMAGE
+.do if !d EQN-HTML-IMAGE-RIGHT .do ds EQN-HTML-IMAGE-RIGHT
+.do if !d EQN-HTML-IMAGE-LEFT .do ds EQN-HTML-IMAGE-LEFT
+.do if !d EQN-HTML-IMAGE-INLINE .do ds EQN-HTML-IMAGE-INLINE
+.do if !d EQN-HTML-DO-IMAGE .do ds EQN-HTML-DO-IMAGE
+.do if !d EQN-HTML-IMAGE-END .do ds EQN-HTML-IMAGE-END
.
.\" Don't let blank lines creep in here.
diff --git a/tmac/www.tmac b/tmac/www.tmac
index 506b0ba6..d1c07936 100644
--- a/tmac/www.tmac
+++ b/tmac/www.tmac
@@ -301,6 +301,26 @@ www functionality. It should work with any macro set.
. \}
..
.
+.\"
+.\" emit an HTML tag. If text has been written in the paragraph
+.\" then do not shut the paragraph down.
+.\" If text was not written, remove the empty
+.\" paragraph tag and emit the desired html tag.
+.\"
+.de HTML<?p>
+. if \\n[www-html] .nop \&\X^html<?p>:\\$*^
+..
+.
+.\"
+.\" emit a MATH tag. If text has been written in the paragraph
+.\" then do not shut the paragraph down.
+.\" If text was not written, remove the empty
+.\" paragraph tag and emit the desired math tag.
+.\"
+.de MATH<?p>
+. if \\n[www-html] .nop \&\X^math<?p>:\\$*^
+..
+.
.\" --------------------------------------------------------------------
.\" HX n
.\"
@@ -490,7 +510,8 @@ www functionality. It should work with any macro set.
. if !'\\$4'' \
. nr www-height \\$4
. HTML <img src="\\$1" alt="Image \\$1" \
- width=\\n[www-width] height=\\n[www-height]>
+ "width=""\\n[www-width]""" \
+ "height=""\\n[www-height]"""></img>
. \}
. el \
. nop \\*[www:open]\f[\\*[www:fontstyle]]\\$1\f[]\\*[www:close]
@@ -537,22 +558,22 @@ www functionality. It should work with any macro set.
. ie (\\n[www-width] == 0) \{\
. ie (\\n[www-height] == 0) \
. HTML</p> <p \\*[www-htmlalign]><img "src=""\\$1""" \
- "alt=""Image \\$1""></p>"
+ "alt=""Image \\$1"""></img></p>"
. el \
. HTML</p> <p \\*[www-htmlalign]><img "src=""\\$1""" \
"alt=""Image \\$1""" \
- height=\\n[www-height]></p>
+ "height=""\\n[www-height]"""></img></p>
. \}
. el \{\
. ie (\\n[www-height] == 0) \
. HTML</p> <p \\*[www-htmlalign]><img "src=""\\$1""" \
"alt=""Image \\$1""" \
- width=\\n[www-width]></p>
+ "width=""\\n[www-width]"""></img></p>
. el \
. HTML</p> <p \\*[www-htmlalign]><img "src=""\\$1""" \
"alt=""Image \\$1""" \
- width=\\n[www-width] \
- height=\\n[www-height]></p>
+ "width=""\\n[www-width]""" \
+ "height=""\\n[www-height]"""></img></p>
. \}
. \}
. el \{\
@@ -687,7 +708,7 @@ www functionality. It should work with any macro set.
.
. nr www-width 1i
. nr www-height 1i
-. ds www-size-specs width=\\n[www-width] height=\\n[www-height]\"
+. ds www-size-specs width=""\\n[www-width]" height="\\n[www-height]"
. ie !'\\$2'' \{\
. nr www-is-absolute 0
. nr www-absolute 0
@@ -698,13 +719,13 @@ www functionality. It should work with any macro set.
. nr www-width (\\n[www-absolute] * \\n[.l] / 100)
. if \\n[www-html] \
. nr www-width (\\n[www-width] * 100 / 240)
-. ds www-size-specs width=\\*[www-percentage]\"
+. ds www-size-specs width=\"\\*[www-percentage]"
. \}
. el \{\
. nr www-width \\n[www-absolute]
. if \\n[www-html] \
. nr www-width (\\n[www-width] * 100 / 240)
-. ds www-size-specs width=\\n[www-width]\"
+. ds www-size-specs width=\"\\n[www-width]"
. \}
.
. nr www-height \\n[www-width]
@@ -718,13 +739,13 @@ www functionality. It should work with any macro set.
. nr www-height (\\n[www-absolute] * \\n[.p] / 100)
. if \\n[www-html] \
. nr www-height (\\n[www-height] * 100 / 240)
-. ds www-size-specs \\*[www-size-specs] height=\\*[www-percentage]\"
+. ds www-size-specs "\\*[www-size-specs] height="\\*[www-percentage]"
. \}
. el \{\
. nr www-height \\n[www-absolute]
. if \\n[www-html] \
. nr www-height (\\n[www-height] * 100 / 240)
-. ds www-size-specs \\*[www-size-specs] height=\\*[www-height]\"
+. ds www-size-specs "\\*[www-size-specs] "height="\\*[www-height]"
. \}
. \}
. \}
@@ -732,11 +753,11 @@ www functionality. It should work with any macro set.
. \" height not specified; use width value
. ie !\\n[www-is-absolute] \{\
. \" percentage value
-. ds www-size-specs \\*[www-size-specs] height=\\*[www-percentage]\"
+. ds www-size-specs "\\*[www-size-specs] "height="\\*[www-percentage]"
. nr www-height \\n[www-width]
. \}
. el \{\
-. ds www-size-specs \\*[www-size-specs] height=\\*[www-width]\"
+. ds www-size-specs "\\*[www-size-specs] "height="\\*[www-width]"
. nr www-height \\n[www-width]
. \}
. \}
@@ -745,13 +766,13 @@ www functionality. It should work with any macro set.
. ie !\\n[www-image-just] \
. HTML <img "src=""\\$1""" \
"alt=""Image \\$1""" \
- hspace=\\n[www-htmlimage-gap] \
- align=right \\*[www-size-specs]>
+ "hspace=""\\n[www-htmlimage-gap]""" \
+ "align=""right"" \\*[www-size-specs]"""></img>
. el \
. HTML <img "src=""\\$1""" \
"alt=""Image \\$1""" \
- hspace=\\n[www-htmlimage-gap] \
- align=left \\*[www-size-specs]>
+ "hspace=""\\n[www-htmlimage-gap]""" \
+ "align=""left"" \\*[www-size-specs]"""></img>
. \}
. el \{\
. tm www-width is \\n[www-width]
@@ -851,7 +872,7 @@ www functionality. It should work with any macro set.
.\" Produce a horizontal line.
.\"
.de HR
-. HTML</p> <hr>
+. HTML</p> <hr></hr>
..
.
.\" --------------------------------------------------------------------
@@ -933,6 +954,7 @@ www functionality. It should work with any macro set.
.de www-push-li
. nr www-depth +1
. ds www-level\\n[www-depth] \\$1\"
+. ds www-ltag\\n[www-depth]
. als LI \\$1
..
.
@@ -941,6 +963,18 @@ www functionality. It should work with any macro set.
. als LI \\*[www-level\\n[www-depth]]
..
.
+.\" www-emit-ltag - shuts down a previous open list tag
+.\" before issuing a new tag \\$1.
+.\" It then records tag \\$1 is open.
+.
+.de www-emit-ltag
+. if !'\\*[www-ltag\\n[www-depth]]'' \
+. HTML-NS </\\*[www-ltag\\n[www-depth]]>
+. if !'\\$1'' \
+. HTML-NS <\\$1>
+. ds www-ltag\\n[www-depth] \\$1
+..
+.
.\"
.\" Auxiliary macro for ULS.
.\"
@@ -984,11 +1018,12 @@ www functionality. It should work with any macro set.
.de ULS
. www-push-li www-li-ul
. www-push-ul-level
-. ie \\n[www-html] \
+. ie \\n[www-html] \{\
+. www-emit-ltag
. HTML</p> <ul>
-. el \{\
-. nr www-li-indent +\w'\\*[www-ul-level\\n[www-ul-level]]'u
. \}
+. el \
+. nr www-li-indent +\w'\\*[www-ul-level\\n[www-ul-level]]'u
..
.
.\" --------------------------------------------------------------------
@@ -997,8 +1032,10 @@ www functionality. It should work with any macro set.
.\" End an unordered list.
.\"
.de ULE
-. ie \\n[www-html] \
-. HTML </ul>
+. ie \\n[www-html] \{\
+. www-emit-ltag
+. HTML</p> </ul>
+. \}
. el \{\
. nr www-li-indent -\w'\\*[www-ul-level\\n[www-ul-level]]'u
. in \\n[www-li-indent]u
@@ -1015,9 +1052,11 @@ www functionality. It should work with any macro set.
.de OLS
. www-push-li www-li-ol
. www-push-ol-level
-. ie \\n[www-html] \
+. ie \\n[www-html] \{\
+. www-emit-ltag
. HTML</p> <ol "style=""list-style-type:" \
"\\*[www-ol-level\\n[www-ol-level]]"">"
+. \}
. el \
. nr www-li-indent +\w'\\*[www-ol-tmp]'u
..
@@ -1028,8 +1067,10 @@ www functionality. It should work with any macro set.
.\" End an ordered list.
.\"
.de OLE
-. ie \\n[www-html] \
+. ie \\n[www-html] \{\
+. www-emit-ltag
. HTML </ol>
+. \}
. el \{\
. nr www-li-indent -\w'\\*[www-ol-tmp]'u
. in \\n[www-li-indent]u
@@ -1047,8 +1088,10 @@ www functionality. It should work with any macro set.
.de DLS
. www-push-li www-li-dl
. nr www-dl-level +1
-. ie \\n[www-html] \
+. ie \\n[www-html] \{\
+. www-emit-ltag
. HTML</p> <dl>
+. \}
. el \{\
. nr www-li-indent +\\n[www-dl-shift]u
. in \\n[www-li-indent]u
@@ -1061,8 +1104,10 @@ www functionality. It should work with any macro set.
.\" End a definition list.
.\"
.de DLE
-. ie \\n[www-html] \
+. ie \\n[www-html] \{\
+. www-emit-ltag
. HTML </dl>
+. \}
. el \{\
. nr www-li-indent -\\n[www-dl-shift]u
. in \\n[www-li-indent]u
@@ -1081,7 +1126,7 @@ www functionality. It should work with any macro set.
.\"
.de www-li-ul
. ie \\n[www-html] \
-. HTML-NS <li>
+. www-emit-ltag li
. el \{\
. www:paraspace
. in \\n[www-li-indent]u
@@ -1095,7 +1140,7 @@ www functionality. It should work with any macro set.
.\"
.de www-li-ol
. ie \\n[www-html] \
-. HTML-NS <li>
+. www-emit-ltag li
. el \{\
. www:paraspace
. in \\n[www-li-indent]u
@@ -1110,7 +1155,7 @@ www functionality. It should work with any macro set.
.de www-li-dl
. ie \\n[www-html] \{\
. HTML <dt>\\$1</dt>
-. HTML-NS <dd>
+. www-emit-ltag dd
. \}
. el \{\
. www:paraspace
@@ -1179,8 +1224,8 @@ www functionality. It should work with any macro set.
.\"
.do if !d TS .do ds TS HTML-IMAGE\"
.do if !d TE .do ds TE HTML-IMAGE-END\"
-.do if !d EQ .do ds EQ HTML-IMAGE\"
-.do if !d EN .do ds EN HTML-IMAGE-END\"
+.do if !d EQ .do ds EQ EQN-HTML-IMAGE\"
+.do if !d EN .do ds EN EQN-HTML-IMAGE-END\"
.
.\"
.\" supplementary macros used by other macro sets
@@ -1245,6 +1290,61 @@ www functionality. It should work with any macro set.
. HTML-DO-IMAGE \\*[www-unique-name] i
..
.
+.\" EQN-HTML-IMAGE and friends check to see whether the equation is
+.\" not in an image, in which case it allows html
+.\" (mathml) to be generated (if -Txhtml was specified).
+.
+.de EQN-HTML-IMAGE
+. \" generates a centered image
+. www-make-unique-name
+. EQN-HTML-DO-IMAGE \\*[www-unique-name] c
+..
+.
+.de EQN-HTML-IMAGE-RIGHT
+. www-make-unique-name
+. EQN-HTML-DO-IMAGE \\*[www-unique-name] r
+..
+.
+.de EQN-HTML-IMAGE-LEFT
+. www-make-unique-name
+. EQN-HTML-DO-IMAGE \\*[www-unique-name] l
+..
+.
+.de EQN-HTML-IMAGE-INLINE
+. www-make-unique-name
+. EQN-HTML-DO-IMAGE \\*[www-unique-name] i
+..
+.\" --------------------------------------------------------------------
+.\" EQN-HTML-DO-IMAGE - tells troff to issue an image marker which can be
+.\" read back by pre-html
+.\"
+.de EQN-HTML-DO-IMAGE
+. ie r xhtml \{\
+. if !(\\n[.O] == 0) \{\
+. if r ps4html \
+. nop \O[5\\$2\\$1.png]\O[1]\O[3]
+. if \\n[www-html] \
+. nop \O[5\\$2\\$1.png]\O[0]\O[3]
+. \}
+. \}
+. el .HTML-DO-IMAGE \\$*
+..
+.
+.\" --------------------------------------------------------------------
+.\" EQN-HTML-IMAGE-END - terminates an image for html
+.\"
+.de EQN-HTML-IMAGE-END
+. ie r xhtml \{\
+. if !(\\n[.O] == 0) \{\
+. if r ps4html \
+. nop \O[4]\O[2]\O[0]
+. if \\n[www-html] \
+. nop \O[4]\O[2]\O[1]
+. \}
+. \}
+. el .HTML-IMAGE-END
+..
+.
.\" --------------------------------------------------------------------
.\" JOBNAME
.\"
@@ -1389,6 +1489,13 @@ www functionality. It should work with any macro set.
. ds www:close \\$2\"
..
.
+.\" MATHML - enable eqn mathml output to pass through to the device
+.\" driver
+.
+.de MATHML
+. if (\\n[.O] == 0) .MATH<?p> \\$*
+..
+.
.\" --------------------------------------------------------------------
.\" Final Setup
.\" --------------------------------------------------------------------