summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorwlemb <wlemb>2001-03-16 15:48:30 +0000
committerwlemb <wlemb>2001-03-16 15:48:30 +0000
commit239e9ceb46c1f27d205552a0d798c29a70fed22f (patch)
tree141aad6d1561b15b9185d4311ea1f8cf3aabd2fa
parente8ba685419d4a0741a0fcde4a313d9d88ca5d1a7 (diff)
downloadgroff-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--ChangeLog80
-rw-r--r--src/devices/grohtml/html-text.cc210
-rw-r--r--src/devices/grohtml/html-text.h30
-rw-r--r--src/devices/grohtml/html.h46
-rw-r--r--src/devices/grohtml/output.cc278
-rw-r--r--src/devices/grohtml/post-html.cc156
-rw-r--r--src/roff/troff/div.cc1
-rw-r--r--src/roff/troff/env.cc6
-rw-r--r--tmac/an-old.tmac3
-rw-r--r--tmac/s.tmac15
10 files changed, 612 insertions, 213 deletions
diff --git a/ChangeLog b/ChangeLog
index 7f2ec77c..360fe5da 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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
.\}