groff
[Top][All Lists]
Advanced

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

[Groff] html.cc (many table fixes)


From: Gaius Mulley
Subject: [Groff] html.cc (many table fixes)
Date: Tue, 28 Dec 1999 17:19:08 +0000 (GMT)

Hi Werner and Groffians,

My Universities email system has gone to sleep until the 4th Jan
sadly and so I've had to find another porthole onto the Internet
:-(. My email to address@hidden will be buffered (I'm told..).

Here are the patches for html.cc which include many table
fixes. So finally (I think..) it deals with manual pages
in a reasonably sensible manner. (Werner's man.n test
works - I've tried a few others bash.1, zcat.1 etc and
they generate reasonable html IMHO). Sometimes it makes
a mistake when subscripting occurs, but I think it is
much better than before. Anyway I'll let you judge :-)

cheers Gaius

ps. the patch for html.cc is against the repositary at 13:00 GMT
    on 28 Dec 1999

---------- cut here for changlog in full  ----------
1999-12-28  Gaius Mulley  <address@hidden>

        * html.cc: revisited the table handling code with a
        vengeance, aiming to make manual pages generate
        sensible html. Superscripting/subscripting revisited.
        Fixed wierd table lengths. Table widths are now specified
        in percentages. Fixed the man.n test example which Werner
        reported.

1999-12-21  Werner LEMBERG  <address@hidden>

        * grohtml.man: Fixed copyright year.

1999-12-15  Gaius Mulley  <address@hidden>

        * html.cc: Some other fixes.

1999-12-13  Gaius Mulley  <address@hidden>

        * html.cc (main): Added new option `-x' to help debugging tables.

1999-12-11  Gaius Mulley  <address@hidden>

        * html.cc: Fixed image position bugs.  However, three major bugs
        remain: Firstly, grohtml sometimes miscalculates the end of an
        html table resulting in text which appears twice.  Secondly,
        equation numbers are not handled correctly.  Thirdly, equation
        macros and pic macros can confuse grohtml; this can be seen by
        nested `graphic-start's -- I believe the best method to solve this
        is to detect .EQ, .EN, .TS, .TE, .PS, .PE sequences in troff and
        add the graphic-start special character at this point.

        * grohtml.man: Minor fixes.
        
1999-11-29  Gaius Mulley  <address@hidden>

        * design.ms: More updates; added some basic introductional
        information.

        * html.cc: Fixed more bugs mainly in the table handling code.
        Making the code terminate a table at the correct position.
        Indented .IPs appear to work now.  Region ends also correctly
        terminate tables.

1999-11-16  Gaius Mulley  <address@hidden>

        * design.ms, grohtml.man: Updated.

        * html.cc, ordered_list.h: 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.

1999-10-05  Gaius Mulley  <address@hidden>

        * Introduced command line options -r to determine the resolution
        of generated images, -I to determine the format of images
        generated.

        * Fixed many bugs to do with superscripts, subscripts,
        indentation, font changes, and extraneous spaces.

        * Fixed bug in determining the range of polygons and splines.

        * Updated the manual page to reflect the new options.

        * The default image type is png format, however this will only
        work if you have a gs with a png output device.  If you don't have
        a gs with this ability you can either reconfigure html to generate
        gif images by default (alter a #define in html.cc).  Or
        alternatively you can use the -Igif option.

1999-09-27  Werner LEMBERG  <address@hidden>

        * html.cc (move_horizontal): Fonts have changed one character too
        late.
        
1999-09-26  Werner LEMBERG  <address@hidden>

        * grohtml.man: Minor cosmetic fixes.

1999-09-25  Gaius Mulley <address@hidden>

        * grohtml.man, html.cc: Rewrite of the html text component.  Basic
        font faces supported together with font types.  Superscript and
        subscript have also been implemented.  Temporarily removed the
        -P-a switch on grohtml as it is not working (never worked).  This
        is the next `to do'.  Added a simple macro tmac.arkup which
        contains simple html features.  This macro needs further work.
        Arc, spline, polygon fill have all been added and arc max/min xy
        limits are calculated, the same needs to be done for spline.  Many
        bugs have been fixed regarding basic html text.

        * design.ms: New file describing how html.cc works.

Aug 1999

        Initial release, very basic html text generated, quite ugly text
        is generated according to many reports :-) Equations, tables,
        pictures generate gif files via gs and ppmquant, ppmtogif, grops.




---------- cut here for patch ---------- cut here for patch ------------
*** groff-cvs/grohtml/html.cc   Tue Dec 14 23:25:41 1999
--- groff-html/grohtml/html.cc  Tue Dec 28 14:09:51 1999
***************
*** 54,60 ****
  #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
  
  
  /*
--- 54,63 ----
  #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 for multiple lines
! #define MIN_COLUMN_FOR_TWO_LINES       20        // minimum column size 
pixels for a 2 line table
! #define MIN_TEXT_PERCENT                5        // try and round to this 
percentage value for used columns
! #define PERCENT_THRESHOLD              20        // don't bother trying to 
increase and width greater than this
  
  
  /*
***************
*** 317,323 ****
  
  int text_glob::is_less (text_glob *a, text_glob *b)
  {
!   if (is_intersection(a->minv, a->maxv, b->minv, b->maxv)) {
      return( a->minh < b->minh );
    } else {
      return( a->maxv < b->maxv );
--- 320,326 ----
  
  int text_glob::is_less (text_glob *a, text_glob *b)
  {
!   if (is_intersection(a->minv+1, a->maxv-1, b->minv+1, b->maxv-1)) {
      return( a->minh < b->minh );
    } else {
      return( a->maxv < b->maxv );
***************
*** 1102,1109 ****
--- 1105,1146 ----
    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
+   int percent;    // what percentage width should we use for this cell?
  };
  
+ /*
+  *  introduce a paragraph class so that we can nest paragraphs
+  *  from plain html text and html tables.
+  */
+ 
+ class html_paragraph {
+ public:
+                             html_paragraph (int in, int need, paragraph_type 
type, html_paragraph *prev);
+                            ~html_paragraph ();
+ 
+   int                      in_paragraph;
+   int                      need_paragraph;
+   paragraph_type           para_type;
+   html_paragraph          *previous;
+ };
+ 
+ /*
+  *  html_paragraph - constructor, fill in the public fields.
+  */
+ 
+ html_paragraph::html_paragraph (int in, int need, paragraph_type type, 
html_paragraph *prev)
+   : in_paragraph(in), need_paragraph(need),
+     para_type(type), previous(prev)
+ {
+ }
+ 
+ /*
+  *  html_paragraph - deconstructor
+  */
+ 
+ html_paragraph::~html_paragraph ()
+ {
+ }
  
  /*
   * note that html_tables are currently only used to provide a better
***************
*** 1170,1181 ****
    int                  right_margin_indent;
    int                  need_one_newline;
    int                  issued_newline;
!   int                  in_paragraph;
!   int                  need_paragraph;
!   paragraph_type       para_type;
    char                 image_name[MAX_STRING_LENGTH];
    int                  image_number;
    int                  graphic_level;
  
    int                  start_region_vpos;
    int                  start_region_hpos;
--- 1207,1217 ----
    int                  right_margin_indent;
    int                  need_one_newline;
    int                  issued_newline;
!   html_paragraph      *current_paragraph;
    char                 image_name[MAX_STRING_LENGTH];
    int                  image_number;
    int                  graphic_level;
+   int                  supress_sub_sup;
  
    int                  start_region_vpos;
    int                  start_region_hpos;
***************
*** 1225,1234 ****
--- 1261,1274 ----
    int   is_on_same_line               (text_glob *g, int vpos);
    int   looks_like_subscript          (text_glob *g);
    int   looks_like_superscript        (text_glob *g);
+   int   looks_like_smaller_font       (text_glob *g);
+   int   looks_like_larger_font        (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  save_paragraph                (void);
+   void  restore_paragraph             (void);
    void  html_newline                  (void);
    void  convert_to_image              (char *name);
    void  write_title                   (int in_head);
***************
*** 1256,1273 ****
    void  display_regions               (void);
    int   check_able_to_use_table       (text_glob *g);
    int   using_table_for_indent        (void);
!   int   collect_columns               (struct text_defn *line, struct 
text_defn *last, int max_words);
    void  include_into_list             (struct text_defn *line, struct 
text_defn *item);
    int   is_in_column                  (struct text_defn *line, struct 
text_defn *item, int max_words);
!   int   is_column_match               (struct text_defn *match, struct 
text_defn *line1, struct text_defn *line2, int max_words);
    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);
--- 1296,1316 ----
    void  display_regions               (void);
    int   check_able_to_use_table       (text_glob *g);
    int   using_table_for_indent        (void);
!   int   collect_columns               (struct text_defn *next_words, struct 
text_defn *next_cols,
!                                      struct text_defn *last_words, struct 
text_defn *last_cols,
!                                      int max_words);
    void  include_into_list             (struct text_defn *line, struct 
text_defn *item);
    int   is_in_column                  (struct text_defn *line, struct 
text_defn *item, int max_words);
!   int   is_column_match               (struct text_defn *match, struct 
text_defn *line1,
!                                      struct text_defn *line2, int max_words);
    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 cell, 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 i);
    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);
***************
*** 1284,1289 ****
--- 1327,1333 ----
    void  add_right_full_width          (struct text_defn *line, int mingap);
    int   is_continueous_column         (text_defn *last_col, text_defn 
*next_line);
    int   is_exact_left                 (text_defn *last_col, text_defn 
*next_line);
+   int   find_column_index_in_line     (text_glob *t, text_defn *line);
    void  emit_space                    (text_glob *g, int force_space);
    int   is_in_middle                  (int left, int right);
    int   check_able_to_use_center      (text_glob *g);
***************
*** 1297,1302 ****
--- 1341,1369 ----
    int   is_subset_of_columns          (text_defn *a, text_defn *b);
    void  count_hits                    (text_defn *col);
    int   calculate_min_gap             (text_glob *g);
+   int   right_indentation             (struct text_defn *last_guess);
+   void  calculate_percentage_width    (text_glob *start);
+   int   able_to_steal_width           (void);
+   int   need_to_steal_width           (void);
+   int   can_distribute_fairly         (void);
+   void  utilize_round_off             (void);
+   int   will_wrap_text                (int i, text_glob *start);
+   int   next_line_on_left_column      (int i, text_glob *start);
+   void  remove_table_column           (int i);
+   void  remove_unnecessary_unused     (text_glob *start);
+   int   is_small_table                (int lines, struct text_defn 
*last_guess,
+                                      struct text_defn *words_1, struct 
text_defn *cols_1,
+                                      struct text_defn *words_2, struct 
text_defn *cols_2,
+                                      int *limit, int *limit_1);
+   int   is_column_subset              (struct text_defn *cols_1, struct 
text_defn *cols_2);
+   int   is_appropriate_to_start_table (struct text_defn *cols_1, struct 
text_defn *cols_2,
+                                      struct text_defn *last_guess);
+   int   is_a_column                   (int percent);
+   int   right_most_column             (struct text_defn *col);
+   int   large_enough_gap_for_two      (struct text_defn *col);
+   void  remove_zero_percentage_column (void);
+ 
+   // ADD HERE
  
  public:
    html_printer();
***************
*** 1332,1340 ****
    image_number(0),
    graphic_level(0),
    cutoff_heading(100),
!   in_paragraph(0),
!   need_paragraph(0),
!   para_type(left_alignment)
  {
    tempfp = xtmpfile();
    html.set_file(tempfp);
--- 1399,1405 ----
    image_number(0),
    graphic_level(0),
    cutoff_heading(100),
!   supress_sub_sup(TRUE)
  {
    tempfp = xtmpfile();
    html.set_file(tempfp);
***************
*** 1355,1369 ****
      r /= 10;
      point++;
    }
!   res = r;
    html.set_fixed_point(point);
!   space_char_index = font::name_to_index("space");
!   paper_length = font::paperlength;
    if (paper_length == 0)
!     paper_length = 11*font::res;
!   page_contents   = new page;
  
!   postscript_res = 72000;
  }
  
  
--- 1420,1435 ----
      r /= 10;
      point++;
    }
!   res               = r;
    html.set_fixed_point(point);
!   space_char_index  = font::name_to_index("space");
!   paper_length      = font::paperlength;
    if (paper_length == 0)
!     paper_length    = 11*font::res;
!   page_contents     = new page;
  
!   postscript_res    = 72000;
!   current_paragraph = new html_paragraph(FALSE, FALSE, left_alignment, 0);
  }
  
  
***************
*** 1380,1389 ****
    }
    if ((name != 0) && (page_contents->is_in_graphic)) {
      flush_sbuf();
!     int r=font::res;   // resolution of the device actually
      page_contents->add_special_char(&sty, (char *)name, strlen(name),
                                    env->vpos-sty.point_size*r/72, env->hpos,
!                                   env->vpos, env->hpos+w);
      sbuf_end_hpos   = env->hpos + w;
      sbuf_start_hpos = env->hpos;
      sbuf_vpos       = env->vpos;
--- 1446,1455 ----
    }
    if ((name != 0) && (page_contents->is_in_graphic)) {
      flush_sbuf();
!     int r=font::res;   // resolution of the device
      page_contents->add_special_char(&sty, (char *)name, strlen(name),
                                    env->vpos-sty.point_size*r/72, env->hpos,
!                                   env->vpos                    , env->hpos+w);
      sbuf_end_hpos   = env->hpos + w;
      sbuf_start_hpos = env->hpos;
      sbuf_vpos       = env->vpos;
***************
*** 1569,1575 ****
    int r        = font::res;
    int height   = output_style.point_size*r/72;
  
!   if (in_paragraph) {
      // safe to generate a pretty newline
      html.put_string("<br>\n");
    } else {
--- 1635,1641 ----
    int r        = font::res;
    int height   = output_style.point_size*r/72;
  
!   if (current_paragraph->in_paragraph) {
      // safe to generate a pretty newline
      html.put_string("<br>\n");
    } else {
***************
*** 1585,1592 ****
  
  void html_printer::force_begin_paragraph (void)
  {
!   if (in_paragraph && need_paragraph) {
!     switch (para_type) {
  
      case left_alignment:   html.put_string("<p>");
                             break;
--- 1651,1658 ----
  
  void html_printer::force_begin_paragraph (void)
  {
!   if (current_paragraph->in_paragraph && current_paragraph->need_paragraph) {
!     switch (current_paragraph->para_type) {
  
      case left_alignment:   html.put_string("<p>");
                             break;
***************
*** 1594,1600 ****
                             break;
      default:               fatal("unknown paragraph alignment type");
      }
!     need_paragraph   = FALSE;
    }
  }
  
--- 1660,1666 ----
                             break;
      default:               fatal("unknown paragraph alignment type");
      }
!     current_paragraph->need_paragraph = FALSE;
    }
  }
  
***************
*** 1605,1622 ****
  
  void html_printer::begin_paragraph (paragraph_type p)
  {
!   if (! in_paragraph) {
!     int r        = font::res;
!     int height   = output_style.point_size*r/72;
  
      if (output_vpos >=0) {
        // we leave it alone if it is set to the top of page
        output_vpos += height;
      }
!     need_paragraph = TRUE;   // delay the <p> just in case we don't actually 
emit text
!     in_paragraph   = TRUE;
!     issued_newline = TRUE;
!     para_type      = p;
    }
  }
  
--- 1671,1688 ----
  
  void html_printer::begin_paragraph (paragraph_type p)
  {
!   if (! current_paragraph->in_paragraph) {
!     int r                             = font::res;
!     int height                        = output_style.point_size*r/72;
  
      if (output_vpos >=0) {
        // we leave it alone if it is set to the top of page
        output_vpos += height;
      }
!     current_paragraph->need_paragraph = TRUE;   // delay the <p> just in case 
we don't actually emit text
!     current_paragraph->in_paragraph   = TRUE;
!     current_paragraph->para_type      = p;
!     issued_newline                    = TRUE;
    }
  }
  
***************
*** 1628,1638 ****
  
  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;
    }
  }
  
--- 1694,1704 ----
  
  void html_printer::begin_paragraph_no_height (paragraph_type p)
  {
!   if (! current_paragraph->in_paragraph) {
!     current_paragraph->need_paragraph = TRUE;   // delay the <p> just in case 
we don't actually emit text
!     current_paragraph->in_paragraph   = TRUE;
!     current_paragraph->para_type      = p;
!     issued_newline                    = TRUE;
    }
  }
  
***************
*** 1643,1651 ****
  
  void html_printer::end_paragraph (void)
  {
!   if (in_paragraph) {
      // check whether we have generated any text inbetween the potential 
paragraph begin end
!     if (! need_paragraph) {
        int r        = font::res;
        int height   = output_style.point_size*r/72;
  
--- 1709,1717 ----
  
  void html_printer::end_paragraph (void)
  {
!   if (current_paragraph->in_paragraph) {
      // check whether we have generated any text inbetween the potential 
paragraph begin end
!     if (! current_paragraph->need_paragraph) {
        int r        = font::res;
        int height   = output_style.point_size*r/72;
  
***************
*** 1653,1661 ****
        html.put_string("</p>\n");
      }
      terminate_current_font();
!     para_type    = left_alignment;
!     in_paragraph = FALSE;
    }
  }
  
  /*
--- 1719,1756 ----
        html.put_string("</p>\n");
      }
      terminate_current_font();
!     current_paragraph->para_type    = left_alignment;
!     current_paragraph->in_paragraph = FALSE;
!   }
! }
! 
! /*
!  *  save_paragraph - saves the current paragraph state and
!  *                   creates new paragraph state.
!  */
! 
! void html_printer::save_paragraph (void)
! {
!   if (current_paragraph == 0) {
!     fatal("current_paragraph is NULL");
    }
+   current_paragraph = new html_paragraph(current_paragraph->in_paragraph,
+                                        current_paragraph->need_paragraph,
+                                        current_paragraph->para_type,
+                                        current_paragraph);
+   terminate_current_font();
+ }
+ 
+ /*
+  *  restore_paragraph - restores the previous paragraph state.
+  */
+ 
+ void html_printer::restore_paragraph (void)
+ {
+   html_paragraph *old = current_paragraph;
+ 
+   current_paragraph = current_paragraph->previous;
+   free(old);
  }
  
  /*
***************
*** 1683,1709 ****
        if ((w->maxh >= 0) && (w->maxh > right_margin_indent)) {
          right_margin_indent = w->maxh;
  #if 0
!         if (right_margin_indent == 950) stop();
  #endif
        }
        page_contents->words.move_right();
        } while (! page_contents->words.is_equal_to_head());
      }
  
!     if (! page_contents->lines.is_empty()) {
!       // now check for diagrams for right margin
!       page_contents->lines.start_from_head();
!       do {
!       g = page_contents->lines.get_data();
!       if ((g->maxh >= 0) && (g->maxh > right_margin_indent)) {
!         right_margin_indent = g->maxh;
  #if 0
!         if (right_margin_indent == 950) stop();
  #endif
!       }
!       page_contents->lines.move_right();
!       } while (! page_contents->lines.is_equal_to_head());
!     }
  
      // now we know the right margin lets do the same to find left margin
  
--- 1778,1807 ----
        if ((w->maxh >= 0) && (w->maxh > right_margin_indent)) {
          right_margin_indent = w->maxh;
  #if 0
!         if (right_margin_indent == 758) stop();
  #endif
        }
        page_contents->words.move_right();
        } while (! page_contents->words.is_equal_to_head());
      }
  
!     /*
!      *  only examine graphics if no words present
!      */
!       if (! page_contents->lines.is_empty()) {
!       // now check for diagrams for right margin
!       page_contents->lines.start_from_head();
!       do {
!         g = page_contents->lines.get_data();
!         if ((g->maxh >= 0) && (g->maxh > right_margin_indent)) {
!           right_margin_indent = g->maxh;
  #if 0
!           if (right_margin_indent == 950) stop();
  #endif
!         }
!         page_contents->lines.move_right();
!       } while (! page_contents->lines.is_equal_to_head());
!       }
  
      // now we know the right margin lets do the same to find left margin
  
***************
*** 1719,1739 ****
        } while (! page_contents->words.is_equal_to_head());
      }
  
!     if (! page_contents->lines.is_empty()) {
!       // now check for diagrams
!       page_contents->lines.start_from_head();
!       do {
!       g = page_contents->lines.get_data();
!       if ((g->minh >= 0) && (g->minh < left_margin_indent)) {
!         left_margin_indent = g->minh;
!       }
!       page_contents->lines.move_right();
!       } while (! page_contents->lines.is_equal_to_head());
!     }
    }
  }
  
- 
  /*
   *  calculate_region - runs through the graphics globs and text globs
   *                     and ensures that all graphic routines
--- 1817,1840 ----
        } while (! page_contents->words.is_equal_to_head());
      }
  
!       /*
!        *  only examine graphic for margins if text yields nothing
!        */
! 
!       if (! page_contents->lines.is_empty()) {
!       // now check for diagrams
!       page_contents->lines.start_from_head();
!       do {
!         g = page_contents->lines.get_data();
!         if ((g->minh >= 0) && (g->minh < left_margin_indent)) {
!           left_margin_indent = g->minh;
!         }
!         page_contents->lines.move_right();
!       } while (! page_contents->lines.is_equal_to_head());
!       }
    }
  }
  
  /*
   *  calculate_region - runs through the graphics globs and text globs
   *                     and ensures that all graphic routines
***************
*** 2314,2321 ****
  void html_printer::flush_page (void)
  {
    calculate_margin();
!   output_vpos = -1;
!   output_hpos = left_margin_indent;
  #if 0
    dump_page();
  #endif
--- 2415,2423 ----
  void html_printer::flush_page (void)
  {
    calculate_margin();
!   output_vpos     = -1;
!   output_hpos     = left_margin_indent;
!   supress_sub_sup = TRUE;
  #if 0
    dump_page();
  #endif
***************
*** 2325,2331 ****
    page_contents->calculate_region();
    remove_duplicate_regions();
    find_title();
! 
    traverse_page_regions();
    terminate_current_font();
    if (need_one_newline) {
--- 2427,2433 ----
    page_contents->calculate_region();
    remove_duplicate_regions();
    find_title();
!   supress_sub_sup = TRUE;
    traverse_page_regions();
    terminate_current_font();
    if (need_one_newline) {
***************
*** 2431,2441 ****
        if (g->text_style.f != 0) {
        fontname = g->text_style.f->get_name();
        size     = (font::res/(72*font::sizescale))*g->text_style.point_size;
- 
-       html_change_font(g, fontname, size);
-       } else {
-       html_change_font(g, fontname, size);
        }
      }
    } else {
      // is to troff
--- 2533,2540 ----
        if (g->text_style.f != 0) {
        fontname = g->text_style.f->get_name();
        size     = (font::res/(72*font::sizescale))*g->text_style.point_size;
        }
+       html_change_font(g, fontname, size);
      }
    } else {
      // is to troff
***************
*** 2455,2461 ****
    }
  }
  
- 
  /*
   *  is_bold - returns TRUE if the text inside, g, is using a bold face.
   *            It returns FALSE is g contains a raw html command, even if this 
uses
--- 2554,2559 ----
***************
*** 2710,2726 ****
    }
  }
  
  int html_printer::looks_like_subscript (text_glob *g)
  {
!   return(((output_vpos < g->minv) && (output_style.point_size != 0) &&
!         (output_style.point_size > g->text_style.point_size)));
  }
  
  
  int html_printer::looks_like_superscript (text_glob *g)
  {
!   return(((output_vpos > g->minv) && (output_style.point_size != 0) &&
!         (output_style.point_size > g->text_style.point_size)));
  }
  
  /*
--- 2808,2872 ----
    }
  }
  
+ /*
+  *  looks_like_subscript - returns TRUE if, g, looks like a subscript.
+  */
+ 
  int html_printer::looks_like_subscript (text_glob *g)
  {
!   int r        = font::res;
!   int height   = output_style.point_size*r/72;
! 
!   /* was return( ((output_vpos < g->minv) && (output_style.point_size != 0) &&
!    *             (output_style.point_size > g->text_style.point_size)) );
!    */
! 
!   return( (! supress_sub_sup) && (output_vpos+height < g->maxv) );
  }
  
+ /*
+  *  looks_like_superscript - returns TRUE if, g, looks like a superscript.
+  */
  
  int html_printer::looks_like_superscript (text_glob *g)
  {
!   int r        = font::res;
!   int height   = output_style.point_size*r/72;
! 
! /* was
!  * return(((output_vpos > g->minv) && (output_style.point_size != 0) &&
!  *        (output_style.point_size > g->text_style.point_size)));
!  */
! 
!   return( (! supress_sub_sup) && (output_vpos+height > g->maxv) );
! }
! 
! /*
!  *  looks_like_larger_font - returns TRUE if, g, can be treated as a larger 
font.
!  *                           g needs to be on the same line
!  */
! 
! int html_printer::looks_like_larger_font (text_glob *g)
! {
!   int r        = font::res;
!   int height   = output_style.point_size*r/72;
! 
!   return( (output_vpos+height == g->maxv) && (output_style.point_size != 0) &&
!         (convertSizeToHTML(g->text_style.point_size)+1 == 
convertSizeToHTML(output_style.point_size)) );
! }
! 
! /*
!  *  looks_like_smaller_font - returns TRUE if, g, can be treated as a smaller 
font.
!  *                            g needs to be on the same line
!  */
! 
! int html_printer::looks_like_smaller_font (text_glob *g)
! {
!   int r        = font::res;
!   int height   = output_style.point_size*r/72;
! 
!   return( (output_vpos+height == g->maxv) && (output_style.point_size != 0) &&
!         (convertSizeToHTML(g->text_style.point_size) == 
convertSizeToHTML(output_style.point_size)+1) );
  }
  
  /*
***************
*** 2737,2746 ****
  
  int html_printer::is_on_same_line (text_glob *g, int vpos)
  {
    return(
         (vpos >= 0) &&
!        is_intersection(vpos, vpos+g->text_style.point_size*font::res/72-1, 
g->minv, g->maxv)
!         );
  }
  
  
--- 2883,2896 ----
  
  int html_printer::is_on_same_line (text_glob *g, int vpos)
  {
+   if (g->is_html_command) {
+     stop();
+   }
    return(
         (vpos >= 0) &&
!        (is_intersection(vpos, vpos+g->text_style.point_size*font::res/72-1, 
g->minv, g->maxv))
!        );
!   // was && ((is_intersection(vpos, vpos, g->minv, g->maxv) && 
(g->is_raw_command))))
  }
  
  
***************
*** 2750,2760 ****
  
  void html_printer::make_html_indent (int indent)
  {
-   int  r=font::res;
- 
    html.put_string("<span style=\" text-indent: ");
!   html.put_float(((double)(indent)/((double)r)));
!   html.put_string("in;\"></span>");
  }
  
  /*
--- 2900,2908 ----
  
  void html_printer::make_html_indent (int indent)
  {
    html.put_string("<span style=\" text-indent: ");
!   
html.put_float(((double)(indent*100)/((double)(right_margin_indent-left_margin_indent))));
!   html.put_string("%;\"></span>");
  }
  
  /*
***************
*** 2781,2826 ****
   *  collect_columns - place html text in a column and return the vertical 
limit reached.
   */
  
! int html_printer::collect_columns (struct text_defn *line, struct text_defn 
*last, int max_words)
  {
    text_glob *start = page_contents->words.get_data();
    text_glob *t     = start;
    int  upper_limit = 0;
  
!   line[0].left  = 0;
!   line[0].right = 0;
    if (start != 0) {
      int graphic_limit = end_region_vpos;
  
      if (is_whole_line_bold(t) && (t->minh == left_margin_indent)) {
!       // found header therefore terminate indentation table
!       upper_limit = -t->minv;  // so we know a header has stopped the column
      } else {
!       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++;
        } else if (i>0) {
!         line[i-1].right = t->maxh;
        }
! 
!       // and record the vertical upper limit
        upper_limit = max(t->minv, upper_limit);
  
        prevh = t->maxh;
        page_contents->words.move_right();
        t = page_contents->words.get_data();
        if (page_contents->words.is_equal_to_head()) {
--- 2929,3042 ----
   *  collect_columns - place html text in a column and return the vertical 
limit reached.
   */
  
! int html_printer::collect_columns (struct text_defn *next_words,
!                                  struct text_defn *next_cols,
!                                  struct text_defn *last_words,
!                                  struct text_defn *last_cols,
!                                  int max_words)
  {
    text_glob *start = page_contents->words.get_data();
    text_glob *t     = start;
    int  upper_limit = 0;
  
!   /*
!    *  initialize cols and words
!    */
!   next_words[0].left  = 0;
!   next_words[0].right = 0;
!   next_cols [0].left  = 0;
!   next_cols [0].right = 0;
! 
!   /*
!    *  if we have not reached the end collect the words on the current line
!    */
    if (start != 0) {
      int graphic_limit = end_region_vpos;
  
      if (is_whole_line_bold(t) && (t->minh == left_margin_indent)) {
!       /*
!        *  found header therefore terminate indentation table.
!        *  Return a negative number so we know a header has
!        *  stopped the column
!        */
!       upper_limit = -t->minv;
      } else {
!       int i      =0;    // is the index into next_cols
!       int j      =0;    // is the column index for last_cols
!       int k      =0;    // is the index into next_words
!       int l      =0;    // is the index into next_words
        int prevh  =0;
        int mingap =calculate_min_gap(start);
  
+       /*
+        *  while words on the same line record them and any significant gaps
+        */
        while ((t != 0) && (is_on_same_line(t, start->minv) && (i<max_words)) &&
             ((graphic_limit == -1) || (graphic_limit > t->minv))) {
! 
!       /*
!        *  now find column index from the last line which corresponds to, t.
!        */
!       j = find_column_index_in_line(t, last_cols);
! 
!       /*
!        *  now find word index from the last line which corresponds to, t.
!        */
!       l = find_column_index_in_line(t, last_words);
! 
!       /*
!        *  Note t->minh might equal t->maxh when we are passing a special 
device character via \X
!        *       we currently ignore this when considering tables
!        *
!        *  if we have found a significant gap then record it
!        */
!       if (((t->minh - prevh >= mingap) ||
!            ((last_cols  != 0) && (last_cols [j].left != 0) && (t->minh == 
last_cols [j].left))) &&
            (t->minh != t->maxh)) {
!         next_cols[i].left    = t->minh;
!         next_cols[i].right   = t->maxh;
          i++;
+         /*
+          *  terminate the array
+          */
+         if (i<max_words) {
+           next_cols[i].left  = 0;
+           next_cols[i].right = 0;
+         }
        } else if (i>0) {
!         /*
!          *  move previous right hand column to align with, t.
!          */
!         
!         if (t->minh > next_cols[i-1].left) {
!           /*
!            *  a simple precaution in case we get globs which are technically 
on the same line
!            *  (sadly this does occur sometimes - maybe we should be stricter 
with is_on_same_line)
!            *  --fixme--
!            */
!           next_cols[i-1].right = max(next_cols[i-1].right, t->maxh);
!         }
        }
!       /*
!        *  remember to record the individual words
!        */
!       next_words[k].left  = t->minh;
!       next_words[k].right = t->maxh;
!       k++;
! 
!       /*
!        *  and record the vertical upper limit
!        */
        upper_limit = max(t->minv, upper_limit);
  
+       /*
+        *  and update prevh - used to detect a when a different line is seen
+        */
        prevh = t->maxh;
+ 
+       /*
+        *  get next word into, t, which equals 0, if no word is found
+        */
        page_contents->words.move_right();
        t = page_contents->words.get_data();
        if (page_contents->words.is_equal_to_head()) {
***************
*** 2828,2836 ****
        }
        }
  
!       if (i<max_words) {
!       line[i].left  = 0;
!       line[i].right = 0;
        }
      }
    }
--- 3044,3075 ----
        }
        }
  
!       /*
!        *  and terminate the next_words array
!        */
! 
!       if (k<max_words) {
!       next_words[k].left  = 0;
!       next_words[k].right = 0;
!       }
! 
!       /*
!        *  consistency check, next_cols, after removing redundant colums.
!        */
! 
!       remove_redundant_columns(next_cols);
! 
!       for (k=0; k<count_columns(next_cols); k++) {
!       if (next_cols[k].left > next_cols[k].right) {
!         fprintf(stderr, "left > right\n"); fflush(stderr);
!         stop();
!         fatal("next_cols has messed up columns");
!       }
!       if ((k>0) && (k+1<count_columns(next_cols)) && (next_cols[k].right > 
next_cols[k+1].left)) {
!         fprintf(stderr, "next_cols[k].right > next_cols[k+1].left\n"); 
fflush(stderr);
!         stop();
!         fatal("next_cols has messed up columns");
!       }
        }
      }
    }
***************
*** 3248,3254 ****
        i++;
      }
    }
!   // 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;
--- 3487,3493 ----
        i++;
      }
    }
!   // now let us 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;
***************
*** 3312,3320 ****
    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)) &&
--- 3551,3559 ----
    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 with no gap
      return( FALSE );
    }
    return( (count == count_columns(last_col)) &&
***************
*** 3356,3365 ****
        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 );
--- 3595,3602 ----
        i++;
      } else {
        // not good enough for a single line, remove it
!       last_col[i].right = last_col[i+1].right;
!       remove_entry_in_line(last_col, i+1);
      }
    }
    return( found );
***************
*** 3450,3526 ****
  }
  
  /*
   *  found_use_for_table - checks whether the some words on one line directly 
match
   *                        the horizontal alignment of the line below.
   */
  
  int html_printer::found_use_for_table (text_glob *start)
  {
    text_glob         *t;
!   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, "man") == 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;
  
    if (page_contents->words.is_equal_to_head() || (limit == 0)) {
!     next_line[0].left  = 0;
!     next_line[0].right = 0;
    } 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
! 
!   if (single_centered_line(last_raw, next_line, start)) {
      rewind_text_to(start);
      write_centered_line(start);
!     indentation.no_of_columns = 0;   // center instead
      return( TRUE );
    } else if (! table_on) {
      rewind_text_to(start);
      return( FALSE );
    }
  
!   combine_line(all_words, next_line);
    if (debug_table_on) {
!     display_columns(start->text_string, "[b] all_words", all_words);
    }
  
!   if ((! remove_white_using_words(next_guess, last_guess, next_line))) {
    }
  
    if ((! conflict_with_words(next_guess, all_words)) &&
        (continue_searching_column(next_guess, next_guess, all_words)) &&
        (! page_contents->words.is_equal_to_head()) &&
        ((end_region_vpos < 0) || (limit < end_region_vpos)) &&
        (limit > 0)) {
  
!     combine_line(last_guess, next_line);
!     // subtract any columns which are bridged by a sequence of words
      do {
!       copy_line(prev_guess, next_guess);
        combine_line(last_guess, next_guess);
  
        if (debug_table_on) {
--- 3687,4345 ----
  }
  
  /*
+  *  right_indentation - returns TRUE if a single column has been found and
+  *                      it resembles an indentation. Ie .RS/.RE or ABSTACT
+  */
+ 
+ int html_printer::right_indentation (struct text_defn *last_guess)
+ {
+   // it assumes that last_guess contains a single column
+   return( (last_guess[0].left > left_margin_indent) );
+ }
+ 
+ /*
+  *  able_to_steal_width - returns TRUE if we have an unused column which we 
can steal from.
+  *                        It must have more than MIN_TEXT_PERCENT to do this.
+  */
+ 
+ int html_printer::able_to_steal_width (void)
+ {
+   int i;
+ 
+   for (i=0; i<indentation.no_of_columns; i++) {
+     if ((! indentation.columns[i].is_used) &&
+       (indentation.columns[i].percent > MIN_TEXT_PERCENT)) {
+       return( TRUE );
+     }
+   }
+   return( FALSE );
+ }
+ 
+ /*
+  *  is_divisible_by - returns TRUE if n is divisible by d leaving no 
remainder.
+  */
+ 
+ static int is_divisible_by (int n, int d)
+ {
+   return( (n % d) == 0 );
+ }
+ 
+ /*
+  *  need_to_steal_width - returns TRUE if a used column need to be
+  *                        given a little extra width for safty sake.
+  */
+ 
+ int html_printer::need_to_steal_width (void)
+ {
+   int i;
+ 
+   for (i=0; i<indentation.no_of_columns; i++) {
+     if ((indentation.columns[i].is_used) &&
+       (indentation.columns[i].percent == (((indentation.columns[i].right - 
indentation.columns[i].left) * 100) /
+                                           
(right_margin_indent-left_margin_indent))) &&
+       (indentation.columns[i].percent < PERCENT_THRESHOLD)) {
+       return( TRUE );
+     }
+   }
+   return( FALSE );
+ }
+ 
+ /*
+  *  utilize_round_off - utilize the remaining percent width in text columns
+  */
+ 
+ void html_printer::utilize_round_off (void)
+ {
+   int total = 0;
+   int excess, i;
+ 
+   // use up the spare excess
+   for (i=0; i<indentation.no_of_columns; i++) {
+     total += indentation.columns[i].percent;
+   }
+   excess = 100-total;
+   for (i=0; (i<indentation.no_of_columns) && (excess>0); i++) {
+     if ((indentation.columns[i].is_used) &&
+       (indentation.columns[i].percent < PERCENT_THRESHOLD)) {
+       indentation.columns[i].percent++;
+       excess--;
+     }
+   }
+   // we might as well try and keep any numbers simple if possible
+   for (i=0; (i<indentation.no_of_columns) && (excess>0); i++) {
+     if ((indentation.columns[i].is_used) &&
+       (! is_divisible_by(indentation.columns[i].percent, MIN_TEXT_PERCENT))) {
+       indentation.columns[i].percent++;
+       excess--;
+     }
+   }
+   // forget the niceties lets just use excess up now!
+   for (i=0; (i<indentation.no_of_columns) && (excess>0); i++) {
+     if (indentation.columns[i].is_used) {
+       indentation.columns[i].percent++;
+       excess--;
+     }
+   }
+ }
+ 
+ /*
+  *  can_distribute_fairly - returns TRUE if we can redistribute some of the 
unused width into
+  *                          columns that are used.
+  */
+ 
+ int html_printer::can_distribute_fairly (void)
+ {
+   int i;
+   int total=0;
+   int used =0;
+   int excess;
+ 
+   // firstly total up all percentages - so we can use round offs
+   for (i=0; i<indentation.no_of_columns; i++) {
+     total += indentation.columns[i].percent;
+     if ((indentation.columns[i].is_used) &&
+       (indentation.columns[i].percent < PERCENT_THRESHOLD)) {
+       used++;
+     }
+   }
+   // 
+   excess = 100-total;
+   if (excess < used) {
+     for (i=0; i<indentation.no_of_columns; i++) {
+       if (! indentation.columns[i].is_used) {
+       if (indentation.columns[i].percent > MIN_TEXT_PERCENT) {
+         indentation.columns[i].percent--;
+         excess++;
+       }
+       }
+     }
+   }
+   if (excess >= used) {
+     for (i=0; i<indentation.no_of_columns; i++) {
+       if ((indentation.columns[i].is_used) &&
+         (indentation.columns[i].percent < PERCENT_THRESHOLD) &&
+         (indentation.columns[i].percent == (((indentation.columns[i].right - 
indentation.columns[i].left) * 100) /
+                                             
(right_margin_indent-left_margin_indent)))) {
+       indentation.columns[i].percent++;
+       excess--;
+       }
+     }
+     return( TRUE );
+   }
+   return( FALSE );
+ }
+ 
+ /*
+  *  remove_table_column - removes column, i, from the indentation.
+  */
+ 
+ void html_printer::remove_table_column (int i)
+ {
+   while (i<indentation.no_of_columns) {
+     indentation.columns[i].left    = indentation.columns[i+1].left;
+     indentation.columns[i].right   = indentation.columns[i+1].right;
+     indentation.columns[i].is_used = indentation.columns[i+1].is_used;
+     indentation.columns[i].percent = indentation.columns[i+1].percent;
+     i++;
+   }
+   indentation.no_of_columns--;
+ }
+ 
+ /*
+  *  next_line_on_left_column - returns TRUE if the next line in
+  *                             column, i, has a word on the left margin.
+  */
+ 
+ int html_printer::next_line_on_left_column (int i, text_glob *start)
+ {
+   int current_vpos=start->minv;
+ 
+   while ((start != 0) && (start->minv < indentation.vertical_limit) &&
+        (is_on_same_line(start, current_vpos))) {
+     if (page_contents->words.is_equal_to_tail()) {
+       start = 0;
+     } else {
+       page_contents->words.move_right();
+       start = page_contents->words.get_data();
+     }
+   }
+   if ((start != 0) && (start->minv < indentation.vertical_limit)) {
+     // onto next line now
+     current_vpos=start->minv;
+     while ((start != 0) && (start->minv < indentation.vertical_limit) &&
+          (is_on_same_line(start, current_vpos))) {
+       if (start->minh == indentation.columns[i].left) {
+       return( TRUE );
+       }
+       if (page_contents->words.is_equal_to_tail()) {
+       start = 0;
+       } else {
+       page_contents->words.move_right();
+       start = page_contents->words.get_data();
+       }
+     }
+   }
+   return( FALSE );
+ }
+ 
+ /*
+  *  will_wrap_text - returns TRUE if text is wrapped in column, i.
+  */
+ 
+ int html_printer::will_wrap_text (int i, text_glob *start)
+ {
+   if (auto_on) {
+     rewind_text_to(start);
+     while ((start != 0) && (start->minv < indentation.vertical_limit)) {
+       if (indentation.columns[i].right == start->maxh) {
+       // ok right word is on column boarder - check next line
+       if (next_line_on_left_column(i, start)) {
+         return( TRUE );
+       }
+       }
+       if (page_contents->words.is_equal_to_tail()) {
+       start = 0;
+       } else {
+       page_contents->words.move_right();
+       start = page_contents->words.get_data();
+       }
+     }
+   }
+   return( FALSE );
+ }
+ 
+ /*
+  *  remove_unnecessary_unused - runs through a table and decides whether an 
unused
+  *                              column can be removed. This is only true if 
the
+  *                              column to the left does not wrap text.
+  */
+ 
+ void html_printer::remove_unnecessary_unused (text_glob *start)
+ {
+   int i=0;
+ 
+   while (i<indentation.no_of_columns) {
+     if ((indentation.columns[i].is_used) &&
+       (i+1<indentation.no_of_columns) && (! 
indentation.columns[i+1].is_used)) {
+       /*
+        *  so i+1 is unused and there is a used column to the left.
+        *  Now we check whether we can add the unused column to the column, i.
+        *  This can only be done if column, i, is not wrapping text.
+        */
+       if (! will_wrap_text(i, start)) {
+       indentation.columns[i].percent += indentation.columns[i+1].percent;
+       remove_table_column(i+1);
+       i=-1;
+       }
+     }
+     i++;
+   }
+ }
+ 
+ /*
+  *  remove_zero_percentage_column - removes all zero percentage width columns
+  */
+ 
+ void html_printer::remove_zero_percentage_column (void)
+ {
+   int i=0;
+ 
+   while (i<indentation.no_of_columns) {
+     if (indentation.columns[i].percent == 0) {
+       remove_table_column(i);
+       i=0;
+     } else {
+       i++;
+     }
+   }
+ }
+ 
+ /*
+  *  calculate_percentage_width - calculates the percentage widths,
+  *                               this function will be generous to
+  *                               columns which have words as some browsers
+  *                               produce messy output if the percentage is 
exactly
+  *                               that required for text..
+  *                               We try and round up to MIN_TEXT_PERCENT
+  *                               of course we can only do this if we can 
steal from
+  *                               an unused column.
+  */
+ 
+ void html_printer::calculate_percentage_width (text_glob *start)
+ {
+   int i;
+ 
+   // firstly calculate raw percentages
+   for (i=0; i<indentation.no_of_columns; i++) {
+     indentation.columns[i].percent = (((indentation.columns[i].right - 
indentation.columns[i].left) * 100) /
+                                     (right_margin_indent-left_margin_indent));
+   }
+   // now steal from the unused columns..
+   remove_unnecessary_unused(start);
+   utilize_round_off();
+   remove_zero_percentage_column();
+ }
+ 
+ 
+ /*
+  *  is_column_subset - returns TRUE if the columns described by small can be 
contained in
+  *                     the columns in large.
+  */
+ 
+ int html_printer::is_column_subset (struct text_defn *small, struct text_defn 
*large)
+ {
+   int ns=count_columns(small);
+   int nl=count_columns(large);
+   int found;
+   int i=0;
+   int j;
+ 
+   while (i<ns) {
+     j=0;
+     found = FALSE;
+     while (j<nl) {
+       if (is_intersection(small[i].left, small[i].right, large[j].left, 
large[j].right)) {
+       found = TRUE;
+       if (! is_subsection(small[i].left, small[i].right, large[j].left, 
large[j].right)) {
+         // found column which is not a subset
+         return( FALSE );
+       }
+       }
+       j++;
+     }
+     if (! found) {
+       return( FALSE );
+     }
+     i++;
+   }
+   // small cannot be an empty set
+   return( ns>0 );
+ }
+ 
+ /*
+  *  right_most_column - returns the right most column position.
+  */
+ 
+ int html_printer::right_most_column (struct text_defn *col)
+ {
+   int i = count_columns(col);
+ 
+   if (i>0) {
+     return( col[i-1].right );
+   } else {
+     return( 0 );
+   }
+ }
+ 
+ /*
+  *  large_enough_gap_for_two - returns TRUE if there exists a large enough gap
+  *                             for two lines.
+  */
+ 
+ int html_printer::large_enough_gap_for_two (struct text_defn *col)
+ {
+   int i=0;
+   int found=FALSE;
+   int r=font::res;
+   int gap=MIN_COLUMN_FOR_TWO_LINES;
+ 
+   if (abs(col[i].left - left_margin_indent) >= gap) {
+     found = TRUE;
+   }
+   while ((col[i].left != 0) && (col[i+1].left != 0)) {
+     if (abs(col[i+1].left-col[i].right) >= gap) {
+       found = TRUE;
+       i++;
+     } else {
+       // not good enough for this table, remove it
+       col[i].right = col[i+1].right;
+       remove_entry_in_line(col, i+1);
+     }
+   }
+   return( found );
+ }
+ 
+ /*
+  *  is_small_table - applies some rigorous rules to test whether we should 
start this
+  *                   table at this point.
+  */
+ 
+ int html_printer::is_small_table (int lines, struct text_defn *last_guess,
+                                 struct text_defn *words_1, struct text_defn 
*cols_1,
+                                 struct text_defn *words_2, struct text_defn 
*cols_2,
+                                 int *limit, int *limit_1)
+ {
+   /*
+    *  firstly we check for an indented paragraph
+    */
+ 
+   if ((lines >= 2) &&
+       (count_columns(cols_1) == count_columns(cols_2)) && 
(count_columns(cols_1) == 1) &&
+       right_indentation(cols_1) && (! right_indentation(cols_2)) &&
+       (cols_1[0].right == right_margin_indent)) {
+     return( FALSE );
+   }
+ 
+   if (lines == 2) {
+     /*
+      *  as we only have two lines in our table we need to examine in detail 
whether
+      *  we should construct a table from these two lines.
+      *  For example if the text is the start of an indented paragraph and
+      *  line1 and line2 are contineous then they should form one row in our 
table but
+      *  if line1 and line2 are not contineous it is safer to treat them 
separately.
+      *
+      *  We are prepared to reduce the table to one line
+      */
+     if (((count_columns(cols_1) != count_columns(cols_2)) && (cols_1[0].left 
> cols_2[0].left)) ||
+       (! ((is_column_subset(cols_1, cols_2)) ||
+           (is_column_subset(cols_2, cols_1))))) {
+       /*
+        *  now we must check to see whether line1 and line2 join
+        */
+       if ((right_most_column(cols_1) == right_margin_indent) &&
+         (cols_2[0].left == left_margin_indent)) {
+       /*
+        *  looks like they join, we don't want a table at all.
+        */
+       return( FALSE );
+       }
+       /*
+        *  use single line table
+        */
+       lines--;
+       *limit = *limit_1;
+       copy_line(last_guess, cols_1);
+     }
+   }
+ 
+   if ((count_columns(last_guess)==1) && (right_indentation(last_guess))) {
+     return( TRUE );
+   }
+ 
+   /*
+    *  check for large gap with single line or if multiple lines with more 
than one column
+    */
+ 
+   if (lines == 1) {
+     if (large_enough_gap(last_guess)) {
+       return( TRUE );
+     }
+   } else if (count_columns(last_guess)>1) {
+     if (lines == 2) {
+       return( large_enough_gap_for_two(last_guess) );
+     }
+     return( TRUE );
+   }
+   return( FALSE );
+ }
+ 
+ 
+ /*
+  *  is_appropriate_to_start_table - returns TRUE if it is appropriate to 
start the table
+  *                                  at this point.
+  */
+ 
+ html_printer::is_appropriate_to_start_table (struct text_defn *cols_1,
+                                            struct text_defn *cols_2,
+                                            struct text_defn *last_guess)
+ {
+   if (count_columns(last_guess) == 1) {
+     if (debug_table_on) {
+       display_columns("", "[is] cols_1"    , cols_1);
+       display_columns("", "[is] cols_2"    , cols_2);
+       display_columns("", "[is] last_guess", last_guess);
+     }
+ 
+     if (! ((is_column_subset(cols_1, cols_2)) ||
+          (is_column_subset(cols_2, cols_1)))) {
+       return( FALSE );
+     }
+     if ((count_columns(cols_1) == 1) &&
+       (cols_1[0].left > left_margin_indent) && (cols_1[0].right < 
right_margin_indent) &&
+       (cols_1[0].right != cols_2[0].right) &&
+       (count_columns(last_guess) == 1)) {
+       return( FALSE );
+     }
+   }
+   return( TRUE );
+ }
+ 
+ /*
+  *  is_a_column - returns TRUE if there exists a column with, percent, width.
+  */
+ 
+ int html_printer::is_a_column (int percent)
+ {
+   int i=0;
+ 
+   while (i<indentation.no_of_columns) {
+     if (indentation.columns[i].percent == percent) {
+       return( TRUE );
+     }
+     i++;
+   }
+   return( FALSE );
+ }
+ 
+ /*
   *  found_use_for_table - checks whether the some words on one line directly 
match
   *                        the horizontal alignment of the line below.
+  *                        This is rather complex as we need to detect text 
tables
+  *                        such as .2C .IP Abstracts and indentations
+  *
+  *                        Algorithm is:
+  *
+  *                        read first line of text and calculate the 
significant
+  *                              gaps between words
+  *                        next next line of text and do the same
+  *                        if a conflict between these lines exists and
+  *                           first line is centered
+  *                        then
+  *                           return centered line
+  *                        elsif start of a table is found
+  *                        then
+  *                           repeat
+  *                              read next line of text and calculate 
significant gaps
+  *                           until conflict between the gaps is found
+  *                           record table
+  *                           return table found
+  *                        else
+  *                           return no table found
+  *                        fi
   */
  
  int html_printer::found_use_for_table (text_glob *start)
  {
    text_glob         *t;
!   struct text_defn   all_words  [MAX_WORDS_PER_LINE];    // logical OR of 
words on each line
!   struct text_defn   words_1    [MAX_WORDS_PER_LINE];    // actual words 
found on first line
!   struct text_defn   words_2    [MAX_WORDS_PER_LINE];    // actual words 
found on second line
!   struct text_defn   cols_1     [MAX_WORDS_PER_LINE];    // columns found on 
line 1
!   struct text_defn   cols_2     [MAX_WORDS_PER_LINE];    // columns found on 
line 2
!   struct text_defn   last_words [MAX_WORDS_PER_LINE];    // actual words 
found on last line
!   struct text_defn   last_cols  [MAX_WORDS_PER_LINE];    // columns found so 
far
!   struct text_defn   next_words [MAX_WORDS_PER_LINE];    // actual words 
found on last line (new)
!   struct text_defn   next_cols  [MAX_WORDS_PER_LINE];    // columns found on 
next line
!   struct text_defn   last_guess [MAX_WORDS_PER_LINE];    // columns found on 
last line
!   //                                                       (logical AND of 
gaps (treat gaps = true))
!   struct text_defn   next_guess [MAX_WORDS_PER_LINE];    // columns found on 
next line
!   //                                                       (logical AND of 
gaps (treat gaps = true))
!   struct text_defn   prev_guess [MAX_WORDS_PER_LINE];    // temporary copy of 
last_guess
    int                i     =0;
!   int                lines =1;                           // number of lines 
read
!   int                mingap=calculate_min_gap(start);    // dependant upon 
point size
!   int                limit;                              // vertical limit 
reached in our table
!   int                limit_1;                            // vertical position 
after line 1
  
  #if 0
!   if (strcmp(start->text_string, "oD") == 0) {
      stop();
    }
  #endif
  
!   /*
!    *  get first set of potential columns into last_line, call this last_guess
!    */
!   limit   = collect_columns(words_1, cols_1, 0, 0, MAX_WORDS_PER_LINE);
!   limit_1 = limit;
!   copy_line(last_guess, cols_1);
! 
!   /*
!    *  initialize the all_words columns - if this should ever equal a complete 
line
!    *  with no gaps then we terminate the table.
!    */
!   copy_line(all_words, cols_1);
! 
!   /*
!    *  and set the current limit found
!    */
    indentation.vertical_limit = limit;
  
+   /*
+    *  have we reached the end of page?
+    */
    if (page_contents->words.is_equal_to_head() || (limit == 0)) {
!     cols_2[0].left  = 0;
!     cols_2[0].right = 0;
    } else {
!     /*
!      *  the answer to the previous question was no.
!      *  So we need to examine the next line
!      */
!     limit = collect_columns(words_2, cols_2, words_1, cols_1, 
MAX_WORDS_PER_LINE);
!     if (limit >= 0) {
!       lines++;
!     }
    }
  
!   /*
!    *  now check to see whether the first line looks like a single centered 
line
!    */
!   if (single_centered_line(cols_1, cols_2, start)) {
      rewind_text_to(start);
      write_centered_line(start);
!     /*
!      *  indicate to caller than we have centered text, not found a table.
!      */
!     indentation.no_of_columns = 0;
      return( TRUE );
    } else if (! table_on) {
+     /*
+      *  user does not allow us to find a table (we are allowed to find 
centered lines (above))
+      */
      rewind_text_to(start);
      return( FALSE );
    }
  
!   /*
!    *  remove any gaps from all_words
!    */
!   combine_line(all_words, cols_2);
    if (debug_table_on) {
!     display_columns(start->text_string, "[1] all_words" , all_words);
!     display_columns(start->text_string, "[1] cols_1"    , cols_1);
!     display_columns(start->text_string, "[1] words_1"   , words_1);
!     display_columns(start->text_string, "[1] cols_2"    , cols_2);
!     display_columns(start->text_string, "[1] words_2"   , words_2);
!     display_columns(start->text_string, "[1] last_guess", last_guess);
    }
  
!   /*
!    *  next_guess = last_guess AND next_cols   (where gap = true)
!    */
! 
!   if (remove_white_using_words(prev_guess, last_guess, cols_2)) {
!   }
!   if (remove_white_using_words(next_guess, prev_guess, all_words)) {
    }
  
+   if (debug_table_on) {
+     display_columns(start->text_string, "[2] next_guess", next_guess);
+   }
+ 
+   copy_line(prev_guess,    cols_1);
+   combine_line(prev_guess, cols_2);
+ 
+   /*
+    *  if no sequence of words crosses a column and
+    *     both the last column and all_words are not a full solid line of text
+    */
    if ((! conflict_with_words(next_guess, all_words)) &&
        (continue_searching_column(next_guess, next_guess, all_words)) &&
+       (is_appropriate_to_start_table(cols_1, cols_2, prev_guess)) &&
        (! page_contents->words.is_equal_to_head()) &&
        ((end_region_vpos < 0) || (limit < end_region_vpos)) &&
        (limit > 0)) {
  
!     /*
!      *  subtract any columns which are bridged by a sequence of words
!      */
! 
!     copy_line(next_cols , cols_2);
!     copy_line(next_words, words_2);
! 
      do {
!       copy_line(prev_guess, next_guess);       // copy next_guess away so we 
can compare it later
        combine_line(last_guess, next_guess);
  
        if (debug_table_on) {
***************
*** 3529,3568 ****
        }
        indentation.vertical_limit = limit;
  
!       copy_line(last_raw, next_line);
        if (page_contents->words.is_equal_to_head()) {
!       next_line[0].left  = 0;
!       next_line[0].right = 0;
        } else {
!       limit = collect_columns(next_line, last_guess, MAX_WORDS_PER_LINE);
        lines++;
        }
! 
!       combine_line(all_words, next_line);
!       if (debug_table_on) {
!       display_columns(t->text_string, "[l] all_words", all_words);
!       display_columns(t->text_string, "[l] last_raw ", last_raw);
!       }
! 
        if (debug_table_on) {
!       display_columns(t->text_string, "[l] next_line", next_line);
        }
        t = page_contents->words.get_data();
  #if 0
        if (strcmp(t->text_string, "market,") == 0) {
        stop();
        }
  #endif
! 
!     } 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()) &&
             ((end_region_vpos <= 0) || (t->minv < end_region_vpos)) &&
             (limit >= 0));
    }
-   lines--;
  
    if (limit < 0) {
      indentation.vertical_limit = limit;
--- 4348,4390 ----
        }
        indentation.vertical_limit = limit;
  
!       copy_line(last_cols,  next_cols);
!       copy_line(last_words, next_words);
        if (page_contents->words.is_equal_to_head()) {
!       /*
!        *  terminate the search
!        */
!       next_cols[0].left  = 0;
!       next_cols[0].right = 0;
        } else {
!       limit = collect_columns(next_words, next_cols, last_words, last_cols, 
MAX_WORDS_PER_LINE);
        lines++;
        }
!       
!       combine_line(all_words, next_cols);
        if (debug_table_on) {
!       display_columns(t->text_string, "[l] all_words" , all_words);
!       display_columns(t->text_string, "[l] last_cols" , last_cols);
!       display_columns(t->text_string, "[l] next_words", next_words);
!       display_columns(t->text_string, "[l] next_cols" , next_cols);
        }
+       
        t = page_contents->words.get_data();
  #if 0
        if (strcmp(t->text_string, "market,") == 0) {
        stop();
        }
  #endif
!       
!     } while ((! remove_white_using_words(next_guess, last_guess, next_cols)) 
&&
             (! conflict_with_words(next_guess, all_words)) &&
             (continue_searching_column(next_guess, last_guess, all_words)) &&
!            ((is_continueous_column(prev_guess, last_cols)) || 
(is_exact_left(last_guess, next_cols))) &&
             (! page_contents->words.is_equal_to_head()) &&
             ((end_region_vpos <= 0) || (t->minv < end_region_vpos)) &&
             (limit >= 0));
+     lines--;
    }
  
    if (limit < 0) {
      indentation.vertical_limit = limit;
***************
*** 3572,3578 ****
      // end of page check whether we should include everything
      if ((! 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)))) {
        // end of page reached - therefore include everything
        page_contents->words.start_from_tail();
        t = page_contents->words.get_data();
--- 4394,4400 ----
      // end of page check whether we should include everything
      if ((! conflict_with_words(next_guess, all_words)) &&
        (continue_searching_column(next_guess, last_guess, all_words)) &&
!       ((is_continueous_column(prev_guess, last_cols)) || 
(is_exact_left(last_guess, next_cols)))) {
        // end of page reached - therefore include everything
        page_contents->words.start_from_tail();
        t = page_contents->words.get_data();
***************
*** 3580,3585 ****
--- 4402,4411 ----
      }
    } else {
      t = page_contents->words.get_data();
+     if (((! conflict_with_words(last_guess, all_words))) &&
+       (t->minv > end_region_vpos) && (end_region_vpos > 0)) {
+       indentation.vertical_limit = limit;
+     }
      if ((end_region_vpos > 0) && (t->minv > end_region_vpos)) {
        indentation.vertical_limit = min(indentation.vertical_limit, 
end_region_vpos+1);
      } else if (indentation.vertical_limit < 0) {
***************
*** 3589,3639 ****
    }
  
    if (debug_table_on) {
!     display_columns(start->text_string, "[x] last_guess", last_guess);
    }
    rewind_text_to(start);
  
    i = count_columns(last_guess);
!   if (((lines > 2) && ((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) {
!       free(indentation.columns);
!     }
!     if (debug_table_on) {
!       display_columns(start->text_string, "[x] last_guess", last_guess);
!     }
!     add_column_gaps(last_guess);
!     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));
  
!     i=0;
!     while (i<indentation.no_of_columns) {
!       indentation.columns[i].left  = last_guess[i].left;
!       indentation.columns[i].right = last_guess[i].right;
!       i++;
      }
-     return( TRUE );
-   } else {
-     return( FALSE );
    }
  }
  
! 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");
  }
  
--- 4415,4486 ----
    }
  
    if (debug_table_on) {
!     display_columns(start->text_string, "[1] all_words" , all_words);
!     display_columns(start->text_string, "[1] cols_1"    , cols_1);
!     display_columns(start->text_string, "[1] words_1"   , words_1);
!     display_columns(start->text_string, "[1] cols_2"    , cols_2);
!     display_columns(start->text_string, "[1] words_2"   , words_2);
!     display_columns(start->text_string, "[1] last_guess", last_guess);
!     display_columns(start->text_string, "[1] next_guess", next_guess);
    }
    rewind_text_to(start);
  
    i = count_columns(last_guess);
!   if ((i>1) || right_indentation(last_guess)) {
!     // was (continue_searching_column(last_guess, last_guess, all_words)))) {
!     if (is_small_table(lines, last_guess, words_1, cols_1, words_2, cols_2,
!                      &indentation.vertical_limit, &limit_1)) {
  
!       // copy match into permenant html_table
! 
!       if (indentation.columns != 0) {
!       free(indentation.columns);
!       }
!       if (debug_table_on) {
!       display_columns(start->text_string, "[x] last_guess", last_guess);
!       }
!       add_column_gaps(last_guess);
!       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));
  
!       i=0;
!       while (i<indentation.no_of_columns) {
!       indentation.columns[i].left  = last_guess[i].left;
!       indentation.columns[i].right = last_guess[i].right;
!       i++;
!       }
! 
!       if (indentation.no_of_columns>0) {
!       assign_used_columns(start);
!       rewind_text_to(start);
!       calculate_percentage_width(start);
! 
!       // clearly a single column 100% is not worth using a table for
!       if (is_a_column(100)) {
!         indentation.no_of_columns = 0;
!         free( indentation.columns );
!         indentation.columns = 0;
!       } else {
!         return( TRUE );
!       }
!       }
      }
    }
+   return( FALSE );
  }
  
! /*
!  *  define_cell - creates a table cell using the percentage width.
!  */
  
! void html_printer::define_cell (int i)
! {
!   html.put_string("<td valign=\"top\" align=\"left\" width=\"");
!   html.put_number(indentation.columns[i].percent);
    html.put_string("%\">\n");
  }
  
***************
*** 3642,3653 ****
   *                        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)) {
--- 4489,4501 ----
   *                        write out html text within this region.
   */
  
! void html_printer::column_display_word (int cell, int vert, int left, int 
right, int next)
  {
    text_glob *g=page_contents->words.get_data();
  
+   supress_sub_sup = TRUE;
    if (left != next) {
!     define_cell(cell);
      begin_paragraph_no_height(left_alignment);
      while ((g != 0) && (g->minv <= vert)) {
        if ((left <= g->minh) && (g->minh<right)) {
***************
*** 3673,3686 ****
        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");
--- 4521,4526 ----
***************
*** 3701,3710 ****
  {
    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");
  }
  
  /*
--- 4541,4550 ----
  {
    int i;
  
!   save_paragraph();  // was end_paragraph();
!   html.put_string("\n<table width=\"100%\" rules=\"none\" frame=\"none\" 
cols=\"");
    html.put_number(indentation.no_of_columns);
!   html.put_string("\" cellspacing=\"0\" cellpadding=\"0\">\n");
  }
  
  /*
***************
*** 3715,3720 ****
--- 4555,4562 ----
  {
    html.put_string("</table>\n");
    indentation.no_of_columns = 0;
+   restore_paragraph();
+   supress_sub_sup = TRUE;
  }
  
  /*
***************
*** 3763,3769 ****
        return( right );  // no words in this column
      } else {
        if (count == 1) {
!       return( rightmost+1 );
        } else {
        return( rightmost );
        }
--- 4605,4611 ----
        return( right );  // no words in this column
      } else {
        if (count == 1) {
!       return( rightmost );    // why do we add 1 gaius ? was +1
        } else {
        return( rightmost );
        }
***************
*** 3809,3814 ****
--- 4651,4671 ----
   *  find_column_index - returns the index to the column in which glob, t, 
exists.
   */
  
+ int html_printer::find_column_index_in_line (text_glob *t, text_defn *line)
+ {
+   int i=0;
+ 
+   while ((line != 0) && ((line[i].left != 0) || (line[i].right != 0)) &&
+        (! ((line[i].left<=t->minh) && (line[i].right>t->minh)))) {
+     i++;
+   }
+   return( i );
+ }
+ 
+ /*
+  *  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;
***************
*** 3831,3838 ****
  {
    text_glob *t;
    int        i;
!   int        vpos, prev, last;
!   int is_gap[MAX_WORDS_PER_LINE];
  
    if (v >= indentation.vertical_limit) {
      return( v+1 );
--- 4688,4695 ----
  {
    text_glob *t;
    int        i;
!   int        vpos, last, prev;
!   text_glob *is_gap[MAX_WORDS_PER_LINE];
  
    if (v >= indentation.vertical_limit) {
      return( v+1 );
***************
*** 3857,3863 ****
      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()) {
--- 4714,4720 ----
      t = page_contents->words.get_data();
      prev = t->minv;
      for (i=0; i<indentation.no_of_columns; i++) {
!       is_gap[i] = t;
      }
  
      if (! page_contents->words.is_equal_to_tail()) {
***************
*** 3875,3887 ****
        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()) &&
--- 4732,4744 ----
        prev = last;
        }
  
!       if ((! is_on_same_line(is_gap[i], vpos)) && (! 
is_on_same_line(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] = t;
        page_contents->words.move_right();
        t = page_contents->words.get_data();
      } while ((! page_contents->words.is_equal_to_head()) &&
***************
*** 3946,3952 ****
      int left, right;
      int limit=-1;
  
-     assign_used_columns(start);
      start_table();
      rewind_text_to(start);
  
--- 4803,4808 ----
***************
*** 3980,3986 ****
          }
        }
  
!       column_display_word(limit, left, right, indentation.columns[i].right);
        i++;
        }
  
--- 4836,4842 ----
          }
        }
  
!       column_display_word(i, limit, left, right, 
indentation.columns[i].right);
        i++;
        }
  
***************
*** 4023,4030 ****
    move_vertical(g, center_alignment);
  
    header.written_header = FALSE;
!   output_vpos = g->minv;
!   output_hpos = g->minh;
    do {
      char *postword=html_position_text(g, left_margin_indent, 
right_margin_indent);
  
--- 4879,4887 ----
    move_vertical(g, center_alignment);
  
    header.written_header = FALSE;
!   supress_sub_sup       = TRUE;
!   output_vpos           = g->minv;
!   output_hpos           = g->minh;
    do {
      char *postword=html_position_text(g, left_margin_indent, 
right_margin_indent);
  
***************
*** 4042,4048 ****
      }    
      page_contents->words.move_right();
      g = page_contents->words.get_data();
!   } while ((! page_contents->words.is_equal_to_head()) && (g->minv == 
current_vpos));
    page_contents->words.move_left();  // so when we move right we land on the 
word following this centered line
    need_one_newline = TRUE;
  }
--- 4899,4905 ----
      }    
      page_contents->words.move_right();
      g = page_contents->words.get_data();
!   } while ((! page_contents->words.is_equal_to_head()) && (is_on_same_line(g, 
current_vpos)));
    page_contents->words.move_left();  // so when we move right we land on the 
word following this centered line
    need_one_newline = TRUE;
  }
***************
*** 4079,4085 ****
      // 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];
!     int                limit = collect_columns(last_guess, 0, 
MAX_WORDS_PER_LINE);
  
      rewind_text_to(g);    
      if ((count_columns(last_guess) == 1) && (is_in_middle(last_guess[0].left, 
last_guess[0].right))) {
--- 4936,4943 ----
      // 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];
!     struct text_defn   last_words[MAX_WORDS_PER_LINE];
!     int                limit = collect_columns(last_words, last_guess, 0, 0, 
MAX_WORDS_PER_LINE);
  
      rewind_text_to(g);    
      if ((count_columns(last_guess) == 1) && (is_in_middle(last_guess[0].left, 
last_guess[0].right))) {
***************
*** 4115,4126 ****
  
  void html_printer::move_vertical (text_glob *g, paragraph_type p)
  {
!   int  r        =font::res;
    int  height   = (g->text_style.point_size+2)*r/72;   // --fixme-- we always 
assume VS is PS+2 (could do better)
    int  temp_vpos;
  
    if (auto_on) {
!     if ((more_than_line_break(output_vpos, g->minv, height)) || (p != 
para_type)) {
        end_paragraph();
        begin_paragraph(p);
      } else {
--- 4973,4984 ----
  
  void html_printer::move_vertical (text_glob *g, paragraph_type p)
  {
!   int  r        = font::res;
    int  height   = (g->text_style.point_size+2)*r/72;   // --fixme-- we always 
assume VS is PS+2 (could do better)
    int  temp_vpos;
  
    if (auto_on) {
!     if ((more_than_line_break(output_vpos, g->minv, height)) || (p != 
current_paragraph->para_type)) {
        end_paragraph();
        begin_paragraph(p);
      } else {
***************
*** 4156,4162 ****
  
  void html_printer::emit_space (text_glob *g, int force_space)
  {
!   if (! need_paragraph) {
      // only generate a space if we have written a word - as html will ignore 
it otherwise
      if ((output_style != g->text_style) && (g->text_style.f != 0)) {
        terminate_current_font();
--- 5014,5020 ----
  
  void html_printer::emit_space (text_glob *g, int force_space)
  {
!   if (! current_paragraph->need_paragraph) {
      // only generate a space if we have written a word - as html will ignore 
it otherwise
      if ((output_style != g->text_style) && (g->text_style.f != 0)) {
        terminate_current_font();
***************
*** 4177,4194 ****
  {
    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) ||
         pretend_is_on_same_line(g, left_margin, right_margin))) {
-     // check whether the font was reset after generating an image
  
      header.written_header = FALSE;
      force_begin_paragraph();
  
--- 5035,5055 ----
  {
    char *postword=0;
  
    begin_paragraph(left_alignment);
  
    if ((! header.written_header) &&
        (is_on_same_line(g, output_vpos) ||
         pretend_is_on_same_line(g, left_margin, right_margin))) {
  
+     /*
+      *  check whether we should supress superscripts and subscripts.
+      *  I guess we might be able to do better by examining text on this line
+      *  --fixme--
+      */
+ 
+     if ((! is_on_same_line(g, output_vpos)) && (pretend_is_on_same_line(g, 
left_margin, right_margin))) {
+       supress_sub_sup = TRUE;
+     }
      header.written_header = FALSE;
      force_begin_paragraph();
  
***************
*** 4197,4202 ****
--- 5058,5064 ----
        emit_space(g, TRUE);
      }
  
+     // check whether the font was reset after generating an image
      if (output_style.f == 0) {
        change_font(g, TRUE);
      }
***************
*** 4220,4225 ****
--- 5082,5088 ----
      } else {
        move_horizontal(g, left_margin);
      }
+     supress_sub_sup = FALSE;
    } else {
      // we have found a new line
      if (! header.written_header) {
***************
*** 4239,4244 ****
--- 5102,5108 ----
        make_html_indent(g->minh-left_margin);
        }
        change_font(g, TRUE);
+       supress_sub_sup = FALSE;
      }
    }
    output_vpos = g->minv;
***************
*** 4263,4280 ****
        } else {
        temp_vpos = output_vpos;
        }
! 
! #if 1
        if (need_one_newline) {
        html_newline();
        temp_vpos += height;
        } else {
        need_one_newline = TRUE;
        }
- #else
-       html_newline();
-       temp_vpos += height;
- #endif
  
        while ((temp_vpos < start_region_vpos) &&
             (more_than_line_break(temp_vpos, start_region_vpos, height))) {
--- 5127,5139 ----
        } else {
        temp_vpos = output_vpos;
        }
!       supress_sub_sup = TRUE;
        if (need_one_newline) {
        html_newline();
        temp_vpos += height;
        } else {
        need_one_newline = TRUE;
        }
  
        while ((temp_vpos < start_region_vpos) &&
             (more_than_line_break(temp_vpos, start_region_vpos, height))) {
***************
*** 4287,4308 ****
      is_center = TRUE;
    } else {
      if (start_region_hpos > left_margin_indent) {
!       html.put_string("<span style=\" text-indent: ");
!       
html.put_float(((double)(start_region_hpos-left_margin_indent)/((double)r)));
!       html.put_string("in;\"></span>");
      }
    }
- #if 0
-    } else {
-       // on the same line
-       if (start_region_hpos > output_hpos) {
-       html.put_string("<span style=\" text-indent: ");
-       html.put_float(((double)(start_region_hpos-output_hpos)/((double)r)));
-       html.put_string("in;\"></span>");
-       }
-     }
-   }
- #endif
    output_vpos = start_region_vpos;
    output_hpos = start_region_hpos;
    return( is_center );
--- 5146,5154 ----
      is_center = TRUE;
    } else {
      if (start_region_hpos > left_margin_indent) {
!       make_html_indent(start_region_hpos-left_margin_indent);
      }
    }
    output_vpos = start_region_vpos;
    output_hpos = start_region_hpos;
    return( is_center );
***************
*** 4380,4386 ****
  void html_printer::html_display_word (text_glob *g)
  {
  #if 0
!   if (strcmp(g->text_string, "increased.") == 0) {
      stop();
    }
  #endif
--- 5226,5232 ----
  void html_printer::html_display_word (text_glob *g)
  {
  #if 0
!   if (strcmp(g->text_string, "ot") == 0) {
      stop();
    }
  #endif
***************
*** 4644,4655 ****
  void html_printer::flush_sbuf()
  {
    if (sbuf_len > 0) {
!     int r=font::res;   // resolution of the device actually
      set_style(sbuf_style);
  
      page_contents->add(&sbuf_style, sbuf, sbuf_len,
                       sbuf_vpos-sbuf_style.point_size*r/72, sbuf_start_hpos,
!                      sbuf_vpos,                            sbuf_end_hpos);
             
      output_hpos = sbuf_end_hpos;
      output_vpos = sbuf_vpos;
--- 5490,5501 ----
  void html_printer::flush_sbuf()
  {
    if (sbuf_len > 0) {
!     int r=font::res;   // resolution of the device
      set_style(sbuf_style);
  
      page_contents->add(&sbuf_style, sbuf, sbuf_len,
                       sbuf_vpos-sbuf_style.point_size*r/72, sbuf_start_hpos,
!                      sbuf_vpos                           , sbuf_end_hpos);
             
      output_hpos = sbuf_end_hpos;
      output_vpos = sbuf_vpos;
***************
*** 5057,5070 ****
        flush_graphic();
        }
      } else if (strncmp(s, "html:", 5) == 0) {
!       int r=font::res;   // resolution of the device actually
  
        page_contents->add_html_command(&sbuf_style, &s[5], strlen(s)-5,
  
        // need to pass rest of string through to html output during flush
  
                                      env->vpos-env->size*r/72, env->hpos,
!                                     env->vpos            , env->hpos);
        // assume that the html command has no width, if it does then we 
hopefully troff
        // will have fudged this in a macro and requested that the formatting 
move right by
        // the appropriate width
--- 5903,5916 ----
        flush_graphic();
        }
      } else if (strncmp(s, "html:", 5) == 0) {
!       int r=font::res;   // resolution of the device
  
        page_contents->add_html_command(&sbuf_style, &s[5], strlen(s)-5,
  
        // need to pass rest of string through to html output during flush
  
                                      env->vpos-env->size*r/72, env->hpos,
!                                     env->vpos               , env->hpos);
        // assume that the html command has no width, if it does then we 
hopefully troff
        // will have fudged this in a macro and requested that the formatting 
move right by
        // the appropriate width



reply via email to

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