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