summaryrefslogtreecommitdiffstats
path: root/contrib/groff/src/devices
diff options
context:
space:
mode:
authorru <ru@FreeBSD.org>2003-05-01 13:15:22 +0000
committerru <ru@FreeBSD.org>2003-05-01 13:15:22 +0000
commit1a17e98fb2e3ecba5ba136f8d1ae8d39061d2f65 (patch)
treee6cd9552c06f55c81873906321c3f600223592c7 /contrib/groff/src/devices
parentc96557721be60d942f4d486b9ea7f9b7cbb034cc (diff)
downloadFreeBSD-src-1a17e98fb2e3ecba5ba136f8d1ae8d39061d2f65.zip
FreeBSD-src-1a17e98fb2e3ecba5ba136f8d1ae8d39061d2f65.tar.gz
Removed files not present in v1.19 import.
Diffstat (limited to 'contrib/groff/src/devices')
-rw-r--r--contrib/groff/src/devices/grodvi/dvi.cc947
-rw-r--r--contrib/groff/src/devices/grohtml/html-table.cc687
-rw-r--r--contrib/groff/src/devices/grohtml/html-text.cc964
-rw-r--r--contrib/groff/src/devices/grohtml/output.cc356
-rw-r--r--contrib/groff/src/devices/grohtml/post-html.cc3745
-rw-r--r--contrib/groff/src/devices/grolbp/lbp.cc740
-rw-r--r--contrib/groff/src/devices/grolj4/lj4.cc708
-rw-r--r--contrib/groff/src/devices/grops/ps.cc1642
-rw-r--r--contrib/groff/src/devices/grops/psrm.cc1147
-rw-r--r--contrib/groff/src/devices/grotty/tty.cc776
10 files changed, 0 insertions, 11712 deletions
diff --git a/contrib/groff/src/devices/grodvi/dvi.cc b/contrib/groff/src/devices/grodvi/dvi.cc
deleted file mode 100644
index 8412636..0000000
--- a/contrib/groff/src/devices/grodvi/dvi.cc
+++ /dev/null
@@ -1,947 +0,0 @@
-// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001, 2002
- Free Software Foundation, Inc.
- Written by James Clark (jjc@jclark.com)
-
-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 2, 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 groff; see the file COPYING. If not, write to the Free Software
-Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#include "driver.h"
-#include "nonposix.h"
-
-extern "C" const char *Version_string;
-
-#define DEFAULT_LINEWIDTH 40
-static int linewidth = DEFAULT_LINEWIDTH;
-
-static int draw_flag = 1;
-
-/* These values were chosen because:
-
-(MULTIPLIER*SIZESCALE)/(RES*UNITWIDTH) == 1/(2^20 * 72.27)
-
-and 57816 is an exact multiple of both 72.27*SIZESCALE and 72.
-
-The width in the groff font file is the product of MULTIPLIER and the
-width in the tfm file. */
-
-#define RES 57816
-#define RES_7227 (RES/7227)
-#define UNITWIDTH 131072
-#define SIZESCALE 100
-#define MULTIPLIER 1
-
-class dvi_font : public font {
- dvi_font(const char *);
-public:
- int checksum;
- int design_size;
- ~dvi_font();
- void handle_unknown_font_command(const char *command, const char *arg,
- const char *filename, int lineno);
- static dvi_font *load_dvi_font(const char *);
-};
-
-dvi_font *dvi_font::load_dvi_font(const char *s)
-{
- dvi_font *f = new dvi_font(s);
- if (!f->load()) {
- delete f;
- return 0;
- }
- return f;
-}
-
-dvi_font::dvi_font(const char *nm)
-: font(nm), checksum(0), design_size(0)
-{
-}
-
-dvi_font::~dvi_font()
-{
-}
-
-void dvi_font::handle_unknown_font_command(const char *command,
- const char *arg,
- const char *filename, int lineno)
-{
- char *ptr;
- if (strcmp(command, "checksum") == 0) {
- if (arg == 0)
- fatal_with_file_and_line(filename, lineno,
- "`checksum' command requires an argument");
- checksum = int(strtol(arg, &ptr, 10));
- if (checksum == 0 && ptr == arg) {
- fatal_with_file_and_line(filename, lineno, "bad checksum");
- }
- }
- else if (strcmp(command, "designsize") == 0) {
- if (arg == 0)
- fatal_with_file_and_line(filename, lineno,
- "`designsize' command requires an argument");
- design_size = int(strtol(arg, &ptr, 10));
- if (design_size == 0 && ptr == arg) {
- fatal_with_file_and_line(filename, lineno, "bad design size");
- }
- }
-}
-
-#define FONTS_MAX 256
-
-struct output_font {
- dvi_font *f;
- int point_size;
- output_font() : f(0) { }
-};
-
-class dvi_printer : public printer {
- FILE *fp;
- int max_drift;
- int byte_count;
- int last_bop;
- int page_count;
- int cur_h;
- int cur_v;
- int end_h;
- int max_h;
- int max_v;
- output_font output_font_table[FONTS_MAX];
- font *cur_font;
- int cur_point_size;
- color cur_color;
- int pushed;
- int pushed_h;
- int pushed_v;
- int have_pushed;
- void preamble();
- void postamble();
- void define_font(int);
- void set_font(int);
- void possibly_begin_line();
- void set_color(color *);
-protected:
- enum {
- id_byte = 2,
- set1 = 128,
- put1 = 133,
- put_rule = 137,
- bop = 139,
- eop = 140,
- push = 141,
- pop = 142,
- right1 = 143,
- down1 = 157,
- fnt_num_0 = 171,
- fnt1 = 235,
- xxx1 = 239,
- fnt_def1 = 243,
- pre = 247,
- post = 248,
- post_post = 249,
- filler = 223
- };
- int line_thickness;
-
- void out1(int);
- void out2(int);
- void out3(int);
- void out4(int);
- void moveto(int, int);
- void out_string(const char *);
- void out_signed(unsigned char, int);
- void out_unsigned(unsigned char, int);
- void do_special(const char *);
-public:
- dvi_printer();
- ~dvi_printer();
- font *make_font(const char *);
- void begin_page(int);
- void end_page(int);
- void set_char(int, font *, const environment *, int w, const char *name);
- void special(char *arg, const environment *env, char type);
- void end_of_line();
- void draw(int code, int *p, int np, const environment *env);
-};
-
-
-class draw_dvi_printer : public dvi_printer {
- int output_pen_size;
- void set_line_thickness(const environment *);
- void fill_next(const environment *);
-public:
- draw_dvi_printer();
- ~draw_dvi_printer();
- void draw(int code, int *p, int np, const environment *env);
- void end_page(int);
-};
-
-dvi_printer::dvi_printer()
-: fp(stdout), byte_count(0), last_bop(-1), page_count(0), max_h(0), max_v(0),
- cur_font(0), cur_point_size(-1), pushed(0), line_thickness(-1)
-{
- if (font::res != RES)
- fatal("resolution must be %1", RES);
- if (font::unitwidth != UNITWIDTH)
- fatal("unitwidth must be %1", UNITWIDTH);
- if (font::hor != 1)
- fatal("hor must be equal to 1");
- if (font::vert != 1)
- fatal("vert must be equal to 1");
- if (font::sizescale != SIZESCALE)
- fatal("sizescale must be equal to %1", SIZESCALE);
- max_drift = font::res/1000; // this is fairly arbitrary
- preamble();
-}
-
-dvi_printer::~dvi_printer()
-{
- postamble();
-}
-
-
-draw_dvi_printer::draw_dvi_printer()
-: output_pen_size(-1)
-{
-}
-
-draw_dvi_printer::~draw_dvi_printer()
-{
-}
-
-
-void dvi_printer::out1(int n)
-{
- byte_count += 1;
- putc(n & 0xff, fp);
-}
-
-void dvi_printer::out2(int n)
-{
- byte_count += 2;
- putc((n >> 8) & 0xff, fp);
- putc(n & 0xff, fp);
-}
-
-void dvi_printer::out3(int n)
-{
- byte_count += 3;
- putc((n >> 16) & 0xff, fp);
- putc((n >> 8) & 0xff, fp);
- putc(n & 0xff, fp);
-}
-
-void dvi_printer::out4(int n)
-{
- byte_count += 4;
- putc((n >> 24) & 0xff, fp);
- putc((n >> 16) & 0xff, fp);
- putc((n >> 8) & 0xff, fp);
- putc(n & 0xff, fp);
-}
-
-void dvi_printer::out_string(const char *s)
-{
- out1(strlen(s));
- while (*s != 0)
- out1(*s++);
-}
-
-
-void dvi_printer::end_of_line()
-{
- if (pushed) {
- out1(pop);
- pushed = 0;
- cur_h = pushed_h;
- cur_v = pushed_v;
- }
-}
-
-void dvi_printer::possibly_begin_line()
-{
- if (!pushed) {
- have_pushed = pushed = 1;
- pushed_h = cur_h;
- pushed_v = cur_v;
- out1(push);
- }
-}
-
-int scale(int x, int z)
-{
- int sw;
- int a, b, c, d;
- int alpha, beta;
- alpha = 16*z; beta = 16;
- while (z >= 040000000L) {
- z /= 2; beta /= 2;
- }
- d = x & 255;
- c = (x >> 8) & 255;
- b = (x >> 16) & 255;
- a = (x >> 24) & 255;
- sw = (((((d * z) / 0400) + (c * z)) / 0400) + (b * z)) / beta;
- if (a == 255)
- sw -= alpha;
- else
- assert(a == 0);
- return sw;
-}
-
-void dvi_printer::set_color(color *col)
-{
- cur_color = *col;
- char buf[256];
- unsigned int components[4];
- color_scheme cs = col->get_components(components);
- switch (cs) {
- case DEFAULT:
- sprintf(buf, "color gray 0");
- break;
- case RGB:
- sprintf(buf, "color rgb %.3g %.3g %.3g",
- double(Red) / color::MAX_COLOR_VAL,
- double(Green) / color::MAX_COLOR_VAL,
- double(Blue) / color::MAX_COLOR_VAL);
- break;
- case CMY:
- col->get_cmyk(&Cyan, &Magenta, &Yellow, &Black);
- // fall through
- case CMYK:
- sprintf(buf, "color cmyk %.3g %.3g %.3g %.3g",
- double(Cyan) / color::MAX_COLOR_VAL,
- double(Magenta) / color::MAX_COLOR_VAL,
- double(Yellow) / color::MAX_COLOR_VAL,
- double(Black) / color::MAX_COLOR_VAL);
- break;
- case GRAY:
- sprintf(buf, "color gray %.3g",
- double(Gray) / color::MAX_COLOR_VAL);
- break;
- }
- do_special(buf);
-}
-
-void dvi_printer::set_char(int index, font *f, const environment *env,
- int w, const char *name)
-{
- if (*env->col != cur_color)
- set_color(env->col);
- int code = f->get_code(index);
- if (env->size != cur_point_size || f != cur_font) {
- cur_font = f;
- cur_point_size = env->size;
- int i;
- for (i = 0;; i++) {
- if (i >= FONTS_MAX) {
- fatal("too many output fonts required");
- }
- if (output_font_table[i].f == 0) {
- output_font_table[i].f = (dvi_font *)cur_font;
- output_font_table[i].point_size = cur_point_size;
- define_font(i);
- }
- if (output_font_table[i].f == cur_font
- && output_font_table[i].point_size == cur_point_size)
- break;
- }
- set_font(i);
- }
- int distance = env->hpos - cur_h;
- if (env->hpos != end_h && distance != 0) {
- out_signed(right1, distance);
- cur_h = env->hpos;
- }
- else if (distance > max_drift) {
- out_signed(right1, distance - max_drift);
- cur_h = env->hpos - max_drift;
- }
- else if (distance < -max_drift) {
- out_signed(right1, distance + max_drift);
- cur_h = env->hpos + max_drift;
- }
- if (env->vpos != cur_v) {
- out_signed(down1, env->vpos - cur_v);
- cur_v = env->vpos;
- }
- possibly_begin_line();
- end_h = env->hpos + w;
- cur_h += scale(f->get_width(index, UNITWIDTH)/MULTIPLIER,
- cur_point_size*RES_7227);
- if (cur_h > max_h)
- max_h = cur_h;
- if (cur_v > max_v)
- max_v = cur_v;
- if (code >= 0 && code <= 127)
- out1(code);
- else
- out_unsigned(set1, code);
-}
-
-void dvi_printer::define_font(int i)
-{
- out_unsigned(fnt_def1, i);
- dvi_font *f = output_font_table[i].f;
- out4(f->checksum);
- out4(output_font_table[i].point_size*RES_7227);
- out4(int((double(f->design_size)/(1<<20))*RES_7227*100 + .5));
- const char *nm = f->get_internal_name();
- out1(0);
- out_string(nm);
-}
-
-void dvi_printer::set_font(int i)
-{
- if (i >= 0 && i <= 63)
- out1(fnt_num_0 + i);
- else
- out_unsigned(fnt1, i);
-}
-
-void dvi_printer::out_signed(unsigned char base, int param)
-{
- if (-128 <= param && param < 128) {
- out1(base);
- out1(param);
- }
- else if (-32768 <= param && param < 32768) {
- out1(base+1);
- out2(param);
- }
- else if (-(1 << 23) <= param && param < (1 << 23)) {
- out1(base+2);
- out3(param);
- }
- else {
- out1(base+3);
- out4(param);
- }
-}
-
-void dvi_printer::out_unsigned(unsigned char base, int param)
-{
- if (param >= 0) {
- if (param < 256) {
- out1(base);
- out1(param);
- }
- else if (param < 65536) {
- out1(base+1);
- out2(param);
- }
- else if (param < (1 << 24)) {
- out1(base+2);
- out3(param);
- }
- else {
- out1(base+3);
- out4(param);
- }
- }
- else {
- out1(base+3);
- out4(param);
- }
-}
-
-void dvi_printer::preamble()
-{
- out1(pre);
- out1(id_byte);
- out4(254000);
- out4(font::res);
- out4(1000);
- out1(0);
-}
-
-void dvi_printer::postamble()
-{
- int tem = byte_count;
- out1(post);
- out4(last_bop);
- out4(254000);
- out4(font::res);
- out4(1000);
- out4(max_v);
- out4(max_h);
- out2(have_pushed); // stack depth
- out2(page_count);
- int i;
- for (i = 0; i < FONTS_MAX && output_font_table[i].f != 0; i++)
- define_font(i);
- out1(post_post);
- out4(tem);
- out1(id_byte);
- for (i = 0; i < 4 || byte_count % 4 != 0; i++)
- out1(filler);
-}
-
-void dvi_printer::begin_page(int i)
-{
- page_count++;
- int tem = byte_count;
- out1(bop);
- out4(i);
- for (int j = 1; j < 10; j++)
- out4(0);
- out4(last_bop);
- last_bop = tem;
- if (cur_color != default_color)
- set_color(&cur_color);
- // By convention position (0,0) in a dvi file is placed at (1in, 1in).
- cur_h = font::res;
- cur_v = font::res;
- end_h = 0;
-}
-
-void dvi_printer::end_page(int)
-{
- set_color(&default_color);
- if (pushed)
- end_of_line();
- out1(eop);
- cur_font = 0;
-}
-
-void draw_dvi_printer::end_page(int len)
-{
- dvi_printer::end_page(len);
- output_pen_size = -1;
-}
-
-void dvi_printer::do_special(const char *s)
-{
- int len = strlen(s);
- if (len == 0)
- return;
- possibly_begin_line();
- out_unsigned(xxx1, len);
- while (*s)
- out1(*s++);
-}
-
-void dvi_printer::special(char *arg, const environment *env, char type)
-{
- if (type != 'p')
- return;
- moveto(env->hpos, env->vpos);
- do_special(arg);
-}
-
-void dvi_printer::moveto(int h, int v)
-{
- if (h != cur_h) {
- out_signed(right1, h - cur_h);
- cur_h = h;
- if (cur_h > max_h)
- max_h = cur_h;
- }
- if (v != cur_v) {
- out_signed(down1, v - cur_v);
- cur_v = v;
- if (cur_v > max_v)
- max_v = cur_v;
- }
- end_h = 0;
-}
-
-void dvi_printer::draw(int code, int *p, int np, const environment *env)
-{
- if (code == 'l') {
- int x = 0, y = 0;
- int height = 0, width = 0;
- int thickness;
- if (line_thickness < 0)
- thickness = env->size*RES_7227*linewidth/1000;
- else if (line_thickness > 0)
- thickness = line_thickness;
- else
- thickness = 1;
- if (np != 2) {
- error("2 arguments required for line");
- }
- else if (p[0] == 0) {
- // vertical rule
- if (p[1] > 0) {
- x = env->hpos - thickness/2;
- y = env->vpos + p[1] + thickness/2;
- height = p[1] + thickness;
- width = thickness;
- }
- else if (p[1] < 0) {
- x = env->hpos - thickness/2;
- y = env->vpos + thickness/2;
- height = thickness - p[1];
- width = thickness;
- }
- }
- else if (p[1] == 0) {
- if (p[0] > 0) {
- x = env->hpos - thickness/2;
- y = env->vpos + thickness/2;
- height = thickness;
- width = p[0] + thickness;
- }
- else if (p[0] < 0) {
- x = env->hpos - p[0] - thickness/2;
- y = env->vpos + thickness/2;
- height = thickness;
- width = thickness - p[0];
- }
- }
- if (height != 0) {
- moveto(x, y);
- out1(put_rule);
- out4(height);
- out4(width);
- }
- }
- else if (code == 't') {
- if (np == 0) {
- line_thickness = -1;
- }
- else {
- // troff gratuitously adds an extra 0
- if (np != 1 && np != 2)
- error("0 or 1 argument required for thickness");
- else
- line_thickness = p[0];
- }
- }
- else if (code == 'R') {
- if (np != 2)
- error("2 arguments required for rule");
- else if (p[0] != 0 || p[1] != 0) {
- int dh = p[0];
- int dv = p[1];
- int oh = env->hpos;
- int ov = env->vpos;
- if (dv > 0) {
- ov += dv;
- dv = -dv;
- }
- if (dh < 0) {
- oh += dh;
- dh = -dh;
- }
- moveto(oh, ov);
- out1(put_rule);
- out4(-dv);
- out4(dh);
- }
- }
-}
-
-// XXX Will this overflow?
-
-inline int milliinches(int n)
-{
- return (n*1000 + font::res/2)/font::res;
-}
-
-void draw_dvi_printer::set_line_thickness(const environment *env)
-{
- int desired_pen_size
- = milliinches(line_thickness < 0
- // Will this overflow?
- ? env->size*RES_7227*linewidth/1000
- : line_thickness);
- if (desired_pen_size != output_pen_size) {
- char buf[256];
- sprintf(buf, "pn %d", desired_pen_size);
- do_special(buf);
- output_pen_size = desired_pen_size;
- }
-}
-
-void draw_dvi_printer::fill_next(const environment *env)
-{
- unsigned int g;
- if (env->fill->is_default())
- g = 0;
- else {
- // currently, only BW support
- env->fill->get_gray(&g);
- }
- char buf[256];
- sprintf(buf, "sh %.3g", 1 - double(g)/color::MAX_COLOR_VAL);
- do_special(buf);
-}
-
-void draw_dvi_printer::draw(int code, int *p, int np, const environment *env)
-{
- char buf[1024];
- int fill_flag = 0;
- switch (code) {
- case 'C':
- fill_flag = 1;
- // fall through
- case 'c':
- // troff adds an extra argument to C
- if (np != 1 && !(code == 'C' && np == 2)) {
- error("1 argument required for circle");
- break;
- }
- moveto(env->hpos+p[0]/2, env->vpos);
- if (fill_flag)
- fill_next(env);
- else
- set_line_thickness(env);
- int rad;
- rad = milliinches(p[0]/2);
- sprintf(buf, "%s 0 0 %d %d 0 6.28319",
- (fill_flag ? "ia" : "ar"),
- rad,
- rad);
- do_special(buf);
- break;
- case 'l':
- if (np != 2) {
- error("2 arguments required for line");
- break;
- }
- moveto(env->hpos, env->vpos);
- set_line_thickness(env);
- do_special("pa 0 0");
- sprintf(buf, "pa %d %d", milliinches(p[0]), milliinches(p[1]));
- do_special(buf);
- do_special("fp");
- break;
- case 'E':
- fill_flag = 1;
- // fall through
- case 'e':
- if (np != 2) {
- error("2 arguments required for ellipse");
- break;
- }
- moveto(env->hpos+p[0]/2, env->vpos);
- if (fill_flag)
- fill_next(env);
- sprintf(buf, "%s 0 0 %d %d 0 6.28319",
- (fill_flag ? "ia" : "ar"),
- milliinches(p[0]/2),
- milliinches(p[1]/2));
- do_special(buf);
- break;
- case 'P':
- fill_flag = 1;
- // fall through
- case 'p':
- {
- if (np & 1) {
- error("even number of arguments required for polygon");
- break;
- }
- if (np == 0) {
- error("no arguments for polygon");
- break;
- }
- moveto(env->hpos, env->vpos);
- if (fill_flag)
- fill_next(env);
- else
- set_line_thickness(env);
- do_special("pa 0 0");
- int h = 0, v = 0;
- for (int i = 0; i < np; i += 2) {
- h += p[i];
- v += p[i+1];
- sprintf(buf, "pa %d %d", milliinches(h), milliinches(v));
- do_special(buf);
- }
- do_special("pa 0 0");
- do_special(fill_flag ? "ip" : "fp");
- break;
- }
- case '~':
- {
- if (np & 1) {
- error("even number of arguments required for spline");
- break;
- }
- if (np == 0) {
- error("no arguments for spline");
- break;
- }
- moveto(env->hpos, env->vpos);
- set_line_thickness(env);
- do_special("pa 0 0");
- int h = 0, v = 0;
- for (int i = 0; i < np; i += 2) {
- h += p[i];
- v += p[i+1];
- sprintf(buf, "pa %d %d", milliinches(h), milliinches(v));
- do_special(buf);
- }
- do_special("sp");
- break;
- }
- case 'a':
- {
- if (np != 4) {
- error("4 arguments required for arc");
- break;
- }
- set_line_thickness(env);
- double c[2];
- if (adjust_arc_center(p, c)) {
- int rad = milliinches(int(sqrt(c[0]*c[0] + c[1]*c[1]) + .5));
- moveto(env->hpos + int(c[0]), env->vpos + int(c[1]));
- sprintf(buf, "ar 0 0 %d %d %f %f",
- rad,
- rad,
- atan2(p[1] + p[3] - c[1], p[0] + p[2] - c[0]),
- atan2(-c[1], -c[0]));
- do_special(buf);
- }
- else {
- moveto(env->hpos, env->vpos);
- do_special("pa 0 0");
- sprintf(buf,
- "pa %d %d",
- milliinches(p[0] + p[2]),
- milliinches(p[1] + p[3]));
- do_special(buf);
- do_special("fp");
- }
- break;
- }
- case 't':
- {
- if (np == 0) {
- line_thickness = -1;
- }
- else {
- // troff gratuitously adds an extra 0
- if (np != 1 && np != 2) {
- error("0 or 1 argument required for thickness");
- break;
- }
- line_thickness = p[0];
- }
- break;
- }
- case 'R':
- {
- if (np != 2) {
- error("2 arguments required for rule");
- break;
- }
- int dh = p[0];
- if (dh == 0)
- break;
- int dv = p[1];
- if (dv == 0)
- break;
- int oh = env->hpos;
- int ov = env->vpos;
- if (dv > 0) {
- ov += dv;
- dv = -dv;
- }
- if (dh < 0) {
- oh += dh;
- dh = -dh;
- }
- moveto(oh, ov);
- out1(put_rule);
- out4(-dv);
- out4(dh);
- break;
- }
- default:
- error("unrecognised drawing command `%1'", char(code));
- break;
- }
-}
-
-font *dvi_printer::make_font(const char *nm)
-{
- return dvi_font::load_dvi_font(nm);
-}
-
-printer *make_printer()
-{
- if (draw_flag)
- return new draw_dvi_printer;
- else
- return new dvi_printer;
-}
-
-static void usage(FILE *stream);
-
-int main(int argc, char **argv)
-{
- program_name = argv[0];
- static char stderr_buf[BUFSIZ];
- setbuf(stderr, stderr_buf);
- int c;
- static const struct option long_options[] = {
- { "help", no_argument, 0, CHAR_MAX + 1 },
- { "version", no_argument, 0, 'v' },
- { NULL, 0, 0, 0 }
- };
- while ((c = getopt_long(argc, argv, "F:vw:d", long_options, NULL)) != EOF)
- switch(c) {
- case 'v':
- {
- printf("GNU grodvi (groff) version %s\n", Version_string);
- exit(0);
- break;
- }
- case 'w':
- if (sscanf(optarg, "%d", &linewidth) != 1
- || linewidth < 0 || linewidth > 1000) {
- error("bad line width");
- linewidth = DEFAULT_LINEWIDTH;
- }
- break;
- case 'd':
- draw_flag = 0;
- break;
- case 'F':
- font::command_line_font_dir(optarg);
- break;
- case CHAR_MAX + 1: // --help
- usage(stdout);
- exit(0);
- break;
- case '?':
- usage(stderr);
- exit(1);
- break;
- default:
- assert(0);
- }
-#ifdef SET_BINARY
- SET_BINARY(fileno(stdout));
-#endif
- if (optind >= argc)
- do_file("-");
- else {
- for (int i = optind; i < argc; i++)
- do_file(argv[i]);
- }
- delete pr;
- return 0;
-}
-
-static void usage(FILE *stream)
-{
- fprintf(stream, "usage: %s [-dv] [-F dir] [-w n] [files ...]\n",
- program_name);
-}
diff --git a/contrib/groff/src/devices/grohtml/html-table.cc b/contrib/groff/src/devices/grohtml/html-table.cc
deleted file mode 100644
index a2bb255..0000000
--- a/contrib/groff/src/devices/grohtml/html-table.cc
+++ /dev/null
@@ -1,687 +0,0 @@
-// -*- C++ -*-
-/* Copyright (C) 2002 Free Software Foundation, Inc.
- *
- * Gaius Mulley (gaius@glam.ac.uk) wrote html-table.cc
- *
- * html-table.h
- *
- * provides the methods necessary to handle indentation and tab
- * positions using html tables.
- */
-
-/*
-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 2, 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 groff; see the file COPYING. If not, write to the Free Software
-Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#include "driver.h"
-#include "stringclass.h"
-#include "cset.h"
-#include "html-table.h"
-#include "ctype.h"
-#include "html.h"
-
-#if !defined(TRUE)
-# define TRUE (1==1)
-#endif
-#if !defined(FALSE)
-# define FALSE (1==0)
-#endif
-
-tabs::tabs ()
- : tab(NULL)
-{
-}
-
-tabs::~tabs ()
-{
- delete_list();
-}
-
-/*
- * delete_list - frees the tab list and sets tab to NULL.
- */
-
-void tabs::delete_list (void)
-{
- tab_position *p = tab;
- tab_position *q;
-
- while (p != NULL) {
- q = p;
- p = p->next;
- free(q);
- }
- tab = NULL;
-}
-
-void tabs::clear (void)
-{
- delete_list();
-}
-
-/*
- * compatible - returns TRUE if the tab stops in, s, do
- * not conflict with the current tab stops.
- * The new tab stops are _not_ placed into
- * this class.
- */
-
-int tabs::compatible (const char *s)
-{
- char align;
- int total=0;
- tab_position *last = tab;
-
- if (last == NULL)
- return FALSE; // no tab stops defined
-
- // move over tag name
- while ((*s != (char)0) && !isspace(*s))
- s++;
-
- while (*s != (char)0 && last != NULL) {
- // move over white space
- while ((*s != (char)0) && isspace(*s))
- s++;
- // collect alignment
- align = *s;
- // move over alignment
- s++;
- // move over white space
- while ((*s != (char)0) && isspace(*s))
- s++;
- // collect tab position
- total += atoi(s);
- // move over tab position
- while ((*s != (char)0) && !isspace(*s))
- s++;
- if (last->alignment != align || last->position != total)
- return FALSE;
-
- last = last->next;
- }
- return TRUE;
-}
-
-/*
- * init - scans the string, s, and initializes the tab stops.
- */
-
-void tabs::init (const char *s)
-{
- char align;
- int total=0;
- tab_position *last = NULL;
-
- clear(); // remove any tab stops
-
- // move over tag name
- while ((*s != (char)0) && !isspace(*s))
- s++;
-
- while (*s != (char)0) {
- // move over white space
- while ((*s != (char)0) && isspace(*s))
- s++;
- // collect alignment
- align = *s;
- // move over alignment
- s++;
- // move over white space
- while ((*s != (char)0) && isspace(*s))
- s++;
- // collect tab position
- total = atoi(s);
- // move over tab position
- while ((*s != (char)0) && !isspace(*s))
- s++;
- if (last == NULL) {
- tab = (tab_position *)malloc(sizeof(tab_position));
- last = tab;
- } else {
- last->next = (tab_position *)malloc(sizeof(tab_position));
- last = last->next;
- }
- last->alignment = align;
- last->position = total;
- last->next = NULL;
- }
-}
-
-/*
- * find_tab - returns the tab number corresponding to the position, pos.
- */
-
-int tabs::find_tab (int pos)
-{
- tab_position *p;
- int i=0;
-
- for (p = tab; p != NULL; p = p->next) {
- i++;
- if (p->position == pos)
- return i;
- }
- return 0;
-}
-
-/*
- * get_tab_pos - returns the, nth, tab position
- */
-
-int tabs::get_tab_pos (int n)
-{
- tab_position *p;
-
- n--;
- for (p = tab; (p != NULL) && (n>0); p = p->next) {
- n--;
- if (n == 0)
- return p->position;
- }
- return 0;
-}
-
-char tabs::get_tab_align (int n)
-{
- tab_position *p;
-
- n--;
- for (p = tab; (p != NULL) && (n>0); p = p->next) {
- n--;
- if (n == 0)
- return p->alignment;
- }
- return 'L';
-}
-
-/*
- * dump_tab - display tab positions
- */
-
-void tabs::dump_tabs (void)
-{
- int i=1;
- tab_position *p;
-
- for (p = tab; p != NULL; p = p->next) {
- printf("tab %d is %d\n", i, p->position);
- i++;
- }
-}
-
-/*
- * html_table - methods
- */
-
-html_table::html_table (simple_output *op, int linelen)
- : columns(NULL), out(op), linelength(linelen), last_col(NULL), start_space(FALSE)
-{
- tab_stops = new tabs();
-}
-
-html_table::~html_table ()
-{
- if (tab_stops != NULL)
- delete tab_stops;
-}
-
-/*
- * remove_cols - remove a list of columns as defined by, c.
- */
-
-void html_table::remove_cols (cols *c)
-{
- cols *p;
-
- while (c != NULL) {
- p = c;
- c = c->next;
- free(p);
- }
-}
-
-/*
- * set_linelength - sets the line length value in this table.
- * It also adds an extra blank column to the
- * table should linelen exceed the last column.
- */
-
-void html_table::set_linelength (int linelen)
-{
- cols *p = NULL;
- cols *c;
- linelength = linelen;
-
- for (c = columns; c != NULL; c = c->next) {
- if (c->right > linelength) {
- c->right = linelength;
- remove_cols(c->next);
- c->next = NULL;
- return;
- }
- p = c;
- }
- if (p != NULL && p->right != 0)
- add_column(p->no+1, p->right+1, linelen, 'L');
-}
-
-/*
- * get_effective_linelength -
- */
-
-int html_table::get_effective_linelength (void)
-{
- if (columns != NULL)
- return linelength - columns->left;
- else
- return linelength;
-}
-
-/*
- * add_indent - adds the indent to a table.
- */
-
-void html_table::add_indent (int indent)
-{
- if (columns != NULL && columns->left > indent)
- add_column(0, indent, columns->left-1, 'L');
-}
-
-/*
- * emit_table_header - emits the html header for this table.
- */
-
-void html_table::emit_table_header (int space)
-{
- if (columns == NULL)
- return;
-
- // dump_table();
-
- last_col = NULL;
- if (linelength > 0) {
- int n = no_columns() + no_gaps();
-
- out->nl();
- out->nl();
- if (space)
- out->put_string("<p>");
- start_space = space;
- out->put_string("<table width=\"100%\" border=0 rules=\"none\" frame=\"void\"\n cols=\"").put_number(n).put_string("\" cellspacing=\"0\" cellpadding=\"0\">").nl();
- out->put_string("<tr valign=\"top\" align=\"left\">").nl();
- }
-}
-
-/*
- * get_right - returns the right most position of this column.
- */
-
-int html_table::get_right (cols *c)
-{
- if (c != NULL && c->right > 0)
- return c->right;
- if (c->next != NULL)
- return c->left;
- return linelength;
-}
-
-/*
- * emit_col - moves onto column, n.
- */
-
-void html_table::emit_col (int n)
-{
- cols *c = columns;
- cols *b = columns;
- int width = 0;
-
- // must be a different row
- if (last_col != NULL && n <= last_col->no)
- emit_new_row();
-
- while (c != NULL && c->no < n)
- c = c->next;
-
- // can we find column, n?
- if (c != NULL && c->no == n) {
- // shutdown previous column
- if (last_col != NULL)
- out->put_string("</td>").nl();
-
- // find previous column
- if (last_col == NULL)
- b = columns;
- else
- b = last_col;
-
- // have we a gap?
- if (last_col != NULL) {
- if (is_gap(b))
- out->put_string("<td width=\"").put_number(is_gap(b)).put_string("%\"></td>").nl();
- b = b->next;
- }
-
- // move across to column n
- while (b != c) {
- width = ((get_right(b) - b->left) * 100)/get_effective_linelength();
- out->put_string("<td width=\"").put_number(width).put_string("%\"></td>").nl();
- // have we a gap?
- if (is_gap(b))
- out->put_string("<td width=\"").put_number(is_gap(b)).put_string("%\"></td>").nl();
- b = b->next;
- }
- width = ((get_right(b) - b->left) * 100)/get_effective_linelength();
- switch (b->alignment) {
-
- case 'C': out->put_string("<td width=\"").put_number(width).put_string("%\" align=center>").nl();
- break;
- case 'R': out->put_string("<td width=\"").put_number(width).put_string("%\" align=right>").nl();
- break;
- default:
- out->put_string("<td width=\"").put_number(width).put_string("%\">").nl();
- }
- // remember column, b
- last_col = b;
- }
-}
-
-/*
- * finish_row -
- */
-
-void html_table::finish_row (void)
-{
- int n = 0;
- cols *c;
-
- if (last_col != NULL) {
- for (c = last_col->next; c != NULL; c = c->next)
- n = c->no;
-
- if (n > 0)
- emit_col(n);
- out->put_string("</td>").nl();
- }
-}
-
-/*
- * emit_new_row - move to the next row.
- */
-
-void html_table::emit_new_row (void)
-{
- finish_row();
- out->put_string("<tr valign=\"top\" align=\"left\">").nl();
- last_col = NULL;
-}
-
-void html_table::emit_finish_table (void)
-{
- finish_row();
- // out->put_string("linelength = ").put_number(linelength).nl();
- out->put_string("</table>");
- if (start_space)
- out->put_string("</p>");
- out->nl();
-}
-
-/*
- * add_column - adds a column. It returns FALSE if hstart..hend
- * crosses into a different columns.
- */
-
-int html_table::add_column (int coln, int hstart, int hend, char align)
-{
- cols *c = get_column(coln);
-
- if (c == NULL)
- return insert_column(coln, hstart, hend, align);
- else
- return modify_column(c, hstart, hend, align);
-}
-
-/*
- * get_column - returns the column, coln.
- */
-
-cols *html_table::get_column (int coln)
-{
- cols *c = columns;
-
- while (c != NULL && coln != c->no)
- c = c->next;
-
- if (c != NULL && coln == c->no)
- return c;
- else
- return NULL;
-}
-
-/*
- * insert_column - inserts a column, coln.
- * It returns TRUE if it does not bump into
- * another column.
- */
-
-int html_table::insert_column (int coln, int hstart, int hend, char align)
-{
- cols *c = columns;
- cols *l = NULL;
- cols *n = NULL;
-
- while (c != NULL && c->no < coln) {
- l = c;
- c = c->next;
- }
- if ((l != NULL) && (hstart < l->right))
- return FALSE; // new column bumps into previous one
-
- if ((l != NULL) && (l->next != NULL) &&
- (l->next->left < hend))
- return FALSE; // new column bumps into next one
-
- n = (cols *)malloc(sizeof(cols));
- if (l == NULL) {
- n->next = columns;
- columns = n;
- } else {
- n->next = l->next;
- l->next = n;
- }
- n->left = hstart;
- n->right = hend;
- n->no = coln;
- n->alignment = align;
- return TRUE;
-}
-
-/*
- * modify_column - given a column, c, modify the width to
- * contain hstart..hend.
- * It returns TRUE if it does not clash with
- * the next or previous column.
- */
-
-int html_table::modify_column (cols *c, int hstart, int hend, char align)
-{
- cols *l = columns;
-
- while (l != NULL && l->next != c)
- l = l->next;
-
- if ((l != NULL) && (hstart < l->right))
- return FALSE; // new column bumps into previous one
-
- if ((c->next != NULL) && (c->next->left < hend))
- return FALSE; // new column bumps into next one
-
- if (c->left > hstart)
- c->left = hstart;
-
- if (c->right < hend)
- c->right = hend;
-
- c->alignment = align;
-
- return TRUE;
-}
-
-/*
- * find_tab_column - finds the column number for position, pos.
- * It searches through the list tab stops.
- */
-
-int html_table::find_tab_column (int pos)
-{
- // remember the first column is reserved for un tabbed glyphs
- return tab_stops->find_tab(pos)+1;
-}
-
-/*
- * find_column - find the column number for position, pos.
- * It searches through the list of columns.
- */
-
-int html_table::find_column (int pos)
-{
- int p=0;
- cols *c;
-
- for (c = columns; c != NULL; c = c->next) {
- if (c->left > pos)
- return p;
- p = c->no;
- }
- return p;
-}
-
-/*
- * no_columns - returns the number of table columns (rather than tabs)
- */
-
-int html_table::no_columns (void)
-{
- int n=0;
- cols *c;
-
- for (c = columns; c != NULL; c = c->next)
- n++;
- return n;
-}
-
-/*
- * is_gap - returns the gap between column, c, and the next column.
- */
-
-int html_table::is_gap (cols *c)
-{
- if (c == NULL || c->right == 0 || c->next == NULL)
- return 0;
- else
- return (c->next->left - c->right)*100/get_effective_linelength();
-}
-
-/*
- * no_gaps - returns the number of table gaps between the columns
- */
-
-int html_table::no_gaps (void)
-{
- int n=0;
- cols *c;
-
- for (c = columns; c != NULL; c = c->next)
- if (is_gap(c))
- n++;
- return n;
-}
-
-/*
- * get_tab_pos - returns the, nth, tab position
- */
-
-int html_table::get_tab_pos (int n)
-{
- return tab_stops->get_tab_pos(n);
-}
-
-char html_table::get_tab_align (int n)
-{
- return tab_stops->get_tab_align(n);
-}
-
-
-void html_table::dump_table (void)
-{
- if (columns != NULL) {
- cols *c;
- for (c = columns; c != NULL; c = c->next) {
- printf("column %d %d..%d %c\n", c->no, c->left, c->right, c->alignment);
- }
- } else
- tab_stops->dump_tabs();
-}
-
-/*
- * html_indent - creates an indent with indentation, ind, given
- * a line length of linelength.
- */
-
-html_indent::html_indent (simple_output *op, int ind, int pageoffset, int linelength)
-{
- table = new html_table(op, linelength);
-
- table->add_column(1, ind+pageoffset, linelength, 'L');
- table->add_indent(pageoffset);
- in = ind;
- pg = pageoffset;
- ll = linelength;
- is_used = FALSE;
-}
-
-html_indent::~html_indent (void)
-{
- end();
- delete table;
-}
-
-void html_indent::begin (int space)
-{
- if (! is_used) {
- table->emit_table_header(space);
- table->emit_col(1);
- is_used = TRUE;
- }
-}
-
-void html_indent::end (void)
-{
- if (is_used)
- table->emit_finish_table();
- is_used = FALSE;
-}
-
-/*
- * get_reg - collects the registers as supplied during initialization.
- */
-
-void html_indent::get_reg (int *ind, int *pageoffset, int *linelength)
-{
- *ind = in;
- *pageoffset = pg;
- *linelength = ll;
-}
diff --git a/contrib/groff/src/devices/grohtml/html-text.cc b/contrib/groff/src/devices/grohtml/html-text.cc
deleted file mode 100644
index 31e4311..0000000
--- a/contrib/groff/src/devices/grohtml/html-text.cc
+++ /dev/null
@@ -1,964 +0,0 @@
-// -*- C++ -*-
-/* Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
- *
- * Gaius Mulley (gaius@glam.ac.uk) wrote html-text.cc
- *
- * html-text.cc
- *
- * provide a troff like state machine interface which
- * generates html text.
- */
-
-/*
-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 2, 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 groff; see the file COPYING. If not, write to the Free Software
-Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#include "driver.h"
-#include "stringclass.h"
-#include "cset.h"
-
-#if !defined(TRUE)
-# define TRUE (1==1)
-#endif
-#if !defined(FALSE)
-# define FALSE (1==0)
-#endif
-
-
-#include "html-text.h"
-
-// #define DEBUGGING
-
-html_text::html_text (simple_output *op) :
- stackptr(NULL), lastptr(NULL), out(op), space_emitted(TRUE),
- current_indentation(-1), pageoffset(-1), linelength(-1),
- blank_para(TRUE), start_space(FALSE)
-{
-}
-
-html_text::~html_text ()
-{
- flush_text();
-}
-
-
-#if defined(DEBUGGING)
-static int debugStack = FALSE;
-
-
-/*
- * turnDebug - flip the debugStack boolean and return the new value.
- */
-
-static int turnDebug (void)
-{
- debugStack = 1-debugStack;
- return debugStack;
-}
-
-/*
- * dump_stack_element - display an element of the html stack, p.
- */
-
-void html_text::dump_stack_element (tag_definition *p)
-{
- fprintf(stderr, " | ");
- switch (p->type) {
-
- case P_TAG: if (p->indent == NULL) {
- fprintf(stderr, "<P %s>", (char *)p->arg1); break;
- } else {
- fprintf(stderr, "<P %s [TABLE]>", (char *)p->arg1); break;
- }
- case I_TAG: fprintf(stderr, "<I>"); break;
- case B_TAG: fprintf(stderr, "<B>"); break;
- case SUB_TAG: fprintf(stderr, "<SUB>"); break;
- case SUP_TAG: fprintf(stderr, "<SUP>"); break;
- case TT_TAG: fprintf(stderr, "<TT>"); break;
- case PRE_TAG: if (p->indent == NULL) {
- fprintf(stderr, "<PRE>"); break;
- } else {
- fprintf(stderr, "<PRE [TABLE]>"); break;
- }
- case SMALL_TAG: fprintf(stderr, "<SMALL>"); break;
- case BIG_TAG: fprintf(stderr, "<BIG>"); break;
- case BREAK_TAG: fprintf(stderr, "<BREAK>"); break;
- case COLOR_TAG: {
- if (p->col.is_default())
- fprintf(stderr, "<COLOR (default)>");
- else {
- unsigned int r, g, b;
-
- p->col.get_rgb(&r, &g, &b);
- fprintf(stderr, "<COLOR %x %x %x>", r/0x101, g/0x101, b/0x101);
- }
- break;
- }
- default: fprintf(stderr, "unknown tag");
- }
- if (p->text_emitted)
- fprintf(stderr, "[t] ");
-}
-
-/*
- * dump_stack - debugging function only.
- */
-
-void html_text::dump_stack (void)
-{
- if (debugStack) {
- tag_definition *p = stackptr;
-
- while (p != NULL) {
- dump_stack_element(p);
- p = p->next;
- }
- }
- fprintf(stderr, "\n");
- fflush(stderr);
-}
-#else
-void html_text::dump_stack (void) {}
-#endif
-
-
-/*
- * end_tag - shuts down the tag.
- */
-
-void html_text::end_tag (tag_definition *t)
-{
- switch (t->type) {
-
- case I_TAG: out->put_string("</i>"); break;
- case B_TAG: out->put_string("</b>"); break;
- case P_TAG: out->put_string("</p>");
- if (t->indent != NULL) {
- delete t->indent;
- t->indent = NULL;
- }
- out->nl(); out->enable_newlines(FALSE);
- blank_para = TRUE; break;
- case SUB_TAG: out->put_string("</sub>"); break;
- case SUP_TAG: out->put_string("</sup>"); break;
- case TT_TAG: out->put_string("</tt>"); break;
- case PRE_TAG: out->put_string("</pre>"); out->nl(); out->enable_newlines(TRUE);
- blank_para = TRUE; break;
- case SMALL_TAG: out->put_string("</small>"); break;
- case BIG_TAG: out->put_string("</big>"); break;
- case COLOR_TAG: out->put_string("</font>"); break;
-
- default:
- error("unrecognised tag");
- }
-}
-
-/*
- * issue_tag - writes out an html tag with argument.
- */
-
-void html_text::issue_tag (char *tagname, char *arg)
-{
- if ((arg == 0) || (strlen(arg) == 0)) {
- out->put_string(tagname);
- out->put_string(">");
- } else {
- out->put_string(tagname);
- out->put_string(" ");
- out->put_string(arg);
- out->put_string(">");
- }
-}
-
-/*
- * issue_color_begin - writes out an html color tag.
- */
-
-void html_text::issue_color_begin (color *c)
-{
- unsigned int r, g, b;
- char buf[6+1];
-
- out->put_string("<font color=\"#");
- if (c->is_default())
- sprintf(buf, "000000");
- else {
- c->get_rgb(&r, &g, &b);
- // we have to scale 0..0xFFFF to 0..0xFF
- sprintf(buf, "%.2X%.2X%.2X", r/0x101, g/0x101, b/0x101);
- }
- out->put_string(buf);
- out->put_string("\">");
-}
-
-/*
- * start_tag - starts a tag.
- */
-
-void html_text::start_tag (tag_definition *t)
-{
- switch (t->type) {
-
- case I_TAG: issue_tag("<i", (char *)t->arg1); break;
- case B_TAG: issue_tag("<b", (char *)t->arg1); break;
- case P_TAG: if (t->indent == NULL) {
- out->nl();
- issue_tag("\n<p", (char *)t->arg1);
- } else {
- out->nl();
- out->simple_comment("INDENTATION");
- t->indent->begin(FALSE);
- start_space = FALSE;
- issue_tag("<p", (char *)t->arg1);
- }
-
- out->enable_newlines(TRUE); break;
- case SUB_TAG: issue_tag("<sub", (char *)t->arg1); break;
- case SUP_TAG: issue_tag("<sup", (char *)t->arg1); break;
- case TT_TAG: issue_tag("<tt", (char *)t->arg1); break;
- case PRE_TAG: if (t->indent != NULL) {
- out->nl();
- out->simple_comment("INDENTATION");
- t->indent->begin(FALSE);
- start_space = FALSE;
- }
- out->enable_newlines(TRUE);
- out->nl(); issue_tag("<pre", (char *)t->arg1);
- out->enable_newlines(FALSE); break;
- case SMALL_TAG: issue_tag("<small", (char *)t->arg1); break;
- case BIG_TAG: issue_tag("<big", (char *)t->arg1); break;
- case BREAK_TAG: break;
- case COLOR_TAG: issue_color_begin(&t->col); break;
-
- default:
- error("unrecognised tag");
- }
-}
-
-/*
- * flush_text - flushes html tags which are outstanding on the html stack.
- */
-
-void html_text::flush_text (void)
-{
- int notext=TRUE;
- tag_definition *p=stackptr;
-
- while (stackptr != 0) {
- notext = (notext && (! stackptr->text_emitted));
- if (! notext) {
- end_tag(stackptr);
- }
- p = stackptr;
- stackptr = stackptr->next;
- free(p);
- }
- lastptr = NULL;
-}
-
-/*
- * is_present - returns TRUE if tag is already present on the stack.
- */
-
-int html_text::is_present (HTML_TAG t)
-{
- tag_definition *p=stackptr;
-
- while (p != NULL) {
- if (t == p->type)
- return TRUE;
- p = p->next;
- }
- return FALSE;
-}
-
-extern void stop();
-
-/*
- * do_push - places, tag_definition, p, onto the stack
- */
-
-void html_text::do_push (tag_definition *p)
-{
- HTML_TAG t = p->type;
-
-#if defined(DEBUGGING)
- if (t == PRE_TAG)
- stop();
- debugStack = TRUE;
- fprintf(stderr, "\nentering do_push (");
- dump_stack_element(p);
- fprintf(stderr, ")\n");
- dump_stack();
- fprintf(stderr, ")\n");
- fflush(stderr);
-#endif
-
- /*
- * if t is a P_TAG or PRE_TAG make sure it goes on the end of the stack.
- */
-
- if (((t == P_TAG) || (t == PRE_TAG)) && (lastptr != NULL)) {
- /*
- * store, p, at the end
- */
- lastptr->next = p;
- lastptr = p;
- p->next = NULL;
- } else {
- p->next = stackptr;
- if (stackptr == NULL)
- lastptr = p;
- stackptr = p;
- }
-
-#if defined(DEBUGGING)
- dump_stack();
- fprintf(stderr, "exiting do_push\n");
-#endif
-}
-
-/*
- * push_para - adds a new entry onto the html paragraph stack.
- */
-
-void html_text::push_para (HTML_TAG t, void *arg, html_indent *in)
-{
- tag_definition *p=(tag_definition *)malloc(sizeof(tag_definition));
-
- p->type = t;
- p->arg1 = arg;
- p->text_emitted = FALSE;
- p->indent = in;
-
- if (t == PRE_TAG && is_present(PRE_TAG))
- fatal("cannot have multiple PRE_TAGs");
-
- do_push(p);
-}
-
-void html_text::push_para (HTML_TAG t)
-{
- push_para(t, (void *)"", NULL);
-}
-
-void html_text::push_para (color *c)
-{
- tag_definition *p=(tag_definition *)malloc(sizeof(tag_definition));
-
- p->type = COLOR_TAG;
- p->arg1 = NULL;
- p->col = *c;
- p->text_emitted = FALSE;
- p->indent = NULL;
-
- do_push(p);
-}
-
-/*
- * do_italic - changes to italic
- */
-
-void html_text::do_italic (void)
-{
- if (! is_present(I_TAG))
- push_para(I_TAG);
-}
-
-/*
- * do_bold - changes to bold.
- */
-
-void html_text::do_bold (void)
-{
- if (! is_present(B_TAG))
- push_para(B_TAG);
-}
-
-/*
- * do_tt - changes to teletype.
- */
-
-void html_text::do_tt (void)
-{
- if ((! is_present(TT_TAG)) && (! is_present(PRE_TAG)))
- push_para(TT_TAG);
-}
-
-/*
- * do_pre - changes to preformated text.
- */
-
-void html_text::do_pre (void)
-{
- done_tt();
- if (is_present(P_TAG)) {
- html_indent *i = remove_indent(P_TAG);
- (void)done_para();
- if (! is_present(PRE_TAG))
- push_para(PRE_TAG, NULL, i);
- } else if (! is_present(PRE_TAG))
- push_para(PRE_TAG, NULL, NULL);
- dump_stack();
-}
-
-/*
- * is_in_pre - returns TRUE if we are currently within a preformatted
- * <pre> block.
- */
-
-int html_text::is_in_pre (void)
-{
- return is_present(PRE_TAG);
-}
-
-/*
- * do_color - initiates a new color tag.
- */
-
-void html_text::do_color (color *c)
-{
- shutdown(COLOR_TAG); // shutdown a previous color tag, if present
- push_para(c);
-}
-
-/*
- * done_color - shutdown an outstanding color tag, if it exists.
- */
-
-void html_text::done_color (void)
-{
- shutdown(COLOR_TAG);
-}
-
-/*
- * shutdown - shuts down an html tag.
- */
-
-char *html_text::shutdown (HTML_TAG t)
-{
- char *arg=NULL;
-
- if (is_present(t)) {
- tag_definition *p =stackptr;
- tag_definition *temp =NULL;
- int notext =TRUE;
-
- dump_stack();
- while ((stackptr != NULL) && (stackptr->type != t)) {
- notext = (notext && (! stackptr->text_emitted));
- if (! notext) {
- end_tag(stackptr);
- }
-
- /*
- * pop tag
- */
- p = stackptr;
- stackptr = stackptr->next;
- if (stackptr == NULL)
- lastptr = NULL;
-
- /*
- * push tag onto temp stack
- */
- p->next = temp;
- temp = p;
- }
-
- /*
- * and examine stackptr
- */
- if ((stackptr != NULL) && (stackptr->type == t)) {
- if (stackptr->text_emitted) {
- end_tag(stackptr);
- }
- if (t == P_TAG) {
- arg = (char *)stackptr->arg1;
- }
- p = stackptr;
- stackptr = stackptr->next;
- if (stackptr == NULL)
- lastptr = NULL;
- if (p->indent != NULL)
- delete p->indent;
- free(p);
- }
-
- /*
- * and restore unaffected tags
- */
- while (temp != NULL) {
- if (temp->type == COLOR_TAG)
- push_para(&temp->col);
- else
- push_para(temp->type, temp->arg1, temp->indent);
- p = temp;
- temp = temp->next;
- free(p);
- }
- }
- return arg;
-}
-
-/*
- * done_bold - shuts downs a bold tag.
- */
-
-void html_text::done_bold (void)
-{
- shutdown(B_TAG);
-}
-
-/*
- * done_italic - shuts downs an italic tag.
- */
-
-void html_text::done_italic (void)
-{
- shutdown(I_TAG);
-}
-
-/*
- * done_sup - shuts downs a sup tag.
- */
-
-void html_text::done_sup (void)
-{
- shutdown(SUP_TAG);
-}
-
-/*
- * done_sub - shuts downs a sub tag.
- */
-
-void html_text::done_sub (void)
-{
- shutdown(SUB_TAG);
-}
-
-/*
- * done_tt - shuts downs a tt tag.
- */
-
-void html_text::done_tt (void)
-{
- shutdown(TT_TAG);
-}
-
-/*
- * done_pre - shuts downs a pre tag.
- */
-
-void html_text::done_pre (void)
-{
- shutdown(PRE_TAG);
-}
-
-/*
- * done_small - shuts downs a small tag.
- */
-
-void html_text::done_small (void)
-{
- shutdown(SMALL_TAG);
-}
-
-/*
- * done_big - shuts downs a big tag.
- */
-
-void html_text::done_big (void)
-{
- shutdown(BIG_TAG);
-}
-
-/*
- * check_emit_text - ensures that all previous tags have been emitted (in order)
- * before the text is written.
- */
-
-void html_text::check_emit_text (tag_definition *t)
-{
- if ((t != NULL) && (! t->text_emitted)) {
- check_emit_text(t->next);
- t->text_emitted = TRUE;
- start_tag(t);
- }
-}
-
-/*
- * do_emittext - tells the class that text was written during the current tag.
- */
-
-void html_text::do_emittext (const char *s, int length)
-{
- if ((! is_present(P_TAG)) && (! is_present(PRE_TAG)))
- do_para("");
-
- if (is_present(BREAK_TAG)) {
- int text = remove_break();
- check_emit_text(stackptr);
- if (text) {
- if (is_present(PRE_TAG)) {
- out->nl();
- } else {
- out->put_string("<br>").nl();
- }
- }
- } else {
- check_emit_text(stackptr);
- }
- out->put_string(s, length);
- space_emitted = FALSE;
- blank_para = FALSE;
-}
-
-/*
- * do_para - starts a new paragraph
- */
-
-void html_text::do_para (const char *arg, html_indent *in)
-{
- if (! is_present(P_TAG)) {
- if (is_present(PRE_TAG)) {
- html_indent *i = remove_indent(PRE_TAG);
- done_pre();
- if (i == in || in == NULL)
- in = i;
- else
- delete i;
- }
- remove_sub_sup();
- push_para(P_TAG, (void *)arg, in);
- space_emitted = TRUE;
- }
-}
-
-void html_text::do_para (const char *arg)
-{
- do_para(arg, NULL);
-}
-
-void html_text::do_para (simple_output *op, const char *arg1,
- int indentation, int pageoffset, int linelength)
-{
- html_indent *indent;
-
- if (indentation == 0)
- indent = NULL;
- else
- indent = new html_indent(op, indentation, pageoffset, linelength);
- do_para(arg1, indent);
-}
-
-/*
- * done_para - shuts down a paragraph tag.
- */
-
-char *html_text::done_para (void)
-{
- space_emitted = TRUE;
- return shutdown(P_TAG);
-}
-
-/*
- * remove_indent - returns the indent associated with, tag.
- * The indent associated with tag is set to NULL.
- */
-
-html_indent *html_text::remove_indent (HTML_TAG tag)
-{
- tag_definition *p=stackptr;
-
- while (p != NULL) {
- if (tag == p->type) {
- html_indent *i = p->indent;
- p->indent = NULL;
- return i;
- }
- p = p->next;
- }
- return NULL;
-}
-
-/*
- * do_space - issues an end of paragraph
- */
-
-void html_text::do_space (void)
-{
- if (is_in_pre()) {
- if (blank_para)
- start_space = TRUE;
- else {
- do_emittext("", 0);
- out->nl();
- }
- } else {
- html_indent *i = remove_indent(P_TAG);
-
- do_para(done_para(), i);
- space_emitted = TRUE;
- start_space = TRUE;
- }
-}
-
-/*
- * do_break - issue a break tag.
- */
-
-void html_text::do_break (void)
-{
- if (! is_present(PRE_TAG)) {
- if (emitted_text()) {
- if (! is_present(BREAK_TAG)) {
- push_para(BREAK_TAG);
- }
- }
- }
- space_emitted = TRUE;
-}
-
-/*
- * do_newline - issue a newline providing that we are inside a <pre> tag.
- */
-
-void html_text::do_newline (void)
-{
- if (is_present(PRE_TAG)) {
- do_emittext("\n", 1);
- space_emitted = TRUE;
- }
-}
-
-/*
- * emitted_text - returns FALSE if white space has just been written.
- */
-
-int html_text::emitted_text (void)
-{
- return !space_emitted;
-}
-
-/*
- * ever_emitted_text - returns TRUE if we have ever emitted text in this paragraph.
- */
-
-int html_text::ever_emitted_text (void)
-{
- return !blank_para;
-}
-
-/*
- * starts_with_space - returns TRUE if we have start this paragraph with a .sp
- */
-
-int html_text::starts_with_space (void)
-{
- return start_space;
-}
-
-/*
- * emit_space - writes a space providing that text was written beforehand.
- */
-
-void html_text::emit_space (void)
-{
- if (space_emitted) {
- if (is_present(PRE_TAG)) {
- do_emittext(" ", 1);
- }
- } else {
- out->space_or_newline();
- space_emitted = TRUE;
- }
-}
-
-/*
- * remove_def - removes a definition, t, from the stack.
- */
-
-void html_text::remove_def (tag_definition *t)
-{
- tag_definition *p = stackptr;
- tag_definition *l = 0;
- tag_definition *q = 0;
-
- while ((p != 0) && (p != t)) {
- l = p;
- p = p->next;
- }
- if ((p != 0) && (p == t)) {
- if (p == stackptr) {
- stackptr = stackptr->next;
- if (stackptr == NULL)
- lastptr = NULL;
- q = stackptr;
- } else if (l == 0) {
- error("stack list pointers are wrong");
- } else {
- l->next = p->next;
- q = p->next;
- if (l->next == NULL)
- lastptr = l;
- }
- free(p);
- }
-}
-
-/*
- * remove_tag - removes a tag from the stack.
- */
-
-void html_text::remove_tag (HTML_TAG tag)
-{
- tag_definition *p = stackptr;
-
- while ((p != 0) && (p->type != tag)) {
- p = p->next;
- }
- if ((p != 0) && (p->type == tag))
- remove_def(p);
-}
-
-/*
- * remove_sub_sup - removes a sub or sup tag, should either exist on the stack.
- */
-
-void html_text::remove_sub_sup (void)
-{
- if (is_present(SUB_TAG)) {
- remove_tag(SUB_TAG);
- }
- if (is_present(SUP_TAG)) {
- remove_tag(SUP_TAG);
- }
- if (is_present(PRE_TAG)) {
- remove_tag(PRE_TAG);
- }
-}
-
-/*
- * remove_break - break tags are not balanced thus remove it once it has been emitted.
- * It returns TRUE if text was emitted before the <br> was issued.
- */
-
-int html_text::remove_break (void)
-{
- tag_definition *p = stackptr;
- tag_definition *l = 0;
- tag_definition *q = 0;
-
- while ((p != 0) && (p->type != BREAK_TAG)) {
- l = p;
- p = p->next;
- }
- if ((p != 0) && (p->type == BREAK_TAG)) {
- if (p == stackptr) {
- stackptr = stackptr->next;
- if (stackptr == NULL)
- lastptr = NULL;
- q = stackptr;
- } else if (l == 0)
- error("stack list pointers are wrong");
- else {
- l->next = p->next;
- q = p->next;
- if (l->next == NULL)
- lastptr = l;
- }
- free(p);
- }
- /*
- * now determine whether text was issued before <br>
- */
- while (q != 0) {
- if (q->text_emitted)
- return TRUE;
- else
- q = q->next;
- }
- return FALSE;
-}
-
-/*
- * remove_para_align - removes a paragraph which has a text
- * argument. If the paragraph has no text
- * argument then it is left alone.
- */
-
-void html_text::remove_para_align (void)
-{
- if (is_present(P_TAG)) {
- tag_definition *p=stackptr;
-
- while (p != NULL) {
- if (p->type == P_TAG && p->arg1 != NULL) {
- html_indent *i = remove_indent(P_TAG);
- done_para();
- do_para("", i);
- return;
- }
- p = p->next;
- }
- }
-}
-
-/*
- * do_small - potentially inserts a <small> tag into the html stream.
- * However we check for a <big> tag, if present then we terminate it.
- * Otherwise a <small> tag is inserted.
- */
-
-void html_text::do_small (void)
-{
- if (is_present(BIG_TAG))
- done_big();
- else
- push_para(SMALL_TAG);
-}
-
-/*
- * do_big - is the mirror image of do_small.
- */
-
-void html_text::do_big (void)
-{
- if (is_present(SMALL_TAG))
- done_small();
- else
- push_para(BIG_TAG);
-}
-
-/*
- * do_sup - save a superscript tag on the stack of tags.
- */
-
-void html_text::do_sup (void)
-{
- push_para(SUP_TAG);
-}
-
-/*
- * do_sub - save a subscript tag on the stack of tags.
- */
-
-void html_text::do_sub (void)
-{
- push_para(SUB_TAG);
-}
-
diff --git a/contrib/groff/src/devices/grohtml/output.cc b/contrib/groff/src/devices/grohtml/output.cc
deleted file mode 100644
index 67d5874..0000000
--- a/contrib/groff/src/devices/grohtml/output.cc
+++ /dev/null
@@ -1,356 +0,0 @@
-// -*- C++ -*-
-/* Copyright (C) 2000, 2001 Free Software Foundation, Inc.
- *
- * Gaius Mulley (gaius@glam.ac.uk) wrote output.cc
- * but it owes a huge amount of ideas and raw code from
- * James Clark (jjc@jclark.com) grops/ps.cc.
- *
- * output.cc
- *
- * provide the simple low level output routines needed by html.cc
- */
-
-/*
-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 2, 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 groff; see the file COPYING. If not, write to the Free Software
-Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#include "driver.h"
-#include "stringclass.h"
-#include "cset.h"
-
-#include <time.h>
-#include "html.h"
-
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#undef DEBUGGING
-// #define DEBUGGING
-
-#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 = (char *)malloc(n+1);
- strncpy(s, w, n);
- s[n] = (char)0;
-}
-
-/*
- * destroy word and the string copy.
- */
-
-word::~word ()
-{
- free(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 *s)
-{
- 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;
-}
-
-/*
- * 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);
- if (col != 0) {
- 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);
- }
- }
-}
diff --git a/contrib/groff/src/devices/grohtml/post-html.cc b/contrib/groff/src/devices/grohtml/post-html.cc
deleted file mode 100644
index 4431f17..0000000
--- a/contrib/groff/src/devices/grohtml/post-html.cc
+++ /dev/null
@@ -1,3745 +0,0 @@
-// -*- C++ -*-
-/* Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
- *
- * Gaius Mulley (gaius@glam.ac.uk) wrote post-html.cc
- * but it owes a huge amount of ideas and raw code from
- * James Clark (jjc@jclark.com) grops/ps.cc.
- */
-
-/*
-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 2, 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 groff; see the file COPYING. If not, write to the Free Software
-Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#include "driver.h"
-#include "stringclass.h"
-#include "cset.h"
-#include "html.h"
-#include "html-text.h"
-#include "html-table.h"
-
-#include <time.h>
-
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#include <stdio.h>
-#include <fcntl.h>
-
-extern "C" const char *Version_string;
-
-#if !defined(TRUE)
-# define TRUE (1==1)
-#endif
-#if !defined(FALSE)
-# define FALSE (1==0)
-#endif
-
-#define MAX_LINE_LENGTH 60 /* maximum characters we want in a line */
-#define SIZE_INCREMENT 2 /* font size increment <big> = +2 */
-#define BASE_POINT_SIZE 10 /* 10 points is the base size ie html size 3 */
-#define CENTER_TOLERANCE 2 /* how many pixels off center will we still */
-#define ANCHOR_TEMPLATE "heading" /* if simple anchor is set we use this */
-#define UNICODE_DESC_START 0x80 /* all character entities above this are */
- /* either encoded by their glyph names or if */
- /* there is no name then we use &#nnn; */
-typedef enum {CENTERED, LEFT, RIGHT, INLINE} TAG_ALIGNMENT;
-typedef enum {col_tag, tab_tag, tab0_tag, none} colType;
-
-#undef DEBUG_TABLES
-
-
-/*
- * prototypes
- */
-
-char *get_html_translation (font *f, const string &name);
-int char_translate_to_html (font *f, char *buf, int buflen, unsigned char ch, int b, int and_single);
-
-
-static int auto_links = TRUE; /* by default we enable automatic links at */
- /* top of the document. */
-static int auto_rule = TRUE; /* by default we enable an automatic rule */
- /* at the top and bottom of the document */
-static int simple_anchors = FALSE; /* default to anchors with heading text */
-static int manufacture_headings = FALSE; /* default is to use the Hn html headings, */
- /* rather than manufacture our own. */
-static color *default_background = NULL; /* has user requested initial bg color? */
-
-
-/*
- * start with a few favorites
- */
-
-void stop () {}
-
-static int min (int a, int b)
-{
- if (a < b)
- return a;
- else
- return b;
-}
-
-static int max (int a, int b)
-{
- if (a > b)
- return a;
- else
- return b;
-}
-
-/*
- * is_intersection - returns TRUE if range a1..a2 intersects with b1..b2
- */
-
-static int is_intersection (int a1, int a2, int b1, int b2)
-{
- // easier to prove NOT outside limits
- return( ! ((a1 > b2) || (a2 < b1)) );
-}
-
-/*
- * is_digit - returns TRUE if character, ch, is a digit.
- */
-
-static int is_digit (char ch)
-{
- return( (ch >= '0') && (ch <= '9') );
-}
-
-/*
- * the classes and methods for maintaining a list of files.
- */
-
-struct file {
- FILE *fp;
- file *next;
-
- file (FILE *f);
-};
-
-/*
- * file - initialize all fields to NULL
- */
-
-file::file (FILE *f)
- : fp(f), next(0)
-{
-}
-
-class files {
-public:
- files ();
- FILE *get_file (void);
- void start_of_list (void);
- void move_next (void);
- void add_new_file (FILE *f);
-private:
- file *head;
- file *tail;
- file *ptr;
-};
-
-/*
- * files - create an empty list of files.
- */
-
-files::files ()
- : head(0), tail(0), ptr(0)
-{
-}
-
-/*
- * get_file - returns the FILE associated with ptr.
- */
-
-FILE *files::get_file (void)
-{
- if (ptr) {
- return( ptr->fp );
- } else {
- return( 0 );
- }
-}
-
-/*
- * start_of_list - reset the ptr to the start of the list.
- */
-
-void files::start_of_list (void)
-{
- ptr = head;
-}
-
-/*
- * move_next - moves the ptr to the next element on the list.
- */
-
-void files::move_next (void)
-{
- if (ptr != 0)
- ptr = ptr->next;
-}
-
-/*
- * add_new_file - adds a new file, f, to the list.
- */
-
-void files::add_new_file (FILE *f)
-{
- if (head == 0) {
- head = new file(f);
- tail = head;
- } else {
- tail->next = new file(f);
- tail = tail->next;
- }
- ptr = tail;
-}
-
-/*
- * the class and methods for styles
- */
-
-struct style {
- font *f;
- int point_size;
- int font_no;
- int height;
- int slant;
- color col;
- style ();
- style (font *, int, int, int, int, color);
- int operator == (const style &) const;
- int operator != (const style &) const;
-};
-
-style::style()
- : f(0)
-{
-}
-
-style::style(font *p, int sz, int h, int sl, int no, color c)
- : f(p), point_size(sz), font_no(no), height(h), slant(sl), col(c)
-{
-}
-
-int style::operator==(const style &s) const
-{
- return (f == s.f && point_size == s.point_size
- && height == s.height && slant == s.slant && col == s.col);
-}
-
-int style::operator!=(const style &s) const
-{
- return !(*this == s);
-}
-
-/*
- * the class and methods for retaining ascii text
- */
-
-struct char_block {
- enum { SIZE = 256 };
- char *buffer;
- int used;
- char_block *next;
-
- char_block();
- char_block::char_block(int length);
-};
-
-char_block::char_block()
-: buffer(NULL), used(0), next(0)
-{
-}
-
-char_block::char_block(int length)
-: used(0), next(0)
-{
- buffer = (char *)malloc(max(length, char_block::SIZE));
- if (buffer == NULL)
- fatal("out of memory error");
-}
-
-class char_buffer {
-public:
- char_buffer();
- ~char_buffer();
- char *add_string(const char *, unsigned int);
- char *add_string(const string &);
-private:
- char_block *head;
- char_block *tail;
-};
-
-char_buffer::char_buffer()
-: head(0), tail(0)
-{
-}
-
-char_buffer::~char_buffer()
-{
- while (head != 0) {
- char_block *temp = head;
- head = head->next;
- delete temp;
- }
-}
-
-char *char_buffer::add_string (const char *s, unsigned int length)
-{
- int i=0;
- unsigned int old_used;
-
- if (s == NULL || length == 0)
- return NULL;
-
- if (tail == 0) {
- tail = new char_block(length+1);
- head = tail;
- } else {
- if (tail->used + length+1 > char_block::SIZE) {
- tail->next = new char_block(length+1);
- tail = tail->next;
- }
- }
-
- old_used = tail->used;
- do {
- tail->buffer[tail->used] = s[i];
- tail->used++;
- i++;
- length--;
- } while (length>0);
-
- // add terminating nul character
-
- tail->buffer[tail->used] = '\0';
- tail->used++;
-
- // and return start of new string
-
- return( &tail->buffer[old_used] );
-}
-
-char *char_buffer::add_string (const string &s)
-{
- return add_string(s.contents(), s.length());
-}
-
-/*
- * the classes and methods for maintaining glyph positions.
- */
-
-class text_glob {
-public:
- void text_glob_html (style *s, char *str, int length,
- int min_vertical, int min_horizontal,
- int max_vertical, int max_horizontal);
- void text_glob_special (style *s, char *str, int length,
- int min_vertical, int min_horizontal,
- int max_vertical, int max_horizontal);
- void text_glob_line (style *s,
- int min_vertical, int min_horizontal,
- int max_vertical, int max_horizontal,
- int thickness);
- void text_glob_auto_image(style *s, char *str, int length,
- int min_vertical, int min_horizontal,
- int max_vertical, int max_horizontal);
- void text_glob_tag (style *s, char *str, int length,
- int min_vertical, int min_horizontal,
- int max_vertical, int max_horizontal);
-
- text_glob (void);
- ~text_glob (void);
- int is_a_line (void);
- int is_a_tag (void);
- int is_eol (void);
- int is_auto_img (void);
- int is_br (void);
- int is_in (void);
- int is_po (void);
- int is_ti (void);
- int is_ce (void);
- int is_eol_ce (void);
- int is_col (void);
- int is_tab (void);
- int is_tab0 (void);
- int is_ta (void);
- int is_tab_ts (void);
- int is_tab_te (void);
- int is_nf (void);
- int is_fi (void);
- int get_arg (void);
- int get_tab_args (char *align);
-
- void remember_table (html_table *t);
- html_table *get_table (void);
-
- style text_style;
- const char *text_string;
- unsigned int text_length;
- int minv, minh, maxv, maxh;
- int is_tag; // is this a .br, .sp, .tl etc
- int is_img_auto; // image created by eqn delim
- int is_special; // text has come via 'x X html:'
- int is_line; // is the command a <line>?
- int thickness; // the thickness of a line
- html_table *tab; // table description
-
-private:
- text_glob (style *s, char *str, int length,
- int min_vertical , int min_horizontal,
- int max_vertical , int max_horizontal,
- bool is_troff_command,
- bool is_auto_image, bool is_special_command,
- bool is_a_line , int thickness);
-};
-
-text_glob::text_glob (style *s, char *str, int length,
- int min_vertical, int min_horizontal,
- int max_vertical, int max_horizontal,
- bool is_troff_command,
- bool is_auto_image, bool is_special_command,
- bool is_a_line, int line_thickness)
- : text_style(*s), text_string(str), text_length(length),
- minv(min_vertical), minh(min_horizontal), maxv(max_vertical), maxh(max_horizontal),
- is_tag(is_troff_command), is_img_auto(is_auto_image), is_special(is_special_command),
- is_line(is_a_line), thickness(line_thickness), tab(NULL)
-{
-}
-
-text_glob::text_glob ()
- : text_string(0), text_length(0), minv(-1), minh(-1), maxv(-1), maxh(-1),
- is_tag(FALSE), is_special(FALSE), is_line(FALSE), thickness(0), tab(NULL)
-{
-}
-
-text_glob::~text_glob ()
-{
- if (tab != NULL)
- delete tab;
-}
-
-/*
- * text_glob_html - used to place html text into the glob buffer.
- */
-
-void text_glob::text_glob_html (style *s, char *str, int length,
- int min_vertical , int min_horizontal,
- int max_vertical , int max_horizontal)
-{
- text_glob *g = new text_glob(s, str, length,
- min_vertical, min_horizontal, max_vertical, max_horizontal,
- FALSE, FALSE, FALSE, FALSE, 0);
- *this = *g;
-}
-
-/*
- * text_glob_html - used to place html specials into the glob buffer.
- * This text is essentially html commands coming through
- * from the macro sets, with special designated sequences of
- * characters translated into html. See add_and_encode.
- */
-
-void text_glob::text_glob_special (style *s, char *str, int length,
- int min_vertical , int min_horizontal,
- int max_vertical , int max_horizontal)
-{
- text_glob *g = new text_glob(s, str, length,
- min_vertical, min_horizontal, max_vertical, max_horizontal,
- FALSE, FALSE, TRUE, FALSE, 0);
- *this = *g;
-}
-
-/*
- * text_glob_line - record horizontal draw line commands.
- */
-
-void text_glob::text_glob_line (style *s,
- int min_vertical , int min_horizontal,
- int max_vertical , int max_horizontal,
- int thickness)
-{
- text_glob *g = new text_glob(s, "", 0,
- min_vertical, min_horizontal, max_vertical, max_horizontal,
- FALSE, FALSE, FALSE, TRUE, thickness);
- *this = *g;
-}
-
-/*
- * text_glob_auto_image - record the presence of a .auto-image tag command.
- * Used to mark that an image has been created automatically
- * by a preprocessor and (pre-grohtml/troff) combination.
- * Under some circumstances images may not be created.
- * (consider .EQ
- * delim $$
- * .EN
- * .TS
- * tab(!), center;
- * l!l.
- * $1 over x$!recripical of x
- * .TE
- *
- * the first auto-image marker is created via .EQ/.EN pair
- * and no image is created.
- * The second auto-image marker occurs at $1 over x$
- * Currently this image will not be created
- * as the whole of the table is created as an image.
- * (Once html tables are handled by grohtml this will change.
- * Shortly this will be the case).
- */
-
-void text_glob::text_glob_auto_image(style *s, char *str, int length,
- int min_vertical, int min_horizontal,
- int max_vertical, int max_horizontal)
-{
- text_glob *g = new text_glob(s, str, length,
- min_vertical, min_horizontal, max_vertical, max_horizontal,
- TRUE, TRUE, FALSE, FALSE, 0);
- *this = *g;
-}
-
-/*
- * text_glob_tag - records a troff tag.
- */
-
-void text_glob::text_glob_tag (style *s, char *str, int length,
- int min_vertical, int min_horizontal,
- int max_vertical, int max_horizontal)
-{
- text_glob *g = new text_glob(s, str, length,
- min_vertical, min_horizontal, max_vertical, max_horizontal,
- TRUE, FALSE, FALSE, FALSE, 0);
- *this = *g;
-}
-
-/*
- * is_a_line - returns TRUE if glob should be converted into an <hr>
- */
-
-int text_glob::is_a_line (void)
-{
- return is_line;
-}
-
-/*
- * is_a_tag - returns TRUE if glob contains a troff directive.
- */
-
-int text_glob::is_a_tag (void)
-{
- return is_tag;
-}
-
-/*
- * is_eol - returns TRUE if glob contains the tag eol
- */
-
-int text_glob::is_eol (void)
-{
- return( is_tag && (strcmp(text_string, "html-tag:eol") == 0) );
-}
-
-/*
- * is_eol_ce - returns TRUE if glob contains the tag eol.ce
- */
-
-int text_glob::is_eol_ce (void)
-{
- return( is_tag && (strcmp(text_string, "html-tag:eol.ce") == 0) );
-}
-
-
-/*
- * is_nf - returns TRUE if glob contains the tag .nf
- */
-
-int text_glob::is_nf (void)
-{
- return( is_tag && (strcmp(text_string, "html-tag:.nf") == 0) );
-}
-
-/*
- * is_fi - returns TRUE if glob contains the tag .fi
- */
-
-int text_glob::is_fi (void)
-{
- return( is_tag && (strcmp(text_string, "html-tag:.fi") == 0) );
-}
-
-/*
- * is_ce - returns TRUE if glob contains the tag .ce
- */
-
-int text_glob::is_ce (void)
-{
- return( is_tag && (strcmp(text_string, "html-tag:.ce") == 0) );
-}
-
-/*
- * is_in - returns TRUE if glob contains the tag .in
- */
-
-int text_glob::is_in (void)
-{
- return( is_tag && (strncmp(text_string, "html-tag:.in ", strlen("html-tag:.in ")) == 0) );
-}
-
-/*
- * is_po - returns TRUE if glob contains the tag .po
- */
-
-int text_glob::is_po (void)
-{
- return( is_tag && (strncmp(text_string, "html-tag:.po ", strlen("html-tag:.po ")) == 0) );
-}
-
-/*
- * is_ti - returns TRUE if glob contains the tag .ti
- */
-
-int text_glob::is_ti (void)
-{
- return( is_tag && (strncmp(text_string, "html-tag:.ti ", strlen("html-tag:.ti ")) == 0) );
-}
-
-/*
- * is_col - returns TRUE if glob contains the tag .col
- */
-
-int text_glob::is_col (void)
-{
- return( is_tag && (strncmp(text_string, "html-tag:.col", strlen("html-tag:.col")) == 0) );
-}
-
-/*
- * is_tab_ts - returns TRUE if glob contains the tag .tab_ts
- */
-
-int text_glob::is_tab_ts (void)
-{
- return( is_tag && (strcmp(text_string, "html-tag:.tab-ts") == 0) );
-}
-
-/*
- * is_tab_te - returns TRUE if glob contains the tag .tab_te
- */
-
-int text_glob::is_tab_te (void)
-{
- return( is_tag && (strcmp(text_string, "html-tag:.tab-te") == 0) );
-}
-
-/*
- * is_ta - returns TRUE if glob contains the tag .ta
- */
-
-int text_glob::is_ta (void)
-{
- return( is_tag && (strncmp(text_string, "html-tag:.ta ", strlen("html-tag:.ta ")) == 0) );
-}
-
-/*
- * is_tab - returns TRUE if glob contains the tag tab
- */
-
-int text_glob::is_tab (void)
-{
- return( is_tag && (strncmp(text_string, "html-tag:tab ", strlen("html-tag:tab ")) == 0) );
-}
-
-/*
- * is_tab0 - returns TRUE if glob contains the tag tab0
- */
-
-int text_glob::is_tab0 (void)
-{
- return( is_tag && (strncmp(text_string, "html-tag:tab0", strlen("html-tag:tab0")) == 0) );
-}
-
-/*
- * is_auto_img - returns TRUE if the glob contains an automatically
- * generated image.
- */
-
-int text_glob::is_auto_img (void)
-{
- return is_img_auto;
-}
-
-/*
- * is_br - returns TRUE if the glob is a tag containing a .br
- * or an implied .br. Note that we do not include .nf or .fi
- * as grohtml will place a .br after these commands if they
- * should break the line.
- */
-
-int text_glob::is_br (void)
-{
- return( is_a_tag() && ((strcmp ("html-tag:.br", text_string) == 0) ||
- (strncmp("html-tag:.sp", text_string, 11) == 0) ||
- (strcmp ("html-tag:.ce", text_string) == 0)) );
-}
-
-int text_glob::get_arg (void)
-{
- if (strncmp("html-tag:", text_string, strlen("html-tag:")) == 0) {
- const char *p = text_string;
-
- while ((*p != (char)0) && (!isspace(*p)))
- p++;
- while ((*p != (char)0) && (isspace(*p)))
- p++;
- if (*p == (char)0)
- return -1;
- return atoi(p);
- }
- return -1;
-}
-
-/*
- * get_tab_args - returns the tab position and alignment of the tab tag
- */
-
-int text_glob::get_tab_args (char *align)
-{
- if (strncmp("html-tag:", text_string, strlen("html-tag:")) == 0) {
- const char *p = text_string;
-
- // firstly the alignment C|R|L
- while ((*p != (char)0) && (!isspace(*p)))
- p++;
- while ((*p != (char)0) && (isspace(*p)))
- p++;
- *align = *p;
- // now the int value
- while ((*p != (char)0) && (!isspace(*p)))
- p++;
- while ((*p != (char)0) && (isspace(*p)))
- p++;
- if (*p == (char)0)
- return -1;
- return atoi(p);
- }
- return -1;
-}
-
-/*
- * remember_table - saves table, t, in the text_glob.
- */
-
-void text_glob::remember_table (html_table *t)
-{
- tab = t;
-}
-
-/*
- * get_table - returns the stored table description.
- */
-
-html_table *text_glob::get_table (void)
-{
- return tab;
-}
-
-/*
- * the class and methods used to construct ordered double linked lists.
- * In a previous implementation we used templates via #include "ordered-list.h",
- * but this does assume that all C++ compilers can handle this feature. Pragmatically
- * it is safer to assume this is not the case.
- */
-
-struct element_list {
- element_list *right;
- element_list *left;
- text_glob *datum;
- int lineno;
- int minv, minh, maxv, maxh;
-
- element_list (text_glob *d,
- int line_number,
- int min_vertical, int min_horizontal,
- int max_vertical, int max_horizontal);
- element_list ();
-};
-
-element_list::element_list ()
- : right(0), left(0), datum(0), lineno(0), minv(-1), minh(-1), maxv(-1), maxh(-1)
-{
-}
-
-/*
- * element_list - create a list element assigning the datum and region parameters.
- */
-
-element_list::element_list (text_glob *in,
- int line_number,
- int min_vertical, int min_horizontal,
- int max_vertical, int max_horizontal)
- : right(0), left(0), datum(in), lineno(line_number),
- minv(min_vertical), minh(min_horizontal), maxv(max_vertical), maxh(max_horizontal)
-{
-}
-
-class list {
-public:
- list ();
- ~list ();
- int is_less (element_list *a, element_list *b);
- void add (text_glob *in,
- int line_number,
- int min_vertical, int min_horizontal,
- int max_vertical, int max_horizontal);
- void sub_move_right (void);
- void move_right (void);
- void move_left (void);
- int is_empty (void);
- int is_equal_to_tail (void);
- int is_equal_to_head (void);
- void start_from_head (void);
- void start_from_tail (void);
- void insert (text_glob *in);
- void move_to (text_glob *in);
- text_glob *move_right_get_data (void);
- text_glob *move_left_get_data (void);
- text_glob *get_data (void);
-private:
- element_list *head;
- element_list *tail;
- element_list *ptr;
-};
-
-/*
- * list - construct an empty list.
- */
-
-list::list ()
- : head(0), tail(0), ptr(0)
-{
-}
-
-/*
- * ~list - destroy a complete list.
- */
-
-list::~list()
-{
- element_list *temp=head;
-
- do {
- temp = head;
- if (temp != 0) {
- head = head->right;
- delete temp;
- }
- } while ((head != 0) && (head != tail));
-}
-
-/*
- * is_less - returns TRUE if a is left of b if on the same line or
- * if a is higher up the page than b.
- */
-
-int list::is_less (element_list *a, element_list *b)
-{
- // was if (is_intersection(a->minv+1, a->maxv-1, b->minv+1, b->maxv-1)) {
- if (a->lineno < b->lineno) {
- return( TRUE );
- } else if (a->lineno > b->lineno) {
- return( FALSE );
- } else if (is_intersection(a->minv, a->maxv, b->minv, b->maxv)) {
- return( a->minh < b->minh );
- } else {
- return( a->maxv < b->maxv );
- }
-}
-
-/*
- * add - adds a datum to the list in the order specified by the region position.
- */
-
-void list::add (text_glob *in, int line_number, int min_vertical, int min_horizontal, int max_vertical, int max_horizontal)
-{
- // create a new list element with datum and position fields initialized
- element_list *t = new element_list(in, line_number, min_vertical, min_horizontal, max_vertical, max_horizontal);
- element_list *last;
-
- if (head == 0) {
- head = t;
- tail = t;
- ptr = t;
- t->left = t;
- t->right = t;
- } else {
- last = tail;
-
- while ((last != head) && (is_less(t, last))) {
- last = last->left;
- }
-
- if (is_less(t, last)) {
- t->right = last;
- last->left->right = t;
- t->left = last->left;
- last->left = t;
- // now check for a new head
- if (last == head) {
- head = t;
- }
- } else {
- // add t beyond last
- t->right = last->right;
- t->left = last;
- last->right->left = t;
- last->right = t;
- // now check for a new tail
- if (last == tail) {
- tail = t;
- }
- }
- }
-}
-
-/*
- * sub_move_right - removes the element which is currently pointed to by ptr
- * from the list and moves ptr to the right.
- */
-
-void list::sub_move_right (void)
-{
- element_list *t=ptr->right;
-
- if (head == tail) {
- head = 0;
- if (tail != 0) {
- delete tail;
- }
- tail = 0;
- ptr = 0;
- } else {
- if (head == ptr) {
- head = head->right;
- }
- if (tail == ptr) {
- tail = tail->left;
- }
- ptr->left->right = ptr->right;
- ptr->right->left = ptr->left;
- ptr=t;
- }
-}
-
-/*
- * start_from_head - assigns ptr to the head.
- */
-
-void list::start_from_head (void)
-{
- ptr = head;
-}
-
-/*
- * start_from_tail - assigns ptr to the tail.
- */
-
-void list::start_from_tail (void)
-{
- ptr = tail;
-}
-
-/*
- * is_empty - returns TRUE if the list has no elements.
- */
-
-int list::is_empty (void)
-{
- return( head == 0 );
-}
-
-/*
- * is_equal_to_tail - returns TRUE if the ptr equals the tail.
- */
-
-int list::is_equal_to_tail (void)
-{
- return( ptr == tail );
-}
-
-/*
- * is_equal_to_head - returns TRUE if the ptr equals the head.
- */
-
-int list::is_equal_to_head (void)
-{
- return( ptr == head );
-}
-
-/*
- * move_left - moves the ptr left.
- */
-
-void list::move_left (void)
-{
- ptr = ptr->left;
-}
-
-/*
- * move_right - moves the ptr right.
- */
-
-void list::move_right (void)
-{
- ptr = ptr->right;
-}
-
-/*
- * get_datum - returns the datum referenced via ptr.
- */
-
-text_glob* list::get_data (void)
-{
- return( ptr->datum );
-}
-
-/*
- * move_right_get_data - returns the datum referenced via ptr and moves
- * ptr right.
- */
-
-text_glob* list::move_right_get_data (void)
-{
- ptr = ptr->right;
- if (ptr == head) {
- return( 0 );
- } else {
- return( ptr->datum );
- }
-}
-
-/*
- * move_left_get_data - returns the datum referenced via ptr and moves
- * ptr right.
- */
-
-text_glob* list::move_left_get_data (void)
-{
- ptr = ptr->left;
- if (ptr == tail) {
- return( 0 );
- } else {
- return( ptr->datum );
- }
-}
-
-/*
- * insert - inserts data after the current position.
- */
-
-void list::insert (text_glob *in)
-{
- if (is_empty())
- fatal("list must not be empty if we are inserting data");
- else {
- if (ptr == 0)
- ptr = head;
-
- element_list *t = new element_list(in, ptr->lineno, ptr->minv, ptr->minh, ptr->maxv, ptr->maxh);
- if (ptr == tail)
- tail = t;
- ptr->right->left = t;
- t->right = ptr->right;
- ptr->right = t;
- t->left = ptr;
- }
-}
-
-/*
- * move_to - moves the current position to the point where data, in, exists.
- * This is an expensive method and should be used sparingly.
- */
-
-void list::move_to (text_glob *in)
-{
- ptr = head;
- while (ptr != tail && ptr->datum != in)
- ptr = ptr->right;
-}
-
-/*
- * page class and methods
- */
-
-class page {
-public:
- page (void);
- void add (style *s, const string &str,
- int line_number,
- int min_vertical, int min_horizontal,
- int max_vertical, int max_horizontal);
- void add_tag (style *s, const string &str,
- int line_number,
- int min_vertical, int min_horizontal,
- int max_vertical, int max_horizontal);
- void add_and_encode (style *s, const string &str,
- int line_number,
- int min_vertical, int min_horizontal,
- int max_vertical, int max_horizontal);
- void add_line (style *s,
- int line_number,
- int x1, int y1, int x2, int y2,
- int thickness);
- void insert_tag (const string &str);
- void dump_page (void); // debugging method
-
- // and the data
-
- list glyphs; // position of glyphs and specials on page
- char_buffer buffer; // all characters for this page
-};
-
-page::page()
-{
-}
-
-/*
- * insert_tag - inserts a tag after the current position.
- */
-
-void page::insert_tag (const string &str)
-{
- if (str.length() > 0) {
- text_glob *g=new text_glob();
- text_glob *f=glyphs.get_data();
- g->text_glob_tag(&f->text_style, buffer.add_string(str), str.length(),
- f->minv, f->minh, f->maxv, f->maxh);
- glyphs.insert(g);
- }
-}
-
-/*
- * add - add html text to the list of glyphs.
- */
-
-void page::add (style *s, const string &str,
- int line_number,
- int min_vertical, int min_horizontal,
- int max_vertical, int max_horizontal)
-{
- if (str.length() > 0) {
- text_glob *g=new text_glob();
- g->text_glob_html(s, buffer.add_string(str), str.length(),
- min_vertical, min_horizontal, max_vertical, max_horizontal);
- glyphs.add(g, line_number, min_vertical, min_horizontal, max_vertical, max_horizontal);
- }
-}
-
-/*
- * add_tag - adds a troff tag, for example: .tl .sp .br
- */
-
-void page::add_tag (style *s, const string &str,
- int line_number,
- int min_vertical, int min_horizontal,
- int max_vertical, int max_horizontal)
-{
- if (str.length() > 0) {
- text_glob *g;
-
- if (strncmp((str+'\0').contents(), "html-tag:.auto-image", 20) == 0) {
- g = new text_glob();
- g->text_glob_auto_image(s, buffer.add_string(str), str.length(),
- min_vertical, min_horizontal, max_vertical, max_horizontal);
- } else {
- g = new text_glob();
- g->text_glob_tag(s, buffer.add_string(str), str.length(),
- min_vertical, min_horizontal, max_vertical, max_horizontal);
- }
- glyphs.add(g, line_number, min_vertical, min_horizontal, max_vertical, max_horizontal);
- }
-}
-
-/*
- * add_line - adds the <line> primitive providing that y1==y2
- */
-
-void page::add_line (style *s,
- int line_number,
- int x1, int y1, int x2, int y2,
- int thickness)
-{
- if (y1 == y2) {
- text_glob *g = new text_glob();
- g->text_glob_line(s,
- min(y1, y2), min(x1, y2), max(y1, y2), max(x1, x2),
- thickness);
- glyphs.add(g, line_number, min(y1, y2), min(x1, y2), max(y1, y2), max(x1, x2));
- }
-}
-
-/*
- * to_unicode - returns a unicode translation of int, ch.
- */
-
-static char *to_unicode (unsigned int ch)
-{
- static char buf[30];
-
- sprintf(buf, "&#%u;", ch);
- return buf;
-}
-
-/*
- * add_and_encode - adds a special string to the page, it translates the string
- * into html glyphs. The special string will have come from x X html:
- * and can contain troff character encodings which appear as
- * \(char\). A sequence of \\ represents \.
- * So for example we can write:
- * "cost = \(Po\)3.00 file = \\foo\\bar"
- * which is translated into:
- * "cost = &pound;3.00 file = \foo\bar"
- */
-
-void page::add_and_encode (style *s, const string &str,
- int line_number,
- int min_vertical, int min_horizontal,
- int max_vertical, int max_horizontal)
-{
- string html_string;
- char *html_glyph;
- int i=0;
-
- if (s->f == NULL)
- return;
- while (i < str.length()) {
- if ((i+1<str.length()) && (str.substring(i, 2) == string("\\("))) {
- // start of escape
- i += 2; // move over \(
- int a = i;
- while ((i+1<str.length()) && (str.substring(i, 2) != string("\\)"))) {
- i++;
- }
- int n = i;
- if ((i+1<str.length()) && (str.substring(i, 2) == string("\\)")))
- i++;
- else
- n = -1;
- if (n > 0) {
- string troff_charname = str.substring(a, n-a);
- html_glyph = get_html_translation(s->f, troff_charname);
- if (html_glyph)
- html_string += html_glyph;
- else {
- int index=s->f->name_to_index((troff_charname + '\0').contents());
-
- if (s->f->contains(index) && (index != 0))
- html_string += s->f->get_code(index);
- }
- }
- } else
- html_string += str[i];
- i++;
- }
- if (html_string.length() > 0) {
- text_glob *g=new text_glob();
- g->text_glob_special(s, buffer.add_string(html_string), html_string.length(),
- min_vertical, min_horizontal, max_vertical, max_horizontal);
- glyphs.add(g, line_number, min_vertical, min_horizontal, max_vertical, max_horizontal);
- }
-}
-
-/*
- * dump_page - dump the page contents for debugging purposes.
- */
-
-void page::dump_page(void)
-{
-#if defined(DEBUG_TABLES)
- text_glob *old_pos = glyphs.get_data();
- text_glob *g;
-
- printf("\n<!--\n");
- printf("\n\ndebugging start\n");
- glyphs.start_from_head();
- do {
- g = glyphs.get_data();
- if (g->is_tab_ts()) {
- printf("\n\n");
- if (g->get_table() != NULL)
- g->get_table()->dump_table();
- }
- printf("%s ", g->text_string);
- if (g->is_tab_te())
- printf("\n\n");
- glyphs.move_right();
- } while (! glyphs.is_equal_to_head());
- glyphs.move_to(old_pos);
- printf("\ndebugging end\n\n");
- printf("\n-->\n");
- fflush(stdout);
-#endif
-}
-
-/*
- * font classes and methods
- */
-
-class html_font : public font {
- html_font(const char *);
-public:
- int encoding_index;
- char *encoding;
- char *reencoded_name;
- ~html_font();
- static html_font *load_html_font(const char *);
-};
-
-html_font *html_font::load_html_font(const char *s)
-{
- html_font *f = new html_font(s);
- if (!f->load()) {
- delete f;
- return 0;
- }
- return f;
-}
-
-html_font::html_font(const char *nm)
-: font(nm)
-{
-}
-
-html_font::~html_font()
-{
-}
-
-/*
- * a simple class to contain the header to this document
- */
-
-class title_desc {
-public:
- title_desc ();
- ~title_desc ();
-
- int has_been_written;
- int has_been_found;
- int with_h1;
- string text;
-};
-
-
-title_desc::title_desc ()
- : has_been_written(FALSE), has_been_found(FALSE), with_h1(FALSE)
-{
-}
-
-title_desc::~title_desc ()
-{
-}
-
-class header_desc {
-public:
- header_desc ();
- ~header_desc ();
-
- int no_of_headings; // how many headings have we found?
- char_buffer headings; // all the headings used in the document
- list headers; // list of headers built from .NH and .SH
- int header_level; // current header level
- int written_header; // have we written the header yet?
- string header_buffer; // current header text
-
- void write_headings (FILE *f, int force);
-};
-
-header_desc::header_desc ()
- : no_of_headings(0), header_level(2), written_header(0)
-{
-}
-
-header_desc::~header_desc ()
-{
-}
-
-/*
- * write_headings - emits a list of links for the headings in this document
- */
-
-void header_desc::write_headings (FILE *f, int force)
-{
- text_glob *g;
-
- if (auto_links || force) {
- if (! headers.is_empty()) {
- int h=1;
-
- headers.start_from_head();
- do {
- g = headers.get_data();
- fputs("<a href=\"#", f);
- if (simple_anchors) {
- string buffer(ANCHOR_TEMPLATE);
-
- buffer += as_string(h);
- buffer += '\0';
- fprintf(f, buffer.contents());
- } else
- fputs(g->text_string, f);
- h++;
- fputs("\">", f);
- fputs(g->text_string, f);
- fputs("</a><br>\n", f);
- headers.move_right();
- } while (! headers.is_equal_to_head());
- fputs("\n", f);
- }
- }
-}
-
-class html_printer : public printer {
- files file_list;
- simple_output html;
- int res;
- int space_char_index;
- int space_width;
- int no_of_printed_pages;
- int paper_length;
- string sbuf;
- int sbuf_start_hpos;
- int sbuf_vpos;
- int sbuf_end_hpos;
- int sbuf_prev_hpos;
- int sbuf_kern;
- style sbuf_style;
- int last_sbuf_length;
- int overstrike_detected;
- style output_style;
- int output_hpos;
- int output_vpos;
- int output_vpos_max;
- int output_draw_point_size;
- int line_thickness;
- int output_line_thickness;
- unsigned char output_space_code;
- char *inside_font_style;
- int page_number;
- title_desc title;
- header_desc header;
- int header_indent;
- int supress_sub_sup;
- int cutoff_heading;
- page *page_contents;
- html_text *current_paragraph;
- html_indent *indent;
- html_table *table;
- int end_center;
- int end_tempindent;
- TAG_ALIGNMENT next_tag;
- int fill_on;
- int max_linelength;
- int linelength;
- int pageoffset;
- int indentation;
- int prev_indent;
- int pointsize;
- int vertical_spacing;
- int line_number;
- color *background;
-
- void flush_sbuf ();
- void set_style (const style &);
- void set_space_code (unsigned char c);
- void do_exec (char *, const environment *);
- void do_import (char *, const environment *);
- void do_def (char *, const environment *);
- void do_mdef (char *, const environment *);
- void do_file (char *, const environment *);
- void set_line_thickness (const environment *);
- void terminate_current_font (void);
- void flush_font (void);
- void add_to_sbuf (int index, const string &s);
- void write_title (int in_head);
- int sbuf_continuation (int index, const char *name, const environment *env, int w);
- void flush_page (void);
- void troff_tag (text_glob *g);
- void flush_globs (void);
- void emit_line (text_glob *g);
- void emit_raw (text_glob *g);
- void emit_html (text_glob *g);
- void determine_space (text_glob *g);
- void start_font (const char *name);
- void end_font (const char *name);
- int is_font_courier (font *f);
- int is_courier_until_eol (void);
- void start_size (int from, int to);
- void do_font (text_glob *g);
- void do_center (char *arg);
- void do_break (void);
- void do_eol (void);
- void do_eol_ce (void);
- void do_title (void);
- void do_fill (int on);
- void do_heading (char *arg);
- void write_header (void);
- void determine_header_level (int level);
- void do_linelength (char *arg);
- void do_pageoffset (char *arg);
- void do_indentation (char *arg);
- void do_tempindent (char *arg);
- void do_indentedparagraph (void);
- void do_verticalspacing (char *arg);
- void do_pointsize (char *arg);
- void do_centered_image (void);
- void do_left_image (void);
- void do_right_image (void);
- void do_auto_image (text_glob *g, const char *filename);
- void do_links (void);
- void do_flush (void);
- int is_in_middle (int left, int right);
- void do_sup_or_sub (text_glob *g);
- int start_subscript (text_glob *g);
- int end_subscript (text_glob *g);
- int start_superscript (text_glob *g);
- int end_superscript (text_glob *g);
- void outstanding_eol (int n);
- int is_bold (font *f);
- font *make_bold (font *f);
- int overstrike (int index, const char *name, const environment *env, int w);
- void do_body (void);
- int next_horiz_pos (text_glob *g, int nf);
- void lookahead_for_tables (void);
- void insert_tab_te (void);
- text_glob *insert_tab_ts (text_glob *where);
- void insert_tab0_foreach_tab (void);
- void insert_tab_0 (text_glob *where);
- void do_indent (int in, int pageoff, int linelen);
- void shutdown_table (void);
- void do_tab_ts (text_glob *g);
- void do_tab_te (void);
- void do_col (char *s);
- void do_tab (char *s);
- void do_tab0 (void);
- int calc_nf (text_glob *g, int nf);
- void calc_po_in (text_glob *g, int nf);
- void remove_tabs (void);
- void remove_courier_tabs (void);
- void update_min_max (colType type_of_col, int *minimum, int *maximum, text_glob *g);
- void add_table_end (char *debug_string);
- // ADD HERE
-
-public:
- html_printer ();
- ~html_printer ();
- void set_char (int i, font *f, const environment *env, int w, const char *name);
- void draw (int code, int *p, int np, const environment *env);
- void begin_page (int);
- void end_page (int);
- void special (char *arg, const environment *env, char type);
- font *make_font (const char *);
- void end_of_line ();
-};
-
-printer *make_printer()
-{
- return new html_printer;
-}
-
-static void usage(FILE *stream);
-
-void html_printer::set_style(const style &sty)
-{
- const char *fontname = sty.f->get_name();
- if (fontname == NULL)
- fatal("no internalname specified for font");
-
-#if 0
- change_font(fontname, (font::res/(72*font::sizescale))*sty.point_size);
-#endif
-}
-
-/*
- * is_bold - returns TRUE if font, f, is bold.
- */
-
-int html_printer::is_bold (font *f)
-{
- const char *fontname = f->get_name();
- return (strcmp(fontname, "B") == 0) || (strcmp(fontname, "BI") == 0);
-}
-
-/*
- * make_bold - if a bold font of, f, exists then return it.
- */
-
-font *html_printer::make_bold (font *f)
-{
- const char *fontname = f->get_name();
-
- if (strcmp(fontname, "B") == 0)
- return f;
- if (strcmp(fontname, "I") == 0)
- return font::load_font("BI");
- if (strcmp(fontname, "BI") == 0)
- return f;
- return NULL;
-}
-
-void html_printer::end_of_line()
-{
- flush_sbuf();
- line_number++;
-}
-
-/*
- * emit_line - writes out a horizontal rule.
- */
-
-void html_printer::emit_line (text_glob *g)
-{
- // --fixme-- needs to know the length in percentage
- html.put_string("<hr>");
-}
-
-/*
- * emit_raw - writes the raw html information directly to the device.
- */
-
-void html_printer::emit_raw (text_glob *g)
-{
- do_font(g);
- if (next_tag == INLINE) {
- determine_space(g);
- current_paragraph->do_emittext(g->text_string, g->text_length);
- } else {
- current_paragraph->done_para();
- switch (next_tag) {
-
- case CENTERED:
- current_paragraph->do_para("align=center");
- break;
- case LEFT:
- current_paragraph->do_para(&html, "align=left", indentation, pageoffset, linelength);
- break;
- case RIGHT:
- current_paragraph->do_para(&html, "align=right", indentation, pageoffset, linelength);
- break;
- default:
- fatal("unknown enumeration");
- }
- current_paragraph->do_emittext(g->text_string, g->text_length);
- current_paragraph->done_para();
- next_tag = INLINE;
- supress_sub_sup = TRUE;
- if (indentation > 0) {
- /*
- * restore indentation
- */
- int newin = indentation;
- indentation = 0;
- do_indent(newin, pageoffset, linelength);
- }
- }
-}
-
-/*
- * do_center - handle the .ce commands from troff.
- */
-
-void html_printer::do_center (char *arg)
-{
- int n = atoi(arg);
- current_paragraph->do_break();
-
- if (n > 0) {
- current_paragraph->done_para();
- supress_sub_sup = TRUE;
- current_paragraph->do_para("align=center");
- end_center += n;
- } else {
- end_center = 0;
- current_paragraph->remove_para_align();
- }
-}
-
-/*
- * do_centered_image - set a flag such that the next html-tag is
- * placed inside a centered paragraph.
- */
-
-void html_printer::do_centered_image (void)
-{
- next_tag = CENTERED;
-}
-
-/*
- * do_right_image - set a flag such that the next html-tag is
- * placed inside a right aligned paragraph.
- */
-
-void html_printer::do_right_image (void)
-{
- next_tag = RIGHT;
-}
-
-/*
- * do_left_image - set a flag such that the next html-tag is
- * placed inside a left aligned paragraph.
- */
-
-void html_printer::do_left_image (void)
-{
- next_tag = LEFT;
-}
-
-/*
- * exists - returns TRUE if filename exists.
- */
-
-static int exists (const char *filename)
-{
- FILE *fp = fopen(filename, "r");
-
- if (fp == 0) {
- return( FALSE );
- } else {
- fclose(fp);
- return( TRUE );
- }
-}
-
-/*
- * generate_img_src - returns a html image tag for the filename
- * providing that the image exists.
- */
-
-static string &generate_img_src (const char *filename)
-{
- string *s = new string("");
-
- while (filename && (filename[0] == ' ')) {
- filename++;
- }
- if (exists(filename))
- *s += string("<img src=\"") + filename + "\">";
- return *s;
-}
-
-/*
- * do_auto_image - tests whether the image, indicated by filename,
- * is present, if so then it emits an html image tag.
- * An image tag may be passed through from pic, eqn
- * but the corresponding image might not be created.
- * Consider .EQ delim $$ .EN or an empty .PS .PE.
- */
-
-void html_printer::do_auto_image (text_glob *g, const char *filename)
-{
- string buffer = generate_img_src(filename);
-
- if (! buffer.empty()) {
- /*
- * utilize emit_raw by creating a new text_glob.
- */
- text_glob h = *g;
-
- h.text_string = buffer.contents();
- h.text_length = buffer.length();
- emit_raw(&h);
- } else
- next_tag = INLINE;
-}
-
-/*
- * outstanding_eol - call do_eol, n, times.
- */
-
-void html_printer::outstanding_eol (int n)
-{
- while (n > 0) {
- do_eol();
- n--;
- }
-}
-
-/*
- * do_title - handle the .tl commands from troff.
- */
-
-void html_printer::do_title (void)
-{
- text_glob *t;
- int removed_from_head;
- int eol_ce = 0;
-
- if (page_number == 1) {
- int found_title_start = FALSE;
- if (! page_contents->glyphs.is_empty()) {
- page_contents->glyphs.sub_move_right(); /* move onto next word */
- do {
- t = page_contents->glyphs.get_data();
- removed_from_head = FALSE;
- if (t->is_auto_img()) {
- string img = generate_img_src((char *)(t->text_string + 20));
-
- if (! img.empty()) {
- if (found_title_start)
- title.text += " ";
- found_title_start = TRUE;
- title.has_been_found = TRUE;
- title.text += img;
- }
- page_contents->glyphs.sub_move_right(); /* move onto next word */
- removed_from_head = ((!page_contents->glyphs.is_empty()) &&
- (page_contents->glyphs.is_equal_to_head()));
- } else if (t->is_eol_ce()) {
- /* process the eol associated with .ce
- */
- eol_ce++;
- page_contents->glyphs.sub_move_right(); /* move onto next word */
- } else if (t->is_eol()) {
- /* end of title found
- */
- title.has_been_found = TRUE;
- outstanding_eol(eol_ce);
- return;
- } else if (t->is_a_tag()) {
- /* end of title found, but move back so that we read this tag and process it
- */
- page_contents->glyphs.move_left(); /* move backwards to last word */
- title.has_been_found = TRUE;
- outstanding_eol(eol_ce);
- return;
- } else if (found_title_start) {
- title.text += " " + string(t->text_string, t->text_length);
- page_contents->glyphs.sub_move_right(); /* move onto next word */
- removed_from_head = ((!page_contents->glyphs.is_empty()) &&
- (page_contents->glyphs.is_equal_to_head()));
- } else {
- title.text += string(t->text_string, t->text_length);
- found_title_start = TRUE;
- title.has_been_found = TRUE;
- page_contents->glyphs.sub_move_right(); /* move onto next word */
- removed_from_head = ((!page_contents->glyphs.is_empty()) &&
- (page_contents->glyphs.is_equal_to_head()));
- }
- } while ((! page_contents->glyphs.is_equal_to_head()) || (removed_from_head));
- }
- outstanding_eol(eol_ce);
- }
-}
-
-void html_printer::write_header (void)
-{
- if (! header.header_buffer.empty()) {
- if (header.header_level > 7) {
- header.header_level = 7;
- }
-
- // firstly we must terminate any font and type faces
- current_paragraph->done_para();
- supress_sub_sup = TRUE;
-
- if (cutoff_heading+2 > header.header_level) {
- // now we save the header so we can issue a list of links
- header.no_of_headings++;
- style st;
-
- text_glob *h=new text_glob();
- h->text_glob_html(&st,
- header.headings.add_string(header.header_buffer),
- header.header_buffer.length(),
- header.no_of_headings, header.header_level,
- header.no_of_headings, header.header_level);
-
- header.headers.add(h,
- header.no_of_headings,
- header.no_of_headings, header.no_of_headings,
- header.no_of_headings, header.no_of_headings); // and add this header to the header list
-
- // lastly we generate a tag
-
- html.nl().put_string("<a name=\"");
- if (simple_anchors) {
- string buffer(ANCHOR_TEMPLATE);
-
- buffer += as_string(header.no_of_headings);
- buffer += '\0';
- html.put_string(buffer.contents());
- } else {
- html.put_string(header.header_buffer);
- }
- html.put_string("\"></a>").nl();
- }
-
- if (manufacture_headings) {
- // line break before a header
- if (!current_paragraph->emitted_text())
- current_paragraph->do_space();
- // user wants manufactured headings which look better than <Hn></Hn>
- if (header.header_level<4) {
- html.put_string("<b><font size=\"+1\">");
- html.put_string(header.header_buffer);
- html.put_string("</font></b>").nl();
- }
- else {
- html.put_string("<b>");
- html.put_string(header.header_buffer);
- html.put_string("</b>").nl();
- }
- }
- else {
- // and now we issue the real header
- html.put_string("<h");
- html.put_number(header.header_level);
- html.put_string(">");
- html.put_string(header.header_buffer);
- html.put_string("</h");
- html.put_number(header.header_level);
- html.put_string(">").nl();
- }
-
- current_paragraph->do_para(&html, "", indentation, pageoffset, linelength);
- }
-}
-
-void html_printer::determine_header_level (int level)
-{
- if (level == 0) {
- int i;
-
- for (i=0; ((i<header.header_buffer.length())
- && ((header.header_buffer[i] == '.')
- || is_digit(header.header_buffer[i]))) ; i++) {
- if (header.header_buffer[i] == '.') {
- level++;
- }
- }
- }
- header.header_level = level+1;
-}
-
-/*
- * do_heading - handle the .SH and .NH and equivalent commands from troff.
- */
-
-void html_printer::do_heading (char *arg)
-{
- text_glob *g;
- text_glob *l = 0;
- int level=atoi(arg);
-
- header.header_buffer.clear();
- page_contents->glyphs.move_right();
- if (! page_contents->glyphs.is_equal_to_head()) {
- g = page_contents->glyphs.get_data();
- do {
- if (g->is_auto_img()) {
- string img=generate_img_src((char *)(g->text_string + 20));
-
- if (! img.empty()) {
- simple_anchors = TRUE; // we cannot use full heading anchors with images
- if (l != 0)
- header.header_buffer += " ";
-
- l = g;
- header.header_buffer += img;
- }
- } else if (! (g->is_a_line() || g->is_a_tag())) {
- /*
- * we ignore tags commands when constructing a heading
- */
- if (l != 0)
- header.header_buffer += " ";
- l = g;
-
- header.header_buffer += string(g->text_string, g->text_length);
- }
- page_contents->glyphs.move_right();
- g = page_contents->glyphs.get_data();
- } while ((! page_contents->glyphs.is_equal_to_head()) &&
- (! g->is_br()));
- }
-
- determine_header_level(level);
- write_header();
-
- // finally set the output to neutral for after the header
- g = page_contents->glyphs.get_data();
- page_contents->glyphs.move_left(); // so that next time we use old g
-}
-
-/*
- * is_courier_until_eol - returns TRUE if we can see a whole line which is courier
- */
-
-int html_printer::is_courier_until_eol (void)
-{
- text_glob *orig = page_contents->glyphs.get_data();
- int result = TRUE;
- text_glob *g;
-
- if (! page_contents->glyphs.is_equal_to_tail()) {
- page_contents->glyphs.move_right();
- do {
- g = page_contents->glyphs.get_data();
- if (! g->is_a_tag() && (! is_font_courier(g->text_style.f)))
- result = FALSE;
- page_contents->glyphs.move_right();
- } while (result &&
- (! page_contents->glyphs.is_equal_to_head()) &&
- (! g->is_fi()) && (! g->is_eol()));
-
- /*
- * now restore our previous position.
- */
- while (page_contents->glyphs.get_data() != orig)
- page_contents->glyphs.move_left();
- }
- return result;
-}
-
-/*
- * do_linelength - handle the .ll command from troff.
- */
-
-void html_printer::do_linelength (char *arg)
-{
- if (max_linelength == -1)
- max_linelength = atoi(arg);
-
- if (fill_on)
- do_indent(indentation, pageoffset, atoi(arg));
-}
-
-/*
- * do_pageoffset - handle the .po command from troff.
- */
-
-void html_printer::do_pageoffset (char *arg)
-{
- if (fill_on)
- do_indent(indentation, atoi(arg), linelength);
-}
-
-/*
- * do_indentation - handle the .in command from troff.
- */
-
-void html_printer::do_indentation (char *arg)
-{
- if (fill_on)
- do_indent(atoi(arg), pageoffset, linelength);
-}
-
-/*
- * do_tempindent - handle the .ti command from troff.
- */
-
-void html_printer::do_tempindent (char *arg)
-{
- if (fill_on) {
- end_tempindent = 1;
- prev_indent = indentation;
- do_indent(atoi(arg), pageoffset, linelength);
- }
-}
-
-/*
- * shutdown_table - shuts down the current table.
- */
-
-void html_printer::shutdown_table (void)
-{
- if (table != NULL) {
- current_paragraph->done_para();
- table->emit_finish_table();
- // dont delete this table as it will be deleted when we destroy the text_glob
- table = NULL;
- }
-}
-
-/*
- * do_indent - remember the indent parameters and if
- * indent is > pageoff and indent has changed
- * then we start a html table to implement the indentation.
- */
-
-void html_printer::do_indent (int in, int pageoff, int linelen)
-{
- if ((indentation != -1) &&
- (pageoffset+indentation != in+pageoff)) {
-
- current_paragraph->done_para();
-
- indentation = in;
- pageoffset = pageoff;
- if (linelen <= max_linelength)
- linelength = linelen;
-
- current_paragraph->do_para(&html, "", indentation, pageoffset, max_linelength);
- }
-}
-
-/*
- * do_verticalspacing - handle the .vs command from troff.
- */
-
-void html_printer::do_verticalspacing (char *arg)
-{
- vertical_spacing = atoi(arg);
-}
-
-/*
- * do_pointsize - handle the .ps command from troff.
- */
-
-void html_printer::do_pointsize (char *arg)
-{
- pointsize = atoi(arg);
-}
-
-/*
- * do_fill - records whether troff has requested that text be filled.
- */
-
-void html_printer::do_fill (int on)
-{
- current_paragraph->do_break();
- output_hpos = indentation+pageoffset;
- supress_sub_sup = TRUE;
-
- if (fill_on != on) {
- if (on)
- current_paragraph->do_para("");
- else
- current_paragraph->do_pre();
- fill_on = on;
- }
-}
-
-/*
- * do_eol - handle the end of line
- */
-
-void html_printer::do_eol (void)
-{
- if (! fill_on) {
- if (current_paragraph->ever_emitted_text()) {
- current_paragraph->do_newline();
- current_paragraph->do_break();
- }
- }
- output_hpos = indentation+pageoffset;
-}
-
-/*
- * do_eol_ce - handle end of line specifically for a .ce
- */
-
-void html_printer::do_eol_ce (void)
-{
- if (end_center > 0) {
- if (end_center > 1)
- if (current_paragraph->emitted_text())
- current_paragraph->do_break();
-
- end_center--;
- if (end_center == 0) {
- current_paragraph->done_para();
- supress_sub_sup = TRUE;
- }
- }
-}
-
-/*
- * do_flush - flushes all output and tags.
- */
-
-void html_printer::do_flush (void)
-{
- current_paragraph->done_para();
-}
-
-/*
- * do_links - moves onto a new temporary file and sets auto_links to FALSE.
- */
-
-void html_printer::do_links (void)
-{
- current_paragraph->done_para();
- auto_links = FALSE; /* from now on only emit under user request */
- file_list.add_new_file(xtmpfile());
- html.set_file(file_list.get_file());
-}
-
-/*
- * do_break - handles the ".br" request and also
- * undoes an outstanding ".ti" command.
- */
-
-void html_printer::do_break (void)
-{
- current_paragraph->do_break();
- if (end_tempindent > 0) {
- end_tempindent--;
- if (end_tempindent == 0)
- do_indent(prev_indent, pageoffset, linelength);
- }
- output_hpos = indentation+pageoffset;
- supress_sub_sup = TRUE;
-}
-
-/*
- * do_tab_ts - start a table, which will have already been defined.
- */
-
-void html_printer::do_tab_ts (text_glob *g)
-{
- html_table *t = g->get_table();
-
- if (t != NULL) {
- current_paragraph->done_pre();
- current_paragraph->done_para();
-
- html.simple_comment("TABS");
-
- t->set_linelength(max_linelength);
- t->add_indent(pageoffset);
- t->emit_table_header(FALSE);
- }
-
- table = t;
-}
-
-/*
- * do_tab_te - finish a table.
- */
-
-void html_printer::do_tab_te (void)
-{
- if (table) {
- current_paragraph->done_para();
- table->emit_finish_table();
- }
-
- table = NULL;
-
- if (indentation > 0) {
- /*
- * restore indentation
- */
- int newin = indentation;
- indentation = 0;
- do_indent(newin, pageoffset, linelength);
- }
-}
-
-/*
- * do_tab - handle the "html-tag:tab" tag
- */
-
-void html_printer::do_tab (char *s)
-{
- if (table) {
- while (isspace(*s))
- s++;
- s++;
- int col = table->find_column(atoi(s) + pageoffset + indentation);
- if (col > 0) {
- current_paragraph->done_para();
- table->emit_col(col);
- }
- }
-}
-
-/*
- * do_tab0 - handle the "html-tag:tab0" tag
- */
-
-void html_printer::do_tab0 (void)
-{
- if (table) {
- int col = table->find_column(pageoffset+indentation);
- if (col > 0) {
- current_paragraph->done_para();
- table->emit_col(col);
- }
- }
-}
-
-/*
- * do_col - start column, s.
- */
-
-void html_printer::do_col (char *s)
-{
- if (table) {
- current_paragraph->done_para();
- table->emit_col(atoi(s));
- }
-}
-
-/*
- * troff_tag - processes the troff tag and manipulates the troff state machine.
- */
-
-void html_printer::troff_tag (text_glob *g)
-{
- /*
- * firstly skip over html-tag:
- */
- char *t=(char *)g->text_string+9;
-
- if (g->is_eol()) {
- do_eol();
- } else if (g->is_eol_ce()) {
- do_eol_ce();
- } else if (strncmp(t, ".sp", 3) == 0) {
- if (g->get_arg() > 0)
- current_paragraph->do_space();
- else
- current_paragraph->do_break();
- supress_sub_sup = TRUE;
- } else if (strncmp(t, ".br", 3) == 0) {
- do_break();
- } else if (strcmp(t, ".centered-image") == 0) {
- do_centered_image();
- } else if (strcmp(t, ".right-image") == 0) {
- do_right_image();
- } else if (strcmp(t, ".left-image") == 0) {
- do_left_image();
- } else if (strncmp(t, ".auto-image", 11) == 0) {
- char *a = (char *)t+11;
- do_auto_image(g, a);
- } else if (strncmp(t, ".ce", 3) == 0) {
- char *a = (char *)t+3;
- supress_sub_sup = TRUE;
- do_center(a);
- } else if (strncmp(t, ".tl", 3) == 0) {
- supress_sub_sup = TRUE;
- title.with_h1 = TRUE;
- do_title();
- } else if (strncmp(t, ".html-tl", 8) == 0) {
- supress_sub_sup = TRUE;
- title.with_h1 = FALSE;
- do_title();
- } else if (strncmp(t, ".fi", 3) == 0) {
- do_fill(TRUE);
- } else if (strncmp(t, ".nf", 3) == 0) {
- do_fill(FALSE);
- } else if ((strncmp(t, ".SH", 3) == 0) || (strncmp(t, ".NH", 3) == 0)) {
- char *a = (char *)t+3;
- do_heading(a);
- } else if (strncmp(t, ".ll", 3) == 0) {
- char *a = (char *)t+3;
- do_linelength(a);
- } else if (strncmp(t, ".po", 3) == 0) {
- char *a = (char *)t+3;
- do_pageoffset(a);
- } else if (strncmp(t, ".in", 3) == 0) {
- char *a = (char *)t+3;
- do_indentation(a);
- } else if (strncmp(t, ".ti", 3) == 0) {
- char *a = (char *)t+3;
- do_tempindent(a);
- } else if (strncmp(t, ".vs", 3) == 0) {
- char *a = (char *)t+3;
- do_verticalspacing(a);
- } else if (strncmp(t, ".ps", 3) == 0) {
- char *a = (char *)t+3;
- do_pointsize(a);
- } else if (strcmp(t, ".links") == 0) {
- do_links();
- } else if (strcmp(t, ".no-auto-rule") == 0) {
- auto_rule = FALSE;
- } else if (strcmp(t, ".tab-ts") == 0) {
- do_tab_ts(g);
- } else if (strcmp(t, ".tab-te") == 0) {
- do_tab_te();
- } else if (strncmp(t, ".col ", 5) == 0) {
- char *a = (char *)t+4;
- do_col(a);
- } else if (strncmp(t, "tab ", 4) == 0) {
- char *a = (char *)t+3;
- do_tab(a);
- } else if (strncmp(t, "tab0", 4) == 0) {
- do_tab0();
- }
-}
-
-/*
- * is_in_middle - returns TRUE if the positions left..right are in the center of the page.
- */
-
-int html_printer::is_in_middle (int left, int right)
-{
- return( abs(abs(left-pageoffset) - abs(pageoffset+linelength-right)) <= CENTER_TOLERANCE );
-}
-
-/*
- * flush_globs - runs through the text glob list and emits html.
- */
-
-void html_printer::flush_globs (void)
-{
- text_glob *g;
-
- if (! page_contents->glyphs.is_empty()) {
- page_contents->glyphs.start_from_head();
- do {
- g = page_contents->glyphs.get_data();
-
- if (strcmp(g->text_string, "XXXXXXX") == 0)
- stop();
-
- if (g->is_a_tag()) {
- troff_tag(g);
- } else if (g->is_a_line()) {
- emit_line(g);
- } else {
- emit_html(g);
- }
- /*
- * after processing the title (and removing it) the glyph list might be empty
- */
- if (! page_contents->glyphs.is_empty()) {
- page_contents->glyphs.move_right();
- }
- } while (! page_contents->glyphs.is_equal_to_head());
- }
-}
-
-/*
- * calc_nf - calculates the _no_ format flag, given the
- * text glob, g.
- */
-
-int html_printer::calc_nf (text_glob *g, int nf)
-{
- if (g != NULL) {
- if (g->is_fi())
- return FALSE;
- if (g->is_nf())
- return TRUE;
- }
- return nf;
-}
-
-/*
- * calc_po_in - calculates the, in, po, registers
- */
-
-void html_printer::calc_po_in (text_glob *g, int nf)
-{
- if (g->is_in())
- indentation = g->get_arg();
- else if (g->is_po())
- pageoffset = g->get_arg();
- else if (g->is_ti()) {
- prev_indent = indentation;
- indentation = g->get_arg();
- end_tempindent = 1;
- } else if (g->is_br() && ((end_tempindent > 0) || (nf && g->is_eol()))) {
- end_tempindent = 0;
- indentation = prev_indent;
- }
-}
-
-/*
- * next_horiz_pos - returns the next horiz position.
- * -1 is returned if it doesn't exist.
- */
-
-int html_printer::next_horiz_pos (text_glob *g, int nf)
-{
- int next = -1;
-
- if ((g != NULL) && (g->is_br() || (nf && g->is_eol())))
- if (! page_contents->glyphs.is_empty()) {
- page_contents->glyphs.move_right_get_data();
- if (g == NULL)
- page_contents->glyphs.start_from_head();
- else {
- next = g->minh;
- page_contents->glyphs.move_left();
- }
- }
- return next;
-}
-
-/*
- * insert_tab_ts - inserts a tab-ts before, where.
- */
-
-text_glob *html_printer::insert_tab_ts (text_glob *where)
-{
- text_glob *start_of_table;
- text_glob *old_pos = page_contents->glyphs.get_data();
-
- page_contents->glyphs.move_to(where);
- page_contents->glyphs.move_left();
- page_contents->insert_tag(string("html-tag:.tab-ts")); // tab table start
- page_contents->glyphs.move_right();
- start_of_table = page_contents->glyphs.get_data();
- page_contents->glyphs.move_to(old_pos);
- return start_of_table;
-}
-
-/*
- * insert_tab_te - inserts a tab-te before the current position
- * (it skips backwards over .sp/.br)
- */
-
-void html_printer::insert_tab_te (void)
-{
- text_glob *g = page_contents->glyphs.get_data();
- page_contents->dump_page();
-
- while (page_contents->glyphs.get_data()->is_a_tag())
- page_contents->glyphs.move_left();
-
- page_contents->insert_tag(string("html-tag:.tab-te")); // tab table end
- while (g != page_contents->glyphs.get_data())
- page_contents->glyphs.move_right();
- page_contents->dump_page();
-}
-
-/*
- * insert_tab_0 - inserts a tab0 before, where.
- */
-
-void html_printer::insert_tab_0 (text_glob *where)
-{
- text_glob *old_pos = page_contents->glyphs.get_data();
-
- page_contents->glyphs.move_to(where);
- page_contents->glyphs.move_left();
- page_contents->insert_tag(string("html-tag:tab0")); // tab0 start of line
- page_contents->glyphs.move_right();
- page_contents->glyphs.move_to(old_pos);
-}
-
-/*
- * remove_tabs - removes the tabs tags on this line.
- */
-
-void html_printer::remove_tabs (void)
-{
- text_glob *orig = page_contents->glyphs.get_data();
- text_glob *g;
-
- if (! page_contents->glyphs.is_equal_to_tail()) {
- do {
- g = page_contents->glyphs.get_data();
- if (g->is_tab()) {
- page_contents->glyphs.sub_move_right();
- if (g == orig)
- orig = page_contents->glyphs.get_data();
- } else
- page_contents->glyphs.move_right();
- } while ((! page_contents->glyphs.is_equal_to_head()) &&
- (! g->is_eol()));
-
- /*
- * now restore our previous position.
- */
- while (page_contents->glyphs.get_data() != orig)
- page_contents->glyphs.move_left();
- }
-}
-
-void html_printer::remove_courier_tabs (void)
-{
- text_glob *g;
- int line_start = TRUE;
- int nf = FALSE;
-
- if (! page_contents->glyphs.is_empty()) {
- page_contents->glyphs.start_from_head();
- line_start = TRUE;
- do {
- g = page_contents->glyphs.get_data();
-
- nf = calc_nf(g, nf);
-
- if (line_start) {
- if (line_start && nf && is_courier_until_eol()) {
- remove_tabs();
- g = page_contents->glyphs.get_data();
- }
- }
-
- line_start = g->is_br() || g->is_nf() || g->is_fi() || (nf && g->is_eol());
- page_contents->glyphs.move_right();
- } while (! page_contents->glyphs.is_equal_to_head());
- }
-}
-
-void html_printer::insert_tab0_foreach_tab (void)
-{
- text_glob *start_of_line = NULL;
- text_glob *g = NULL;
- int seen_tab = FALSE;
- int seen_col = FALSE;
- int nf = FALSE;
-
- if (! page_contents->glyphs.is_empty()) {
- page_contents->glyphs.start_from_head();
- start_of_line = page_contents->glyphs.get_data();
- do {
- g = page_contents->glyphs.get_data();
-
- nf = calc_nf(g, nf);
-
- if (g->is_tab())
- seen_tab = TRUE;
-
- if (g->is_col())
- seen_col = TRUE;
-
- if (g->is_br() || (nf && g->is_eol())) {
- do {
- page_contents->glyphs.move_right();
- g = page_contents->glyphs.get_data();
- nf = calc_nf(g, nf);
- if (page_contents->glyphs.is_equal_to_head()) {
- if (seen_tab && !seen_col)
- insert_tab_0(start_of_line);
- return;
- }
- } while (g->is_br() || (nf && g->is_eol()) || g->is_ta());
- // printf("\nstart_of_line is: %s\n", g->text_string);
- if (seen_tab && !seen_col) {
- insert_tab_0(start_of_line);
- page_contents->glyphs.move_to(g);
- }
-
- seen_tab = FALSE;
- seen_col = FALSE;
- start_of_line = g;
- }
- page_contents->glyphs.move_right();
- } while (! page_contents->glyphs.is_equal_to_head());
- if (seen_tab && !seen_col)
- insert_tab_0(start_of_line);
-
- }
-}
-
-/*
- * update_min_max - updates the extent of a column, given the left and right
- * extents of a glyph, g.
- */
-
-void html_printer::update_min_max (colType type_of_col, int *minimum, int *maximum, text_glob *g)
-{
- switch (type_of_col) {
-
- case tab_tag:
- break;
- case tab0_tag:
- *minimum = g->minh;
- break;
- case col_tag:
- *minimum = g->minh;
- *maximum = g->maxh;
- break;
- default:
- break;
- }
-}
-
-/*
- * add_table_end - moves left one glyph, adds a table end tag and adds a
- * debugging string.
- */
-
-void html_printer::add_table_end (char *debug_string)
-{
- page_contents->glyphs.move_left();
- insert_tab_te();
-#if defined(DEBUG_TABLES)
- page_contents->insert_tag(string(debug_string));
-#endif
-}
-
-/*
- * lookahead_for_tables - checks for .col tags and inserts table start/end tags
- */
-
-void html_printer::lookahead_for_tables (void)
-{
- text_glob *g;
- text_glob *start_of_line = NULL;
- text_glob *start_of_table = NULL;
- text_glob *last = NULL;
- colType type_of_col = none;
- int left = 0;
- int found_col = FALSE;
- int seen_text = FALSE;
- int ncol = 0;
- int colmin;
- int colmax;
- html_table *table = new html_table(&html, -1);
- const char *tab_defs = NULL;
- char align = 'L';
- int nf = FALSE;
- int old_pageoffset = pageoffset;
-
- remove_courier_tabs();
- page_contents->dump_page();
- insert_tab0_foreach_tab();
- page_contents->dump_page();
- if (! page_contents->glyphs.is_empty()) {
- page_contents->glyphs.start_from_head();
- g = page_contents->glyphs.get_data();
- do {
-#if defined(DEBUG_TABLES)
- fprintf(stderr, " [") ;
- fprintf(stderr, g->text_string) ;
- fprintf(stderr, "] ") ;
- fflush(stderr);
- if (strcmp(g->text_string, "XXXXXXX") == 0)
- stop();
-#endif
-
- nf = calc_nf(g, nf);
- calc_po_in(g, nf);
- if (g->is_col()) {
- if (type_of_col == tab_tag && start_of_table != NULL) {
- page_contents->glyphs.move_left();
- insert_tab_te();
- start_of_table->remember_table(table);
- table = new html_table(&html, -1);
- page_contents->insert_tag(string("*** TAB -> COL ***"));
- if (tab_defs != NULL)
- table->tab_stops->init(tab_defs);
- start_of_table = NULL;
- last = NULL;
- }
- type_of_col = col_tag;
- found_col = TRUE;
- ncol = g->get_arg();
- align = 'L';
- colmin = 0;
- colmax = 0;
- } else if (g->is_tab()) {
- type_of_col = tab_tag;
- colmin = g->get_tab_args(&align);
- align = 'L'; // for now as 'C' and 'R' are broken
- ncol = table->find_tab_column(colmin);
- colmin += pageoffset + indentation;
- colmax = table->get_tab_pos(ncol+1);
- if (colmax > 0)
- colmax += pageoffset + indentation;
- } else if (g->is_tab0()) {
- if (type_of_col == col_tag && start_of_table != NULL) {
- page_contents->glyphs.move_left();
- insert_tab_te();
- start_of_table->remember_table(table);
- table = new html_table(&html, -1);
- page_contents->insert_tag(string("*** COL -> TAB ***"));
- start_of_table = NULL;
- last = NULL;
- }
- if (tab_defs != NULL)
- table->tab_stops->init(tab_defs);
-
- type_of_col = tab0_tag;
- ncol = 1;
- colmin = 0;
- colmax = table->get_tab_pos(2) + pageoffset + indentation;
- } else if (! g->is_a_tag())
- update_min_max(type_of_col, &colmin, &colmax, g);
-
- if ((! g->is_a_tag()) || g->is_tab())
- seen_text = TRUE;
-
- if ((g->is_col() || g->is_tab() || g->is_tab0())
- && (start_of_line != NULL) && (start_of_table == NULL)) {
- start_of_table = insert_tab_ts(start_of_line);
- start_of_line = NULL;
- seen_text = FALSE;
- } else if (g->is_ce() && (start_of_table != NULL)) {
- add_table_end("*** CE ***");
- start_of_table->remember_table(table);
- start_of_table = NULL;
- last = NULL;
- } else if (g->is_ta()) {
- tab_defs = g->text_string;
- if (!table->tab_stops->compatible(tab_defs)) {
- if (start_of_table != NULL) {
- add_table_end("*** TABS ***");
- start_of_table->remember_table(table);
- table = new html_table(&html, -1);
- start_of_table = NULL;
- type_of_col = none;
- last = NULL;
- }
- table->tab_stops->init(tab_defs);
- }
- }
-
- if (((! g->is_a_tag()) || g->is_tab()) && (start_of_table != NULL)) {
- // we are in a table and have a glyph
- if ((ncol == 0) || (! table->add_column(ncol, colmin, colmax, align))) {
- if (ncol == 0)
- add_table_end("*** NCOL == 0 ***");
- else
- add_table_end("*** CROSSED COLS ***");
-
- start_of_table->remember_table(table);
- table = new html_table(&html, -1);
- start_of_table = NULL;
- type_of_col = none;
- last = NULL;
- }
- }
-
- /*
- * move onto next glob, check whether we are starting a new line
- */
- g = page_contents->glyphs.move_right_get_data();
-
- if (g == NULL) {
- if (found_col) {
- page_contents->glyphs.start_from_head();
- last = g;
- found_col = FALSE;
- }
- } else if (g->is_br() || (nf && g->is_eol())) {
- do {
- g = page_contents->glyphs.move_right_get_data();
- nf = calc_nf(g, nf);
- } while ((g != NULL) && (g->is_br() || (nf && g->is_eol())));
- start_of_line = g;
- seen_text = FALSE;
- ncol = 0;
- left = next_horiz_pos(g, nf);
- if (found_col)
- last = g;
- found_col = FALSE;
- }
- } while ((g != NULL) && (! page_contents->glyphs.is_equal_to_head()));
-
-#if defined(DEBUG_TABLES)
- fprintf(stderr, "finished scanning for tables\n");
-#endif
-
- page_contents->glyphs.start_from_head();
- if (start_of_table != NULL) {
- if (last != NULL)
- while (last != page_contents->glyphs.get_data())
- page_contents->glyphs.move_left();
-
- insert_tab_te();
- start_of_table->remember_table(table);
- table = NULL;
- page_contents->insert_tag(string("*** LAST ***"));
- }
- }
- if (table != NULL)
- delete table;
-
- // and reset the registers
- pageoffset = old_pageoffset;
- indentation = 0;
- prev_indent = 0;
- end_tempindent = 0;
-}
-
-void html_printer::flush_page (void)
-{
- supress_sub_sup = TRUE;
- flush_sbuf();
- page_contents->dump_page();
- lookahead_for_tables();
- page_contents->dump_page();
-
- flush_globs();
- current_paragraph->done_para();
-
- // move onto a new page
- delete page_contents;
-#if defined(DEBUG_TABLES)
- fprintf(stderr, "\n\n*** flushed page ***\n\n");
-
- html.simple_comment("new page called");
-#endif
- page_contents = new page;
-}
-
-/*
- * determine_space - works out whether we need to write a space.
- * If last glyph is ajoining then no space emitted.
- */
-
-void html_printer::determine_space (text_glob *g)
-{
- if (current_paragraph->is_in_pre()) {
- /*
- * .nf has been specified
- */
- while (output_hpos < g->minh) {
- output_hpos += space_width;
- current_paragraph->emit_space();
- }
- } else {
- if ((output_vpos != g->minv) || (output_hpos < g->minh)) {
- current_paragraph->emit_space();
- }
- }
-}
-
-/*
- * is_font_courier - returns TRUE if the font, f, is courier.
- */
-
-int html_printer::is_font_courier (font *f)
-{
- if (f != 0) {
- const char *fontname = f->get_name();
-
- return( (fontname != 0) && (fontname[0] == 'C') );
- }
- return( FALSE );
-}
-
-/*
- * end_font - shuts down the font corresponding to fontname.
- */
-
-void html_printer::end_font (const char *fontname)
-{
- if (strcmp(fontname, "B") == 0) {
- current_paragraph->done_bold();
- } else if (strcmp(fontname, "I") == 0) {
- current_paragraph->done_italic();
- } else if (strcmp(fontname, "BI") == 0) {
- current_paragraph->done_bold();
- current_paragraph->done_italic();
- } else if (strcmp(fontname, "CR") == 0) {
- current_paragraph->done_tt();
- } else if (strcmp(fontname, "CI") == 0) {
- current_paragraph->done_italic();
- current_paragraph->done_tt();
- } else if (strcmp(fontname, "CB") == 0) {
- current_paragraph->done_bold();
- current_paragraph->done_tt();
- } else if (strcmp(fontname, "CBI") == 0) {
- current_paragraph->done_bold();
- current_paragraph->done_italic();
- current_paragraph->done_tt();
- }
-}
-
-/*
- * start_font - starts the font corresponding to name.
- */
-
-void html_printer::start_font (const char *fontname)
-{
- if (strcmp(fontname, "R") == 0) {
- current_paragraph->done_bold();
- current_paragraph->done_italic();
- current_paragraph->done_tt();
- } else if (strcmp(fontname, "B") == 0) {
- current_paragraph->do_bold();
- } else if (strcmp(fontname, "I") == 0) {
- current_paragraph->do_italic();
- } else if (strcmp(fontname, "BI") == 0) {
- current_paragraph->do_bold();
- current_paragraph->do_italic();
- } else if (strcmp(fontname, "CR") == 0) {
- if ((! fill_on) && (is_courier_until_eol())) {
- current_paragraph->do_pre();
- }
- current_paragraph->do_tt();
- } else if (strcmp(fontname, "CI") == 0) {
- if ((! fill_on) && (is_courier_until_eol())) {
- current_paragraph->do_pre();
- }
- current_paragraph->do_tt();
- current_paragraph->do_italic();
- } else if (strcmp(fontname, "CB") == 0) {
- if ((! fill_on) && (is_courier_until_eol())) {
- current_paragraph->do_pre();
- }
- current_paragraph->do_tt();
- current_paragraph->do_bold();
- } else if (strcmp(fontname, "CBI") == 0) {
- if ((! fill_on) && (is_courier_until_eol())) {
- current_paragraph->do_pre();
- }
- current_paragraph->do_tt();
- current_paragraph->do_italic();
- current_paragraph->do_bold();
- }
-}
-
-/*
- * start_size - from is old font size, to is the new font size.
- * The html increase <big> and <small> decrease alters the
- * font size by 20%. We try and map these onto glyph sizes.
- */
-
-void html_printer::start_size (int from, int to)
-{
- if (from < to) {
- while (from < to) {
- current_paragraph->do_big();
- from += SIZE_INCREMENT;
- }
- } else if (from > to) {
- while (from > to) {
- current_paragraph->do_small();
- from -= SIZE_INCREMENT;
- }
- }
-}
-
-/*
- * do_font - checks to see whether we need to alter the html font.
- */
-
-void html_printer::do_font (text_glob *g)
-{
- /*
- * check if the output_style.point_size has not been set yet
- * this allow users to place .ps at the top of their troff files
- * and grohtml can then treat the .ps value as the base font size (3)
- */
- if (output_style.point_size == -1) {
- output_style.point_size = pointsize;
- }
-
- if (g->text_style.f != output_style.f) {
- if (output_style.f != 0) {
- end_font(output_style.f->get_name());
- }
- output_style.f = g->text_style.f;
- if (output_style.f != 0) {
- start_font(output_style.f->get_name());
- }
- }
- if (output_style.point_size != g->text_style.point_size) {
- do_sup_or_sub(g);
- if ((output_style.point_size > 0) &&
- (g->text_style.point_size > 0)) {
- start_size(output_style.point_size, g->text_style.point_size);
- }
- if (g->text_style.point_size > 0) {
- output_style.point_size = g->text_style.point_size;
- }
- }
- if (output_style.col != g->text_style.col) {
- current_paragraph->done_color();
- output_style.col = g->text_style.col;
- current_paragraph->do_color(&output_style.col);
- }
-}
-
-/*
- * start_subscript - returns TRUE if, g, looks like a subscript start.
- */
-
-int html_printer::start_subscript (text_glob *g)
-{
- int r = font::res;
- int height = output_style.point_size*r/72;
-
- return( (output_style.point_size != 0) &&
- (output_vpos < g->minv) &&
- (output_vpos-height > g->maxv) &&
- (output_style.point_size > g->text_style.point_size) );
-}
-
-/*
- * start_superscript - returns TRUE if, g, looks like a superscript start.
- */
-
-int html_printer::start_superscript (text_glob *g)
-{
- int r = font::res;
- int height = output_style.point_size*r/72;
-
- return( (output_style.point_size != 0) &&
- (output_vpos > g->minv) &&
- (output_vpos-height < g->maxv) &&
- (output_style.point_size > g->text_style.point_size) );
-}
-
-/*
- * end_subscript - returns TRUE if, g, looks like the end of a subscript.
- */
-
-int html_printer::end_subscript (text_glob *g)
-{
- int r = font::res;
- int height = output_style.point_size*r/72;
-
- return( (output_style.point_size != 0) &&
- (g->minv < output_vpos) &&
- (output_vpos-height > g->maxv) &&
- (output_style.point_size < g->text_style.point_size) );
-}
-
-/*
- * end_superscript - returns TRUE if, g, looks like the end of a superscript.
- */
-
-int html_printer::end_superscript (text_glob *g)
-{
- int r = font::res;
- int height = output_style.point_size*r/72;
-
- return( (output_style.point_size != 0) &&
- (g->minv > output_vpos) &&
- (output_vpos-height < g->maxv) &&
- (output_style.point_size < g->text_style.point_size) );
-}
-
-/*
- * do_sup_or_sub - checks to see whether the next glyph is a subscript/superscript
- * start/end and it calls the services of html-text to issue the
- * appropriate tags.
- */
-
-void html_printer::do_sup_or_sub (text_glob *g)
-{
- if (! supress_sub_sup) {
- if (start_subscript(g)) {
- current_paragraph->do_sub();
- } else if (start_superscript(g)) {
- current_paragraph->do_sup();
- } else if (end_subscript(g)) {
- current_paragraph->done_sub();
- } else if (end_superscript(g)) {
- current_paragraph->done_sup();
- }
- }
-}
-
-/*
- * emit_html - write out the html text
- */
-
-void html_printer::emit_html (text_glob *g)
-{
- do_font(g);
- determine_space(g);
- current_paragraph->do_emittext(g->text_string, g->text_length);
- output_vpos = g->minv;
- output_hpos = g->maxh;
- output_vpos_max = g->maxv;
- supress_sub_sup = FALSE;
-}
-
-/*
- * flush_sbuf - flushes the current sbuf into the list of glyphs.
- */
-
-void html_printer::flush_sbuf()
-{
- if (sbuf.length() > 0) {
- int r=font::res; // resolution of the device
- set_style(sbuf_style);
- if (overstrike_detected && (! is_bold(sbuf_style.f))) {
- font *bold_font = make_bold(sbuf_style.f);
- if (bold_font != NULL)
- sbuf_style.f = bold_font;
- }
-
- page_contents->add(&sbuf_style, sbuf,
- line_number,
- sbuf_vpos-sbuf_style.point_size*r/72, sbuf_start_hpos,
- sbuf_vpos , sbuf_end_hpos);
-
- output_hpos = sbuf_end_hpos;
- output_vpos = sbuf_vpos;
- last_sbuf_length = 0;
- sbuf_prev_hpos = sbuf_end_hpos;
- overstrike_detected = FALSE;
- sbuf.clear();
- }
-}
-
-void html_printer::set_line_thickness(const environment *env)
-{
- line_thickness = env->size;
-}
-
-void html_printer::draw(int code, int *p, int np, const environment *env)
-{
- switch (code) {
-
- case 'l':
-# if 0
- if (np == 2) {
- page_contents->add_line(&sbuf_style,
- line_number,
- env->hpos, env->vpos, env->hpos+p[0], env->vpos+p[1], line_thickness);
- } else {
- error("2 arguments required for line");
- }
-# endif
- break;
- case 't':
- {
- if (np == 0) {
- line_thickness = -1;
- } else {
- // troff gratuitously adds an extra 0
- if (np != 1 && np != 2) {
- error("0 or 1 argument required for thickness");
- break;
- }
- line_thickness = p[0];
- }
- break;
- }
-
- case 'P':
- break;
- case 'p':
- break;
- case 'E':
- break;
- case 'e':
- break;
- case 'C':
- break;
- case 'c':
- break;
- case 'a':
- break;
- case '~':
- break;
- case 'f':
- break;
- case 'F':
- // fill with color env->fill
- if (background != NULL)
- delete background;
- background = new color;
- *background = *env->fill;
- break;
-
- default:
- error("unrecognised drawing command `%1'", char(code));
- break;
- }
-}
-
-html_printer::html_printer()
-: html(0, MAX_LINE_LENGTH),
- no_of_printed_pages(0),
- last_sbuf_length(0),
- overstrike_detected(FALSE),
- output_hpos(-1),
- output_vpos(-1),
- output_vpos_max(-1),
- line_thickness(-1),
- inside_font_style(0),
- page_number(0),
- header_indent(-1),
- supress_sub_sup(TRUE),
- cutoff_heading(100),
- indent(NULL),
- table(NULL),
- end_center(0),
- end_tempindent(0),
- next_tag(INLINE),
- fill_on(TRUE),
- max_linelength(-1),
- linelength(0),
- pageoffset(0),
- indentation(0),
- prev_indent(0),
- pointsize(0),
- line_number(0),
- background(default_background)
-{
- file_list.add_new_file(xtmpfile());
- html.set_file(file_list.get_file());
- if (font::hor != 24)
- fatal("horizontal resolution must be 24");
- if (font::vert != 40)
- fatal("vertical resolution must be 40");
-#if 0
- // should be sorted html..
- if (font::res % (font::sizescale*72) != 0)
- fatal("res must be a multiple of 72*sizescale");
-#endif
- int r = font::res;
- int point = 0;
- while (r % 10 == 0) {
- r /= 10;
- point++;
- }
- res = r;
- html.set_fixed_point(point);
- space_char_index = font::name_to_index("space");
- space_width = font::hor;
- paper_length = font::paperlength;
- linelength = font::res*13/2;
- if (paper_length == 0)
- paper_length = 11*font::res;
-
- page_contents = new page();
-}
-
-/*
- * add_to_sbuf - adds character code or name to the sbuf.
- */
-
-void html_printer::add_to_sbuf (int index, const string &s)
-{
- if (sbuf_style.f == NULL)
- return;
-
- char *html_glyph = NULL;
- unsigned int code = sbuf_style.f->get_code(index);
-
- if (s.empty()) {
- if (sbuf_style.f->contains(index))
- html_glyph = (char *)sbuf_style.f->get_special_device_encoding(index);
- else
- html_glyph = NULL;
-
- if ((html_glyph == NULL) && (code >= UNICODE_DESC_START))
- html_glyph = to_unicode(code);
- } else
- html_glyph = get_html_translation(sbuf_style.f, s);
-
- last_sbuf_length = sbuf.length();
- if (html_glyph == NULL)
- sbuf += ((char)code);
- else
- sbuf += html_glyph;
-}
-
-int html_printer::sbuf_continuation (int index, const char *name,
- const environment *env, int w)
-{
- /*
- * lets see whether the glyph is closer to the end of sbuf
- */
- if ((sbuf_end_hpos == env->hpos)
- || ((sbuf_prev_hpos < sbuf_end_hpos)
- && (env->hpos < sbuf_end_hpos)
- && ((sbuf_end_hpos-env->hpos < env->hpos-sbuf_prev_hpos)))) {
- add_to_sbuf(index, name);
- sbuf_prev_hpos = sbuf_end_hpos;
- sbuf_end_hpos += w + sbuf_kern;
- return TRUE;
- } else {
- if ((env->hpos >= sbuf_end_hpos) &&
- ((sbuf_kern == 0) || (sbuf_end_hpos - sbuf_kern != env->hpos))) {
- /*
- * lets see whether a space is needed or not
- */
-
- if (env->hpos-sbuf_end_hpos < space_width) {
- add_to_sbuf(index, name);
- sbuf_prev_hpos = sbuf_end_hpos;
- sbuf_end_hpos = env->hpos + w;
- return TRUE;
- }
- }
- }
- return FALSE ;
-}
-
-/*
- * get_html_translation - given the position of the character and its name
- * return the device encoding for such character.
- */
-
-char *get_html_translation (font *f, const string &name)
-{
- int index;
-
- if ((f == 0) || name.empty())
- return NULL;
- else {
- index = f->name_to_index((char *)(name + '\0').contents());
- if (index == 0) {
- error("character `%s' not found", (name + '\0').contents());
- return NULL;
- } else
- if (f->contains(index))
- return (char *)f->get_special_device_encoding(index);
- else
- return NULL;
- }
-}
-
-/*
- * overstrike - returns TRUE if the glyph (i, name) is going to overstrike
- * a previous glyph in sbuf.
- * If TRUE the font is changed to bold and the previous sbuf
- * is flushed.
- */
-
-int html_printer::overstrike(int index, const char *name, const environment *env, int w)
-{
- if ((env->hpos < sbuf_end_hpos)
- || ((sbuf_kern != 0) && (sbuf_end_hpos - sbuf_kern < env->hpos))) {
- /*
- * at this point we have detected an overlap
- */
- if (overstrike_detected) {
- /* already detected, remove previous glyph and use this glyph */
- sbuf.set_length(last_sbuf_length);
- add_to_sbuf(index, name);
- sbuf_end_hpos = env->hpos + w;
- return TRUE;
- } else {
- /* first time we have detected an overstrike in the sbuf */
- sbuf.set_length(last_sbuf_length); /* remove previous glyph */
- if (! is_bold(sbuf_style.f))
- flush_sbuf();
- overstrike_detected = TRUE;
- add_to_sbuf(index, name);
- sbuf_end_hpos = env->hpos + w;
- return TRUE;
- }
- }
- return FALSE ;
-}
-
-/*
- * set_char - adds a character into the sbuf if it is a continuation with the previous
- * word otherwise flush the current sbuf and add character anew.
- */
-
-void html_printer::set_char(int i, font *f, const environment *env, int w, const char *name)
-{
- style sty(f, env->size, env->height, env->slant, env->fontno, *env->col);
- if (sty.slant != 0) {
- if (sty.slant > 80 || sty.slant < -80) {
- error("silly slant `%1' degrees", sty.slant);
- sty.slant = 0;
- }
- }
- if (((! sbuf.empty()) && (sty == sbuf_style) && (sbuf_vpos == env->vpos))
- && (sbuf_continuation(i, name, env, w) || overstrike(i, name, env, w)))
- return;
-
- flush_sbuf();
- add_to_sbuf(i, name);
- sbuf_end_hpos = env->hpos + w;
- sbuf_start_hpos = env->hpos;
- sbuf_prev_hpos = env->hpos;
- sbuf_vpos = env->vpos;
- sbuf_style = sty;
- sbuf_kern = 0;
-}
-
-/*
- * write_title - writes the title to this document
- */
-
-void html_printer::write_title (int in_head)
-{
- if (title.has_been_found) {
- if (in_head) {
- html.put_string("<title>");
- html.put_string(title.text);
- html.put_string("</title>").nl().nl();
- } else {
- title.has_been_written = TRUE;
- if (title.with_h1) {
- html.put_string("<h1 align=center>");
- html.put_string(title.text);
- html.put_string("</h1>").nl().nl();
- }
- }
- } else if (in_head) {
- // place empty title tags to help conform to `tidy'
- html.put_string("<title></title>").nl();
- }
-}
-
-/*
- * write_rule - emits a html rule tag, if the auto_rule boolean is true.
- */
-
-static void write_rule (void)
-{
- if (auto_rule)
- fputs("<hr>\n", stdout);
-}
-
-void html_printer::begin_page(int n)
-{
- page_number = n;
-#if defined(DEBUGGING)
- html.begin_comment("Page: ").put_string(i_to_a(page_number)).end_comment();;
-#endif
- no_of_printed_pages++;
-
- output_style.f = 0;
- output_style.point_size= -1;
- output_space_code = 32;
- output_draw_point_size = -1;
- output_line_thickness = -1;
- output_hpos = -1;
- output_vpos = -1;
- output_vpos_max = -1;
- current_paragraph = new html_text(&html);
- do_indent(indentation, pageoffset, linelength);
- current_paragraph->do_para("");
-}
-
-void html_printer::end_page(int)
-{
- flush_sbuf();
- flush_page();
-}
-
-font *html_printer::make_font(const char *nm)
-{
- return html_font::load_html_font(nm);
-}
-
-void html_printer::do_body (void)
-{
- if (background == NULL)
- fputs("<body>\n\n", stdout);
- else {
- unsigned int r, g, b;
- char buf[6+1];
-
- background->get_rgb(&r, &g, &b);
- // we have to scale 0..0xFFFF to 0..0xFF
- sprintf(buf, "%.2X%.2X%.2X", r/0x101, g/0x101, b/0x101);
-
- fputs("<body bgcolor=\"#", stdout);
- fputs(buf, stdout);
- fputs("\">\n\n", stdout);
- }
-}
-
-html_printer::~html_printer()
-{
-#ifdef LONG_FOR_TIME_T
- long t;
-#else
- time_t t;
-#endif
-
- current_paragraph->flush_text();
- html.end_line();
- html.set_file(stdout);
- html.begin_comment("Creator : ")
- .put_string("groff ")
- .put_string("version ")
- .put_string(Version_string)
- .end_comment();
-
- t = time(0);
- html.begin_comment("CreationDate: ")
- .put_string(ctime(&t), strlen(ctime(&t))-1)
- .end_comment();
-
- /*
- * 'HTML: The definitive guide', O'Reilly, p47. advises against specifying
- * the dtd.
- */
- // fputs("<!doctype html public \"-//IETF//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n", stdout);
- fputs("<html>\n", stdout);
- fputs("<head>\n", stdout);
- fputs("<meta name=\"generator\" content=\"groff -Thtml, see www.gnu.org\">\n", stdout);
- fputs("<meta name=\"Content-Style\" content=\"text/css\">\n", stdout);
- write_title(TRUE);
- fputs("</head>\n", stdout);
- do_body();
-
- write_title(FALSE);
- header.write_headings(stdout, FALSE);
- write_rule();
-#if defined(DEBUGGING)
- html.begin_comment("Total number of pages: ").put_string(i_to_a(no_of_printed_pages)).end_comment();
-#endif
- html.end_line();
- html.end_line();
- /*
- * now run through the file list copying each temporary file in turn and emitting the links.
- */
- file_list.start_of_list();
- while (file_list.get_file() != 0) {
- if (fseek(file_list.get_file(), 0L, 0) < 0)
- fatal("fseek on temporary file failed");
- html.copy_file(file_list.get_file());
- fclose(file_list.get_file());
- file_list.move_next();
- if (file_list.get_file() != 0)
- header.write_headings(stdout, TRUE);
- }
- write_rule();
- fputs("</body>\n", stdout);
- fputs("</html>\n", stdout);
-}
-
-/*
- * special - handle all x X requests from troff. For post-html they allow users
- * to pass raw html commands, turn auto linked headings off/on and
- * also allow troff to emit tags to indicate when a: .br, .sp etc occurs.
- */
-
-void html_printer::special(char *s, const environment *env, char type)
-{
- if (type != 'p')
- return;
- if (s != 0) {
- flush_sbuf();
- if (env->fontno >= 0) {
- style sty(get_font_from_index(env->fontno), env->size, env->height,
- env->slant, env->fontno, *env->col);
- sbuf_style = sty;
- }
-
- if (strncmp(s, "html:", 5) == 0) {
- int r=font::res; /* resolution of the device */
- font *f=sbuf_style.f;
-
- if (f == NULL) {
- int found=FALSE;
-
- f = font::load_font("TR", &found);
- }
-
- /*
- * need to pass rest of string through to html output during flush
- */
- page_contents->add_and_encode(&sbuf_style, string(&s[5]),
- line_number,
- env->vpos-env->size*r/72, env->hpos,
- env->vpos , env->hpos);
-
- /*
- * assume that the html command has no width, if it does then hopefully troff
- * will have fudged this in a macro by requesting that the formatting move right by
- * the appropriate amount.
- */
- } else if (strncmp(s, "index:", 6) == 0) {
- cutoff_heading = atoi(&s[6]);
- } else if (strncmp(s, "html-tag:", 9) == 0) {
- int r=font::res; /* resolution of the device */
-
- page_contents->add_tag(&sbuf_style, string(s),
- line_number,
- env->vpos-env->size*r/72, env->hpos,
- env->vpos , env->hpos);
- }
- }
-}
-
-int main(int argc, char **argv)
-{
- program_name = argv[0];
- static char stderr_buf[BUFSIZ];
- setbuf(stderr, stderr_buf);
- int c;
- static const struct option long_options[] = {
- { "help", no_argument, 0, CHAR_MAX + 1 },
- { "version", no_argument, 0, 'v' },
- { NULL, 0, 0, 0 }
- };
- while ((c = getopt_long(argc, argv, "a:g:o:i:I:D:F:vbdhlrnp", long_options, NULL))
- != EOF)
- switch(c) {
- case 'v':
- printf("GNU post-grohtml (groff) version %s\n", Version_string);
- exit(0);
- break;
- case 'a':
- /* text antialiasing bits - handled by pre-html */
- break;
- case 'g':
- /* graphic antialiasing bits - handled by pre-html */
- break;
- case 'b':
- // set background color to white
- default_background = new color;
- default_background->set_gray(color::MAX_COLOR_VAL);
- break;
- case 'F':
- font::command_line_font_dir(optarg);
- break;
- case 'l':
- auto_links = FALSE;
- break;
- case 'r':
- auto_rule = FALSE;
- break;
- case 'd':
- /* handled by pre-html */
- break;
- case 'h':
- /* do not use the Hn headings of html, but manufacture our own */
- manufacture_headings = TRUE;
- break;
- case 'o':
- /* handled by pre-html */
- break;
- case 'p':
- /* handled by pre-html */
- break;
- case 'i':
- /* handled by pre-html */
- break;
- case 'I':
- /* handled by pre-html */
- break;
- case 'D':
- /* handled by pre-html */
- break;
- case 'n':
- simple_anchors = TRUE;
- break;
- case CHAR_MAX + 1: // --help
- usage(stdout);
- exit(0);
- break;
- case '?':
- usage(stderr);
- exit(1);
- break;
- default:
- assert(0);
- }
- if (optind >= argc) {
- do_file("-");
- } else {
- for (int i = optind; i < argc; i++)
- do_file(argv[i]);
- }
- delete pr;
- return 0;
-}
-
-static void usage(FILE *stream)
-{
- fprintf(stream, "usage: %s [-vblnh] [-D dir] [-I image_stem] [-F dir] [files ...]\n",
- program_name);
-}
diff --git a/contrib/groff/src/devices/grolbp/lbp.cc b/contrib/groff/src/devices/grolbp/lbp.cc
deleted file mode 100644
index 76db32a..0000000
--- a/contrib/groff/src/devices/grolbp/lbp.cc
+++ /dev/null
@@ -1,740 +0,0 @@
-// -*- C++ -*-
-/* Copyright (C) 1994, 2000, 2001, 2002 Free Software Foundation, Inc.
- Written by Francisco Andrés Verdú <pandres@dragonet.es> with many ideas
- taken from the other groff drivers.
-
-
-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 2, 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 groff; see the file COPYING. If not, write to the Free Software
-Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-/*
-TODO
-
- - Add X command to include bitmaps
-*/
-#define _GNU_SOURCE
-
-#include "driver.h"
-#include "lbp.h"
-#include "charset.h"
-#include "paper.h"
-
-#include "nonposix.h"
-
-extern "C" const char *Version_string;
-
-static int user_papersize = -1; // papersize
-static int orientation = -1; // orientation
-static double user_paperlength = 0; // Custom Paper size
-static double user_paperwidth = 0;
-static int ncopies = 1; // Number of copies
-
-#define DEFAULT_LINEWIDTH_FACTOR 40 // 0.04em
-static int linewidth_factor = DEFAULT_LINEWIDTH_FACTOR;
-
-static int set_papersize(const char *paperformat);
-
-class lbp_font : public font {
-public:
- ~lbp_font();
- void handle_unknown_font_command(const char *command, const char *arg,
- const char *filename, int lineno);
- static lbp_font *load_lbp_font(const char *);
- char *lbpname;
- char is_scalable;
-private:
- lbp_font(const char *);
-};
-
-class lbp_printer : public printer {
-public:
- lbp_printer(int, double, double);
- ~lbp_printer();
- void set_char(int, font *, const environment *, int, const char *name);
- void draw(int code, int *p, int np, const environment *env);
- void begin_page(int);
- void end_page(int page_length);
- font *make_font(const char *);
- void end_of_line();
-private:
- void set_line_thickness(int size,const environment *env);
- void vdmstart();
- void vdmflush(); // the name vdmend was already used in lbp.h
- void setfillmode(int mode);
- void polygon( int hpos,int vpos,int np,int *p);
- char *font_name(const lbp_font *f, const int siz);
-
- int fill_pattern;
- int fill_mode;
- int cur_hpos;
- int cur_vpos;
- lbp_font *cur_font;
- int cur_size;
- unsigned short cur_symbol_set;
- int line_thickness;
- int req_linethickness; // requested line thickness
- int papersize;
- int paperlength; // custom paper size
- int paperwidth;
-};
-
-// Compatibility section.
-//
-// Here we define some functions not present in some of the targets
-// platforms
-#ifndef HAVE_STRSEP
-// Solaris 8 doesn't have the strsep function
-static char *strsep(char **pcadena, const char *delim)
-{
- char *p;
- p = strtok(*pcadena, delim);
- *pcadena = strtok(NULL, delim);
- return p;
-}
-#endif
-
-lbp_font::lbp_font(const char *nm)
-: font(nm)
-{
-}
-
-lbp_font::~lbp_font()
-{
-}
-
-lbp_font *lbp_font::load_lbp_font(const char *s)
-{
- lbp_font *f = new lbp_font(s);
- f->lbpname = NULL;
- f->is_scalable = 1; // Default is that fonts are scalable
- if (!f->load()) {
- delete f;
- return 0;
- }
- return f;
-}
-
-
-void lbp_font::handle_unknown_font_command(const char *command,
- const char *arg,
- const char *filename, int lineno)
-{
- if (strcmp(command, "lbpname") == 0) {
- if (arg == 0)
- fatal_with_file_and_line(filename, lineno,
- "`%1' command requires an argument",
- command);
- this->lbpname = new char[strlen(arg) + 1];
- strcpy(this->lbpname, arg);
- // we recognize bitmapped fonts by the first character of its name
- if (arg[0] == 'N')
- this->is_scalable = 0;
- // fprintf(stderr, "Loading font \"%s\" \n", arg);
- }
- // fprintf(stderr, "Loading font %s \"%s\" in %s at %d\n",
- // command, arg, filename, lineno);
-}
-
-static void wp54charset()
-{
- unsigned int i;
- lbpputs("\033[714;100;29;0;32;120.}");
- for (i = 0; i < sizeof(symset); i++)
- lbpputc(symset[i]);
- lbpputs("\033[100;0 D");
- return;
-}
-
-lbp_printer::lbp_printer(int ps, double pw, double pl)
-: fill_pattern(1),
- fill_mode(0),
- cur_hpos(-1),
- cur_font(0),
- cur_size(0),
- cur_symbol_set(0),
- req_linethickness(-1)
-{
-#ifdef SET_BINARY
- SET_BINARY(fileno(stdout));
-#endif
- lbpinit(stdout);
- lbpputs("\033c\033;\033[2&z\033[7 I\033[?32h\033[?33h\033[11h");
- wp54charset(); // Define the new symbol set
- lbpputs("\033[7 I\033[?32h\033[?33h\033[11h");
- // Paper size handling
- if (orientation < 0)
- orientation = 0; // Default orientation is portrait
- papersize = 14; // Default paper size is A4
- if (font::papersize) {
- papersize = set_papersize(font::papersize);
- paperlength = font::paperlength;
- paperwidth = font::paperwidth;
- }
- if (ps >= 0) {
- papersize = ps;
- paperlength = int(pl * font::res + 0.5);
- paperwidth = int(pw * font::res + 0.5);
- }
- if (papersize < 80) // standard paper
- lbpprintf("\033[%dp", (papersize | orientation));
- else // Custom paper
- lbpprintf("\033[%d;%d;%dp", (papersize | orientation),
- paperlength, paperwidth);
- // Number of copies
- lbpprintf("\033[%dv\n", ncopies);
- lbpputs("\033[0u\033[1u\033P1y Grolbp\033\\");
- lbpmoveabs(0, 0);
- lbpputs("\033[0t\033[2t");
- lbpputs("\033('$2\033)' 1"); // Primary symbol set IBML
- // Secondary symbol set IBMR1
- cur_symbol_set = 0;
-}
-
-lbp_printer::~lbp_printer()
-{
- lbpputs("\033P1y\033\\");
- lbpputs("\033c\033<");
-}
-
-void lbp_printer::begin_page(int)
-{
-}
-
-void lbp_printer::end_page(int)
-{
- if (vdminited())
- vdmflush();
- lbpputc('\f');
- cur_hpos = -1;
-}
-
-void lbp_printer::end_of_line()
-{
- cur_hpos = -1; // force absolute motion
-}
-
-char *lbp_printer::font_name(const lbp_font *f, const int siz)
-{
- static char bfont_name[255]; // The resulting font name
- char type, // Italic, Roman, Bold
- ori, // Normal or Rotated
- *nam; // The font name without other data.
- int cpi; // The font size in characters per inch
- // (bitmapped fonts are monospaced).
- /* Bitmap font selection is ugly in this printer, so don't expect
- this function to be elegant. */
- bfont_name[0] = 0x00;
- if (orientation) // Landscape
- ori = 'R';
- else // Portrait
- ori = 'N';
- type = f->lbpname[strlen(f->lbpname) - 1];
- nam = new char[strlen(f->lbpname) - 2];
- strncpy(nam, &(f->lbpname[1]), strlen(f->lbpname) - 2);
- nam[strlen(f->lbpname) - 2] = 0x00;
- // fprintf(stderr, "Bitmap font '%s' %d %c %c \n", nam, siz, type, ori);
- /* Since these fonts are available only at certain sizes,
- 10 and 17 cpi for courier, 12 and 17 cpi for elite,
- we adjust the resulting size. */
- cpi = 17;
- // Fortunately there are only two bitmapped fonts shipped with the printer.
- if (!strcasecmp(nam, "courier")) {
- // Courier font
- if (siz >= 12)
- cpi = 10;
- else cpi = 17;
- }
- if (!strcasecmp(nam, "elite")) {
- if (siz >= 10)
- cpi = 12;
- else cpi = 17;
- }
- // Now that we have all the data, let's generate the font name.
- if ((type != 'B') && (type != 'I')) // Roman font
- sprintf(bfont_name, "%c%s%d", ori, nam, cpi);
- else
- sprintf(bfont_name, "%c%s%d%c", ori, nam, cpi, type);
- return bfont_name;
-}
-
-void lbp_printer::set_char(int index, font *f, const environment *env,
- int w, const char *name)
-{
- int code = f->get_code(index);
- unsigned char ch = code & 0xff;
- unsigned short symbol_set = code >> 8;
- if (f != cur_font) {
- lbp_font *psf = (lbp_font *)f;
- // fprintf(stderr, "Loading font %s \"%d\" \n", psf->lbpname, env->size);
- if (psf->is_scalable) {
- // Scalable font selection is different from bitmaped
- lbpprintf("\033Pz%s.IBML\033\\\033[%d C", psf->lbpname,
- (int)((env->size * font::res) / 72));
- }
- else
- // bitmapped font
- lbpprintf("\033Pz%s.IBML\033\\\n", font_name(psf, env->size));
- lbpputs("\033)' 1"); // Select IBML and IBMR1 symbol set
- cur_font = psf;
- cur_symbol_set = 0;
- // Update the line thickness if needed
- if ((req_linethickness < 0 ) && (env->size != cur_size))
- set_line_thickness(req_linethickness,env);
- cur_size = env->size;
- }
- if (symbol_set != cur_symbol_set) {
- if (cur_symbol_set == 3)
- // if current symbol set is Symbol we must restore the font
- lbpprintf("\033Pz%s.IBML\033\\\033[%d C", cur_font->lbpname,
- (int)((env->size * font::res) / 72));
- switch (symbol_set) {
- case 0:
- lbpputs("\033('$2\033)' 1"); // Select IBML and IBMR1 symbol sets
- break;
- case 1:
- lbpputs("\033(d\033)' 1"); // Select wp54 symbol set
- break;
- case 2:
- lbpputs("\033('$2\033)'!0"); // Select IBMP symbol set
- break;
- case 3:
- lbpprintf("\033PzSymbol.SYML\033\\\033[%d C",
- (int)((env->size * font::res) / 72));
- lbpputs("\033(\"!!0\033)\"!!1"); // Select symbol font
- break;
- case 4:
- lbpputs("\033)\"! 1\033(\"!$2"); // Select PS symbol set
- break;
- }
- cur_symbol_set = symbol_set;
- }
- if (env->size != cur_size) {
- if (!cur_font->is_scalable)
- lbpprintf("\033Pz%s.IBML\033\\\n", font_name(cur_font, env->size));
- else
- lbpprintf("\033[%d C", (int)((env->size * font::res) / 72));
- cur_size = env->size;
- // Update the line thickness if needed
- if (req_linethickness < 0 )
- set_line_thickness(req_linethickness,env);
- }
- if ((env->hpos != cur_hpos) || (env->vpos != cur_vpos)) {
- // lbpmoveabs(env->hpos - ((5 * 300) / 16), env->vpos);
- lbpmoveabs(env->hpos - 64, env->vpos - 64);
- cur_vpos = env->vpos;
- cur_hpos = env->hpos;
- }
- if ((ch & 0x7F) < 32)
- lbpputs("\033[1.v");
- lbpputc(ch);
- cur_hpos += w;
-}
-
-void lbp_printer::vdmstart()
-{
- FILE *f;
- static int changed_origin = 0;
- errno = 0;
- f = tmpfile();
- // f = fopen("/tmp/gtmp","w+");
- if (f == NULL)
- perror("Opening temporary file");
- vdminit(f);
- if (!changed_origin) { // we should change the origin only one time
- changed_origin = 1;
- vdmorigin(-63, 0);
- }
- vdmlinewidth(line_thickness);
-}
-
-void
-lbp_printer::vdmflush()
-{
- char buffer[1024];
- int bytes_read = 1;
- vdmend();
- fflush(lbpoutput);
- /* let's copy the vdm code to the output */
- rewind(vdmoutput);
- do {
- bytes_read = fread(buffer, 1, sizeof(buffer), vdmoutput);
- bytes_read = fwrite(buffer, 1, bytes_read, lbpoutput);
- } while (bytes_read == sizeof(buffer));
- fclose(vdmoutput); // This will also delete the file,
- // since it is created by tmpfile()
- vdmoutput = NULL;
-}
-
-inline void lbp_printer::setfillmode(int mode)
-{
- if (mode != fill_mode) {
- if (mode != 1)
- vdmsetfillmode(mode, 1, 0);
- else
- vdmsetfillmode(mode, 1, 1); // To get black we must use white
- // inverted
- fill_mode = mode;
- }
-}
-
-inline void lbp_printer::polygon(int hpos, int vpos, int np, int *p)
-{
- int *points, i;
- points = new int[np + 2];
- points[0] = hpos;
- points[1] = vpos;
- // fprintf(stderr, "Poligon (%d,%d) ", points[0], points[1]);
- for (i = 0; i < np; i++)
- points[i + 2] = p[i];
- // for (i = 0; i < np; i++) fprintf(stderr, " %d ", p[i]);
- // fprintf(stderr, "\n");
- vdmpolygon((np /2) + 1, points);
-}
-
-inline void lbp_printer::set_line_thickness(int size,const environment *env)
-{
- if (size == 0)
- line_thickness = 1;
- else {
- if (size < 0)
- // line_thickness =
- // (env->size * (font::res/72)) * (linewidth_factor/1000)
- // we ought to check for overflow
- line_thickness =
- env->size * linewidth_factor * font::res / 72000;
- else // size > 0
- line_thickness = size;
- } // else from if (size == 0)
- if (line_thickness < 1)
- line_thickness = 1;
- if (vdminited())
- vdmlinewidth(line_thickness);
- req_linethickness = size; // an size requested
- /* fprintf(stderr, "thickness: %d == %d, size %d, %d \n",
- size, line_thickness, env->size,req_linethickness); */
- return;
-}; // lbp_printer::set_line_thickness
-
-void lbp_printer::draw(int code, int *p, int np, const environment *env)
-{
- if ((req_linethickness < 0 ) && (env->size != cur_size))
- set_line_thickness(req_linethickness,env);
-
- switch (code) {
- case 't':
- if (np == 0)
- line_thickness = 1;
- else { // troff gratuitously adds an extra 0
- if (np != 1 && np != 2) {
- error("0 or 1 argument required for thickness");
- break;
- };
- set_line_thickness(p[0],env);
- };
- break;
- case 'l': // Line
- if (np != 2) {
- error("2 arguments required for line");
- break;
- }
- if (!vdminited())
- vdmstart();
- vdmline(env->hpos, env->vpos, p[0], p[1]);
-/* fprintf(stderr, "\nline: %d,%d - %d,%d thickness %d == %d\n",
- env->hpos - 64,env->vpos -64, env->hpos - 64 + p[0],
- env->vpos -64 + p[1], env->size, line_thickness);*/
- break;
- case 'R': // Rule
- if (np != 2) {
- error("2 arguments required for Rule");
- break;
- }
- if (vdminited()) {
- setfillmode(fill_pattern); // Solid Rule
- vdmrectangle(env->hpos, env->vpos, p[0], p[1]);
- }
- else {
- lbpruleabs(env->hpos - 64, env->vpos -64, p[0], p[1]);
- cur_vpos = p[1];
- cur_hpos = p[0];
- }
- // fprintf(stderr, "\nrule: thickness %d == %d\n",
- // env->size, line_thickness);
- break;
- case 'P': // Filled Polygon
- if (!vdminited())
- vdmstart();
- setfillmode(fill_pattern);
- polygon(env->hpos, env->vpos, np, p);
- break;
- case 'p': // Empty Polygon
- if (!vdminited())
- vdmstart();
- setfillmode(0);
- polygon(env->hpos, env->vpos, np, p);
- break;
- case 'C': // Filled Circle
- if (!vdminited())
- vdmstart();
- // fprintf(stderr, "Circle (%d,%d) Fill %d\n",
- // env->hpos, env->vpos, fill_pattern);
- setfillmode(fill_pattern);
- vdmcircle(env->hpos + (p[0]/2), env->vpos, p[0]/2);
- break;
- case 'c': // Empty Circle
- if (!vdminited())
- vdmstart();
- setfillmode(0);
- vdmcircle(env->hpos + (p[0]/2), env->vpos, p[0]/2);
- break;
- case 'E': // Filled Ellipse
- if (!vdminited())
- vdmstart();
- setfillmode(fill_pattern);
- vdmellipse(env->hpos + (p[0]/2), env->vpos, p[0]/2, p[1]/2, 0);
- break;
- case 'e': // Empty Ellipse
- if (!vdminited())
- vdmstart();
- setfillmode(0);
- vdmellipse(env->hpos + (p[0]/2), env->vpos, p[0]/2, p[1]/2, 0);
- break;
- case 'a': // Arc
- if (!vdminited())
- vdmstart();
- setfillmode(0);
- // VDM draws arcs clockwise and pic counterclockwise
- // We must compensate for that, exchanging the starting and
- // ending points
- vdmvarc(env->hpos + p[0], env->vpos+p[1],
- int(sqrt(double((p[0]*p[0]) + (p[1]*p[1])))),
- p[2], p[3],
- (-p[0]), (-p[1]), 1, 2);
- break;
- case '~': // Spline
- if (!vdminited())
- vdmstart();
- setfillmode(0);
- vdmspline(np/2, env->hpos, env->vpos, p);
- break;
- case 'f':
- if (np != 1 && np != 2) {
- error("1 argument required for fill");
- break;
- }
- // fprintf(stderr, "Fill %d\n", p[0]);
- if ((p[0] == 1) || (p[0] >= 1000)) { // Black
- fill_pattern = 1;
- break;
- }
- if (p[0] == 0) { // White
- fill_pattern = 0;
- break;
- }
- if ((p[0] > 1) && (p[0] < 1000))
- {
- if (p[0] >= 990) fill_pattern = -23;
- else if (p[0] >= 700) fill_pattern = -28;
- else if (p[0] >= 500) fill_pattern = -27;
- else if (p[0] >= 400) fill_pattern = -26;
- else if (p[0] >= 300) fill_pattern = -25;
- else if (p[0] >= 200) fill_pattern = -22;
- else if (p[0] >= 100) fill_pattern = -24;
- else fill_pattern = -21;
- }
- break;
- case 'F':
- // not implemented yet
- break;
- default:
- error("unrecognised drawing command `%1'", char(code));
- break;
- }
- return;
-}
-
-font *lbp_printer::make_font(const char *nm)
-{
- return lbp_font::load_lbp_font(nm);
-}
-
-printer *make_printer()
-{
- return new lbp_printer(user_papersize, user_paperwidth, user_paperlength);
-}
-
-static struct {
- const char *name;
- int code;
-} lbp_papersizes[] =
- {{ "A4", 14 },
- { "letter", 30 },
- { "legal", 32 },
- { "executive", 40 },
- };
-
-static int set_papersize(const char *paperformat)
-{
- unsigned int i;
- // First test for a standard (i.e. supported directly by the printer)
- // paper size
- for (i = 0 ; i < sizeof(lbp_papersizes) / sizeof(lbp_papersizes[0]); i++)
- {
- if (strcasecmp(lbp_papersizes[i].name,paperformat) == 0)
- return lbp_papersizes[i].code;
- }
- // Otherwise, we assume a custom paper size
- return 82;
-}
-
-static void handle_unknown_desc_command(const char *command, const char *arg,
- const char *filename, int lineno)
-{
- // orientation command
- if (strcasecmp(command, "orientation") == 0) {
- // We give priority to command line options
- if (orientation > 0)
- return;
- if (arg == 0)
- error_with_file_and_line(filename, lineno,
- "`orientation' command requires an argument");
- else {
- if (strcasecmp(arg, "portrait") == 0)
- orientation = 0;
- else {
- if (strcasecmp(arg, "landscape") == 0)
- orientation = 1;
- else
- error_with_file_and_line(filename, lineno,
- "invalid argument to `orientation' command");
- }
- }
- }
-}
-
-static struct option long_options[] = {
- { "orientation", required_argument, NULL, 'o' },
- { "version", no_argument, NULL, 'v' },
- { "copies", required_argument, NULL, 'c' },
- { "landscape", no_argument, NULL, 'l' },
- { "papersize", required_argument, NULL, 'p' },
- { "linewidth", required_argument, NULL, 'w' },
- { "fontdir", required_argument, NULL, 'F' },
- { "help", no_argument, NULL, 'h' },
- { NULL, 0, 0, 0 }
-};
-
-static void usage(FILE *stream)
-{
- fprintf(stream,
- "usage: %s [-lvh] [-c n] [-p paper_size] [-F dir] [-o or]\n"
- " [-w width] [files ...]\n"
- "\n"
- " -o --orientation=[portrait|landscape]\n"
- " -v --version\n"
- " -c --copies=numcopies\n"
- " -l --landscape\n"
- " -p --papersize=paper_size\n"
- " -w --linewidth=width\n"
- " -F --fontdir=dir\n"
- " -h --help\n",
- program_name);
-}
-
-int main(int argc, char **argv)
-{
- if (program_name == NULL)
- program_name = strsave(argv[0]);
- font::set_unknown_desc_command_handler(handle_unknown_desc_command);
- // command line parsing
- int c = 0;
- int option_index = 0;
- while (c >= 0) {
- c = getopt_long (argc, argv, "F:p:lvo:c:hw:",
- long_options, &option_index);
- switch (c) {
- case 'F':
- font::command_line_font_dir(optarg);
- break;
- case 'p':
- {
- const char *s;
- if (!font::scan_papersize(optarg, &s,
- &user_paperlength, &user_paperwidth))
- error("invalid paper size `%1' ignored", optarg);
- else
- user_papersize = set_papersize(s);
- break;
- }
- case 'l':
- orientation = 1;
- break;
- case 'v':
- printf("GNU grolbp (groff) version %s\n", Version_string);
- exit(0);
- break;
- case 'o':
- if (strcasecmp(optarg, "portrait") == 0)
- orientation = 0;
- else {
- if (strcasecmp(optarg, "landscape") == 0)
- orientation = 1;
- else
- error("unknown orientation '%1'", optarg);
- };
- break;
- case 'c':
- {
- char *ptr;
- long n = strtol(optarg, &ptr, 10);
- if ((n <= 0) && (ptr == optarg))
- error("argument for -c must be a positive integer");
- else if (n <= 0 || n > 32767)
- error("out of range argument for -c");
- else
- ncopies = unsigned(n);
- break;
- }
- case 'w':
- {
- char *ptr;
- long n = strtol(optarg, &ptr, 10);
- if (n == 0 && ptr == optarg)
- error("argument for -w must be a non-negative integer");
- else if (n < 0 || n > INT_MAX)
- error("out of range argument for -w");
- else
- linewidth_factor = int(n);
- break;
- }
- case 'h':
- usage(stdout);
- exit(0);
- break;
- case '?':
- usage(stderr);
- exit(1);
- break;
- }
- }
- if (optind >= argc)
- do_file("-");
- while (optind < argc)
- do_file(argv[optind++]);
- lbpputs("\033c\033<");
- delete pr;
- return 0;
-}
diff --git a/contrib/groff/src/devices/grolj4/lj4.cc b/contrib/groff/src/devices/grolj4/lj4.cc
deleted file mode 100644
index 0c3150d..0000000
--- a/contrib/groff/src/devices/grolj4/lj4.cc
+++ /dev/null
@@ -1,708 +0,0 @@
-// -*- C++ -*-
-/* Copyright (C) 1994, 2000, 2001, 2002 Free Software Foundation, Inc.
- Written by James Clark (jjc@jclark.com)
-
-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 2, 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 groff; see the file COPYING. If not, write to the Free Software
-Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-/*
-TODO
-
-option to use beziers for circle/ellipse/arc
-option to use lines for spline (for LJ3)
-left/top offset registration
-output bin selection option
-paper source option
-output non-integer parameters using fixed point numbers
-X command to insert contents of file
-X command to specify inline escape sequence (how to specify unprintable chars?)
-X command to include bitmap graphics
-*/
-
-#include "driver.h"
-#include "nonposix.h"
-
-extern "C" const char *Version_string;
-
-static struct {
- const char *name;
- int code;
- // at 300dpi
- int x_offset_portrait;
- int x_offset_landscape;
-} paper_table[] = {
- { "letter", 2, 75, 60 },
- { "legal", 3, 75, 60 },
- { "executive", 1, 75, 60 },
- { "a4", 26, 71, 59 },
- { "com10", 81, 75, 60 },
- { "monarch", 80, 75, 60 },
- { "c5", 91, 71, 59 },
- { "b5", 100, 71, 59 },
- { "dl", 90, 71, 59 },
-};
-
-static int user_paper_size = -1;
-static int landscape_flag = 0;
-static int duplex_flag = 0;
-
-// An upper limit on the paper size in centipoints,
-// used for setting HPGL picture frame.
-#define MAX_PAPER_WIDTH (12*720)
-#define MAX_PAPER_HEIGHT (17*720)
-
-// Dotted lines that are thinner than this don't work right.
-#define MIN_DOT_PEN_WIDTH .351
-
-#ifndef DEFAULT_LINE_WIDTH_FACTOR
-// in ems/1000
-#define DEFAULT_LINE_WIDTH_FACTOR 40
-#endif
-
-const int DEFAULT_HPGL_UNITS = 1016;
-int line_width_factor = DEFAULT_LINE_WIDTH_FACTOR;
-unsigned ncopies = 0; // 0 means don't send ncopies command
-
-static int lookup_paper_size(const char *);
-
-class lj4_font : public font {
-public:
- ~lj4_font();
- void handle_unknown_font_command(const char *command, const char *arg,
- const char *filename, int lineno);
- static lj4_font *load_lj4_font(const char *);
- int weight;
- int style;
- int proportional;
- int typeface;
-private:
- lj4_font(const char *);
-};
-
-lj4_font::lj4_font(const char *nm)
-: font(nm), weight(0), style(0), proportional(0), typeface(0)
-{
-}
-
-lj4_font::~lj4_font()
-{
-}
-
-lj4_font *lj4_font::load_lj4_font(const char *s)
-{
- lj4_font *f = new lj4_font(s);
- if (!f->load()) {
- delete f;
- return 0;
- }
- return f;
-}
-
-static struct {
- const char *s;
- int lj4_font::*ptr;
- int min;
- int max;
-} command_table[] = {
- { "pclweight", &lj4_font::weight, -7, 7 },
- { "pclstyle", &lj4_font::style, 0, 32767 },
- { "pclproportional", &lj4_font::proportional, 0, 1 },
- { "pcltypeface", &lj4_font::typeface, 0, 65535 },
-};
-
-void lj4_font::handle_unknown_font_command(const char *command,
- const char *arg,
- const char *filename, int lineno)
-{
- for (unsigned int i = 0;
- i < sizeof(command_table)/sizeof(command_table[0]); i++) {
- if (strcmp(command, command_table[i].s) == 0) {
- if (arg == 0)
- fatal_with_file_and_line(filename, lineno,
- "`%1' command requires an argument",
- command);
- char *ptr;
- long n = strtol(arg, &ptr, 10);
- if (n == 0 && ptr == arg)
- fatal_with_file_and_line(filename, lineno,
- "`%1' command requires numeric argument",
- command);
- if (n < command_table[i].min) {
- error_with_file_and_line(filename, lineno,
- "argument for `%1' command must not be less than %2",
- command, command_table[i].min);
- n = command_table[i].min;
- }
- else if (n > command_table[i].max) {
- error_with_file_and_line(filename, lineno,
- "argument for `%1' command must not be greater than %2",
- command, command_table[i].max);
- n = command_table[i].max;
- }
- this->*command_table[i].ptr = int(n);
- break;
- }
- }
-}
-
-class lj4_printer : public printer {
-public:
- lj4_printer(int);
- ~lj4_printer();
- void set_char(int, font *, const environment *, int, const char *name);
- void draw(int code, int *p, int np, const environment *env);
- void begin_page(int);
- void end_page(int page_length);
- font *make_font(const char *);
- void end_of_line();
-private:
- void set_line_thickness(int size, int dot = 0);
- void hpgl_init();
- void hpgl_start();
- void hpgl_end();
- int moveto(int hpos, int vpos);
- int moveto1(int hpos, int vpos);
-
- int cur_hpos;
- int cur_vpos;
- lj4_font *cur_font;
- int cur_size;
- unsigned short cur_symbol_set;
- int x_offset;
- int line_thickness;
- double pen_width;
- double hpgl_scale;
- int hpgl_inited;
- int paper_size;
-};
-
-inline
-int lj4_printer::moveto(int hpos, int vpos)
-{
- if (cur_hpos != hpos || cur_vpos != vpos || cur_hpos < 0)
- return moveto1(hpos, vpos);
- else
- return 1;
-}
-
-inline
-void lj4_printer::hpgl_start()
-{
- fputs("\033%1B", stdout);
-}
-
-inline
-void lj4_printer::hpgl_end()
-{
- fputs(";\033%0A", stdout);
-}
-
-lj4_printer::lj4_printer(int ps)
-: cur_hpos(-1),
- cur_font(0),
- cur_size(0),
- cur_symbol_set(0),
- line_thickness(-1),
- pen_width(-1.0),
- hpgl_inited(0)
-{
- if (7200 % font::res != 0)
- fatal("invalid resolution %1: resolution must be a factor of 7200",
- font::res);
- fputs("\033E", stdout); // reset
- if (font::res != 300)
- printf("\033&u%dD", font::res); // unit of measure
- if (ncopies > 0)
- printf("\033&l%uX", ncopies);
- paper_size = 0; // default to letter
- if (font::papersize) {
- int n = lookup_paper_size(font::papersize);
- if (n < 0)
- error("unknown paper size `%1'", font::papersize);
- else
- paper_size = n;
- }
- if (ps >= 0)
- paper_size = ps;
- printf("\033&l%dA" // paper size
- "\033&l%dO" // orientation
- "\033&l0E", // no top margin
- paper_table[paper_size].code,
- landscape_flag != 0);
- if (landscape_flag)
- x_offset = paper_table[paper_size].x_offset_landscape;
- else
- x_offset = paper_table[paper_size].x_offset_portrait;
- x_offset = (x_offset * font::res) / 300;
- if (duplex_flag)
- printf("\033&l%dS", duplex_flag);
-}
-
-lj4_printer::~lj4_printer()
-{
- fputs("\033E", stdout);
-}
-
-void lj4_printer::begin_page(int)
-{
-}
-
-void lj4_printer::end_page(int)
-{
- putchar('\f');
- cur_hpos = -1;
-}
-
-void lj4_printer::end_of_line()
-{
- cur_hpos = -1; // force absolute motion
-}
-
-inline
-int is_unprintable(unsigned char c)
-{
- return c < 32 && (c == 0 || (7 <= c && c <= 15) || c == 27);
-}
-
-void lj4_printer::set_char(int index, font *f, const environment *env,
- int w, const char *name)
-{
- int code = f->get_code(index);
-
- unsigned char ch = code & 0xff;
- unsigned short symbol_set = code >> 8;
- if (symbol_set != cur_symbol_set) {
- printf("\033(%d%c", symbol_set/32, (symbol_set & 31) + 64);
- cur_symbol_set = symbol_set;
- }
- if (f != cur_font) {
- lj4_font *psf = (lj4_font *)f;
- // FIXME only output those that are needed
- printf("\033(s%dp%ds%db%dT",
- psf->proportional,
- psf->style,
- psf->weight,
- psf->typeface);
- if (!psf->proportional || !cur_font || !cur_font->proportional)
- cur_size = 0;
- cur_font = psf;
- }
- if (env->size != cur_size) {
- if (cur_font->proportional) {
- static const char *quarters[] = { "", ".25", ".5", ".75" };
- printf("\033(s%d%sV", env->size/4, quarters[env->size & 3]);
- }
- else {
- double pitch = double(font::res)/w;
- // PCL uses the next largest pitch, so round it down.
- pitch = floor(pitch*100.0)/100.0;
- printf("\033(s%.2fH", pitch);
- }
- cur_size = env->size;
- }
- if (!moveto(env->hpos, env->vpos))
- return;
- if (is_unprintable(ch))
- fputs("\033&p1X", stdout);
- putchar(ch);
- cur_hpos += w;
-}
-
-int lj4_printer::moveto1(int hpos, int vpos)
-{
- if (hpos < x_offset || vpos < 0)
- return 0;
- fputs("\033*p", stdout);
- if (cur_hpos < 0)
- printf("%dx%dY", hpos - x_offset, vpos);
- else {
- if (cur_hpos != hpos)
- printf("%s%d%c", hpos > cur_hpos ? "+" : "",
- hpos - cur_hpos, vpos == cur_vpos ? 'X' : 'x');
- if (cur_vpos != vpos)
- printf("%s%dY", vpos > cur_vpos ? "+" : "", vpos - cur_vpos);
- }
- cur_hpos = hpos;
- cur_vpos = vpos;
- return 1;
-}
-
-void lj4_printer::draw(int code, int *p, int np, const environment *env)
-{
- switch (code) {
- case 'R':
- {
- if (np != 2) {
- error("2 arguments required for rule");
- break;
- }
- int hpos = env->hpos;
- int vpos = env->vpos;
- int hsize = p[0];
- int vsize = p[1];
- if (hsize < 0) {
- hpos += hsize;
- hsize = -hsize;
- }
- if (vsize < 0) {
- vpos += vsize;
- vsize = -vsize;
- }
- if (!moveto(hpos, vpos))
- return;
- printf("\033*c%da%db0P", hsize, vsize);
- break;
- }
- case 'l':
- if (np != 2) {
- error("2 arguments required for line");
- break;
- }
- hpgl_init();
- if (!moveto(env->hpos, env->vpos))
- return;
- hpgl_start();
- set_line_thickness(env->size, p[0] == 0 && p[1] == 0);
- printf("PD%d,%d", p[0], p[1]);
- hpgl_end();
- break;
- case 'p':
- case 'P':
- {
- if (np & 1) {
- error("even number of arguments required for polygon");
- break;
- }
- if (np == 0) {
- error("no arguments for polygon");
- break;
- }
- hpgl_init();
- if (!moveto(env->hpos, env->vpos))
- return;
- hpgl_start();
- if (code == 'p')
- set_line_thickness(env->size);
- printf("PMPD%d", p[0]);
- for (int i = 1; i < np; i++)
- printf(",%d", p[i]);
- printf("PM2%cP", code == 'p' ? 'E' : 'F');
- hpgl_end();
- break;
- }
- case '~':
- {
- if (np & 1) {
- error("even number of arguments required for spline");
- break;
- }
- if (np == 0) {
- error("no arguments for spline");
- break;
- }
- hpgl_init();
- if (!moveto(env->hpos, env->vpos))
- return;
- hpgl_start();
- set_line_thickness(env->size);
- printf("PD%d,%d", p[0]/2, p[1]/2);
- const int tnum = 2;
- const int tden = 3;
- if (np > 2) {
- fputs("BR", stdout);
- for (int i = 0; i < np - 2; i += 2) {
- if (i != 0)
- putchar(',');
- printf("%d,%d,%d,%d,%d,%d",
- (p[i]*tnum)/(2*tden),
- (p[i + 1]*tnum)/(2*tden),
- p[i]/2 + (p[i + 2]*(tden - tnum))/(2*tden),
- p[i + 1]/2 + (p[i + 3]*(tden - tnum))/(2*tden),
- (p[i] - p[i]/2) + p[i + 2]/2,
- (p[i + 1] - p[i + 1]/2) + p[i + 3]/2);
- }
- }
- printf("PR%d,%d", p[np - 2] - p[np - 2]/2, p[np - 1] - p[np - 1]/2);
- hpgl_end();
- break;
- }
- case 'c':
- case 'C':
- // troff adds an extra argument to C
- if (np != 1 && !(code == 'C' && np == 2)) {
- error("1 argument required for circle");
- break;
- }
- hpgl_init();
- if (!moveto(env->hpos + p[0]/2, env->vpos))
- return;
- hpgl_start();
- if (code == 'c') {
- set_line_thickness(env->size);
- printf("CI%d", p[0]/2);
- }
- else
- printf("WG%d,0,360", p[0]/2);
- hpgl_end();
- break;
- case 'e':
- case 'E':
- if (np != 2) {
- error("2 arguments required for ellipse");
- break;
- }
- hpgl_init();
- if (!moveto(env->hpos + p[0]/2, env->vpos))
- return;
- hpgl_start();
- printf("SC0,%.4f,0,-%.4f,2", hpgl_scale * double(p[0])/p[1], hpgl_scale);
- if (code == 'e') {
- set_line_thickness(env->size);
- printf("CI%d", p[1]/2);
- }
- else
- printf("WG%d,0,360", p[1]/2);
- printf("SC0,%.4f,0,-%.4f,2", hpgl_scale, hpgl_scale);
- hpgl_end();
- break;
- case 'a':
- {
- if (np != 4) {
- error("4 arguments required for arc");
- break;
- }
- hpgl_init();
- if (!moveto(env->hpos, env->vpos))
- return;
- hpgl_start();
- set_line_thickness(env->size);
- double c[2];
- if (adjust_arc_center(p, c)) {
- double sweep = ((atan2(p[1] + p[3] - c[1], p[0] + p[2] - c[0])
- - atan2(-c[1], -c[0]))
- * 180.0/PI);
- if (sweep > 0.0)
- sweep -= 360.0;
- printf("PDAR%d,%d,%f", int(c[0]), int(c[1]), sweep);
- }
- else
- printf("PD%d,%d", p[0] + p[2], p[1] + p[3]);
- hpgl_end();
- }
- break;
- case 'f':
- if (np != 1 && np != 2) {
- error("1 argument required for fill");
- break;
- }
- hpgl_init();
- hpgl_start();
- if (p[0] >= 0 && p[0] <= 1000)
- printf("FT10,%d", p[0]/10);
- hpgl_end();
- break;
- case 'F':
- // not implemented yet
- break;
- case 't':
- {
- if (np == 0) {
- line_thickness = -1;
- }
- else {
- // troff gratuitously adds an extra 0
- if (np != 1 && np != 2) {
- error("0 or 1 argument required for thickness");
- break;
- }
- line_thickness = p[0];
- }
- break;
- }
- default:
- error("unrecognised drawing command `%1'", char(code));
- break;
- }
-}
-
-void lj4_printer::hpgl_init()
-{
- if (hpgl_inited)
- return;
- hpgl_inited = 1;
- hpgl_scale = double(DEFAULT_HPGL_UNITS)/font::res;
- printf("\033&f0S" // push position
- "\033*p0x0Y" // move to 0,0
- "\033*c%dx%dy0T" // establish picture frame
- "\033%%1B" // switch to HPGL
- "SP1SC0,%.4f,0,-%.4f,2IR0,100,0,100" // set up scaling
- "LA1,4,2,4" // round line ends and joins
- "PR" // relative plotting
- "TR0" // opaque
- ";\033%%1A" // back to PCL
- "\033&f1S", // pop position
- MAX_PAPER_WIDTH, MAX_PAPER_HEIGHT,
- hpgl_scale, hpgl_scale);
-}
-
-void lj4_printer::set_line_thickness(int size, int dot)
-{
- double pw;
- if (line_thickness < 0)
- pw = (size * (line_width_factor * 25.4))/(font::sizescale * 72000.0);
- else
- pw = line_thickness*25.4/font::res;
- if (dot && pw < MIN_DOT_PEN_WIDTH)
- pw = MIN_DOT_PEN_WIDTH;
- if (pw != pen_width) {
- printf("PW%f", pw);
- pen_width = pw;
- }
-}
-
-font *lj4_printer::make_font(const char *nm)
-{
- return lj4_font::load_lj4_font(nm);
-}
-
-printer *make_printer()
-{
- return new lj4_printer(user_paper_size);
-}
-
-static
-int lookup_paper_size(const char *s)
-{
- for (unsigned int i = 0;
- i < sizeof(paper_table)/sizeof(paper_table[0]); i++) {
- // FIXME Perhaps allow unique prefix.
- if (strcasecmp(s, paper_table[i].name) == 0)
- return i;
- }
- return -1;
-}
-
-static void usage(FILE *stream);
-
-extern "C" int optopt, optind;
-
-int main(int argc, char **argv)
-{
- program_name = argv[0];
- static char stderr_buf[BUFSIZ];
- setbuf(stderr, stderr_buf);
- int c;
- static const struct option long_options[] = {
- { "help", no_argument, 0, CHAR_MAX + 1 },
- { "version", no_argument, 0, 'v' },
- { NULL, 0, 0, 0 }
- };
- while ((c = getopt_long(argc, argv, ":F:p:d:lvw:c:", long_options, NULL))
- != EOF)
- switch(c) {
- case 'l':
- landscape_flag = 1;
- break;
- case ':':
- if (optopt == 'd') {
- fprintf(stderr, "duplex assumed to be long-side\n");
- duplex_flag = 1;
- } else
- fprintf(stderr, "option -%c requires an operand\n", optopt);
- fflush(stderr);
- break;
- case 'd':
- if (!isdigit(*optarg)) // this ugly hack prevents -d without
- optind--; // args from messing up the arg list
- duplex_flag = atoi(optarg);
- if (duplex_flag != 1 && duplex_flag != 2) {
- fprintf(stderr, "odd value for duplex; assumed to be long-side\n");
- duplex_flag = 1;
- }
- break;
- case 'p':
- {
- int n = lookup_paper_size(optarg);
- if (n < 0)
- error("unknown paper size `%1'", optarg);
- else
- user_paper_size = n;
- break;
- }
- case 'v':
- {
- printf("GNU grolj4 (groff) version %s\n", Version_string);
- exit(0);
- break;
- }
- case 'F':
- font::command_line_font_dir(optarg);
- break;
- case 'c':
- {
- char *ptr;
- long n = strtol(optarg, &ptr, 10);
- if (n == 0 && ptr == optarg)
- error("argument for -c must be a positive integer");
- else if (n <= 0 || n > 32767)
- error("out of range argument for -c");
- else
- ncopies = unsigned(n);
- break;
- }
- case 'w':
- {
- char *ptr;
- long n = strtol(optarg, &ptr, 10);
- if (n == 0 && ptr == optarg)
- error("argument for -w must be a non-negative integer");
- else if (n < 0 || n > INT_MAX)
- error("out of range argument for -w");
- else
- line_width_factor = int(n);
- break;
- }
- case CHAR_MAX + 1: // --help
- usage(stdout);
- exit(0);
- break;
- case '?':
- usage(stderr);
- exit(1);
- break;
- default:
- assert(0);
- }
-#ifdef SET_BINARY
- SET_BINARY(fileno(stdout));
-#endif
- if (optind >= argc)
- do_file("-");
- else {
- for (int i = optind; i < argc; i++)
- do_file(argv[i]);
- }
- delete pr;
- return 0;
-}
-
-static void usage(FILE *stream)
-{
- fprintf(stream,
- "usage: %s [-lv] [-d [n]] [-c n] [-p paper_size]\n"
- " [-w n] [-F dir] [files ...]\n",
- program_name);
-}
diff --git a/contrib/groff/src/devices/grops/ps.cc b/contrib/groff/src/devices/grops/ps.cc
deleted file mode 100644
index 47d1f65..0000000
--- a/contrib/groff/src/devices/grops/ps.cc
+++ /dev/null
@@ -1,1642 +0,0 @@
-// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001, 2002
- Free Software Foundation, Inc.
- Written by James Clark (jjc@jclark.com)
-
-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 2, 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 groff; see the file COPYING. If not, write to the Free Software
-Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#include "driver.h"
-#include "stringclass.h"
-#include "cset.h"
-#include "nonposix.h"
-#include "paper.h"
-
-#include "ps.h"
-#include <time.h>
-
-#ifdef NEED_DECLARATION_PUTENV
-extern "C" {
- int putenv(const char *);
-}
-#endif /* NEED_DECLARATION_PUTENV */
-
-extern "C" const char *Version_string;
-
-static int landscape_flag = 0;
-static int manual_feed_flag = 0;
-static int ncopies = 1;
-static int linewidth = -1;
-// Non-zero means generate PostScript code that guesses the paper
-// length using the imageable area.
-static int guess_flag = 0;
-static double user_paper_length = 0;
-
-// Non-zero if -b was specified on the command line.
-static int bflag = 0;
-unsigned broken_flags = 0;
-
-#define DEFAULT_LINEWIDTH 40 /* in ems/1000 */
-#define MAX_LINE_LENGTH 72
-#define FILL_MAX 1000
-
-const char *const dict_name = "grops";
-const char *const defs_dict_name = "DEFS";
-const int DEFS_DICT_SPARE = 50;
-
-double degrees(double r)
-{
- return r*180.0/PI;
-}
-
-double radians(double d)
-{
- return d*PI/180.0;
-}
-
-inline double transform_fill(int fill)
-{
- return 1 - fill/double(FILL_MAX);
-}
-
-// This is used for testing whether a character should be output in the
-// PostScript file using \nnn, so we really want the character to be
-// less than 0200.
-
-inline int is_ascii(char c)
-{
- return (unsigned char)c < 0200;
-}
-
-ps_output::ps_output(FILE *f, int n)
-: fp(f), col(0), max_line_length(n), need_space(0), fixed_point(0)
-{
-}
-
-ps_output &ps_output::set_file(FILE *f)
-{
- fp = f;
- col = 0;
- return *this;
-}
-
-ps_output &ps_output::copy_file(FILE *infp)
-{
- int c;
- while ((c = getc(infp)) != EOF)
- putc(c, fp);
- return *this;
-}
-
-ps_output &ps_output::end_line()
-{
- if (col != 0) {
- putc('\n', fp);
- col = 0;
- need_space = 0;
- }
- return *this;
-}
-
-ps_output &ps_output::special(const char *s)
-{
- if (s == 0 || *s == '\0')
- return *this;
- if (col != 0) {
- putc('\n', fp);
- col = 0;
- }
- fputs(s, fp);
- if (strchr(s, '\0')[-1] != '\n')
- putc('\n', fp);
- need_space = 0;
- return *this;
-}
-
-ps_output &ps_output::simple_comment(const char *s)
-{
- if (col != 0)
- putc('\n', fp);
- putc('%', fp);
- putc('%', fp);
- fputs(s, fp);
- putc('\n', fp);
- col = 0;
- need_space = 0;
- return *this;
-}
-
-ps_output &ps_output::begin_comment(const char *s)
-{
- if (col != 0)
- putc('\n', fp);
- putc('%', fp);
- putc('%', fp);
- fputs(s, fp);
- col = 2 + strlen(s);
- return *this;
-}
-
-ps_output &ps_output::end_comment()
-{
- if (col != 0) {
- putc('\n', fp);
- col = 0;
- }
- need_space = 0;
- return *this;
-}
-
-ps_output &ps_output::comment_arg(const char *s)
-{
- int len = strlen(s);
- if (col + len + 1 > max_line_length) {
- putc('\n', fp);
- fputs("%%+", fp);
- col = 3;
- }
- putc(' ', fp);
- fputs(s, fp);
- col += len + 1;
- return *this;
-}
-
-ps_output &ps_output::set_fixed_point(int n)
-{
- assert(n >= 0 && n <= 10);
- fixed_point = n;
- return *this;
-}
-
-ps_output &ps_output::put_delimiter(char c)
-{
- if (col + 1 > max_line_length) {
- putc('\n', fp);
- col = 0;
- }
- putc(c, fp);
- col++;
- need_space = 0;
- return *this;
-}
-
-ps_output &ps_output::put_string(const char *s, int n)
-{
- int len = 0;
- int i;
- for (i = 0; i < n; i++) {
- char c = s[i];
- if (is_ascii(c) && csprint(c)) {
- if (c == '(' || c == ')' || c == '\\')
- len += 2;
- else
- len += 1;
- }
- else
- len += 4;
- }
- if (len > n*2) {
- if (col + n*2 + 2 > max_line_length && n*2 + 2 <= max_line_length) {
- putc('\n', fp);
- col = 0;
- }
- if (col + 1 > max_line_length) {
- putc('\n', fp);
- col = 0;
- }
- putc('<', fp);
- col++;
- for (i = 0; i < n; i++) {
- if (col + 2 > max_line_length) {
- putc('\n', fp);
- col = 0;
- }
- fprintf(fp, "%02x", s[i] & 0377);
- col += 2;
- }
- putc('>', fp);
- col++;
- }
- else {
- if (col + len + 2 > max_line_length && len + 2 <= max_line_length) {
- putc('\n', fp);
- col = 0;
- }
- if (col + 2 > max_line_length) {
- putc('\n', fp);
- col = 0;
- }
- putc('(', fp);
- col++;
- for (i = 0; i < n; i++) {
- char c = s[i];
- if (is_ascii(c) && csprint(c)) {
- if (c == '(' || c == ')' || c == '\\')
- len = 2;
- else
- len = 1;
- }
- else
- len = 4;
- if (col + len + 1 > max_line_length) {
- putc('\\', fp);
- putc('\n', fp);
- col = 0;
- }
- switch (len) {
- case 1:
- putc(c, fp);
- break;
- case 2:
- putc('\\', fp);
- putc(c, fp);
- break;
- case 4:
- fprintf(fp, "\\%03o", c & 0377);
- break;
- default:
- assert(0);
- }
- col += len;
- }
- putc(')', fp);
- col++;
- }
- need_space = 0;
- return *this;
-}
-
-ps_output &ps_output::put_number(int n)
-{
- char buf[1 + INT_DIGITS + 1];
- sprintf(buf, "%d", n);
- int len = strlen(buf);
- if (col > 0 && col + len + need_space > max_line_length) {
- putc('\n', fp);
- col = 0;
- need_space = 0;
- }
- if (need_space) {
- putc(' ', fp);
- col++;
- }
- fputs(buf, fp);
- col += len;
- need_space = 1;
- return *this;
-}
-
-ps_output &ps_output::put_fix_number(int i)
-{
- const char *p = if_to_a(i, fixed_point);
- int len = strlen(p);
- if (col > 0 && col + len + need_space > max_line_length) {
- putc('\n', fp);
- col = 0;
- need_space = 0;
- }
- if (need_space) {
- putc(' ', fp);
- col++;
- }
- fputs(p, fp);
- col += len;
- need_space = 1;
- return *this;
-}
-
-ps_output &ps_output::put_float(double d)
-{
- char buf[128];
- sprintf(buf, "%.3g", d);
- int len = strlen(buf);
- if (col > 0 && col + len + need_space > max_line_length) {
- putc('\n', fp);
- col = 0;
- need_space = 0;
- }
- if (need_space) {
- putc(' ', fp);
- col++;
- }
- fputs(buf, fp);
- col += len;
- need_space = 1;
- return *this;
-}
-
-ps_output &ps_output::put_symbol(const char *s)
-{
- int len = strlen(s);
- if (col > 0 && col + len + need_space > max_line_length) {
- putc('\n', fp);
- col = 0;
- need_space = 0;
- }
- if (need_space) {
- putc(' ', fp);
- col++;
- }
- fputs(s, fp);
- col += len;
- need_space = 1;
- return *this;
-}
-
-ps_output &ps_output::put_color(unsigned int c)
-{
- char buf[128];
- sprintf(buf, "%.3g", double(c) / color::MAX_COLOR_VAL);
- int len = strlen(buf);
- if (col > 0 && col + len + need_space > max_line_length) {
- putc('\n', fp);
- col = 0;
- need_space = 0;
- }
- if (need_space) {
- putc(' ', fp);
- col++;
- }
- fputs(buf, fp);
- col += len;
- need_space = 1;
- return *this;
-}
-
-ps_output &ps_output::put_literal_symbol(const char *s)
-{
- int len = strlen(s);
- if (col > 0 && col + len + 1 > max_line_length) {
- putc('\n', fp);
- col = 0;
- }
- putc('/', fp);
- fputs(s, fp);
- col += len + 1;
- need_space = 1;
- return *this;
-}
-
-class ps_font : public font {
- ps_font(const char *);
-public:
- int encoding_index;
- char *encoding;
- char *reencoded_name;
- ~ps_font();
- void handle_unknown_font_command(const char *command, const char *arg,
- const char *filename, int lineno);
- static ps_font *load_ps_font(const char *);
-};
-
-ps_font *ps_font::load_ps_font(const char *s)
-{
- ps_font *f = new ps_font(s);
- if (!f->load()) {
- delete f;
- return 0;
- }
- return f;
-}
-
-ps_font::ps_font(const char *nm)
-: font(nm), encoding_index(-1), encoding(0), reencoded_name(0)
-{
-}
-
-ps_font::~ps_font()
-{
- a_delete encoding;
- a_delete reencoded_name;
-}
-
-void ps_font::handle_unknown_font_command(const char *command, const char *arg,
- const char *filename, int lineno)
-{
- if (strcmp(command, "encoding") == 0) {
- if (arg == 0)
- error_with_file_and_line(filename, lineno,
- "`encoding' command requires an argument");
- else
- encoding = strsave(arg);
- }
-}
-
-static void handle_unknown_desc_command(const char *command, const char *arg,
- const char *filename, int lineno)
-{
- if (strcmp(command, "broken") == 0) {
- if (arg == 0)
- error_with_file_and_line(filename, lineno,
- "`broken' command requires an argument");
- else if (!bflag)
- broken_flags = atoi(arg);
- }
-}
-
-struct style {
- font *f;
- int point_size;
- int height;
- int slant;
- style();
- style(font *, int, int, int);
- int operator==(const style &) const;
- int operator!=(const style &) const;
-};
-
-style::style() : f(0)
-{
-}
-
-style::style(font *p, int sz, int h, int sl)
-: f(p), point_size(sz), height(h), slant(sl)
-{
-}
-
-int style::operator==(const style &s) const
-{
- return (f == s.f && point_size == s.point_size
- && height == s.height && slant == s.slant);
-}
-
-int style::operator!=(const style &s) const
-{
- return !(*this == s);
-}
-
-class ps_printer : public printer {
- FILE *tempfp;
- ps_output out;
- int res;
- int space_char_index;
- int pages_output;
- int paper_length;
- int equalise_spaces;
- enum { SBUF_SIZE = 256 };
- char sbuf[SBUF_SIZE];
- int sbuf_len;
- int sbuf_start_hpos;
- int sbuf_vpos;
- int sbuf_end_hpos;
- int sbuf_space_width;
- int sbuf_space_count;
- int sbuf_space_diff_count;
- int sbuf_space_code;
- int sbuf_kern;
- style sbuf_style;
- color sbuf_color; // the current PS color
- style output_style;
- int output_hpos;
- int output_vpos;
- int output_draw_point_size;
- int line_thickness;
- int output_line_thickness;
- unsigned char output_space_code;
- enum { MAX_DEFINED_STYLES = 50 };
- style defined_styles[MAX_DEFINED_STYLES];
- int ndefined_styles;
- int next_encoding_index;
- string defs;
- int ndefs;
- resource_manager rm;
- int invis_count;
-
- void flush_sbuf();
- void set_style(const style &);
- void set_space_code(unsigned char c);
- int set_encoding_index(ps_font *);
- void do_exec(char *, const environment *);
- void do_import(char *, const environment *);
- void do_def(char *, const environment *);
- void do_mdef(char *, const environment *);
- void do_file(char *, const environment *);
- void do_invis(char *, const environment *);
- void do_endinvis(char *, const environment *);
- void set_line_thickness_and_color(const environment *);
- void fill_path(const environment *);
- void encode_fonts();
- void define_encoding(const char *, int);
- void reencode_font(ps_font *);
- void set_color(color *c, int fill = 0);
-
-public:
- ps_printer(double);
- ~ps_printer();
- void set_char(int i, font *f, const environment *env, int w, const char *name);
- void draw(int code, int *p, int np, const environment *env);
- void begin_page(int);
- void end_page(int);
- void special(char *arg, const environment *env, char type);
- font *make_font(const char *);
- void end_of_line();
-};
-
-// `pl' is in inches
-ps_printer::ps_printer(double pl)
-: out(0, MAX_LINE_LENGTH),
- pages_output(0),
- sbuf_len(0),
- output_hpos(-1),
- output_vpos(-1),
- line_thickness(-1),
- ndefined_styles(0),
- next_encoding_index(0),
- ndefs(0),
- invis_count(0)
-{
- tempfp = xtmpfile();
- out.set_file(tempfp);
- if (linewidth < 0)
- linewidth = DEFAULT_LINEWIDTH;
- if (font::hor != 1)
- fatal("horizontal resolution must be 1");
- if (font::vert != 1)
- fatal("vertical resolution must be 1");
- if (font::res % (font::sizescale*72) != 0)
- fatal("res must be a multiple of 72*sizescale");
- int r = font::res;
- int point = 0;
- while (r % 10 == 0) {
- r /= 10;
- point++;
- }
- res = r;
- out.set_fixed_point(point);
- space_char_index = font::name_to_index("space");
- if (pl == 0)
- paper_length = font::paperlength;
- else
- paper_length = int(pl * font::res + 0.5);
- if (paper_length == 0)
- paper_length = 11 * font::res;
- equalise_spaces = font::res >= 72000;
-}
-
-int ps_printer::set_encoding_index(ps_font *f)
-{
- if (f->encoding_index >= 0)
- return f->encoding_index;
- for (font_pointer_list *p = font_list; p; p = p->next)
- if (p->p != f) {
- char *encoding = ((ps_font *)p->p)->encoding;
- int encoding_index = ((ps_font *)p->p)->encoding_index;
- if (encoding != 0 && encoding_index >= 0
- && strcmp(f->encoding, encoding) == 0) {
- return f->encoding_index = encoding_index;
- }
- }
- return f->encoding_index = next_encoding_index++;
-}
-
-void ps_printer::set_char(int i, font *f, const environment *env, int w, const char *name)
-{
- if (i == space_char_index || invis_count > 0)
- return;
- unsigned char code = f->get_code(i);
- style sty(f, env->size, env->height, env->slant);
- if (sty.slant != 0) {
- if (sty.slant > 80 || sty.slant < -80) {
- error("silly slant `%1' degrees", sty.slant);
- sty.slant = 0;
- }
- }
- if (sbuf_len > 0) {
- if (sbuf_len < SBUF_SIZE
- && sty == sbuf_style
- && sbuf_vpos == env->vpos
- && sbuf_color == *env->col) {
- if (sbuf_end_hpos == env->hpos) {
- sbuf[sbuf_len++] = code;
- sbuf_end_hpos += w + sbuf_kern;
- return;
- }
- if (sbuf_len == 1 && sbuf_kern == 0) {
- sbuf_kern = env->hpos - sbuf_end_hpos;
- sbuf_end_hpos = env->hpos + sbuf_kern + w;
- sbuf[sbuf_len++] = code;
- return;
- }
- /* If sbuf_end_hpos - sbuf_kern == env->hpos, we are better off
- starting a new string. */
- if (sbuf_len < SBUF_SIZE - 1 && env->hpos >= sbuf_end_hpos
- && (sbuf_kern == 0 || sbuf_end_hpos - sbuf_kern != env->hpos)) {
- if (sbuf_space_code < 0) {
- if (f->contains(space_char_index)) {
- sbuf_space_code = f->get_code(space_char_index);
- sbuf_space_width = env->hpos - sbuf_end_hpos;
- sbuf_end_hpos = env->hpos + w + sbuf_kern;
- sbuf[sbuf_len++] = sbuf_space_code;
- sbuf[sbuf_len++] = code;
- sbuf_space_count++;
- return;
- }
- }
- else {
- int diff = env->hpos - sbuf_end_hpos - sbuf_space_width;
- if (diff == 0 || (equalise_spaces && (diff == 1 || diff == -1))) {
- sbuf_end_hpos = env->hpos + w + sbuf_kern;
- sbuf[sbuf_len++] = sbuf_space_code;
- sbuf[sbuf_len++] = code;
- sbuf_space_count++;
- if (diff == 1)
- sbuf_space_diff_count++;
- else if (diff == -1)
- sbuf_space_diff_count--;
- return;
- }
- }
- }
- }
- flush_sbuf();
- }
- sbuf_len = 1;
- sbuf[0] = code;
- sbuf_end_hpos = env->hpos + w;
- sbuf_start_hpos = env->hpos;
- sbuf_vpos = env->vpos;
- sbuf_style = sty;
- sbuf_space_code = -1;
- sbuf_space_width = 0;
- sbuf_space_count = sbuf_space_diff_count = 0;
- sbuf_kern = 0;
- if (sbuf_color != *env->col)
- set_color(env->col);
-}
-
-static char *make_encoding_name(int encoding_index)
-{
- static char buf[3 + INT_DIGITS + 1];
- sprintf(buf, "ENC%d", encoding_index);
- return buf;
-}
-
-const char *const WS = " \t\n\r";
-
-void ps_printer::define_encoding(const char *encoding, int encoding_index)
-{
- char *vec[256];
- int i;
- for (i = 0; i < 256; i++)
- vec[i] = 0;
- char *path;
- FILE *fp = font::open_file(encoding, &path);
- if (fp == 0)
- fatal("can't open encoding file `%1'", encoding);
- int lineno = 1;
- char buf[256];
- while (fgets(buf, 512, fp) != 0) {
- char *p = buf;
- while (csspace(*p))
- p++;
- if (*p != '#' && *p != '\0' && (p = strtok(buf, WS)) != 0) {
- char *q = strtok(0, WS);
- int n;
- if (q == 0 || sscanf(q, "%d", &n) != 1 || n < 0 || n >= 256)
- fatal_with_file_and_line(path, lineno, "bad second field");
- vec[n] = new char[strlen(p) + 1];
- strcpy(vec[n], p);
- }
- lineno++;
- }
- a_delete path;
- out.put_literal_symbol(make_encoding_name(encoding_index));
- out.put_delimiter('[');
- for (i = 0; i < 256; i++) {
- if (vec[i] == 0)
- out.put_literal_symbol(".notdef");
- else {
- out.put_literal_symbol(vec[i]);
- a_delete vec[i];
- }
- }
- out.put_delimiter(']')
- .put_symbol("def");
-}
-
-void ps_printer::reencode_font(ps_font *f)
-{
- out.put_literal_symbol(f->reencoded_name)
- .put_symbol(make_encoding_name(f->encoding_index))
- .put_literal_symbol(f->get_internal_name())
- .put_symbol("RE");
-}
-
-void ps_printer::encode_fonts()
-{
- if (next_encoding_index == 0)
- return;
- char *done_encoding = new char[next_encoding_index];
- for (int i = 0; i < next_encoding_index; i++)
- done_encoding[i] = 0;
- for (font_pointer_list *f = font_list; f; f = f->next) {
- int encoding_index = ((ps_font *)f->p)->encoding_index;
- if (encoding_index >= 0) {
- assert(encoding_index < next_encoding_index);
- if (!done_encoding[encoding_index]) {
- done_encoding[encoding_index] = 1;
- define_encoding(((ps_font *)f->p)->encoding, encoding_index);
- }
- reencode_font((ps_font *)f->p);
- }
- }
- a_delete done_encoding;
-}
-
-void ps_printer::set_style(const style &sty)
-{
- char buf[1 + INT_DIGITS + 1];
- for (int i = 0; i < ndefined_styles; i++)
- if (sty == defined_styles[i]) {
- sprintf(buf, "F%d", i);
- out.put_symbol(buf);
- return;
- }
- if (ndefined_styles >= MAX_DEFINED_STYLES)
- ndefined_styles = 0;
- sprintf(buf, "F%d", ndefined_styles);
- out.put_literal_symbol(buf);
- const char *psname = sty.f->get_internal_name();
- if (psname == 0)
- fatal("no internalname specified for font `%1'", sty.f->get_name());
- char *encoding = ((ps_font *)sty.f)->encoding;
- if (encoding != 0) {
- char *s = ((ps_font *)sty.f)->reencoded_name;
- if (s == 0) {
- int ei = set_encoding_index((ps_font *)sty.f);
- char *tem = new char[strlen(psname) + 1 + INT_DIGITS + 1];
- sprintf(tem, "%s@%d", psname, ei);
- psname = tem;
- ((ps_font *)sty.f)->reencoded_name = tem;
- }
- else
- psname = s;
- }
- out.put_fix_number((font::res/(72*font::sizescale))*sty.point_size);
- if (sty.height != 0 || sty.slant != 0) {
- int h = sty.height == 0 ? sty.point_size : sty.height;
- h *= font::res/(72*font::sizescale);
- int c = int(h*tan(radians(sty.slant)) + .5);
- out.put_fix_number(c)
- .put_fix_number(h)
- .put_literal_symbol(psname)
- .put_symbol("MF");
- }
- else {
- out.put_literal_symbol(psname)
- .put_symbol("SF");
- }
- defined_styles[ndefined_styles++] = sty;
-}
-
-void ps_printer::set_color(color *col, int fill)
-{
- sbuf_color = *col;
- unsigned int components[4];
- char s[3];
- color_scheme cs = col->get_components(components);
- s[0] = fill ? 'F' : 'C';
- s[2] = 0;
- switch (cs) {
- case DEFAULT: // black
- out.put_symbol("0");
- s[1] = 'g';
- break;
- case RGB:
- out.put_color(Red)
- .put_color(Green)
- .put_color(Blue);
- s[1] = 'r';
- break;
- case CMY:
- col->get_cmyk(&Cyan, &Magenta, &Yellow, &Black);
- // fall through
- case CMYK:
- out.put_color(Cyan)
- .put_color(Magenta)
- .put_color(Yellow)
- .put_color(Black);
- s[1] = 'k';
- break;
- case GRAY:
- out.put_color(Gray);
- s[1] = 'g';
- break;
- }
- out.put_symbol(s);
-}
-
-void ps_printer::set_space_code(unsigned char c)
-{
- out.put_literal_symbol("SC")
- .put_number(c)
- .put_symbol("def");
-}
-
-void ps_printer::end_of_line()
-{
- flush_sbuf();
- // this ensures that we do an absolute motion to the beginning of a line
- output_vpos = output_hpos = -1;
-}
-
-void ps_printer::flush_sbuf()
-{
- enum {
- NONE,
- RELATIVE_H,
- RELATIVE_V,
- RELATIVE_HV,
- ABSOLUTE
- } motion = NONE;
- int space_flag = 0;
- if (sbuf_len == 0)
- return;
- if (output_style != sbuf_style) {
- set_style(sbuf_style);
- output_style = sbuf_style;
- }
- int extra_space = 0;
- if (output_hpos < 0 || output_vpos < 0)
- motion = ABSOLUTE;
- else {
- if (output_hpos != sbuf_start_hpos)
- motion = RELATIVE_H;
- if (output_vpos != sbuf_vpos) {
- if (motion != NONE)
- motion = RELATIVE_HV;
- else
- motion = RELATIVE_V;
- }
- }
- if (sbuf_space_code >= 0) {
- int w = sbuf_style.f->get_width(space_char_index, sbuf_style.point_size);
- if (w + sbuf_kern != sbuf_space_width) {
- if (sbuf_space_code != output_space_code) {
- set_space_code(sbuf_space_code);
- output_space_code = sbuf_space_code;
- }
- space_flag = 1;
- extra_space = sbuf_space_width - w - sbuf_kern;
- if (sbuf_space_diff_count > sbuf_space_count/2)
- extra_space++;
- else if (sbuf_space_diff_count < -(sbuf_space_count/2))
- extra_space--;
- }
- }
- if (space_flag)
- out.put_fix_number(extra_space);
- if (sbuf_kern != 0)
- out.put_fix_number(sbuf_kern);
- out.put_string(sbuf, sbuf_len);
- char command_array[] = {'A', 'B', 'C', 'D',
- 'E', 'F', 'G', 'H',
- 'I', 'J', 'K', 'L',
- 'M', 'N', 'O', 'P',
- 'Q', 'R', 'S', 'T'};
- char sym[2];
- sym[0] = command_array[motion*4 + space_flag + 2*(sbuf_kern != 0)];
- sym[1] = '\0';
- switch (motion) {
- case NONE:
- break;
- case ABSOLUTE:
- out.put_fix_number(sbuf_start_hpos)
- .put_fix_number(sbuf_vpos);
- break;
- case RELATIVE_H:
- out.put_fix_number(sbuf_start_hpos - output_hpos);
- break;
- case RELATIVE_V:
- out.put_fix_number(sbuf_vpos - output_vpos);
- break;
- case RELATIVE_HV:
- out.put_fix_number(sbuf_start_hpos - output_hpos)
- .put_fix_number(sbuf_vpos - output_vpos);
- break;
- default:
- assert(0);
- }
- out.put_symbol(sym);
- output_hpos = sbuf_end_hpos;
- output_vpos = sbuf_vpos;
- sbuf_len = 0;
-}
-
-void ps_printer::set_line_thickness_and_color(const environment *env)
-{
- if (line_thickness < 0) {
- if (output_draw_point_size != env->size) {
- // we ought to check for overflow here
- int lw = ((font::res/(72*font::sizescale))*linewidth*env->size)/1000;
- out.put_fix_number(lw)
- .put_symbol("LW");
- output_draw_point_size = env->size;
- output_line_thickness = -1;
- }
- }
- else {
- if (output_line_thickness != line_thickness) {
- out.put_fix_number(line_thickness)
- .put_symbol("LW");
- output_line_thickness = line_thickness;
- output_draw_point_size = -1;
- }
- }
- if (sbuf_color != *env->col)
- set_color(env->col);
-}
-
-void ps_printer::fill_path(const environment *env)
-{
- if (sbuf_color == *env->fill)
- out.put_symbol("FL");
- else
- set_color(env->fill, 1);
-}
-
-void ps_printer::draw(int code, int *p, int np, const environment *env)
-{
- if (invis_count > 0)
- return;
- flush_sbuf();
- int fill_flag = 0;
- switch (code) {
- case 'C':
- fill_flag = 1;
- // fall through
- case 'c':
- // troff adds an extra argument to C
- if (np != 1 && !(code == 'C' && np == 2)) {
- error("1 argument required for circle");
- break;
- }
- out.put_fix_number(env->hpos + p[0]/2)
- .put_fix_number(env->vpos)
- .put_fix_number(p[0]/2)
- .put_symbol("DC");
- if (fill_flag)
- fill_path(env);
- else {
- set_line_thickness_and_color(env);
- out.put_symbol("ST");
- }
- break;
- case 'l':
- if (np != 2) {
- error("2 arguments required for line");
- break;
- }
- set_line_thickness_and_color(env);
- out.put_fix_number(p[0] + env->hpos)
- .put_fix_number(p[1] + env->vpos)
- .put_fix_number(env->hpos)
- .put_fix_number(env->vpos)
- .put_symbol("DL");
- break;
- case 'E':
- fill_flag = 1;
- // fall through
- case 'e':
- if (np != 2) {
- error("2 arguments required for ellipse");
- break;
- }
- out.put_fix_number(p[0])
- .put_fix_number(p[1])
- .put_fix_number(env->hpos + p[0]/2)
- .put_fix_number(env->vpos)
- .put_symbol("DE");
- if (fill_flag)
- fill_path(env);
- else {
- set_line_thickness_and_color(env);
- out.put_symbol("ST");
- }
- break;
- case 'P':
- fill_flag = 1;
- // fall through
- case 'p':
- {
- if (np & 1) {
- error("even number of arguments required for polygon");
- break;
- }
- if (np == 0) {
- error("no arguments for polygon");
- break;
- }
- out.put_fix_number(env->hpos)
- .put_fix_number(env->vpos)
- .put_symbol("MT");
- for (int i = 0; i < np; i += 2)
- out.put_fix_number(p[i])
- .put_fix_number(p[i+1])
- .put_symbol("RL");
- out.put_symbol("CL");
- if (fill_flag)
- fill_path(env);
- else {
- set_line_thickness_and_color(env);
- out.put_symbol("ST");
- }
- break;
- }
- case '~':
- {
- if (np & 1) {
- error("even number of arguments required for spline");
- break;
- }
- if (np == 0) {
- error("no arguments for spline");
- break;
- }
- out.put_fix_number(env->hpos)
- .put_fix_number(env->vpos)
- .put_symbol("MT");
- out.put_fix_number(p[0]/2)
- .put_fix_number(p[1]/2)
- .put_symbol("RL");
- /* tnum/tden should be between 0 and 1; the closer it is to 1
- the tighter the curve will be to the guiding lines; 2/3
- is the standard value */
- const int tnum = 2;
- const int tden = 3;
- for (int i = 0; i < np - 2; i += 2) {
- out.put_fix_number((p[i]*tnum)/(2*tden))
- .put_fix_number((p[i + 1]*tnum)/(2*tden))
- .put_fix_number(p[i]/2 + (p[i + 2]*(tden - tnum))/(2*tden))
- .put_fix_number(p[i + 1]/2 + (p[i + 3]*(tden - tnum))/(2*tden))
- .put_fix_number((p[i] - p[i]/2) + p[i + 2]/2)
- .put_fix_number((p[i + 1] - p[i + 1]/2) + p[i + 3]/2)
- .put_symbol("RC");
- }
- out.put_fix_number(p[np - 2] - p[np - 2]/2)
- .put_fix_number(p[np - 1] - p[np - 1]/2)
- .put_symbol("RL");
- set_line_thickness_and_color(env);
- out.put_symbol("ST");
- }
- break;
- case 'a':
- {
- if (np != 4) {
- error("4 arguments required for arc");
- break;
- }
- set_line_thickness_and_color(env);
- double c[2];
- if (adjust_arc_center(p, c))
- out.put_fix_number(env->hpos + int(c[0]))
- .put_fix_number(env->vpos + int(c[1]))
- .put_fix_number(int(sqrt(c[0]*c[0] + c[1]*c[1])))
- .put_float(degrees(atan2(-c[1], -c[0])))
- .put_float(degrees(atan2(p[1] + p[3] - c[1], p[0] + p[2] - c[0])))
- .put_symbol("DA");
- else
- out.put_fix_number(p[0] + p[2] + env->hpos)
- .put_fix_number(p[1] + p[3] + env->vpos)
- .put_fix_number(env->hpos)
- .put_fix_number(env->vpos)
- .put_symbol("DL");
- }
- break;
- case 't':
- if (np == 0)
- line_thickness = -1;
- else {
- // troff gratuitously adds an extra 0
- if (np != 1 && np != 2) {
- error("0 or 1 argument required for thickness");
- break;
- }
- line_thickness = p[0];
- }
- break;
- default:
- error("unrecognised drawing command `%1'", char(code));
- break;
- }
- output_hpos = output_vpos = -1;
-}
-
-void ps_printer::begin_page(int n)
-{
- out.begin_comment("Page:")
- .comment_arg(i_to_a(n));
- out.comment_arg(i_to_a(++pages_output))
- .end_comment();
- output_style.f = 0;
- output_space_code = 32;
- output_draw_point_size = -1;
- output_line_thickness = -1;
- output_hpos = output_vpos = -1;
- ndefined_styles = 0;
- out.simple_comment("BeginPageSetup")
- .put_symbol("BP")
- .simple_comment("EndPageSetup");
- if (sbuf_color != default_color)
- set_color(&sbuf_color);
-}
-
-void ps_printer::end_page(int)
-{
- flush_sbuf();
- set_color(&default_color);
- out.put_symbol("EP");
- if (invis_count != 0) {
- error("missing `endinvis' command");
- invis_count = 0;
- }
-}
-
-font *ps_printer::make_font(const char *nm)
-{
- return ps_font::load_ps_font(nm);
-}
-
-ps_printer::~ps_printer()
-{
- out.simple_comment("Trailer")
- .put_symbol("end")
- .simple_comment("EOF");
- if (fseek(tempfp, 0L, 0) < 0)
- fatal("fseek on temporary file failed");
- fputs("%!PS-Adobe-", stdout);
- fputs((broken_flags & USE_PS_ADOBE_2_0) ? "2.0" : "3.0", stdout);
- putchar('\n');
- out.set_file(stdout);
- {
- out.begin_comment("Creator:")
- .comment_arg("groff")
- .comment_arg("version")
- .comment_arg(Version_string)
- .end_comment();
- }
- {
- fputs("%%CreationDate: ", out.get_file());
-#ifdef LONG_FOR_TIME_T
- long
-#else
- time_t
-#endif
- t = time(0);
- fputs(ctime(&t), out.get_file());
- }
- for (font_pointer_list *f = font_list; f; f = f->next) {
- ps_font *psf = (ps_font *)(f->p);
- rm.need_font(psf->get_internal_name());
- }
- rm.print_header_comments(out);
- out.begin_comment("Pages:")
- .comment_arg(i_to_a(pages_output))
- .end_comment();
- out.begin_comment("PageOrder:")
- .comment_arg("Ascend")
- .end_comment();
-#if 0
- fprintf(out.get_file(), "%%%%DocumentMedia: () %g %g 0 () ()\n",
- font::paperwidth*72.0/font::res,
- paper_length*72.0/font::res);
-#endif
- out.begin_comment("Orientation:")
- .comment_arg(landscape_flag ? "Landscape" : "Portrait")
- .end_comment();
- if (ncopies != 1) {
- out.end_line();
- fprintf(out.get_file(), "%%%%Requirements: numcopies(%d)\n", ncopies);
- }
- out.simple_comment("EndComments");
- out.simple_comment("BeginProlog");
- rm.output_prolog(out);
- if (!(broken_flags & NO_SETUP_SECTION)) {
- out.simple_comment("EndProlog");
- out.simple_comment("BeginSetup");
- }
- rm.document_setup(out);
- out.put_symbol(dict_name)
- .put_symbol("begin");
- if (ndefs > 0)
- ndefs += DEFS_DICT_SPARE;
- out.put_literal_symbol(defs_dict_name)
- .put_number(ndefs + 1)
- .put_symbol("dict")
- .put_symbol("def");
- out.put_symbol(defs_dict_name)
- .put_symbol("begin");
- out.put_literal_symbol("u")
- .put_delimiter('{')
- .put_fix_number(1)
- .put_symbol("mul")
- .put_delimiter('}')
- .put_symbol("bind")
- .put_symbol("def");
- defs += '\0';
- out.special(defs.contents());
- out.put_symbol("end");
- if (ncopies != 1)
- out.put_literal_symbol("#copies")
- .put_number(ncopies)
- .put_symbol("def");
- out.put_literal_symbol("RES")
- .put_number(res)
- .put_symbol("def");
- out.put_literal_symbol("PL");
- if (guess_flag)
- out.put_symbol("PLG");
- else
- out.put_fix_number(paper_length);
- out.put_symbol("def");
- out.put_literal_symbol("LS")
- .put_symbol(landscape_flag ? "true" : "false")
- .put_symbol("def");
- if (manual_feed_flag) {
- out.begin_comment("BeginFeature:")
- .comment_arg("*ManualFeed")
- .comment_arg("True")
- .end_comment()
- .put_symbol("MANUAL")
- .simple_comment("EndFeature");
- }
- encode_fonts();
- out.simple_comment((broken_flags & NO_SETUP_SECTION)
- ? "EndProlog"
- : "EndSetup");
- out.end_line();
- out.copy_file(tempfp);
- fclose(tempfp);
-}
-
-void ps_printer::special(char *arg, const environment *env, char type)
-{
- if (type != 'p')
- return;
- typedef void (ps_printer::*SPECIAL_PROCP)(char *, const environment *);
- static struct {
- const char *name;
- SPECIAL_PROCP proc;
- } proc_table[] = {
- { "exec", &ps_printer::do_exec },
- { "def", &ps_printer::do_def },
- { "mdef", &ps_printer::do_mdef },
- { "import", &ps_printer::do_import },
- { "file", &ps_printer::do_file },
- { "invis", &ps_printer::do_invis },
- { "endinvis", &ps_printer::do_endinvis },
- };
- char *p;
- for (p = arg; *p == ' ' || *p == '\n'; p++)
- ;
- char *tag = p;
- for (; *p != '\0' && *p != ':' && *p != ' ' && *p != '\n'; p++)
- ;
- if (*p == '\0' || strncmp(tag, "ps", p - tag) != 0) {
- error("X command without `ps:' tag ignored");
- return;
- }
- p++;
- for (; *p == ' ' || *p == '\n'; p++)
- ;
- char *command = p;
- for (; *p != '\0' && *p != ' ' && *p != '\n'; p++)
- ;
- if (*command == '\0') {
- error("empty X command ignored");
- return;
- }
- for (unsigned int i = 0; i < sizeof(proc_table)/sizeof(proc_table[0]); i++)
- if (strncmp(command, proc_table[i].name, p - command) == 0) {
- (this->*(proc_table[i].proc))(p, env);
- return;
- }
- error("X command `%1' not recognised", command);
-}
-
-// A conforming PostScript document must not have lines longer
-// than 255 characters (excluding line termination characters).
-
-static int check_line_lengths(const char *p)
-{
- for (;;) {
- const char *end = strchr(p, '\n');
- if (end == 0)
- end = strchr(p, '\0');
- if (end - p > 255)
- return 0;
- if (*end == '\0')
- break;
- p = end + 1;
- }
- return 1;
-}
-
-void ps_printer::do_exec(char *arg, const environment *env)
-{
- flush_sbuf();
- while (csspace(*arg))
- arg++;
- if (*arg == '\0') {
- error("missing argument to X exec command");
- return;
- }
- if (!check_line_lengths(arg)) {
- error("lines in X exec command must not be more than 255 characters long");
- return;
- }
- out.put_fix_number(env->hpos)
- .put_fix_number(env->vpos)
- .put_symbol("EBEGIN")
- .special(arg)
- .put_symbol("EEND");
- output_hpos = output_vpos = -1;
- output_style.f = 0;
- output_draw_point_size = -1;
- output_line_thickness = -1;
- ndefined_styles = 0;
- if (!ndefs)
- ndefs = 1;
-}
-
-void ps_printer::do_file(char *arg, const environment *env)
-{
- flush_sbuf();
- while (csspace(*arg))
- arg++;
- if (*arg == '\0') {
- error("missing argument to X file command");
- return;
- }
- const char *filename = arg;
- do {
- ++arg;
- } while (*arg != '\0' && *arg != ' ' && *arg != '\n');
- out.put_fix_number(env->hpos)
- .put_fix_number(env->vpos)
- .put_symbol("EBEGIN");
- rm.import_file(filename, out);
- out.put_symbol("EEND");
- output_hpos = output_vpos = -1;
- output_style.f = 0;
- output_draw_point_size = -1;
- output_line_thickness = -1;
- ndefined_styles = 0;
- if (!ndefs)
- ndefs = 1;
-}
-
-void ps_printer::do_def(char *arg, const environment *)
-{
- flush_sbuf();
- while (csspace(*arg))
- arg++;
- if (!check_line_lengths(arg)) {
- error("lines in X def command must not be more than 255 characters long");
- return;
- }
- defs += arg;
- if (*arg != '\0' && strchr(arg, '\0')[-1] != '\n')
- defs += '\n';
- ndefs++;
-}
-
-// Like def, but the first argument says how many definitions it contains.
-
-void ps_printer::do_mdef(char *arg, const environment *)
-{
- flush_sbuf();
- char *p;
- int n = (int)strtol(arg, &p, 10);
- if (n == 0 && p == arg) {
- error("first argument to X mdef must be an integer");
- return;
- }
- if (n < 0) {
- error("out of range argument `%1' to X mdef command", int(n));
- return;
- }
- arg = p;
- while (csspace(*arg))
- arg++;
- if (!check_line_lengths(arg)) {
- error("lines in X mdef command must not be more than 255 characters long");
- return;
- }
- defs += arg;
- if (*arg != '\0' && strchr(arg, '\0')[-1] != '\n')
- defs += '\n';
- ndefs += n;
-}
-
-void ps_printer::do_import(char *arg, const environment *env)
-{
- flush_sbuf();
- while (*arg == ' ' || *arg == '\n')
- arg++;
- char *p;
- for (p = arg; *p != '\0' && *p != ' ' && *p != '\n'; p++)
- ;
- if (*p != '\0')
- *p++ = '\0';
- int parms[6];
- int nparms = 0;
- while (nparms < 6) {
- char *end;
- long n = strtol(p, &end, 10);
- if (n == 0 && end == p)
- break;
- parms[nparms++] = int(n);
- p = end;
- }
- if (csalpha(*p) && (p[1] == '\0' || p[1] == ' ' || p[1] == '\n')) {
- error("scaling indicators not allowed in arguments for X import command");
- return;
- }
- while (*p == ' ' || *p == '\n')
- p++;
- if (nparms < 5) {
- if (*p == '\0')
- error("too few arguments for X import command");
- else
- error("invalid argument `%1' for X import command", p);
- return;
- }
- if (*p != '\0') {
- error("superflous argument `%1' for X import command", p);
- return;
- }
- int llx = parms[0];
- int lly = parms[1];
- int urx = parms[2];
- int ury = parms[3];
- int desired_width = parms[4];
- int desired_height = parms[5];
- if (desired_width <= 0) {
- error("bad width argument `%1' for X import command: must be > 0",
- desired_width);
- return;
- }
- if (nparms == 6 && desired_height <= 0) {
- error("bad height argument `%1' for X import command: must be > 0",
- desired_height);
- return;
- }
- if (llx == urx) {
- error("llx and urx arguments for X import command must not be equal");
- return;
- }
- if (lly == ury) {
- error("lly and ury arguments for X import command must not be equal");
- return;
- }
- if (nparms == 5) {
- int old_wid = urx - llx;
- int old_ht = ury - lly;
- if (old_wid < 0)
- old_wid = -old_wid;
- if (old_ht < 0)
- old_ht = -old_ht;
- desired_height = int(desired_width*(double(old_ht)/double(old_wid)) + .5);
- }
- if (env->vpos - desired_height < 0)
- warning("top of imported graphic is above the top of the page");
- out.put_number(llx)
- .put_number(lly)
- .put_fix_number(desired_width)
- .put_number(urx - llx)
- .put_fix_number(-desired_height)
- .put_number(ury - lly)
- .put_fix_number(env->hpos)
- .put_fix_number(env->vpos)
- .put_symbol("PBEGIN");
- rm.import_file(arg, out);
- // do this here just in case application defines PEND
- out.put_symbol("end");
- out.put_symbol("PEND");
-}
-
-void ps_printer::do_invis(char *, const environment *)
-{
- invis_count++;
-}
-
-void ps_printer::do_endinvis(char *, const environment *)
-{
- if (invis_count == 0)
- error("unbalanced `endinvis' command");
- else
- --invis_count;
-}
-
-printer *make_printer()
-{
- return new ps_printer(user_paper_length);
-}
-
-static void usage(FILE *stream);
-
-int main(int argc, char **argv)
-{
- program_name = argv[0];
- string env;
- static char stderr_buf[BUFSIZ];
- setbuf(stderr, stderr_buf);
- int c;
- static const struct option long_options[] = {
- { "help", no_argument, 0, CHAR_MAX + 1 },
- { "version", no_argument, 0, 'v' },
- { NULL, 0, 0, 0 }
- };
- while ((c = getopt_long(argc, argv, "b:c:F:glmp:P:vw:", long_options, NULL))
- != EOF)
- switch(c) {
- case 'b':
- // XXX check this
- broken_flags = atoi(optarg);
- bflag = 1;
- break;
- case 'c':
- if (sscanf(optarg, "%d", &ncopies) != 1 || ncopies <= 0) {
- error("bad number of copies `%s'", optarg);
- ncopies = 1;
- }
- break;
- case 'F':
- font::command_line_font_dir(optarg);
- break;
- case 'g':
- guess_flag = 1;
- break;
- case 'l':
- landscape_flag = 1;
- break;
- case 'm':
- manual_feed_flag = 1;
- break;
- case 'p':
- if (!font::scan_papersize(optarg, 0, &user_paper_length, 0))
- error("invalid custom paper size `%1' ignored", optarg);
- break;
- case 'P':
- env = "GROPS_PROLOGUE";
- env += '=';
- env += optarg;
- env += '\0';
- if (putenv(strsave(env.contents())))
- fatal("putenv failed");
- break;
- case 'v':
- printf("GNU grops (groff) version %s\n", Version_string);
- exit(0);
- break;
- case 'w':
- if (sscanf(optarg, "%d", &linewidth) != 1 || linewidth < 0) {
- error("bad linewidth `%1'", optarg);
- linewidth = -1;
- }
- break;
- case CHAR_MAX + 1: // --help
- usage(stdout);
- exit(0);
- break;
- case '?':
- usage(stderr);
- exit(1);
- break;
- default:
- assert(0);
- }
- font::set_unknown_desc_command_handler(handle_unknown_desc_command);
-#ifdef SET_BINARY
- SET_BINARY(fileno(stdout));
-#endif
- if (optind >= argc)
- do_file("-");
- else {
- for (int i = optind; i < argc; i++)
- do_file(argv[i]);
- }
- delete pr;
- return 0;
-}
-
-static void usage(FILE *stream)
-{
- fprintf(stream,
- "usage: %s [-glmv] [-b n] [-c n] [-w n] [-P prologue] [-F dir] [files ...]\n",
- program_name);
-}
diff --git a/contrib/groff/src/devices/grops/psrm.cc b/contrib/groff/src/devices/grops/psrm.cc
deleted file mode 100644
index f2177da..0000000
--- a/contrib/groff/src/devices/grops/psrm.cc
+++ /dev/null
@@ -1,1147 +0,0 @@
-// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001, 2002
- Free Software Foundation, Inc.
- Written by James Clark (jjc@jclark.com)
-
-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 2, 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 groff; see the file COPYING. If not, write to the Free Software
-Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#include "driver.h"
-#include "stringclass.h"
-#include "cset.h"
-
-#include "ps.h"
-
-#ifdef NEED_DECLARATION_PUTENV
-extern "C" {
- int putenv(const char *);
-}
-#endif /* NEED_DECLARATION_PUTENV */
-
-#define GROPS_PROLOGUE "prologue"
-
-static void print_ps_string(const string &s, FILE *outfp);
-
-cset white_space("\n\r \t");
-string an_empty_string;
-
-const char *extension_table[] = {
- "DPS",
- "CMYK",
- "Composite",
- "FileSystem",
-};
-
-const int NEXTENSIONS = sizeof(extension_table)/sizeof(extension_table[0]);
-
-const char *resource_table[] = {
- "font",
- "procset",
- "file",
- "encoding",
- "form",
- "pattern",
-};
-
-const int NRESOURCES = sizeof(resource_table)/sizeof(resource_table[0]);
-
-static int read_uint_arg(const char **pp, unsigned *res)
-{
- while (white_space(**pp))
- *pp += 1;
- if (**pp == '\0') {
- error("missing argument");
- return 0;
- }
- const char *start = *pp;
- // XXX use strtoul
- long n = strtol(start, (char **)pp, 10);
- if (n == 0 && *pp == start) {
- error("not an integer");
- return 0;
- }
- if (n < 0) {
- error("argument must not be negative");
- return 0;
- }
- *res = unsigned(n);
- return 1;
-}
-
-struct resource {
- resource *next;
- resource_type type;
- string name;
- enum { NEEDED = 01, SUPPLIED = 02, FONT_NEEDED = 04, BUSY = 010 };
- unsigned flags;
- string version;
- unsigned revision;
- char *filename;
- int rank;
- resource(resource_type, string &, string & = an_empty_string, unsigned = 0);
- ~resource();
- void print_type_and_name(FILE *outfp);
-};
-
-resource::resource(resource_type t, string &n, string &v, unsigned r)
-: next(0), type(t), flags(0), revision(r), filename(0), rank(-1)
-{
- name.move(n);
- version.move(v);
- if (type == RESOURCE_FILE) {
- if (name.search('\0') >= 0)
- error("filename contains a character with code 0");
- filename = name.extract();
- }
-}
-
-resource::~resource()
-{
- a_delete filename;
-}
-
-void resource::print_type_and_name(FILE *outfp)
-{
- fputs(resource_table[type], outfp);
- putc(' ', outfp);
- print_ps_string(name, outfp);
- if (type == RESOURCE_PROCSET) {
- putc(' ', outfp);
- print_ps_string(version, outfp);
- fprintf(outfp, " %u", revision);
- }
-}
-
-resource_manager::resource_manager()
-: extensions(0), language_level(0), resource_list(0)
-{
- read_download_file();
- string procset_name("grops");
- extern const char *version_string;
- extern const char *revision_string;
- unsigned revision_uint;
- if ( !read_uint_arg( &revision_string, &revision_uint) )
- revision_uint = 0;
- string procset_version(version_string);
- procset_resource = lookup_resource(RESOURCE_PROCSET, procset_name,
- procset_version, revision_uint);
- procset_resource->flags |= resource::SUPPLIED;
-}
-
-resource_manager::~resource_manager()
-{
- while (resource_list) {
- resource *tem = resource_list;
- resource_list = resource_list->next;
- delete tem;
- }
-}
-
-resource *resource_manager::lookup_resource(resource_type type,
- string &name,
- string &version,
- unsigned revision)
-{
- resource *r;
- for (r = resource_list; r; r = r->next)
- if (r->type == type
- && r->name == name
- && r->version == version
- && r->revision == revision)
- return r;
- r = new resource(type, name, version, revision);
- r->next = resource_list;
- resource_list = r;
- return r;
-}
-
-// Just a specialized version of lookup_resource().
-
-resource *resource_manager::lookup_font(const char *name)
-{
- resource *r;
- for (r = resource_list; r; r = r->next)
- if (r->type == RESOURCE_FONT
- && strlen(name) == (size_t)r->name.length()
- && memcmp(name, r->name.contents(), r->name.length()) == 0)
- return r;
- string s(name);
- r = new resource(RESOURCE_FONT, s);
- r->next = resource_list;
- resource_list = r;
- return r;
-}
-
-void resource_manager::need_font(const char *name)
-{
- lookup_font(name)->flags |= resource::FONT_NEEDED;
-}
-
-typedef resource *Presource; // Work around g++ bug.
-
-void resource_manager::document_setup(ps_output &out)
-{
- int nranks = 0;
- resource *r;
- for (r = resource_list; r; r = r->next)
- if (r->rank >= nranks)
- nranks = r->rank + 1;
- if (nranks > 0) {
- // Sort resource_list in reverse order of rank.
- Presource *head = new Presource[nranks + 1];
- Presource **tail = new Presource *[nranks + 1];
- int i;
- for (i = 0; i < nranks + 1; i++) {
- head[i] = 0;
- tail[i] = &head[i];
- }
- for (r = resource_list; r; r = r->next) {
- i = r->rank < 0 ? 0 : r->rank + 1;
- *tail[i] = r;
- tail[i] = &(*tail[i])->next;
- }
- resource_list = 0;
- for (i = 0; i < nranks + 1; i++)
- if (head[i]) {
- *tail[i] = resource_list;
- resource_list = head[i];
- }
- a_delete head;
- a_delete tail;
- // check it
- for (r = resource_list; r; r = r->next)
- if (r->next)
- assert(r->rank >= r->next->rank);
- for (r = resource_list; r; r = r->next)
- if (r->type == RESOURCE_FONT && r->rank >= 0)
- supply_resource(r, -1, out.get_file());
- }
-}
-
-void resource_manager::print_resources_comment(unsigned flag, FILE *outfp)
-{
- int continued = 0;
- for (resource *r = resource_list; r; r = r->next)
- if (r->flags & flag) {
- if (continued)
- fputs("%%+ ", outfp);
- else {
- fputs(flag == resource::NEEDED
- ? "%%DocumentNeededResources: "
- : "%%DocumentSuppliedResources: ",
- outfp);
- continued = 1;
- }
- r->print_type_and_name(outfp);
- putc('\n', outfp);
- }
-}
-
-void resource_manager::print_header_comments(ps_output &out)
-{
- for (resource *r = resource_list; r; r = r->next)
- if (r->type == RESOURCE_FONT && (r->flags & resource::FONT_NEEDED))
- supply_resource(r, 0, 0);
- print_resources_comment(resource::NEEDED, out.get_file());
- print_resources_comment(resource::SUPPLIED, out.get_file());
- print_language_level_comment(out.get_file());
- print_extensions_comment(out.get_file());
-}
-
-void resource_manager::output_prolog(ps_output &out)
-{
- FILE *outfp = out.get_file();
- out.end_line();
- char *path;
- if (!getenv("GROPS_PROLOGUE")) {
- string e = "GROPS_PROLOGUE";
- e += '=';
- e += GROPS_PROLOGUE;
- e += '\0';
- if (putenv(strsave(e.contents())))
- fatal("putenv failed");
- }
- char *prologue = getenv("GROPS_PROLOGUE");
- FILE *fp = font::open_file(prologue, &path);
- if (!fp)
- fatal("can't find `%1'", prologue);
- fputs("%%BeginResource: ", outfp);
- procset_resource->print_type_and_name(outfp);
- putc('\n', outfp);
- process_file(-1, fp, path, outfp);
- fclose(fp);
- a_delete path;
- fputs("%%EndResource\n", outfp);
-}
-
-void resource_manager::import_file(const char *filename, ps_output &out)
-{
- out.end_line();
- string name(filename);
- resource *r = lookup_resource(RESOURCE_FILE, name);
- supply_resource(r, -1, out.get_file(), 1);
-}
-
-void resource_manager::supply_resource(resource *r, int rank, FILE *outfp,
- int is_document)
-{
- if (r->flags & resource::BUSY) {
- r->name += '\0';
- fatal("loop detected in dependency graph for %1 `%2'",
- resource_table[r->type],
- r->name.contents());
- }
- r->flags |= resource::BUSY;
- if (rank > r->rank)
- r->rank = rank;
- char *path;
- FILE *fp = 0;
- if (r->filename != 0) {
- if (r->type == RESOURCE_FONT) {
- fp = font::open_file(r->filename, &path);
- if (!fp) {
- error("can't find `%1'", r->filename);
- a_delete r->filename;
- r->filename = 0;
- }
- }
- else {
- errno = 0;
- fp = fopen(r->filename, "r");
- if (!fp) {
- error("can't open `%1': %2", r->filename, strerror(errno));
- a_delete r->filename;
- r->filename = 0;
- }
- else
- path = r->filename;
- }
- }
- if (fp) {
- if (outfp) {
- if (r->type == RESOURCE_FILE && is_document) {
- fputs("%%BeginDocument: ", outfp);
- print_ps_string(r->name, outfp);
- putc('\n', outfp);
- }
- else {
- fputs("%%BeginResource: ", outfp);
- r->print_type_and_name(outfp);
- putc('\n', outfp);
- }
- }
- process_file(rank, fp, path, outfp);
- fclose(fp);
- if (r->type == RESOURCE_FONT)
- a_delete path;
- if (outfp) {
- if (r->type == RESOURCE_FILE && is_document)
- fputs("%%EndDocument\n", outfp);
- else
- fputs("%%EndResource\n", outfp);
- }
- r->flags |= resource::SUPPLIED;
- }
- else {
- if (outfp) {
- if (r->type == RESOURCE_FILE && is_document) {
- fputs("%%IncludeDocument: ", outfp);
- print_ps_string(r->name, outfp);
- putc('\n', outfp);
- }
- else {
- fputs("%%IncludeResource: ", outfp);
- r->print_type_and_name(outfp);
- putc('\n', outfp);
- }
- }
- r->flags |= resource::NEEDED;
- }
- r->flags &= ~resource::BUSY;
-}
-
-
-#define PS_LINE_MAX 255
-#define PS_MAGIC "%!PS-Adobe-"
-
-static int ps_get_line(char *buf, FILE *fp)
-{
- int c = getc(fp);
- if (c == EOF) {
- buf[0] = '\0';
- return 0;
- }
- current_lineno++;
- int i = 0;
- int err = 0;
- while (c != '\r' && c != '\n' && c != EOF) {
- if ((c < 0x1b && !white_space(c)) || c == 0x7f)
- error("invalid input character code %1", int(c));
- else if (i < PS_LINE_MAX)
- buf[i++] = c;
- else if (!err) {
- err = 1;
- error("PostScript file non-conforming "
- "because length of line exceeds 255");
- }
- c = getc(fp);
- }
- buf[i++] = '\n';
- buf[i] = '\0';
- if (c == '\r') {
- c = getc(fp);
- if (c != EOF && c != '\n')
- ungetc(c, fp);
- }
- return 1;
-}
-
-static int read_text_arg(const char **pp, string &res)
-{
- res.clear();
- while (white_space(**pp))
- *pp += 1;
- if (**pp == '\0') {
- error("missing argument");
- return 0;
- }
- if (**pp != '(') {
- for (; **pp != '\0' && !white_space(**pp); *pp += 1)
- res += **pp;
- return 1;
- }
- *pp += 1;
- res.clear();
- int level = 0;
- for (;;) {
- if (**pp == '\0' || **pp == '\r' || **pp == '\n') {
- error("missing ')'");
- return 0;
- }
- if (**pp == ')') {
- if (level == 0) {
- *pp += 1;
- break;
- }
- res += **pp;
- level--;
- }
- else if (**pp == '(') {
- level++;
- res += **pp;
- }
- else if (**pp == '\\') {
- *pp += 1;
- switch (**pp) {
- case 'n':
- res += '\n';
- break;
- case 'r':
- res += '\n';
- break;
- case 't':
- res += '\t';
- break;
- case 'b':
- res += '\b';
- break;
- case 'f':
- res += '\f';
- break;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- {
- int val = **pp - '0';
- if ((*pp)[1] >= '0' && (*pp)[1] <= '7') {
- *pp += 1;
- val = val*8 + (**pp - '0');
- if ((*pp)[1] >= '0' && (*pp)[1] <= '7') {
- *pp += 1;
- val = val*8 + (**pp - '0');
- }
- }
- }
- break;
- default:
- res += **pp;
- break;
- }
- }
- else
- res += **pp;
- *pp += 1;
- }
- return 1;
-}
-
-resource *resource_manager::read_file_arg(const char **ptr)
-{
- string arg;
- if (!read_text_arg(ptr, arg))
- return 0;
- return lookup_resource(RESOURCE_FILE, arg);
-}
-
-resource *resource_manager::read_font_arg(const char **ptr)
-{
- string arg;
- if (!read_text_arg(ptr, arg))
- return 0;
- return lookup_resource(RESOURCE_FONT, arg);
-}
-
-resource *resource_manager::read_procset_arg(const char **ptr)
-{
- string arg;
- if (!read_text_arg(ptr, arg))
- return 0;
- string version;
- if (!read_text_arg(ptr, version))
- return 0;
- unsigned revision;
- if (!read_uint_arg(ptr, &revision))
- return 0;
- return lookup_resource(RESOURCE_PROCSET, arg, version, revision);
-}
-
-resource *resource_manager::read_resource_arg(const char **ptr)
-{
- while (white_space(**ptr))
- *ptr += 1;
- const char *name = *ptr;
- while (**ptr != '\0' && !white_space(**ptr))
- *ptr += 1;
- if (name == *ptr) {
- error("missing resource type");
- return 0;
- }
- int ri;
- for (ri = 0; ri < NRESOURCES; ri++)
- if (strlen(resource_table[ri]) == size_t(*ptr - name)
- && memcmp(resource_table[ri], name, *ptr - name) == 0)
- break;
- if (ri >= NRESOURCES) {
- error("unknown resource type");
- return 0;
- }
- if (ri == RESOURCE_PROCSET)
- return read_procset_arg(ptr);
- string arg;
- if (!read_text_arg(ptr, arg))
- return 0;
- return lookup_resource(resource_type(ri), arg);
-}
-
-static const char *matches_comment(const char *buf, const char *comment)
-{
- if (buf[0] != '%' || buf[1] != '%')
- return 0;
- for (buf += 2; *comment; comment++, buf++)
- if (*buf != *comment)
- return 0;
- if (comment[-1] == ':')
- return buf;
- if (*buf == '\0' || white_space(*buf))
- return buf;
- return 0;
-}
-
-// Return 1 if the line should be copied out.
-
-int resource_manager::do_begin_resource(const char *ptr, int, FILE *,
- FILE *)
-{
- resource *r = read_resource_arg(&ptr);
- if (r)
- r->flags |= resource::SUPPLIED;
- return 1;
-}
-
-int resource_manager::do_include_resource(const char *ptr, int rank, FILE *,
- FILE *outfp)
-{
- resource *r = read_resource_arg(&ptr);
- if (r) {
- if (r->type == RESOURCE_FONT) {
- if (rank >= 0)
- supply_resource(r, rank + 1, outfp);
- else
- r->flags |= resource::FONT_NEEDED;
- }
- else
- supply_resource(r, rank, outfp);
- }
- return 0;
-}
-
-int resource_manager::do_begin_document(const char *ptr, int, FILE *,
- FILE *)
-{
- resource *r = read_file_arg(&ptr);
- if (r)
- r->flags |= resource::SUPPLIED;
- return 1;
-}
-
-int resource_manager::do_include_document(const char *ptr, int rank, FILE *,
- FILE *outfp)
-{
- resource *r = read_file_arg(&ptr);
- if (r)
- supply_resource(r, rank, outfp, 1);
- return 0;
-}
-
-int resource_manager::do_begin_procset(const char *ptr, int, FILE *,
- FILE *outfp)
-{
- resource *r = read_procset_arg(&ptr);
- if (r) {
- r->flags |= resource::SUPPLIED;
- if (outfp) {
- fputs("%%BeginResource: ", outfp);
- r->print_type_and_name(outfp);
- putc('\n', outfp);
- }
- }
- return 0;
-}
-
-int resource_manager::do_include_procset(const char *ptr, int rank, FILE *,
- FILE *outfp)
-{
- resource *r = read_procset_arg(&ptr);
- if (r)
- supply_resource(r, rank, outfp);
- return 0;
-}
-
-int resource_manager::do_begin_file(const char *ptr, int, FILE *,
- FILE *outfp)
-{
- resource *r = read_file_arg(&ptr);
- if (r) {
- r->flags |= resource::SUPPLIED;
- if (outfp) {
- fputs("%%BeginResource: ", outfp);
- r->print_type_and_name(outfp);
- putc('\n', outfp);
- }
- }
- return 0;
-}
-
-int resource_manager::do_include_file(const char *ptr, int rank, FILE *,
- FILE *outfp)
-{
- resource *r = read_file_arg(&ptr);
- if (r)
- supply_resource(r, rank, outfp);
- return 0;
-}
-
-int resource_manager::do_begin_font(const char *ptr, int, FILE *,
- FILE *outfp)
-{
- resource *r = read_font_arg(&ptr);
- if (r) {
- r->flags |= resource::SUPPLIED;
- if (outfp) {
- fputs("%%BeginResource: ", outfp);
- r->print_type_and_name(outfp);
- putc('\n', outfp);
- }
- }
- return 0;
-}
-
-int resource_manager::do_include_font(const char *ptr, int rank, FILE *,
- FILE *outfp)
-{
- resource *r = read_font_arg(&ptr);
- if (r) {
- if (rank >= 0)
- supply_resource(r, rank + 1, outfp);
- else
- r->flags |= resource::FONT_NEEDED;
- }
- return 0;
-}
-
-int resource_manager::change_to_end_resource(const char *, int, FILE *,
- FILE *outfp)
-{
- if (outfp)
- fputs("%%EndResource\n", outfp);
- return 0;
-}
-
-int resource_manager::do_begin_preview(const char *, int, FILE *fp, FILE *)
-{
- char buf[PS_LINE_MAX + 2];
- do {
- if (!ps_get_line(buf, fp)) {
- error("end of file in preview section");
- break;
- }
- } while (!matches_comment(buf, "EndPreview"));
- return 0;
-}
-
-int read_one_of(const char **ptr, const char **s, int n)
-{
- while (white_space(**ptr))
- *ptr += 1;
- if (**ptr == '\0')
- return -1;
- const char *start = *ptr;
- do {
- ++(*ptr);
- } while (**ptr != '\0' && !white_space(**ptr));
- for (int i = 0; i < n; i++)
- if (strlen(s[i]) == size_t(*ptr - start)
- && memcmp(s[i], start, *ptr - start) == 0)
- return i;
- return -1;
-}
-
-void skip_possible_newline(const char *ptr, FILE *fp, FILE *outfp)
-{
- int c = getc(fp);
- if (c == '\r') {
- current_lineno++;
- if (outfp)
- putc(c, outfp);
- int cc = getc(fp);
- if (cc != '\n') {
- if (cc != EOF)
- ungetc(cc, fp);
- }
- else {
- if (outfp)
- putc(cc, outfp);
- }
- }
- else if (c == '\n') {
- current_lineno++;
- if (outfp)
- putc(c, outfp);
- }
- else if (c != EOF)
- ungetc(c, fp);
-}
-
-int resource_manager::do_begin_data(const char *ptr, int, FILE *fp,
- FILE *outfp)
-{
- while (white_space(*ptr))
- ptr++;
- const char *start = ptr;
- unsigned numberof;
- if (!read_uint_arg(&ptr, &numberof))
- return 0;
- static const char *types[] = { "Binary", "Hex", "ASCII" };
- const int Binary = 0;
- int type = 0;
- static const char *units[] = { "Bytes", "Lines" };
- const int Bytes = 0;
- int unit = Bytes;
- while (white_space(*ptr))
- ptr++;
- if (*ptr != '\0') {
- type = read_one_of(&ptr, types, 3);
- if (type < 0) {
- error("bad data type");
- return 0;
- }
- while (white_space(*ptr))
- ptr++;
- if (*ptr != '\0') {
- unit = read_one_of(&ptr, units, 2);
- if (unit < 0) {
- error("expected `Bytes' or `Lines'");
- return 0;
- }
- }
- }
- if (type != Binary)
- return 1;
- if (outfp) {
- fputs("%%BeginData: ", outfp);
- fputs(start, outfp);
- }
- if (numberof > 0) {
- unsigned bytecount = 0;
- unsigned linecount = 0;
- do {
- int c = getc(fp);
- if (c == EOF) {
- error("end of file within data section");
- return 0;
- }
- if (outfp)
- putc(c, outfp);
- bytecount++;
- if (c == '\r') {
- int cc = getc(fp);
- if (cc != '\n') {
- linecount++;
- current_lineno++;
- }
- if (cc != EOF)
- ungetc(c, fp);
- }
- else if (c == '\n') {
- linecount++;
- current_lineno++;
- }
- } while ((unit == Bytes ? bytecount : linecount) < numberof);
- }
- skip_possible_newline(ptr, fp, outfp);
- char buf[PS_LINE_MAX + 2];
- if (!ps_get_line(buf, fp)) {
- error("missing %%%%EndData line");
- return 0;
- }
- if (!matches_comment(buf, "EndData"))
- error("bad %%%%EndData line");
- if (outfp)
- fputs(buf, outfp);
- return 0;
-}
-
-int resource_manager::do_begin_binary(const char *ptr, int, FILE *fp,
- FILE *outfp)
-{
- if (!outfp)
- return 0;
- unsigned count;
- if (!read_uint_arg(&ptr, &count))
- return 0;
- if (outfp)
- fprintf(outfp, "%%%%BeginData: %u Binary Bytes\n", count);
- while (count != 0) {
- int c = getc(fp);
- if (c == EOF) {
- error("end of file within binary section");
- return 0;
- }
- if (outfp)
- putc(c, outfp);
- --count;
- if (c == '\r') {
- int cc = getc(fp);
- if (cc != '\n')
- current_lineno++;
- if (cc != EOF)
- ungetc(cc, fp);
- }
- else if (c == '\n')
- current_lineno++;
- }
- skip_possible_newline(ptr, fp, outfp);
- char buf[PS_LINE_MAX + 2];
- if (!ps_get_line(buf, fp)) {
- error("missing %%%%EndBinary line");
- return 0;
- }
- if (!matches_comment(buf, "EndBinary")) {
- error("bad %%%%EndBinary line");
- if (outfp)
- fputs(buf, outfp);
- }
- else if (outfp)
- fputs("%%EndData\n", outfp);
- return 0;
-}
-
-static unsigned parse_extensions(const char *ptr)
-{
- unsigned flags = 0;
- for (;;) {
- while (white_space(*ptr))
- ptr++;
- if (*ptr == '\0')
- break;
- const char *name = ptr;
- do {
- ++ptr;
- } while (*ptr != '\0' && !white_space(*ptr));
- int i;
- for (i = 0; i < NEXTENSIONS; i++)
- if (strlen(extension_table[i]) == size_t(ptr - name)
- && memcmp(extension_table[i], name, ptr - name) == 0) {
- flags |= (1 << i);
- break;
- }
- if (i >= NEXTENSIONS) {
- string s(name, ptr - name);
- s += '\0';
- error("unknown extension `%1'", s.contents());
- }
- }
- return flags;
-}
-
-// XXX if it has not been surrounded with {Begin,End}Document need to strip
-// out Page: Trailer {Begin,End}Prolog {Begin,End}Setup sections.
-
-// XXX Perhaps the decision whether to use BeginDocument or
-// BeginResource: file should be postponed till we have seen
-// the first line of the file.
-
-void resource_manager::process_file(int rank, FILE *fp, const char *filename,
- FILE *outfp)
-{
- // If none of these comments appear in the header section, and we are
- // just analyzing the file (ie outfp is 0), then we can return immediately.
- static const char *header_comment_table[] = {
- "DocumentNeededResources:",
- "DocumentSuppliedResources:",
- "DocumentNeededFonts:",
- "DocumentSuppliedFonts:",
- "DocumentNeededProcSets:",
- "DocumentSuppliedProcSets:",
- "DocumentNeededFiles:",
- "DocumentSuppliedFiles:",
- };
-
- const int NHEADER_COMMENTS = (sizeof(header_comment_table)
- / sizeof(header_comment_table[0]));
- struct comment_info {
- const char *name;
- int (resource_manager::*proc)(const char *, int, FILE *, FILE *);
- };
-
- static comment_info comment_table[] = {
- { "BeginResource:", &resource_manager::do_begin_resource },
- { "IncludeResource:", &resource_manager::do_include_resource },
- { "BeginDocument:", &resource_manager::do_begin_document },
- { "IncludeDocument:", &resource_manager::do_include_document },
- { "BeginProcSet:", &resource_manager::do_begin_procset },
- { "IncludeProcSet:", &resource_manager::do_include_procset },
- { "BeginFont:", &resource_manager::do_begin_font },
- { "IncludeFont:", &resource_manager::do_include_font },
- { "BeginFile:", &resource_manager::do_begin_file },
- { "IncludeFile:", &resource_manager::do_include_file },
- { "EndProcSet", &resource_manager::change_to_end_resource },
- { "EndFont", &resource_manager::change_to_end_resource },
- { "EndFile", &resource_manager::change_to_end_resource },
- { "BeginPreview:", &resource_manager::do_begin_preview },
- { "BeginData:", &resource_manager::do_begin_data },
- { "BeginBinary:", &resource_manager::do_begin_binary },
- };
-
- const int NCOMMENTS = sizeof(comment_table)/sizeof(comment_table[0]);
- char buf[PS_LINE_MAX + 2];
- int saved_lineno = current_lineno;
- const char *saved_filename = current_filename;
- current_filename = filename;
- current_lineno = 0;
- if (!ps_get_line(buf, fp)) {
- current_filename = saved_filename;
- current_lineno = saved_lineno;
- return;
- }
- if (strlen(buf) < sizeof(PS_MAGIC) - 1
- || memcmp(buf, PS_MAGIC, sizeof(PS_MAGIC) - 1) != 0) {
- if (outfp) {
- do {
- if (!(broken_flags & STRIP_PERCENT_BANG)
- || buf[0] != '%' || buf[1] != '!')
- fputs(buf, outfp);
- } while (ps_get_line(buf, fp));
- }
- }
- else {
- if (!(broken_flags & STRIP_PERCENT_BANG) && outfp)
- fputs(buf, outfp);
- int in_header = 1;
- int interesting = 0;
- int had_extensions_comment = 0;
- int had_language_level_comment = 0;
- for (;;) {
- if (!ps_get_line(buf, fp))
- break;
- int copy_this_line = 1;
- if (buf[0] == '%') {
- if (buf[1] == '%') {
- const char *ptr;
- int i;
- for (i = 0; i < NCOMMENTS; i++)
- if ((ptr = matches_comment(buf, comment_table[i].name))) {
- copy_this_line
- = (this->*(comment_table[i].proc))(ptr, rank, fp, outfp);
- break;
- }
- if (i >= NCOMMENTS && in_header) {
- if ((ptr = matches_comment(buf, "EndComments")))
- in_header = 0;
- else if (!had_extensions_comment
- && (ptr = matches_comment(buf, "Extensions:"))) {
- extensions |= parse_extensions(ptr);
- // XXX handle possibility that next line is %%+
- had_extensions_comment = 1;
- }
- else if (!had_language_level_comment
- && (ptr = matches_comment(buf, "LanguageLevel:"))) {
- unsigned ll;
- if (read_uint_arg(&ptr, &ll) && ll > language_level)
- language_level = ll;
- had_language_level_comment = 1;
- }
- else {
- for (i = 0; i < NHEADER_COMMENTS; i++)
- if (matches_comment(buf, header_comment_table[i])) {
- interesting = 1;
- break;
- }
- }
- }
- if ((broken_flags & STRIP_STRUCTURE_COMMENTS)
- && (matches_comment(buf, "EndProlog")
- || matches_comment(buf, "Page:")
- || matches_comment(buf, "Trailer")))
- copy_this_line = 0;
- }
- else if (buf[1] == '!') {
- if (broken_flags & STRIP_PERCENT_BANG)
- copy_this_line = 0;
- }
- }
- else
- in_header = 0;
- if (!outfp && !in_header && !interesting)
- break;
- if (copy_this_line && outfp)
- fputs(buf, outfp);
- }
- }
- current_filename = saved_filename;
- current_lineno = saved_lineno;
-}
-
-void resource_manager::read_download_file()
-{
- char *path = 0;
- FILE *fp = font::open_file("download", &path);
- if (!fp)
- fatal("can't find `download'");
- char buf[512];
- int lineno = 0;
- while (fgets(buf, sizeof(buf), fp)) {
- lineno++;
- char *p = strtok(buf, " \t\r\n");
- if (p == 0 || *p == '#')
- continue;
- char *q = strtok(0, " \t\r\n");
- if (!q)
- fatal_with_file_and_line(path, lineno, "missing filename");
- lookup_font(p)->filename = strsave(q);
- }
- a_delete path;
- fclose(fp);
-}
-
-// XXX Can we share some code with ps_output::put_string()?
-
-static void print_ps_string(const string &s, FILE *outfp)
-{
- int len = s.length();
- const char *str = s.contents();
- int funny = 0;
- if (str[0] == '(')
- funny = 1;
- else {
- for (int i = 0; i < len; i++)
- if (str[i] <= 040 || str[i] > 0176) {
- funny = 1;
- break;
- }
- }
- if (!funny) {
- put_string(s, outfp);
- return;
- }
- int level = 0;
- int i;
- for (i = 0; i < len; i++)
- if (str[i] == '(')
- level++;
- else if (str[i] == ')' && --level < 0)
- break;
- putc('(', outfp);
- for (i = 0; i < len; i++)
- switch (str[i]) {
- case '(':
- case ')':
- if (level != 0)
- putc('\\', outfp);
- putc(str[i], outfp);
- break;
- case '\\':
- fputs("\\\\", outfp);
- break;
- case '\n':
- fputs("\\n", outfp);
- break;
- case '\r':
- fputs("\\r", outfp);
- break;
- case '\t':
- fputs("\\t", outfp);
- break;
- case '\b':
- fputs("\\b", outfp);
- break;
- case '\f':
- fputs("\\f", outfp);
- break;
- default:
- if (str[i] < 040 || str[i] > 0176)
- fprintf(outfp, "\\%03o", str[i] & 0377);
- else
- putc(str[i], outfp);
- break;
- }
- putc(')', outfp);
-}
-
-void resource_manager::print_extensions_comment(FILE *outfp)
-{
- if (extensions) {
- fputs("%%Extensions:", outfp);
- for (int i = 0; i < NEXTENSIONS; i++)
- if (extensions & (1 << i)) {
- putc(' ', outfp);
- fputs(extension_table[i], outfp);
- }
- putc('\n', outfp);
- }
-}
-
-void resource_manager::print_language_level_comment(FILE *outfp)
-{
- if (language_level)
- fprintf(outfp, "%%%%LanguageLevel: %u\n", language_level);
-}
-
diff --git a/contrib/groff/src/devices/grotty/tty.cc b/contrib/groff/src/devices/grotty/tty.cc
deleted file mode 100644
index 7cfb658..0000000
--- a/contrib/groff/src/devices/grotty/tty.cc
+++ /dev/null
@@ -1,776 +0,0 @@
-// -*- C++ -*-
-/* Copyright (C) 1989-2000, 2001, 2002 Free Software Foundation, Inc.
- Written by James Clark (jjc@jclark.com)
-
-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 2, 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 groff; see the file COPYING. If not, write to the Free Software
-Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#include "driver.h"
-#include "device.h"
-
-extern "C" const char *Version_string;
-
-#define putstring(s) fputs(s, stdout)
-
-#ifndef SHRT_MIN
-#define SHRT_MIN (-32768)
-#endif
-
-#ifndef SHRT_MAX
-#define SHRT_MAX 32767
-#endif
-
-#define TAB_WIDTH 8
-
-static int horizontal_tab_flag = 0;
-static int form_feed_flag = 0;
-static int bold_flag = 1;
-static int underline_flag = 1;
-static int overstrike_flag = 1;
-static int draw_flag = 1;
-static int italic_flag = 0;
-static int reverse_flag = 0;
-static int old_drawing_scheme = 0;
-
-enum {
- UNDERLINE_MODE = 0x01,
- BOLD_MODE = 0x02,
- VDRAW_MODE = 0x04,
- HDRAW_MODE = 0x08,
- CU_MODE = 0x10,
- COLOR_CHANGE = 0x20
-};
-
-// Mode to use for bold-underlining.
-static unsigned char bold_underline_mode = BOLD_MODE|UNDERLINE_MODE;
-
-#ifndef IS_EBCDIC_HOST
-#define CSI "\033["
-#else
-#define CSI "\047["
-#endif
-
-// SGR handling (ISO 6429)
-#define SGR_BOLD CSI "1m"
-#define SGR_NO_BOLD CSI "22m"
-#define SGR_ITALIC CSI "3m"
-#define SGR_NO_ITALIC CSI "23m"
-#define SGR_UNDERLINE CSI "4m"
-#define SGR_NO_UNDERLINE CSI "24m"
-#define SGR_REVERSE CSI "7m"
-#define SGR_NO_REVERSE CSI "27m"
-// many terminals can't handle `CSI 39 m' and `CSI 49 m' to reset
-// the foreground and bachground color, respectively; thus we use
-// `CSI 0 m' exclusively
-#define SGR_DEFAULT CSI "0m"
-
-#define TTY_MAX_COLORS 8
-#define DEFAULT_COLOR_IDX TTY_MAX_COLORS
-
-class tty_font : public font {
- tty_font(const char *);
- unsigned char mode;
-public:
- ~tty_font();
- unsigned char get_mode() { return mode; }
-#if 0
- void handle_x_command(int argc, const char **argv);
-#endif
- static tty_font *load_tty_font(const char *);
-};
-
-tty_font *tty_font::load_tty_font(const char *s)
-{
- tty_font *f = new tty_font(s);
- if (!f->load()) {
- delete f;
- return 0;
- }
- const char *num = f->get_internal_name();
- long n;
- if (num != 0 && (n = strtol(num, 0, 0)) != 0)
- f->mode = int(n & (BOLD_MODE|UNDERLINE_MODE));
- if (!underline_flag)
- f->mode &= ~UNDERLINE_MODE;
- if (!bold_flag)
- f->mode &= ~BOLD_MODE;
- if ((f->mode & (BOLD_MODE|UNDERLINE_MODE)) == (BOLD_MODE|UNDERLINE_MODE))
- f->mode = (f->mode & ~(BOLD_MODE|UNDERLINE_MODE)) | bold_underline_mode;
- return f;
-}
-
-tty_font::tty_font(const char *nm)
-: font(nm), mode(0)
-{
-}
-
-tty_font::~tty_font()
-{
-}
-
-#if 0
-void tty_font::handle_x_command(int argc, const char **argv)
-{
- if (argc >= 1 && strcmp(argv[0], "bold") == 0)
- mode |= BOLD_MODE;
- else if (argc >= 1 && strcmp(argv[0], "underline") == 0)
- mode |= UNDERLINE_MODE;
-}
-#endif
-
-class glyph {
- static glyph *free_list;
-public:
- glyph *next;
- short hpos;
- unsigned int code;
- unsigned char mode;
- unsigned char back_color_idx;
- unsigned char fore_color_idx;
- void *operator new(size_t);
- void operator delete(void *);
- inline int draw_mode() { return mode & (VDRAW_MODE|HDRAW_MODE); }
- inline int order() {
- return mode & (VDRAW_MODE|HDRAW_MODE|CU_MODE|COLOR_CHANGE); }
-};
-
-glyph *glyph::free_list = 0;
-
-void *glyph::operator new(size_t)
-{
- if (!free_list) {
- const int BLOCK = 1024;
- free_list = (glyph *)new char[sizeof(glyph) * BLOCK];
- for (int i = 0; i < BLOCK - 1; i++)
- free_list[i].next = free_list + i + 1;
- free_list[BLOCK - 1].next = 0;
- }
- glyph *p = free_list;
- free_list = free_list->next;
- p->next = 0;
- return p;
-}
-
-void glyph::operator delete(void *p)
-{
- if (p) {
- ((glyph *)p)->next = free_list;
- free_list = (glyph *)p;
- }
-}
-
-class tty_printer : public printer {
- int is_utf8;
- glyph **lines;
- int nlines;
- int cached_v;
- int cached_vpos;
- unsigned char curr_fore_idx;
- unsigned char curr_back_idx;
- int is_underline;
- int is_bold;
- int cu_flag;
- color tty_colors[TTY_MAX_COLORS];
- void make_underline();
- void make_bold(unsigned int);
- unsigned char color_to_idx(color *col);
- void add_char(unsigned int, int, int, color *, color *, unsigned char);
-public:
- tty_printer(const char *device);
- ~tty_printer();
- void set_char(int, font *, const environment *, int, const char *name);
- void draw(int code, int *p, int np, const environment *env);
- void special(char *arg, const environment *env, char type);
- void change_color(const environment *env);
- void change_fill_color(const environment *env);
- void put_char(unsigned int);
- void put_color(unsigned char, int);
- void begin_page(int) { }
- void end_page(int page_length);
- font *make_font(const char *);
-};
-
-tty_printer::tty_printer(const char *device) : cached_v(0)
-{
- is_utf8 = !strcmp(device, "utf8");
- tty_colors[0].set_rgb(0, // black
- 0,
- 0);
- tty_colors[1].set_rgb(color::MAX_COLOR_VAL, // red
- 0,
- 0);
- tty_colors[2].set_rgb(0, // green
- color::MAX_COLOR_VAL,
- 0);
- tty_colors[3].set_rgb(color::MAX_COLOR_VAL, // yellow
- color::MAX_COLOR_VAL,
- 0);
- tty_colors[4].set_rgb(0, // blue
- 0,
- color::MAX_COLOR_VAL);
- tty_colors[5].set_rgb(color::MAX_COLOR_VAL, // magenta
- 0,
- color::MAX_COLOR_VAL);
- tty_colors[6].set_rgb(0, // cyan
- color::MAX_COLOR_VAL,
- color::MAX_COLOR_VAL);
- tty_colors[7].set_rgb(color::MAX_COLOR_VAL, // white
- color::MAX_COLOR_VAL,
- color::MAX_COLOR_VAL);
- nlines = 66;
- lines = new glyph *[nlines];
- for (int i = 0; i < nlines; i++)
- lines[i] = 0;
- cu_flag = 0;
-}
-
-tty_printer::~tty_printer()
-{
- a_delete lines;
-}
-
-void tty_printer::make_underline()
-{
- if (old_drawing_scheme) {
- putchar('_');
- putchar('\b');
- }
- else {
- if (!is_underline) {
- if (italic_flag)
- putstring(SGR_ITALIC);
- else if (reverse_flag)
- putstring(SGR_REVERSE);
- else
- putstring(SGR_UNDERLINE);
- }
- is_underline = 1;
- }
-}
-
-void tty_printer::make_bold(unsigned int c)
-{
- if (old_drawing_scheme) {
- put_char(c);
- putchar('\b');
- }
- else {
- if (!is_bold)
- putstring(SGR_BOLD);
- is_bold = 1;
- }
-}
-
-unsigned char tty_printer::color_to_idx(color *col)
-{
- if (col->is_default())
- return DEFAULT_COLOR_IDX;
- for (int i = 0; i < TTY_MAX_COLORS; i++)
- if (*col == tty_colors[i])
- return (unsigned char)i;
- unsigned r, g, b;
- col->get_rgb(&r, &g, &b);
- error("Unknown color (%1, %2, %3) mapped to default", r, g, b);
- return DEFAULT_COLOR_IDX;
-}
-
-void tty_printer::set_char(int i, font *f, const environment *env,
- int w, const char *name)
-{
- if (w != font::hor)
- fatal("width of character not equal to horizontal resolution");
- add_char(f->get_code(i),
- env->hpos, env->vpos,
- env->col, env->fill,
- ((tty_font *)f)->get_mode());
-}
-
-void tty_printer::add_char(unsigned int c,
- int h, int v,
- color *fore, color *back,
- unsigned char mode)
-{
-#if 0
- // This is too expensive.
- if (h % font::hor != 0)
- fatal("horizontal position not a multiple of horizontal resolution");
-#endif
- int hpos = h / font::hor;
- if (hpos < SHRT_MIN || hpos > SHRT_MAX) {
- error("character with ridiculous horizontal position discarded");
- return;
- }
- int vpos;
- if (v == cached_v && cached_v != 0)
- vpos = cached_vpos;
- else {
- if (v % font::vert != 0)
- fatal("vertical position not a multiple of vertical resolution");
- vpos = v / font::vert;
- if (vpos > nlines) {
- glyph **old_lines = lines;
- lines = new glyph *[vpos + 1];
- memcpy(lines, old_lines, nlines * sizeof(glyph *));
- for (int i = nlines; i <= vpos; i++)
- lines[i] = 0;
- a_delete old_lines;
- nlines = vpos + 1;
- }
- // Note that the first output line corresponds to groff
- // position font::vert.
- if (vpos <= 0) {
- error("character above first line discarded");
- return;
- }
- cached_v = v;
- cached_vpos = vpos;
- }
- glyph *g = new glyph;
- g->hpos = hpos;
- g->code = c;
- g->fore_color_idx = color_to_idx(fore);
- g->back_color_idx = color_to_idx(back);
- g->mode = mode;
-
- // The list will be reversed later. After reversal, it must be in
- // increasing order of hpos, with COLOR_CHANGE and CU specials before
- // HDRAW characters before VDRAW characters before normal characters
- // at each hpos, and otherwise in order of occurrence.
-
- glyph **pp;
- for (pp = lines + (vpos - 1); *pp; pp = &(*pp)->next)
- if ((*pp)->hpos < hpos
- || ((*pp)->hpos == hpos && (*pp)->order() >= g->order()))
- break;
- g->next = *pp;
- *pp = g;
-}
-
-void tty_printer::special(char *arg, const environment *env, char type)
-{
- if (type == 'u') {
- add_char(*arg - '0', env->hpos, env->vpos, env->col, env->fill, CU_MODE);
- return;
- }
- if (type != 'p')
- return;
- char *p;
- for (p = arg; *p == ' ' || *p == '\n'; p++)
- ;
- char *tag = p;
- for (; *p != '\0' && *p != ':' && *p != ' ' && *p != '\n'; p++)
- ;
- if (*p == '\0' || strncmp(tag, "tty", p - tag) != 0) {
- error("X command without `tty:' tag ignored");
- return;
- }
- p++;
- for (; *p == ' ' || *p == '\n'; p++)
- ;
- char *command = p;
- for (; *p != '\0' && *p != ' ' && *p != '\n'; p++)
- ;
- if (*command == '\0') {
- error("empty X command ignored");
- return;
- }
- if (strncmp(command, "sgr", p - command) == 0) {
- for (; *p == ' ' || *p == '\n'; p++)
- ;
- int n;
- if (*p != '\0' && sscanf(p, "%d", &n) == 1 && n == 0)
- old_drawing_scheme = 1;
- else
- old_drawing_scheme = 0;
- }
-}
-
-void tty_printer::change_color(const environment *env)
-{
- add_char(0, env->hpos, env->vpos, env->col, env->fill, COLOR_CHANGE);
-}
-
-void tty_printer::change_fill_color(const environment *env)
-{
- add_char(0, env->hpos, env->vpos, env->col, env->fill, COLOR_CHANGE);
-}
-
-void tty_printer::draw(int code, int *p, int np, const environment *env)
-{
- if (code != 'l' || !draw_flag)
- return;
- if (np != 2) {
- error("2 arguments required for line");
- return;
- }
- if (p[0] == 0) {
- // vertical line
- int v = env->vpos;
- int len = p[1];
- if (len < 0) {
- v += len;
- len = -len;
- }
- while (len >= 0) {
- add_char('|', env->hpos, v, env->col, env->fill, VDRAW_MODE);
- len -= font::vert;
- v += font::vert;
- }
- }
- if (p[1] == 0) {
- // horizontal line
- int h = env->hpos;
- int len = p[0];
- if (len < 0) {
- h += len;
- len = -len;
- }
- while (len >= 0) {
- add_char('-', h, env->vpos, env->col, env->fill, HDRAW_MODE);
- len -= font::hor;
- h += font::hor;
- }
- }
-}
-
-void tty_printer::put_char(unsigned int wc)
-{
- if (is_utf8 && wc >= 0x80) {
- char buf[6 + 1];
- int count;
- char *p = buf;
- if (wc < 0x800)
- count = 1, *p = (unsigned char)((wc >> 6) | 0xc0);
- else if (wc < 0x10000)
- count = 2, *p = (unsigned char)((wc >> 12) | 0xe0);
- else if (wc < 0x200000)
- count = 3, *p = (unsigned char)((wc >> 18) | 0xf0);
- else if (wc < 0x4000000)
- count = 4, *p = (unsigned char)((wc >> 24) | 0xf8);
- else if (wc <= 0x7fffffff)
- count = 5, *p = (unsigned char)((wc >> 30) | 0xfC);
- else
- return;
- do *++p = (unsigned char)(((wc >> (6 * --count)) & 0x3f) | 0x80);
- while (count > 0);
- *++p = '\0';
- putstring(buf);
- }
- else
- putchar(wc);
-}
-
-void tty_printer::put_color(unsigned char color_index, int back)
-{
- if (color_index == DEFAULT_COLOR_IDX) {
- putstring(SGR_DEFAULT);
- // set bold and underline again
- if (is_bold)
- putstring(SGR_BOLD);
- if (is_underline) {
- if (italic_flag)
- putstring(SGR_ITALIC);
- else if (reverse_flag)
- putstring(SGR_REVERSE);
- else
- putstring(SGR_UNDERLINE);
- }
- // set other color again
- back = !back;
- color_index = back ? curr_back_idx : curr_fore_idx;
- }
- putstring(CSI);
- if (back)
- putchar('4');
- else
- putchar('3');
- putchar(color_index + '0');
- putchar('m');
-}
-
-void tty_printer::end_page(int page_length)
-{
- if (page_length % font::vert != 0)
- error("vertical position at end of page not multiple of vertical resolution");
- int lines_per_page = page_length / font::vert;
- int last_line;
- for (last_line = nlines; last_line > 0; last_line--)
- if (lines[last_line - 1])
- break;
-#if 0
- if (last_line > lines_per_page) {
- error("characters past last line discarded");
- do {
- --last_line;
- while (lines[last_line]) {
- glyph *tem = lines[last_line];
- lines[last_line] = tem->next;
- delete tem;
- }
- } while (last_line > lines_per_page);
- }
-#endif
- for (int i = 0; i < last_line; i++) {
- glyph *p = lines[i];
- lines[i] = 0;
- glyph *g = 0;
- while (p) {
- glyph *tem = p->next;
- p->next = g;
- g = p;
- p = tem;
- }
- int hpos = 0;
- glyph *nextp;
- curr_fore_idx = DEFAULT_COLOR_IDX;
- curr_back_idx = DEFAULT_COLOR_IDX;
- is_underline = 0;
- is_bold = 0;
- for (p = g; p; delete p, p = nextp) {
- nextp = p->next;
- if (p->mode & CU_MODE) {
- cu_flag = p->code;
- continue;
- }
- if (nextp && p->hpos == nextp->hpos) {
- if (p->draw_mode() == HDRAW_MODE &&
- nextp->draw_mode() == VDRAW_MODE) {
- nextp->code = '+';
- continue;
- }
- if (p->draw_mode() != 0 && p->draw_mode() == nextp->draw_mode()) {
- nextp->code = p->code;
- continue;
- }
- if (!overstrike_flag)
- continue;
- }
- if (hpos > p->hpos) {
- do {
- putchar('\b');
- hpos--;
- } while (hpos > p->hpos);
- }
- else {
- if (horizontal_tab_flag) {
- for (;;) {
- int next_tab_pos = ((hpos + TAB_WIDTH) / TAB_WIDTH) * TAB_WIDTH;
- if (next_tab_pos > p->hpos)
- break;
- if (cu_flag)
- make_underline();
- else if (!old_drawing_scheme && is_underline) {
- if (italic_flag)
- putstring(SGR_NO_ITALIC);
- else if (reverse_flag)
- putstring(SGR_NO_REVERSE);
- else
- putstring(SGR_NO_UNDERLINE);
- is_underline = 0;
- }
- putchar('\t');
- hpos = next_tab_pos;
- }
- }
- for (; hpos < p->hpos; hpos++) {
- if (cu_flag)
- make_underline();
- else if (!old_drawing_scheme && is_underline) {
- if (italic_flag)
- putstring(SGR_NO_ITALIC);
- else if (reverse_flag)
- putstring(SGR_NO_REVERSE);
- else
- putstring(SGR_NO_UNDERLINE);
- is_underline = 0;
- }
- putchar(' ');
- }
- }
- assert(hpos == p->hpos);
- if (p->mode & COLOR_CHANGE) {
- if (!old_drawing_scheme) {
- if (p->fore_color_idx != curr_fore_idx) {
- put_color(p->fore_color_idx, 0);
- curr_fore_idx = p->fore_color_idx;
- }
- if (p->back_color_idx != curr_back_idx) {
- put_color(p->back_color_idx, 1);
- curr_back_idx = p->back_color_idx;
- }
- }
- continue;
- }
- if (p->mode & UNDERLINE_MODE)
- make_underline();
- else if (!old_drawing_scheme && is_underline) {
- if (italic_flag)
- putstring(SGR_NO_ITALIC);
- else if (reverse_flag)
- putstring(SGR_NO_REVERSE);
- else
- putstring(SGR_NO_UNDERLINE);
- is_underline = 0;
- }
- if (p->mode & BOLD_MODE)
- make_bold(p->code);
- else if (!old_drawing_scheme && is_bold) {
- putstring(SGR_NO_BOLD);
- is_bold = 0;
- }
- if (!old_drawing_scheme) {
- if (p->fore_color_idx != curr_fore_idx) {
- put_color(p->fore_color_idx, 0);
- curr_fore_idx = p->fore_color_idx;
- }
- if (p->back_color_idx != curr_back_idx) {
- put_color(p->back_color_idx, 1);
- curr_back_idx = p->back_color_idx;
- }
- }
- put_char(p->code);
- hpos++;
- }
- if (!old_drawing_scheme
- && (is_bold || is_underline
- || curr_fore_idx != DEFAULT_COLOR_IDX
- || curr_back_idx != DEFAULT_COLOR_IDX))
- putstring(SGR_DEFAULT);
- putchar('\n');
- }
- if (form_feed_flag) {
- if (last_line < lines_per_page)
- putchar('\f');
- }
- else {
- for (; last_line < lines_per_page; last_line++)
- putchar('\n');
- }
-}
-
-font *tty_printer::make_font(const char *nm)
-{
- return tty_font::load_tty_font(nm);
-}
-
-printer *make_printer()
-{
- return new tty_printer(device);
-}
-
-static void usage(FILE *stream);
-
-int main(int argc, char **argv)
-{
- program_name = argv[0];
- static char stderr_buf[BUFSIZ];
- if (getenv("GROFF_NO_SGR"))
- old_drawing_scheme = 1;
- setbuf(stderr, stderr_buf);
- int c;
- static const struct option long_options[] = {
- { "help", no_argument, 0, CHAR_MAX + 1 },
- { "version", no_argument, 0, 'v' },
- { NULL, 0, 0, 0 }
- };
- while ((c = getopt_long(argc, argv, "bBcdfF:hioruUv", long_options, NULL))
- != EOF)
- switch(c) {
- case 'v':
- printf("GNU grotty (groff) version %s\n", Version_string);
- exit(0);
- break;
- case 'i':
- // Use italic font instead of underlining.
- italic_flag = 1;
- break;
- case 'b':
- // Do not embolden by overstriking.
- bold_flag = 0;
- break;
- case 'c':
- // Use old scheme for emboldening and underline.
- old_drawing_scheme = 1;
- break;
- case 'u':
- // Do not underline.
- underline_flag = 0;
- break;
- case 'o':
- // Do not overstrike (other than emboldening and underlining).
- overstrike_flag = 0;
- break;
- case 'r':
- // Use reverse mode instead of underlining.
- reverse_flag = 1;
- break;
- case 'B':
- // Do bold-underlining as bold.
- bold_underline_mode = BOLD_MODE;
- break;
- case 'U':
- // Do bold-underlining as underlining.
- bold_underline_mode = UNDERLINE_MODE;
- break;
- case 'h':
- // Use horizontal tabs.
- horizontal_tab_flag = 1;
- break;
- case 'f':
- form_feed_flag = 1;
- break;
- case 'F':
- font::command_line_font_dir(optarg);
- break;
- case 'd':
- // Ignore \D commands.
- draw_flag = 0;
- break;
- case CHAR_MAX + 1: // --help
- usage(stdout);
- exit(0);
- break;
- case '?':
- usage(stderr);
- exit(1);
- break;
- default:
- assert(0);
- }
- if (old_drawing_scheme) {
- italic_flag = 0;
- reverse_flag = 0;
- }
- else {
- bold_underline_mode = BOLD_MODE|UNDERLINE_MODE;
- bold_flag = 1;
- underline_flag = 1;
- }
- if (optind >= argc)
- do_file("-");
- else {
- for (int i = optind; i < argc; i++)
- do_file(argv[i]);
- }
- delete pr;
- return 0;
-}
-
-static void usage(FILE *stream)
-{
- fprintf(stream, "usage: %s [-bBcdfhioruUv] [-F dir] [files ...]\n",
- program_name);
-}
OpenPOWER on IntegriCloud