diff options
author | wl <wl> | 2007-09-19 14:55:54 +0000 |
---|---|---|
committer | wl <wl> | 2007-09-19 14:55:54 +0000 |
commit | e4f206b8a3104ee734b913a2d50980bf5bdf3634 (patch) | |
tree | 814cb9652b873192c9648453480aa48f37c41271 /src | |
parent | e128c4d2011e4dce3bb8db70fdeb59816f839c40 (diff) | |
download | groff-e4f206b8a3104ee734b913a2d50980bf5bdf3634.tar.gz |
* 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.
Diffstat (limited to 'src')
-rw-r--r-- | src/devices/grohtml/grohtml.man | 54 | ||||
-rw-r--r-- | src/devices/grohtml/html-table.cpp | 128 | ||||
-rw-r--r-- | src/devices/grohtml/html-table.h | 6 | ||||
-rw-r--r-- | src/devices/grohtml/html-text.cpp | 35 | ||||
-rw-r--r-- | src/devices/grohtml/html-text.h | 11 | ||||
-rw-r--r-- | src/devices/grohtml/post-html.cpp | 371 | ||||
-rw-r--r-- | src/preproc/eqn/box.cpp | 9 | ||||
-rw-r--r-- | src/preproc/eqn/eqn.h | 1 | ||||
-rw-r--r-- | src/preproc/eqn/main.cpp | 14 | ||||
-rw-r--r-- | src/preproc/eqn/text.cpp | 2 | ||||
-rw-r--r-- | src/preproc/html/pre-html.cpp | 168 | ||||
-rw-r--r-- | src/roff/groff/groff.cpp | 47 | ||||
-rw-r--r-- | src/roff/troff/input.cpp | 1 |
13 files changed, 675 insertions, 172 deletions
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", "Λ"}, // ISOgrk3 {"*m", "μ"}, // ISOgrk3 {"*M", "M"}, - {"*n", "&nu"}, // ISOgrk3 + {"*n", "ν"}, // 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); |