/contrib/groff/src/devices/grohtml/output.cpp

https://bitbucket.org/freebsd/freebsd-head/ · C++ · 367 lines · 245 code · 51 blank · 71 comment · 36 complexity · c31a404f7f2af4ecb714757fe99fb28b MD5 · raw file

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