1114402Sru// -*- C++ -*- 2151497Sru/* Copyright (C) 2000, 2001, 2003, 2004, 2005 Free Software Foundation, Inc. 3114402Sru * 4114402Sru * Gaius Mulley (gaius@glam.ac.uk) wrote output.cpp 5114402Sru * but it owes a huge amount of ideas and raw code from 6114402Sru * James Clark (jjc@jclark.com) grops/ps.cpp. 7114402Sru * 8114402Sru * output.cpp 9114402Sru * 10114402Sru * provide the simple low level output routines needed by html.cpp 11114402Sru */ 12114402Sru 13114402Sru/* 14114402SruThis file is part of groff. 15114402Sru 16114402Srugroff is free software; you can redistribute it and/or modify it under 17114402Sruthe terms of the GNU General Public License as published by the Free 18114402SruSoftware Foundation; either version 2, or (at your option) any later 19114402Sruversion. 20114402Sru 21114402Srugroff is distributed in the hope that it will be useful, but WITHOUT ANY 22114402SruWARRANTY; without even the implied warranty of MERCHANTABILITY or 23114402SruFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 24114402Srufor more details. 25114402Sru 26114402SruYou should have received a copy of the GNU General Public License along 27114402Sruwith groff; see the file COPYING. If not, write to the Free Software 28151497SruFoundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ 29114402Sru 30114402Sru#include "driver.h" 31114402Sru#include "stringclass.h" 32114402Sru#include "cset.h" 33114402Sru 34114402Sru#include <time.h> 35114402Sru#include "html.h" 36114402Sru 37114402Sru#ifdef HAVE_UNISTD_H 38114402Sru#include <unistd.h> 39114402Sru#endif 40114402Sru 41114402Sru#undef DEBUGGING 42114402Sru// #define DEBUGGING 43114402Sru 44114402Sru#if !defined(TRUE) 45114402Sru# define TRUE (1==1) 46114402Sru#endif 47114402Sru#if !defined(FALSE) 48114402Sru# define FALSE (1==0) 49114402Sru#endif 50114402Sru 51114402Sru 52114402Sru#if defined(DEBUGGING) 53114402Sru# define FPUTC(X,Y) do { fputc((X),(Y)); fputc((X), stderr); fflush(stderr); } while (0) 54114402Sru# define FPUTS(X,Y) do { fputs((X),(Y)); fputs((X), stderr); fflush(stderr); } while (0) 55114402Sru# define PUTC(X,Y) do { putc((X),(Y)); putc((X), stderr); fflush(stderr); } while (0) 56114402Sru#else 57114402Sru# define FPUTC(X,Y) do { fputc((X),(Y)); } while (0) 58114402Sru# define FPUTS(X,Y) do { fputs((X),(Y)); } while (0) 59114402Sru# define PUTC(X,Y) do { putc((X),(Y)); } while (0) 60114402Sru#endif 61114402Sru 62114402Sru 63114402Sru/* 64114402Sru * word - initialise a word and set next to NULL 65114402Sru */ 66114402Sru 67114402Sruword::word (const char *w, int n) 68114402Sru : next(0) 69114402Sru{ 70151497Sru s = new char[n+1]; 71114402Sru strncpy(s, w, n); 72114402Sru s[n] = (char)0; 73114402Sru} 74114402Sru 75114402Sru/* 76114402Sru * destroy word and the string copy. 77114402Sru */ 78114402Sru 79114402Sruword::~word () 80114402Sru{ 81151497Sru a_delete s; 82114402Sru} 83114402Sru 84114402Sru/* 85114402Sru * word_list - create an empty word list. 86114402Sru */ 87114402Sru 88114402Sruword_list::word_list () 89114402Sru : length(0), head(0), tail(0) 90114402Sru{ 91114402Sru} 92114402Sru 93114402Sru/* 94114402Sru * flush - flush a word list to a FILE, f, and return the 95114402Sru * length of the buffered string. 96114402Sru */ 97114402Sru 98114402Sruint word_list::flush (FILE *f) 99114402Sru{ 100114402Sru word *t; 101114402Sru int len=length; 102114402Sru 103114402Sru while (head != 0) { 104114402Sru t = head; 105114402Sru head = head->next; 106114402Sru FPUTS(t->s, f); 107114402Sru delete t; 108114402Sru } 109114402Sru head = 0; 110114402Sru tail = 0; 111114402Sru length = 0; 112114402Sru#if defined(DEBUGGING) 113114402Sru fflush(f); // just for testing 114114402Sru#endif 115114402Sru return( len ); 116114402Sru} 117114402Sru 118114402Sru/* 119114402Sru * add_word - adds a word to the outstanding word list. 120114402Sru */ 121114402Sru 122114402Sruvoid word_list::add_word (const char *s, int n) 123114402Sru{ 124114402Sru if (head == 0) { 125114402Sru head = new word(s, n); 126114402Sru tail = head; 127114402Sru } else { 128114402Sru tail->next = new word(s, n); 129114402Sru tail = tail->next; 130114402Sru } 131114402Sru length += n; 132114402Sru} 133114402Sru 134114402Sru/* 135114402Sru * get_length - returns the number of characters buffered 136114402Sru */ 137114402Sru 138114402Sruint word_list::get_length (void) 139114402Sru{ 140114402Sru return( length ); 141114402Sru} 142114402Sru 143114402Sru/* 144114402Sru * the classes and methods for simple_output manipulation 145114402Sru */ 146114402Sru 147114402Srusimple_output::simple_output(FILE *f, int n) 148114402Sru: fp(f), max_line_length(n), col(0), fixed_point(0), newlines(0) 149114402Sru{ 150114402Sru} 151114402Sru 152114402Srusimple_output &simple_output::set_file(FILE *f) 153114402Sru{ 154114402Sru if (fp) 155114402Sru fflush(fp); 156114402Sru fp = f; 157114402Sru return *this; 158114402Sru} 159114402Sru 160114402Srusimple_output &simple_output::copy_file(FILE *infp) 161114402Sru{ 162114402Sru int c; 163114402Sru while ((c = getc(infp)) != EOF) 164114402Sru PUTC(c, fp); 165114402Sru return *this; 166114402Sru} 167114402Sru 168114402Srusimple_output &simple_output::end_line() 169114402Sru{ 170114402Sru flush_last_word(); 171114402Sru if (col != 0) { 172114402Sru PUTC('\n', fp); 173114402Sru col = 0; 174114402Sru } 175114402Sru return *this; 176114402Sru} 177114402Sru 178114402Srusimple_output &simple_output::special(const char *) 179114402Sru{ 180114402Sru return *this; 181114402Sru} 182114402Sru 183114402Srusimple_output &simple_output::simple_comment(const char *s) 184114402Sru{ 185114402Sru flush_last_word(); 186114402Sru if (col != 0) 187114402Sru PUTC('\n', fp); 188114402Sru FPUTS("<!-- ", fp); 189114402Sru FPUTS(s, fp); 190114402Sru FPUTS(" -->\n", fp); 191114402Sru col = 0; 192114402Sru return *this; 193114402Sru} 194114402Sru 195114402Srusimple_output &simple_output::begin_comment(const char *s) 196114402Sru{ 197114402Sru flush_last_word(); 198114402Sru if (col != 0) 199114402Sru PUTC('\n', fp); 200114402Sru col = 0; 201114402Sru put_string("<!--"); 202114402Sru space_or_newline(); 203114402Sru last_word.add_word(s, strlen(s)); 204114402Sru return *this; 205114402Sru} 206114402Sru 207114402Srusimple_output &simple_output::end_comment() 208114402Sru{ 209114402Sru flush_last_word(); 210114402Sru space_or_newline(); 211114402Sru put_string("-->").nl(); 212114402Sru return *this; 213114402Sru} 214114402Sru 215114402Sru/* 216114402Sru * check_newline - checks to see whether we are able to issue 217114402Sru * a newline and that one is needed. 218114402Sru */ 219114402Sru 220114402Srusimple_output &simple_output::check_newline(int n) 221114402Sru{ 222114402Sru if ((col + n + last_word.get_length() + 1 > max_line_length) && (newlines)) { 223114402Sru FPUTC('\n', fp); 224114402Sru col = last_word.flush(fp); 225114402Sru } 226114402Sru return *this; 227114402Sru} 228114402Sru 229114402Sru/* 230114402Sru * space_or_newline - will emit a newline or a space later on 231114402Sru * depending upon the current column. 232114402Sru */ 233114402Sru 234114402Srusimple_output &simple_output::space_or_newline (void) 235114402Sru{ 236114402Sru if ((col + last_word.get_length() + 1 > max_line_length) && (newlines)) { 237114402Sru FPUTC('\n', fp); 238114402Sru if (last_word.get_length() > 0) { 239114402Sru col = last_word.flush(fp); 240114402Sru } else { 241114402Sru col = 0; 242114402Sru } 243114402Sru } else { 244114402Sru if (last_word.get_length() != 0) { 245114402Sru if (col > 0) { 246114402Sru FPUTC(' ', fp); 247114402Sru col++; 248114402Sru } 249114402Sru col += last_word.flush(fp); 250114402Sru } 251114402Sru } 252114402Sru return *this; 253114402Sru} 254114402Sru 255114402Sru/* 256151497Sru * force_nl - forces a newline. 257151497Sru */ 258151497Sru 259151497Srusimple_output &simple_output::force_nl (void) 260151497Sru{ 261151497Sru space_or_newline(); 262151497Sru col += last_word.flush(fp); 263151497Sru FPUTC('\n', fp); 264151497Sru col = 0; 265151497Sru return *this ; 266151497Sru} 267151497Sru 268151497Sru/* 269114402Sru * nl - writes a newline providing that we 270114402Sru * are not in the first column. 271114402Sru */ 272114402Sru 273114402Srusimple_output &simple_output::nl (void) 274114402Sru{ 275114402Sru space_or_newline(); 276114402Sru col += last_word.flush(fp); 277151497Sru FPUTC('\n', fp); 278151497Sru col = 0; 279114402Sru return *this ; 280114402Sru} 281114402Sru 282114402Srusimple_output &simple_output::set_fixed_point(int n) 283114402Sru{ 284114402Sru assert(n >= 0 && n <= 10); 285114402Sru fixed_point = n; 286114402Sru return *this; 287114402Sru} 288114402Sru 289114402Srusimple_output &simple_output::put_raw_char(char c) 290114402Sru{ 291114402Sru col += last_word.flush(fp); 292114402Sru PUTC(c, fp); 293114402Sru col++; 294114402Sru return *this; 295114402Sru} 296114402Sru 297114402Srusimple_output &simple_output::put_string(const char *s, int n) 298114402Sru{ 299114402Sru last_word.add_word(s, n); 300114402Sru return *this; 301114402Sru} 302114402Sru 303114402Srusimple_output &simple_output::put_string(const char *s) 304114402Sru{ 305114402Sru last_word.add_word(s, strlen(s)); 306114402Sru return *this; 307114402Sru} 308114402Sru 309114402Srusimple_output &simple_output::put_string(const string &s) 310114402Sru{ 311114402Sru last_word.add_word(s.contents(), s.length()); 312114402Sru return *this; 313114402Sru} 314114402Sru 315114402Srusimple_output &simple_output::put_number(int n) 316114402Sru{ 317114402Sru char buf[1 + INT_DIGITS + 1]; 318114402Sru sprintf(buf, "%d", n); 319114402Sru put_string(buf); 320114402Sru return *this; 321114402Sru} 322114402Sru 323114402Srusimple_output &simple_output::put_float(double d) 324114402Sru{ 325114402Sru char buf[128]; 326114402Sru 327114402Sru sprintf(buf, "%.4f", d); 328114402Sru put_string(buf); 329114402Sru return *this; 330114402Sru} 331114402Sru 332114402Srusimple_output &simple_output::enable_newlines (int auto_newlines) 333114402Sru{ 334114402Sru check_newline(0); 335114402Sru newlines = auto_newlines; 336114402Sru check_newline(0); 337114402Sru return *this; 338114402Sru} 339114402Sru 340114402Sru/* 341114402Sru * flush_last_word - flushes the last word and adjusts the 342114402Sru * col position. It will insert a newline 343114402Sru * before the last word if allowed and if 344114402Sru * necessary. 345114402Sru */ 346114402Sru 347114402Sruvoid simple_output::flush_last_word (void) 348114402Sru{ 349114402Sru int len=last_word.get_length(); 350114402Sru 351114402Sru if (len > 0) { 352114402Sru if (newlines) { 353114402Sru if (col + len + 1 > max_line_length) { 354114402Sru FPUTS("\n", fp); 355114402Sru col = 0; 356114402Sru } else { 357114402Sru FPUTS(" ", fp); 358114402Sru col++; 359114402Sru } 360114402Sru len += last_word.flush(fp); 361114402Sru } else { 362114402Sru FPUTS(" ", fp); 363114402Sru col++; 364114402Sru col += last_word.flush(fp); 365114402Sru } 366114402Sru } 367114402Sru} 368