summaryrefslogtreecommitdiffstats
path: root/src/devices/grohtml/output.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/grohtml/output.cpp')
-rw-r--r--src/devices/grohtml/output.cpp363
1 files changed, 363 insertions, 0 deletions
diff --git a/src/devices/grohtml/output.cpp b/src/devices/grohtml/output.cpp
new file mode 100644
index 0000000..0ffeb58
--- /dev/null
+++ b/src/devices/grohtml/output.cpp
@@ -0,0 +1,363 @@
+// -*- C++ -*-
+/* Copyright (C) 2000-2020 Free Software Foundation, Inc.
+ *
+ * Gaius Mulley (gaius@glam.ac.uk) wrote output.cpp
+ * but it owes a huge amount of ideas and raw code from
+ * James Clark (jjc@jclark.com) grops/ps.cpp.
+ *
+ * output.cpp
+ *
+ * provide the simple low level output routines needed by html.cpp
+ */
+
+/*
+This file is part of groff.
+
+groff is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "driver.h"
+#include "stringclass.h"
+#include "cset.h"
+
+#include <time.h>
+#include "html.h"
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#if !defined(TRUE)
+# define TRUE (1==1)
+#endif
+#if !defined(FALSE)
+# define FALSE (1==0)
+#endif
+
+
+#if defined(DEBUGGING)
+# define FPUTC(X,Y) do { fputc((X),(Y)); fputc((X), stderr); fflush(stderr); } while (0)
+# define FPUTS(X,Y) do { fputs((X),(Y)); fputs((X), stderr); fflush(stderr); } while (0)
+# define PUTC(X,Y) do { putc((X),(Y)); putc((X), stderr); fflush(stderr); } while (0)
+#else
+# define FPUTC(X,Y) do { fputc((X),(Y)); } while (0)
+# define FPUTS(X,Y) do { fputs((X),(Y)); } while (0)
+# define PUTC(X,Y) do { putc((X),(Y)); } while (0)
+#endif
+
+
+/*
+ * word - initialise a word and set next to NULL
+ */
+
+word::word (const char *w, int n)
+ : next(0)
+{
+ s = new char[n+1];
+ strncpy(s, w, n);
+ s[n] = (char)0;
+}
+
+/*
+ * destroy word and the string copy.
+ */
+
+word::~word ()
+{
+ delete[] s;
+}
+
+/*
+ * word_list - create an empty word list.
+ */
+
+word_list::word_list ()
+ : length(0), head(0), tail(0)
+{
+}
+
+/*
+ * flush - flush a word list to a FILE, f, and return the
+ * length of the buffered string.
+ */
+
+int word_list::flush (FILE *f)
+{
+ word *t;
+ int len=length;
+
+ while (head != 0) {
+ t = head;
+ head = head->next;
+ FPUTS(t->s, f);
+ delete t;
+ }
+ head = 0;
+ tail = 0;
+ length = 0;
+#if defined(DEBUGGING)
+ fflush(f); // just for testing
+#endif
+ return( len );
+}
+
+/*
+ * add_word - adds a word to the outstanding word list.
+ */
+
+void word_list::add_word (const char *s, int n)
+{
+ if (head == 0) {
+ head = new word(s, n);
+ tail = head;
+ } else {
+ tail->next = new word(s, n);
+ tail = tail->next;
+ }
+ length += n;
+}
+
+/*
+ * get_length - returns the number of characters buffered
+ */
+
+int word_list::get_length (void)
+{
+ return( length );
+}
+
+/*
+ * the classes and methods for simple_output manipulation
+ */
+
+simple_output::simple_output(FILE *f, int n)
+: fp(f), max_line_length(n), col(0), fixed_point(0), newlines(0)
+{
+}
+
+simple_output &simple_output::set_file(FILE *f)
+{
+ if (fp)
+ fflush(fp);
+ fp = f;
+ return *this;
+}
+
+simple_output &simple_output::copy_file(FILE *infp)
+{
+ int c;
+ while ((c = getc(infp)) != EOF)
+ PUTC(c, fp);
+ return *this;
+}
+
+simple_output &simple_output::end_line()
+{
+ flush_last_word();
+ if (col != 0) {
+ PUTC('\n', fp);
+ col = 0;
+ }
+ return *this;
+}
+
+simple_output &simple_output::special(const char *)
+{
+ return *this;
+}
+
+simple_output &simple_output::simple_comment(const char *s)
+{
+ flush_last_word();
+ if (col != 0)
+ PUTC('\n', fp);
+ FPUTS("<!-- ", fp);
+ FPUTS(s, fp);
+ FPUTS(" -->\n", fp);
+ col = 0;
+ return *this;
+}
+
+simple_output &simple_output::begin_comment(const char *s)
+{
+ flush_last_word();
+ if (col != 0)
+ PUTC('\n', fp);
+ col = 0;
+ put_string("<!--");
+ space_or_newline();
+ last_word.add_word(s, strlen(s));
+ return *this;
+}
+
+simple_output &simple_output::end_comment()
+{
+ flush_last_word();
+ space_or_newline();
+ put_string("-->").nl();
+ return *this;
+}
+
+/*
+ * check_newline - checks to see whether we are able to issue
+ * a newline and that one is needed.
+ */
+
+simple_output &simple_output::check_newline(int n)
+{
+ if ((col + n + last_word.get_length() + 1 > max_line_length) && (newlines)) {
+ FPUTC('\n', fp);
+ col = last_word.flush(fp);
+ }
+ return *this;
+}
+
+/*
+ * space_or_newline - will emit a newline or a space later on
+ * depending upon the current column.
+ */
+
+simple_output &simple_output::space_or_newline (void)
+{
+ if ((col + last_word.get_length() + 1 > max_line_length) && (newlines)) {
+ FPUTC('\n', fp);
+ if (last_word.get_length() > 0) {
+ col = last_word.flush(fp);
+ } else {
+ col = 0;
+ }
+ } else {
+ if (last_word.get_length() != 0) {
+ if (col > 0) {
+ FPUTC(' ', fp);
+ col++;
+ }
+ col += last_word.flush(fp);
+ }
+ }
+ return *this;
+}
+
+/*
+ * force_nl - forces a newline.
+ */
+
+simple_output &simple_output::force_nl (void)
+{
+ space_or_newline();
+ col += last_word.flush(fp);
+ FPUTC('\n', fp);
+ col = 0;
+ return *this ;
+}
+
+/*
+ * nl - writes a newline providing that we
+ * are not in the first column.
+ */
+
+simple_output &simple_output::nl (void)
+{
+ space_or_newline();
+ col += last_word.flush(fp);
+ FPUTC('\n', fp);
+ col = 0;
+ return *this ;
+}
+
+simple_output &simple_output::set_fixed_point(int n)
+{
+ assert(n >= 0 && n <= 10);
+ fixed_point = n;
+ return *this;
+}
+
+simple_output &simple_output::put_raw_char(char c)
+{
+ col += last_word.flush(fp);
+ PUTC(c, fp);
+ col++;
+ return *this;
+}
+
+simple_output &simple_output::put_string(const char *s, int n)
+{
+ last_word.add_word(s, n);
+ return *this;
+}
+
+simple_output &simple_output::put_string(const char *s)
+{
+ last_word.add_word(s, strlen(s));
+ return *this;
+}
+
+simple_output &simple_output::put_string(const string &s)
+{
+ last_word.add_word(s.contents(), s.length());
+ return *this;
+}
+
+simple_output &simple_output::put_number(int n)
+{
+ char buf[1 + INT_DIGITS + 1];
+ sprintf(buf, "%d", n);
+ put_string(buf);
+ return *this;
+}
+
+simple_output &simple_output::put_float(double d)
+{
+ char buf[128];
+
+ sprintf(buf, "%.4f", d);
+ put_string(buf);
+ return *this;
+}
+
+simple_output &simple_output::enable_newlines (int auto_newlines)
+{
+ check_newline(0);
+ newlines = auto_newlines;
+ check_newline(0);
+ return *this;
+}
+
+/*
+ * flush_last_word - flushes the last word and adjusts the
+ * col position. It will insert a newline
+ * before the last word if allowed and if
+ * necessary.
+ */
+
+void simple_output::flush_last_word (void)
+{
+ int len=last_word.get_length();
+
+ if (len > 0) {
+ if (newlines) {
+ if (col + len + 1 > max_line_length) {
+ FPUTS("\n", fp);
+ col = 0;
+ } else {
+ FPUTS(" ", fp);
+ col++;
+ }
+ len += last_word.flush(fp);
+ } else {
+ FPUTS(" ", fp);
+ col++;
+ col += last_word.flush(fp);
+ }
+ }
+}