Merge branch 'topic/sync-to-go-2'
[s-roff.git] / src / dev-html / output.cpp
blobb7caa3663d8eaf63e6b9650ccb52469eed9bdaf4
1 /*@ Provide the simple low level output routines needed by html.cpp.
3 * Copyright (c) 2014 - 2017 Steffen (Daode) Nurpmeso <steffen@sdaoden.eu>.
5 * Copyright (C) 2000 - 2001, 2003 - 2005 Free Software Foundation, Inc.
7 * Gaius Mulley (gaius@glam.ac.uk) wrote output.cpp
8 * but it owes a huge amount of ideas and raw code from
9 * James Clark (jjc@jclark.com) grops/ps.cpp.
12 * This is free software; you can redistribute it and/or modify it under
13 * the terms of the GNU General Public License as published by the Free
14 * Software Foundation; either version 2, or (at your option) any later
15 * version.
17 * This is distributed in the hope that it will be useful, but WITHOUT ANY
18 * WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 * for more details.
22 * You should have received a copy of the GNU General Public License along
23 * with groff; see the file COPYING. If not, write to the Free Software
24 * Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA.
27 #include "config.h"
28 #include "html-config.h"
30 #include <time.h>
32 #ifdef HAVE_UNISTD_H
33 # include <unistd.h>
34 #endif
36 #include "cset.h"
37 #include "driver.h"
38 #include "stringclass.h"
40 #include "html.h"
42 #ifdef DEBUGGING
43 # define FPUTC(X,Y) do { fputc((X),(Y)); fputc((X), stderr); fflush(stderr); } while (0)
44 # define FPUTS(X,Y) do { fputs((X),(Y)); fputs((X), stderr); fflush(stderr); } while (0)
45 # define PUTC(X,Y) do { putc((X),(Y)); putc((X), stderr); fflush(stderr); } while (0)
46 #else
47 # define FPUTC(X,Y) do { fputc((X),(Y)); } while (0)
48 # define FPUTS(X,Y) do { fputs((X),(Y)); } while (0)
49 # define PUTC(X,Y) do { putc((X),(Y)); } while (0)
50 #endif
53 * word - initialise a word and set next to NULL
56 word::word (const char *w, int n)
57 : next(0)
59 s = new char[n+1];
60 strncpy(s, w, n);
61 s[n] = (char)0;
65 * destroy word and the string copy.
68 word::~word ()
70 a_delete s;
74 * word_list - create an empty word list.
77 word_list::word_list ()
78 : length(0), head(0), tail(0)
83 * flush - flush a word list to a FILE, f, and return the
84 * length of the buffered string.
87 int word_list::flush (FILE *f)
89 word *t;
90 int len=length;
92 while (head != 0) {
93 t = head;
94 head = head->next;
95 FPUTS(t->s, f);
96 delete t;
98 head = 0;
99 tail = 0;
100 length = 0;
101 #if defined(DEBUGGING)
102 fflush(f); // just for testing
103 #endif
104 return( len );
108 * add_word - adds a word to the outstanding word list.
111 void word_list::add_word (const char *s, int n)
113 if (head == 0) {
114 head = new word(s, n);
115 tail = head;
116 } else {
117 tail->next = new word(s, n);
118 tail = tail->next;
120 length += n;
124 * get_length - returns the number of characters buffered
127 int word_list::get_length (void)
129 return( length );
133 * the classes and methods for simple_output manipulation
136 simple_output::simple_output(FILE *f, int n)
137 : fp(f), max_line_length(n), col(0), fixed_point(0), newlines(0)
141 simple_output &simple_output::set_file(FILE *f)
143 if (fp)
144 fflush(fp);
145 fp = f;
146 return *this;
149 simple_output &simple_output::copy_file(FILE *infp)
151 int c;
152 while ((c = getc(infp)) != EOF)
153 PUTC(c, fp);
154 return *this;
157 simple_output &simple_output::end_line()
159 flush_last_word();
160 if (col != 0) {
161 PUTC('\n', fp);
162 col = 0;
164 return *this;
167 simple_output &simple_output::special(const char *)
169 return *this;
172 simple_output &simple_output::simple_comment(const char *s)
174 flush_last_word();
175 if (col != 0)
176 PUTC('\n', fp);
177 FPUTS("<!-- ", fp);
178 FPUTS(s, fp);
179 FPUTS(" -->\n", fp);
180 col = 0;
181 return *this;
184 simple_output &simple_output::begin_comment(const char *s)
186 flush_last_word();
187 if (col != 0)
188 PUTC('\n', fp);
189 col = 0;
190 put_string("<!--");
191 space_or_newline();
192 last_word.add_word(s, strlen(s));
193 return *this;
196 simple_output &simple_output::end_comment()
198 flush_last_word();
199 space_or_newline();
200 put_string("-->").nl();
201 return *this;
205 * check_newline - checks to see whether we are able to issue
206 * a newline and that one is needed.
209 simple_output &simple_output::check_newline(int n)
211 if ((col + n + last_word.get_length() + 1 > max_line_length) && (newlines)) {
212 FPUTC('\n', fp);
213 col = last_word.flush(fp);
215 return *this;
219 * space_or_newline - will emit a newline or a space later on
220 * depending upon the current column.
223 simple_output &simple_output::space_or_newline (void)
225 if ((col + last_word.get_length() + 1 > max_line_length) && (newlines)) {
226 FPUTC('\n', fp);
227 if (last_word.get_length() > 0) {
228 col = last_word.flush(fp);
229 } else {
230 col = 0;
232 } else {
233 if (last_word.get_length() != 0) {
234 if (col > 0) {
235 FPUTC(' ', fp);
236 col++;
238 col += last_word.flush(fp);
241 return *this;
245 * force_nl - forces a newline.
248 simple_output &simple_output::force_nl (void)
250 space_or_newline();
251 col += last_word.flush(fp);
252 FPUTC('\n', fp);
253 col = 0;
254 return *this ;
258 * nl - writes a newline providing that we
259 * are not in the first column.
262 simple_output &simple_output::nl (void)
264 space_or_newline();
265 col += last_word.flush(fp);
266 FPUTC('\n', fp);
267 col = 0;
268 return *this ;
271 simple_output &simple_output::set_fixed_point(int n)
273 assert(n >= 0 && n <= 10);
274 fixed_point = n;
275 return *this;
278 simple_output &simple_output::put_raw_char(char c)
280 col += last_word.flush(fp);
281 PUTC(c, fp);
282 col++;
283 return *this;
286 simple_output &simple_output::put_string(const char *s, int n)
288 last_word.add_word(s, n);
289 return *this;
292 simple_output &simple_output::put_string(const char *s)
294 last_word.add_word(s, strlen(s));
295 return *this;
298 simple_output &simple_output::put_string(const string &s)
300 last_word.add_word(s.contents(), s.length());
301 return *this;
304 simple_output &simple_output::put_number(int n)
306 char buf[1 + INT_DIGITS + 1];
307 sprintf(buf, "%d", n);
308 put_string(buf);
309 return *this;
312 simple_output &simple_output::put_float(double d)
314 char buf[128];
316 sprintf(buf, "%.4f", d);
317 put_string(buf);
318 return *this;
321 simple_output &simple_output::enable_newlines (int auto_newlines)
323 check_newline(0);
324 newlines = auto_newlines;
325 check_newline(0);
326 return *this;
330 * flush_last_word - flushes the last word and adjusts the
331 * col position. It will insert a newline
332 * before the last word if allowed and if
333 * necessary.
336 void simple_output::flush_last_word (void)
338 int len=last_word.get_length();
340 if (len > 0) {
341 if (newlines) {
342 if (col + len + 1 > max_line_length) {
343 FPUTS("\n", fp);
344 col = 0;
345 } else {
346 FPUTS(" ", fp);
347 col++;
349 len += last_word.flush(fp);
350 } else {
351 FPUTS(" ", fp);
352 col++;
353 col += last_word.flush(fp);
358 // s-it2-mode