diff options
author | wlemb <wlemb> | 2001-12-06 10:03:21 +0000 |
---|---|---|
committer | wlemb <wlemb> | 2001-12-06 10:03:21 +0000 |
commit | 18b836fb33487d2277c0f9b4836ecd94d5a826d1 (patch) | |
tree | e9e2b01f7fd959add202e2cbe99d481329e11441 /src | |
parent | 6cfe607b019766844a38f54dacd67745ddfe4412 (diff) | |
download | groff-18b836fb33487d2277c0f9b4836ecd94d5a826d1.tar.gz |
* src/roff/troff/input.cc (get_delim_file_name): Removed since no
longer used.
* src/devices/grohtml/post-html.cc (html_printer::html_printer): Fix
order of initializers.
* NEWS: Updated.
* doc/groff.texinfo: Fix documentation of \O.
* src/devices/grohtml/html-text.cc (html_text::do_indent,
html_text::do_table, html_text::do_emittext, html_text::do_para):
Use `const' for first argument.
(html_text::do_table): Use cast.
* src/devices/grohtml/html-text.h: Updated.
* src/devices/grohtml/output.cc (simple_output::put_string): Add
method for `const string &s'.
* src/devices/grohtml/html.h: Updated.
* src/devices/grohtml/post-html.cc (MAX_STRING_LENGTH): Removed.
(ANCHOR_TEMPLATE): Modified.
(manufacture_headings): New global variable to handle `-h' option.
(is_subsection): Removed.
(char_buffer::add_string): Add `const' to first argument.
Protect against invalid string argument.
Add method for `const string &s'.
(text_glob): Completely redesigned.
(page): Use `const' for strings and remove string length variable.
(page::add_html): Removed.
(page::add_end_encode): New member function.
(to_unicode): Moved upwards.
(title_desc, header_desc): Updated.
(header_desc::write_headings): Updated to new ANCHOR_TEMPLATE
definition.
(html_printer::is_bold, html_printer::make_bold): New member
functions.
(html_printer::end_of_line): Updated.
(generate_img_src, html_printer::do_auto_image,
html_printer::do_title, html_printer::write_header,
html_printer::determine_header_level, html_printer::do_heading,
html_printer::do_linelength, html_printer::do_pageoffset,
html_printer::do_indentation, html_printer::do_tempindent,
html_printer::do_indentedparagraph, html_printer::do_break,
html_printer::flush_sbuf, get_html_translation,
html_printer::begin_page, html_printer::special): Rewritten to get
rid of static string length limit.
(html_printer::troff_tag): Added `.no-auto-rule'.
(html_printer::flush_globs): Small fix.
(html_printer::determine_space): Don't compute `space_width'.
(html_printer::translate_to_html): Renamed to ...
(html_printer::emit_html): This (with updates).
(html_printer::write_header): Implement `-h' option.
(html_printer::draw): Remove commented-out code. Handle `F'
command.
(html_printer::add_char_to_sbuf): Removed.
(html_printer::add_to_sbuf): Rewritten.
(html_printer::sbuf_continuation): Fixed.
(html_printer::seen_backwards_escape, reverse,
html_printer::remove_last_char_from_sbuf): Removed.
(char_translate_to_html, str_translate_to_html): Removed.
(html_printer::overstrike): New function member.
(html_printer::set_char): Use it.
(html_printer::do_body): New function member.
(html_printer::~html_printer): Use it.
(main): Handle `-h' option.
(usage): Updated.
* src/devices/grohtml/grohtml.man: Document -h switch.
* src/preproc/html/pre-html.cc: Include searchpath.h
Replace `POSTSCRIPTRES' macro with `postscriptRes' variable.
(get_resolution): New function.
(checkImageDir): Use `0777' permissions in mkdir()
(write_start_image): Rewritten to use `\O[5...]'.
(createImage, generateImages): Updated.
(main): Handle `F' and `h' options.
Use `get_resolution'.
* src/roff/troff/input.cc (begin, end, image): Removed.
(do_suppress): Take parameter.
Handle modified syntax of `\O'.
(token::next): Updated.
(init_markup_requests): Removed.
(main): Updated.
* src/roff/troff/div.h: Add declaration for begin_page().
* tmac/color-html.tmac: Removed. Contents moved to...
* tmac/html.tmac: Here. Set background color.
* tmac/color.tmac: Removed. Contents moved to...
* tmac/ps.tmac: Here.
* tmac/www.tmac: Remove the title command when generating images
for html.
(NO_AUTO_RULE): New macro.
(HTML_DO_IMAGE): Use revised `\O' escapes.
* tmac/Makefile.sub, tmac/groff_www.man, tmac/troffrc: Updated.
Diffstat (limited to 'src')
-rw-r--r-- | src/devices/grohtml/grohtml.man | 11 | ||||
-rw-r--r-- | src/devices/grohtml/html-text.cc | 12 | ||||
-rw-r--r-- | src/devices/grohtml/html-text.h | 8 | ||||
-rw-r--r-- | src/devices/grohtml/html.h | 1 | ||||
-rw-r--r-- | src/devices/grohtml/output.cc | 6 | ||||
-rw-r--r-- | src/devices/grohtml/post-html.cc | 1146 | ||||
-rw-r--r-- | src/preproc/html/pre-html.cc | 104 | ||||
-rw-r--r-- | src/roff/troff/div.h | 1 | ||||
-rw-r--r-- | src/roff/troff/input.cc | 198 |
9 files changed, 669 insertions, 818 deletions
diff --git a/src/devices/grohtml/grohtml.man b/src/devices/grohtml/grohtml.man index 7525ae6a..b39194a4 100644 --- a/src/devices/grohtml/grohtml.man +++ b/src/devices/grohtml/grohtml.man @@ -36,7 +36,7 @@ grohtml \- html driver for groff .ie \\n(.$-1 .RI "[\ \fB\\$1\fP" "\\$2" "\ ]" .el .RB "[\ " "\\$1" "\ ]" .. -.OP \-vlrn +.OP \-vhlrn .OP \-D dir .OP \-F dir .OP \-i resolution @@ -81,6 +81,15 @@ using option. .SH OPTIONS .TP +.B -h +Generates section and number headings by using +.BR <B> .\|.\|. </B> +and increasing the font size, rather than using the +.BI <H n >\c +\&.\|.\|.\c +.BI </H n > +tags. +.TP .B -l Turns off the production of automatic section links at the top of the document. .TP diff --git a/src/devices/grohtml/html-text.cc b/src/devices/grohtml/html-text.cc index f0c6dcd2..e78bddad 100644 --- a/src/devices/grohtml/html-text.cc +++ b/src/devices/grohtml/html-text.cc @@ -289,7 +289,7 @@ void html_text::push_para (HTML_TAG t) * then we start a html table to implement the indentation. */ -void html_text::do_indent (char *arg, int indent, int pageoff, int linelen) +void html_text::do_indent (const char *arg, int indent, int pageoff, int linelen) { if ((current_indentation != -1) && (pageoffset+current_indentation != indent+pageoff)) { @@ -304,7 +304,7 @@ void html_text::do_indent (char *arg, int indent, int pageoff, int linelen) linelength = linelen; } -void html_text::do_table (char *arg) +void html_text::do_table (const char *arg) { int in_pre = is_in_pre(); // char *para_type = done_para(); @@ -315,7 +315,7 @@ void html_text::do_table (char *arg) do_pre(); } // do_para(para_type); - push_para(TABLE_TAG, arg); + push_para(TABLE_TAG, (void *)arg); } /* @@ -604,7 +604,7 @@ void html_text::check_emit_text (tag_definition *t) * do_emittext - tells the class that text was written during the current tag. */ -void html_text::do_emittext (char *s, int length) +void html_text::do_emittext (const char *s, int length) { if ((! is_present(P_TAG)) && (! is_present(PRE_TAG))) do_para(""); @@ -630,7 +630,7 @@ void html_text::do_emittext (char *s, int length) * do_para- starts a new paragraph */ -void html_text::do_para (char *arg) +void html_text::do_para (const char *arg) { done_pre(); if (! is_present(P_TAG)) { @@ -701,7 +701,7 @@ void html_text::do_newline (void) int html_text::emitted_text (void) { - return( ! space_emitted); + return !space_emitted; } /* diff --git a/src/devices/grohtml/html-text.h b/src/devices/grohtml/html-text.h index c59b4646..9cf02311 100644 --- a/src/devices/grohtml/html-text.h +++ b/src/devices/grohtml/html-text.h @@ -53,7 +53,7 @@ public: html_text (simple_output *op); ~html_text (void); void flush_text (void); - void do_emittext (char *s, int length); + void do_emittext (const char *s, int length); void do_italic (void); void do_bold (void); void do_roman (void); @@ -61,13 +61,13 @@ public: void do_pre (void); void do_small (void); void do_big (void); - void do_para (char *arg1); + void do_para (const char *arg1); void do_sup (void); void do_sub (void); void do_space (void); void do_break (void); void do_newline (void); - void do_table (char *arg); + void do_table (const char *arg); void done_bold (void); void done_italic (void); char *done_para (void); @@ -77,7 +77,7 @@ public: void done_pre (void); void done_small (void); void done_big (void); - void do_indent (char *arg, int indent, int pageoff, int linelen); + void do_indent (const char *arg, int indent, int pageoff, int linelen); void do_color (color *c); void done_color (void); int emitted_text (void); diff --git a/src/devices/grohtml/html.h b/src/devices/grohtml/html.h index 69b6e35e..8d9e34c2 100644 --- a/src/devices/grohtml/html.h +++ b/src/devices/grohtml/html.h @@ -53,6 +53,7 @@ public: simple_output(FILE *, int max_line_length); simple_output &put_string(const char *, int); simple_output &put_string(const char *s); + simple_output &put_string(const string &s); simple_output &put_troffps_char (const char *s); simple_output &put_translated_string(const char *s); simple_output &put_number(int); diff --git a/src/devices/grohtml/output.cc b/src/devices/grohtml/output.cc index 88ab7d6c..01a249de 100644 --- a/src/devices/grohtml/output.cc +++ b/src/devices/grohtml/output.cc @@ -283,6 +283,12 @@ simple_output &simple_output::put_string(const char *s) return *this; } +simple_output &simple_output::put_string(const string &s) +{ + last_word.add_word(s.contents(), s.length()); + return *this; +} + simple_output &simple_output::put_number(int n) { char buf[1 + INT_DIGITS + 1]; diff --git a/src/devices/grohtml/post-html.cc b/src/devices/grohtml/post-html.cc index 754ed9d5..ecc2ba0a 100644 --- a/src/devices/grohtml/post-html.cc +++ b/src/devices/grohtml/post-html.cc @@ -47,12 +47,11 @@ extern "C" const char *Version_string; # define FALSE (1==0) #endif -#define MAX_STRING_LENGTH 4096 #define MAX_LINE_LENGTH 60 /* maximum characters we want in a line */ #define SIZE_INCREMENT 2 /* font size increment <big> = +2 */ #define BASE_POINT_SIZE 10 /* 10 points is the base size ie html size 3 */ #define CENTER_TOLERANCE 2 /* how many pixels off center will we still */ -#define ANCHOR_TEMPLATE "heading%d" /* if simple anchor is set we use this */ +#define ANCHOR_TEMPLATE "heading" /* if simple anchor is set we use this */ #define UNICODE_DESC_START 0x80 /* all character entities above this are */ /* either encoded by their glyph names or if */ /* there is no name then we use &#nnn; */ @@ -64,8 +63,8 @@ typedef enum {CENTERED, LEFT, RIGHT, INLINE} TAG_ALIGNMENT; * prototypes */ -void str_translate_to_html (font *f, char *buf, int buflen, char *str, int len, int and_single, int is_special); -char *get_html_translation (font *f, const char *name); +char *get_html_translation (font *f, const string &name); +int char_translate_to_html (font *f, char *buf, int buflen, unsigned char ch, int b, int and_single); static int auto_links = TRUE; /* by default we enable automatic links at */ @@ -73,6 +72,8 @@ static int auto_links = TRUE; /* by default we enable aut static int auto_rule = TRUE; /* by default we enable an automatic rule */ /* at the top and bottom of the document */ static int simple_anchors = FALSE; /* default to anchors with heading text */ +static int manufacture_headings = FALSE; /* default is to use the Hn html headings, */ + /* rather than manufacture our own. */ /* @@ -100,18 +101,6 @@ static int max (int a, int b) } /* - * is_subsection - returns TRUE if a1..a2 is within b1..b2 - */ - -#if 0 -static int is_subsection (int a1, int a2, int b1, int b2) -{ - // easier to see whether this is not the case - return( !((a1 < b1) || (a1 > b2) || (a2 < b1) || (a2 > b2)) ); -} -#endif - -/* * is_intersection - returns TRUE if range a1..a2 intersects with b1..b2 */ @@ -280,7 +269,8 @@ class char_buffer { public: char_buffer(); ~char_buffer(); - char *add_string(char *, unsigned int); + char *add_string(const char *, unsigned int); + char *add_string(const string &); private: char_block *head; char_block *tail; @@ -300,11 +290,14 @@ char_buffer::~char_buffer() } } -char *char_buffer::add_string (char *s, unsigned int length) +char *char_buffer::add_string (const char *s, unsigned int length) { int i=0; unsigned int old_used; + if (s == NULL || length == 0) + return NULL; + if (tail == 0) { tail = new char_block; head = tail; @@ -337,55 +330,78 @@ char *char_buffer::add_string (char *s, unsigned int length) return( &tail->buffer[old_used] ); } +char *char_buffer::add_string (const string &s) +{ + return add_string(s.contents(), s.length()); +} + /* * the classes and methods for maintaining glyph positions. */ class text_glob { public: - text_glob (style *s, char *string, unsigned int length, - int min_vertical , int min_horizontal, - int max_vertical , int max_horizontal, - int is_html , int is_troff_command, - int is_auto_image, - int is_a_line , int thickness); - text_glob (void); - ~text_glob (void); - int is_a_line (void); - int is_a_tag (void); - int is_raw (void); - int is_eol (void); - int is_auto_img (void); - int is_br (void); - int is_eol_ce (void); + void text_glob_html (style *s, char *str, int length, + int min_vertical, int min_horizontal, + int max_vertical, int max_horizontal); + void text_glob_special (style *s, char *str, int length, + int min_vertical, int min_horizontal, + int max_vertical, int max_horizontal); + void text_glob_line (style *s, + int min_vertical, int min_horizontal, + int max_vertical, int max_horizontal, + int thickness); + void text_glob_auto_image(style *s, char *str, int length, + int min_vertical, int min_horizontal, + int max_vertical, int max_horizontal); + void text_glob_tag (style *s, char *str, int length, + int min_vertical, int min_horizontal, + int max_vertical, int max_horizontal); + + text_glob (void); + ~text_glob (void); + int is_a_line (void); + int is_a_tag (void); + int is_eol (void); + int is_auto_img (void); + int is_br (void); + int is_eol_ce (void); style text_style; - char *text_string; + const char *text_string; unsigned int text_length; int minv, minh, maxv, maxh; - int is_raw_command; // should the text be sent directly to the device? int is_tag; // is this a .br, .sp, .tl etc int is_img_auto; // image created by eqn delim + int is_special; // text has come via 'x X html:' int is_line; // is the command a <line>? int thickness; // the thickness of a line + +private: + text_glob (style *s, char *str, int length, + int min_vertical , int min_horizontal, + int max_vertical , int max_horizontal, + bool is_troff_command, + bool is_auto_image, bool is_special_command, + bool is_a_line , int thickness); }; -text_glob::text_glob (style *s, char *string, unsigned int length, +text_glob::text_glob (style *s, char *str, int length, int min_vertical, int min_horizontal, int max_vertical, int max_horizontal, - int is_html, int is_troff_command, - int is_auto_image, - int is_a_line, int line_thickness) - : text_style(*s), text_string(string), text_length(length), + bool is_troff_command, + bool is_auto_image, bool is_special_command, + bool is_a_line, int line_thickness) + : text_style(*s), text_string(str), text_length(length), minv(min_vertical), minh(min_horizontal), maxv(max_vertical), maxh(max_horizontal), - is_raw_command(is_html), is_tag(is_troff_command), is_img_auto(is_auto_image), + is_tag(is_troff_command), is_img_auto(is_auto_image), is_special(is_special_command), is_line(is_a_line), thickness(line_thickness) { } text_glob::text_glob () : text_string(0), text_length(0), minv(-1), minh(-1), maxv(-1), maxh(-1), - is_raw_command(FALSE), is_tag(FALSE), is_line(FALSE), thickness(0) + is_tag(FALSE), is_special(FALSE), is_line(FALSE), thickness(0) { } @@ -394,12 +410,105 @@ text_glob::~text_glob () } /* + * text_glob_html - used to place html text into the glob buffer. + */ + +void text_glob::text_glob_html (style *s, char *str, int length, + int min_vertical , int min_horizontal, + int max_vertical , int max_horizontal) +{ + text_glob *g = new text_glob(s, str, length, + min_vertical, min_horizontal, max_vertical, max_horizontal, + FALSE, FALSE, FALSE, FALSE, 0); + *this = *g; +} + +/* + * text_glob_html - used to place html specials into the glob buffer. + * This text is essentially html commands coming through + * from the macro sets, with special designated sequences of + * characters translated into html. See add_and_encode. + */ + +void text_glob::text_glob_special (style *s, char *str, int length, + int min_vertical , int min_horizontal, + int max_vertical , int max_horizontal) +{ + text_glob *g = new text_glob(s, str, length, + min_vertical, min_horizontal, max_vertical, max_horizontal, + FALSE, FALSE, TRUE, FALSE, 0); + *this = *g; +} + +/* + * text_glob_line - record horizontal draw line commands. + */ + +void text_glob::text_glob_line (style *s, + int min_vertical , int min_horizontal, + int max_vertical , int max_horizontal, + int thickness) +{ + text_glob *g = new text_glob(s, "", 0, + min_vertical, min_horizontal, max_vertical, max_horizontal, + FALSE, FALSE, FALSE, TRUE, thickness); + *this = *g; +} + +/* + * text_glob_auto_image - record the presence of a .auto-image tag command. + * Used to mark that an image has been created automatically + * by a preprocessor and (pre-grohtml/troff) combination. + * Under some circumstances images may not be created. + * (consider .EQ + * delim $$ + * .EN + * .TS + * tab(!), center; + * l!l. + * $1 over x$!recripical of x + * .TE + * + * the first auto-image marker is created via .EQ/.EN pair + * and no image is created. + * The second auto-image marker occurs at $1 over x$ + * Currently this image will not be created + * as the whole of the table is created as an image. + * (Once html tables are handled by grohtml this will change. + * Shortly this will be the case). + */ + +void text_glob::text_glob_auto_image(style *s, char *str, int length, + int min_vertical, int min_horizontal, + int max_vertical, int max_horizontal) +{ + text_glob *g = new text_glob(s, str, length, + min_vertical, min_horizontal, max_vertical, max_horizontal, + TRUE, TRUE, FALSE, FALSE, 0); + *this = *g; +} + +/* + * text_glob_tag - records a troff tag. + */ + +void text_glob::text_glob_tag (style *s, char *str, int length, + int min_vertical, int min_horizontal, + int max_vertical, int max_horizontal) +{ + text_glob *g = new text_glob(s, str, length, + min_vertical, min_horizontal, max_vertical, max_horizontal, + TRUE, FALSE, FALSE, FALSE, 0); + *this = *g; +} + +/* * is_a_line - returns TRUE if glob should be converted into an <hr> */ int text_glob::is_a_line (void) { - return( is_line ); + return is_line; } /* @@ -408,7 +517,7 @@ int text_glob::is_a_line (void) int text_glob::is_a_tag (void) { - return( is_tag ); + return is_tag; } /* @@ -430,22 +539,13 @@ int text_glob::is_eol_ce (void) } /* - * is_raw - returns TRUE if glob contains raw html. - */ - -int text_glob::is_raw (void) -{ - return( is_raw_command ); -} - -/* * is_auto_img - returns TRUE if the glob contains an automatically * generated image. */ int text_glob::is_auto_img (void) { - return( is_img_auto ); + return is_img_auto; } /* @@ -455,9 +555,10 @@ int text_glob::is_auto_img (void) int text_glob::is_br (void) { - return( is_a_tag() && ((strcmp("html-tag:.br", text_string) == 0) || - (strcmp("html-tag:.ce", text_string) == 0) || - (strcmp("html-tag:.nf", text_string) == 0)) ); + return( is_a_tag() && ((strcmp ("html-tag:.br", text_string) == 0) || + (strncmp("html-tag:.sp", text_string, 11) == 0) || + (strcmp ("html-tag:.ce", text_string) == 0) || + (strcmp ("html-tag:.nf", text_string) == 0)) ); } /* @@ -753,15 +854,15 @@ text_glob* list::move_left_get_data (void) class page { public: page (void); - void add (style *s, char *string, unsigned int length, + void add (style *s, const string &str, int line_number, int min_vertical, int min_horizontal, int max_vertical, int max_horizontal); - void add_html (style *s, char *string, unsigned int length, + void add_tag (style *s, const string &str, int line_number, int min_vertical, int min_horizontal, int max_vertical, int max_horizontal); - void add_tag (style *s, char *string, unsigned int length, + void add_and_encode (style *s, const string &str, int line_number, int min_vertical, int min_horizontal, int max_vertical, int max_horizontal); @@ -781,32 +882,19 @@ page::page() { } -void page::add (style *s, char *string, unsigned int length, - int line_number, - int min_vertical, int min_horizontal, - int max_vertical, int max_horizontal) -{ - if (length > 0) { - text_glob *g=new text_glob(s, buffer.add_string(string, length), length, - min_vertical, min_horizontal, max_vertical, max_horizontal, - FALSE, FALSE, FALSE, FALSE, 0); - glyphs.add(g, line_number, min_vertical, min_horizontal, max_vertical, max_horizontal); - } -} - /* - * add_html - add a raw html command, for example mailto, line, background, image etc. + * add - add html text to the list of glyphs. */ -void page::add_html (style *s, char *string, unsigned int length, - int line_number, - int min_vertical, int min_horizontal, - int max_vertical, int max_horizontal) +void page::add (style *s, const string &str, + int line_number, + int min_vertical, int min_horizontal, + int max_vertical, int max_horizontal) { - if (length > 0) { - text_glob *g=new text_glob(s, buffer.add_string(string, length), length, - min_vertical, min_horizontal, max_vertical, max_horizontal, - TRUE, FALSE, FALSE, FALSE, 0); + if (str.length() > 0) { + text_glob *g=new text_glob(); + g->text_glob_html(s, buffer.add_string(str), str.length(), + min_vertical, min_horizontal, max_vertical, max_horizontal); glyphs.add(g, line_number, min_vertical, min_horizontal, max_vertical, max_horizontal); } } @@ -815,17 +903,23 @@ void page::add_html (style *s, char *string, unsigned int length, * add_tag - adds a troff tag, for example: .tl .sp .br */ -void page::add_tag (style *s, char *string, unsigned int length, +void page::add_tag (style *s, const string &str, int line_number, int min_vertical, int min_horizontal, int max_vertical, int max_horizontal) { - if (length > 0) { - text_glob *g=new text_glob(s, buffer.add_string(string, length), length, - min_vertical, min_horizontal, max_vertical, max_horizontal, - FALSE, TRUE, - (strncmp(string, "html-tag:.auto-image", 20) == 0), - FALSE, 0); + if (str.length() > 0) { + text_glob *g; + + if (strncmp((str+'\0').contents(), "html-tag:.auto-image", 20) == 0) { + g = new text_glob(); + g->text_glob_auto_image(s, buffer.add_string(str), str.length(), + min_vertical, min_horizontal, max_vertical, max_horizontal); + } else { + g = new text_glob(); + g->text_glob_tag(s, buffer.add_string(str), str.length(), + min_vertical, min_horizontal, max_vertical, max_horizontal); + } glyphs.add(g, line_number, min_vertical, min_horizontal, max_vertical, max_horizontal); } } @@ -840,14 +934,86 @@ void page::add_line (style *s, int thickness) { if (y1 == y2) { - text_glob *g = new text_glob(s, "", 0, - min(y1, y2), min(x1, y2), max(y1, y2), max(x1, x2), - FALSE, TRUE, FALSE, FALSE, thickness); + text_glob *g = new text_glob(); + g->text_glob_line(s, + min(y1, y2), min(x1, y2), max(y1, y2), max(x1, x2), + thickness); glyphs.add(g, line_number, min(y1, y2), min(x1, y2), max(y1, y2), max(x1, x2)); } } /* + * to_unicode - returns a unicode translation of char, ch. + */ + +static char *to_unicode (unsigned char ch) +{ + static char buf[20]; + + sprintf(buf, "&#%u;", (unsigned int)ch); + return buf; +} + +/* + * add_and_encode - adds a special string to the page, it translates the string + * into html glyphs. The special string will have come from x X html: + * and can contain troff character encodings which appear as + * \(char\). A sequence of \\ represents \. + * So for example we can write: + * "cost = \(Po\)3.00 file = \\foo\\bar" + * which is translated into: + * "cost = £3.00 file = \foo\bar" + */ + +void page::add_and_encode (style *s, const string &str, + int line_number, + int min_vertical, int min_horizontal, + int max_vertical, int max_horizontal) +{ + string html_string; + char *html_glyph; + int i=0; + + if (s->f == NULL) + return; + while (i < str.length()) { + if ((i+1<str.length()) && (str.substring(i, 2) == string("\\("))) { + // start of escape + i += 2; // move over \( + int a = i; + string troff_charname; + while ((i+1<str.length()) && (str.substring(i, 2) != string("\\)"))) { + i++; + } + int n = i; + if ((i+1<str.length()) && (str.substring(i, 2) == string("\\)"))) + i++; + else + n = -1; + if (n > 0) { + html_glyph = get_html_translation(s->f, str.substring(a, n-a)); + if (html_glyph) + html_string += html_glyph; + else { + int index=s->f->name_to_index((troff_charname + '\0').contents()); + + if (s->f->contains(index) && (index != 0)) + html_string += s->f->get_code(index); + } + } + } else + html_string += str[i]; + i++; + } + if (html_string.length() > 0) { + text_glob *g=new text_glob(); + g->text_glob_special(s, buffer.add_string(html_string), html_string.length(), + min_vertical, min_horizontal, max_vertical, max_horizontal); + glyphs.add(g, line_number, min_vertical, min_horizontal, max_vertical, max_horizontal); + } +} + +/* * dump_page - dump the page contents for debugging purposes. */ @@ -909,7 +1075,7 @@ public: int has_been_written; int has_been_found; - char text[MAX_STRING_LENGTH]; + string text; }; @@ -932,7 +1098,7 @@ public: list headers; // list of headers built from .NH and .SH int header_level; // current header level int written_header; // have we written the header yet? - char header_buffer[MAX_STRING_LENGTH]; // current header text + string header_buffer; // current header text void write_headings (FILE *f, int force); }; @@ -962,9 +1128,12 @@ void header_desc::write_headings (FILE *f, int force) do { g = headers.get_data(); fputs("<a href=\"#", f); - if (simple_anchors) - fprintf(f, ANCHOR_TEMPLATE, h); - else + if (simple_anchors) { + string buffer(ANCHOR_TEMPLATE); + + buffer += as_string(h); + fprintf(f, buffer.contents()); + } else fputs(g->text_string, f); h++; fputs("\">", f); @@ -982,16 +1151,17 @@ class html_printer : public printer { simple_output html; int res; int space_char_index; + int space_width; int no_of_printed_pages; int paper_length; - enum { SBUF_SIZE = 8192 }; - char sbuf[SBUF_SIZE]; - int sbuf_len; + string sbuf; int sbuf_start_hpos; int sbuf_vpos; int sbuf_end_hpos; int sbuf_kern; style sbuf_style; + int last_sbuf_length; + int overstrike_detected; style output_style; int output_hpos; int output_vpos; @@ -1000,7 +1170,6 @@ class html_printer : public printer { int line_thickness; int output_line_thickness; unsigned char output_space_code; - string defs; char *inside_font_style; int page_number; title_desc title; @@ -1022,6 +1191,7 @@ class html_printer : public printer { int pointsize; int vertical_spacing; int line_number; + color *background; void flush_sbuf (); void set_style (const style &); @@ -1034,8 +1204,7 @@ class html_printer : public printer { void set_line_thickness (const environment *); void terminate_current_font (void); void flush_font (void); - void add_char_to_sbuf (unsigned char code); - void add_to_sbuf (unsigned char code, const char *name); + void add_to_sbuf (unsigned char code, const string &s); void write_title (int in_head); void determine_diacritical_mark (const char *name, const environment *env); int sbuf_continuation (unsigned char code, const char *name, const environment *env, int w); @@ -1046,7 +1215,7 @@ class html_printer : public printer { void flush_globs (void); void emit_line (text_glob *g); void emit_raw (text_glob *g); - void translate_to_html (text_glob *g); + void emit_html (text_glob *g); void determine_space (text_glob *g); void start_font (const char *name); void end_font (const char *name); @@ -1082,6 +1251,10 @@ class html_printer : public printer { int start_superscript (text_glob *g); int end_superscript (text_glob *g); void outstanding_eol (int n); + int is_bold (font *f); + font *make_bold (font *f); + int overstrike (unsigned char code, const char *name, const environment *env, int w); + void do_body (void); // ADD HERE @@ -1107,7 +1280,7 @@ static void usage(FILE *stream); void html_printer::set_style(const style &sty) { const char *fontname = sty.f->get_name(); - if (fontname == 0) + if (fontname == NULL) fatal("no internalname specified for font"); #if 0 @@ -1115,6 +1288,33 @@ void html_printer::set_style(const style &sty) #endif } +/* + * is_bold - returns TRUE if font, f, is bold. + */ + +int html_printer::is_bold (font *f) +{ + const char *fontname = f->get_name(); + return (strcmp(fontname, "B") == 0) || (strcmp(fontname, "BI") == 0); +} + +/* + * make_bold - if a bold font of, f, exists then return it. + */ + +font *html_printer::make_bold (font *f) +{ + const char *fontname = f->get_name(); + + if (strcmp(fontname, "B") == 0) + return f; + if (strcmp(fontname, "I") == 0) + return font::load_font("BI"); + if (strcmp(fontname, "BI") == 0) + return f; + return NULL; +} + void html_printer::end_of_line() { flush_sbuf(); @@ -1165,9 +1365,8 @@ void html_printer::emit_raw (text_glob *g) supress_sub_sup = TRUE; #if defined(INDENTATION) if (in_table) { - stop(); current_paragraph->do_indent(NULL, 0, pageoffset, linelength); - current_paragraph->do_indent(indent.text, indentation, pageoffset, linelength); + current_paragraph->do_indent(page_contents->buffer.add_string(indent.text), indentation, pageoffset, linelength); } #endif } @@ -1244,23 +1443,16 @@ static int exists (const char *filename) * providing that the image exists. */ -static char *generate_img_src (const char *filename) +static string &generate_img_src (const char *filename) { - static char buffer[MAX_STRING_LENGTH]; + string *s = new string(""); while (filename && (filename[0] == ' ')) { filename++; } - if (exists(filename)) { - strcpy(buffer, "<img src=\""); - strncat(buffer, filename, MAX_STRING_LENGTH-strlen("<img src=\"")-1); - if (strlen(buffer) < MAX_STRING_LENGTH-3) { - strncat(buffer, "\">", 3); - } - return( (char *)&buffer ); - } else { - return( 0 ); - } + if (exists(filename)) + *s += string("<img src=\"") + filename + "\">"; + return *s; } /* @@ -1273,20 +1465,19 @@ static char *generate_img_src (const char *filename) void html_printer::do_auto_image (text_glob *g, const char *filename) { - char *buffer = generate_img_src(filename); + string buffer = generate_img_src(filename); - if (buffer) { + if (! buffer.empty()) { /* * utilize emit_raw by creating a new text_glob. */ text_glob h = *g; - h.text_string = buffer; - h.text_length = strlen(buffer); + h.text_string = buffer.contents(); + h.text_length = buffer.length(); emit_raw(&h); - } else { + } else next_tag = INLINE; - } } /* @@ -1310,7 +1501,6 @@ void html_printer::do_title (void) text_glob *t; int removed_from_head; int eol_ce = 0; - char buf[MAX_STRING_LENGTH]; if (page_number == 1) { int found_title_start = FALSE; @@ -1320,23 +1510,18 @@ void html_printer::do_title (void) t = page_contents->glyphs.get_data(); removed_from_head = FALSE; if (t->is_auto_img()) { - char *img=generate_img_src((char *)(t->text_string + 20)); + string img = generate_img_src((char *)(t->text_string + 20)); - if (img) { - if (found_title_start) { - strcat(title.text, " "); - } + if (! img.empty()) { + if (found_title_start) + title.text += " "; found_title_start = TRUE; title.has_been_found = TRUE; - strcat(title.text, img); + title.text += img; } page_contents->glyphs.sub_move_right(); /* move onto next word */ removed_from_head = ((!page_contents->glyphs.is_empty()) && (page_contents->glyphs.is_equal_to_head())); - } else if (t->is_raw_command) { - /* skip raw commands - */ - page_contents->glyphs.sub_move_right(); /* move onto next word */ } else if (t->is_eol_ce()) { /* process the eol associated with .ce */ @@ -1356,15 +1541,12 @@ void html_printer::do_title (void) outstanding_eol(eol_ce); return; } else if (found_title_start) { - strcat(title.text, " "); - str_translate_to_html(t->text_style.f, buf, MAX_STRING_LENGTH, t->text_string, t->text_length, TRUE, FALSE); - strcat(title.text, buf); - page_contents->glyphs.sub_move_right(); /* move onto next word */ - removed_from_head = ((!page_contents->glyphs.is_empty()) && - (page_contents->glyphs.is_equal_to_head())); + title.text += " " + string(t->text_string, t->text_length); + page_contents->glyphs.sub_move_right(); /* move onto next word */ + removed_from_head = ((!page_contents->glyphs.is_empty()) && + (page_contents->glyphs.is_equal_to_head())); } else { - str_translate_to_html(t->text_style.f, buf, MAX_STRING_LENGTH, t->text_string, t->text_length, TRUE, FALSE); - strcpy((char *)title.text, buf); + title.text += string(t->text_string, t->text_length); found_title_start = TRUE; title.has_been_found = TRUE; page_contents->glyphs.sub_move_right(); /* move onto next word */ @@ -1379,7 +1561,7 @@ void html_printer::do_title (void) void html_printer::write_header (void) { - if (strlen(header.header_buffer) > 0) { + if (! header.header_buffer.empty()) { if (header.header_level > 7) { header.header_level = 7; } @@ -1394,12 +1576,13 @@ void html_printer::write_header (void) header.no_of_headings++; style st; - text_glob *h=new text_glob(&st, - header.headings.add_string(header.header_buffer, strlen(header.header_buffer)), - strlen(header.header_buffer), - header.no_of_headings, header.header_level, - header.no_of_headings, header.header_level, - FALSE, FALSE, FALSE, FALSE, FALSE); + text_glob *h=new text_glob(); + h->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, header.no_of_headings, header.no_of_headings, header.no_of_headings, @@ -1409,24 +1592,42 @@ void html_printer::write_header (void) html.nl().put_string("<a name=\""); if (simple_anchors) { - char buffer[MAX_LINE_LENGTH]; + string buffer(ANCHOR_TEMPLATE); - sprintf(buffer, ANCHOR_TEMPLATE, header.no_of_headings); - html.put_string(buffer); + buffer += as_string(header.no_of_headings); + html.put_string(buffer.contents()); } else { html.put_string(header.header_buffer); } html.put_string("\"></a>").nl(); } - // and now we issue the real header - html.put_string("<h"); - html.put_number(header.header_level); - html.put_string(">"); - html.put_string(header.header_buffer); - html.put_string("</h"); - html.put_number(header.header_level); - html.put_string(">").nl(); + if (manufacture_headings) { + // line break before a header + if (!current_paragraph->emitted_text()) + current_paragraph->do_space(); + // user wants manufactured headings which look better than <Hn></Hn> + if (header.header_level<4) { + html.put_string("<b><font size=\"+1\">"); + html.put_string(header.header_buffer); + html.put_string("</font></b>").nl(); + } + else { + html.put_string("<b>"); + html.put_string(header.header_buffer); + html.put_string("</b>").nl(); + } + } + else { + // and now we issue the real header + html.put_string("<h"); + html.put_number(header.header_level); + html.put_string(">"); + html.put_string(header.header_buffer); + html.put_string("</h"); + html.put_number(header.header_level); + html.put_string(">").nl(); + } current_paragraph->do_para(""); } @@ -1436,9 +1637,10 @@ void html_printer::determine_header_level (int level) { if (level == 0) { int i; - int l=strlen(header.header_buffer); - for (i=0; ((i<l) && ((header.header_buffer[i] == '.') || is_digit(header.header_buffer[i]))) ; i++) { + for (i=0; ((i<header.header_buffer.length()) + && ((header.header_buffer[i] == '.') + || is_digit(header.header_buffer[i]))) ; i++) { if (header.header_buffer[i] == '.') { level++; } @@ -1455,35 +1657,33 @@ void html_printer::do_heading (char *arg) { text_glob *g; text_glob *l = 0; - char buf[MAX_STRING_LENGTH]; int level=atoi(arg); - strcpy(header.header_buffer, ""); + header.header_buffer.clear(); page_contents->glyphs.move_right(); if (! page_contents->glyphs.is_equal_to_head()) { g = page_contents->glyphs.get_data(); do { if (g->is_auto_img()) { - char *img=generate_img_src((char *)(g->text_string + 20)); + string img=generate_img_src((char *)(g->text_string + 20)); - if (img) { + if (! img.empty()) { simple_anchors = TRUE; // we cannot use full heading anchors with images - if (l != 0) { - strcat(header.header_buffer, " "); - } + if (l != 0) + header.header_buffer += " "; + l = g; - strcat(header.header_buffer, img); + header.header_buffer += img; } - } else if (! (g->is_a_line() || g->is_a_tag() || g->is_raw())) { + } else if (! (g->is_a_line() || g->is_a_tag())) { /* - * we ignore raw commands when constructing a heading + * we ignore tags commands when constructing a heading */ - if (l != 0) { - strcat(header.header_buffer, " "); - } + if (l != 0) + header.header_buffer += " "; l = g; - str_translate_to_html(g->text_style.f, buf, MAX_STRING_LENGTH, g->text_string, g->text_length, TRUE, FALSE); - strcat(header.header_buffer, (char *)buf); + + header.header_buffer += string(g->text_string, g->text_length); } page_contents->glyphs.move_right(); g = page_contents->glyphs.get_data(); @@ -1540,7 +1740,7 @@ void html_printer::do_linelength (char *arg) #if defined(INDENTATION) if (fill_on) { linelength = atoi(arg); - current_paragraph->do_indent(indent.text, indentation, pageoffset, linelength); + current_paragraph->do_indent(page_contents->buffer.add_string(indent.text), indentation, pageoffset, linelength); } #endif } @@ -1554,7 +1754,7 @@ void html_printer::do_pageoffset (char *arg) #if defined(INDENTATION) pageoffset = atoi(arg); if (fill_on) { - current_paragraph->do_indent(indent.text, indentation, pageoffset, linelength); + current_paragraph->do_indent(page_contents->buffer.add_string(indent.text), indentation, pageoffset, linelength); } #endif } @@ -1568,7 +1768,7 @@ void html_printer::do_indentation (char *arg) #if defined(INDENTATION) if (fill_on) { indentation = atoi(arg); - current_paragraph->do_indent(indent.text, indentation, pageoffset, linelength); + current_paragraph->do_indent(page_contents->buffer.add_string(indent.text), indentation, pageoffset, linelength); } #endif } @@ -1584,7 +1784,7 @@ void html_printer::do_tempindent (char *arg) end_tempindent = 1; prev_indent = indentation; indentation = atoi(arg); - current_paragraph->do_indent(indent.text, indentation, pageoffset, linelength); + current_paragraph->do_indent(page_contents->buffer.add_string(indent.text), indentation, pageoffset, linelength); } #endif } @@ -1600,11 +1800,10 @@ void html_printer::do_indentedparagraph (void) #if defined(INDENTATION) text_glob *t; int removed_from_head; - char buf[MAX_STRING_LENGTH]; int found_indent_start = FALSE; indent.has_been_found = FALSE; - indent.text[0] = (char)0; + indent.text.clear(); if (! page_contents->glyphs.is_empty()) { page_contents->glyphs.sub_move_right(); /* move onto next word */ @@ -1612,20 +1811,16 @@ void html_printer::do_indentedparagraph (void) t = page_contents->glyphs.get_data(); removed_from_head = FALSE; if (t->is_auto_img()) { - char *img=generate_img_src((char *)(t->text_string + 20)); + string img = generate_img_src((char *)(t->text_string + 20)); + + if (! img.empty()) { + if (found_indent_start) + indent.text += " "; - if (img) { - if (found_indent_start) { - strcat(indent.text, " "); - } found_indent_start = TRUE; - strcat(indent.text, img); + indent.text += img; } page_contents->glyphs.sub_move_right(); /* move onto next word */ - } else if (t->is_raw_command) { - /* skip raw commands - */ - page_contents->glyphs.sub_move_right(); /* move onto next word */ } else if (t->is_a_tag() && (strncmp(t->text_string, "html-tag:.br", 12) == 0)) { /* end of indented para found, but move back so that we read this tag and process it */ @@ -1633,17 +1828,18 @@ void html_printer::do_indentedparagraph (void) indent.has_been_found = TRUE; return; } else if (t->is_a_tag()) { + if (strncmp(t->text_string, "html-tag:.ti", 12) == 0) { + char *a = (char *)t->text_string+12; + do_tempindent(a); + } page_contents->glyphs.sub_move_right(); /* move onto next word */ } else if (found_indent_start) { - strcat(indent.text, " "); - str_translate_to_html(t->text_style.f, buf, MAX_STRING_LENGTH, t->text_string, t->text_length, TRUE, FALSE); - strcat(indent.text, buf); + indent.text += " " + string(t->text_string, t->text_length); page_contents->glyphs.sub_move_right(); /* move onto next word */ removed_from_head = ((!page_contents->glyphs.is_empty()) && (page_contents->glyphs.is_equal_to_head())); } else { - str_translate_to_html(t->text_style.f, buf, MAX_STRING_LENGTH, t->text_string, t->text_length, TRUE, FALSE); - strcpy((char *)indent.text, buf); + indent.text += string(t->text_string, t->text_length); found_indent_start = TRUE; indent.has_been_found = TRUE; page_contents->glyphs.sub_move_right(); /* move onto next word */ @@ -1755,7 +1951,7 @@ void html_printer::do_break (void) end_tempindent--; if (end_tempindent == 0) { indentation = prev_indent; - current_paragraph->do_indent(indent.text, indentation, pageoffset, linelength); + current_paragraph->do_indent(page_contents->buffer.add_string(indent.text), indentation, pageoffset, linelength); } } #endif @@ -1825,6 +2021,8 @@ void html_printer::troff_tag (text_glob *g) do_indentedparagraph(); } else if (strcmp(t, ".links") == 0) { do_links(); + } else if (strcmp(t, ".no-auto-rule") == 0) { + auto_rule = FALSE; } } @@ -1854,14 +2052,12 @@ void html_printer::flush_globs (void) stop(); } - if (g->is_raw()) { - emit_raw(g); - } else if (g->is_a_tag()) { + if (g->is_a_tag()) { troff_tag(g); } else if (g->is_a_line()) { emit_line(g); } else { - translate_to_html(g); + emit_html(g); } /* * after processing the title (and removing it) the glyph list might be empty @@ -1889,13 +2085,12 @@ void html_printer::flush_page (void) /* * determine_space - works out whether we need to write a space. - * If last glyth is ajoining then no space emitted. + * If last glyph is ajoining then no space emitted. */ void html_printer::determine_space (text_glob *g) { if (current_paragraph->is_in_pre()) { - int space_width = sbuf_style.f->get_space_width(sbuf_style.point_size); /* * .nf has been specified */ @@ -2113,18 +2308,14 @@ void html_printer::do_sup_or_sub (text_glob *g) } /* - * translate_to_html - translates a textual string into html text + * emit_html - write out the html text */ -void html_printer::translate_to_html (text_glob *g) +void html_printer::emit_html (text_glob *g) { - char buf[MAX_STRING_LENGTH]; - do_font(g); determine_space(g); - str_translate_to_html(g->text_style.f, buf, MAX_STRING_LENGTH, - g->text_string, g->text_length, TRUE, FALSE); - current_paragraph->do_emittext(buf, strlen(buf)); + current_paragraph->do_emittext(g->text_string, g->text_length); output_vpos = g->minv; output_hpos = g->maxh; output_vpos_max = g->maxv; @@ -2137,18 +2328,25 @@ void html_printer::translate_to_html (text_glob *g) void html_printer::flush_sbuf() { - if (sbuf_len > 0) { + if (sbuf.length() > 0) { int r=font::res; // resolution of the device set_style(sbuf_style); + if (overstrike_detected && (! is_bold(sbuf_style.f))) { + font *bold_font = make_bold(sbuf_style.f); + if (bold_font != NULL) + sbuf_style.f = bold_font; + } - page_contents->add(&sbuf_style, sbuf, sbuf_len, + page_contents->add(&sbuf_style, sbuf, line_number, sbuf_vpos-sbuf_style.point_size*r/72, sbuf_start_hpos, sbuf_vpos , sbuf_end_hpos); output_hpos = sbuf_end_hpos; output_vpos = sbuf_vpos; - sbuf_len = 0; + last_sbuf_length = 0; + overstrike_detected = FALSE; + sbuf.clear(); } } @@ -2186,127 +2384,26 @@ void html_printer::draw(int code, int *p, int np, const environment *env) } case 'P': - // fall through + break; case 'p': - { -#if 0 - if (np & 1) { - error("even number of arguments required for polygon"); - break; - } - if (np == 0) { - error("no arguments for polygon"); - break; - } - // firstly lets add our current position to polygon - int oh=env->hpos; - int ov=env->vpos; - int i=0; - - while (i<np) { - p[i+0] += oh; - p[i+1] += ov; - oh = p[i+0]; - ov = p[i+1]; - i += 2; - } - // now store polygon in page - page_contents->add_polygon(code, np, p, env->hpos, env->vpos, env->size, fill); -#endif - } break; case 'E': - // fall through + break; case 'e': -#if 0 - if (np != 2) { - error("2 arguments required for ellipse"); - break; - } - page_contents->add_line(code, - env->hpos, env->vpos-p[1]/2, env->hpos+p[0], env->vpos+p[1]/2, - env->size, fill); -#endif break; case 'C': - // fill circle - + break; case 'c': - { -#if 0 - // troff adds an extra argument to C - if (np != 1 && !(code == 'C' && np == 2)) { - error("1 argument required for circle"); - break; - } - page_contents->add_line(code, - env->hpos, env->vpos-p[0]/2, env->hpos+p[0], env->vpos+p[0]/2, - env->size, fill); -#endif - } break; case 'a': - { -#if 0 - if (np == 4) { - double c[2]; - - if (adjust_arc_center(p, c)) { - page_contents->add_arc('a', env->hpos, env->vpos, p, c, env->size, fill); - } else { - // a straignt line - page_contents->add_line('l', env->hpos, env->vpos, p[0]+p[2], p[1]+p[3], env->size, fill); - } - } else { - error("4 arguments required for arc"); - } -#endif - } break; case '~': - { -#if 0 - if (np & 1) { - error("even number of arguments required for spline"); - break; - } - if (np == 0) { - error("no arguments for spline"); - break; - } - // firstly lets add our current position to spline - int oh=env->hpos; - int ov=env->vpos; - int i=0; - - while (i<np) { - p[i+0] += oh; - p[i+1] += ov; - oh = p[i+0]; - ov = p[i+1]; - i += 2; - } - page_contents->add_spline('~', env->hpos, env->vpos, np, p, env->size, fill); -#endif - } break; case 'f': - { -#if 0 - if (np != 1 && np != 2) { - error("1 argument required for fill"); - break; - } - fill = p[0]; - if (fill < 0 || fill > FILL_MAX) { - // This means fill with the current color. - fill = FILL_MAX + 1; - } -#endif - break; - } + break; case 'F': // fill with color env->fill + background = env->fill; break; default: @@ -2318,7 +2415,8 @@ void html_printer::draw(int code, int *p, int np, const environment *env) html_printer::html_printer() : html(0, MAX_LINE_LENGTH), no_of_printed_pages(0), - sbuf_len(0), + last_sbuf_length(0), + overstrike_detected(FALSE), output_hpos(-1), output_vpos(-1), output_vpos_max(-1), @@ -2336,7 +2434,8 @@ html_printer::html_printer() pageoffset(0), indentation(0), prev_indent(0), - line_number(0) + line_number(0), + background(NULL) { #if defined(DEBUGGING) file_list.add_new_file(stdout); @@ -2362,6 +2461,7 @@ html_printer::html_printer() res = r; html.set_fixed_point(point); space_char_index = font::name_to_index("space"); + space_width = font::hor; paper_length = font::paperlength; linelength = font::res*13/2; if (paper_length == 0) @@ -2371,48 +2471,26 @@ html_printer::html_printer() } /* - * add_char_to_sbuf - adds a single character to the sbuf. - */ - -void html_printer::add_char_to_sbuf (unsigned char code) -{ - if (sbuf_len < SBUF_SIZE) { - sbuf[sbuf_len] = code; - sbuf_len++; - } else { - fatal("need to increase SBUF_SIZE"); - } -} - -/* * add_to_sbuf - adds character code or name to the sbuf. */ -void html_printer::add_to_sbuf (unsigned char code, const char *name) +void html_printer::add_to_sbuf (unsigned char code, const string &s) { - if (name == 0) { - add_char_to_sbuf(code); - } else { - if (sbuf_style.f != NULL) { - char *html_glyph = get_html_translation(sbuf_style.f, name); + char *html_glyph; - if (html_glyph == NULL) { - add_char_to_sbuf(code); - } else { - int l = strlen(html_glyph); - int i; + if (s.empty()) { + html_glyph = get_html_translation(sbuf_style.f, string(code)); + if ((html_glyph == NULL) && (code >= UNICODE_DESC_START)) + html_glyph = to_unicode(code); + } else + if (sbuf_style.f != NULL) + html_glyph = get_html_translation(sbuf_style.f, s); - // Escape the name, so that "&" doesn't get expanded to "&" - // later during translate_to_html. - add_char_to_sbuf('\\'); add_char_to_sbuf('('); - - for (i=0; i<l; i++) { - add_char_to_sbuf(html_glyph[i]); - } - add_char_to_sbuf('\\'); add_char_to_sbuf(')'); - } - } - } + last_sbuf_length = sbuf.length(); + if (html_glyph == NULL) + sbuf += code; + else + sbuf += html_glyph; } int html_printer::sbuf_continuation (unsigned char code, const char *name, @@ -2421,124 +2499,22 @@ int html_printer::sbuf_continuation (unsigned char code, const char *name, if (sbuf_end_hpos == env->hpos) { add_to_sbuf(code, name); sbuf_end_hpos += w + sbuf_kern; - return( TRUE ); + return TRUE; } else { - if ((sbuf_len < SBUF_SIZE-1) && (env->hpos >= sbuf_end_hpos) && + if ((env->hpos >= sbuf_end_hpos) && ((sbuf_kern == 0) || (sbuf_end_hpos - sbuf_kern != env->hpos))) { /* * lets see whether a space is needed or not */ - int space_width = sbuf_style.f->get_space_width(sbuf_style.point_size); - if (env->hpos-sbuf_end_hpos < space_width/2) { + if (env->hpos-sbuf_end_hpos < space_width) { add_to_sbuf(code, name); sbuf_end_hpos = env->hpos + w; - return( TRUE ); + return TRUE; } } } - return( FALSE ); -} - -/* - * seen_backwards_escape - returns TRUE if we can see a escape at position i..l in s - */ - -int html_printer::seen_backwards_escape (char *s, int l) -{ - /* - * this is tricky so it is broken into components for clarity - * (we let the compiler put in all back into a complex expression) - */ - if ((l>0) && (sbuf[l] == '(') && (sbuf[l-1] == '\\')) { - /* - * ok seen '\(' but we must now check for '\\(' - */ - if ((l>1) && (sbuf[l-2] == '\\')) { - /* - * escaped the escape - */ - return( FALSE ); - } else { - return( TRUE ); - } - } else { - return( FALSE ); - } -} - -/* - * reverse - return reversed string. - */ - -char *reverse (char *s) -{ - int i=0; - int j=strlen(s)-1; - char t; - - while (i<j) { - t = s[i]; - s[i] = s[j]; - s[j] = t; - i++; - j--; - } - return( s ); -} - -/* - * remove_last_char_from_sbuf - removes the last character from sbuf. - */ - -char *html_printer::remove_last_char_from_sbuf () -{ - int l=sbuf_len; - static char last[MAX_STRING_LENGTH]; - - if (l>0) { - l--; - if ((sbuf[l] == ')') && (l>0) && (sbuf[l-1] == '\\')) { - /* - * found terminating escape - */ - int i=0; - - l -= 2; - while ((l>0) && (! seen_backwards_escape(sbuf, l))) { - if (sbuf[l] == '\\') { - if (sbuf[l-1] == '\\') { - last[i] = sbuf[l]; - i++; - l--; - } - } else { - last[i] = sbuf[l]; - i++; - } - l--; - } - last[i] = (char)0; - sbuf_len = l; - if (seen_backwards_escape(sbuf, l)) { - sbuf_len--; - } - return( reverse(last) ); - } else { - if ((sbuf[l] == '\\') && (l>0) && (sbuf[l-1] == '\\')) { - l -= 2; - sbuf_len = l; - return( "\\" ); - } else { - sbuf_len--; - last[0] = sbuf[sbuf_len]; - last[1] = (char)0; - return( last ); - } - } - } else { - return( NULL ); - } + return FALSE ; } /* @@ -2546,144 +2522,57 @@ char *html_printer::remove_last_char_from_sbuf () * return the device encoding for such character. */ -char *get_html_translation (font *f, const char *name) +char *get_html_translation (font *f, const string &name) { - int index; + int index; - if ((f == 0) || (name == 0) || (strcmp(name, "") == 0)) { - return( NULL ); - } else { - index = f->name_to_index((char *)name); + if ((f == 0) || name.empty()) + return NULL; + else { + index = f->name_to_index((char *)(name + '\0').contents()); if (index == 0) { - error("character `%s' not found", name); - return( NULL ); - } else { - if (f->contains(index)) { - return( (char *)f->get_special_device_encoding(index) ); - } else { - return( NULL ); - } - } + error("character `%s' not found", (name + '\0').contents()); + return NULL; + } else + if (f->contains(index)) + return (char *)f->get_special_device_encoding(index); + else + return NULL; } } /* - * to_unicode - returns a unicode translation of char, ch. - */ - -static char *to_unicode (unsigned char ch) -{ - static char buf[20]; - - sprintf(buf, "&#%u;", (unsigned int)ch); - return( buf ); -} - -/* - * char_translate_to_html - convert a single non escaped character - * into the appropriate html character. + * overstrike - returns TRUE if the glyph (i, name) is going to overstrike + * a previous glyph in sbuf. + * If TRUE the font is changed to bold and the previous sbuf + * is flushed. */ -int char_translate_to_html (font *f, char *buf, int buflen, unsigned char ch, int b, int and_single) +int html_printer::overstrike(unsigned char code, const char *name, const environment *env, int w) { - if (and_single) { - int t, l; - char *translation; - char name[2]; - - name[0] = ch; - name[1] = (char)0; - translation = get_html_translation(f, name); - if ((translation == NULL) && (ch >= UNICODE_DESC_START)) { - translation = to_unicode(ch); - } - if (translation) { - l = strlen(translation); - t = max(0, min(l, buflen-b)); - strncpy(&buf[b], translation, t); - b += t; - } else { - if (b<buflen) { - buf[b] = ch; - b++; - } - } - } else { + if ((env->hpos < sbuf_end_hpos) + || ((sbuf_kern != 0) && (sbuf_end_hpos - sbuf_kern < env->hpos))) { /* - * do not attempt to encode single characters + * at this point we have detected an overlap */ - if (b<buflen) { - buf[b] = ch; - b++; - } - } - return( b ); -} - -/* - * str_translate_to_html - converts a string, str, into html text. It places - * the output input buffer, buf. It truncates string, str, if - * there is not enough space in buf. - * It looks up the html character encoding of single characters - * if, and_single, is TRUE. Characters such as < > & etc. - * If is_special then we will decode special characters from an escape sequence. - */ - -void str_translate_to_html (font *f, char *buf, int buflen, char *str, int len, int and_single, int is_special) -{ - char *translation; - int e; - char escaped_char[MAX_STRING_LENGTH]; - int l; - int i=0; - int b=0; - int t=0; - -#if 0 - if (strcmp(str, "``@,;:\\\\()[]''") == 0) { - stop(); - } -#endif - while (str[i] != (char)0) { - if ((str[i]=='\\') && (i+1<len) && (str[i+1] == '(') && is_special) { - // start of escape - i += 2; // move over \( - e = 0; - while ((str[i] != (char)0) && - (! ((str[i] == '\\') && (i+1<len) && (str[i+1] == ')')))) { - if (str[i] == '\\') { - i++; - } - escaped_char[e] = str[i]; - e++; - i++; - } - if ((str[i] == '\\') && (i+1<len) && (str[i+1] == ')')) { - i += 2; - } - escaped_char[e] = (char)0; - if (e > 0) { - translation = get_html_translation(f, escaped_char); - if (translation) { - l = strlen(translation); - t = max(0, min(l, buflen-b)); - strncpy(&buf[b], translation, t); - b += t; - } else { - int index=f->name_to_index(escaped_char); - - if (f->contains(index) && (index != 0)) { - buf[b] = f->get_code(index); - b++; - } - } - } + if (overstrike_detected) { + /* already detected, remove previous glyph and use this glyph */ + sbuf.set_length(last_sbuf_length); + add_to_sbuf(code, name); + sbuf_end_hpos = env->hpos + w; + return TRUE; } else { - b = char_translate_to_html(f, buf, buflen, str[i], b, and_single); - i++; + /* first time we have detected an overstrike in the sbuf */ + sbuf.set_length(last_sbuf_length); /* remove previous glyph */ + if (! is_bold(sbuf_style.f)) + flush_sbuf(); + overstrike_detected = TRUE; + add_to_sbuf(code, name); + sbuf_end_hpos = env->hpos + w; + return TRUE; } } - buf[min(b, buflen)] = (char)0; + return FALSE ; } /* @@ -2695,11 +2584,6 @@ void html_printer::set_char(int i, font *f, const environment *env, int w, const { unsigned char code = f->get_code(i); -#if 0 - if (code == ' ') { - stop(); - } -#endif style sty(f, env->size, env->height, env->slant, env->fontno, env->col); if (sty.slant != 0) { if (sty.slant > 80 || sty.slant < -80) { @@ -2707,19 +2591,17 @@ void html_printer::set_char(int i, font *f, const environment *env, int w, const sty.slant = 0; } } - if ((sbuf_len > 0) && (sbuf_len < SBUF_SIZE) && (sty == sbuf_style) && - (sbuf_vpos == env->vpos) && (sbuf_continuation(code, name, env, w))) { + if (((! sbuf.empty()) && (sty == sbuf_style) && (sbuf_vpos == env->vpos)) + && (sbuf_continuation(code, name, env, w) || overstrike(code, name, env, w))) return; - } else { - flush_sbuf(); - sbuf_len = 0; - add_to_sbuf(code, name); - sbuf_end_hpos = env->hpos + w; - sbuf_start_hpos = env->hpos; - sbuf_vpos = env->vpos; - sbuf_style = sty; - sbuf_kern = 0; - } + + flush_sbuf(); + add_to_sbuf(code, name); + sbuf_end_hpos = env->hpos + w; + sbuf_start_hpos = env->hpos; + sbuf_vpos = env->vpos; + sbuf_style = sty; + sbuf_kern = 0; } /* @@ -2773,7 +2655,7 @@ void html_printer::begin_page(int n) output_vpos_max = -1; current_paragraph = new html_text(&html); #if defined(INDENTATION) - current_paragraph->do_indent(indent.text, indentation, pageoffset, linelength); + current_paragraph->do_indent(page_contents->buffer.add_string(indent.text), indentation, pageoffset, linelength); #endif current_paragraph->do_para(""); } @@ -2789,6 +2671,26 @@ font *html_printer::make_font(const char *nm) return html_font::load_html_font(nm); } +void html_printer::do_body (void) +{ + if (background == NULL) + fputs("<body>\n\n", stdout); + else { + double r, g, b; + char buf[6+1]; + + background->get_rgb(&r, &g, &b); + sprintf(buf, "%.2X%.2X%.2X", + (unsigned int)(((double) 0xff)*r), + (unsigned int)(((double) 0xff)*g), + (unsigned int)(((double) 0xff)*b)); + + fputs("<body bgcolor=\"#", stdout); + fputs(buf, stdout); + fputs("\">\n\n", stdout); + } +} + html_printer::~html_printer() { current_paragraph->flush_text(); @@ -2808,7 +2710,8 @@ html_printer::~html_printer() fputs("<meta name=\"Content-Style\" content=\"text/css\">\n", stdout); write_title(TRUE); fputs("</head>\n", stdout); - fputs("<body>\n\n", stdout); + do_body(); + write_title(FALSE); header.write_headings(stdout, FALSE); write_rule(); @@ -2873,7 +2776,6 @@ void html_printer::special(char *s, const environment *env, char type) if (strncmp(s, "html:", 5) == 0) { int r=font::res; /* resolution of the device */ - char buf[MAX_STRING_LENGTH]; font *f=sbuf_style.f; if (f == NULL) { @@ -2881,28 +2783,26 @@ void html_printer::special(char *s, const environment *env, char type) f = font::load_font("TR", &found); } - str_translate_to_html(f, buf, MAX_STRING_LENGTH, - &s[5], strlen(s)-5, FALSE, TRUE); /* * need to pass rest of string through to html output during flush */ - page_contents->add_html(&sbuf_style, buf, strlen(buf), - line_number, - env->vpos-env->size*r/72, env->hpos, - env->vpos , env->hpos); + page_contents->add_and_encode(&sbuf_style, string(&s[5]), + line_number, + env->vpos-env->size*r/72, env->hpos, + env->vpos , env->hpos); /* * assume that the html command has no width, if it does then hopefully troff * will have fudged this in a macro by requesting that the formatting move right by - * the appropriate width. + * the appropriate amount. */ } else if (strncmp(s, "index:", 6) == 0) { cutoff_heading = atoi(&s[6]); } else if (strncmp(s, "html-tag:", 9) == 0) { int r=font::res; /* resolution of the device */ - page_contents->add_tag(&sbuf_style, s, strlen(s), + page_contents->add_tag(&sbuf_style, string(s), line_number, env->vpos-env->size*r/72, env->hpos, env->vpos , env->hpos); @@ -2921,7 +2821,7 @@ int main(int argc, char **argv) { "version", no_argument, 0, 'v' }, { NULL, 0, 0, 0 } }; - while ((c = getopt_long(argc, argv, "o:i:I:D:F:vdlrn", long_options, NULL)) + while ((c = getopt_long(argc, argv, "o:i:I:D:F:vdhlrn", long_options, NULL)) != EOF) switch(c) { case 'v': @@ -2940,6 +2840,10 @@ int main(int argc, char **argv) case 'd': /* handled by pre-html */ break; + case 'h': + /* do not use the Hn headings of html, but manufacture our own */ + manufacture_headings = TRUE; + break; case 'o': /* handled by pre-html */ break; @@ -2978,6 +2882,6 @@ int main(int argc, char **argv) static void usage(FILE *stream) { - fprintf(stream, "usage: %s [-vln] [-D dir] [-I image_stem] [-F dir] [files ...]\n", + fprintf(stream, "usage: %s [-vlnh] [-D dir] [-I image_stem] [-F dir] [files ...]\n", program_name); } diff --git a/src/preproc/html/pre-html.cc b/src/preproc/html/pre-html.cc index 2e8de446..001f9d59 100644 --- a/src/preproc/html/pre-html.cc +++ b/src/preproc/html/pre-html.cc @@ -32,6 +32,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "stringclass.h" #include "posix.h" #include "defs.h" +#include "searchpath.h" #include <errno.h> #include <sys/types.h> @@ -56,7 +57,6 @@ extern "C" const char *Version_string; #include "pushback.h" #include "html-strings.h" -#define POSTSCRIPTRES 72000 // maybe there is a better way to find this? --fixme-- #define DEFAULT_IMAGE_RES 80 // 80 pixels per inch resolution #ifdef PAGEA4 # define DEFAULT_VERTICAL_OFFSET 0 // DEFAULT_VERTICAL_OFFSET/72 of an inch @@ -91,6 +91,7 @@ extern "C" const char *Version_string; typedef enum {CENTERED, LEFT, RIGHT, INLINE} IMAGE_ALIGNMENT; +static int postscriptRes =-1; // postscript resolution, dots per inch static int stdoutfd = 1; // output file descriptor - normally 1 but might move // -1 means closed static int copyofstdoutfd =-1; // a copy of stdout, so we can restore stdout when @@ -110,6 +111,10 @@ static char *troffFileName = NULL; // output of pre-html output whi static char *htmlFileName = NULL; // output of pre-html output which is sent to troff -Thtml #endif +const char *const FONT_ENV_VAR = "GROFF_FONT_PATH"; +static search_path font_path(FONT_ENV_VAR, FONTPATH, 0, 0); + + /* * Images are generated via postscript, gs and the pnm utilities. */ @@ -132,8 +137,34 @@ void sys_fatal (const char *s) } /* + * get_resolution - returns the postscript resolution from devps/DESC + */ + +static int get_resolution (void) +{ + char *pathp; + FILE *f; + unsigned long int res; + int n; + int c; + f = font_path.open_file("devps/DESC", &pathp); + if (f == 0) sys_fatal("fopen"); + while (1) { + n = fscanf(f, " res %lu", &res); + if (n < 0) sys_fatal("EOF"); + if (n >= 1) { + fclose(f); + return res; + } + while (( c = getc(f) ) != '\n') + if (c == EOF) sys_fatal("EOF"); + } +} + +/* * html_system - a wrapper for system() */ + void html_system(const char *s, int redirect_stdout) { // Redirect standard error to the null device. This is more @@ -371,7 +402,7 @@ static void makeFileName (void) static void checkImageDir (void) { if ((image_dir != NULL) && (strcmp(image_dir, "") != 0)) - if (! ((mkdir(image_dir, 0700) == 0) || (errno == EEXIST))) { + if (! ((mkdir(image_dir, 0777) == 0) || (errno == EEXIST))) { error("cannot create directory `%1'", image_dir); exit(1); } @@ -383,17 +414,16 @@ static void checkImageDir (void) static void write_end_image (int is_html) { - if (is_html) { + if (is_html) /* * emit image name and enable output */ writeString("\\O[2]\\O[1]\\O[4]\n"); - } else { + else /* * postscript, therefore emit image boundaries */ writeString("\\O[2]\\O[4]\n"); - } } /* @@ -406,36 +436,29 @@ static void write_end_image (int is_html) static void write_start_image (IMAGE_ALIGNMENT pos, int is_html) { - if (pos == INLINE) { - writeString("\\O[3]\\O[5 "); - writeString(image_template); writeString(".png]"); - } else { - writeString(".begin \\{\\\n"); - switch (pos) { - - case LEFT: - writeString(". image l "); - break; - case RIGHT: - writeString(". image r "); - break; - case CENTERED: - default: - writeString(". image c "); - } - writeString(image_template); writeString(".png\n"); - if (! is_html) { - writeString(".bp\n"); - writeString(".tl ''''\n"); - } - writeString("\\}\n"); + writeString("\\O[3]\\O[5"); + switch (pos) { + + case INLINE: + writeString("i"); + break; + case LEFT: + writeString("l"); + break; + case RIGHT: + writeString("r"); + break; + case CENTERED: + default: + writeString("c"); + break; } - if (is_html) { + writeString(image_template); writeString(".png]"); + if (is_html) writeString("\\O[0]\n"); - } else { + else // reset min/max registers writeString("\\O[0]\\O[1]\n"); - } } /* @@ -786,10 +809,10 @@ static void createImage (imageItem *i) { if (i->X1 != -1) { char *s; - int x1 = max(min(i->X1, i->X2)*image_res/POSTSCRIPTRES-1*IMAGE_BOARDER_PIXELS, 0); - int y1 = max((image_res*vertical_offset/72)+min(i->Y1, i->Y2)*image_res/POSTSCRIPTRES-IMAGE_BOARDER_PIXELS, 0); - int x2 = max(i->X1, i->X2)*image_res/POSTSCRIPTRES+1*IMAGE_BOARDER_PIXELS; - int y2 = (image_res*vertical_offset/72)+(max(i->Y1, i->Y2)*image_res/POSTSCRIPTRES)+1+IMAGE_BOARDER_PIXELS; + int x1 = max(min(i->X1, i->X2)*image_res/postscriptRes-1*IMAGE_BOARDER_PIXELS, 0); + int y1 = max((image_res*vertical_offset/72)+min(i->Y1, i->Y2)*image_res/postscriptRes-IMAGE_BOARDER_PIXELS, 0); + int x2 = max(i->X1, i->X2)*image_res/postscriptRes+1*IMAGE_BOARDER_PIXELS; + int y2 = (image_res*vertical_offset/72)+(max(i->Y1, i->Y2)*image_res/postscriptRes)+1+IMAGE_BOARDER_PIXELS; s = make_message("pnmcut%s %d %d %d %d < %s/%d | pnmcrop | pnmtopng%s %s > %s \n", EXE_EXT, @@ -899,7 +922,7 @@ static void generateImages (char *regionFileName) int y2 = f->readInt(); int maxx = max(f->readInt(), MAX_WIDTH*image_res); char *name = f->readString(); - int res = POSTSCRIPTRES; // --fixme-- prefer (f->readInt()) providing that troff can discover the value + int res = postscriptRes; listOfImages.add(x1, y1, x2, y2, page, res, maxx, name); while ((f->putPB(f->getPB()) != '\n') && (f->putPB(f->getPB()) != eof)) { @@ -1185,7 +1208,7 @@ int scanArguments (int argc, char **argv) { "version", no_argument, 0, 'v' }, { NULL, 0, 0, 0 } }; - while ((c = getopt_long(argc, argv, "+o:i:I:D:F:vdlrn", long_options, NULL)) + while ((c = getopt_long(argc, argv, "+o:i:I:D:F:vdhlrn", long_options, NULL)) != EOF) switch(c) { case 'v': @@ -1200,6 +1223,9 @@ int scanArguments (int argc, char **argv) case 'i': image_res = atoi(optarg); break; + case 'F': + font_path.command_line_dir(optarg); + break; case 'o': vertical_offset = atoi(optarg); break; @@ -1208,6 +1234,9 @@ int scanArguments (int argc, char **argv) debug = TRUE; #endif break; + case 'h': + // handled by post-grohtml + break; case CHAR_MAX + 1: // --help usage(stdout); exit(0); @@ -1288,6 +1317,7 @@ int main(int argc, char **argv) int ok=1; i = scanArguments(argc, argv); + postscriptRes = get_resolution(); checkImageDir(); makeFileName(); while (i < argc) { diff --git a/src/roff/troff/div.h b/src/roff/troff/div.h index 3b726c37..37ec3fa6 100644 --- a/src/roff/troff/div.h +++ b/src/roff/troff/div.h @@ -152,5 +152,6 @@ void push_page_ejector(); void continue_page_eject(); void handle_first_page_transition(); void blank_line(); +void begin_page(void); extern void cleanup_and_exit(int); diff --git a/src/roff/troff/input.cc b/src/roff/troff/input.cc index f2916b0f..b145a218 100644 --- a/src/roff/troff/input.cc +++ b/src/roff/troff/input.cc @@ -138,7 +138,6 @@ static void interpolate_arg(symbol); static request_or_macro *lookup_request(symbol); static int get_delim_number(units *, int); static int get_delim_number(units *, int, units); -static symbol get_delim_file_name(); static int get_line_arg(units *res, int si, charinfo **cp); static int read_size(int *); static symbol get_delim_name(); @@ -1011,7 +1010,7 @@ int non_interpreted_char_node::interpret(macro *mac) static void do_width(); static node *do_non_interpreted(); static node *do_special(); -static node *do_suppress(); +static node *do_suppress(symbol nm); static void do_register(); dictionary color_dictionary(501); @@ -1879,7 +1878,7 @@ void token::next() type = TOKEN_NODE; return; case 'O': - nd = do_suppress(); + nd = do_suppress(read_escape_name()); if (!nd) break; type = TOKEN_NODE; @@ -4357,70 +4356,6 @@ static symbol get_delim_name() } } -static symbol get_delim_file_name() -{ - token start; - start.next(); - if (start.eof()) { - error("end of input at start of delimited file name"); - return NULL_SYMBOL; - } - if (start.newline()) { - error("can't delimit file name with a newline"); - return NULL_SYMBOL; - } - int start_level = input_stack::get_level(); - char abuf[ABUF_SIZE]; - char *buf = abuf; - int buf_size = ABUF_SIZE; - int i = 0; - // move over initial spaces - while (tok.ch() == 0) - tok.next(); - if ((buf[i] = start.ch()) != 0) - i++; - for (;;) { - if (i + 1 > buf_size) { - if (buf == abuf) { - buf = new char[ABUF_SIZE*2]; - memcpy(buf, abuf, buf_size); - buf_size = ABUF_SIZE*2; - } - else { - char *old_buf = buf; - buf = new char[buf_size*2]; - memcpy(buf, old_buf, buf_size); - buf_size *= 2; - a_delete old_buf; - } - } - if ((buf[i] = tok.ch()) == 0) { - error("missing delimiter (got %1)", tok.description()); - if (buf != abuf) - a_delete buf; - return NULL_SYMBOL; - } - i++; - tok.next(); - if (tok.ch() == ']' && input_stack::get_level() == start_level) - break; - } - buf[i] = '\0'; - if (buf == abuf) { - if (i == 0) { - error("empty delimited file name"); - return NULL_SYMBOL; - } - else - return symbol(buf); - } - else { - symbol s(buf); - a_delete buf; - return s; - } -} - // Implement \R static void do_register() @@ -4657,19 +4592,14 @@ node *do_special() return new special_node(mac); } -node *do_suppress() +static node *do_suppress(symbol nm) { - tok.next(); - int c = tok.ch(); - if (c != '[') { - error("argument(s) of \\O must be enclosed in brackets (got %1)", - char(c)); + if (nm.is_null()) { + error("expecting an argument to escape \\O"); return 0; } - tok.next(); - c = tok.ch(); - tok.next(); - switch (c) { + const char *s = nm.contents(); + switch (*s) { case '0': if (begin_level == 1) return new suppress_node(0, 0); @@ -4684,23 +4614,60 @@ node *do_suppress() break; case '3': begin_level++; + if ((begin_level == 1) && (! is_html)) { + if (curdiv == topdiv) { + if (topdiv->before_first_page) { + if (!break_flag) { + if (!topdiv->no_space_mode) + topdiv->begin_page(); + } + else if (topdiv->no_space_mode) + topdiv->begin_page(); + else { + push_page_ejector(); + topdiv->begin_page(); + topdiv->set_ejecting(); + } + } + else { + push_page_ejector(); + if (break_flag) + curenv->do_break(); + if (!topdiv->no_space_mode) + topdiv->set_ejecting(); + } + } + } break; case '4': begin_level--; break; case '5': { - symbol filename = get_delim_file_name(); - if (filename.is_null()) { - error("missing filename as second argument to \\O"); + s++; // move over '5' + char position = *s; + if (*s == (char)0) { + error("missing position and filename in \\O"); + return 0; + } + if (!(position == 'l' + || position == 'r' + || position == 'c' + || position == 'i')) { + error("l, r, c, or i position expected (got %1 in \\O)", position); + return 0; + } + s++; // onto image name + if (s == (char *)0) { + error("missing image name for \\O"); return 0; } if (begin_level == 1) - return new suppress_node(filename, 'i'); + return new suppress_node(symbol(s), position); } break; default: - error("`%1' is an invalid argument to \\O", char(c)); + error("`%1' is an invalid argument to \\O", *s); } return 0; } @@ -4945,65 +4912,6 @@ void else_request() } } -/* - * begin - if this is the outermost html_begin request then execute the - * rest of the line, else skip line - */ - -void begin() -{ - begin_level++; - if (begin_level == 1) - begin_alternative(); - else - skip_alternative(); -} - -/* - * end - if this is the outermost html_end request then execute the - * rest of the line, else skip line - */ - -void end() -{ - begin_level--; - if (begin_level == 0) - begin_alternative(); - else - skip_alternative(); - if (begin_level < 0) - begin_level = 0; -} - -/* - * image - implements the directive `.image {l|r|c|i} filename' - * which places the filename into a node which is later - * written out - * - * . either as a special in the form of an image tag for -Thtml - * . or as an image region definition for all other devices - * - */ - -void image() -{ - if (has_arg()) { - char position = tok.ch(); - if (!(position == 'l' - || position == 'r' - || position == 'c' - || position == 'i')) { - error("l, r, c, or i expected (got %1)", tok.description()); - position = 'c'; - } - tok.next(); - symbol filename = get_long_name(1); - if (!filename.is_null()) - curenv->add_node(new suppress_node(filename, position)); - } - skip_line(); -} - static int while_depth = 0; static int while_break_flag = 0; @@ -6636,7 +6544,6 @@ int main(int argc, char **argv) init_column_requests(); #endif /* COLUMN */ init_node_requests(); - init_markup_requests(); number_reg_dictionary.define(".T", new constant_reg(tflag ? "1" : "0")); init_registers(); init_reg_requests(); @@ -6747,13 +6654,6 @@ void get_output_registers(int *minx, int *miny, int *maxx, int *maxy) *maxy = output_reg_maxy_contents; } -void init_markup_requests() -{ - init_request("begin", begin); - init_request("end", end); - init_request("image", image); -} - void init_input_requests() { init_request("ds", define_string); |