Home | History | Annotate | Line # | Download | only in grohtml
      1 /*	$NetBSD: output.cpp,v 1.1.1.1 2016/01/13 18:41:49 christos Exp $	*/
      2 
      3 // -*- C++ -*-
      4 /* Copyright (C) 2000, 2001, 2003, 2004, 2005 Free Software Foundation, Inc.
      5  *
      6  *  Gaius Mulley (gaius (at) glam.ac.uk) wrote output.cpp
      7  *  but it owes a huge amount of ideas and raw code from
      8  *  James Clark (jjc (at) jclark.com) grops/ps.cpp.
      9  *
     10  *  output.cpp
     11  *
     12  *  provide the simple low level output routines needed by html.cpp
     13  */
     14 
     15 /*
     16 This file is part of groff.
     17 
     18 groff is free software; you can redistribute it and/or modify it under
     19 the terms of the GNU General Public License as published by the Free
     20 Software Foundation; either version 2, or (at your option) any later
     21 version.
     22 
     23 groff is distributed in the hope that it will be useful, but WITHOUT ANY
     24 WARRANTY; without even the implied warranty of MERCHANTABILITY or
     25 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     26 for more details.
     27 
     28 You should have received a copy of the GNU General Public License along
     29 with groff; see the file COPYING.  If not, write to the Free Software
     30 Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */
     31 
     32 #include "driver.h"
     33 #include "stringclass.h"
     34 #include "cset.h"
     35 
     36 #include <time.h>
     37 #include "html.h"
     38 
     39 #ifdef HAVE_UNISTD_H
     40 #include <unistd.h>
     41 #endif
     42 
     43 #undef DEBUGGING
     44 // #define DEBUGGING
     45 
     46 #if !defined(TRUE)
     47 #   define TRUE  (1==1)
     48 #endif
     49 #if !defined(FALSE)
     50 #   define FALSE (1==0)
     51 #endif
     52 
     53 
     54 #if defined(DEBUGGING)
     55 #  define FPUTC(X,Y)   do { fputc((X),(Y)); fputc((X), stderr); fflush(stderr); } while (0)
     56 #  define FPUTS(X,Y)   do { fputs((X),(Y)); fputs((X), stderr); fflush(stderr); } while (0)
     57 #  define PUTC(X,Y)    do { putc((X),(Y)); putc((X), stderr); fflush(stderr); } while (0)
     58 #else
     59 #  define FPUTC(X,Y)   do { fputc((X),(Y)); } while (0)
     60 #  define FPUTS(X,Y)   do { fputs((X),(Y)); } while (0)
     61 #  define PUTC(X,Y)    do { putc((X),(Y)); } while (0)
     62 #endif
     63 
     64 
     65 /*
     66  *  word - initialise a word and set next to NULL
     67  */
     68 
     69 word::word (const char *w, int n)
     70   : next(0)
     71 {
     72   s = new char[n+1];
     73   strncpy(s, w, n);
     74   s[n] = (char)0;
     75 }
     76 
     77 /*
     78  *  destroy word and the string copy.
     79  */
     80 
     81 word::~word ()
     82 {
     83   a_delete s;
     84 }
     85 
     86 /*
     87  *  word_list - create an empty word list.
     88  */
     89 
     90 word_list::word_list ()
     91   : length(0), head(0), tail(0)
     92 {
     93 }
     94 
     95 /*
     96  *  flush - flush a word list to a FILE, f, and return the
     97  *          length of the buffered string.
     98  */
     99 
    100 int word_list::flush (FILE *f)
    101 {
    102   word *t;
    103   int   len=length;
    104 
    105   while (head != 0) {
    106     t = head;
    107     head = head->next;
    108     FPUTS(t->s, f);
    109     delete t;
    110   }
    111   head   = 0;
    112   tail   = 0;
    113   length = 0;
    114 #if defined(DEBUGGING)
    115   fflush(f);   // just for testing
    116 #endif
    117   return( len );
    118 }
    119 
    120 /*
    121  *  add_word - adds a word to the outstanding word list.
    122  */
    123 
    124 void word_list::add_word (const char *s, int n)
    125 {
    126   if (head == 0) {
    127     head = new word(s, n);
    128     tail = head;
    129   } else {
    130     tail->next = new word(s, n);
    131     tail       = tail->next;
    132   }
    133   length += n;
    134 }
    135 
    136 /*
    137  *  get_length - returns the number of characters buffered
    138  */
    139 
    140 int word_list::get_length (void)
    141 {
    142   return( length );
    143 }
    144 
    145 /*
    146  *  the classes and methods for simple_output manipulation
    147  */
    148 
    149 simple_output::simple_output(FILE *f, int n)
    150 : fp(f), max_line_length(n), col(0), fixed_point(0), newlines(0)
    151 {
    152 }
    153 
    154 simple_output &simple_output::set_file(FILE *f)
    155 {
    156   if (fp)
    157     fflush(fp);
    158   fp = f;
    159   return *this;
    160 }
    161 
    162 simple_output &simple_output::copy_file(FILE *infp)
    163 {
    164   int c;
    165   while ((c = getc(infp)) != EOF)
    166     PUTC(c, fp);
    167   return *this;
    168 }
    169 
    170 simple_output &simple_output::end_line()
    171 {
    172   flush_last_word();
    173   if (col != 0) {
    174     PUTC('\n', fp);
    175     col = 0;
    176   }
    177   return *this;
    178 }
    179 
    180 simple_output &simple_output::special(const char *)
    181 {
    182   return *this;
    183 }
    184 
    185 simple_output &simple_output::simple_comment(const char *s)
    186 {
    187   flush_last_word();
    188   if (col != 0)
    189     PUTC('\n', fp);
    190   FPUTS("<!-- ", fp);
    191   FPUTS(s, fp);
    192   FPUTS(" -->\n", fp);
    193   col = 0;
    194   return *this;
    195 }
    196 
    197 simple_output &simple_output::begin_comment(const char *s)
    198 {
    199   flush_last_word();
    200   if (col != 0)
    201     PUTC('\n', fp);
    202   col = 0;
    203   put_string("<!--");
    204   space_or_newline();
    205   last_word.add_word(s, strlen(s));
    206   return *this;
    207 }
    208 
    209 simple_output &simple_output::end_comment()
    210 {
    211   flush_last_word();
    212   space_or_newline();
    213   put_string("-->").nl();
    214   return *this;
    215 }
    216 
    217 /*
    218  *  check_newline - checks to see whether we are able to issue
    219  *                  a newline and that one is needed.
    220  */
    221 
    222 simple_output &simple_output::check_newline(int n)
    223 {
    224   if ((col + n + last_word.get_length() + 1 > max_line_length) && (newlines)) {
    225     FPUTC('\n', fp);
    226     col = last_word.flush(fp);
    227   }
    228   return *this;
    229 }
    230 
    231 /*
    232  *  space_or_newline - will emit a newline or a space later on
    233  *                     depending upon the current column.
    234  */
    235 
    236 simple_output &simple_output::space_or_newline (void)
    237 {
    238   if ((col + last_word.get_length() + 1 > max_line_length) && (newlines)) {
    239     FPUTC('\n', fp);
    240     if (last_word.get_length() > 0) {
    241       col = last_word.flush(fp);
    242     } else {
    243       col = 0;
    244     }
    245   } else {
    246     if (last_word.get_length() != 0) {
    247       if (col > 0) {
    248 	FPUTC(' ', fp);
    249 	col++;
    250       }
    251       col += last_word.flush(fp);
    252     }
    253   }
    254   return *this;
    255 }
    256 
    257 /*
    258  *  force_nl - forces a newline.
    259  */
    260 
    261 simple_output &simple_output::force_nl (void)
    262 {
    263   space_or_newline();
    264   col += last_word.flush(fp);
    265   FPUTC('\n', fp);
    266   col = 0;
    267   return *this ;
    268 }
    269 
    270 /*
    271  *  nl - writes a newline providing that we
    272  *       are not in the first column.
    273  */
    274 
    275 simple_output &simple_output::nl (void)
    276 {
    277   space_or_newline();
    278   col += last_word.flush(fp);
    279   FPUTC('\n', fp);
    280   col = 0;
    281   return *this ;
    282 }
    283 
    284 simple_output &simple_output::set_fixed_point(int n)
    285 {
    286   assert(n >= 0 && n <= 10);
    287   fixed_point = n;
    288   return *this;
    289 }
    290 
    291 simple_output &simple_output::put_raw_char(char c)
    292 {
    293   col += last_word.flush(fp);
    294   PUTC(c, fp);
    295   col++;
    296   return *this;
    297 }
    298 
    299 simple_output &simple_output::put_string(const char *s, int n)
    300 {
    301   last_word.add_word(s, n);
    302   return *this;
    303 }
    304 
    305 simple_output &simple_output::put_string(const char *s)
    306 {
    307   last_word.add_word(s, strlen(s));
    308   return *this;
    309 }
    310 
    311 simple_output &simple_output::put_string(const string &s)
    312 {
    313   last_word.add_word(s.contents(), s.length());
    314   return *this;
    315 }
    316 
    317 simple_output &simple_output::put_number(int n)
    318 {
    319   char buf[1 + INT_DIGITS + 1];
    320   sprintf(buf, "%d", n);
    321   put_string(buf);
    322   return *this;
    323 }
    324 
    325 simple_output &simple_output::put_float(double d)
    326 {
    327   char buf[128];
    328 
    329   sprintf(buf, "%.4f", d);
    330   put_string(buf);
    331   return *this;
    332 }
    333 
    334 simple_output &simple_output::enable_newlines (int auto_newlines)
    335 {
    336   check_newline(0);
    337   newlines = auto_newlines;
    338   check_newline(0);
    339   return *this;
    340 }
    341 
    342 /*
    343  *  flush_last_word - flushes the last word and adjusts the
    344  *                    col position. It will insert a newline
    345  *                    before the last word if allowed and if
    346  *                    necessary.
    347  */
    348 
    349 void simple_output::flush_last_word (void)
    350 {
    351   int len=last_word.get_length();
    352 
    353   if (len > 0) {
    354     if (newlines) {
    355       if (col + len + 1 > max_line_length) {
    356 	FPUTS("\n", fp);
    357 	col = 0;
    358       } else {
    359 	FPUTS(" ", fp);
    360 	col++;
    361       }
    362       len += last_word.flush(fp);
    363     } else {
    364       FPUTS(" ", fp);
    365       col++;
    366       col += last_word.flush(fp);
    367     }
    368   }
    369 }
    370