diff options
author | wlemb <wlemb> | 2001-03-16 15:48:30 +0000 |
---|---|---|
committer | wlemb <wlemb> | 2001-03-16 15:48:30 +0000 |
commit | 239e9ceb46c1f27d205552a0d798c29a70fed22f (patch) | |
tree | 141aad6d1561b15b9185d4311ea1f8cf3aabd2fa | |
parent | e8ba685419d4a0741a0fcde4a313d9d88ca5d1a7 (diff) | |
download | groff-239e9ceb46c1f27d205552a0d798c29a70fed22f.tar.gz |
Introduced simple html tables to implement indentation.
* src/devices/grohtml/html.h (word, word_list): New structures.
(simple_output): Use it.
* src/devices/grohtml/post-html.cc: Add `INDENTATION'.
(html_printer): Improve indentation handling.
(html_printer::emit_raw): Set `in_table' element. Handle
indentation if set.
(html_printer::write_header): Move conditional downwards.
Don't allow whitespace in tags.
(html_printer::do_linelength): Handle line length and indentation
conditionally.
(html_printer::do_pageoffset): Handle indentation conditionally.
(html_printer::do_indentation): Ditto.
(html_printer::do_tempindent): New function member.
(html_printer::do_fill): Take care of indentation.
(html_printer::do_flush): Finish table.
(html_printer::do_links): Ditto.
(html_printer::do_break): New function for handling `.br' and `.ti'.
(html_printer::troff_tag): Use it.
Handle `.ti'.
(html_printer::flush_globs): Fix.
(html_printer::flush_page): Finish table.
(html_printer::html_printer): Fix error message. Set up
`linelength'.
(html_printer::add_to_sbuf): Remove special handling of character
code 255.
(to_unicode): Remove `stop()'.
(html_printer::write_title): Cleanup.
(html_printer::begin_page): Use `put_string()'. Handle indentation.
(html_printer::~html_printer): Flush text and end the line.
Use `put_string()'.
* src/devices/grohtml/html_text.h: Add more *_TAG enum values.
* src/devices/grohtml/html_text.cc (html_text::end_tag): Fix
emission of tags.
(html_text::start_tag): Disable newlines.
(html_text::table_is_void): New function.
(html_text::issue_table_begin): Ditto.
(html_text::issue_table_end): Ditto.
(html_text::push_para): Better table handling.
(html_text::do_indent): New function.
(html_text::do_table): Ditto.
(html_text::done_table): Ditto.
(html_text::do_tt): Handle PRE_TAG.
(html_text::is_in_table): New function.
(html_text::check_emit_text): Handle tables.
(html_text::do_emittext): Use `nl()'.
(html_text::do_para): Handle table.
(html_text::remove_def): New function.
* src/devices/grohtml/output.cc (word, word_list): Implement
methods.
(simple_output::end_line): Flush last word.
(simple_output::simple_comment): Ditto.
(simple_output::begin_comment): Recoded.
(simple_output::end_comment): Ditto.
(simple_output::comment_arg): Removed.
(simple_output::check_newline): Improve test and flush last word.
(simple_output::space_or_newline): Improved.
(simple_output::write_newline): Replaced with...
(simple_output::nl): This.
(simple_output::put_raw_char): Flush last word.
(simple_output::check_space): Removed.
(simple_output::put_translated_string): Ditto.
(simple_output::put_string): Simplified.
(simple_output::put_number): Updated.
(simple_output::put_float): Ditto.
(simple_output::put_symbol): Removed.
(simple_output::enable_newlines): Add `check_newline()'.
(simple_output::flush_last_word): New function.
* src/roff/troff/enc.cc (no_fill): Remove call to add_html_tag().
* src/roff/troff/div.cc (page_offset): Add call to add_html_tag().
* tmac/s.tmac (@PP, @IP): Add html conditional code.
* tmac/an-old.tmac (TP): Ditto.
* mdate.sh: Make it POSIX compliant.
-rw-r--r-- | ChangeLog | 80 | ||||
-rw-r--r-- | src/devices/grohtml/html-text.cc | 210 | ||||
-rw-r--r-- | src/devices/grohtml/html-text.h | 30 | ||||
-rw-r--r-- | src/devices/grohtml/html.h | 46 | ||||
-rw-r--r-- | src/devices/grohtml/output.cc | 278 | ||||
-rw-r--r-- | src/devices/grohtml/post-html.cc | 156 | ||||
-rw-r--r-- | src/roff/troff/div.cc | 1 | ||||
-rw-r--r-- | src/roff/troff/env.cc | 6 | ||||
-rw-r--r-- | tmac/an-old.tmac | 3 | ||||
-rw-r--r-- | tmac/s.tmac | 15 |
10 files changed, 612 insertions, 213 deletions
@@ -1,6 +1,84 @@ +2001-03-16 Gaius Mulley <gaius@glam.ac.uk> + + Introduced simple html tables to implement indentation. + + * src/devices/grohtml/html.h (word, word_list): New structures. + (simple_output): Use it. + * src/devices/grohtml/post-html.cc: Add `INDENTATION'. + (html_printer): Improve indentation handling. + (html_printer::emit_raw): Set `in_table' element. Handle + indentation if set. + (html_printer::write_header): Move conditional downwards. + Don't allow whitespace in tags. + (html_printer::do_linelength): Handle line length and indentation + conditionally. + (html_printer::do_pageoffset): Handle indentation conditionally. + (html_printer::do_indentation): Ditto. + (html_printer::do_tempindent): New function member. + (html_printer::do_fill): Take care of indentation. + (html_printer::do_flush): Finish table. + (html_printer::do_links): Ditto. + (html_printer::do_break): New function for handling `.br' and `.ti'. + (html_printer::troff_tag): Use it. + Handle `.ti'. + (html_printer::flush_globs): Fix. + (html_printer::flush_page): Finish table. + (html_printer::html_printer): Fix error message. Set up + `linelength'. + (html_printer::add_to_sbuf): Remove special handling of character + code 255. + (to_unicode): Remove `stop()'. + (html_printer::write_title): Cleanup. + (html_printer::begin_page): Use `put_string()'. Handle indentation. + (html_printer::~html_printer): Flush text and end the line. + Use `put_string()'. + * src/devices/grohtml/html_text.h: Add more *_TAG enum values. + * src/devices/grohtml/html_text.cc (html_text::end_tag): Fix + emission of tags. + (html_text::start_tag): Disable newlines. + (html_text::table_is_void): New function. + (html_text::issue_table_begin): Ditto. + (html_text::issue_table_end): Ditto. + (html_text::push_para): Better table handling. + (html_text::do_indent): New function. + (html_text::do_table): Ditto. + (html_text::done_table): Ditto. + (html_text::do_tt): Handle PRE_TAG. + (html_text::is_in_table): New function. + (html_text::check_emit_text): Handle tables. + (html_text::do_emittext): Use `nl()'. + (html_text::do_para): Handle table. + (html_text::remove_def): New function. + * src/devices/grohtml/output.cc (word, word_list): Implement + methods. + (simple_output::end_line): Flush last word. + (simple_output::simple_comment): Ditto. + (simple_output::begin_comment): Recoded. + (simple_output::end_comment): Ditto. + (simple_output::comment_arg): Removed. + (simple_output::check_newline): Improve test and flush last word. + (simple_output::space_or_newline): Improved. + (simple_output::write_newline): Replaced with... + (simple_output::nl): This. + (simple_output::put_raw_char): Flush last word. + (simple_output::check_space): Removed. + (simple_output::put_translated_string): Ditto. + (simple_output::put_string): Simplified. + (simple_output::put_number): Updated. + (simple_output::put_float): Ditto. + (simple_output::put_symbol): Removed. + (simple_output::enable_newlines): Add `check_newline()'. + (simple_output::flush_last_word): New function. + + * src/roff/troff/enc.cc (no_fill): Remove call to add_html_tag(). + * src/roff/troff/div.cc (page_offset): Add call to add_html_tag(). + + * tmac/s.tmac (@PP, @IP): Add html conditional code. + * tmac/an-old.tmac (TP): Ditto. + 2001-03-09 Ruslan Ermilov <ru@freebsd.org> - mdate.sh: Make it POSIX compliant. + * mdate.sh: Make it POSIX compliant. 2001-03-09 Werner LEMBERG <wl@gnu.org> diff --git a/src/devices/grohtml/html-text.cc b/src/devices/grohtml/html-text.cc index 1621085b..63794125 100644 --- a/src/devices/grohtml/html-text.cc +++ b/src/devices/grohtml/html-text.cc @@ -42,7 +42,8 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ html_text::html_text (simple_output *op) : - stackptr(NULL), lastptr(NULL), out(op), space_emitted(TRUE) + stackptr(NULL), lastptr(NULL), out(op), space_emitted(TRUE), + current_indentation(-1), pageoffset(-1), linelength(-1) { } @@ -61,13 +62,19 @@ void html_text::end_tag (tag_definition *t) case I_TAG: out->put_string("</i>"); break; case B_TAG: out->put_string("</b>"); break; - case P_TAG: out->put_string("</p>"); out->write_newline(); out->enable_newlines(FALSE); break; + case P_TAG: out->put_string("</p>").nl().enable_newlines(FALSE); break; case SUB_TAG: out->put_string("</sub>"); break; case SUP_TAG: out->put_string("</sup>"); break; case TT_TAG: out->put_string("</tt>"); break; - case PRE_TAG: out->put_string("</pre>\n"); out->enable_newlines(TRUE); break; + case PRE_TAG: out->put_string("</pre>"); + if (! is_present(TABLE_TAG)) { + out->nl(); + out->enable_newlines(TRUE); + } + break; case SMALL_TAG: out->put_string("</small>"); break; case BIG_TAG: out->put_string("</big>"); break; + case TABLE_TAG: issue_table_end(); break; default: error("unrecognised tag"); @@ -101,13 +108,16 @@ void html_text::start_tag (tag_definition *t) case I_TAG: issue_tag("<i", t->arg1); break; case B_TAG: issue_tag("<b", t->arg1); break; - case P_TAG: issue_tag("\n<p", t->arg1); out->enable_newlines(TRUE); break; + case P_TAG: issue_tag("\n<p", t->arg1); + out->enable_newlines(TRUE); break; case SUB_TAG: issue_tag("<sub", t->arg1); break; case SUP_TAG: issue_tag("<sup", t->arg1); break; case TT_TAG: issue_tag("<tt", t->arg1); break; - case PRE_TAG: issue_tag("\n<pre", t->arg1); out->enable_newlines(FALSE); break; + case PRE_TAG: out->nl(); issue_tag("<pre", t->arg1); + out->enable_newlines(FALSE); break; case SMALL_TAG: issue_tag("<small", t->arg1); break; case BIG_TAG: issue_tag("<big", t->arg1); break; + case TABLE_TAG: issue_table_begin(t); break; case BREAK_TAG: break; default: @@ -115,6 +125,35 @@ void html_text::start_tag (tag_definition *t) } } +int html_text::table_is_void (tag_definition *t) +{ + if (linelength > 0) { + return( current_indentation*100/linelength <= 0 ); + } else { + return( FALSE ); + } +} + +void html_text::issue_table_begin (tag_definition *t) +{ + if (linelength > 0) { + int width=current_indentation*100/linelength; + + if (width > 0) { + out->put_string("<table width=\"100%\" rules=\"none\" frame=\"none\"\n cols=\"2\" cellspacing=\"0\" cellpadding=\"0\">").nl(); + out->put_string("<tr valign=\"top\" align=\"left\">").nl(); + out->put_string("<td width=\"").put_number(width).put_string("%\"></td>"); + out->put_string("<td width=\"").put_number(100-width).put_string("%\">").nl(); + } + } +} + +void html_text::issue_table_end (void) +{ + out->put_string("</td></table>").nl(); + out->enable_newlines(TRUE); +} + /* * flush_text - flushes html tags which are outstanding on the html stack. */ @@ -166,13 +205,44 @@ void html_text::push_para (HTML_TAG t, char *arg) p->text_emitted = FALSE; /* - * if t is a P_TAG or PRE_TAG make sure it goes on the end of the stack. + * if t is a P_TAG or TABLE_TAG or PRE_TAG make sure it goes on the end of the stack. + * But we insist that a TABLE_TAG is always after a PRE_TAG + * and that a P_TAG is always after a TABLE_TAG */ - if (((t == P_TAG) || (t == PRE_TAG)) && (lastptr != NULL)) { - lastptr->next = p; - lastptr = p; - p->next = NULL; + if (((t == P_TAG) || (t == PRE_TAG) || (t == TABLE_TAG)) && + (lastptr != NULL)) { + if (((lastptr->type == TABLE_TAG) && (t == PRE_TAG)) || + ((lastptr->type == P_TAG) && (t == TABLE_TAG))) { + /* + * insert p before the lastptr + */ + if (stackptr == lastptr) { + /* + * only on element of the stack + */ + p->next = stackptr; + stackptr = p; + } else { + /* + * more than one element is on the stack + */ + tag_definition *q = stackptr; + + while (q->next != lastptr) { + q = q->next; + } + q->next = p; + p->next = lastptr; + } + } else { + /* + * store, p, at the end + */ + lastptr->next = p; + lastptr = p; + p->next = NULL; + } } else { p->next = stackptr; if (stackptr == NULL) @@ -182,6 +252,51 @@ void html_text::push_para (HTML_TAG t, char *arg) } /* + * do_indent - remember the indent parameters and if + * indent is > pageoff and indent has changed + * then we start a html table to implement the indentation. + */ + +void html_text::do_indent (int indent, int pageoff, int linelen) +{ + if ((current_indentation != -1) && + (pageoffset+current_indentation != indent+pageoff)) { + /* + * actual indentation of text has changed, we need to put + * a table tag onto the stack. + */ + do_table(); + } + current_indentation = indent; + pageoffset = pageoff; + linelength = linelen; +} + +void html_text::do_table (void) +{ + int in_pre = is_in_pre(); + // char *para_type = done_para(); + done_pre(); + shutdown(TABLE_TAG); // shutdown a previous table, if present + remove_break(); + if (in_pre) { + do_pre(); + } + // do_para(para_type); + push_para(TABLE_TAG, ""); +} + +/* + * done_table - terminates a possibly existing table. + */ + +void html_text::done_table (void) +{ + shutdown(TABLE_TAG); + space_emitted = TRUE; +} + +/* * do_italic - changes to italic */ @@ -215,7 +330,7 @@ void html_text::do_tt (void) { done_bold(); done_italic(); - if (! is_present(TT_TAG)) { + if ((! is_present(TT_TAG)) && (! is_present(PRE_TAG))) { push_para(TT_TAG, ""); } } @@ -246,6 +361,15 @@ int html_text::is_in_pre (void) } /* + * is_in_table - returns TRUE if we are currently within a table. + */ + +int html_text::is_in_table (void) +{ + return( is_present(TABLE_TAG) ); +} + +/* * shutdown - shuts down an html tag. */ @@ -389,9 +513,37 @@ void html_text::done_big (void) void html_text::check_emit_text (tag_definition *t) { if ((t != NULL) && (! t->text_emitted)) { - check_emit_text(t->next); - t->text_emitted = TRUE; - start_tag(t); + /* + * we peep and see whether there is a <p> before the <table> + * in which case we skip the <p> + */ + if (t->type == TABLE_TAG) { + if (table_is_void(t)) { + tag_definition *n = t->next; + remove_def(t); + check_emit_text(n); + } else { + /* + * a table which will be emitted, is there a <p> succeeding it? + */ + if ((t->next != NULL) && + (t->next->type == P_TAG) && + ((t->next->arg1 == 0) || strcmp(t->next->arg1, "") == 0)) { + /* + * yes skip the <p> + */ + check_emit_text(t->next->next); + } else { + check_emit_text(t->next); + } + t->text_emitted = TRUE; + start_tag(t); + } + } else { + check_emit_text(t->next); + t->text_emitted = TRUE; + start_tag(t); + } } } @@ -409,9 +561,9 @@ void html_text::do_emittext (char *s, int length) check_emit_text(stackptr); if (text) { if (is_present(PRE_TAG)) { - out->put_string("\n"); + out->nl(); } else { - out->put_string("<br>\n"); + out->put_string("<br>").nl(); } } } else { @@ -430,6 +582,9 @@ void html_text::do_para (char *arg) done_pre(); if (! is_present(P_TAG)) { remove_sub_sup(); + if ((arg != 0) && (strcmp(arg, "") != 0)) { + remove_tag(TABLE_TAG); + } push_para(P_TAG, arg); space_emitted = TRUE; } @@ -509,20 +664,20 @@ int html_text::emit_space (void) } /* - * remove_tag - removes a tag from the stack. + * remove_def - removes a definition, t, from the stack. */ -void html_text::remove_tag (HTML_TAG tag) +void html_text::remove_def (tag_definition *t) { tag_definition *p = stackptr; tag_definition *l = 0; tag_definition *q = 0; - while ((p != 0) && (p->type != tag)) { + while ((p != 0) && (p != t)) { l = p; p = p->next; } - if ((p != 0) && (p->type == tag)) { + if ((p != 0) && (p == t)) { if (p == stackptr) { stackptr = stackptr->next; if (stackptr == NULL) @@ -541,6 +696,21 @@ void html_text::remove_tag (HTML_TAG tag) } /* + * remove_tag - removes a tag from the stack. + */ + +void html_text::remove_tag (HTML_TAG tag) +{ + tag_definition *p = stackptr; + + while ((p != 0) && (p->type != tag)) { + p = p->next; + } + if ((p != 0) && (p->type == tag)) + remove_def(p); +} + +/* * remove_sub_sup - removes a sub or sup tag, should either exist on the stack. */ diff --git a/src/devices/grohtml/html-text.h b/src/devices/grohtml/html-text.h index b9164e6e..47182a4c 100644 --- a/src/devices/grohtml/html-text.h +++ b/src/devices/grohtml/html-text.h @@ -31,7 +31,8 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ * html tags */ -typedef enum {I_TAG, B_TAG, P_TAG, SUB_TAG, SUP_TAG, TT_TAG, PRE_TAG, SMALL_TAG, BIG_TAG, BREAK_TAG} HTML_TAG; +typedef enum {I_TAG, B_TAG, P_TAG, SUB_TAG, SUP_TAG, TT_TAG, + PRE_TAG, SMALL_TAG, BIG_TAG, BREAK_TAG, TABLE_TAG} HTML_TAG; typedef struct tag_definition { HTML_TAG type; @@ -65,6 +66,7 @@ public: void do_space (void); void do_break (void); void do_newline (void); + void do_table (void); void done_bold (void); void done_italic (void); char *done_para (void); @@ -74,24 +76,34 @@ public: void done_pre (void); void done_small (void); void done_big (void); + void do_indent (int indent, int pageoff, int linelen); int emitted_text (void); int emit_space (void); int is_in_pre (void); void remove_tag (HTML_TAG tag); void remove_sub_sup (void); + void done_table (void); + int is_in_table (void); private: tag_definition *stackptr; /* the current paragraph state */ tag_definition *lastptr; /* the end of the stack */ simple_output *out; int space_emitted; + int current_indentation; /* current .in value */ + int pageoffset; /* .po value */ + int linelength; /* current line length */ - int is_present (HTML_TAG t); - void end_tag (tag_definition *t); - void start_tag (tag_definition *t); - void push_para (HTML_TAG t, char *arg); - char *shutdown (HTML_TAG t); - void check_emit_text (tag_definition *t); - int remove_break (void); - void issue_tag (char *tagname, char *arg); + int is_present (HTML_TAG t); + void end_tag (tag_definition *t); + void start_tag (tag_definition *t); + void push_para (HTML_TAG t, char *arg); + char *shutdown (HTML_TAG t); + void check_emit_text (tag_definition *t); + int remove_break (void); + void issue_tag (char *tagname, char *arg); + void issue_table_begin (tag_definition *t); + void issue_table_end (void); + int table_is_void (tag_definition *t); + void remove_def (tag_definition *t); }; diff --git a/src/devices/grohtml/html.h b/src/devices/grohtml/html.h index 3e442b8f..69b6e35e 100644 --- a/src/devices/grohtml/html.h +++ b/src/devices/grohtml/html.h @@ -21,7 +21,32 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #if !defined(HTML_H) # define HTML_H # undef DEBUGGING -// #define DEBUGGING +// # define DEBUGGING + +/* + * class and structure needed to buffer words + */ + +struct word { + char *s; + word *next; + + word (const char *w, int n); + ~word (); +}; + +class word_list { +public: + word_list (); + int flush (FILE *f); + void add_word (const char *s, int n); + int get_length (void); + +private: + int length; + word *head; + word *tail; +}; class simple_output { public: @@ -47,17 +72,20 @@ public: simple_output &special(const char *); simple_output &enable_newlines(int); simple_output &check_newline(int n); - simple_output &write_newline(void); + simple_output &nl(void); simple_output &space_or_newline (void); - simple_output &check_space (int n); + simple_output &begin_tag (void); FILE *get_file(); private: - FILE *fp; - int max_line_length; // not including newline - int col; - int need_space; - int fixed_point; - int newlines; // can we issue newlines automatically? + FILE *fp; + int max_line_length; // not including newline + int col; + int fixed_point; + int newlines; // can we issue newlines automatically? + word_list last_word; + + void flush_last_word (void); + int check_space (const char *s, int n); }; inline FILE *simple_output::get_file() diff --git a/src/devices/grohtml/output.cc b/src/devices/grohtml/output.cc index 15b26f2c..4c72bba7 100644 --- a/src/devices/grohtml/output.cc +++ b/src/devices/grohtml/output.cc @@ -46,11 +46,91 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #endif /* + * word - initialise a word and set next to NULL + */ + +word::word (const char *w, int n) + : next(0) +{ + s = (char *)malloc(n+1); + strncpy(s, w, n); + s[n] = (char)0; +} + +/* + * destroy word and the string copy. + */ + +word::~word () +{ + free(s); +} + +/* + * word_list - create an empty word list. + */ + +word_list::word_list () + : head(0), tail(0), length(0) +{ +} + +/* + * flush - flush a word list to a FILE, f, and return the + * length of the buffered string. + */ + +int word_list::flush (FILE *f) +{ + word *t; + int len=length; + + while (head != 0) { + t = head; + head = head->next; + fputs(t->s, f); + delete t; + } + head = 0; + tail = 0; + length = 0; +#if defined(DEBUGGING) + fflush(f); // just for testing +#endif + return( len ); +} + +/* + * add_word - adds a word to the outstanding word list. + */ + +void word_list::add_word (const char *s, int n) +{ + if (head == 0) { + head = new word(s, n); + tail = head; + } else { + tail->next = new word(s, n); + tail = tail->next; + } + length += n; +} + +/* + * get_length - returns the number of characters buffered + */ + +int word_list::get_length (void) +{ + return( length ); +} + +/* * the classes and methods for simple_output manipulation */ simple_output::simple_output(FILE *f, int n) -: fp(f), max_line_length(n), col(0), need_space(0), fixed_point(0), newlines(0) +: fp(f), max_line_length(n), col(0), fixed_point(0), newlines(0) { } @@ -72,10 +152,10 @@ simple_output &simple_output::copy_file(FILE *infp) simple_output &simple_output::end_line() { + flush_last_word(); if (col != 0) { putc('\n', fp); col = 0; - need_space = 0; } return *this; } @@ -87,55 +167,33 @@ simple_output &simple_output::special(const char *s) simple_output &simple_output::simple_comment(const char *s) { + flush_last_word(); if (col != 0) putc('\n', fp); fputs("<!-- ", fp); fputs(s, fp); fputs(" -->\n", fp); col = 0; - need_space = 0; return *this; } simple_output &simple_output::begin_comment(const char *s) { + flush_last_word(); if (col != 0) putc('\n', fp); - fputs("<!-- ", fp); - fputs(s, fp); - need_space = 0; - col = 5 + strlen(s); - return *this; -} - -simple_output &simple_output::end_comment() -{ - if (need_space) { - putc(' ', fp); - } - fputs("-->\n", fp); col = 0; - need_space = 0; + put_string("<!--"); + space_or_newline(); + last_word.add_word(s, strlen(s)); return *this; } -simple_output &simple_output::comment_arg(const char *s) +simple_output &simple_output::end_comment() { - int len = strlen(s); - int i = 0; - - if (col + len + 1 > max_line_length) { - fputs("\n ", fp); - col = 1; - } - while (i < len) { - if (s[i] != '\n') { - putc(s[i], fp); - col++; - } - i++; - } - need_space = 1; + flush_last_word(); + space_or_newline(); + put_string("-->").nl(); return *this; } @@ -146,10 +204,9 @@ simple_output &simple_output::comment_arg(const char *s) simple_output &simple_output::check_newline(int n) { - if ((col + n > max_line_length) && (newlines)) { + if ((col + n + last_word.get_length() + 1 > max_line_length) && (newlines)) { fputc('\n', fp); - need_space = 0; - col = 0; + col = last_word.flush(fp); } } @@ -160,27 +217,41 @@ simple_output &simple_output::check_newline(int n) simple_output &simple_output::space_or_newline (void) { - if ((col + 1 > max_line_length) && (newlines)) { +#if defined(DEBUGGING) + fflush(fp); // just for testing +#endif + if ((col + last_word.get_length() + 1 > max_line_length) && (newlines)) { fputc('\n', fp); - need_space = 0; - col = 0; + if (last_word.get_length() > 0) { + col = last_word.flush(fp); + } else { + col = 0; + } } else { - need_space = 1; + if (last_word.get_length() != 0) { + if (col > 0) { + fputc(' ', fp); + col++; + } + col += last_word.flush(fp); + } } } /* - * write_newline - writes a newline providing that we - * are not in the first column. + * nl - writes a newline providing that we + * are not in the first column. */ -simple_output &simple_output::write_newline (void) +simple_output &simple_output::nl (void) { + space_or_newline(); + col += last_word.flush(fp); if (col != 0) { fputc('\n', fp); - need_space = 0; col = 0; } + return *this ; } simple_output &simple_output::set_fixed_point(int n) @@ -192,83 +263,21 @@ simple_output &simple_output::set_fixed_point(int n) simple_output &simple_output::put_raw_char(char c) { + col += last_word.flush(fp); putc(c, fp); col++; - need_space = 0; return *this; } -/* - * check_space - writes a space if required. - */ - -simple_output &simple_output::check_space (int n) -{ - check_newline(n); - if (need_space) { - fputc(' ', fp); - need_space = 0; - col++; - } -} - simple_output &simple_output::put_string(const char *s, int n) { - int i=0; - - check_space(n); - - while (i<n) { - fputc(s[i], fp); - i++; - } -#if defined(DEBUGGING) - fflush(fp); // just for testing -#endif - col += n; - return *this; -} - -simple_output &simple_output::put_translated_string(const char *s) -{ - int i=0; - - check_space(strlen(s)); - - while (s[i] != (char)0) { - if ((s[i] & 0x7f) == s[i]) { - fputc(s[i], fp); - } - i++; - } -#if defined(DEBUGGING) - fflush(fp); // just for testing -#endif - col += i; + last_word.add_word(s, n); return *this; } simple_output &simple_output::put_string(const char *s) { - int i=0; - int j=0; - - check_space(strlen(s)); - - while (s[i] != '\0') { - fputc(s[i], fp); - if (s[i] == '\n') { - col = 0; - j = 0; - } else { - j++; - } - i++; - } - col += j; -#if defined(DEBUGGING) - fflush(fp); // just for testing -#endif + last_word.add_word(s, strlen(s)); return *this; } @@ -276,8 +285,7 @@ simple_output &simple_output::put_number(int n) { char buf[1 + INT_DIGITS + 1]; sprintf(buf, "%d", n); - int len = strlen(buf); - put_string(buf, len); + put_string(buf); return *this; } @@ -286,28 +294,42 @@ simple_output &simple_output::put_float(double d) char buf[128]; sprintf(buf, "%.4f", d); - int len = strlen(buf); - put_string(buf, len); - need_space = 1; - return *this; -} - -simple_output &simple_output::put_symbol(const char *s) -{ - int len = strlen(s); - - if (need_space) { - putc(' ', fp); - col++; - } - fputs(s, fp); - col += len; - need_space = 1; + put_string(buf); return *this; } simple_output &simple_output::enable_newlines (int auto_newlines) { + check_newline(0); newlines = auto_newlines; check_newline(0); } + +/* + * flush_last_word - flushes the last word and adjusts the + * col position. It will insert a newline + * before the last word if allowed and if + * necessary. + */ + +void simple_output::flush_last_word (void) +{ + int len=last_word.get_length(); + + if (len > 0) { + if (newlines) { + if (col + len + 1 > max_line_length) { + fputs("\n", fp); + col = 0; + } else { + fputs(" ", fp); + col++; + } + len += last_word.flush(fp); + } else { + fputs(" ", fp); + col++; + col += last_word.flush(fp); + } + } +} diff --git a/src/devices/grohtml/post-html.cc b/src/devices/grohtml/post-html.cc index e025cb48..dc608854 100644 --- a/src/devices/grohtml/post-html.cc +++ b/src/devices/grohtml/post-html.cc @@ -55,6 +55,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #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; */ +#define INDENTATION /* #undef INDENTATION to remove .in handling */ typedef enum {CENTERED, LEFT, RIGHT, INLINE} TAG_ALIGNMENT; @@ -967,11 +968,13 @@ class html_printer : public printer { page *page_contents; html_text *current_paragraph; int end_center; + int end_tempindent; TAG_ALIGNMENT next_tag; int fill_on; int linelength; int pageoffset; int indentation; + int prev_indent; int pointsize; int vertical_spacing; int line_number; @@ -1007,9 +1010,8 @@ class html_printer : public printer { int is_courier_until_eol (void); void start_size (int from, int to); void do_font (text_glob *g); - void do_space (void); - void do_break (void); void do_center (char *arg); + void do_break (void); void do_eol (void); void do_title (void); void do_fill (int on); @@ -1019,13 +1021,13 @@ class html_printer : public printer { void do_linelength (char *arg); void do_pageoffset (char *arg); void do_indentation (char *arg); + void do_tempindent (char *arg); void do_verticalspacing (char *arg); void do_pointsize (char *arg); void do_centered_image (void); void do_left_image (void); void do_right_image (void); void do_auto_image (text_glob *g, const char *filename); - void do_indent (char *arg); void do_links (void); void do_flush (void); int is_in_middle (int left, int right); @@ -1094,6 +1096,8 @@ void html_printer::emit_raw (text_glob *g) determine_space(g); current_paragraph->do_emittext(g->text_string, g->text_length); } else { + int in_table=current_paragraph->is_in_table(); + current_paragraph->done_para(); switch (next_tag) { @@ -1113,6 +1117,13 @@ void html_printer::emit_raw (text_glob *g) current_paragraph->done_para(); next_tag = INLINE; supress_sub_sup = TRUE; +#if defined(INDENTATION) + if (in_table) { + stop(); + current_paragraph->do_indent(0, pageoffset, linelength); + current_paragraph->do_indent(indentation, pageoffset, linelength); + } +#endif } } @@ -1276,11 +1287,12 @@ void html_printer::write_header (void) header.header_level = 7; } - if (cutoff_heading+2 > header.header_level) { - // firstly we must terminate any font and type faces - current_paragraph->done_para(); - supress_sub_sup = TRUE; + // firstly we must terminate any font and type faces + current_paragraph->done_para(); + current_paragraph->done_table(); + supress_sub_sup = TRUE; + if (cutoff_heading+2 > header.header_level) { // now we save the header so we can issue a list of links header.no_of_headings++; style st; @@ -1298,7 +1310,7 @@ void html_printer::write_header (void) // lastly we generate a tag - html.put_string("\n<a name=\""); + html.nl().put_string("<a name=\""); if (simple_anchors) { char buffer[MAX_LINE_LENGTH]; @@ -1307,10 +1319,7 @@ void html_printer::write_header (void) } else { html.put_string(header.header_buffer); } - html.put_string("\"></a>\n"); - } else { - current_paragraph->done_para(); - supress_sub_sup = TRUE; + html.put_string("\"></a>").nl(); } // and now we issue the real header @@ -1320,7 +1329,7 @@ void html_printer::write_header (void) html.put_string(header.header_buffer); html.put_string("</h"); html.put_number(header.header_level); - html.put_string(">\n"); + html.put_string(">").nl(); current_paragraph->do_para(""); } @@ -1420,7 +1429,12 @@ int html_printer::is_courier_until_eol (void) void html_printer::do_linelength (char *arg) { - linelength = atoi(arg); +#if defined(INDENTATION) + if (fill_on) { + linelength = atoi(arg); + current_paragraph->do_indent(indentation, pageoffset, linelength); + } +#endif } /* @@ -1429,7 +1443,12 @@ void html_printer::do_linelength (char *arg) void html_printer::do_pageoffset (char *arg) { +#if defined(INDENTATION) pageoffset = atoi(arg); + if (fill_on) { + current_paragraph->do_indent(indentation, pageoffset, linelength); + } +#endif } /* @@ -1438,7 +1457,28 @@ void html_printer::do_pageoffset (char *arg) void html_printer::do_indentation (char *arg) { - indentation = atoi(arg); +#if defined(INDENTATION) + if (fill_on) { + indentation = atoi(arg); + current_paragraph->do_indent(indentation, pageoffset, linelength); + } +#endif +} + +/* + * do_tempindent - handle the .ti command from troff. + */ + +void html_printer::do_tempindent (char *arg) +{ +#if defined(INDENTATION) + if (fill_on) { + end_tempindent = 1; + prev_indent = indentation; + indentation = atoi(arg); + current_paragraph->do_indent(indentation, pageoffset, linelength); + } +#endif } /* @@ -1465,6 +1505,10 @@ void html_printer::do_pointsize (char *arg) void html_printer::do_fill (int on) { + current_paragraph->do_break(); + output_hpos = indentation+pageoffset; + supress_sub_sup = TRUE; + if (fill_on != on) { if (is_font_courier(output_style.f) && (is_courier_until_eol())) { if (on) { @@ -1487,7 +1531,7 @@ void html_printer::do_eol (void) current_paragraph->do_newline(); current_paragraph->do_break(); } - output_hpos = pageoffset; + output_hpos = indentation+pageoffset; if (end_center > 0) { if (end_center > 1) { current_paragraph->do_break(); @@ -1507,6 +1551,7 @@ void html_printer::do_eol (void) void html_printer::do_flush (void) { current_paragraph->done_para(); + current_paragraph->done_table(); } /* @@ -1516,6 +1561,7 @@ void html_printer::do_flush (void) void html_printer::do_links (void) { current_paragraph->done_para(); + current_paragraph->done_table(); auto_links = FALSE; /* from now on only emit under user request */ #if !defined(DEBUGGING) file_list.add_new_file(xtmpfile()); @@ -1524,6 +1570,27 @@ void html_printer::do_links (void) } /* + * do_break - handles the ".br" request and also + * undoes an outstanding ".ti" command. + */ + +void html_printer::do_break (void) +{ + current_paragraph->do_break(); +#if defined(INDENTATION) + if (end_tempindent > 0) { + end_tempindent--; + if (end_tempindent == 0) { + indentation = prev_indent; + current_paragraph->do_indent(indentation, pageoffset, linelength); + } + } +#endif + output_hpos = indentation+pageoffset; + supress_sub_sup = TRUE; +} + +/* * troff_tag - processes the troff tag and manipulates the troff state machine. */ @@ -1540,9 +1607,7 @@ void html_printer::troff_tag (text_glob *g) current_paragraph->do_space(); supress_sub_sup = TRUE; } else if (strncmp(t, ".br", 3) == 0) { - current_paragraph->do_break(); - output_hpos = pageoffset; - supress_sub_sup = TRUE; + do_break(); } else if (strcmp(t, ".centered-image") == 0) { do_centered_image(); } else if (strcmp(t, ".right-image") == 0) { @@ -1575,6 +1640,9 @@ void html_printer::troff_tag (text_glob *g) } else if (strncmp(t, ".in", 3) == 0) { char *a = (char *)t+3; do_indentation(a); + } else if (strncmp(t, ".ti", 3) == 0) { + char *a = (char *)t+3; + do_tempindent(a); } else if (strncmp(t, ".vs", 3) == 0) { char *a = (char *)t+3; do_verticalspacing(a); @@ -1605,7 +1673,7 @@ void html_printer::flush_globs (void) do { g = page_contents->glyphs.get_data(); - if (strcmp(g->text_string, "ZZZZ") == 0) { + if (strcmp(g->text_string, "XXXXXXX") == 0) { stop(); } @@ -1635,6 +1703,7 @@ void html_printer::flush_page (void) // page_contents->dump_page(); flush_globs(); current_paragraph->done_para(); + current_paragraph->done_table(); // move onto a new page delete page_contents; @@ -2074,11 +2143,13 @@ html_printer::html_printer() supress_sub_sup(TRUE), cutoff_heading(100), end_center(0), + end_tempindent(0), next_tag(INLINE), fill_on(TRUE), - linelength(0), pageoffset(0), indentation(0), + prev_indent(0), + linelength(0), line_number(0) { #if defined(DEBUGGING) @@ -2088,9 +2159,9 @@ html_printer::html_printer() #endif html.set_file(file_list.get_file()); if (font::hor != 24) - fatal("horizontal resolution must be 1"); + fatal("horizontal resolution must be 24"); if (font::vert != 40) - fatal("vertical resolution must be 1"); + fatal("vertical resolution must be 40"); #if 0 // should be sorted html.. if (font::res % (font::sizescale*72) != 0) @@ -2106,6 +2177,7 @@ html_printer::html_printer() html.set_fixed_point(point); space_char_index = font::name_to_index("space"); paper_length = font::paperlength; + linelength = font::res*13/2; if (paper_length == 0) paper_length = 11*font::res; @@ -2132,8 +2204,6 @@ void html_printer::add_char_to_sbuf (unsigned char code) void html_printer::add_to_sbuf (unsigned char code, const char *name) { - if (code == 255) stop(); - if (name == 0) { add_char_to_sbuf(code); } else { @@ -2314,7 +2384,6 @@ static char *to_unicode (unsigned char ch) { static char buf[20]; - stop(); sprintf(buf, "&#%u;", (unsigned int)ch); return( buf ); } @@ -2477,16 +2546,16 @@ void html_printer::write_title (int in_head) if (in_head) { html.put_string("<title>"); html.put_string(title.text); - html.put_string("</title>\n\n"); + html.put_string("</title>").nl().nl(); } else { title.has_been_written = TRUE; html.put_string("<h1 align=center>"); html.put_string(title.text); - html.put_string("</h1>\n\n"); + html.put_string("</h1>").nl().nl(); } } else if (in_head) { // place empty title tags to help conform to `tidy' - html.put_string("<title></title>\n"); + html.put_string("<title></title>").nl(); } } @@ -2503,7 +2572,7 @@ static void write_rule (void) void html_printer::begin_page(int n) { page_number = n; - html.begin_comment("Page: ").comment_arg(i_to_a(page_number)).end_comment();; + html.begin_comment("Page: ").put_string(i_to_a(page_number)).end_comment();; no_of_printed_pages++; output_style.f = 0; @@ -2515,6 +2584,9 @@ void html_printer::begin_page(int n) output_vpos = -1; output_vpos_max = -1; current_paragraph = new html_text(&html); +#if defined(INDENTATION) + current_paragraph->do_indent(indentation, pageoffset, linelength); +#endif current_paragraph->do_para(""); } @@ -2531,9 +2603,17 @@ font *html_printer::make_font(const char *nm) html_printer::~html_printer() { - current_paragraph->done_para(); + current_paragraph->flush_text(); + html.end_line(); html.set_file(stdout); - // fputs("<!doctype html public \"-//IETF//DTD HTML 4.0//EN\">\n", stdout); + /* + * 'HTML: The definitive guide', O'Reilly, p47. advises against specifying + * the dtd, so for the moment I'll leave this commented out. + * If requested we could always emit it if a command line switch + * was present. + * + * fputs("<!doctype html public \"-//IETF//DTD HTML 4.0//EN\">\n", stdout); + */ fputs("<html>\n", stdout); fputs("<head>\n", stdout); fputs("<meta name=\"generator\" content=\"groff -Thtml, see www.gnu.org\">\n", stdout); @@ -2547,9 +2627,9 @@ html_printer::~html_printer() { extern const char *Version_string; html.begin_comment("Creator : ") - .comment_arg("groff ") - .comment_arg("version ") - .comment_arg(Version_string) + .put_string("groff ") + .put_string("version ") + .put_string(Version_string) .end_comment(); } { @@ -2560,10 +2640,10 @@ html_printer::~html_printer() #endif t = time(0); html.begin_comment("CreationDate: ") - .comment_arg(ctime(&t)) - .end_comment(); + .put_string(ctime(&t)) + .end_comment(); } - html.begin_comment("Total number of pages: ").comment_arg(i_to_a(no_of_printed_pages)).end_comment(); + html.begin_comment("Total number of pages: ").put_string(i_to_a(no_of_printed_pages)).end_comment(); html.end_line(); /* * now run through the file list copying each temporary file in turn and emitting the links. diff --git a/src/roff/troff/div.cc b/src/roff/troff/div.cc index c8d2e256..60bdc998 100644 --- a/src/roff/troff/div.cc +++ b/src/roff/troff/div.cc @@ -639,6 +639,7 @@ void page_offset() n = topdiv->prev_page_offset; topdiv->prev_page_offset = topdiv->page_offset; topdiv->page_offset = n; + curenv->add_html_tag(".po", n.to_units()); skip_line(); } diff --git a/src/roff/troff/env.cc b/src/roff/troff/env.cc index bae4fc5d..a1a63470 100644 --- a/src/roff/troff/env.cc +++ b/src/roff/troff/env.cc @@ -1130,10 +1130,9 @@ void no_fill() { while (!tok.newline() && !tok.eof()) tok.next(); - if (break_flag) { + if (break_flag) curenv->do_break(); - curenv->add_html_tag(".br"); - } + curenv->fill = 0; curenv->add_html_tag(".nf"); curenv->ignore_next_eol = 1; @@ -2030,6 +2029,7 @@ void environment::add_html_tag(const char *name, int i) ignore_next_eol = 1; // since the .ce creates an eol } } + /* * need to emit tag for post-grohtml * but we check to see whether we can emit specials diff --git a/tmac/an-old.tmac b/tmac/an-old.tmac index 5b406a07..e0ac1bec 100644 --- a/tmac/an-old.tmac +++ b/tmac/an-old.tmac @@ -280,7 +280,8 @@ . if \\n[.$] .nr an-prevailing-indent (n;\\$1) . it 1 an-trap . if !\\n[an-div?] .di an-div -. in 0 +. ie \\n[html-or-html-old] .in \\n[an-margin]u +. el .in 0 . nr an-div? 1 .. . diff --git a/tmac/s.tmac b/tmac/s.tmac index 9a8d65e9..076a4775 100644 --- a/tmac/s.tmac +++ b/tmac/s.tmac @@ -1132,7 +1132,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. .de @PP .par*start 0 0 .nr \\n[.ev]:ai \\n[\\n[.ev]:PI] -.ti +\\n[\\n[.ev]:ai]u +.if !'\*(.T'html' .ti +\\n[\\n[.ev]:ai]u .. .de @QP .nr \\n[.ev]:ai \\n[\\n[.ev]:PI] @@ -1153,11 +1153,18 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. . par*pop-tag-env . di . chop par*label -. ti -\\n[\\n[.ev]:ai]u -. ie \\n[dl]+1n<=\\n[\\n[.ev]:ai] \\*[par*label]\h'|\\n[\\n[.ev]:ai]u'\c +. ie '\*(.T'html' \{\ +. ti -\\n[\\n[.ev]:ai]u +\\*[par*label] +. br +. \} . el \{\ +. ti -\\n[\\n[.ev]:ai]u +. ie \\n[dl]+1n<=\\n[\\n[.ev]:ai] \\*[par*label]\h'|\\n[\\n[.ev]:ai]u'\c +. el \{\ \\*[par*label] -. br +. br +. \} . \} . rm par*label .\} |