groff
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Groff] improved html.cc (ignore my diffs from last week)


From: Gaius Mulley
Subject: [Groff] improved html.cc (ignore my diffs from last week)
Date: Mon, 15 Nov 99 18:34 GMT

Hi Werner,

I'm not sure whether to post this direct to you or
whether you would prefer it via ffii ? So feel free
to delete one copy of the email :-)

Many thanks for your bug report regarding the manual
page. Here is the latest html.cc diffs and macro changes.
I believe that it produces much better html IMHO
and I think that your test case works now.
I've run it through my tests and am actively using it on:

http://floppsie.comp.glam.ac.uk

I've generated these diffs against the cvs repository as
of 15/11/99 so you can ignore my diffs from last week.
(Hopefully a bargin at two for the price of one..)

Many thanks for your patience and hard work

cheers Gaius


diff -r -c groff/tmac/tmac.an groff-html/tmac/tmac.an
*** groff/tmac/tmac.an  Mon Nov 15 17:08:33 1999
--- groff-html/tmac/tmac.an     Fri Nov 12 11:07:08 1999
***************
*** 31,36 ****
--- 31,44 ----
  .if !rD .nr D 0
  .if !rC .nr C 0
  .if rP .pn 0\nP
+ .de set-an-margin
+ .  ie '\*(.T'html' \{\
+ .    nr an-margin 0i
+ .  \}
+ .  el \{\
+ .    nr an-margin \\n[IN]
+ .  \}
+ ..
  .\" .TH title section extra1 extra2 extra3
  .de TH
  .cp 0
***************
*** 45,57 ****
  .ds an-init
  \\..
  .DT
! .nr IN 7.2n
  .nr LL 6.5i
  .PD
  .nr PS 10 \" normal point-size
  .nr SN 3n \" the indentation of sub-sub-headings relative to sub-headings
  .nr an-level 1
! .nr an-margin \\n[IN]
  .nr an-prevailing-indent \\n[IN]
  .nr an-tag-sep 1n
  .nr an-no-space-flag 0
--- 53,70 ----
  .ds an-init
  \\..
  .DT
! .ie '\*(.T'html' \{\
! .  nr IN 1.3i
! .\}
! .el \{\
! .  nr IN 7.2n
! .\}
  .nr LL 6.5i
  .PD
  .nr PS 10 \" normal point-size
  .nr SN 3n \" the indentation of sub-sub-headings relative to sub-headings
  .nr an-level 1
! .set-an-margin
  .nr an-prevailing-indent \\n[IN]
  .nr an-tag-sep 1n
  .nr an-no-space-flag 0
***************
*** 75,83 ****
  .de an-header
  .an-init
  .ev 1
! .sp .5i
! .tl 
'\\*[an-title](\\*[an-section])'\\*[an-extra3]'\\*[an-title](\\*[an-section])'
! .sp |1i
  .ev
  .ns
  ..
--- 88,101 ----
  .de an-header
  .an-init
  .ev 1
! .ie '\*(.T'html' \{\
! .   tl ''''
! .\}
! .el \{\
! .   sp .5i
! .   tl 
'\\*[an-title](\\*[an-section])'\\*[an-extra3]'\\*[an-title](\\*[an-section])'
! .   sp |1i
! .\}
  .ev
  .ns
  ..
***************
*** 87,93 ****
  .af an-page-letter a
  .de an-p-footer
  .ev 1
! .ds an-page-string \\n%
  .if rX \{\
  .     if \\n%>\\nX \{\
  .             nr an-page-letter \\n%-\\nX
--- 105,116 ----
  .af an-page-letter a
  .de an-p-footer
  .ev 1
! .if '\*(.T'html' \{\
! .   ds an-page-string "
! .   ds an-extra1      "
! .   ds an-extra2      "
! .\}
! .el .ds an-page-string \\n%
  .if rX \{\
  .     if \\n%>\\nX \{\
  .             nr an-page-letter \\n%-\\nX
***************
*** 98,112 ****
  .     if e .tl '\\*[an-page-string]'\\*[an-extra1]'\\*[an-extra2]'
  .\}
  .el .tl '\\*[an-extra2]'\\*[an-extra1]'\\*[an-page-string]'
  .ev
  ..
  .de SH
  .sp \\n[PD]u
  .nr an-level 1
! .nr an-margin \\n[IN]
  .nr an-prevailing-indent \\n[IN]
  .fi
! .in \\n[IN]u
  .ti 0
  .it 1 an-trap
  .nr an-no-space-flag 1
--- 121,136 ----
  .     if e .tl '\\*[an-page-string]'\\*[an-extra1]'\\*[an-extra2]'
  .\}
  .el .tl '\\*[an-extra2]'\\*[an-extra1]'\\*[an-page-string]'
+ .if '\*(.T'html' .tl ''''
  .ev
  ..
  .de SH
  .sp \\n[PD]u
  .nr an-level 1
! .set-an-margin
  .nr an-prevailing-indent \\n[IN]
  .fi
! .in \\n[an-margin]u
  .ti 0
  .it 1 an-trap
  .nr an-no-space-flag 1
***************
*** 119,125 ****
  .de SS
  .sp \\n[PD]u
  .nr an-level 1
! .nr an-margin \\n[IN]
  .nr an-prevailing-indent \\n[IN]
  .fi
  .in \\n[IN]u
--- 143,149 ----
  .de SS
  .sp \\n[PD]u
  .nr an-level 1
! .set-an-margin
  .nr an-prevailing-indent \\n[IN]
  .fi
  .in \\n[IN]u
diff -r -c groff/tmac/tmac.html groff-html/tmac/tmac.html
*** groff/tmac/tmac.html        Mon Nov 15 17:08:34 1999
--- groff-html/tmac/tmac.html   Mon Nov 15 11:53:45 1999
***************
*** 37,44 ****
  .if !c\(ah .char \(ah \v'-.55m'\s[\En[.s]/2u]v\s0\v'.55m'
  .if !c\(ao .char \(ao \v'-.55m'\s[\En[.s]*6u/10u]\D'c .25m'\s0\v'.55m'
  .if !c\(ho .char \(ho \s[\En[.s]/2u]\v'.4m'c\v'-.4m'\s0
! .if !c\(lh .tr \(lh\(lA
! .if !c\(rh .tr \(rh\(rA
  .if !c\(bq .tr \(bq,
  .if !c\(aq .tr \(aq'
  .if '\*(.T'html' .char \[radicalex] \h'-\w'\(sr'u'\[radicalex]\h'\w'\(sr'u'
--- 37,44 ----
  .if !c\(ah .char \(ah \v'-.55m'\s[\En[.s]/2u]v\s0\v'.55m'
  .if !c\(ao .char \(ao \v'-.55m'\s[\En[.s]*6u/10u]\D'c .25m'\s0\v'.55m'
  .if !c\(ho .char \(ho \s[\En[.s]/2u]\v'.4m'c\v'-.4m'\s0
! .if !c\(lh .char \(lh <-
! .if !c\(rh .char \(rh ->
  .if !c\(bq .tr \(bq,
  .if !c\(aq .tr \(aq'
  .if '\*(.T'html' .char \[radicalex] \h'-\w'\(sr'u'\[radicalex]\h'\w'\(sr'u'
***************
*** 53,55 ****
--- 53,58 ----
  .of '''
  .oh '''
  .eh '''
+ .\" it doesn't make sense to use hyphenation with html, so we turn it off.
+ .hy 0
+ .nr HY 0
diff -r -c groff/grohtml/ChangeLog groff-html/grohtml/ChangeLog
*** groff/grohtml/ChangeLog     Mon Nov 15 17:08:27 1999
--- groff-html/grohtml/ChangeLog        Fri Nov  5 19:15:58 1999
***************
*** 1,9 ****
  1999-10-30  Gaius Mulley  <address@hidden>
  
!       * implemented auto formatting and introduced html table code
!       (activated with `-t' for the moment).  Fixed several text handling
!       bugs and grohtml will detect centered lines -- an offshoot of the
!       html table code.
  
        * reverted meaning of grohtml's `-a' switch: using -a means that
        output will be preformatted.
--- 1,17 ----
+ 1999-11-05  Gaius Mulley  <address@hidden>
+ 
+       * fixed many bugs in the table handling code. Reverted the -t
+       switch so that table handling code is used by default and
+       users must turn it off with -t.
+       Manual page generation using groff -Thtml -man is much better
+       due in large part to the table code and minor alterations in
+       tmac.an.
+ 
  1999-10-30  Gaius Mulley  <address@hidden>
  
!         * implemented auto formatting and introduced html table
!       code. Fixed several text handling bugs and grohtml will
!       detect centered lines - an offshoot of the html table code.
  
        * reverted meaning of grohtml's `-a' switch: using -a means that
        output will be preformatted.
diff -r -c groff/grohtml/design.ms groff-html/grohtml/design.ms
*** groff/grohtml/design.ms     Mon Nov 15 17:08:27 1999
--- groff-html/grohtml/design.ms        Wed Nov 10 10:10:42 1999
***************
*** 83,88 ****
--- 83,110 ----
  into a list of links which are later written to the beginning
  of the html document.
  .SH
+ Table handling code
+ .LP
+ Provided that the -t option is not present when grohtml is run the grohtml
+ driver will attempt to find textual tables and generate html tables.
+ This allows .RS and .RE commands to operate with auto formatting. It also
+ should grohtml to process .2C correctly. However, the table handling code
+ has to examine the troff output and \fIguess\fR when a table starts and
+ finishes. It is well to know the limitations of this approach as it
+ sometimes makes the wrong decision.
+ .PP
+ Here are some of the rules that grohtml uses for terminating a html table:
+ .RS
+ .IP "\(bu"
+ A table will be terminated when grohtml finds line which is all in bold
+ font (it believes that this is a header which is outside of a table).
+ This might be considered incorrect behaviour especially if you use .2C
+ which generates a heading on the left column when the corresponding
+ right row is blank.
+ .IP "\(bu"
+ A table is terminated when grohtml sees that the complete line is
+ has been spanned by words. Ie no gaps exist.
+ .SH
  To do
  .LP
  .IP (i)
***************
*** 92,107 ****
  (originally taken from devX100)
  .IP (iii)
  improve tmac.arkup
! .IP (iv)
! finish the -a option. Currently it is broken as reported
! by Werner:
! .sp
! \f[CR]groff -Thtml -P-a -mhtml groff_mm.man > groff_mm.html\fP
! .sp
! for the time being the -P-a option has been removed but it should be
! replaced when it works.
! .sp
! .IP (v)
  also improve documentation.
  .SH
  Dependencies
--- 114,120 ----
  (originally taken from devX100)
  .IP (iii)
  improve tmac.arkup
! .IP (vi)
  also improve documentation.
  .SH
  Dependencies
diff -r -c groff/grohtml/grohtml.man groff-html/grohtml/grohtml.man
*** groff/grohtml/grohtml.man   Mon Nov 15 17:08:27 1999
--- groff-html/grohtml/grohtml.man      Fri Nov  5 19:07:07 1999
***************
*** 92,104 ****
  will not remove left margins.
  .TP
  .B \-t
! allows grohtml generate html tables when implementing indentation.
! Typically .IP can be implemented by tables or html indents. However if .2C
! is used it can only be sensibly converted to html when this option
! is present.
! Note that the html table code is still under development and contains several 
known bugs.
! Eventually when the html table code is completely debugged then
! this option will be enabled by default.
  .TP
  .BI \-F dir
  Search the directory
--- 92,107 ----
  will not remove left margins.
  .TP
  .B \-t
! forbids
! .B grohtml
! from generating html tables when implementing indentation and tabular text.
! .B grohtml
! can implement .IP by tables or html indents. However if .2C
! is used it can only be sensibly converted to html using a table structure.
! As a few known bugs still exist with the html table code this option is 
present
! to supress execution of this development code. The default in
! .B grohtml
! is that html tables are generated when appropriate.
  .TP
  .BI \-F dir
  Search the directory
diff -r -c groff/grohtml/html.cc groff-html/grohtml/html.cc
*** groff/grohtml/html.cc       Mon Nov 15 17:08:28 1999
--- groff-html/grohtml/html.cc  Mon Nov 15 17:21:28 1999
***************
*** 51,58 ****
  #define DEFAULT_IMAGE_RES              80
  #define IMAGE_BOARDER_PIXELS           10
  #define MAX_WORDS_PER_LINE           1000        // only used for table 
indentation
! #define GAP_SPACES                      4        // how many spaces needed to 
guess a gap?
  #define CENTER_TOLERANCE                2        // how many pixels off 
center will we think a line or region is centered
  
  
  /*
--- 51,60 ----
  #define DEFAULT_IMAGE_RES              80
  #define IMAGE_BOARDER_PIXELS           10
  #define MAX_WORDS_PER_LINE           1000        // only used for table 
indentation
! #define GAP_SPACES                      3        // how many spaces needed to 
guess a gap?
! #define GAP_WIDTH_ONE_LINE              2        // 1/GAP_WIDTH_ONE_LINE 
inches required for one line table
  #define CENTER_TOLERANCE                2        // how many pixels off 
center will we think a line or region is centered
+ #define MIN_COLUMN                      7        // minimum column size pixels
  
  
  /*
***************
*** 77,83 ****
  static int guess_on                 =  TRUE;
  static int margin_on                = FALSE;
  static int auto_on                  =  TRUE;
! static int table_on                 = FALSE;
  static int image_res                = DEFAULT_IMAGE_RES;
  static int debug_table_on           = FALSE;
  
--- 79,85 ----
  static int guess_on                 =  TRUE;
  static int margin_on                = FALSE;
  static int auto_on                  =  TRUE;
! static int table_on                 =  TRUE;
  static int image_res                = DEFAULT_IMAGE_RES;
  static int debug_table_on           = FALSE;
  
***************
*** 1099,1104 ****
--- 1101,1107 ----
  struct text_defn {
    int left;       // the start of a word or text
    int right;      // the end of the text and beginning of white space
+   int is_used;    // will this this column be used for words or space
  };
  
  
***************
*** 1223,1228 ****
--- 1226,1232 ----
    int   looks_like_subscript          (text_glob *g);
    int   looks_like_superscript        (text_glob *g);
    void  begin_paragraph               (paragraph_type p);
+   void  begin_paragraph_no_height     (paragraph_type p);
    void  force_begin_paragraph         (void);
    void  end_paragraph                 (void);
    void  html_newline                  (void);
***************
*** 1235,1240 ****
--- 1239,1245 ----
    void  build_header                  (text_glob *g);
    void  make_html_indent              (int indent);
    int   is_whole_line_bold            (text_glob *g);
+   int   is_a_header                   (text_glob *g);
    int   processed_header              (text_glob *g);
    void  make_new_image_name           (void);
    void  create_temp_name              (char *name, char *extension);
***************
*** 1258,1268 ****
    int   count_columns                 (struct text_defn *line);
    void  rewind_text_to                (text_glob *g);
    int   found_use_for_table           (text_glob *start);
!   void  column_display_word           (int left, int right, int next);
    void  start_table                   (void);
    void  end_table                     (void);
    void  foreach_column_include_text   (text_glob *start);
    void  define_cell                   (int left, int right);
    int   column_calculate_right_margin (int left, int right);
    void  display_columns               (const char *word, const char *name, 
text_defn *line);
    void  calculate_right               (struct text_defn *line, int max_words);
--- 1263,1274 ----
    int   count_columns                 (struct text_defn *line);
    void  rewind_text_to                (text_glob *g);
    int   found_use_for_table           (text_glob *start);
!   void  column_display_word           (int vert, int left, int right, int 
next);
    void  start_table                   (void);
    void  end_table                     (void);
    void  foreach_column_include_text   (text_glob *start);
    void  define_cell                   (int left, int right);
+   int   column_calculate_left_margin  (int left, int right);
    int   column_calculate_right_margin (int left, int right);
    void  display_columns               (const char *word, const char *name, 
text_defn *line);
    void  calculate_right               (struct text_defn *line, int max_words);
***************
*** 1283,1288 ****
--- 1289,1302 ----
    int   check_able_to_use_center      (text_glob *g);
    void  write_centered_line           (text_glob *g);
    int   single_centered_line          (text_defn *first, text_defn *second, 
text_glob *g);
+   int   determine_row_limit           (text_glob *start, int v);
+   void  assign_used_columns           (text_glob *start);
+   int   find_column_index             (text_glob *t);
+   int   large_enough_gap              (text_defn *last_col);
+   int   is_worth_column               (int left, int right);
+   int   is_subset_of_columns          (text_defn *a, text_defn *b);
+   void  count_hits                    (text_defn *col);
+   int   calculate_min_gap             (text_glob *g);
  
  public:
    html_printer();
***************
*** 1603,1608 ****
--- 1617,1638 ----
    }
  }
  
+ 
+ /*
+  *  begin_paragraph_no_height - starts a new paragraph. It does nothing if a 
paragraph
+  *                              has already been started. Note it does not 
alter output_vpos.
+  */
+ 
+ void html_printer::begin_paragraph_no_height (paragraph_type p)
+ {
+   if (! in_paragraph) {
+     need_paragraph = TRUE;   // delay the <p> just in case we don't actually 
emit text
+     in_paragraph   = TRUE;
+     issued_newline = TRUE;
+     para_type      = p;
+   }
+ }
+ 
  /*
   *  end_paragraph - end the current paragraph. It does nothing if a paragraph
   *                  has not been started.
***************
*** 2190,2202 ****
        something = TRUE;
        display_line(g, is_to_html);
        }
!       g = page_contents->lines.move_right_get_data();
      } else if ((g == 0) && (t != 0)) {
        if (is_within_region(t)) {
        display_word(t, is_to_html);
        something = TRUE;
        }
!       t = page_contents->words.move_right_get_data();
      } else {
        if ((g == 0) || (t == 0)) {
        // hmm nothing to print out...
--- 2220,2240 ----
        something = TRUE;
        display_line(g, is_to_html);
        }
!       if (page_contents->lines.is_empty() || 
page_contents->lines.is_equal_to_tail()) {
!       g = 0;
!       } else {
!       g = page_contents->lines.move_right_get_data();
!       }
      } else if ((g == 0) && (t != 0)) {
        if (is_within_region(t)) {
        display_word(t, is_to_html);
        something = TRUE;
        }
!       if (page_contents->words.is_empty() || 
page_contents->words.is_equal_to_tail()) {
!       t = 0;
!       } else {
!       t = page_contents->words.move_right_get_data();
!       }
      } else {
        if ((g == 0) || (t == 0)) {
        // hmm nothing to print out...
***************
*** 2205,2217 ****
          display_line(g, is_to_html);
          something = TRUE;
        }
!       g = page_contents->lines.move_right_get_data();
        } else {
        if (is_within_region(t)) {
          display_word(t, is_to_html);
          something = TRUE;
        }
!       t = page_contents->words.move_right_get_data();
        }
      }
    } while ((t != 0) || (g != 0));
--- 2243,2263 ----
          display_line(g, is_to_html);
          something = TRUE;
        }
!       if (page_contents->lines.is_empty() || 
page_contents->lines.is_equal_to_tail()) {
!         g = 0;
!       } else {
!         g = page_contents->lines.move_right_get_data();
!       }
        } else {
        if (is_within_region(t)) {
          display_word(t, is_to_html);
          something = TRUE;
        }
!       if (page_contents->words.is_empty() || 
page_contents->words.is_equal_to_tail()) {
!         t = 0;
!       } else {
!         t = page_contents->words.move_right_get_data();
!       }
        }
      }
    } while ((t != 0) || (g != 0));
***************
*** 2252,2260 ****
  
  void html_printer::flush_page (void)
  {
-   output_vpos = -1;
-   output_hpos = -1;
    calculate_margin();
  #if 0
    dump_page();
  #endif
--- 2298,2306 ----
  
  void html_printer::flush_page (void)
  {
    calculate_margin();
+   output_vpos = -1;
+   output_hpos = left_margin_indent;
  #if 0
    dump_page();
  #endif
***************
*** 2511,2529 ****
  
  void html_printer::build_header (text_glob *g)
  {
-   int current_vpos = g->minv;
    int r            = font::res;
    int height       = g->text_style.point_size*r/72;
  
    strcpy(header.header_buffer, "");
    do {
      strcat(header.header_buffer, (char *)g->text_string);
      page_contents->words.move_right();
      g = page_contents->words.get_data();
      if (g->minv == current_vpos) {
        strcat(header.header_buffer, " ");
      }
!   } while ((! page_contents->words.is_equal_to_head()) && (g->minv == 
current_vpos));
  
    determine_header_level();
    // finally set the output to neutral for after the header
--- 2557,2579 ----
  
  void html_printer::build_header (text_glob *g)
  {
    int r            = font::res;
    int height       = g->text_style.point_size*r/72;
+   text_glob *l;
+   int current_vpos;
  
    strcpy(header.header_buffer, "");
    do {
+     l = g;
+     current_vpos = g->minv;
      strcat(header.header_buffer, (char *)g->text_string);
      page_contents->words.move_right();
      g = page_contents->words.get_data();
      if (g->minv == current_vpos) {
        strcat(header.header_buffer, " ");
      }
!   } while ((! page_contents->words.is_equal_to_head()) &&
!          ((g->minv == current_vpos) || (l->maxh == right_margin_indent)));
  
    determine_header_level();
    // finally set the output to neutral for after the header
***************
*** 2556,2562 ****
        }
        return( FALSE );
      }
!   } while ((! page_contents->words.is_equal_to_head()) && (n->minv == 
current_vpos));
    while (page_contents->words.get_data() != g) {
      page_contents->words.move_left();
    }
--- 2606,2646 ----
        }
        return( FALSE );
      }
!   } while ((! page_contents->words.is_equal_to_head()) && (is_on_same_line(n, 
current_vpos)));
!   // was (n->minv == current_vpos)
!   while (page_contents->words.get_data() != g) {
!     page_contents->words.move_left();
!   }
!   return( TRUE );
! }
! 
! 
! /*
!  *  is_a_header - returns TRUE if the whole sequence of contineous lines are 
bold.
!  *                It checks to see whether a line is likely to be contineous 
and
!  *                then checks that all words are bold.
!  */
! 
! int html_printer::is_a_header (text_glob *g)
! {
!   text_glob *l;
!   text_glob *n=g;
!   int        current_vpos;
! 
!   do {
!     l = n;
!     current_vpos = n->minv;
!     if (is_bold(n)) {
!       page_contents->words.move_right();
!       n = page_contents->words.get_data();
!     } else {
!       while (page_contents->words.get_data() != g) {
!       page_contents->words.move_left();
!       }
!       return( FALSE );
!     }
!   } while ((! page_contents->words.is_equal_to_head()) &&
!          ((n->minv == current_vpos) || (l->maxh == right_margin_indent)));
    while (page_contents->words.get_data() != g) {
      page_contents->words.move_left();
    }
***************
*** 2566,2573 ****
  
  int html_printer::processed_header (text_glob *g)
  {
!   if ((guess_on) && (g->minh == left_margin_indent) &&
!       (is_whole_line_bold(g))) {
      build_header(g);
      write_header();
      return( TRUE );
--- 2650,2657 ----
  
  int html_printer::processed_header (text_glob *g)
  {
!   if ((guess_on) && (g->minh == left_margin_indent) && (! 
using_table_for_indent()) &&
!       (is_a_header(g))) {
      build_header(g);
      write_header();
      return( TRUE );
***************
*** 2624,2634 ****
          (output_style.point_size > g->text_style.point_size)));
  }
  
  
  int html_printer::pretend_is_on_same_line (text_glob *g, int left_margin, int 
right_margin)
  {
    return( auto_on && (right_margin == output_hpos) && (left_margin == 
g->minh) &&
!         (! is_whole_line_bold(g)) );
  }
  
  int html_printer::is_on_same_line (text_glob *g, int vpos)
--- 2708,2723 ----
          (output_style.point_size > g->text_style.point_size)));
  }
  
+ /*
+  *  pretend_is_on_same_line - returns TRUE if we think, g, is on the same 
line as the previous glob.
+  *                            Note that it believes a single word spanning 
the left..right as being
+  *                            on a different line.
+  */
  
  int html_printer::pretend_is_on_same_line (text_glob *g, int left_margin, int 
right_margin)
  {
    return( auto_on && (right_margin == output_hpos) && (left_margin == 
g->minh) &&
!         (right_margin != g->maxh) && ((! is_whole_line_bold(g)) || 
(g->text_style.f == output_style.f)) );
  }
  
  int html_printer::is_on_same_line (text_glob *g, int vpos)
***************
*** 2661,2666 ****
--- 2750,2765 ----
  }
  
  /*
+  *  calculate_min_gap - returns the minimum gap by which we deduce columns.
+  *                      This is a rough heuristic.
+  */
+ 
+ int html_printer::calculate_min_gap (text_glob *g)
+ {
+   return( 
g->text_style.f->get_space_width(g->text_style.point_size)*GAP_SPACES );
+ }
+ 
+ /*
   *  collect_columns - place html text in a column and return the vertical 
limit reached.
   */
  
***************
*** 2668,2674 ****
  {
    text_glob *start = page_contents->words.get_data();
    text_glob *t     = start;
!   int  upper_limit = -1;
  
    line[0].left  = 0;
    line[0].right = 0;
--- 2767,2773 ----
  {
    text_glob *start = page_contents->words.get_data();
    text_glob *t     = start;
!   int  upper_limit = 0;
  
    line[0].left  = 0;
    line[0].right = 0;
***************
*** 2682,2695 ****
        int i      =0;
        int j      =0;
        int prevh  =0;
!       int mingap 
=start->text_style.f->get_space_width(start->text_style.point_size)*GAP_SPACES;
  
        while ((t != 0) && (is_on_same_line(t, start->minv) && (i<max_words)) &&
             ((graphic_limit == -1) || (graphic_limit > t->minv))) {
        while ((last != 0) && (j<max_words) && (last[j].left != 0) && 
(last[j].left < t->minh)) {
          j++;
        }
!       if ((t->minh - prevh >= mingap) || ((last != 0) && (last[j].left != 0) 
&& (t->minh == last[j].left))) {
          line[i].left    = t->minh;
          line[i].right   = t->maxh;
          i++;
--- 2781,2797 ----
        int i      =0;
        int j      =0;
        int prevh  =0;
!       int mingap =calculate_min_gap(start);
  
        while ((t != 0) && (is_on_same_line(t, start->minv) && (i<max_words)) &&
             ((graphic_limit == -1) || (graphic_limit > t->minv))) {
        while ((last != 0) && (j<max_words) && (last[j].left != 0) && 
(last[j].left < t->minh)) {
          j++;
        }
!       // t->minh might equal t->maxh when we are passing a special device 
character via \X
!       // we currently ignore these when considering tables
!       if (((t->minh - prevh >= mingap) || ((last != 0) && (last[j].left != 0) 
&& (t->minh == last[j].left))) &&
!           (t->minh != t->maxh)) {
          line[i].left    = t->minh;
          line[i].right   = t->maxh;
          i++;
***************
*** 2816,2821 ****
--- 2918,2926 ----
    if (line[i].left == 0) {
      // add to the end
      if (i<MAX_WORDS_PER_LINE) {
+       if ((i>0) && (line[i-1].left > item->left)) {
+       fatal("insertion error");
+       }
        line[i].left  = item->left;
        line[i].right = item->right;
        i++;
***************
*** 3017,3022 ****
--- 3122,3131 ----
        }
      }
    }
+   if (i<MAX_WORDS_PER_LINE) {
+     next_guess[i].left  = 0;
+     next_guess[i].right = 0;
+   }
    if (debug_table_on) {
      if (removed) {
        fprintf(stderr, "have removed column\n");
***************
*** 3103,3116 ****
    struct text_defn t;
  
    // firstly lets see whether we need an initial column on the left hand side
!   if ((line[0].left != left_margin_indent) && (line[0].left != 0)) {
      t.left  = left_margin_indent;
      t.right = line[0].left;
      include_into_list(line, &t);
    }
  
    while ((i<MAX_WORDS_PER_LINE) && (line[i].left != 0)) {
!     if ((i+1<MAX_WORDS_PER_LINE) && (line[i+1].left != 0) && (line[i].right 
!= line[i+1].left)) {
        t.left  = line[i].right;
        t.right = line[i+1].left;
        include_into_list(line, &t);
--- 3212,3227 ----
    struct text_defn t;
  
    // firstly lets see whether we need an initial column on the left hand side
!   if ((line[0].left != left_margin_indent) && (line[0].left != 0) &&
!       (left_margin_indent < line[0].left) && 
(is_worth_column(left_margin_indent, line[0].left))) {
      t.left  = left_margin_indent;
      t.right = line[0].left;
      include_into_list(line, &t);
    }
  
    while ((i<MAX_WORDS_PER_LINE) && (line[i].left != 0)) {
!     if ((i+1<MAX_WORDS_PER_LINE) && (line[i+1].left != 0) && (line[i].right 
!= line[i+1].left) &&
!       (is_worth_column(line[i].right, line[i+1].left))) {
        t.left  = line[i].right;
        t.right = line[i+1].left;
        include_into_list(line, &t);
***************
*** 3120,3126 ****
      }
    }
    // lastly lets see whether we need a final column on the right hand side
!   if ((i>0) && (line[i-1].right != right_margin_indent)) {
      t.left  = line[i-1].right;
      t.right = right_margin_indent;
      include_into_list(line, &t);
--- 3231,3238 ----
      }
    }
    // lastly lets see whether we need a final column on the right hand side
!   if ((i>0) && (line[i-1].right != right_margin_indent) &&
!       (is_worth_column(line[i-1].right, right_margin_indent))) {
      t.left  = line[i-1].right;
      t.right = right_margin_indent;
      include_into_list(line, &t);
***************
*** 3181,3193 ****
    int count = count_columns(next_col);
    int words = count_columns(all_words);
  
!   if ((words == 1) &&
!       (all_words[0].left == left_margin_indent) &&
!       (all_words[0].right == right_margin_indent)) {
      // no point as we have now seen a full line of contineous text
      return( FALSE );
    }
!   return( (count == count_columns(last_col)) );
  }
  
  /*
--- 3293,3434 ----
    int count = count_columns(next_col);
    int words = count_columns(all_words);
  
!   if ((words == 0) || ((words == 1) &&
!                      (all_words[0].left == left_margin_indent) &&
!                      (all_words[0].right == right_margin_indent))) {
      // no point as we have now seen a full line of contineous text
      return( FALSE );
    }
!   return( (count == count_columns(last_col)) &&
!         (last_col[0].left != left_margin_indent) || (last_col[0].right != 
right_margin_indent) );
! }
! 
! /*
!  *  is_worth_column - returns TRUE if the size of this column is worth 
defining.
!  */
! 
! int html_printer::is_worth_column (int left, int right)
! {
! #if 0
!   return( abs(right-left) >= MIN_COLUMN );
! #endif
!   return( TRUE );
! }
! 
! /*
!  *  large_enough_gap - returns TRUE if a large enough gap for one line was 
seen.
!  *                     We need to make sure that a single line definitely 
warrents
!  *                     a table.
!  *                     It also removes other smaller gaps.
!  */
! 
! int html_printer::large_enough_gap (text_defn *last_col)
! {
!   int i=0;
!   int found=FALSE;
!   int r=font::res;
!   int gap=r/GAP_WIDTH_ONE_LINE;
! 
!   if (abs(last_col[i].left - left_margin_indent) >= gap) {
!     found = TRUE;
!   }
!   while ((last_col[i].left != 0) && (last_col[i+1].left != 0)) {
!     if (abs(last_col[i+1].left-last_col[i].right) >= gap) {
!       found = TRUE;
!       i++;
!     } else {
!       // not good enough for a single line, remove it
!       if (i>0) {
!       last_col[i-1].right = last_col[i].right;
!       }
!       remove_entry_in_line(last_col, i);
!     }
!   }
!   return( found );
! }
! 
! /*
!  *  is_subset_of_columns - returns TRUE if line, a, is a subset of line, b.
!  */
! 
! int html_printer::is_subset_of_columns (text_defn *a, text_defn *b)
! {
!   int i;
!   int j;
! 
!   i=0;
!   while ((i<MAX_WORDS_PER_LINE) && (a[i].left != 0)) {
!     j=0;
!     while ((j<MAX_WORDS_PER_LINE) && (b[j].left != 0) &&
!          ((b[j].left != a[i].left) || (b[j].right != a[i].right))) {
!       j++;
!     }
!     if ((j==MAX_WORDS_PER_LINE) || (b[j].left == 0)) {
!       // found a different column - not a subset
!       return( FALSE );
!     }
!     i++;
!   }
!   return( TRUE );
! }
! 
! /*
!  *  count_hits - counts the number of hits per column. A hit is when the
!  *               left hand position of a glob hits the left hand column.
!  */
! 
! void html_printer::count_hits (text_defn *col)
! {
!   int        i;
!   text_glob *start = page_contents->words.get_data();
!   text_glob *g     = start;
!   int        r     = font::res;
!   int        gap   = r/GAP_WIDTH_ONE_LINE;
!   int        n     = count_columns(col);
!   int        left;
! 
!   // firstly reset the used field
!   for (i=0; i<n; i++) {
!     col[i].is_used = 0;
!   }
!   // now calculate the left hand hits
!   while ((g != 0) && (g->minv <= indentation.vertical_limit)) {
!     i=0;
!     while ((col[i].left < g->minh) && (col[i].left != 0)) {
!       i++;
!     }
!     if ((col[i].left == g->minh) && (col[i].left != 0)) {
!       col[i].is_used++;
!     }
!     page_contents->words.move_right();
!     if (page_contents->words.is_equal_to_head()) {
!       g = 0;
!       page_contents->words.start_from_tail();
!     } else {
!       g=page_contents->words.get_data();
!     }
!   }
!   // now remove any column which is less than the
!   // minimal gap for one hit.
!   // column 0 is excempt
! 
!   left = col[0].left;
!   i=1;
!   while (i<count_columns(col)) {
!     if (col[i].is_used == 1) {
!       if (col[i].left - left < gap) {
!       col[i-1].right = col[i].right;
!       remove_entry_in_line(col, i);
!       left = col[i].left;
!       } else {
!       left = col[i].left;
!       i++;
!       }
!     } else {
!       left = col[i].left;
!       i++;
!     }
!   }
  }
  
  /*
***************
*** 3201,3217 ****
    struct text_defn   all_words [MAX_WORDS_PER_LINE];
    struct text_defn   last_raw  [MAX_WORDS_PER_LINE];
    struct text_defn   next_line [MAX_WORDS_PER_LINE];
    struct text_defn   last_guess[MAX_WORDS_PER_LINE];
    struct text_defn   next_guess[MAX_WORDS_PER_LINE];
    int                i     =0;
!   int                lines =1;
!   int                
mingap=start->text_style.f->get_space_width(start->text_style.point_size)*GAP_SPACES;
    int                limit;
  
    // get first set of potential columns into line1
    limit = collect_columns(last_guess, 0, MAX_WORDS_PER_LINE);
    copy_line(last_raw, last_guess);
!   add_right_full_width(last_guess, mingap);   // adds extra right column to 
bring table to full width
  
    copy_line(all_words, last_guess);
    indentation.vertical_limit = limit;
--- 3442,3465 ----
    struct text_defn   all_words [MAX_WORDS_PER_LINE];
    struct text_defn   last_raw  [MAX_WORDS_PER_LINE];
    struct text_defn   next_line [MAX_WORDS_PER_LINE];
+   struct text_defn   prev_guess[MAX_WORDS_PER_LINE];
    struct text_defn   last_guess[MAX_WORDS_PER_LINE];
    struct text_defn   next_guess[MAX_WORDS_PER_LINE];
    int                i     =0;
!   int                lines =0;
!   int                mingap=calculate_min_gap(start);
    int                limit;
  
+ #if 0
+   if (strcmp(start->text_string, "(*") == 0) {
+     stop();
+   }
+ #endif
+ 
    // get first set of potential columns into line1
    limit = collect_columns(last_guess, 0, MAX_WORDS_PER_LINE);
    copy_line(last_raw, last_guess);
!   // add_right_full_width(last_guess, mingap);   // adds extra right column 
to bring table to full width
  
    copy_line(all_words, last_guess);
    indentation.vertical_limit = limit;
***************
*** 3222,3227 ****
--- 3470,3476 ----
    } else {
      // and get the next line for finding columns
      limit = collect_columns(next_line, last_guess, MAX_WORDS_PER_LINE);
+     lines++;
    }
  
    // now check to see whether the first line looks like a single centered line
***************
*** 3248,3260 ****
        (continue_searching_column(next_guess, next_guess, all_words)) &&
        (! page_contents->words.is_equal_to_head())) {
  
      // subtract any columns which are bridged by a sequence of words
      do {
!       copy_line(last_guess, next_guess);
!       if (debug_table_on) {
!       if (strcmp(start->text_string, "server") == 0) {
!         stop();
        }
        t = page_contents->words.get_data();
        display_columns(t->text_string, "[l] last_guess", last_guess);
        }
--- 3497,3528 ----
        (continue_searching_column(next_guess, next_guess, all_words)) &&
        (! page_contents->words.is_equal_to_head())) {
  
+     combine_line(last_guess, next_line);
      // subtract any columns which are bridged by a sequence of words
      do {
! #if 0
!       if (is_subset_of_columns(next_guess, last_guess)) {
!       if (debug_table_on) {
!         display_columns("[s]", "last_guess", last_guess);
!         display_columns("[s]", "next_guess", next_guess);
!         fprintf(stderr, "next_guess is a subset of last_guess - do 
nothing\n");
!         fflush(stderr);
        }
+       } else {
+       if (debug_table_on) {
+         display_columns("[s]", "last_guess", last_guess);
+         display_columns("[s]", "next_guess", next_guess);
+         fprintf(stderr, "next_guess is not a subset of last_guess\n");
+         fflush(stderr);
+       }
+       copy_line(last_guess, next_guess);
+       }
+ #else
+       copy_line(prev_guess, next_guess);
+       combine_line(last_guess, next_guess);   // was copy_line
+ #endif
+       
+       if (debug_table_on) {
        t = page_contents->words.get_data();
        display_columns(t->text_string, "[l] last_guess", last_guess);
        }
***************
*** 3266,3271 ****
--- 3534,3540 ----
        next_line[0].right = 0;
        } else {
        limit = collect_columns(next_line, last_guess, MAX_WORDS_PER_LINE);
+       lines++;
        }
  
        combine_line(all_words, next_line);
***************
*** 3274,3291 ****
        display_columns(t->text_string, "[l] last_raw ", last_raw);
        }
  
-       lines++;
- 
        if (debug_table_on) {
        display_columns(t->text_string, "[l] next_line", next_line);
        }
      } while ((! remove_white_using_words(next_guess, last_guess, next_line)) 
&&
             (! conflict_with_words(next_guess, all_words)) &&
             (continue_searching_column(next_guess, last_guess, all_words)) &&
!            ((is_continueous_column(last_guess, last_raw)) || 
(is_exact_left(last_guess, next_line))) &&
!            (! page_contents->words.is_equal_to_head()));
!     lines--;
    }
  
    if (page_contents->words.is_equal_to_head()) {
      // end of page reached - therefore include everything
--- 3543,3558 ----
        display_columns(t->text_string, "[l] last_raw ", last_raw);
        }
  
        if (debug_table_on) {
        display_columns(t->text_string, "[l] next_line", next_line);
        }
      } while ((! remove_white_using_words(next_guess, last_guess, next_line)) 
&&
             (! conflict_with_words(next_guess, all_words)) &&
             (continue_searching_column(next_guess, last_guess, all_words)) &&
!            ((is_continueous_column(prev_guess, last_raw)) || 
(is_exact_left(last_guess, next_line))) &&
!            (! page_contents->words.is_equal_to_head()) && (limit != 0));
    }
+   lines--;
  
    if (page_contents->words.is_equal_to_head()) {
      // end of page reached - therefore include everything
***************
*** 3297,3304 ****
      display_columns(start->text_string, "[x] last_guess", last_guess);
    }
  
    i = count_columns(last_guess);
!   if ((lines > 1) && ((i>1) || (continue_searching_column(last_guess, 
last_guess, all_words)))) {
      // copy match into permenant html_table
  
      if (indentation.columns != 0) {
--- 3564,3580 ----
      display_columns(start->text_string, "[x] last_guess", last_guess);
    }
  
+ #if 0
+   count_hits(last_guess);
+   rewind_text_to(start);
+   if (debug_table_on) {
+     display_columns(start->text_string, "[x] last_guess", last_guess);
+   }
+ #endif
+ 
    i = count_columns(last_guess);
!   if (((lines > 1) && ((i>1) || (continue_searching_column(last_guess, 
last_guess, all_words)))) ||
!       ((lines == 1) && (large_enough_gap(last_guess)))) {
      // copy match into permenant html_table
  
      if (indentation.columns != 0) {
***************
*** 3311,3316 ****
--- 3587,3593 ----
      if (debug_table_on) {
        display_columns(start->text_string, "[g] last_guess", last_guess);
      }
+ 
      indentation.no_of_columns = count_columns(last_guess);
      indentation.columns       = (struct text_defn 
*)malloc(indentation.no_of_columns*sizeof(struct text_defn));
  
***************
*** 3328,3335 ****
  
  void html_printer::define_cell (int left, int right)
  {
!   html.put_string("<td align=\"left\"  width=\"");
!   
html.put_float(((double)(right-left))/((double)(right_margin_indent-left_margin_indent))*100.0);
    html.put_string("%\">\n");
  }
  
--- 3605,3618 ----
  
  void html_printer::define_cell (int left, int right)
  {
!   float 
f=((float)(right-left))/((float)(right_margin_indent-left_margin_indent))*100.0;
! 
!   html.put_string("<td valign=\"top\" align=\"left\"  width=\"");
!   if (f > 1.0) {
!     html.put_float(f);
!   } else {
!     html.put_float(1.0);
!   }
    html.put_string("%\">\n");
  }
  
***************
*** 3338,3351 ****
   *                        write out html text within this region.
   */
  
! void html_printer::column_display_word (int left, int right, int next)
  {
    text_glob *g=page_contents->words.get_data();
  
    if (left != next) {
      define_cell(left, next);
!     begin_paragraph(left_alignment);
!     while ((g != 0) && (g->minv <= indentation.vertical_limit)) {
        if ((left <= g->minh) && (g->minh<right)) {
        char *postword=html_position_text(g, left, right);
        
--- 3621,3634 ----
   *                        write out html text within this region.
   */
  
! void html_printer::column_display_word (int vert, int left, int right, int 
next)
  {
    text_glob *g=page_contents->words.get_data();
  
    if (left != next) {
      define_cell(left, next);
!     begin_paragraph_no_height(left_alignment);
!     while ((g != 0) && (g->minv <= vert)) {
        if ((left <= g->minh) && (g->minh<right)) {
        char *postword=html_position_text(g, left, right);
        
***************
*** 3363,3380 ****
          issued_newline = FALSE;
        }
        }
!       page_contents->words.move_right();
        if (page_contents->words.is_equal_to_head()) {
        g = 0;
        page_contents->words.start_from_tail();
        } else {
!       g=page_contents->words.get_data();
        }
      }
      end_paragraph();
      html.put_string("</td>\n");
      if (g != 0) {
        page_contents->words.move_left();
      }
    }
  }
--- 3646,3673 ----
          issued_newline = FALSE;
        }
        }
!       if (page_contents->words.is_equal_to_tail()) {
!       g = 0;
!       } else {
!       page_contents->words.move_right();
!       g=page_contents->words.get_data();
!       }
! #if 0
        if (page_contents->words.is_equal_to_head()) {
        g = 0;
        page_contents->words.start_from_tail();
        } else {
! 
        }
+ #endif
      }
      end_paragraph();
      html.put_string("</td>\n");
      if (g != 0) {
        page_contents->words.move_left();
+       // and correct output_vpos
+       g=page_contents->words.get_data();
+       output_vpos = g->minv;
      }
    }
  }
***************
*** 3385,3395 ****
  
  void html_printer::start_table (void)
  {
    end_paragraph();
    html.put_string("\n<table width=\"100%\"  rules=\"none\"  frame=\"none\"  
cols=\"");
    html.put_number(indentation.no_of_columns);
    html.put_string("\">\n");
-   html.put_string("<tr valign=\"top\" align=\"left\">\n");
  }
  
  /*
--- 3678,3689 ----
  
  void html_printer::start_table (void)
  {
+   int i;
+ 
    end_paragraph();
    html.put_string("\n<table width=\"100%\"  rules=\"none\"  frame=\"none\"  
cols=\"");
    html.put_number(indentation.no_of_columns);
    html.put_string("\">\n");
  }
  
  /*
***************
*** 3398,3404 ****
  
  void html_printer::end_table (void)
  {
!   html.put_string("</tr></table>\n");
    indentation.no_of_columns = 0;
  }
  
--- 3692,3698 ----
  
  void html_printer::end_table (void)
  {
!   html.put_string("</table>\n");
    indentation.no_of_columns = 0;
  }
  
***************
*** 3411,3417 ****
    if (left == right) {
      return( right );
    } else {
!     int rightmost=0;
      text_glob *start = page_contents->words.get_data();
      text_glob *g     = start;
  
--- 3705,3711 ----
    if (left == right) {
      return( right );
    } else {
!     int rightmost=-1;
      text_glob *start = page_contents->words.get_data();
      text_glob *g     = start;
  
***************
*** 3428,3434 ****
        }
      }
      rewind_text_to(start);
!     return( rightmost );
    }
  }
  
--- 3722,3891 ----
        }
      }
      rewind_text_to(start);
!     if (rightmost == -1) {
!       return( right );  // no words in this column
!     } else {
!       return( rightmost );
!     }
!   }
! }
! 
! /*
!  *  column_calculate_left_margin - scan through the column and find the left 
most margin
!  */
! 
! int html_printer::column_calculate_left_margin (int left, int right)
! {
!   if (left == right) {
!     return( left );
!   } else {
!     int leftmost=right;
!     text_glob *start = page_contents->words.get_data();
!     text_glob *g     = start;
! 
!     while ((g != 0) && (g->minv <= indentation.vertical_limit)) {
!       if ((left <= g->minh) && (g->minh<right)) {
!       leftmost = min(g->minh, leftmost);
!       }
!       page_contents->words.move_right();
!       if (page_contents->words.is_equal_to_head()) {
!       g = 0;
!       page_contents->words.start_from_tail();
!       } else {
!       g=page_contents->words.get_data();
!       }
!     }
!     rewind_text_to(start);
!     if (leftmost == right) {
!       return( left );  // no words in this column
!     } else {
!       return( leftmost );
!     }
!   }
! }
! 
! /*
!  *  find_column_index - returns the index to the column in which glob, t, 
exists.
!  */
! 
! int html_printer::find_column_index (text_glob *t)
! {
!   int i=0;
! 
!   while ((i<indentation.no_of_columns) &&
!        (! ((indentation.columns[i].left<=t->minh) &&
!            (indentation.columns[i].right>t->minh)))) {
!     i++;
!   }
!   return( i );
! }
! 
! /*
!  *  determine_row_limit - checks each row to see if there is a gap in a cell.
!  *                        We return the vertical position after the empty cell
!  *                        at the start of the next line.
!  */
! 
! int html_printer::determine_row_limit (text_glob *start, int v)
! {
!   text_glob *t;
!   int        i;
!   int        vpos, prev, last;
!   int is_gap[MAX_WORDS_PER_LINE];
! 
!   if (v >= indentation.vertical_limit) {
!     return( v+1 );
!   } else {
!     // initially we start with all gaps in our table
!     // after a gap we start a new row
!     // here we set the gap array to the previous line
! 
!     if (v>=0) {
!       t = page_contents->words.get_data();
!       if (t->minv < v) {
!       do {
!         page_contents->words.move_right();
!         t = page_contents->words.get_data();
!       } while ((! page_contents->words.is_equal_to_head()) &&
!                (t->minv <= v));
!       }
!     }
!     if (! page_contents->words.is_equal_to_head()) {
!       page_contents->words.move_left();
!     }
!     t = page_contents->words.get_data();
!     prev = t->minv;
!     for (i=0; i<indentation.no_of_columns; i++) {
!       is_gap[i] = prev;
!     }
! 
!     if (! page_contents->words.is_equal_to_tail()) {
!       page_contents->words.move_right();
!     }
!     t = page_contents->words.get_data();
!     vpos = t->minv;
! 
!     // now check each row for a gap
!     do {
!       last = vpos;
!       vpos = t->minv;
!       i = find_column_index(t);
!       if (! is_on_same_line(t, last)) {
!       prev = last;
!       }
! 
!       if ((is_gap[i] != vpos) && (is_gap[i] != prev) &&
!         (indentation.columns[i].is_used)) {
!       // no word on previous line - must be a gap - force alignment of row
!       rewind_text_to(start);
!       return( last );
!       }
!       is_gap[i] = vpos;
!       page_contents->words.move_right();
!       t = page_contents->words.get_data();
!     } while ((! page_contents->words.is_equal_to_head()) &&
!            (vpos < indentation.vertical_limit) && (vpos >= last));
!     page_contents->words.move_left();
!     t = page_contents->words.get_data();
!     rewind_text_to(start);
!     return( indentation.vertical_limit );
!   }
! }
! 
! /*
!  *  assign_used_columns - sets the is_used field of the column array of 
records.
!  */
! 
! void html_printer::assign_used_columns (text_glob *start)
! {
!   text_glob *t = start;
!   int        i;
! 
!   for (i=0; i<indentation.no_of_columns; i++) {
!     indentation.columns[i].is_used = FALSE;
!   }
! 
!   rewind_text_to(start);
!   if (! page_contents->words.is_empty()) {
!     do {
!       i = find_column_index(t);
!       if (indentation.columns[i].left != 0) {
!       indentation.columns[i].is_used = TRUE;
!       }
!       page_contents->words.move_right();
!       t = page_contents->words.get_data();
!     } while ((t->minv<indentation.vertical_limit) &&
!            (! page_contents->words.is_equal_to_head()));
!   }
!   if (debug_table_on) {
!     for (i=0; i<indentation.no_of_columns; i++) {
!       fprintf(stderr, " <left=%d right=%d is_used=%d> ",
!             indentation.columns[i].left,
!             indentation.columns[i].right,
!             indentation.columns[i].is_used);
!     }
!     fprintf(stderr, "\n");
!     fflush(stderr);
    }
  }
  
***************
*** 3439,3472 ****
  
  void html_printer::foreach_column_include_text (text_glob *start)
  {
!   int i=0;
!   int left=left_margin_indent;
  
!   if (i<indentation.no_of_columns) {
      start_table();
!     while (i<indentation.no_of_columns) {
!       rewind_text_to(start);
!       // reset the output position to the start of column
!       output_vpos = start->minv;
!       output_hpos = indentation.columns[i].left;
!       
!       column_display_word(left, 
column_calculate_right_margin(indentation.columns[i].left, 
indentation.columns[i].right),
!                         indentation.columns[i].right);
!       i++;
!       left = indentation.columns[i].left;
!     }
! #if 0
!     // and the final column
!     if (i>0) {
!       rewind_text_to(start);
!       // reset the output position to the start of column
!       output_vpos = start->minv;
!       output_hpos = indentation.columns[i-1].left;
  
!       column_display_word(indentation.columns[i-1].left, right_margin_indent, 
right_margin_indent);
!     }
! #endif
      end_table();
    }
  }
  
--- 3896,3956 ----
  
  void html_printer::foreach_column_include_text (text_glob *start)
  {
!   if (indentation.no_of_columns>0) {
!     int i;
!     int left;
!     int limit=-1;
  
!     assign_used_columns(start);
      start_table();
!     rewind_text_to(start);
  
!     do {
!       limit = determine_row_limit(start, limit);   // find the bottom of the 
next row
!       html.put_string("<tr valign=\"top\" align=\"left\">\n");
!       left=left_margin_indent;
!       i=0;
!       start = page_contents->words.get_data();
!       while (i<indentation.no_of_columns) {
!       // reset the output position to the start of column
!       rewind_text_to(start);
!       output_vpos = start->minv;
!       output_hpos = indentation.columns[i].left;
!       // and display each column until limit
!       column_display_word(limit,
!                           
column_calculate_left_margin(indentation.columns[i].left,
!                                                        
indentation.columns[i].right),
!                           
column_calculate_right_margin(indentation.columns[i].left,
!                                                         
indentation.columns[i].right),
!                           indentation.columns[i].right);
!       i++;
!       }
! 
!       if (page_contents->words.is_equal_to_tail()) {
!       start = 0;
!       } else {
!       page_contents->words.sub_move_right();
!       if (page_contents->words.is_empty()) {
!         start = 0;
!       } else {
!         start = page_contents->words.get_data();
!       }
!       }
! 
!       html.put_string("</tr>\n");
!     } while ((limit < indentation.vertical_limit) && (start != 0) &&
!            (! page_contents->words.is_empty()));
      end_table();
+ 
+     if (start == 0) {
+       // finished page remove all words
+       page_contents->words.start_from_head();
+       while (! page_contents->words.is_empty()) {
+       page_contents->words.sub_move_right();
+       }
+     } else if (! page_contents->words.is_empty()) {
+       page_contents->words.move_left();
+     }
    }
  }
  
***************
*** 3534,3540 ****
  
  int html_printer::check_able_to_use_center (text_glob *g)
  {
!   if (auto_on && table_on && (! is_on_same_line(g, output_vpos)) && (! 
using_table_for_indent())) {
      // we are allowed to check for centered line
      // first check to see whether we might be looking at a set of columns
      struct text_defn   last_guess[MAX_WORDS_PER_LINE];
--- 4018,4024 ----
  
  int html_printer::check_able_to_use_center (text_glob *g)
  {
!   if (auto_on && table_on && ((! is_on_same_line(g, output_vpos)) || 
issued_newline) && (! using_table_for_indent())) {
      // we are allowed to check for centered line
      // first check to see whether we might be looking at a set of columns
      struct text_defn   last_guess[MAX_WORDS_PER_LINE];
***************
*** 3556,3564 ****
  
  int html_printer::check_able_to_use_table (text_glob *g)
  {
!   if (auto_on && (! is_on_same_line(g, output_vpos)) && (! 
using_table_for_indent())) {
      // we are allowed to check for table
!     if (found_use_for_table(g)) {
        foreach_column_include_text(g);
        return( TRUE );
      }
--- 4040,4049 ----
  
  int html_printer::check_able_to_use_table (text_glob *g)
  {
!   if (auto_on && ((! is_on_same_line(g, output_vpos)) || issued_newline) && 
(! using_table_for_indent())) {
      // we are allowed to check for table
!     
!     if ((output_hpos != right_margin_indent) && (found_use_for_table(g))) {
        foreach_column_include_text(g);
        return( TRUE );
      }
***************
*** 3635,3646 ****
  {
    char *postword=0;
  
-   begin_paragraph(left_alignment);
  #if 0
!   if (strcmp(g->text_string, "Servant") == 0) {
      stop();
    }
  #endif
  
    if ((! header.written_header) &&
        (is_on_same_line(g, output_vpos) ||
--- 4120,4131 ----
  {
    char *postword=0;
  
  #if 0
!   if (strcmp(g->text_string, "increased.") == 0) {
      stop();
    }
  #endif
+   begin_paragraph(left_alignment);
  
    if ((! header.written_header) &&
        (is_on_same_line(g, output_vpos) ||
***************
*** 3834,3840 ****
  void html_printer::html_display_word (text_glob *g)
  {
  #if 0
!   if (strcmp(g->text_string, "Graph") == 0) {
      stop();
    }
  #endif
--- 4319,4325 ----
  void html_printer::html_display_word (text_glob *g)
  {
  #if 0
!   if (strcmp(g->text_string, "increased.") == 0) {
      stop();
    }
  #endif
***************
*** 4585,4591 ****
        auto_on = FALSE;
        break;
      case 't':
!       table_on = TRUE;
        break;
      case 'F':
        font::command_line_font_dir(optarg);
--- 5070,5076 ----
        auto_on = FALSE;
        break;
      case 't':
!       table_on = FALSE;
        break;
      case 'F':
        font::command_line_font_dir(optarg);
diff -r -c groff/grohtml/ordered_list.h groff-html/grohtml/ordered_list.h
*** groff/grohtml/ordered_list.h        Mon Nov 15 17:08:28 1999
--- groff-html/grohtml/ordered_list.h   Mon Nov 15 11:27:46 1999
***************
*** 69,74 ****
--- 69,78 ----
    list_element<T> *t    = new list_element<T>(in);   // create a new list 
element with data field initialized
    list_element<T> *last;
  
+   if (in == 0) {
+     fatal("cannot add NULL to ordered list");
+   }
+ 
    if (head == 0) {
      head     = t;
      tail     = t;
***************
*** 110,116 ****
  
    if (head == tail) {
      head = 0;
!     delete tail;
      tail = 0;
      ptr  = 0;
    } else {
--- 114,122 ----
  
    if (head == tail) {
      head = 0;
!     if (tail != 0) {
!       delete tail;
!     }
      tail = 0;
      ptr  = 0;
    } else {




reply via email to

[Prev in Thread] Current Thread [Next in Thread]