output.cpp revision 114402
1247834Skib// -*- C++ -*- 2247834Skib/* Copyright (C) 2000, 2001, 2003 Free Software Foundation, Inc. 3247834Skib * 4247834Skib * Gaius Mulley (gaius@glam.ac.uk) wrote output.cpp 5247834Skib * but it owes a huge amount of ideas and raw code from 6247834Skib * James Clark (jjc@jclark.com) grops/ps.cpp. 7247834Skib * 8247834Skib * output.cpp 9247834Skib * 10247834Skib * provide the simple low level output routines needed by html.cpp 11247834Skib */ 12247834Skib 13247834Skib/* 14247834SkibThis file is part of groff. 15247834Skib 16247834Skibgroff is free software; you can redistribute it and/or modify it under 17247834Skibthe terms of the GNU General Public License as published by the Free 18247834SkibSoftware Foundation; either version 2, or (at your option) any later 19247834Skibversion. 20247834Skib 21247834Skibgroff is distributed in the hope that it will be useful, but WITHOUT ANY 22247834SkibWARRANTY; without even the implied warranty of MERCHANTABILITY or 23247834SkibFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 24247834Skibfor more details. 25247834Skib 26247834SkibYou should have received a copy of the GNU General Public License along 27247834Skibwith groff; see the file COPYING. If not, write to the Free Software 28247834SkibFoundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 29247834Skib 30247834Skib#include "driver.h" 31247834Skib#include "stringclass.h" 32247834Skib#include "cset.h" 33247834Skib 34247834Skib#include <time.h> 35247834Skib#include "html.h" 36247834Skib 37247834Skib#ifdef HAVE_UNISTD_H 38247834Skib#include <unistd.h> 39247834Skib#endif 40247834Skib 41247834Skib#undef DEBUGGING 42247834Skib// #define DEBUGGING 43247834Skib 44247834Skib#if !defined(TRUE) 45247834Skib# define TRUE (1==1) 46247834Skib#endif 47247834Skib#if !defined(FALSE) 48247834Skib# define FALSE (1==0) 49247834Skib#endif 50247834Skib 51247834Skib 52247834Skib#if defined(DEBUGGING) 53247834Skib# define FPUTC(X,Y) do { fputc((X),(Y)); fputc((X), stderr); fflush(stderr); } while (0) 54247834Skib# define FPUTS(X,Y) do { fputs((X),(Y)); fputs((X), stderr); fflush(stderr); } while (0) 55247834Skib# define PUTC(X,Y) do { putc((X),(Y)); putc((X), stderr); fflush(stderr); } while (0) 56247834Skib#else 57247834Skib# define FPUTC(X,Y) do { fputc((X),(Y)); } while (0) 58247834Skib# define FPUTS(X,Y) do { fputs((X),(Y)); } while (0) 59247834Skib# define PUTC(X,Y) do { putc((X),(Y)); } while (0) 60247834Skib#endif 61247834Skib 62247834Skib 63247834Skib/* 64247834Skib * word - initialise a word and set next to NULL 65247834Skib */ 66247839Sdumbbell 67247834Skibword::word (const char *w, int n) 68247834Skib : next(0) 69247834Skib{ 70247834Skib s = (char *)malloc(n+1); 71247834Skib strncpy(s, w, n); 72247834Skib s[n] = (char)0; 73247834Skib} 74247834Skib 75247834Skib/* 76247834Skib * destroy word and the string copy. 77247834Skib */ 78247834Skib 79282199Sdumbbellword::~word () 80282199Sdumbbell{ 81282199Sdumbbell free(s); 82282199Sdumbbell} 83282199Sdumbbell 84247834Skib/* 85247834Skib * word_list - create an empty word list. 86247834Skib */ 87247834Skib 88247834Skibword_list::word_list () 89247834Skib : length(0), head(0), tail(0) 90247834Skib{ 91247834Skib} 92247834Skib 93247834Skib/* 94247834Skib * flush - flush a word list to a FILE, f, and return the 95247834Skib * length of the buffered string. 96247834Skib */ 97247834Skib 98247834Skibint word_list::flush (FILE *f) 99247834Skib{ 100247834Skib word *t; 101282199Sdumbbell int len=length; 102247834Skib 103247834Skib while (head != 0) { 104247834Skib t = head; 105247834Skib head = head->next; 106247834Skib FPUTS(t->s, f); 107247834Skib delete t; 108247834Skib } 109247834Skib head = 0; 110247834Skib tail = 0; 111247834Skib length = 0; 112248060Sdumbbell#if defined(DEBUGGING) 113247834Skib fflush(f); // just for testing 114247834Skib#endif 115247834Skib return( len ); 116247834Skib} 117282199Sdumbbell 118/* 119 * add_word - adds a word to the outstanding word list. 120 */ 121 122void 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 138int word_list::get_length (void) 139{ 140 return( length ); 141} 142 143/* 144 * the classes and methods for simple_output manipulation 145 */ 146 147simple_output::simple_output(FILE *f, int n) 148: fp(f), max_line_length(n), col(0), fixed_point(0), newlines(0) 149{ 150} 151 152simple_output &simple_output::set_file(FILE *f) 153{ 154 if (fp) 155 fflush(fp); 156 fp = f; 157 return *this; 158} 159 160simple_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 168simple_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 178simple_output &simple_output::special(const char *) 179{ 180 return *this; 181} 182 183simple_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 195simple_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 207simple_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 220simple_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 234simple_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 * nl - writes a newline providing that we 257 * are not in the first column. 258 */ 259 260simple_output &simple_output::nl (void) 261{ 262 space_or_newline(); 263 col += last_word.flush(fp); 264 if (col != 0) { 265 FPUTC('\n', fp); 266 col = 0; 267 } 268 return *this ; 269} 270 271simple_output &simple_output::set_fixed_point(int n) 272{ 273 assert(n >= 0 && n <= 10); 274 fixed_point = n; 275 return *this; 276} 277 278simple_output &simple_output::put_raw_char(char c) 279{ 280 col += last_word.flush(fp); 281 PUTC(c, fp); 282 col++; 283 return *this; 284} 285 286simple_output &simple_output::put_string(const char *s, int n) 287{ 288 last_word.add_word(s, n); 289 return *this; 290} 291 292simple_output &simple_output::put_string(const char *s) 293{ 294 last_word.add_word(s, strlen(s)); 295 return *this; 296} 297 298simple_output &simple_output::put_string(const string &s) 299{ 300 last_word.add_word(s.contents(), s.length()); 301 return *this; 302} 303 304simple_output &simple_output::put_number(int n) 305{ 306 char buf[1 + INT_DIGITS + 1]; 307 sprintf(buf, "%d", n); 308 put_string(buf); 309 return *this; 310} 311 312simple_output &simple_output::put_float(double d) 313{ 314 char buf[128]; 315 316 sprintf(buf, "%.4f", d); 317 put_string(buf); 318 return *this; 319} 320 321simple_output &simple_output::enable_newlines (int auto_newlines) 322{ 323 check_newline(0); 324 newlines = auto_newlines; 325 check_newline(0); 326 return *this; 327} 328 329/* 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. 334 */ 335 336void simple_output::flush_last_word (void) 337{ 338 int len=last_word.get_length(); 339 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++; 348 } 349 len += last_word.flush(fp); 350 } else { 351 FPUTS(" ", fp); 352 col++; 353 col += last_word.flush(fp); 354 } 355 } 356} 357