/[groff]/groff/src/devices/grohtml/post-html.cpp
ViewVC logotype

Diff of /groff/src/devices/grohtml/post-html.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.9 by wl, Thu Oct 7 11:50:17 2004 UTC revision 1.10 by wl, Tue Oct 12 21:39:31 2004 UTC
# Line 38  Foundation, 59 Temple Place - Suite 330, Line 38  Foundation, 59 Temple Place - Suite 330,
38    
39  #include <stdio.h>  #include <stdio.h>
40  #include <fcntl.h>  #include <fcntl.h>
41    #include <string.h>
42    
43  extern "C" const char *Version_string;  extern "C" const char *Version_string;
44    
# Line 50  extern "C" const char *Version_string; Line 51  extern "C" const char *Version_string;
51    
52  #define MAX_LINE_LENGTH                60            /* maximum characters we want in a line      */  #define MAX_LINE_LENGTH                60            /* maximum characters we want in a line      */
53  #define SIZE_INCREMENT                  2            /* font size increment <big> = +2            */  #define SIZE_INCREMENT                  2            /* font size increment <big> = +2            */
54  #define BASE_POINT_SIZE                10            /* 10 points is the base size ie html size 3 */  #define CENTER_TOLERANCE                2            /* how many pixels off center do we allow    */
 #define CENTER_TOLERANCE                2            /* how many pixels off center will we still  */  
55  #define ANCHOR_TEMPLATE         "heading"            /* if simple anchor is set we use this       */  #define ANCHOR_TEMPLATE         "heading"            /* if simple anchor is set we use this       */
56  #define UNICODE_DESC_START           0x80            /* all character entities above this are     */  #define UNICODE_DESC_START           0x80            /* all character entities above this are     */
57                                                       /* either encoded by their glyph names or if */                                                       /* either encoded by their glyph names or if */
# Line 60  typedef enum {CENTERED, LEFT, RIGHT, INL Line 60  typedef enum {CENTERED, LEFT, RIGHT, INL
60  typedef enum {col_tag, tab_tag, tab0_tag, none} colType;  typedef enum {col_tag, tab_tag, tab0_tag, none} colType;
61    
62  #undef DEBUG_TABLES  #undef DEBUG_TABLES
63    // #define DEBUG_TABLES
64    
65  /*  /*
66   *  prototypes   *  prototypes
# Line 83  static string job_name; Line 83  static string job_name;
83  static int multiple_files = FALSE;                   /* must we the output be divided into       */  static int multiple_files = FALSE;                   /* must we the output be divided into       */
84                                                       /* multiple html files, one for each        */                                                       /* multiple html files, one for each        */
85                                                       /* heading?                                 */                                                       /* heading?                                 */
86    static int base_point_size = 0;                      /* which troff font size maps onto html     */
87                                                         /* size 3?                                  */
88    static string head_info;                             /* user supplied information to be placed   */
89                                                         /* into <head> </head>                      */
90    
91    
92  /*  /*
# Line 114  static int max (int a, int b) Line 118  static int max (int a, int b)
118  static int is_intersection (int a1, int a2, int b1, int b2)  static int is_intersection (int a1, int a2, int b1, int b2)
119  {  {
120    // easier to prove NOT outside limits    // easier to prove NOT outside limits
121    return( ! ((a1 > b2) || (a2 < b1)) );    return ! ((a1 > b2) || (a2 < b1));
122  }  }
123    
124  /*  /*
# Line 123  static int is_intersection (int a1, int Line 127  static int is_intersection (int a1, int
127    
128  static int is_digit (char ch)  static int is_digit (char ch)
129  {  {
130    return( (ch >= '0') && (ch <= '9') );    return (ch >= '0') && (ch <= '9');
131  }  }
132    
133  /*  /*
# Line 145  struct file { Line 149  struct file {
149   */   */
150    
151  file::file (FILE *f)  file::file (FILE *f)
152    : fp(f), next(0), new_output_file(FALSE),    : fp(f), next(NULL), new_output_file(FALSE),
153      require_links(FALSE), output_file_name("")      require_links(FALSE), output_file_name("")
154  {  {
155  }  }
# Line 174  private: Line 178  private:
178   */   */
179    
180  files::files ()  files::files ()
181    : head(0), tail(0), ptr(0)    : head(NULL), tail(NULL), ptr(NULL)
182  {  {
183  }  }
184    
# Line 187  FILE *files::get_file (void) Line 191  FILE *files::get_file (void)
191    if (ptr)    if (ptr)
192      return ptr->fp;      return ptr->fp;
193    else    else
194      return 0;      return NULL;
195  }  }
196    
197  /*  /*
# Line 205  void files::start_of_list (void) Line 209  void files::start_of_list (void)
209    
210  void files::move_next (void)  void files::move_next (void)
211  {  {
212    if (ptr != 0)    if (ptr != NULL)
213      ptr = ptr->next;      ptr = ptr->next;
214  }  }
215    
# Line 215  void files::move_next (void) Line 219  void files::move_next (void)
219    
220  void files::add_new_file (FILE *f)  void files::add_new_file (FILE *f)
221  {  {
222    if (head == 0) {    if (head == NULL) {
223      head = new file(f);      head = new file(f);
224      tail = head;      tail = head;
225    } else {    } else {
# Line 313  struct style { Line 317  struct style {
317  };  };
318    
319  style::style()  style::style()
320    : f(0)    : f(NULL)
321  {  {
322  }  }
323    
# Line 349  struct char_block { Line 353  struct char_block {
353  };  };
354    
355  char_block::char_block()  char_block::char_block()
356  : buffer(NULL), used(0), next(0)  : buffer(NULL), used(0), next(NULL)
357  {  {
358  }  }
359    
360  char_block::char_block(int length)  char_block::char_block(int length)
361  : used(0), next(0)  : used(0), next(NULL)
362  {  {
363    buffer = (char *)malloc(max(length, char_block::SIZE));    buffer = (char *)malloc(max(length, char_block::SIZE));
364    if (buffer == NULL)    if (buffer == NULL)
# Line 379  private: Line 383  private:
383  };  };
384    
385  char_buffer::char_buffer()  char_buffer::char_buffer()
386  : head(0), tail(0)  : head(NULL), tail(NULL)
387  {  {
388  }  }
389    
390  char_buffer::~char_buffer()  char_buffer::~char_buffer()
391  {  {
392    while (head != 0) {    while (head != NULL) {
393      char_block *temp = head;      char_block *temp = head;
394      head = head->next;      head = head->next;
395      delete temp;      delete temp;
# Line 400  char *char_buffer::add_string (const cha Line 404  char *char_buffer::add_string (const cha
404    if (s == NULL || length == 0)    if (s == NULL || length == 0)
405      return NULL;      return NULL;
406    
407    if (tail == 0) {    if (tail == NULL) {
408      tail = new char_block(length+1);      tail = new char_block(length+1);
409      head = tail;      head = tail;
410    } else {    } else {
# Line 466  public: Line 470  public:
470    int  is_in               (void);    int  is_in               (void);
471    int  is_po               (void);    int  is_po               (void);
472    int  is_ti               (void);    int  is_ti               (void);
473      int  is_ll               (void);
474    int  is_ce               (void);    int  is_ce               (void);
475      int  is_tl               (void);
476      int  is_eo_tl            (void);
477    int  is_eol_ce           (void);    int  is_eol_ce           (void);
478    int  is_col              (void);    int  is_col              (void);
479    int  is_tab              (void);    int  is_tab              (void);
# Line 476  public: Line 483  public:
483    int  is_tab_te           (void);    int  is_tab_te           (void);
484    int  is_nf               (void);    int  is_nf               (void);
485    int  is_fi               (void);    int  is_fi               (void);
486      int  is_eo_h             (void);
487    int  get_arg             (void);    int  get_arg             (void);
488    int  get_tab_args        (char *align);    int  get_tab_args        (char *align);
489    
# Line 516  text_glob::text_glob (style *s, const ch Line 524  text_glob::text_glob (style *s, const ch
524  }  }
525    
526  text_glob::text_glob ()  text_glob::text_glob ()
527    : text_string(0), text_length(0), minv(-1), minh(-1), maxv(-1), maxh(-1),    : text_string(NULL), text_length(0), minv(-1), minh(-1), maxv(-1), maxh(-1),
528      is_tag(FALSE), is_special(FALSE), is_line(FALSE), thickness(0), tab(NULL)      is_tag(FALSE), is_special(FALSE), is_line(FALSE), thickness(0), tab(NULL)
529  {  {
530  }  }
# Line 649  int text_glob::is_a_tag (void) Line 657  int text_glob::is_a_tag (void)
657    
658  int text_glob::is_eol (void)  int text_glob::is_eol (void)
659  {  {
660    return( is_tag && (strcmp(text_string, "html-tag:eol") == 0) );    return is_tag && (strcmp(text_string, "html-tag:.eol") == 0);
661  }  }
662    
663  /*  /*
# Line 658  int text_glob::is_eol (void) Line 666  int text_glob::is_eol (void)
666    
667  int text_glob::is_eol_ce (void)  int text_glob::is_eol_ce (void)
668  {  {
669    return( is_tag && (strcmp(text_string, "html-tag:eol.ce") == 0) );    return is_tag && (strcmp(text_string, "html-tag:eol.ce") == 0);
670    }
671    
672    /*
673     *  is_tl - returns TRUE if glob contains the tag .tl
674     */
675    
676    int text_glob::is_tl (void)
677    {
678      return is_tag && (strcmp(text_string, "html-tag:.tl") == 0);
679  }  }
680    
681    /*
682     *  is_eo_tl - returns TRUE if glob contains the tag eo.tl
683     */
684    
685    int text_glob::is_eo_tl (void)
686    {
687      return is_tag && (strcmp(text_string, "html-tag:.eo.tl") == 0);
688    }
689    
690  /*  /*
691   *  is_nf - returns TRUE if glob contains the tag .nf   *  is_nf - returns TRUE if glob contains the tag .fi 0
692   */   */
693    
694  int text_glob::is_nf (void)  int text_glob::is_nf (void)
695  {  {
696    return( is_tag && (strcmp(text_string, "html-tag:.nf") == 0) );    return is_tag && (strncmp(text_string, "html-tag:.fi", 12) == 0) &&
697             (get_arg() == 0);
698  }  }
699    
700  /*  /*
701   *  is_fi - returns TRUE if glob contains the tag .fi   *  is_fi - returns TRUE if glob contains the tag .fi 1
702   */   */
703    
704  int text_glob::is_fi (void)  int text_glob::is_fi (void)
705  {  {
706    return( is_tag && (strcmp(text_string, "html-tag:.fi") == 0) );    return( is_tag && (strncmp(text_string, "html-tag:.fi", 12) == 0) &&
707              (get_arg() == 1) );
708    }
709    
710    /*
711     *  is_eo_h - returns TRUE if glob contains the tag .eo.h
712     */
713    
714    int text_glob::is_eo_h (void)
715    {
716      return is_tag && (strcmp(text_string, "html-tag:.eo.h") == 0);
717  }  }
718    
719  /*  /*
# Line 686  int text_glob::is_fi (void) Line 722  int text_glob::is_fi (void)
722    
723  int text_glob::is_ce (void)  int text_glob::is_ce (void)
724  {  {
725    return( is_tag && (strcmp(text_string, "html-tag:.ce") == 0) );    return is_tag && (strcmp(text_string, "html-tag:.ce") == 0);
726  }  }
727    
728  /*  /*
# Line 695  int text_glob::is_ce (void) Line 731  int text_glob::is_ce (void)
731    
732  int text_glob::is_in (void)  int text_glob::is_in (void)
733  {  {
734    return( is_tag && (strncmp(text_string, "html-tag:.in ", strlen("html-tag:.in ")) == 0) );    return is_tag && (strncmp(text_string, "html-tag:.in ", strlen("html-tag:.in ")) == 0);
735  }  }
736    
737  /*  /*
# Line 704  int text_glob::is_in (void) Line 740  int text_glob::is_in (void)
740    
741  int text_glob::is_po (void)  int text_glob::is_po (void)
742  {  {
743    return( is_tag && (strncmp(text_string, "html-tag:.po ", strlen("html-tag:.po ")) == 0) );    return is_tag && (strncmp(text_string, "html-tag:.po ", strlen("html-tag:.po ")) == 0);
744  }  }
745    
746  /*  /*
# Line 713  int text_glob::is_po (void) Line 749  int text_glob::is_po (void)
749    
750  int text_glob::is_ti (void)  int text_glob::is_ti (void)
751  {  {
752    return( is_tag && (strncmp(text_string, "html-tag:.ti ", strlen("html-tag:.ti ")) == 0) );    return is_tag && (strncmp(text_string, "html-tag:.ti ", strlen("html-tag:.ti ")) == 0);
753    }
754    
755    /*
756     *  is_ll - returns TRUE if glob contains the tag .ll
757     */
758    
759    int text_glob::is_ll (void)
760    {
761      return is_tag && (strncmp(text_string, "html-tag:.ll ", strlen("html-tag:.ll ")) == 0);
762  }  }
763    
764  /*  /*
# Line 722  int text_glob::is_ti (void) Line 767  int text_glob::is_ti (void)
767    
768  int text_glob::is_col (void)  int text_glob::is_col (void)
769  {  {
770    return( is_tag && (strncmp(text_string, "html-tag:.col", strlen("html-tag:.col")) == 0) );    return is_tag && (strncmp(text_string, "html-tag:.col", strlen("html-tag:.col")) == 0);
771  }  }
772    
773  /*  /*
# Line 731  int text_glob::is_col (void) Line 776  int text_glob::is_col (void)
776    
777  int text_glob::is_tab_ts (void)  int text_glob::is_tab_ts (void)
778  {  {
779    return( is_tag && (strcmp(text_string, "html-tag:.tab-ts") == 0) );    return is_tag && (strcmp(text_string, "html-tag:.tab-ts") == 0);
780  }  }
781    
782  /*  /*
# Line 740  int text_glob::is_tab_ts (void) Line 785  int text_glob::is_tab_ts (void)
785    
786  int text_glob::is_tab_te (void)  int text_glob::is_tab_te (void)
787  {  {
788    return( is_tag && (strcmp(text_string, "html-tag:.tab-te") == 0) );    return is_tag && (strcmp(text_string, "html-tag:.tab-te") == 0);
789  }  }
790    
791  /*  /*
# Line 749  int text_glob::is_tab_te (void) Line 794  int text_glob::is_tab_te (void)
794    
795  int text_glob::is_ta (void)  int text_glob::is_ta (void)
796  {  {
797    return( is_tag && (strncmp(text_string, "html-tag:.ta ", strlen("html-tag:.ta ")) == 0) );    return is_tag && (strncmp(text_string, "html-tag:.ta ", strlen("html-tag:.ta ")) == 0);
798  }  }
799    
800  /*  /*
# Line 758  int text_glob::is_ta (void) Line 803  int text_glob::is_ta (void)
803    
804  int text_glob::is_tab (void)  int text_glob::is_tab (void)
805  {  {
806    return( is_tag && (strncmp(text_string, "html-tag:tab ", strlen("html-tag:tab ")) == 0) );    return is_tag && (strncmp(text_string, "html-tag:tab ", strlen("html-tag:tab ")) == 0);
807  }  }
808    
809  /*  /*
# Line 767  int text_glob::is_tab (void) Line 812  int text_glob::is_tab (void)
812    
813  int text_glob::is_tab0 (void)  int text_glob::is_tab0 (void)
814  {  {
815    return( is_tag && (strncmp(text_string, "html-tag:tab0", strlen("html-tag:tab0")) == 0) );    return is_tag && (strncmp(text_string, "html-tag:tab0", strlen("html-tag:tab0")) == 0);
816  }  }
817    
818  /*  /*
# Line 789  int text_glob::is_auto_img (void) Line 834  int text_glob::is_auto_img (void)
834    
835  int text_glob::is_br (void)  int text_glob::is_br (void)
836  {  {
837    return( is_a_tag() && ((strcmp ("html-tag:.br", text_string) == 0) ||    return is_a_tag() && ((strcmp ("html-tag:.br", text_string) == 0) ||
838                           (strncmp("html-tag:.sp", text_string, 11) == 0) ||                          (strncmp("html-tag:.sp", text_string, 11) == 0));
                          (strcmp ("html-tag:.ce", text_string) == 0)) );  
839  }  }
840    
841  int text_glob::get_arg (void)  int text_glob::get_arg (void)
# Line 858  html_table *text_glob::get_table (void) Line 902  html_table *text_glob::get_table (void)
902  }  }
903    
904  /*  /*
905   *  the class and methods used to construct ordered double linked lists.   *  the class and methods used to construct ordered double linked
906   *  In a previous implementation we used templates via #include "ordered-list.h",   *  lists.  In a previous implementation we used templates via
907   *  but this does assume that all C++ compilers can handle this feature. Pragmatically   *  #include "ordered-list.h", but this does assume that all C++
908   *  it is safer to assume this is not the case.   *  compilers can handle this feature. Pragmatically it is safer to
909     *  assume this is not the case.
910   */   */
911    
912  struct element_list {  struct element_list {
# Line 977  int list::is_less (element_list *a, elem Line 1022  int list::is_less (element_list *a, elem
1022  }  }
1023    
1024  /*  /*
1025   *  add - adds a datum to the list in the order specified by the region position.   *  add - adds a datum to the list in the order specified by the
1026     *        region position.
1027   */   */
1028    
1029  void list::add (text_glob *in, int line_number, int min_vertical, int min_horizontal, int max_vertical, int max_horizontal)  void list::add (text_glob *in, int line_number, int min_vertical, int min_horizontal, int max_vertical, int max_horizontal)
# Line 986  void list::add (text_glob *in, int line_ Line 1032  void list::add (text_glob *in, int line_
1032    element_list *t    = new element_list(in, line_number, min_vertical, min_horizontal, max_vertical, max_horizontal);    element_list *t    = new element_list(in, line_number, min_vertical, min_horizontal, max_vertical, max_horizontal);
1033    element_list *last;    element_list *last;
1034    
1035    if (head == 0) {  #if 0
1036      fprintf(stderr, "[%s %d,%d,%d,%d] ",
1037              in->text_string, min_vertical, min_horizontal, max_vertical, max_horizontal);
1038      fflush(stderr);
1039    #endif
1040    
1041      if (head == NULL) {
1042      head     = t;      head     = t;
1043      tail     = t;      tail     = t;
1044      ptr      = t;      ptr      = t;
# Line 995  void list::add (text_glob *in, int line_ Line 1047  void list::add (text_glob *in, int line_
1047    } else {    } else {
1048      last = tail;      last = tail;
1049    
1050      while ((last != head) && (is_less(t, last))) {      while ((last != head) && (is_less(t, last)))
1051        last = last->left;        last = last->left;
     }  
1052    
1053      if (is_less(t, last)) {      if (is_less(t, last)) {
1054        t->right          = last;        t->right          = last;
# Line 1005  void list::add (text_glob *in, int line_ Line 1056  void list::add (text_glob *in, int line_
1056        t->left           = last->left;        t->left           = last->left;
1057        last->left        = t;        last->left        = t;
1058        // now check for a new head        // now check for a new head
1059        if (last == head) {        if (last == head)
1060          head = t;          head = t;
       }  
1061      } else {      } else {
1062        // add t beyond last        // add t beyond last
1063        t->right          = last->right;        t->right          = last->right;
# Line 1015  void list::add (text_glob *in, int line_ Line 1065  void list::add (text_glob *in, int line_
1065        last->right->left = t;        last->right->left = t;
1066        last->right       = t;        last->right       = t;
1067        // now check for a new tail        // now check for a new tail
1068        if (last == tail) {        if (last == tail)
1069          tail = t;          tail = t;
       }  
1070      }      }
1071    }    }
1072  }  }
# Line 1032  void list::sub_move_right (void) Line 1081  void list::sub_move_right (void)
1081    element_list *t=ptr->right;    element_list *t=ptr->right;
1082    
1083    if (head == tail) {    if (head == tail) {
1084      head = 0;      head = NULL;
1085      if (tail != 0) {      if (tail != NULL)
1086        delete tail;        delete tail;
1087      }      
1088      tail = 0;      tail = NULL;
1089      ptr  = 0;      ptr  = NULL;
1090    } else {    } else {
1091      if (head == ptr) {      if (head == ptr)
1092        head = head->right;        head = head->right;
1093      }      if (tail == ptr)
     if (tail == ptr) {  
1094        tail = tail->left;        tail = tail->left;
     }  
1095      ptr->left->right = ptr->right;      ptr->left->right = ptr->right;
1096      ptr->right->left = ptr->left;      ptr->right->left = ptr->left;
1097      ptr=t;      ptr = t;
1098    }    }
1099  }  }
1100    
# Line 1075  void list::start_from_tail (void) Line 1122  void list::start_from_tail (void)
1122    
1123  int list::is_empty (void)  int list::is_empty (void)
1124  {  {
1125    return( head == 0 );    return head == NULL;
1126  }  }
1127    
1128  /*  /*
# Line 1084  int list::is_empty (void) Line 1131  int list::is_empty (void)
1131    
1132  int list::is_equal_to_tail (void)  int list::is_equal_to_tail (void)
1133  {  {
1134    return( ptr == tail );    return ptr == tail;
1135  }  }
1136    
1137  /*  /*
# Line 1093  int list::is_equal_to_tail (void) Line 1140  int list::is_equal_to_tail (void)
1140    
1141  int list::is_equal_to_head (void)  int list::is_equal_to_head (void)
1142  {  {
1143    return( ptr == head );    return ptr == head;
1144  }  }
1145    
1146  /*  /*
# Line 1120  void list::move_right (void) Line 1167  void list::move_right (void)
1167    
1168  text_glob* list::get_data (void)  text_glob* list::get_data (void)
1169  {  {
1170    return( ptr->datum );    return ptr->datum;
1171  }  }
1172    
1173  /*  /*
# Line 1131  text_glob* list::get_data (void) Line 1178  text_glob* list::get_data (void)
1178  text_glob* list::move_right_get_data (void)  text_glob* list::move_right_get_data (void)
1179  {  {
1180    ptr = ptr->right;    ptr = ptr->right;
1181    if (ptr == head) {    if (ptr == head)
1182      return( 0 );      return NULL;
1183    } else {    else
1184      return( ptr->datum );      return ptr->datum;
   }  
1185  }  }
1186    
1187  /*  /*
# Line 1146  text_glob* list::move_right_get_data (vo Line 1192  text_glob* list::move_right_get_data (vo
1192  text_glob* list::move_left_get_data (void)  text_glob* list::move_left_get_data (void)
1193  {  {
1194    ptr = ptr->left;    ptr = ptr->left;
1195    if (ptr == tail) {    if (ptr == tail)
1196      return( 0 );      return NULL;
1197    } else {    else
1198      return( ptr->datum );      return ptr->datum;
   }  
1199  }  }
1200    
1201  /*  /*
# Line 1162  void list::insert (text_glob *in) Line 1207  void list::insert (text_glob *in)
1207    if (is_empty())    if (is_empty())
1208      fatal("list must not be empty if we are inserting data");      fatal("list must not be empty if we are inserting data");
1209    else {    else {
1210      if (ptr == 0)      if (ptr == NULL)
1211        ptr = head;        ptr = head;
1212            
1213      element_list *t = new element_list(in, ptr->lineno, ptr->minv, ptr->minh, ptr->maxv, ptr->maxh);      element_list *t = new element_list(in, ptr->lineno, ptr->minv, ptr->minh, ptr->maxv, ptr->maxh);
# Line 1205  public: Line 1250  public:
1250    void                        add_and_encode  (style *s, const string &str,    void                        add_and_encode  (style *s, const string &str,
1251                                                 int line_number,                                                 int line_number,
1252                                                 int min_vertical, int min_horizontal,                                                 int min_vertical, int min_horizontal,
1253                                                 int max_vertical, int max_horizontal);                                                 int max_vertical, int max_horizontal,
1254                                                   int is_tag);
1255    void                        add_line        (style *s,    void                        add_line        (style *s,
1256                                                 int line_number,                                                 int line_number,
1257                                                 int x1, int y1, int x2, int y2,                                                 int x1, int y1, int x2, int y2,
# Line 1327  static char *to_unicode (unsigned int ch Line 1373  static char *to_unicode (unsigned int ch
1373  void page::add_and_encode (style *s, const string &str,  void page::add_and_encode (style *s, const string &str,
1374                             int line_number,                             int line_number,
1375                             int min_vertical, int min_horizontal,                             int min_vertical, int min_horizontal,
1376                             int max_vertical, int max_horizontal)                             int max_vertical, int max_horizontal,
1377                               int is_tag)
1378  {  {
1379    string html_string;    string html_string;
1380    char *html_glyph;    char *html_glyph;
# Line 1366  void page::add_and_encode (style *s, con Line 1413  void page::add_and_encode (style *s, con
1413    }    }
1414    if (html_string.length() > 0) {    if (html_string.length() > 0) {
1415      text_glob *g=new text_glob();      text_glob *g=new text_glob();
1416      g->text_glob_special(s, buffer.add_string(html_string), html_string.length(),      if (is_tag)
1417                           min_vertical, min_horizontal, max_vertical, max_horizontal);        g->text_glob_tag(s, buffer.add_string(html_string),
1418      glyphs.add(g, line_number, min_vertical, min_horizontal, max_vertical, max_horizontal);                         html_string.length(),
1419                           min_vertical, min_horizontal,
1420                           max_vertical, max_horizontal);
1421        else
1422          g->text_glob_special(s, buffer.add_string(html_string),
1423                               html_string.length(),
1424                               min_vertical, min_horizontal,
1425                               max_vertical, max_horizontal);
1426        glyphs.add(g, line_number, min_vertical,
1427                   min_horizontal, max_vertical, max_horizontal);
1428    }    }
1429  }  }
1430    
# Line 1532  void header_desc::write_headings (FILE * Line 1588  void header_desc::write_headings (FILE *
1588    }    }
1589  }  }
1590    
1591    struct assert_pos {
1592      assert_pos *next;
1593      const char *val;
1594      const char *id;
1595    };
1596    
1597    class assert_state {
1598    public:
1599            assert_state ();
1600            ~assert_state ();
1601    
1602      void  addx (const char *c, const char *i, const char *v,
1603                  const char *f, const char *l);
1604      void  addy (const char *c, const char *i, const char *v,
1605                  const char *f, const char *l);
1606      void  build(const char *c, const char *v,
1607                  const char *f, const char *l);
1608      void  check_br (int br);
1609      void  check_ce (int ce);
1610      void  check_fi (int fi);
1611      void  check_sp (int sp);
1612      void  reset    (void);
1613    
1614    private:
1615      int check_br_flag;
1616      int check_ce_flag;
1617      int check_fi_flag;
1618      int check_sp_flag;
1619      const char *val_br;
1620      const char *val_ce;
1621      const char *val_fi;
1622      const char *val_sp;
1623      const char *file_br;
1624      const char *file_ce;
1625      const char *file_fi;
1626      const char *file_sp;
1627      const char *line_br;
1628      const char *line_ce;
1629      const char *line_fi;
1630      const char *line_sp;
1631    
1632      assert_pos *xhead;
1633      assert_pos *yhead;
1634    
1635      void add (assert_pos **h,
1636                const char *c, const char *i, const char *v,
1637                const char *f, const char *l);
1638      void compare(assert_pos *t,
1639                   const char *v, const char *f, const char *l);
1640      void close (const char *c);
1641      void set (const char *c, const char *v,
1642                const char *f, const char *l);
1643      void check_value (const char *s, int v, const char *name,
1644                        const char *f, const char *l, int *flag);
1645      int check_value_error (int c, int v, const char *s,
1646                             const char *name,
1647                             const char *f, const char *l, int flag);
1648    };
1649    
1650    assert_state::assert_state ()
1651    {
1652      reset();
1653      val_br   = NULL;
1654      val_ce   = NULL;
1655      val_fi   = NULL;
1656      val_sp   = NULL;
1657      file_br  = NULL;
1658      file_ce  = NULL;
1659      file_fi  = NULL;
1660      file_sp  = NULL;
1661      line_br  = NULL;
1662      line_ce  = NULL;
1663      line_fi  = NULL;
1664      line_sp  = NULL;
1665      xhead    = NULL;
1666      yhead    = NULL;
1667    }
1668    
1669    assert_state::~assert_state ()
1670    {
1671      assert_pos *t;
1672    
1673      while (xhead != NULL) {
1674        t = xhead;
1675        xhead = xhead->next;
1676        free((void *)t->val);
1677        free((void *)t->id);
1678        free(t);
1679      }
1680      while (yhead != NULL) {
1681        t = yhead;
1682        yhead = yhead->next;
1683        free((void *)t->val);
1684        free((void *)t->id);
1685        free(t);
1686      }
1687    }
1688    
1689    void assert_state::reset (void)
1690    {
1691      check_br_flag = 0;
1692      check_ce_flag = 0;
1693      check_fi_flag = 0;
1694      check_sp_flag = 0;
1695    }
1696    
1697    void assert_state::add (assert_pos **h,
1698                            const char *c, const char *i, const char *v,
1699                            const char *f, const char *l)
1700    {
1701      assert_pos *t = *h;
1702    
1703      while (t != NULL) {
1704        if (strcmp(t->id, i) == 0)
1705          break;
1706        t = t->next;
1707      }
1708      if (t != NULL && v != NULL && (v[0] != '='))
1709        compare(t, v, f, l);
1710      else {
1711        if (t == NULL) {
1712          t = (assert_pos *)malloc(sizeof(struct assert_pos));
1713          t->next = *h;
1714          (*h) = t;
1715        }
1716        if (v == NULL || v[0] != '=') {
1717          if (f == NULL)
1718            f = "stdin";
1719          if (l == NULL)
1720            l = "<none>";
1721          if (v == NULL)
1722            v = "no value at all";
1723          fprintf(stderr, "%s:%s:error in assert format of id=%s expecting value to be prefixed with an `=' got %s\n",
1724                  f, l, i, v);
1725        }
1726        t->id = i;
1727        t->val = v;
1728        free((void *)c);
1729        free((void *)f);
1730        free((void *)l);
1731      }
1732    }
1733    
1734    void assert_state::addx (const char *c, const char *i, const char *v,
1735                             const char *f, const char *l)
1736    {
1737      add(&xhead, c, i, v, f, l);
1738    }
1739    
1740    void assert_state::addy (const char *c, const char *i, const char *v,
1741                             const char *f, const char *l)
1742    {
1743      add(&yhead, c, i, v, f, l);
1744    }
1745    
1746    void assert_state::compare(assert_pos *t,
1747                               const char *v, const char *f, const char *l)
1748    {
1749      const char *s=t->val;
1750    
1751      while ((*v) == '=')
1752        v++;
1753      while ((*s) == '=')
1754        s++;
1755      
1756      if (strcmp(v, s) != 0) {
1757        if (f == NULL)
1758          f = "stdin";
1759        if (l == NULL)
1760          l = "<none>";
1761        fprintf(stderr, "%s:%s: grohtml assertion failed at id%s expecting %s and was given %s\n",
1762                f, l, t->id, s, v);
1763      }
1764    }
1765    
1766    void assert_state::close (const char *c)
1767    {
1768      if (strcmp(c, "sp") == 0)
1769        check_sp_flag = 0;
1770      else if (strcmp(c, "br") == 0)
1771        check_br_flag = 0;
1772      else if (strcmp(c, "fi") == 0)
1773        check_fi_flag = 0;
1774      else if (strcmp(c, "nf") == 0)
1775        check_fi_flag = 0;
1776      else if (strcmp(c, "ce") == 0)
1777        check_ce_flag = 0;
1778      else
1779        fprintf(stderr, "internal error: unrecognised tag in grohtml (%s)\n", c);
1780    }
1781    
1782    const char *replace_negate_str (const char *before, char *after)
1783    {
1784      if (before != NULL)
1785        free((void *)before);
1786    
1787      if (strlen(after) > 0) {
1788        int d = atoi(after);
1789    
1790        if (d < 0 || d > 1) {
1791          fprintf(stderr, "expecting nf/fi value to be 0 or 1 not %d\n", d);
1792          d = 0;
1793        }
1794        if (d == 0)
1795          after[0] = '1';
1796        else
1797          after[0] = '0';
1798        after[1] = (char)0;
1799      }
1800      return after;
1801    }
1802    
1803    const char *replace_str (const char *before, const char *after)
1804    {
1805      if (before != NULL)
1806        free((void *)before);
1807      return after;
1808    }
1809    
1810    void assert_state::set (const char *c, const char *v,
1811                            const char *f, const char *l)
1812    {
1813      if (l == NULL)
1814        l = "<none>";
1815      if (f == NULL)
1816        f = "stdin";
1817    
1818      // fprintf(stderr, "%s:%s:setting %s to %s\n", f, l, c, v);
1819      if (strcmp(c, "sp") == 0) {
1820        check_sp_flag = 1;
1821        val_sp = replace_str(val_sp, strdup(v));
1822        file_sp = replace_str(file_sp, strdup(f));
1823        line_sp = replace_str(line_sp, strdup(l));
1824      } else if (strcmp(c, "br") == 0) {
1825        check_br_flag = 1;
1826        val_br = replace_str(val_br, strdup(v));
1827        file_br = replace_str(file_br, strdup(f));
1828        line_br = replace_str(line_br, strdup(l));
1829      } else if (strcmp(c, "fi") == 0) {
1830        check_fi_flag = 1;
1831        val_fi = replace_str(val_fi, strdup(v));
1832        file_fi = replace_str(file_fi, strdup(f));
1833        line_fi = replace_str(line_fi, strdup(l));
1834      } else if (strcmp(c, "nf") == 0) {
1835        check_fi_flag = 1;
1836        val_fi = replace_negate_str(val_fi, strdup(v));
1837        file_fi = replace_str(file_fi, strdup(f));
1838        line_fi = replace_str(line_fi, strdup(l));
1839      } else if (strcmp(c, "ce") == 0) {
1840        check_ce_flag = 1;
1841        val_ce = replace_str(val_ce, strdup(v));
1842        file_ce = replace_str(file_ce, strdup(f));
1843        line_ce = replace_str(line_ce, strdup(l));
1844      }
1845    }
1846    
1847    /*
1848     *  build - builds the troff state assertion.
1849     *          see tmac/www.tmac for cmd examples.
1850     */
1851    
1852    void assert_state::build (const char *c, const char *v,
1853                              const char *f, const char *l)
1854    {
1855      if (c[0] == '{')
1856        set(&c[1], v, f, l);
1857      if (c[0] == '}')
1858        close(&c[1]);
1859    }
1860    
1861    int assert_state::check_value_error (int c, int v, const char *s,
1862                                         const char *name,
1863                                         const char *f, const char *l, int flag)
1864    {
1865      if (! c) {
1866        if (f == NULL)
1867          f = "stdin";
1868        if (l == NULL)
1869          l = "<none>";
1870        fprintf(stderr, "%s:%s:grohtml (troff state) assertion failed, expected %s to be %s but found it to contain %d\n",
1871                f, l, name, s, v);
1872        return 0;
1873      }
1874      return flag;
1875    }
1876    
1877    void assert_state::check_value (const char *s, int v, const char *name,
1878                                    const char *f, const char *l, int *flag)
1879    {
1880      if (strncmp(s, "<=", 2) == 0)
1881        *flag = check_value_error(v <= atoi(&s[2]), v, s, name, f, l, *flag);
1882      else if (strncmp(s, ">=", 2) == 0)
1883        *flag = check_value_error(v >= atoi(&s[2]), v, s, name, f, l, *flag);
1884      else if (strncmp(s, "==", 2) == 0)
1885        *flag = check_value_error(v == atoi(&s[2]), v, s, name, f, l, *flag);
1886      else if (strncmp(s, "!=", 2) == 0)
1887        *flag = check_value_error(v != atoi(&s[2]), v, s, name, f, l, *flag);
1888      else if (strncmp(s, "<", 1) == 0)
1889        *flag = check_value_error(v < atoi(&s[2]), v, s, name, f, l, *flag);
1890      else if (strncmp(s, ">", 1) == 0)
1891        *flag = check_value_error(v > atoi(&s[2]), v, s, name, f, l, *flag);
1892      else if (strncmp(s, "=", 1) == 0)
1893        *flag = check_value_error(v == atoi(&s[1]), v, s, name, f, l, *flag);
1894      else
1895        *flag = check_value_error(v == atoi(s), v, s, name, f, l, *flag);
1896    }
1897    
1898    void assert_state::check_sp (int sp)
1899    {
1900      if (check_sp_flag)
1901        check_value(val_sp, sp, "sp", file_sp, line_sp, &check_sp_flag);
1902    }
1903    
1904    void assert_state::check_fi (int fi)
1905    {
1906      if (check_fi_flag)
1907        check_value(val_fi, fi, "fi", file_fi, line_fi, &check_fi_flag);
1908    }
1909    
1910    void assert_state::check_br (int br)
1911    {
1912      if (check_br_flag)
1913        check_value(val_br, br, "br", file_br, line_br, &check_br_flag);
1914    }
1915    
1916    void assert_state::check_ce (int ce)
1917    {
1918      if (check_ce_flag)
1919        check_value(val_ce, ce, "ce", file_ce, line_ce, &check_ce_flag);
1920    }
1921    
1922  class html_printer : public printer {  class html_printer : public printer {
1923    files                file_list;    files                file_list;
1924    simple_output        html;    simple_output        html;
# Line 1575  class html_printer : public printer { Line 1962  class html_printer : public printer {
1962    int                  max_linelength;    int                  max_linelength;
1963    int                  linelength;    int                  linelength;
1964    int                  pageoffset;    int                  pageoffset;
1965    int                  indentation;    int                  troff_indent;
1966    int                  prev_indent;    int                  device_indent;
1967      int                  temp_indent;
1968    int                  pointsize;    int                  pointsize;
1969    int                  vertical_spacing;    int                  vertical_spacing;
1970    int                  line_number;    int                  line_number;
1971    color               *background;    color               *background;
1972      int                  seen_indent;
1973      int                  next_indent;
1974      int                  seen_pageoffset;
1975      int                  next_pageoffset;
1976      int                  seen_linelength;
1977      int                  next_linelength;
1978      int                  seen_center;
1979      int                  next_center;
1980      int                  seen_space;
1981      int                  seen_break;
1982      assert_state         as;
1983    
1984    void  flush_sbuf                    ();    void  flush_sbuf                    ();
1985    void  set_style                     (const style &);    void  set_style                     (const style &);
# Line 1610  class html_printer : public printer { Line 2009  class html_printer : public printer {
2009    void  start_size                    (int from, int to);    void  start_size                    (int from, int to);
2010    void  do_font                       (text_glob *g);    void  do_font                       (text_glob *g);
2011    void  do_center                     (char *arg);    void  do_center                     (char *arg);
2012      void  do_check_center               (void);
2013    void  do_break                      (void);    void  do_break                      (void);
2014      void  do_space                      (char *arg);
2015    void  do_eol                        (void);    void  do_eol                        (void);
2016    void  do_eol_ce                     (void);    void  do_eol_ce                     (void);
2017    void  do_title                      (void);    void  do_title                      (void);
2018    void  do_fill                       (int on);    void  do_fill                       (char *arg);
2019    void  do_heading                    (char *arg);    void  do_heading                    (char *arg);
2020    void  write_header                  (void);    void  write_header                  (void);
2021    void  determine_header_level        (int level);    void  determine_header_level        (int level);
# Line 1632  class html_printer : public printer { Line 2033  class html_printer : public printer {
2033    void  do_links                      (void);    void  do_links                      (void);
2034    void  do_flush                      (void);    void  do_flush                      (void);
2035    void  do_job_name                   (char *name);    void  do_job_name                   (char *name);
2036      void  do_head                       (char *name);
2037    void  insert_split_file             (void);    void  insert_split_file             (void);
2038    int   is_in_middle                  (int left, int right);    int   is_in_middle                  (int left, int right);
2039    void  do_sup_or_sub                 (text_glob *g);    void  do_sup_or_sub                 (text_glob *g);
# Line 1667  class html_printer : public printer { Line 2069  class html_printer : public printer {
2069    void write_navigation               (const string &top, const string &prev,    void write_navigation               (const string &top, const string &prev,
2070                                         const string &next, const string &current);                                         const string &next, const string &current);
2071    void emit_link                      (const string &to, const char *name);    void emit_link                      (const string &to, const char *name);
2072      int  get_troff_indent               (void);
2073      void restore_troff_indent           (void);
2074      void handle_assertion               (int minv, int minh, int maxv, int maxh, const char *s);
2075      void handle_state_assertion         (text_glob *g);
2076      void do_end_para                    (text_glob *g);
2077    // ADD HERE    // ADD HERE
2078    
2079  public:  public:
# Line 1674  public: Line 2081  public:
2081    ~html_printer         ();    ~html_printer         ();
2082    void set_char         (int i, font *f, const environment *env, int w, const char *name);    void set_char         (int i, font *f, const environment *env, int w, const char *name);
2083    void set_numbered_char(int num, const environment *env, int *widthp);    void set_numbered_char(int num, const environment *env, int *widthp);
2084      int set_char_and_width(const char *nm, const environment *env,
2085                             int *widthp, font **f);
2086    void draw             (int code, int *p, int np, const environment *env);    void draw             (int code, int *p, int np, const environment *env);
2087    void begin_page       (int);    void begin_page       (int);
2088    void end_page         (int);    void end_page         (int);
# Line 1744  void html_printer::emit_line (text_glob Line 2153  void html_printer::emit_line (text_glob
2153  }  }
2154    
2155  /*  /*
2156     *  restore_troff_indent - is called when we have temporarily shutdown
2157     *                         indentation (typically done when we have
2158     *                         centered an image).
2159     */
2160    
2161    void html_printer::restore_troff_indent (void)
2162    {
2163      troff_indent = next_indent;
2164      if (troff_indent > 0) {
2165        /*
2166         *  force device indentation
2167         */
2168        device_indent = 0;
2169        do_indent(get_troff_indent(), pageoffset, linelength);
2170      }
2171    }
2172    
2173    /*
2174   *  emit_raw - writes the raw html information directly to the device.   *  emit_raw - writes the raw html information directly to the device.
2175   */   */
2176    
# Line 1755  void html_printer::emit_raw (text_glob * Line 2182  void html_printer::emit_raw (text_glob *
2182      current_paragraph->do_emittext(g->text_string, g->text_length);      current_paragraph->do_emittext(g->text_string, g->text_length);
2183    } else {    } else {
2184      current_paragraph->done_para();      current_paragraph->done_para();
2185        shutdown_table();
2186      switch (next_tag) {      switch (next_tag) {
2187    
2188      case CENTERED:      case CENTERED:
2189        current_paragraph->do_para("align=center");        current_paragraph->do_para("align=center");
2190        break;        break;
2191      case LEFT:      case LEFT:
2192        current_paragraph->do_para(&html, "align=left", indentation, pageoffset, linelength);        current_paragraph->do_para(&html, "align=left", get_troff_indent(), pageoffset, linelength);
2193        break;        break;
2194      case RIGHT:      case RIGHT:
2195        current_paragraph->do_para(&html, "align=right", indentation, pageoffset, linelength);        current_paragraph->do_para(&html, "align=right", get_troff_indent(), pageoffset, linelength);
2196        break;        break;
2197      default:      default:
2198        fatal("unknown enumeration");        fatal("unknown enumeration");
# Line 1773  void html_printer::emit_raw (text_glob * Line 2201  void html_printer::emit_raw (text_glob *
2201      current_paragraph->done_para();      current_paragraph->done_para();
2202      next_tag        = INLINE;      next_tag        = INLINE;
2203      supress_sub_sup = TRUE;      supress_sub_sup = TRUE;
2204      if (indentation > 0) {      restore_troff_indent();
       /*  
        *  restore indentation  
        */  
       int newin = indentation;  
       indentation = 0;  
       do_indent(newin, pageoffset, linelength);  
     }  
2205    }    }
2206  }  }
2207    
# Line 1790  void html_printer::emit_raw (text_glob * Line 2211  void html_printer::emit_raw (text_glob *
2211    
2212  void html_printer::do_center (char *arg)  void html_printer::do_center (char *arg)
2213  {  {
2214    int n = atoi(arg);    next_center = atoi(arg);
2215    current_paragraph->do_break();    seen_center = TRUE;
   
   if (n > 0) {  
     current_paragraph->done_para();  
     supress_sub_sup = TRUE;  
     current_paragraph->do_para("align=center");  
     end_center += n;  
   } else {  
     end_center = 0;  
     current_paragraph->remove_para_align();  
   }  
2216  }  }
2217    
2218  /*  /*
# Line 1912  void html_printer::do_title (void) Line 2323  void html_printer::do_title (void)
2323  {  {
2324    text_glob    *t;    text_glob    *t;
2325    int           removed_from_head;    int           removed_from_head;
   int           eol_ce = 0;  
2326    
2327    if (page_number == 1) {    if (page_number == 1) {
2328      int found_title_start  = FALSE;      int found_title_start  = FALSE;
# Line 1934  void html_printer::do_title (void) Line 2344  void html_printer::do_title (void)
2344            page_contents->glyphs.sub_move_right();         /* move onto next word */            page_contents->glyphs.sub_move_right();         /* move onto next word */
2345            removed_from_head = ((!page_contents->glyphs.is_empty()) &&            removed_from_head = ((!page_contents->glyphs.is_empty()) &&
2346                                 (page_contents->glyphs.is_equal_to_head()));                                 (page_contents->glyphs.is_equal_to_head()));
2347          } else if (t->is_eol_ce()) {          } else if (t->is_eo_tl()) {
           /*  process the eol associated with .ce  
            */  
           eol_ce++;  
           page_contents->glyphs.sub_move_right();         /* move onto next word */  
         } else if (t->is_eol()) {  
2348            /* end of title found            /* end of title found
2349             */             */
2350            title.has_been_found = TRUE;            title.has_been_found = TRUE;
           outstanding_eol(eol_ce);  
2351            return;            return;
2352          } else if (t->is_a_tag()) {          } else if (t->is_a_tag()) {
2353            /* end of title found, but move back so that we read this tag and process it            page_contents->glyphs.sub_move_right();         /* move onto next word */
2354             */            removed_from_head = ((!page_contents->glyphs.is_empty()) &&
2355            page_contents->glyphs.move_left();           /* move backwards to last word */                                 (page_contents->glyphs.is_equal_to_head()));
           title.has_been_found = TRUE;  
           outstanding_eol(eol_ce);  
           return;  
2356          } else if (found_title_start) {          } else if (found_title_start) {
2357            title.text += " " + string(t->text_string, t->text_length);            title.text += " " + string(t->text_string, t->text_length);
2358            page_contents->glyphs.sub_move_right();         /* move onto next word */            page_contents->glyphs.sub_move_right();         /* move onto next word */
# Line 1967  void html_printer::do_title (void) Line 2368  void html_printer::do_title (void)
2368          }          }
2369        } while ((! page_contents->glyphs.is_equal_to_head()) || (removed_from_head));        } while ((! page_contents->glyphs.is_equal_to_head()) || (removed_from_head));
2370      }      }
     outstanding_eol(eol_ce);  
2371    }    }
2372  }  }
2373    
# Line 2001  void html_printer::write_header (void) Line 2401  void html_printer::write_header (void)
2401    
2402        // lastly we generate a tag        // lastly we generate a tag
2403    
2404        html.nl().put_string("<a name=\"");        html.nl().nl().put_string("<a name=\"");
2405        if (simple_anchors) {        if (simple_anchors) {
2406          string buffer(ANCHOR_TEMPLATE);          string buffer(ANCHOR_TEMPLATE);
2407    
# Line 2057  void html_printer::write_header (void) Line 2457  void html_printer::write_header (void)
2457                                 header.no_of_headings, header.no_of_headings,                                 header.no_of_headings, header.no_of_headings,
2458                                 header.no_of_headings, header.no_of_headings);                                 header.no_of_headings, header.no_of_headings);
2459    
2460      current_paragraph->do_para(&html, "", indentation, pageoffset, linelength);      current_paragraph->do_para(&html, "", get_troff_indent(), pageoffset, linelength);
2461    }    }
2462  }  }
2463    
# Line 2107  void html_printer::do_heading (char *arg Line 2507  void html_printer::do_heading (char *arg
2507            l = g;            l = g;
2508            header.header_buffer += img;            header.header_buffer += img;
2509          }          }
2510        } else if (! (g->is_a_line() || g->is_a_tag())) {        }
2511          else if (g->is_in() || g->is_ti() || g->is_po() || g->is_ce() || g->is_ll())
2512            troff_tag(g);
2513          else if (g->is_fi())
2514            fill_on = 1;
2515          else if (g->is_nf())
2516            fill_on = 0;
2517          else if (! (g->is_a_line() || g->is_a_tag())) {
2518          /*          /*
2519           *  we ignore tag commands when constructing a heading           *  we ignore the other tag commands when constructing a heading
2520           */           */
2521          if (l != 0)          if (l != 0)
2522            header.header_buffer += " ";            header.header_buffer += " ";
# Line 2120  void html_printer::do_heading (char *arg Line 2527  void html_printer::do_heading (char *arg
2527        page_contents->glyphs.move_right();        page_contents->glyphs.move_right();
2528        g = page_contents->glyphs.get_data();        g = page_contents->glyphs.get_data();
2529      } while ((! page_contents->glyphs.is_equal_to_head()) &&      } while ((! page_contents->glyphs.is_equal_to_head()) &&
2530               (! g->is_br()));               (! g->is_eo_h()));
2531    }    }
2532    
2533    determine_header_level(level);    determine_header_level(level);
# Line 2170  void html_printer::do_linelength (char * Line 2577  void html_printer::do_linelength (char *
2577    if (max_linelength == -1)    if (max_linelength == -1)
2578      max_linelength = atoi(arg);      max_linelength = atoi(arg);
2579    
2580    if (fill_on)    next_linelength = atoi(arg);
2581      do_indent(indentation, pageoffset, atoi(arg));    seen_linelength = TRUE;
2582  }  }
2583    
2584  /*  /*
# Line 2180  void html_printer::do_linelength (char * Line 2587  void html_printer::do_linelength (char *
2587    
2588  void html_printer::do_pageoffset (char *arg)  void html_printer::do_pageoffset (char *arg)
2589  {  {
2590    if (fill_on)    next_pageoffset = atoi(arg);
2591      do_indent(indentation, atoi(arg), linelength);    seen_pageoffset = TRUE;
2592    }
2593    
2594    /*
2595     *  get_troff_indent - returns the indent value.
2596     */
2597    
2598    int html_printer::get_troff_indent (void)
2599    {
2600      if (end_tempindent > 0)
2601        return temp_indent;
2602      else
2603        return troff_indent;
2604  }  }
2605    
2606  /*  /*
# Line 2190  void html_printer::do_pageoffset (char * Line 2609  void html_printer::do_pageoffset (char *
2609    
2610  void html_printer::do_indentation (char *arg)  void html_printer::do_indentation (char *arg)
2611  {  {
2612    if (fill_on)    next_indent = atoi(arg);
2613      do_indent(atoi(arg), pageoffset, linelength);    seen_indent = TRUE;
2614  }  }
2615    
2616  /*  /*
# Line 2201  void html_printer::do_indentation (char Line 2620  void html_printer::do_indentation (char
2620  void html_printer::do_tempindent (char *arg)  void html_printer::do_tempindent (char *arg)
2621  {  {
2622    if (fill_on) {    if (fill_on) {
2623      end_tempindent = 1;      /*
2624      prev_indent    = indentation;       *  we set the end_tempindent to 2 as the first .br
2625      do_indent(atoi(arg), pageoffset, linelength);       *  activates the .ti and the second terminates it.
2626         */
2627        end_tempindent = 2;
2628        temp_indent = atoi(arg);
2629    }    }
2630  }  }
2631    
# Line 2229  void html_printer::shutdown_table (void) Line 2651  void html_printer::shutdown_table (void)
2651    
2652  void html_printer::do_indent (int in, int pageoff, int linelen)  void html_printer::do_indent (int in, int pageoff, int linelen)
2653  {  {
2654    if ((indentation != -1) &&    if ((device_indent != -1) &&
2655        (pageoffset+indentation != in+pageoff)) {        (pageoffset+device_indent != in+pageoff)) {
2656            
2657      current_paragraph->done_para();      current_paragraph->done_para();
2658                
2659      indentation = in;      device_indent = in;
2660      pageoffset  = pageoff;      pageoffset  = pageoff;
2661      if (linelen <= max_linelength)      if (linelen <= max_linelength)
2662        linelength  = linelen;        linelength  = linelen;
2663    
2664      current_paragraph->do_para(&html, "", indentation, pageoffset, max_linelength);      current_paragraph->do_para(&html, "", device_indent,
2665                                   pageoffset, max_linelength);
2666    }    }
2667  }  }
2668    
# Line 2258  void html_printer::do_verticalspacing (c Line 2681  void html_printer::do_verticalspacing (c
2681    
2682  void html_printer::do_pointsize (char *arg)  void html_printer::do_pointsize (char *arg)
2683  {  {
2684    pointsize = atoi(arg);    /*
2685       *  firstly check to see whether this point size is really associated with a .tl tag
2686       */
2687    
2688      if (! page_contents->glyphs.is_empty()) {
2689        text_glob *g = page_contents->glyphs.get_data();
2690        text_glob *t = page_contents->glyphs.get_data();
2691    
2692        while (t->is_a_tag() && (! page_contents->glyphs.is_equal_to_head())) {
2693          if (t->is_tl()) {
2694            /*
2695             *  found title therefore ignore this .ps tag
2696             */
2697            while (t != g) {
2698              page_contents->glyphs.move_left();
2699              t = page_contents->glyphs.get_data();
2700            }
2701            return;
2702          }
2703          page_contents->glyphs.move_right();
2704          t = page_contents->glyphs.get_data();
2705        }
2706        /*
2707         *  move back to original position
2708         */
2709        while (t != g) {
2710          page_contents->glyphs.move_left();
2711          t = page_contents->glyphs.get_data();
2712        }
2713        /*
2714         *  collect legal pointsize
2715         */
2716        pointsize = atoi(arg);
2717      }
2718  }  }
2719    
2720  /*  /*
2721   *  do_fill - records whether troff has requested that text be filled.   *  do_fill - records whether troff has requested that text be filled.
2722   */   */
2723    
2724  void html_printer::do_fill (int on)  void html_printer::do_fill (char *arg)
2725  {  {
2726    current_paragraph->do_break();    int on = atoi(arg);
2727    output_hpos = indentation+pageoffset;        
2728      output_hpos = get_troff_indent()+pageoffset;
2729    supress_sub_sup = TRUE;    supress_sub_sup = TRUE;
2730    
2731    if (fill_on != on) {    if (fill_on != on) {
2732      if (on)      if (on)
2733        current_paragraph->do_para("");        current_paragraph->do_para("");
     else  
       current_paragraph->do_pre();  
2734      fill_on = on;      fill_on = on;
2735    }    }
2736  }  }
# Line 2292  void html_printer::do_eol (void) Line 2747  void html_printer::do_eol (void)
2747        current_paragraph->do_break();        current_paragraph->do_break();
2748      }      }
2749    }    }
2750    output_hpos = indentation+pageoffset;    output_hpos = get_troff_indent()+pageoffset;
2751    }
2752    
2753    /*
2754     *  do_check_center - checks to see whether we have seen a `.ce' tag
2755     *                    during the previous line.
2756     */
2757    
2758    void html_printer::do_check_center(void)
2759    {
2760      if (seen_center) {
2761        seen_center = FALSE;
2762        if (next_center > 0) {
2763          if (end_center == 0) {
2764            current_paragraph->done_para();
2765            supress_sub_sup = TRUE;
2766            current_paragraph->do_para("align=center");
2767          } else
2768            if (strcmp("align=center",
2769                       current_paragraph->get_alignment()) != 0) {
2770              /*
2771               *  different alignment, so shutdown paragraph and open
2772               *  a new one.
2773               */
2774              current_paragraph->done_para();
2775              supress_sub_sup = TRUE;
2776              current_paragraph->do_para("align=center");
2777            } else
2778              /*
2779               *  same alignment, if we have emitted text then issue a break.
2780               */
2781              if (current_paragraph->emitted_text())
2782                current_paragraph->do_break();
2783        } else
2784          /*
2785           *  next_center == 0
2786           */
2787          if (end_center > 0) {
2788            current_paragraph->done_para();
2789            supress_sub_sup = TRUE;
2790          }
2791        end_center = next_center;
2792      }
2793  }  }
2794    
2795  /*  /*
# Line 2374  void html_printer::do_job_name (char *na Line 2871  void html_printer::do_job_name (char *na
2871  }  }
2872    
2873  /*  /*
2874     *  do_head - adds a string to head_info which is to be included into
2875     *            the <head> </head> section of the html document.
2876     */
2877    
2878    void html_printer::do_head (char *name)
2879    {
2880      head_info += string(name);
2881      head_info += '\n';
2882    }
2883    
2884    /*
2885   *  do_break - handles the ".br" request and also   *  do_break - handles the ".br" request and also
2886   *             undoes an outstanding ".ti" command.   *             undoes an outstanding ".ti" command
2887     *             and calls indent if the indentation
2888     *             related registers have changed.
2889   */   */
2890    
2891  void html_printer::do_break (void)  void html_printer::do_break (void)
2892  {  {
2893      int seen_temp_indent = FALSE;
2894    
2895    current_paragraph->do_break();    current_paragraph->do_break();
2896    if (end_tempindent > 0) {    if (end_tempindent > 0) {
2897      end_tempindent--;      end_tempindent--;
2898      if (end_tempindent == 0)      if (end_tempindent > 0)
2899        do_indent(prev_indent, pageoffset, linelength);        seen_temp_indent = TRUE;
2900      }
2901      if (seen_indent || seen_pageoffset || seen_linelength || seen_temp_indent) {
2902        if (seen_indent && (! seen_temp_indent))
2903          troff_indent = next_indent;
2904        if (! seen_pageoffset)
2905          next_pageoffset = pageoffset;
2906        if (! seen_linelength)
2907          next_linelength = linelength;
2908        do_indent(get_troff_indent(), next_pageoffset, next_linelength);
2909      }
2910      seen_indent     = seen_temp_indent;
2911      seen_linelength = FALSE;
2912      seen_pageoffset = FALSE;
2913      do_check_center();
2914      output_hpos     = get_troff_indent()+pageoffset;
2915      supress_sub_sup = TRUE;
2916    }
2917    
2918    void html_printer::do_space (char *arg)
2919    {
2920      int n = atoi(arg);
2921    
2922      seen_space = atoi(arg);
2923      as.check_sp(seen_space);
2924      while (n>0) {
2925        current_paragraph->do_space();
2926        n--;
2927    }    }
   output_hpos = indentation+pageoffset;  
2928    supress_sub_sup = TRUE;    supress_sub_sup = TRUE;
2929  }  }
2930    
# Line 2401  void html_printer::do_tab_ts (text_glob Line 2939  void html_printer::do_tab_ts (text_glob
2939    if (t != NULL) {    if (t != NULL) {
2940      current_paragraph->done_pre();      current_paragraph->done_pre();
2941      current_paragraph->done_para();      current_paragraph->done_para();
2942        current_paragraph->remove_para_space();
2943    
2944    #if defined(DEBUG_TABLES)
2945      html.simple_comment("TABS");      html.simple_comment("TABS");
2946    #endif
2947    
2948      t->set_linelength(max_linelength);      t->set_linelength(max_linelength);
2949      t->add_indent(pageoffset);      t->add_indent(pageoffset);
# Line 2424  void html_printer::do_tab_te (void) Line 2965  void html_printer::do_tab_te (void)
2965    }    }
2966    
2967    table = NULL;    table = NULL;
2968      restore_troff_indent();
   if (indentation > 0) {  
     /*  
      *  restore indentation  
      */  
     int newin = indentation;  
     indentation = 0;  
     do_indent(newin, pageoffset, linelength);  
   }  
2969  }  }
2970    
2971  /*  /*
# Line 2445  void html_printer::do_tab (char *s) Line 2978  void html_printer::do_tab (char *s)
2978      while (isspace(*s))      while (isspace(*s))
2979        s++;        s++;
2980      s++;      s++;
2981      int col = table->find_column(atoi(s) + pageoffset + indentation);      int col = table->find_column(atoi(s) + pageoffset + get_troff_indent());
2982      if (col > 0) {      if (col > 0) {
2983        current_paragraph->done_para();        current_paragraph->done_para();
2984        table->emit_col(col);        table->emit_col(col);
# Line 2460  void html_printer::do_tab (char *s) Line 2993  void html_printer::do_tab (char *s)
2993  void html_printer::do_tab0 (void)  void html_printer::do_tab0 (void)
2994  {  {
2995    if (table) {    if (table) {
2996      int col = table->find_column(pageoffset+indentation);      int col = table->find_column(pageoffset+get_troff_indent());
2997      if (col > 0) {      if (col > 0) {
2998        current_paragraph->done_para();        current_paragraph->done_para();
2999        table->emit_col(col);        table->emit_col(col);
# Line 2481  void html_printer::do_col (char *s) Line 3014  void html_printer::do_col (char *s)
3014  }  }
3015    
3016  /*  /*
3017   *  troff_tag - processes the troff tag and manipulates the troff state machine.   *  troff_tag - processes the troff tag and manipulates the troff
3018     *              state machine.
3019   */   */
3020    
3021  void html_printer::troff_tag (text_glob *g)  void html_printer::troff_tag (text_glob *g)
# Line 2491  void html_printer::troff_tag (text_glob Line 3025  void html_printer::troff_tag (text_glob
3025     */     */
3026    char *t=(char *)g->text_string+9;    char *t=(char *)g->text_string+9;
3027    
3028    if (g->is_eol()) {    if (strncmp(g->text_string, "html</p>:", 9) == 0) {
3029        do_end_para(g);
3030      } else if (g->is_eol()) {
3031      do_eol();      do_eol();
3032    } else if (g->is_eol_ce()) {    } else if (g->is_eol_ce()) {
3033      do_eol_ce();      do_eol_ce();
3034    } else if (strncmp(t, ".sp", 3) == 0) {    } else if (strncmp(t, ".sp", 3) == 0) {
3035      if (g->get_arg() > 0)      char *a = (char *)t+3;
3036        current_paragraph->do_space();      do_space(a);
     else  
       current_paragraph->do_break();  
     supress_sub_sup = TRUE;  
3037    } else if (strncmp(t, ".br", 3) == 0) {    } else if (strncmp(t, ".br", 3) == 0) {
3038        seen_break = 1;
3039        as.check_br(1);
3040      do_break();      do_break();
3041    } else if (strcmp(t, ".centered-image") == 0) {    } else if (strcmp(t, ".centered-image") == 0) {
3042      do_centered_image();      do_centered_image();
# Line 2516  void html_printer::troff_tag (text_glob Line 3051  void html_printer::troff_tag (text_glob
3051      char *a = (char *)t+3;      char *a = (char *)t+3;
3052      supress_sub_sup = TRUE;      supress_sub_sup = TRUE;
3053      do_center(a);      do_center(a);
3054    } else if (strncmp(t, ".tl", 3) == 0) {    } else if (g->is_tl()) {
3055      supress_sub_sup = TRUE;      supress_sub_sup = TRUE;
3056      title.with_h1 = TRUE;      title.with_h1 = TRUE;
3057      do_title();      do_title();
# Line 2525  void html_printer::troff_tag (text_glob Line 3060  void html_printer::troff_tag (text_glob
3060      title.with_h1 = FALSE;      title.with_h1 = FALSE;
3061      do_title();      do_title();
3062    } else if (strncmp(t, ".fi", 3) == 0) {    } else if (strncmp(t, ".fi", 3) == 0) {
3063      do_fill(TRUE);      char *a = (char *)t+3;
3064    } else if (strncmp(t, ".nf", 3) == 0) {      do_fill(a);
     do_fill(FALSE);  
3065    } else if ((strncmp(t, ".SH", 3) == 0) || (strncmp(t, ".NH", 3) == 0)) {    } else if ((strncmp(t, ".SH", 3) == 0) || (strncmp(t, ".NH", 3) == 0)) {
3066      char *a = (char *)t+3;      char *a = (char *)t+3;
3067      do_heading(a);      do_heading(a);
# Line 2554  void html_printer::troff_tag (text_glob Line 3088  void html_printer::troff_tag (text_glob
3088    } else if (strncmp(t, ".job-name", 9) == 0) {    } else if (strncmp(t, ".job-name", 9) == 0) {
3089      char *a = (char *)t+9;      char *a = (char *)t+9;
3090      do_job_name(a);      do_job_name(a);
3091      } else if (strncmp(t, ".head", 5) == 0) {
3092        char *a = (char *)t+5;
3093        do_head(a);
3094    } else if (strcmp(t, ".no-auto-rule") == 0) {    } else if (strcmp(t, ".no-auto-rule") == 0) {
3095      auto_rule = FALSE;      auto_rule = FALSE;
3096    } else if (strcmp(t, ".tab-ts") == 0) {    } else if (strcmp(t, ".tab-ts") == 0) {
# Line 2592  void html_printer::flush_globs (void) Line 3129  void html_printer::flush_globs (void)
3129      page_contents->glyphs.start_from_head();      page_contents->glyphs.start_from_head();
3130      do {      do {
3131        g = page_contents->glyphs.get_data();        g = page_contents->glyphs.get_data();
3132          if (strcmp(g->text_string, "Here") == 0)
3133            stop();
3134    
3135    #if 0
3136          fprintf(stderr, "[%s:%d:%d:%d:%d]",
3137                  g->text_string, g->minv, g->minh, g->maxv, g->maxh) ;
3138          fflush(stderr);
3139    #endif
3140    
3141          handle_state_assertion(g);
3142    
3143        if (strcmp(g->text_string, "XXXXXXX") == 0)        if (strcmp(g->text_string, "XXXXXXX") == 0)
3144          stop();          stop();
3145    
3146        if (g->is_a_tag()) {        if (g->is_a_tag())
3147          troff_tag(g);          troff_tag(g);
3148        } else if (g->is_a_line()) {        else if (g->is_a_line())
3149          emit_line(g);          emit_line(g);
3150        } else {        else {
3151            as.check_sp(seen_space);
3152            as.check_br(seen_break);
3153            seen_break = 0;
3154            seen_space = 0;
3155          emit_html(g);          emit_html(g);
3156        }        }
3157    
3158          as.check_fi(fill_on);
3159          as.check_ce(end_center);
3160        /*        /*
3161         *  after processing the title (and removing it) the glyph list might be empty         *  after processing the title (and removing it) the glyph list might be empty
3162         */         */
# Line 2621  void html_printer::flush_globs (void) Line 3175  void html_printer::flush_globs (void)
3175  int html_printer::calc_nf (text_glob *g, int nf)  int html_printer::calc_nf (text_glob *g, int nf)
3176  {  {
3177    if (g != NULL) {    if (g != NULL) {
3178      if (g->is_fi())      if (g->is_fi()) {
3179          as.check_fi(TRUE);
3180        return FALSE;        return FALSE;
3181      if (g->is_nf())      }
3182        if (g->is_nf()) {
3183          as.check_fi(FALSE);
3184        return TRUE;        return TRUE;
3185        }
3186    }    }
3187      as.check_fi(! nf);
3188    return nf;    return nf;
3189  }  }
3190    
# Line 2636  int html_printer::calc_nf (text_glob *g, Line 3195  int html_printer::calc_nf (text_glob *g,
3195  void html_printer::calc_po_in (text_glob *g, int nf)  void html_printer::calc_po_in (text_glob *g, int nf)
3196  {  {
3197    if (g->is_in())    if (g->is_in())
3198      indentation = g->get_arg();      troff_indent = g->get_arg();
3199    else if (g->is_po())    else if (g->is_po())
3200      pageoffset = g->get_arg();      pageoffset = g->get_arg();
3201    else if (g->is_ti()) {    else if (g->is_ti()) {
3202      prev_indent = indentation;      temp_indent = g->get_arg();
3203      indentation = g->get_arg();      end_tempindent = 2;
3204      end_tempindent = 1;    } else if (g->is_br() || (nf && g->is_eol())) {
3205    } else if (g->is_br() && ((end_tempindent > 0) || (nf && g->is_eol()))) {      if (end_tempindent > 0)
3206      end_tempindent = 0;        end_tempindent--;
     indentation = prev_indent;  
3207    }    }
3208  }  }
3209    
# Line 2656  void html_printer::calc_po_in (text_glob Line 3214  void html_printer::calc_po_in (text_glob
3214    
3215  int html_printer::next_horiz_pos (text_glob *g, int nf)  int html_printer::next_horiz_pos (text_glob *g, int nf)
3216  {  {
3217    int next     = -1;    int next = -1;
3218    
3219    if ((g != NULL) && (g->is_br() || (nf && g->is_eol())))    if ((g != NULL) && (g->is_br() || (nf && g->is_eol())))
3220      if (! page_contents->glyphs.is_empty()) {      if (! page_contents->glyphs.is_empty()) {
3221        page_contents->glyphs.move_right_get_data();        page_contents->glyphs.move_right_get_data();
3222        if (g == NULL)        if (g == NULL) {
3223          page_contents->glyphs.start_from_head();          page_contents->glyphs.start_from_head();
3224            as.reset();
3225          }
3226        else {        else {
3227          next = g->minh;          next = g->minh;
3228          page_contents->glyphs.move_left();          page_contents->glyphs.move_left();
# Line 2760  void html_printer::remove_courier_tabs ( Line 3320  void html_printer::remove_courier_tabs (
3320    
3321    if (! page_contents->glyphs.is_empty()) {    if (! page_contents->glyphs.is_empty()) {
3322      page_contents->glyphs.start_from_head();      page_contents->glyphs.start_from_head();
3323        as.reset();
3324      line_start = TRUE;      line_start = TRUE;
3325      do {      do {
3326        g = page_contents->glyphs.get_data();        g = page_contents->glyphs.get_data();
3327                handle_state_assertion(g);
3328        nf = calc_nf(g, nf);        nf = calc_nf(g, nf);
3329    
3330        if (line_start) {        if (line_start) {
# Line 2773  void html_printer::remove_courier_tabs ( Line 3334  void html_printer::remove_courier_tabs (
3334          }          }
3335        }        }
3336    
3337        line_start = g->is_br() || g->is_nf() || g->is_fi() || (nf && g->is_eol());        // line_start = g->is_br() || g->is_nf() || g->is_fi() || (nf && g->is_eol());
3338          line_start = g->is_br() || (nf && g->is_eol());
3339        page_contents->glyphs.move_right();        page_contents->glyphs.move_right();
3340      } while (! page_contents->glyphs.is_equal_to_head());      } while (! page_contents->glyphs.is_equal_to_head());
3341    }    }
# Line 2789  void html_printer::insert_tab0_foreach_t Line 3351  void html_printer::insert_tab0_foreach_t
3351    
3352    if (! page_contents->glyphs.is_empty()) {    if (! page_contents->glyphs.is_empty()) {
3353      page_contents->glyphs.start_from_head();      page_contents->glyphs.start_from_head();
3354        as.reset();
3355      start_of_line = page_contents->glyphs.get_data();      start_of_line = page_contents->glyphs.get_data();
3356      do {      do {
3357        g = page_contents->glyphs.get_data();        g = page_contents->glyphs.get_data();
3358                handle_state_assertion(g);
3359        nf = calc_nf(g, nf);        nf = calc_nf(g, nf);
3360    
3361        if (g->is_tab())        if (g->is_tab())
# Line 2805  void html_printer::insert_tab0_foreach_t Line 3368  void html_printer::insert_tab0_foreach_t
3368          do {          do {
3369            page_contents->glyphs.move_right();            page_contents->glyphs.move_right();
3370            g = page_contents->glyphs.get_data();            g = page_contents->glyphs.get_data();
3371              handle_state_assertion(g);
3372            nf = calc_nf(g, nf);            nf = calc_nf(g, nf);
3373            if (page_contents->glyphs.is_equal_to_head()) {            if (page_contents->glyphs.is_equal_to_head()) {
3374              if (seen_tab && !seen_col)              if (seen_tab && !seen_col)
# Line 2872  void html_printer::add_table_end (const Line 3436  void html_printer::add_table_end (const
3436  }  }
3437    
3438  /*  /*
3439   *  lookahead_for_tables - checks for .col tags and inserts table start/end tags   *  lookahead_for_tables - checks for .col tags and inserts table
3440     *                         start/end tags
3441   */   */
3442    
3443  void html_printer::lookahead_for_tables (void)  void html_printer::lookahead_for_tables (void)
# Line 2900  void html_printer::lookahead_for_tables Line 3465  void html_printer::lookahead_for_tables
3465    page_contents->dump_page();    page_contents->dump_page();
3466    if (! page_contents->glyphs.is_empty()) {    if (! page_contents->glyphs.is_empty()) {
3467      page_contents->glyphs.start_from_head();      page_contents->glyphs.start_from_head();
3468        as.reset();
3469      g = page_contents->glyphs.get_data();      g = page_contents->glyphs.get_data();
3470        if (g->is_br()) {
3471          g = page_contents->glyphs.move_right_get_data();
3472          handle_state_assertion(g);
3473          if (page_contents->glyphs.is_equal_to_head()) {
3474            if (tbl != NULL)
3475              delete tbl;
3476            return;
3477          }
3478    
3479          start_of_line = g;
3480          seen_text = FALSE;
3481          ncol = 0;
3482          left = next_horiz_pos(g, nf);
3483          if (found_col)
3484            last = g;
3485          found_col = FALSE;
3486        }
3487        
3488      do {      do {
3489  #if defined(DEBUG_TABLES)  #if defined(DEBUG_TABLES)
3490        fprintf(stderr, " [") ;        fprintf(stderr, " [") ;
# Line 2936  void html_printer::lookahead_for_tables Line 3520  void html_printer::lookahead_for_tables
3520          colmin = g->get_tab_args(&align);          colmin = g->get_tab_args(&align);
3521          align = 'L'; // for now as 'C' and 'R' are broken          align = 'L'; // for now as 'C' and 'R' are broken
3522          ncol = tbl->find_tab_column(colmin);          ncol = tbl->find_tab_column(colmin);
3523          colmin += pageoffset + indentation;          colmin += pageoffset + get_troff_indent();
3524          colmax = tbl->get_tab_pos(ncol+1);          colmax = tbl->get_tab_pos(ncol+1);
3525          if (colmax > 0)          if (colmax > 0)
3526            colmax += pageoffset + indentation;            colmax += pageoffset + get_troff_indent();
3527        } else if (g->is_tab0()) {        } else if (g->is_tab0()) {
3528          if (type_of_col == col_tag && start_of_table != NULL) {          if (type_of_col == col_tag && start_of_table != NULL) {
3529            page_contents->glyphs.move_left();            page_contents->glyphs.move_left();
# Line 2956  void html_printer::lookahead_for_tables Line 3540  void html_printer::lookahead_for_tables
3540          type_of_col = tab0_tag;          type_of_col = tab0_tag;
3541          ncol = 1;          ncol = 1;
3542          colmin = 0;          colmin = 0;
3543          colmax = tbl->get_tab_pos(2) + pageoffset + indentation;          colmax = tbl->get_tab_pos(2) + pageoffset + get_troff_indent();
3544        } else if (! g->is_a_tag())        } else if (! g->is_a_tag())
3545          update_min_max(type_of_col, &colmin, &colmax, g);          update_min_max(type_of_col, &colmin, &colmax, g);
3546    
# Line 2975  void html_printer::lookahead_for_tables Line 3559  void html_printer::lookahead_for_tables
3559          last = NULL;          last = NULL;
3560        } else if (g->is_ta()) {        } else if (g->is_ta()) {
3561          tab_defs = g->text_string;          tab_defs = g->text_string;
3562    
3563            if (type_of_col == col_tag)
3564              tbl->tab_stops->check_init(tab_defs);
3565    
3566          if (!tbl->tab_stops->compatible(tab_defs)) {          if (!tbl->tab_stops->compatible(tab_defs)) {
3567            if (start_of_table != NULL) {            if (start_of_table != NULL) {
3568              add_table_end("*** TABS ***");              add_table_end("*** TABS ***");
# Line 3008  void html_printer::lookahead_for_tables Line 3596  void html_printer::lookahead_for_tables
3596         *  move onto next glob, check whether we are starting a new line         *  move onto next glob, check whether we are starting a new line
3597         */         */
3598        g = page_contents->glyphs.move_right_get_data();        g = page_contents->glyphs.move_right_get_data();
3599          handle_state_assertion(g);
3600    
3601        if (g == NULL) {        if (g == NULL) {
3602          if (found_col) {          if (found_col) {
3603            page_contents->glyphs.start_from_head();            page_contents->glyphs.start_from_head();
3604              as.reset();
3605            last = g;            last = g;
3606            found_col = FALSE;            found_col = FALSE;
3607          }          }
3608        } else if (g->is_br() || (nf && g->is_eol())) {        } else if (g->is_br() || (nf && g->is_eol())) {
3609          do {          do {
3610            g = page_contents->glyphs.move_right_get_data();            g = page_contents->glyphs.move_right_get_data();
3611              handle_state_assertion(g);
3612            nf = calc_nf(g, nf);            nf = calc_nf(g, nf);
3613          } while ((g != NULL) && (g->is_br() || (nf && g->is_eol())));          } while ((g != NULL) && (g->is_br() || (nf && g->is_eol())));
3614          start_of_line = g;          start_of_line = g;
# Line 3051  void html_printer::lookahead_for_tables Line 3642  void html_printer::lookahead_for_tables
3642    
3643    // and reset the registers    // and reset the registers
3644    pageoffset = old_pageoffset;    pageoffset = old_pageoffset;
3645    indentation = 0;    troff_indent = 0;
3646    prev_indent = 0;    temp_indent = 0;
3647    end_tempindent = 0;    end_tempindent = 0;
3648  }  }
3649    
# Line 3329  void html_printer::do_sup_or_sub (text_g Line 3920  void html_printer::do_sup_or_sub (text_g
3920  }  }
3921    
3922  /*  /*
3923     *  do_end_para - writes out the html text after shutting down the
3924     *                current paragraph.
3925     */
3926    
3927    void html_printer::do_end_para (text_glob *g)
3928    {
3929      do_font(g);
3930      current_paragraph->done_para();
3931      html.put_string(g->text_string+9);
3932      output_vpos     = g->minv;
3933      output_hpos     = g->maxh;
3934      output_vpos_max = g->maxv;
3935      supress_sub_sup = FALSE;
3936    }
3937    
3938    /*
3939   *  emit_html - write out the html text   *  emit_html - write out the html text
3940   */   */
3941    
# Line 3352  void html_printer::flush_sbuf() Line 3959  void html_printer::flush_sbuf()
3959    if (sbuf.length() > 0) {    if (sbuf.length() > 0) {
3960      int r=font::res;   // resolution of the device      int r=font::res;   // resolution of the device
3961      set_style(sbuf_style);      set_style(sbuf_style);
3962    
3963      if (overstrike_detected && (! is_bold(sbuf_style.f))) {      if (overstrike_detected && (! is_bold(sbuf_style.f))) {
3964        font *bold_font = make_bold(sbuf_style.f);        font *bold_font = make_bold(sbuf_style.f);
3965        if (bold_font != NULL)        if (bold_font != NULL)
# Line 3462  html_printer::html_printer() Line 4070  html_printer::html_printer()
4070    max_linelength(-1),    max_linelength(-1),
4071    linelength(0),    linelength(0),
4072    pageoffset(0),    pageoffset(0),
4073    indentation(0),    troff_indent(0),
4074    prev_indent(0),    device_indent(0),
4075    pointsize(0),    temp_indent(0),
4076      pointsize(base_point_size),
4077    line_number(0),    line_number(0),
4078    background(default_background)    background(default_background),
4079      seen_indent(FALSE),
4080      next_indent(0),
4081      seen_pageoffset(FALSE),
4082      next_pageoffset(0),
4083      seen_linelength(FALSE),
4084      next_linelength(0),
4085      seen_center(FALSE),
4086      next_center(0),
4087      seen_space(0),
4088      seen_break(0)
4089  {  {
4090    file_list.add_new_file(xtmpfile());    file_list.add_new_file(xtmpfile());
4091    html.set_file(file_list.get_file());    html.set_file(file_list.get_file());
# Line 3618  int html_printer::overstrike(int idx, co Line 4237  int html_printer::overstrike(int idx, co
4237  }  }
4238    
4239  /*  /*
4240   *  set_char - adds a character into the sbuf if it is a continuation with the previous   *  set_char - adds a character into the sbuf if it is a continuation
4241   *             word otherwise flush the current sbuf and add character anew.   *             with the previous word otherwise flush the current sbuf
4242     *             and add character anew.
4243   */   */
4244    
4245  void html_printer::set_char(int i, font *f, const environment *env, int w, const char *name)  void html_printer::set_char(int i, font *f, const environment *env,
4246                                int w, const char *name)
4247  {  {
4248    style sty(f, env->size, env->height, env->slant, env->fontno, *env->col);    style sty(f, env->size, env->height, env->slant, env->fontno, *env->col);
4249    if (sty.slant != 0) {    if (sty.slant != 0) {
# Line 3636  void html_printer::set_char(int i, font Line 4257  void html_printer::set_char(int i, font
4257      return;      return;
4258        
4259    flush_sbuf();    flush_sbuf();
4260      if (sbuf_style.f == NULL)
4261        sbuf_style = sty;
4262    add_to_sbuf(i, name);    add_to_sbuf(i, name);
4263    sbuf_end_hpos = env->hpos + w;    sbuf_end_hpos = env->hpos + w;
4264    sbuf_start_hpos = env->hpos;    sbuf_start_hpos = env->hpos;
# Line 3687  void html_printer::set_numbered_char(int Line 4310  void html_printer::set_numbered_char(int
4310    set_char(i, f, env, w, 0);    set_char(i, f, env, w, 0);
4311  }  }
4312    
4313    int html_printer::set_char_and_width(const char *nm, const environment *env,
4314                                         int *widthp, font **f)
4315    {
4316      int i = font::name_to_index(nm);
4317      int fn = env->fontno;
4318      if (fn < 0 || fn >= nfonts) {
4319        error("bad font position `%1'", fn);
4320        return -1;
4321      }
4322      *f = font_table[fn];
4323      if (*f == 0) {
4324        error("no font mounted at `%1'", fn);
4325        return -1;
4326      }
4327      if (!(*f)->contains(i)) {
4328        if (nm[0] != '\0' && nm[1] == '\0')
4329          error("font `%1' does not contain ascii character `%2'",
4330                (*f)->get_name(),
4331                nm[0]);
4332        else
4333          error("font `%1' does not contain special character `%2'",
4334                (*f)->get_name(),
4335                nm);
4336        return -1;
4337      }
4338      int w = (*f)->get_width(i, env->size);
4339      w = round_width(w);
4340      if (widthp)
4341        *widthp = w;
4342      return i;
4343    }
4344    
4345  /*  /*
4346   *  write_title - writes the title to this document   *  write_title - writes the title to this document
4347   */   */
# Line 3739  void html_printer::begin_page(int n) Line 4394  void html_printer::begin_page(int n)
4394    output_vpos            = -1;    output_vpos            = -1;
4395    output_vpos_max        = -1;    output_vpos_max        = -1;
4396    current_paragraph      = new html_text(&html);    current_paragraph      = new html_text(&html);
4397    do_indent(indentation, pageoffset, linelength);    do_indent(get_troff_indent(), pageoffset, linelength);
4398    current_paragraph->do_para("");    current_paragraph->do_para("");
4399  }  }
4400    
# Line 3798  void html_printer::write_navigation (con Line 4453  void html_printer::write_navigation (con
4453    if (multiple_files) {    if (multiple_files) {
4454      write_rule();      write_rule();
4455      fputs("[ ", stdout);      fputs("[ ", stdout);
4456      if (prev != "" && prev != top) {      if ((strcmp(prev.contents(), "") != 0) && prev != top && prev != current) {
4457        emit_link(prev, "prev");        emit_link(prev, "prev");
4458        need_bar = TRUE;        need_bar = TRUE;
4459      }      }
4460      if (next != "" && next != top) {      if ((strcmp(next.contents(), "") != 0) && next != top && next != current) {
4461        if (need_bar)        if (need_bar)
4462          fputs(" | ", stdout);          fputs(" | ", stdout);
4463        emit_link(next, "next");        emit_link(next, "next");
4464        need_bar = TRUE;        need_bar = TRUE;
4465      }      }
4466      if (top != "<standard input>" && top != "" && top != current) {      if (top != "<standard input>" && (strcmp(top.contents(), "") != 0) && top != current) {
4467        if (need_bar)        if (need_bar)
4468          fputs(" | ", stdout);          fputs(" | ", stdout);
4469        emit_link(top, "top");        emit_link(top, "top");
       fputs(" ]\n", stdout);  
4470      }      }
4471        fputs(" ]\n", stdout);
4472      write_rule();      write_rule();
4473    }    }
4474  }  }
4475    
4476  /*  /*
4477   *  do_file_components - scan the file list copying each temporary file in turn.   *  do_file_components - scan the file list copying each temporary
4478   *                       This is used twofold:   *                       file in turn.  This is used twofold:
4479   *   *
4480   *                       firstly to emit section heading links, between file fragments if required   *                       firstly to emit section heading links,
4481   *                       and secondly to generate jobname file fragments if required.   *                       between file fragments if required and
4482     *                       secondly to generate jobname file fragments
4483     *                       if required.
4484   */   */
4485    
4486  void html_printer::do_file_components (void)  void html_printer::do_file_components (void)
# Line 3904  html_printer::~html_printer() Line 4561  html_printer::~html_printer()
4561                "content=\"text/html; charset=US-ASCII\">\n", stdout);                "content=\"text/html; charset=US-ASCII\">\n", stdout);
4562    fputs("<meta name=\"Content-Style\" content=\"text/css\">\n", stdout);    fputs("<meta name=\"Content-Style\" content=\"text/css\">\n", stdout);
4563    write_title(TRUE);    write_title(TRUE);
4564      head_info += '\0';
4565      fputs(head_info.contents(), stdout);
4566    fputs("</head>\n", stdout);    fputs("</head>\n", stdout);
4567    do_body();    do_body();
4568    
# Line 3928  html_printer::~html_printer() Line 4587  html_printer::~html_printer()
4587  }  }
4588    
4589  /*  /*
4590   *  special - handle all x X requests from troff. For post-html they allow users   *  get_str - returns a dupicate of string, s. The duplicate
4591   *            to pass raw html commands, turn auto linked headings off/on and   *            string is terminated at the next ',' or ']'.
4592   *            also allow troff to emit tags to indicate when a: .br, .sp etc occurs.   */
4593    
4594    static char *get_str (const char *s, char **n)
4595    {
4596      int i=0;
4597      char *v;
4598    
4599      while ((s[i] != (char)0) && (s[i] != ',') && (s[i] != ']'))
4600        i++;
4601      if (i>0) {
4602        v = (char *)malloc(i+1);
4603        memcpy(v, s, i+1);
4604        v[i] = (char)0;
4605        if (s[i] == ',')
4606          (*n) = (char *)&s[i+1];
4607        else
4608          (*n) = (char *)&s[i];
4609        return v;
4610      }
4611      if (s[i] == ',')
4612        (*n) = (char *)&s[1];
4613      else
4614        (*n) = (char *)s;
4615      return NULL;
4616    }
4617    
4618    /*
4619     *  make_val - creates a string from if s is NULL.
4620     */
4621    
4622    char *make_val (char *s, int v, char *id, char *f, char *l)
4623    {
4624      if (s == NULL) {
4625        char buf[30];
4626    
4627        sprintf(buf, "%d", v);
4628        return strdup(buf);
4629      }
4630      else {
4631        /*
4632         *  check that value, s, is the same as, v.
4633         */
4634        char *t = s;
4635    
4636        while (*t == '=')
4637          t++;
4638        if (atoi(t) != v) {
4639          if (f == NULL)
4640            f = "stdin";
4641          if (l == NULL)
4642            l = "<none>";
4643          fprintf(stderr, "%s:%s: grohtml assertion failed at id%s expecting %d and was given %s\n",
4644                  f, l, id, v, s);
4645        }
4646        return s;
4647      }
4648    }
4649    
4650    /*
4651     *  handle_assertion - handles the assertions created via .www:ASSERT
4652     *                     in www.tmac. See www.tmac for examples.
4653     *                     This method should be called as we are
4654     *                     parsing the ditroff input. It checks the x, y
4655     *                     position assertions. It does _not_ check the
4656     *                     troff state assertions as these are unknown at this
4657     *                     point.
4658     */
4659    
4660    void html_printer::handle_assertion (int minv, int minh, int maxv, int maxh, const char *s)
4661    {
4662      char *n;
4663      char *cmd = get_str(s, &n);
4664      char *id  = get_str(n, &n);
4665      char *val = get_str(n, &n);
4666      char *file= get_str(n, &n);
4667      char *line= get_str(n, &n);
4668    
4669      if (strcmp(cmd, "assertion:[x") == 0)
4670        as.addx(cmd, id, make_val(val, minh, id, file, line), file, line);
4671      else if (strcmp(cmd, "assertion:[y") == 0)
4672        as.addy(cmd, id, make_val(val, minv, id, file, line), file, line);
4673      else
4674        if (strncmp(cmd, "assertion:[", 11) == 0)
4675          page_contents->add_tag(&sbuf_style, string(s),
4676                                 line_number, minv, minh, maxv, maxh);
4677    }
4678    
4679    /*
4680     *  build_state_assertion - builds the troff state assertions.
4681     */
4682    
4683    void html_printer::handle_state_assertion (text_glob *g)
4684    {
4685      if (g != NULL && g->is_a_tag() &&
4686          (strncmp(g->text_string, "assertion:[", 11) == 0)) {
4687        char *n   = (char *)&g->text_string[11];
4688        char *cmd = get_str(n, &n);
4689        char *val = get_str(n, &n);
4690        char *id  = get_str(n, &n);  // unused
4691        char *file= get_str(n, &n);
4692        char *line= get_str(n, &n);
4693    
4694        as.build(cmd, val, file, line);
4695      }
4696    }
4697    
4698    /*
4699     *  special - handle all x X requests from troff. For post-html they
4700     *            allow users to pass raw html commands, turn auto linked
4701     *            headings off/on and also allow troff to emit tags to
4702     *            indicate when a: .br, .sp etc occurs.
4703   */   */
4704    
4705  void html_printer::special(char *s, const environment *env, char type)  void html_printer::special(char *s, const environment *env, char type)
# Line 3961  void html_printer::special(char *s, cons Line 4730  void html_printer::special(char *s, cons
4730        page_contents->add_and_encode(&sbuf_style, string(&s[5]),        page_contents->add_and_encode(&sbuf_style, string(&s[5]),
4731                                      line_number,                                      line_number,
4732                                      env->vpos-env->size*r/72, env->hpos,                                      env->vpos-env->size*r/72, env->hpos,
4733                                      env->vpos               , env->hpos);                                      env->vpos               , env->hpos,
4734                                        FALSE);
4735    
4736        /*        /*
4737         * assume that the html command has no width, if it does then hopefully troff         * assume that the html command has no width, if it does then
4738         * will have fudged this in a macro by requesting that the formatting move right by         * hopefully troff will have fudged this in a macro by
4739         * the appropriate amount.         * requesting that the formatting move right by the appropriate
4740           * amount.
4741           */
4742        } else if (strncmp(s, "html</p>:", 9) == 0) {
4743          int r=font::res;   /* resolution of the device */
4744          font *f=sbuf_style.f;
4745    
4746          if (f == NULL) {
4747            int found=FALSE;
4748    
4749            f = font::load_font("TR", &found);
4750          }
4751    
4752          /*
4753           *  need to pass all of string through to html output during flush
4754           */
4755          page_contents->add_and_encode(&sbuf_style, string(s),
4756                                        line_number,
4757                                        env->vpos-env->size*r/72, env->hpos,
4758                                        env->vpos               , env->hpos,
4759                                        TRUE);
4760    
4761          /*
4762           * assume that the html command has no width, if it does then
4763           * hopefully troff will have fudged this in a macro by
4764           * requesting that the formatting move right by the appropriate
4765           * amount.
4766         */         */
4767      } else if (strncmp(s, "index:", 6) == 0) {      } else if (strncmp(s, "index:", 6) == 0) {
4768        cutoff_heading = atoi(&s[6]);        cutoff_heading = atoi(&s[6]);
# Line 3977  void html_printer::special(char *s, cons Line 4773  void html_printer::special(char *s, cons
4773                               line_number,                               line_number,
4774                               env->vpos-env->size*r/72, env->hpos,                               env->vpos-env->size*r/72, env->hpos,
4775                               env->vpos               , env->hpos);                               env->vpos               , env->hpos);
4776        } else if (strncmp(s, "assertion:[", 11) == 0) {
4777          int r=font::res;   /* resolution of the device */
4778    
4779          handle_assertion(env->vpos-env->size*r/72, env->hpos,
4780                           env->vpos, env->hpos, s);
4781      }      }
4782    }    }
4783  }  }
# Line 4011  int main(int argc, char **argv) Line 4812  int main(int argc, char **argv)
4812      { "version", no_argument, 0, 'v' },      { "version", no_argument, 0, 'v' },
4813      { NULL, 0, 0, 0 }      { NULL, 0, 0, 0 }
4814    };    };
4815    while ((c = getopt_long(argc, argv, "a:g:o:i:I:j:D:F:vbdhlrnp", long_options, NULL))    while ((c = getopt_long(argc, argv, "a:g:o:i:I:j:D:F:s:vbdhlrnp", long_options, NULL))
4816           != EOF)           != EOF)
4817      switch(c) {      switch(c) {
4818      case 'v':      case 'v':
# Line 4032  int main(int argc, char **argv) Line 4833  int main(int argc, char **argv)
4833      case 'F':      case 'F':
4834        font::command_line_font_dir(optarg);        font::command_line_font_dir(optarg);
4835        break;        break;
4836        case 's':
4837          base_point_size = atoi(optarg);
4838          break;
4839      case 'j':      case 'j':
4840        multiple_files = TRUE;        multiple_files = TRUE;
4841        job_name = optarg;        job_name = optarg;

Legend:
Removed from v.1.9  
changed lines
  Added in v.1.10

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26