summaryrefslogtreecommitdiffstats
path: root/contrib/groff/src
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/groff/src')
-rw-r--r--contrib/groff/src/devices/grodvi/Makefile.sub4
-rw-r--r--contrib/groff/src/devices/grodvi/dvi.cc82
-rw-r--r--contrib/groff/src/devices/grodvi/grodvi.man239
-rw-r--r--contrib/groff/src/devices/grohtml/Makefile.sub11
-rw-r--r--contrib/groff/src/devices/grohtml/grohtml.man96
-rw-r--r--contrib/groff/src/devices/grohtml/html-table.cc687
-rw-r--r--contrib/groff/src/devices/grohtml/html-table.h130
-rw-r--r--contrib/groff/src/devices/grohtml/html-text.cc581
-rw-r--r--contrib/groff/src/devices/grohtml/html-text.h124
-rw-r--r--contrib/groff/src/devices/grohtml/html.h3
-rw-r--r--contrib/groff/src/devices/grohtml/output.cc56
-rw-r--r--contrib/groff/src/devices/grohtml/post-html.cc2417
-rw-r--r--contrib/groff/src/devices/grolbp/Makefile.sub4
-rw-r--r--contrib/groff/src/devices/grolbp/grolbp.man79
-rw-r--r--contrib/groff/src/devices/grolbp/lbp.cc1038
-rw-r--r--contrib/groff/src/devices/grolbp/lbp.h2
-rw-r--r--contrib/groff/src/devices/grolj4/Makefile.sub4
-rw-r--r--contrib/groff/src/devices/grolj4/grolj4.man21
-rw-r--r--contrib/groff/src/devices/grolj4/lj4.cc59
-rw-r--r--contrib/groff/src/devices/grops/Makefile.sub6
-rw-r--r--contrib/groff/src/devices/grops/TODO3
-rw-r--r--contrib/groff/src/devices/grops/grops.man381
-rw-r--r--contrib/groff/src/devices/grops/ps.cc258
-rw-r--r--contrib/groff/src/devices/grops/ps.h3
-rw-r--r--contrib/groff/src/devices/grops/psrm.cc34
-rw-r--r--contrib/groff/src/devices/grotty/Makefile.sub4
-rw-r--r--contrib/groff/src/devices/grotty/tty.cc319
-rw-r--r--contrib/groff/src/include/Makefile.sub5
-rw-r--r--contrib/groff/src/include/color.h87
-rw-r--r--contrib/groff/src/include/config.hin150
-rw-r--r--contrib/groff/src/include/driver.h8
-rw-r--r--contrib/groff/src/include/errarg.h7
-rw-r--r--contrib/groff/src/include/font.h6
-rw-r--r--contrib/groff/src/include/geometry.h27
-rw-r--r--contrib/groff/src/include/getopt.h25
-rw-r--r--contrib/groff/src/include/html-strings.h6
-rw-r--r--contrib/groff/src/include/htmlhint.h37
-rw-r--r--contrib/groff/src/include/lib.h57
-rw-r--r--contrib/groff/src/include/nonposix.h26
-rw-r--r--contrib/groff/src/include/paper.h37
-rw-r--r--contrib/groff/src/include/posix.h14
-rw-r--r--contrib/groff/src/include/printer.h61
-rw-r--r--contrib/groff/src/include/stringclass.h5
-rw-r--r--contrib/groff/src/libs/libbib/Makefile.sub10
-rw-r--r--contrib/groff/src/libs/libbib/index.cc5
-rw-r--r--contrib/groff/src/libs/libbib/linear.cc6
-rw-r--r--contrib/groff/src/libs/libbib/map.c9
-rw-r--r--contrib/groff/src/libs/libbib/search.cc7
-rw-r--r--contrib/groff/src/libs/libdriver/Makefile.sub4
-rw-r--r--contrib/groff/src/libs/libdriver/input.cc2156
-rw-r--r--contrib/groff/src/libs/libdriver/printer.cc119
-rw-r--r--contrib/groff/src/libs/libgroff/Makefile.sub97
-rw-r--r--contrib/groff/src/libs/libgroff/color.cc363
-rw-r--r--contrib/groff/src/libs/libgroff/errarg.cc20
-rw-r--r--contrib/groff/src/libs/libgroff/font.cc158
-rw-r--r--contrib/groff/src/libs/libgroff/fontfile.cc9
-rw-r--r--contrib/groff/src/libs/libgroff/geometry.cc286
-rw-r--r--contrib/groff/src/libs/libgroff/getopt.c349
-rw-r--r--contrib/groff/src/libs/libgroff/getopt1.c16
-rw-r--r--contrib/groff/src/libs/libgroff/htmlhint.cc59
-rw-r--r--contrib/groff/src/libs/libgroff/invalid.cc60
-rw-r--r--contrib/groff/src/libs/libgroff/itoa.c17
-rw-r--r--contrib/groff/src/libs/libgroff/matherr.c6
-rw-r--r--contrib/groff/src/libs/libgroff/maxfilename.cc2
-rw-r--r--contrib/groff/src/libs/libgroff/mksdir.cc34
-rw-r--r--contrib/groff/src/libs/libgroff/mkstemp.cc34
-rw-r--r--contrib/groff/src/libs/libgroff/nametoindex.cc9
-rw-r--r--contrib/groff/src/libs/libgroff/new.cc5
-rw-r--r--contrib/groff/src/libs/libgroff/paper.cc84
-rw-r--r--contrib/groff/src/libs/libgroff/putenv.c6
-rw-r--r--contrib/groff/src/libs/libgroff/searchpath.cc8
-rw-r--r--contrib/groff/src/libs/libgroff/strerror.c6
-rw-r--r--contrib/groff/src/libs/libgroff/string.cc38
-rw-r--r--contrib/groff/src/libs/libgroff/strtol.c7
-rw-r--r--contrib/groff/src/libs/libgroff/tmpfile.cc157
-rw-r--r--contrib/groff/src/libs/libgroff/tmpname.cc116
-rw-r--r--contrib/groff/src/preproc/eqn/Makefile.sub36
-rw-r--r--contrib/groff/src/preproc/eqn/box.cc26
-rw-r--r--contrib/groff/src/preproc/eqn/eqn.h7
-rw-r--r--contrib/groff/src/preproc/eqn/eqn.man16
-rw-r--r--contrib/groff/src/preproc/eqn/lex.cc8
-rw-r--r--contrib/groff/src/preproc/eqn/limit.cc12
-rw-r--r--contrib/groff/src/preproc/eqn/main.cc58
-rw-r--r--contrib/groff/src/preproc/eqn/other.cc12
-rw-r--r--contrib/groff/src/preproc/eqn/over.cc13
-rw-r--r--contrib/groff/src/preproc/eqn/script.cc16
-rw-r--r--contrib/groff/src/preproc/eqn/sqrt.cc18
-rw-r--r--contrib/groff/src/preproc/grn/Makefile.sub10
-rw-r--r--contrib/groff/src/preproc/grn/README10
-rw-r--r--contrib/groff/src/preproc/grn/gprint.h2
-rw-r--r--contrib/groff/src/preproc/grn/grn.man29
-rw-r--r--contrib/groff/src/preproc/grn/hdb.cc23
-rw-r--r--contrib/groff/src/preproc/grn/hgraph.cc30
-rw-r--r--contrib/groff/src/preproc/grn/main.cc6
-rw-r--r--contrib/groff/src/preproc/html/Makefile.sub6
-rw-r--r--contrib/groff/src/preproc/html/pre-html.cc1005
-rw-r--r--contrib/groff/src/preproc/html/pushback.cc333
-rw-r--r--contrib/groff/src/preproc/html/pushback.h54
-rw-r--r--contrib/groff/src/preproc/pic/Makefile.sub22
-rw-r--r--contrib/groff/src/preproc/pic/common.cc1
-rw-r--r--contrib/groff/src/preproc/pic/common.h4
-rw-r--r--contrib/groff/src/preproc/pic/lex.cc70
-rw-r--r--contrib/groff/src/preproc/pic/main.cc18
-rw-r--r--contrib/groff/src/preproc/pic/object.cc141
-rw-r--r--contrib/groff/src/preproc/pic/object.h9
-rw-r--r--contrib/groff/src/preproc/pic/output.h8
-rw-r--r--contrib/groff/src/preproc/pic/pic.h8
-rw-r--r--contrib/groff/src/preproc/pic/pic.man221
-rw-r--r--contrib/groff/src/preproc/pic/pic.y196
-rw-r--r--contrib/groff/src/preproc/pic/tex.cc26
-rw-r--r--contrib/groff/src/preproc/pic/troff.cc83
-rw-r--r--contrib/groff/src/preproc/refer/Makefile.sub14
-rw-r--r--contrib/groff/src/preproc/refer/command.cc7
-rw-r--r--contrib/groff/src/preproc/refer/refer.cc22
-rw-r--r--contrib/groff/src/preproc/refer/refer.h7
-rw-r--r--contrib/groff/src/preproc/soelim/Makefile.sub4
-rw-r--r--contrib/groff/src/preproc/soelim/soelim.cc5
-rw-r--r--contrib/groff/src/preproc/tbl/Makefile.sub6
-rw-r--r--contrib/groff/src/preproc/tbl/main.cc34
-rw-r--r--contrib/groff/src/preproc/tbl/table.h10
-rw-r--r--contrib/groff/src/preproc/tbl/tbl.man346
-rw-r--r--contrib/groff/src/roff/groff/Makefile.sub4
-rw-r--r--contrib/groff/src/roff/groff/groff.cc55
-rw-r--r--contrib/groff/src/roff/groff/pipeline.c24
-rw-r--r--contrib/groff/src/roff/groff/pipeline.h5
-rw-r--r--contrib/groff/src/roff/grog/Makefile.sub9
-rw-r--r--contrib/groff/src/roff/grog/grog.man7
-rw-r--r--contrib/groff/src/roff/grog/grog.pl28
-rw-r--r--contrib/groff/src/roff/grog/grog.sh12
-rw-r--r--contrib/groff/src/roff/troff/Makefile.sub20
-rw-r--r--contrib/groff/src/roff/troff/TODO3
-rw-r--r--contrib/groff/src/roff/troff/charinfo.h38
-rw-r--r--contrib/groff/src/roff/troff/dictionary.cc2
-rw-r--r--contrib/groff/src/roff/troff/div.cc23
-rw-r--r--contrib/groff/src/roff/troff/div.h2
-rw-r--r--contrib/groff/src/roff/troff/env.cc607
-rw-r--r--contrib/groff/src/roff/troff/env.h33
-rw-r--r--contrib/groff/src/roff/troff/input.cc1685
-rw-r--r--contrib/groff/src/roff/troff/node.cc650
-rw-r--r--contrib/groff/src/roff/troff/node.h51
-rw-r--r--contrib/groff/src/roff/troff/number.cc9
-rw-r--r--contrib/groff/src/roff/troff/request.h10
-rw-r--r--contrib/groff/src/roff/troff/symbol.cc14
-rw-r--r--contrib/groff/src/roff/troff/symbol.h9
-rw-r--r--contrib/groff/src/roff/troff/token.h21
-rw-r--r--contrib/groff/src/roff/troff/troff.h18
-rw-r--r--contrib/groff/src/roff/troff/troff.man2595
-rw-r--r--contrib/groff/src/utils/addftinfo/Makefile.sub6
-rw-r--r--contrib/groff/src/utils/addftinfo/addftinfo.cc5
-rw-r--r--contrib/groff/src/utils/afmtodit/afmtodit.man59
-rw-r--r--contrib/groff/src/utils/afmtodit/afmtodit.pl5
-rw-r--r--contrib/groff/src/utils/hpftodit/Makefile.sub4
-rw-r--r--contrib/groff/src/utils/hpftodit/hpftodit.cc23
-rw-r--r--contrib/groff/src/utils/indxbib/Makefile.sub6
-rw-r--r--contrib/groff/src/utils/indxbib/indxbib.cc26
-rw-r--r--contrib/groff/src/utils/indxbib/signal.c6
-rw-r--r--contrib/groff/src/utils/lkbib/Makefile.sub4
-rw-r--r--contrib/groff/src/utils/lkbib/lkbib.cc5
-rw-r--r--contrib/groff/src/utils/lookbib/Makefile.sub4
-rw-r--r--contrib/groff/src/utils/lookbib/lookbib.cc9
-rw-r--r--contrib/groff/src/utils/pfbtops/Makefile.sub4
-rw-r--r--contrib/groff/src/utils/pfbtops/pfbtops.c5
-rw-r--r--contrib/groff/src/utils/tfmtodit/Makefile.sub4
-rw-r--r--contrib/groff/src/utils/tfmtodit/tfmtodit.cc5
-rw-r--r--contrib/groff/src/utils/tfmtodit/tfmtodit.man20
-rw-r--r--contrib/groff/src/xditview/ChangeLog50
-rw-r--r--contrib/groff/src/xditview/DviChar.c1024
-rw-r--r--contrib/groff/src/xditview/Imakefile.in8
-rw-r--r--contrib/groff/src/xditview/parse.c27
-rw-r--r--contrib/groff/src/xditview/xditview.c4
170 files changed, 14175 insertions, 7529 deletions
diff --git a/contrib/groff/src/devices/grodvi/Makefile.sub b/contrib/groff/src/devices/grodvi/Makefile.sub
index 0e5d32c..74e627d 100644
--- a/contrib/groff/src/devices/grodvi/Makefile.sub
+++ b/contrib/groff/src/devices/grodvi/Makefile.sub
@@ -1,6 +1,6 @@
-PROG=grodvi
+PROG=grodvi$(EXEEXT)
MAN1=grodvi.n
XLIBS=$(LIBDRIVER) $(LIBGROFF)
MLIB=$(LIBM)
-OBJS=dvi.o
+OBJS=dvi.$(OBJEXT)
CCSRCS=$(srcdir)/dvi.cc
diff --git a/contrib/groff/src/devices/grodvi/dvi.cc b/contrib/groff/src/devices/grodvi/dvi.cc
index b5b7c49..8412636 100644
--- a/contrib/groff/src/devices/grodvi/dvi.cc
+++ b/contrib/groff/src/devices/grodvi/dvi.cc
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001
+/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001, 2002
Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
@@ -44,8 +44,6 @@ width in the tfm file. */
#define SIZESCALE 100
#define MULTIPLIER 1
-#define FILL_MAX 1000
-
class dvi_font : public font {
dvi_font(const char *);
public:
@@ -123,6 +121,7 @@ class dvi_printer : public printer {
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;
@@ -132,6 +131,7 @@ class dvi_printer : public printer {
void define_font(int);
void set_font(int);
void possibly_begin_line();
+ void set_color(color *);
protected:
enum {
id_byte = 2,
@@ -179,9 +179,8 @@ public:
class draw_dvi_printer : public dvi_printer {
int output_pen_size;
- int fill;
void set_line_thickness(const environment *);
- void fill_next();
+ void fill_next(const environment *);
public:
draw_dvi_printer();
~draw_dvi_printer();
@@ -214,7 +213,7 @@ dvi_printer::~dvi_printer()
draw_dvi_printer::draw_dvi_printer()
-: output_pen_size(-1), fill(FILL_MAX)
+: output_pen_size(-1)
{
}
@@ -302,9 +301,45 @@ int scale(int x, int z)
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)
+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;
@@ -345,7 +380,7 @@ void dvi_printer::set_char(int index, font *f, const environment *env, int w, co
possibly_begin_line();
end_h = env->hpos + w;
cur_h += scale(f->get_width(index, UNITWIDTH)/MULTIPLIER,
- cur_point_size*RES_7227);
+ cur_point_size*RES_7227);
if (cur_h > max_h)
max_h = cur_h;
if (cur_v > max_v)
@@ -464,6 +499,8 @@ void dvi_printer::begin_page(int i)
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;
@@ -472,6 +509,7 @@ void dvi_printer::begin_page(int i)
void dvi_printer::end_page(int)
{
+ set_color(&default_color);
if (pushed)
end_of_line();
out1(eop);
@@ -629,10 +667,17 @@ void draw_dvi_printer::set_line_thickness(const environment *env)
}
}
-void draw_dvi_printer::fill_next()
+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 %.3f", double(fill)/FILL_MAX);
+ sprintf(buf, "sh %.3g", 1 - double(g)/color::MAX_COLOR_VAL);
do_special(buf);
}
@@ -652,7 +697,7 @@ void draw_dvi_printer::draw(int code, int *p, int np, const environment *env)
}
moveto(env->hpos+p[0]/2, env->vpos);
if (fill_flag)
- fill_next();
+ fill_next(env);
else
set_line_thickness(env);
int rad;
@@ -685,7 +730,7 @@ void draw_dvi_printer::draw(int code, int *p, int np, const environment *env)
}
moveto(env->hpos+p[0]/2, env->vpos);
if (fill_flag)
- fill_next();
+ fill_next(env);
sprintf(buf, "%s 0 0 %d %d 0 6.28319",
(fill_flag ? "ia" : "ar"),
milliinches(p[0]/2),
@@ -707,7 +752,7 @@ void draw_dvi_printer::draw(int code, int *p, int np, const environment *env)
}
moveto(env->hpos, env->vpos);
if (fill_flag)
- fill_next();
+ fill_next(env);
else
set_line_thickness(env);
do_special("pa 0 0");
@@ -790,17 +835,6 @@ void draw_dvi_printer::draw(int code, int *p, int np, const environment *env)
}
break;
}
- case 'f':
- {
- if (np != 1 && np != 2) {
- error("1 argument required for fill");
- break;
- }
- fill = p[0];
- if (fill < 0 || fill > FILL_MAX)
- fill = FILL_MAX;
- break;
- }
case 'R':
{
if (np != 2) {
diff --git a/contrib/groff/src/devices/grodvi/grodvi.man b/contrib/groff/src/devices/grodvi/grodvi.man
index a4488ce..f732a42 100644
--- a/contrib/groff/src/devices/grodvi/grodvi.man
+++ b/contrib/groff/src/devices/grodvi/grodvi.man
@@ -1,5 +1,5 @@
.ig
-Copyright (C) 1989-2000, 2001 Free Software Foundation, Inc.
+Copyright (C) 1989-2000, 2001, 2002 Free Software Foundation, Inc.
Permission is granted to make and distribute verbatim copies of
this manual provided the copyright notice and this permission notice
@@ -16,6 +16,8 @@ versions, except that this permission notice may be included in
translations approved by the Free Software Foundation instead of in
the original English.
..
+.
+.
.ie t .ds tx T\h'-.1667m'\v'.224m'E\v'-.224m'\h'-.125m'X
.el .ds tx TeX
.\" Like TP, but if specified indent is more than half
@@ -24,9 +26,13 @@ the original English.
.ie \\n(.$=0:((0\\$1)*2u>(\\n(.lu-\\n(.iu)) .TP
.el .TP "\\$1"
..
+.
+.
.TH GRODVI @MAN1EXT@ "@MDATE@" "Groff Version @VERSION@"
.SH NAME
grodvi \- convert groff output to TeX dvi format
+.
+.
.SH SYNOPSIS
.B grodvi
[
@@ -36,18 +42,22 @@ grodvi \- convert groff output to TeX dvi format
] [
.BI \-F dir
] [
-.IR files \|.\|.\|.
+.IR files \|.\|.\|.\&
]
.PP
It is possible to have whitespace between a command line option and its
parameter.
+.
+.
.SH DESCRIPTION
.B grodvi
is a driver for
.B groff
that produces \*(tx dvi format.
+.
Normally it should be run by
.BR groff\ \-Tdvi .
+.
This will run
.BR @g@troff\ \-Tdvi ;
it will also input the macros
@@ -56,115 +66,312 @@ if the input is being preprocessed with
.B @g@eqn
it will also input
.BR @FONTDIR@/devdvi/eqnchar .
+.
.LP
The dvi file generated by
.B grodvi
can be printed by any correctly-written dvi driver.
+.
The troff drawing primitives are implemented
-using the tpic version 2 specials.
+using the tpic version\~2 specials.
+.
If the driver does not support these, the
-.B \eD
+.B \[rs]D
commands will not produce any output.
+.
.LP
There is an additional drawing command available:
+.
.TP
-.BI \eD'R\ dh\ dv '
+.BI \[rs]D'R\ dh\ dv '
Draw a rule (solid black rectangle), with one corner
at the current position, and the diagonally opposite corner
-at the current position
+at the current position
.RI +( dh , dv ).
-Afterwards the current position will be at the opposite corner. This
-produces a rule in the dvi file and so can be printed even with a
+.
+Afterwards the current position will be at the opposite corner.
+.
+This produces a rule in the dvi file and so can be printed even with a
driver that does not support the tpic specials unlike the other
-.B \eD
+.B \[rs]D
commands.
+.
.LP
The groff command
-.BI \eX' anything '
+.BI \[rs]X' anything '
is translated into the same command in the dvi file as would be
produced by
-.BI \especial{ anything }
+.BI \[rs]special{ anything }
in \*(tx;
-.I anything may not contain a newline.
+.I anything
+may not contain a newline.
+.
+.LP
+For inclusion of EPS image files,
+.B grodvi
+loads
+.B pspic.tmac
+automatically, providing the
+.B PSPIC
+macro.
+.
+Please check
+.B grops (@MAN1EXT@)
+for a detailed description of this macro.
+.
.LP
Font files for
.B grodvi
can be created from tfm files using
.BR tfmtodit (@MAN1EXT@).
+.
The font description file should contain the following
additional commands:
+.
.Tp \w'\fBinternalname'u+2n
.BI internalname\ name
The name of the tfm file (without the
.B .tfm
extension) is
.IR name .
+.
.TP
.BI checksum\ n
The checksum in the tfm file is
.IR n .
+.
.TP
.BI designsize\ n
The designsize in the tfm file is
.IR n .
+.
.LP
These are automatically generated by
.B tfmtodit.
+.
+.LP
+The default color for
+.B \[rs]m
+and
+.B \[rs]M
+is black.
+.
+Currently, the drawing color for
+.B \[rs]D
+commands is always black, and fill color values are translated to gray.
+.
.LP
In
.B troff
the
-.B \eN
+.B \[rs]N
escape sequence can be used to access characters by their position
in the corresponding tfm file;
all characters in the tfm file can be accessed this way.
+.
+.
.SH OPTIONS
.TP
.B \-d
Do not use tpic specials to implement drawing commands.
+.
Horizontal and vertical lines will be implemented by rules.
+.
Other drawing commands will be ignored.
+.
.TP
.B \-v
Print the version number.
+.
.TP
.BI \-w n
Set the default line thickness to
.I n
-thousandths of an em.
+thousandths of an em.
+If this option isn't specified, the line thickness defaults to 0.04\~em.
+.
.TP
.BI \-F dir
Prepend directory
-.IB dir /devdvi
-to the search path for font and device description files.
+.IB dir /dev name
+to the search path for font and device description files;
+.I name
+is the name of the device, usually
+.BR dvi .
+.
+.
+.SH USAGE
+There are styles called
+.BR R ,
+.BR I ,
+.BR B ,
+and
+.B BI
+mounted at font positions 1 to 4.
+The fonts are grouped into families
+.B T
+and
+.B H
+having members in each of these styles:
+.
+.de FT
+.if '\\*(.T'dvi' .ft \\$1
+..
+.
+.RS
+.TP
+.B TR
+.FT TR
+CM Roman (cmr10)
+.FT
+.
+.TP
+.B TI
+.FT TI
+CM Text Italic (cmti10)
+.FT
+.
+.TP
+.B TB
+.FT TB
+CM Bold Extended Roman (cmbx10)
+.FT
+.
+.TP
+.B TBI
+.FT TBI
+CM Bold Extended Text Italic (cmbxti10)
+.FT
+.
+.TP
+.B HR
+.FT HR
+CM Sans Serif (cmss10)
+.FT
+.
+.TP
+.B HI
+.FT HI
+CM Slanted Sans Serif (cmssi10)
+.FT
+.
+.TP
+.B HB
+.FT HB
+CM Sans Serif Bold Extended (cmssbx10)
+.FT
+.
+.TP
+.B HBI
+.FT HBI
+CM Slanted Sans Serif Bold Extended (cmssbxo10)
+.FT
+.RE
+.
+.LP
+There are also the following fonts which are not members of a family:
+.
+.RS
+.TP
+.B CW
+CM Typewriter Text (cmtt10)
+.FT CW
+.FT
+.
+.TP
+.B CWI
+CM Italic Typewriter Text (cmitt10)
+.FT CWI
+.FT
+.RE
+.
+.LP
+Special fonts are
+.B MI
+(cmmi10),
+.B S
+(cmsy10),
+.B EX
+(cmex10),
+and, perhaps surprisingly,
+.BR TR ,
+.BR TI ,
+and
+.BR CW ,
+due to the different font encodings of text fonts.
+.
+For italic fonts,
+.B CWI
+is used instead of
+.BR CW .
+.
+.LP
+Finally, the symbol fonts of the American Mathematical Society are available
+as special fonts
+.B SA
+(msam10) and
+.B SB
+(msbm10).
+.
+These two fonts are not mounted by default.
+.
+.LP
+Using the option
+.B \-mec
+(loading the file
+.BR ec.tmac )
+EC and TC fonts are used.
+.
+The design of the EC family is very similar to that of the CM fonts;
+additionally, they give a much better coverage of groff symbols.
+.
+Note that
+.B ec.tmac
+must be called before any language-specific files; it doesn't take care of
+hcode values.
+.
+.
.SH FILES
.TP
.B @FONTDIR@/devdvi/DESC
Device description file.
+.
.TP
.BI @FONTDIR@/devdvi/ F
Font description file for font
.IR F .
+.
.TP
.B @MACRODIR@/dvi.tmac
Macros for use with
.BR grodvi .
+.
+.TP
+.B @MACRODIR@/ec.tmac
+Macros to switch to EC fonts.
+.
+.
.SH BUGS
Dvi files produced by
.B grodvi
use a different resolution (57816 units per inch) to those produced by
\*(tx.
+.
Incorrectly written drivers which assume the resolution used by \*(tx,
rather than using the resolution specified in the dvi file will not
work with
.BR grodvi .
+.
.LP
When using the
.B \-d
option with boxed tables,
vertical and horizontal lines can sometimes protrude by one pixel.
+.
This is a consequence of the way \*(tx requires that the heights
and widths of rules be rounded.
+.
+.
.SH "SEE ALSO"
.BR tfmtodit (@MAN1EXT@),
.BR groff (@MAN1EXT@),
diff --git a/contrib/groff/src/devices/grohtml/Makefile.sub b/contrib/groff/src/devices/grohtml/Makefile.sub
index 10f28ce..33e41f8 100644
--- a/contrib/groff/src/devices/grohtml/Makefile.sub
+++ b/contrib/groff/src/devices/grohtml/Makefile.sub
@@ -1,15 +1,18 @@
-PROG=post-grohtml
+PROG=post-grohtml$(EXEEXT)
MAN1=grohtml.n
XLIBS=$(LIBDRIVER) $(LIBGROFF)
MLIB=$(LIBM)
OBJS=\
- post-html.o \
- html-text.o \
- output.o
+ post-html.$(OBJEXT) \
+ html-table.$(OBJEXT) \
+ html-text.$(OBJEXT) \
+ output.$(OBJEXT)
CCSRCS=\
$(srcdir)/post-html.cc \
+ $(srcdir)/html-table.cc \
$(srcdir)/html-text.cc \
$(srcdir)/output.cc
HDRS=\
$(srcdir)/html.h \
+ $(srcdir)/html-table.h \
$(srcdir)/html-text.h
diff --git a/contrib/groff/src/devices/grohtml/grohtml.man b/contrib/groff/src/devices/grohtml/grohtml.man
index 7b0f5e1..976990a 100644
--- a/contrib/groff/src/devices/grohtml/grohtml.man
+++ b/contrib/groff/src/devices/grohtml/grohtml.man
@@ -1,5 +1,5 @@
.ig
-Copyright (C) 1999-2000, 2001 Free Software Foundation, Inc.
+Copyright (C) 1999-2000, 2001, 2002 Free Software Foundation, Inc.
Permission is granted to make and distribute verbatim copies of this
manual provided the copyright notice and this permission notice are
@@ -23,8 +23,10 @@ the original English.
.el .TP "\\$1"
..
.TH GROHTML @MAN1EXT@ "@MDATE@" "Groff Version @VERSION@"
+.
.SH NAME
grohtml \- html driver for groff
+.
.SH SYNOPSIS
.nr a \n(.j
.ad l
@@ -36,17 +38,25 @@ grohtml \- html driver for groff
.ie \\n(.$-1 .RI "[\ \fB\\$1\fP" "\\$2" "\ ]"
.el .RB "[\ " "\\$1" "\ ]"
..
-.OP \-v?lrn
+.OP \-vhlrn
.OP \-D dir
.OP \-F dir
.OP \-i resolution
-.OP \-I image stem
-.OP \-o image vertical offset
+.OP \-I \%image-stem
+.OP \-o \%image-vertical-offset
+.OP \-a \%aa-text-bits
+.OP \-a \%aa-graphic-bits
.RI "[\ " files\|.\|.\|. "\ ]"
.br
.ad \na
+.
.SH DESCRIPTION
+The
.B grohtml
+front end (which consists of a preprocessor,
+.BR pre-grohtml ,
+and a device driver,
+.BR post-grohtml )
translates the output of GNU
.B troff
to html.
@@ -76,11 +86,51 @@ using
option.
.SH OPTIONS
.TP
-.B \-v
-Displays the version.
+.BI \-a aa-text-bits
+Number of bits of antialiasing information to be used by
+.I text
+when generating png images.
+The default is\~4 but legal values are 0, 1, 2, and\~4.
+Note your version of
+.B gs
+needs to support the
+.B \%\-dTextAlphaBits
+and
+.B \%\-dGraphicAlphaBits
+options in order to exploit antialiasing.
+A value of\~0 stops
+.B grohtml
+from issuing antialiasing commands to
+.BR gs .
+.TP
+.BI \-g aa-graphic-bits
+Number of bits of antialiasing information to be used by
+.I graphics
+when generating png images.
+The default is\~4 but legal values are 0, 1, 2, and\~4.
+Note your version of
+.B gs
+needs to support the
+.B \%\-dTextAlphaBits
+and
+.B \%\-dGraphicAlphaBits
+options in order to exploit antialiasing.
+A value of\~0 stops
+.B grohtml
+from issuing antialiasing commands to
+.BR gs .
+.TP
+.B -b
+Initialize the background color to white.
.TP
-.B \-?
-Emits a usage synopsis.
+.B -h
+Generates section and number headings by using
+.BR <B> .\|.\|. </B>
+and increasing the font size, rather than using the
+.BI <H n >\c
+\&.\|.\|.\c
+.BI </H n >
+tags.
.TP
.B -l
Turns off the production of automatic section links at the top of the document.
@@ -91,10 +141,15 @@ Turns off the automatic header and footer line (html rule).
.B -n
Generate simple heading anchors whenever a section/number heading is found.
Without the option the anchor value is the textual heading.
-This can cause problems when a heading contains a `?' on some brousers
+This can cause problems when a heading contains a `?' on some browsers
(netscape).
This flag is automatically turned on if a heading contains an image.
.TP
+.B -p
+Display page rendering progress to stderr.
+.B grohtml
+only displays a page number when an image is required.
+.TP
.BI \-F dir
Prepend directory
.IB dir /dev name
@@ -105,8 +160,8 @@ is the name of the device, usually
.TP
.BI \-i resolution
Select the resolution for all images.
-By default this is 80 pixels per inch.
-Example: -i100 indicates 100 pixels per inch.
+By default this is 100 pixels per inch.
+Example: -i200 indicates 200 pixels per inch.
.TP
.BI \-I stem
Determine the image stem name.
@@ -115,6 +170,9 @@ If omitted grohtml uses
.RI ( XXX
is the process ID).
.TP
+.BI \-o vertical-offset
+Specify the vertical offset of images in points.
+.TP
.BI \-D dir
Inform
.B grohtml
@@ -123,9 +181,7 @@ to place all image files into directory
.TP
.B \-v
Print the version number.
-.TP
-.B \-?
-Display usage.
+.
.SH USAGE
There are styles called
.BR R ,
@@ -137,9 +193,19 @@ mounted at font positions 1 to 4.
.SH DEPENDENCIES
.B grohtml
is dependent upon the png utilities
-.RB ( \&\%pnmcut ,\ \%pnmtopng )
+.RB ( \&\%pnmcut ,\ \%pnmcrop ,\ \%pnmtopng )
and GhostScript
.RB ( gs ).
+.B \%pnmtopng
+(version 2.37.6 or greater)
+and
+.B \%pnmcut
+from the netpbm package (version 9.16 or greater) will work also.
+It is also dependent upon
+.B \%psselect
+from the
+.B PSUtils
+package.
Images are generated whenever a table, picture, equation or line is
encountered.
.SH BUGS
diff --git a/contrib/groff/src/devices/grohtml/html-table.cc b/contrib/groff/src/devices/grohtml/html-table.cc
new file mode 100644
index 0000000..a2bb255
--- /dev/null
+++ b/contrib/groff/src/devices/grohtml/html-table.cc
@@ -0,0 +1,687 @@
+// -*- 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-table.h b/contrib/groff/src/devices/grohtml/html-table.h
new file mode 100644
index 0000000..3152060
--- /dev/null
+++ b/contrib/groff/src/devices/grohtml/html-table.h
@@ -0,0 +1,130 @@
+// -*- 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 "html.h"
+
+#if !defined(HTML_TABLE_H)
+#define HTML_TABLE_H
+
+typedef struct tab_position {
+ char alignment;
+ int position;
+ struct tab_position *next;
+} tab_position;
+
+
+class tabs {
+public:
+ tabs ();
+ ~tabs ();
+ void clear (void);
+ int compatible (const char *s);
+ void init (const char *s);
+ int find_tab (int pos);
+ int get_tab_pos (int n);
+ char get_tab_align (int n);
+ void dump_tabs (void);
+
+private:
+ void delete_list (void);
+ tab_position *tab;
+};
+
+/*
+ * define a column
+ */
+
+typedef struct cols {
+ int left, right;
+ int no;
+ char alignment;
+ struct cols *next;
+} cols;
+
+class html_table {
+public:
+ html_table (simple_output *op, int linelen);
+ ~html_table (void);
+ int add_column (int coln, int hstart, int hend, char align);
+ cols *get_column (int coln);
+ int insert_column (int coln, int hstart, int hend, char align);
+ int modify_column (cols *c, int hstart, int hend, char align);
+ int find_tab_column (int pos);
+ int find_column (int pos);
+ int get_tab_pos (int n);
+ char get_tab_align (int n);
+ void set_linelength (int linelen);
+ int no_columns (void);
+ int no_gaps (void);
+ int is_gap (cols *c);
+ void dump_table (void);
+ void emit_table_header (int space);
+ void emit_col (int n);
+ void emit_new_row (void);
+ void emit_finish_table (void);
+ int get_right (cols *c);
+ void add_indent (int indent);
+ void finish_row (void);
+ int get_effective_linelength (void);
+
+ tabs *tab_stops; /* tab stop positions */
+private:
+ cols *columns; /* column entries */
+ simple_output *out;
+ int linelength;
+ cols *last_col; /* last column started */
+ int start_space; /* encapsulate with <p> </p> */
+
+ void remove_cols (cols *c);
+};
+
+/*
+ * the indentation wrapper.
+ * Builds an indentation from a html-table.
+ * This table is only emitted if the paragraph is emitted.
+ */
+
+class html_indent {
+public:
+ html_indent (simple_output *op, int ind, int pageoffset, int linelength);
+ ~html_indent (void);
+ void begin (int space); // called if we need to use the indent
+ void get_reg (int *ind, int *pageoffset, int *linelength);
+
+ // the indent is shutdown when it is deleted
+
+private:
+ void end (void);
+ int is_used;
+ int pg; // values of the registers as passed via initialization
+ int ll;
+ int in;
+ html_table *table;
+};
+
+#endif
diff --git a/contrib/groff/src/devices/grohtml/html-text.cc b/contrib/groff/src/devices/grohtml/html-text.cc
index 56d6c78..31e4311 100644
--- a/contrib/groff/src/devices/grohtml/html-text.cc
+++ b/contrib/groff/src/devices/grohtml/html-text.cc
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+/* Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
*
* Gaius Mulley (gaius@glam.ac.uk) wrote html-text.cc
*
@@ -40,10 +40,12 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#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)
+ current_indentation(-1), pageoffset(-1), linelength(-1),
+ blank_para(TRUE), start_space(FALSE)
{
}
@@ -52,6 +54,87 @@ 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.
*/
@@ -62,19 +145,21 @@ void html_text::end_tag (tag_definition *t)
case I_TAG: out->put_string("</i>"); break;
case B_TAG: out->put_string("</b>"); break;
- case P_TAG: out->put_string("</p>").nl().enable_newlines(FALSE); 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>");
- if (! is_present(TABLE_TAG)) {
- out->nl();
- out->enable_newlines(TRUE);
- }
- 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 TABLE_TAG: issue_table_end(); break;
+ case COLOR_TAG: out->put_string("</font>"); break;
default:
error("unrecognised tag");
@@ -99,6 +184,27 @@ void html_text::issue_tag (char *tagname, char *arg)
}
/*
+ * 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.
*/
@@ -106,60 +212,42 @@ void html_text::start_tag (tag_definition *t)
{
switch (t->type) {
- case I_TAG: issue_tag("<i", t->arg1); break;
- case B_TAG: issue_tag("<b", t->arg1); break;
- case P_TAG: issue_tag("\n<p", t->arg1);
+ 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", t->arg1); break;
- case SUP_TAG: issue_tag("<sup", t->arg1); break;
- case TT_TAG: issue_tag("<tt", t->arg1); break;
- case PRE_TAG: out->nl(); issue_tag("<pre", t->arg1);
+ 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", t->arg1); break;
- case BIG_TAG: issue_tag("<big", t->arg1); break;
- case TABLE_TAG: issue_table_begin(t); 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");
}
}
-int html_text::table_is_void (tag_definition *t)
-{
- if (linelength > 0) {
- return( current_indentation*100/linelength <= 0 );
- } else {
- return( FALSE );
- }
-}
-
-void html_text::issue_table_begin (tag_definition *t)
-{
- if (linelength > 0) {
- int width=current_indentation*100/linelength;
-
- if (width > 0) {
- out->put_string("<table width=\"100%\" border=0 rules=\"none\" frame=\"void\"\n cols=\"2\" cellspacing=\"0\" cellpadding=\"0\">").nl();
- out->put_string("<tr valign=\"top\" align=\"left\">").nl();
- if ((t->arg1 == 0) || (strcmp(t->arg1, "") == 0))
- out->put_string("<td width=\"").put_number(width).put_string("%\"></td>");
- else {
- out->put_string("<td width=\"").put_number(width).put_string("%\">").nl();
- out->put_string(t->arg1).put_string("</td>");
- t->arg1[0] = (char)0;
- }
- out->put_string("<td width=\"").put_number(100-width).put_string("%\">").nl();
- }
- }
-}
-
-void html_text::issue_table_end (void)
-{
- out->put_string("</td></table>").nl();
- out->enable_newlines(TRUE);
-}
-
/*
* flush_text - flushes html tags which are outstanding on the html stack.
*/
@@ -190,116 +278,94 @@ int html_text::is_present (HTML_TAG t)
tag_definition *p=stackptr;
while (p != NULL) {
- if (t == p->type) {
- return( TRUE );
- }
+ if (t == p->type)
+ return TRUE;
p = p->next;
}
- return( FALSE );
+ return FALSE;
}
+extern void stop();
+
/*
- * push_para - adds a new entry onto the html paragraph stack.
+ * do_push - places, tag_definition, p, onto the stack
*/
-void html_text::push_para (HTML_TAG t, char *arg)
+void html_text::do_push (tag_definition *p)
{
- tag_definition *p=(tag_definition *)malloc(sizeof(tag_definition));
+ HTML_TAG t = p->type;
- p->type = t;
- p->arg1 = arg;
- p->text_emitted = FALSE;
+#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 TABLE_TAG or PRE_TAG make sure it goes on the end of the stack.
- * But we insist that a TABLE_TAG is always after a PRE_TAG
- * and that a P_TAG is always after a TABLE_TAG
+ * 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) || (t == TABLE_TAG)) &&
- (lastptr != NULL)) {
- if (((lastptr->type == TABLE_TAG) && (t == PRE_TAG)) ||
- ((lastptr->type == P_TAG) && (t == TABLE_TAG))) {
- /*
- * insert p before the lastptr
- */
- if (stackptr == lastptr) {
- /*
- * only on element of the stack
- */
- p->next = stackptr;
- stackptr = p;
- } else {
- /*
- * more than one element is on the stack
- */
- tag_definition *q = stackptr;
-
- while (q->next != lastptr) {
- q = q->next;
- }
- q->next = p;
- p->next = lastptr;
- }
- } else {
- /*
- * store, p, at the end
- */
- lastptr->next = p;
- lastptr = p;
- p->next = NULL;
- }
+ 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
}
/*
- * 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.
+ * push_para - adds a new entry onto the html paragraph stack.
*/
-void html_text::do_indent (char *arg, int indent, int pageoff, int linelen)
+void html_text::push_para (HTML_TAG t, void *arg, html_indent *in)
{
- if ((current_indentation != -1) &&
- (pageoffset+current_indentation != indent+pageoff)) {
- /*
- * actual indentation of text has changed, we need to put
- * a table tag onto the stack.
- */
- do_table(arg);
- }
- current_indentation = indent;
- pageoffset = pageoff;
- linelength = linelen;
+ 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::do_table (char *arg)
+void html_text::push_para (HTML_TAG t)
{
- int in_pre = is_in_pre();
- // char *para_type = done_para();
- done_pre();
- shutdown(TABLE_TAG); // shutdown a previous table, if present
- remove_break();
- if (in_pre) {
- do_pre();
- }
- // do_para(para_type);
- push_para(TABLE_TAG, arg);
+ push_para(t, (void *)"", NULL);
}
-/*
- * done_table - terminates a possibly existing table.
- */
-
-void html_text::done_table (void)
+void html_text::push_para (color *c)
{
- shutdown(TABLE_TAG);
- space_emitted = TRUE;
+ 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);
}
/*
@@ -308,11 +374,8 @@ void html_text::done_table (void)
void html_text::do_italic (void)
{
- done_bold();
- done_tt();
- if (! is_present(I_TAG)) {
- push_para(I_TAG, "");
- }
+ if (! is_present(I_TAG))
+ push_para(I_TAG);
}
/*
@@ -321,11 +384,8 @@ void html_text::do_italic (void)
void html_text::do_bold (void)
{
- done_italic();
- done_tt();
- if (! is_present(B_TAG)) {
- push_para(B_TAG, "");
- }
+ if (! is_present(B_TAG))
+ push_para(B_TAG);
}
/*
@@ -334,11 +394,8 @@ void html_text::do_bold (void)
void html_text::do_tt (void)
{
- done_bold();
- done_italic();
- if ((! is_present(TT_TAG)) && (! is_present(PRE_TAG))) {
- push_para(TT_TAG, "");
- }
+ if ((! is_present(TT_TAG)) && (! is_present(PRE_TAG)))
+ push_para(TT_TAG);
}
/*
@@ -347,13 +404,15 @@ void html_text::do_tt (void)
void html_text::do_pre (void)
{
- done_bold();
- done_italic();
done_tt();
- (void)done_para();
- if (! is_present(PRE_TAG)) {
- push_para(PRE_TAG, "");
- }
+ 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();
}
/*
@@ -363,16 +422,26 @@ void html_text::do_pre (void)
int html_text::is_in_pre (void)
{
- return( is_present(PRE_TAG) );
+ 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);
}
/*
- * is_in_table - returns TRUE if we are currently within a table.
+ * done_color - shutdown an outstanding color tag, if it exists.
*/
-int html_text::is_in_table (void)
+void html_text::done_color (void)
{
- return( is_present(TABLE_TAG) );
+ shutdown(COLOR_TAG);
}
/*
@@ -388,6 +457,7 @@ char *html_text::shutdown (HTML_TAG t)
tag_definition *temp =NULL;
int notext =TRUE;
+ dump_stack();
while ((stackptr != NULL) && (stackptr->type != t)) {
notext = (notext && (! stackptr->text_emitted));
if (! notext) {
@@ -417,12 +487,14 @@ char *html_text::shutdown (HTML_TAG t)
end_tag(stackptr);
}
if (t == P_TAG) {
- arg = stackptr->arg1;
+ arg = (char *)stackptr->arg1;
}
p = stackptr;
stackptr = stackptr->next;
if (stackptr == NULL)
lastptr = NULL;
+ if (p->indent != NULL)
+ delete p->indent;
free(p);
}
@@ -430,13 +502,16 @@ char *html_text::shutdown (HTML_TAG t)
* and restore unaffected tags
*/
while (temp != NULL) {
- push_para(temp->type, temp->arg1);
+ 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 );
+ return arg;
}
/*
@@ -519,37 +594,9 @@ void html_text::done_big (void)
void html_text::check_emit_text (tag_definition *t)
{
if ((t != NULL) && (! t->text_emitted)) {
- /*
- * we peep and see whether there is a <p> before the <table>
- * in which case we skip the <p>
- */
- if (t->type == TABLE_TAG) {
- if (table_is_void(t)) {
- tag_definition *n = t->next;
- remove_def(t);
- check_emit_text(n);
- } else {
- /*
- * a table which will be emitted, is there a <p> succeeding it?
- */
- if ((t->next != NULL) &&
- (t->next->type == P_TAG) &&
- ((t->next->arg1 == 0) || strcmp(t->next->arg1, "") == 0)) {
- /*
- * yes skip the <p>
- */
- check_emit_text(t->next->next);
- } else {
- check_emit_text(t->next);
- }
- t->text_emitted = TRUE;
- start_tag(t);
- }
- } else {
- check_emit_text(t->next);
- t->text_emitted = TRUE;
- start_tag(t);
- }
+ check_emit_text(t->next);
+ t->text_emitted = TRUE;
+ start_tag(t);
}
}
@@ -557,7 +604,7 @@ void html_text::check_emit_text (tag_definition *t)
* do_emittext - tells the class that text was written during the current tag.
*/
-void html_text::do_emittext (char *s, int length)
+void html_text::do_emittext (const char *s, int length)
{
if ((! is_present(P_TAG)) && (! is_present(PRE_TAG)))
do_para("");
@@ -577,25 +624,47 @@ void html_text::do_emittext (char *s, int length)
}
out->put_string(s, length);
space_emitted = FALSE;
+ blank_para = FALSE;
}
/*
- * do_para- starts a new paragraph
+ * do_para - starts a new paragraph
*/
-void html_text::do_para (char *arg)
+void html_text::do_para (const char *arg, html_indent *in)
{
- done_pre();
if (! is_present(P_TAG)) {
- remove_sub_sup();
- if ((arg != 0) && (strcmp(arg, "") != 0)) {
- remove_tag(TABLE_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;
}
- push_para(P_TAG, arg);
+ 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.
*/
@@ -603,7 +672,27 @@ void html_text::do_para (char *arg)
char *html_text::done_para (void)
{
space_emitted = TRUE;
- return( shutdown(P_TAG) );
+ 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;
}
/*
@@ -613,11 +702,19 @@ char *html_text::done_para (void)
void html_text::do_space (void)
{
if (is_in_pre()) {
- do_emittext("", 0);
+ if (blank_para)
+ start_space = TRUE;
+ else {
+ do_emittext("", 0);
+ out->nl();
+ }
} else {
- do_para(done_para());
+ html_indent *i = remove_indent(P_TAG);
+
+ do_para(done_para(), i);
+ space_emitted = TRUE;
+ start_space = TRUE;
}
- space_emitted = TRUE;
}
/*
@@ -629,7 +726,7 @@ void html_text::do_break (void)
if (! is_present(PRE_TAG)) {
if (emitted_text()) {
if (! is_present(BREAK_TAG)) {
- push_para(BREAK_TAG, "");
+ push_para(BREAK_TAG);
}
}
}
@@ -654,7 +751,25 @@ void html_text::do_newline (void)
int html_text::emitted_text (void)
{
- return( ! space_emitted);
+ 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;
}
/*
@@ -758,9 +873,9 @@ int html_text::remove_break (void)
if (stackptr == NULL)
lastptr = NULL;
q = stackptr;
- } else if (l == 0) {
+ } else if (l == 0)
error("stack list pointers are wrong");
- } else {
+ else {
l->next = p->next;
q = p->next;
if (l->next == NULL)
@@ -772,13 +887,35 @@ int html_text::remove_break (void)
* now determine whether text was issued before <br>
*/
while (q != 0) {
- if (q->text_emitted) {
- return( TRUE );
- } else {
+ 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;
}
}
- return( FALSE );
}
/*
@@ -789,11 +926,10 @@ int html_text::remove_break (void)
void html_text::do_small (void)
{
- if (is_present(BIG_TAG)) {
+ if (is_present(BIG_TAG))
done_big();
- } else {
- push_para(SMALL_TAG, "");
- }
+ else
+ push_para(SMALL_TAG);
}
/*
@@ -802,11 +938,10 @@ void html_text::do_small (void)
void html_text::do_big (void)
{
- if (is_present(SMALL_TAG)) {
+ if (is_present(SMALL_TAG))
done_small();
- } else {
- push_para(BIG_TAG, "");
- }
+ else
+ push_para(BIG_TAG);
}
/*
@@ -815,7 +950,7 @@ void html_text::do_big (void)
void html_text::do_sup (void)
{
- push_para(SUP_TAG, "");
+ push_para(SUP_TAG);
}
/*
@@ -824,6 +959,6 @@ void html_text::do_sup (void)
void html_text::do_sub (void)
{
- push_para(SUB_TAG, "");
+ push_para(SUB_TAG);
}
diff --git a/contrib/groff/src/devices/grohtml/html-text.h b/contrib/groff/src/devices/grohtml/html-text.h
index 5bbcd43..c43cbda 100644
--- a/contrib/groff/src/devices/grohtml/html-text.h
+++ b/contrib/groff/src/devices/grohtml/html-text.h
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+/* Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
*
* Gaius Mulley (gaius@glam.ac.uk) wrote html-text.cc
*
@@ -26,18 +26,22 @@ 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 "html.h"
+#include "html-table.h"
/*
* html tags
*/
typedef enum {I_TAG, B_TAG, P_TAG, SUB_TAG, SUP_TAG, TT_TAG,
- PRE_TAG, SMALL_TAG, BIG_TAG, BREAK_TAG, TABLE_TAG} HTML_TAG;
+ PRE_TAG, SMALL_TAG, BIG_TAG, BREAK_TAG,
+ COLOR_TAG} HTML_TAG;
typedef struct tag_definition {
HTML_TAG type;
- char *arg1;
+ void *arg1;
int text_emitted;
+ color col;
+ html_indent *indent;
tag_definition *next;
} tag_definition ;
@@ -49,61 +53,73 @@ typedef struct tag_definition {
class html_text {
public:
- html_text (simple_output *op);
- ~html_text (void);
- void flush_text (void);
- void do_emittext (char *s, int length);
- void do_italic (void);
- void do_bold (void);
- void do_roman (void);
- void do_tt (void);
- void do_pre (void);
- void do_small (void);
- void do_big (void);
- void do_para (char *arg1);
- void do_sup (void);
- void do_sub (void);
- void do_space (void);
- void do_break (void);
- void do_newline (void);
- void do_table (char *arg);
- void done_bold (void);
- void done_italic (void);
- char *done_para (void);
- void done_sup (void);
- void done_sub (void);
- void done_tt (void);
- void done_pre (void);
- void done_small (void);
- void done_big (void);
- void do_indent (char *arg, int indent, int pageoff, int linelen);
- int emitted_text (void);
- void emit_space (void);
- int is_in_pre (void);
- void remove_tag (HTML_TAG tag);
- void remove_sub_sup (void);
- void done_table (void);
- int is_in_table (void);
+ html_text (simple_output *op);
+ ~html_text (void);
+ void flush_text (void);
+ void do_emittext (const char *s, int length);
+ void do_italic (void);
+ void do_bold (void);
+ void do_roman (void);
+ void do_tt (void);
+ void do_pre (void);
+ void do_small (void);
+ void do_big (void);
+ void do_para (const char *arg); // used for no indentation
+ void do_para (simple_output *op, const char *arg1,
+ int indentation, int pageoffset, int linelength);
+ void do_sup (void);
+ void do_sub (void);
+ void do_space (void);
+ void do_break (void);
+ void do_newline (void);
+ void do_table (const char *arg);
+ void done_bold (void);
+ void done_italic (void);
+ char *done_para (void);
+ void done_sup (void);
+ void done_sub (void);
+ void done_tt (void);
+ void done_pre (void);
+ void done_small (void);
+ void done_big (void);
+ void do_color (color *c);
+ void done_color (void);
+ int emitted_text (void);
+ int ever_emitted_text (void);
+ int starts_with_space (void);
+ void emit_space (void);
+ int is_in_pre (void);
+ void remove_tag (HTML_TAG tag);
+ void remove_sub_sup (void);
+ void remove_para_align (void);
private:
tag_definition *stackptr; /* the current paragraph state */
tag_definition *lastptr; /* the end of the stack */
simple_output *out;
- int space_emitted;
- int current_indentation; /* current .in value */
- int pageoffset; /* .po value */
- int linelength; /* current line length */
+ int space_emitted; /* just emitted a space? */
+ int current_indentation; /* current .in value */
+ int pageoffset; /* .po value */
+ int linelength; /* current line length */
+ int blank_para; /* have we ever written text? */
+ int start_space; /* does para start with a .sp */
+ html_indent *indent; /* our indent class */
- int is_present (HTML_TAG t);
- void end_tag (tag_definition *t);
- void start_tag (tag_definition *t);
- void push_para (HTML_TAG t, char *arg);
- char *shutdown (HTML_TAG t);
- void check_emit_text (tag_definition *t);
- int remove_break (void);
- void issue_tag (char *tagname, char *arg);
- void issue_table_begin (tag_definition *t);
- void issue_table_end (void);
- int table_is_void (tag_definition *t);
- void remove_def (tag_definition *t);
+ int is_present (HTML_TAG t);
+ void end_tag (tag_definition *t);
+ void start_tag (tag_definition *t);
+ void do_para (const char *arg, html_indent *in);
+ void push_para (HTML_TAG t);
+ void push_para (HTML_TAG t, void *arg, html_indent *in);
+ void push_para (color *c);
+ void do_push (tag_definition *p);
+ char *shutdown (HTML_TAG t);
+ void check_emit_text (tag_definition *t);
+ int remove_break (void);
+ void issue_tag (char *tagname, char *arg);
+ void issue_color_begin (color *c);
+ void remove_def (tag_definition *t);
+ html_indent *remove_indent (HTML_TAG tag);
+ void dump_stack_element (tag_definition *p);
+ void dump_stack (void);
};
diff --git a/contrib/groff/src/devices/grohtml/html.h b/contrib/groff/src/devices/grohtml/html.h
index 69b6e35..431647c 100644
--- a/contrib/groff/src/devices/grohtml/html.h
+++ b/contrib/groff/src/devices/grohtml/html.h
@@ -20,8 +20,6 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#if !defined(HTML_H)
# define HTML_H
-# undef DEBUGGING
-// # define DEBUGGING
/*
* class and structure needed to buffer words
@@ -53,6 +51,7 @@ public:
simple_output(FILE *, int max_line_length);
simple_output &put_string(const char *, int);
simple_output &put_string(const char *s);
+ simple_output &put_string(const string &s);
simple_output &put_troffps_char (const char *s);
simple_output &put_translated_string(const char *s);
simple_output &put_number(int);
diff --git a/contrib/groff/src/devices/grohtml/output.cc b/contrib/groff/src/devices/grohtml/output.cc
index 88ab7d6..67d5874 100644
--- a/contrib/groff/src/devices/grohtml/output.cc
+++ b/contrib/groff/src/devices/grohtml/output.cc
@@ -38,6 +38,9 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include <unistd.h>
#endif
+#undef DEBUGGING
+// #define DEBUGGING
+
#if !defined(TRUE)
# define TRUE (1==1)
#endif
@@ -45,6 +48,18 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
# 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
*/
@@ -88,7 +103,7 @@ int word_list::flush (FILE *f)
while (head != 0) {
t = head;
head = head->next;
- fputs(t->s, f);
+ FPUTS(t->s, f);
delete t;
}
head = 0;
@@ -146,7 +161,7 @@ simple_output &simple_output::copy_file(FILE *infp)
{
int c;
while ((c = getc(infp)) != EOF)
- putc(c, fp);
+ PUTC(c, fp);
return *this;
}
@@ -154,7 +169,7 @@ simple_output &simple_output::end_line()
{
flush_last_word();
if (col != 0) {
- putc('\n', fp);
+ PUTC('\n', fp);
col = 0;
}
return *this;
@@ -169,10 +184,10 @@ 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);
+ PUTC('\n', fp);
+ FPUTS("<!-- ", fp);
+ FPUTS(s, fp);
+ FPUTS(" -->\n", fp);
col = 0;
return *this;
}
@@ -181,7 +196,7 @@ simple_output &simple_output::begin_comment(const char *s)
{
flush_last_word();
if (col != 0)
- putc('\n', fp);
+ PUTC('\n', fp);
col = 0;
put_string("<!--");
space_or_newline();
@@ -205,7 +220,7 @@ simple_output &simple_output::end_comment()
simple_output &simple_output::check_newline(int n)
{
if ((col + n + last_word.get_length() + 1 > max_line_length) && (newlines)) {
- fputc('\n', fp);
+ FPUTC('\n', fp);
col = last_word.flush(fp);
}
return *this;
@@ -218,11 +233,8 @@ simple_output &simple_output::check_newline(int n)
simple_output &simple_output::space_or_newline (void)
{
-#if defined(DEBUGGING)
- fflush(fp); // just for testing
-#endif
if ((col + last_word.get_length() + 1 > max_line_length) && (newlines)) {
- fputc('\n', fp);
+ FPUTC('\n', fp);
if (last_word.get_length() > 0) {
col = last_word.flush(fp);
} else {
@@ -231,7 +243,7 @@ simple_output &simple_output::space_or_newline (void)
} else {
if (last_word.get_length() != 0) {
if (col > 0) {
- fputc(' ', fp);
+ FPUTC(' ', fp);
col++;
}
col += last_word.flush(fp);
@@ -250,7 +262,7 @@ simple_output &simple_output::nl (void)
space_or_newline();
col += last_word.flush(fp);
if (col != 0) {
- fputc('\n', fp);
+ FPUTC('\n', fp);
col = 0;
}
return *this ;
@@ -266,7 +278,7 @@ simple_output &simple_output::set_fixed_point(int n)
simple_output &simple_output::put_raw_char(char c)
{
col += last_word.flush(fp);
- putc(c, fp);
+ PUTC(c, fp);
col++;
return *this;
}
@@ -283,6 +295,12 @@ simple_output &simple_output::put_string(const char *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];
@@ -322,15 +340,15 @@ void simple_output::flush_last_word (void)
if (len > 0) {
if (newlines) {
if (col + len + 1 > max_line_length) {
- fputs("\n", fp);
+ FPUTS("\n", fp);
col = 0;
} else {
- fputs(" ", fp);
+ FPUTS(" ", fp);
col++;
}
len += last_word.flush(fp);
} else {
- fputs(" ", fp);
+ 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
index 0c36941..4431f17 100644
--- a/contrib/groff/src/devices/grohtml/post-html.cc
+++ b/contrib/groff/src/devices/grohtml/post-html.cc
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+/* 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
@@ -28,6 +28,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "cset.h"
#include "html.h"
#include "html-text.h"
+#include "html-table.h"
#include <time.h>
@@ -47,25 +48,26 @@ extern "C" const char *Version_string;
# define FALSE (1==0)
#endif
-#define MAX_STRING_LENGTH 4096
#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%d" /* if simple anchor is set we use this */
+#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; */
-#define INDENTATION /* #undef INDENTATION to remove .in handling */
-
typedef enum {CENTERED, LEFT, RIGHT, INLINE} TAG_ALIGNMENT;
+typedef enum {col_tag, tab_tag, tab0_tag, none} colType;
+
+#undef DEBUG_TABLES
+
/*
* prototypes
*/
-void str_translate_to_html (font *f, char *buf, int buflen, char *str, int len, int and_single);
-char *get_html_translation (font *f, const char *name);
+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 */
@@ -73,6 +75,9 @@ static int auto_links = TRUE; /* by default we enable aut
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? */
/*
@@ -83,41 +88,27 @@ void stop () {}
static int min (int a, int b)
{
- if (a < b) {
- return( a );
- } else {
- return( b );
- }
+ if (a < b)
+ return a;
+ else
+ return b;
}
static int max (int a, int b)
{
- if (a > b) {
- return( a );
- } else {
- return( b );
- }
+ if (a > b)
+ return a;
+ else
+ return b;
}
/*
- * is_subsection - returns TRUE if a1..a2 is within b1..b2
- */
-
-#if 0
-static int is_subsection (int a1, int a2, int b1, int b2)
-{
- // easier to see whether this is not the case
- return( !((a1 < b1) || (a1 > b2) || (a2 < b1) || (a2 > b2)) );
-}
-#endif
-
-/*
* is_intersection - returns TRUE if range a1..a2 intersects with b1..b2
*/
static int is_intersection (int a1, int a2, int b1, int b2)
{
- // again easier to prove NOT outside limits
+ // easier to prove NOT outside limits
return( ! ((a1 > b2) || (a2 < b1)) );
}
@@ -230,8 +221,9 @@ struct style {
int font_no;
int height;
int slant;
+ color col;
style ();
- style (font *, int, int, int, int);
+ style (font *, int, int, int, int, color);
int operator == (const style &) const;
int operator != (const style &) const;
};
@@ -241,15 +233,15 @@ style::style()
{
}
-style::style(font *p, int sz, int h, int sl, int no)
- : f(p), point_size(sz), font_no(no), height(h), slant(sl)
+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);
+ && height == s.height && slant == s.slant && col == s.col);
}
int style::operator!=(const style &s) const
@@ -263,23 +255,33 @@ int style::operator!=(const style &s) const
struct char_block {
enum { SIZE = 256 };
- char buffer[SIZE];
+ 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(char *, unsigned int);
+ char *add_string(const char *, unsigned int);
+ char *add_string(const string &);
private:
char_block *head;
char_block *tail;
@@ -299,24 +301,23 @@ char_buffer::~char_buffer()
}
}
-char *char_buffer::add_string (char *s, unsigned int length)
+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;
+ tail = new char_block(length+1);
head = tail;
} else {
if (tail->used + length+1 > char_block::SIZE) {
- tail->next = new char_block;
- tail = tail->next;
+ tail->next = new char_block(length+1);
+ tail = tail->next;
}
}
- // at this point we have a tail which is ready for the string.
- if (tail->used + length+1 > char_block::SIZE) {
- fatal("need to increase char_block::SIZE");
- }
old_used = tail->used;
do {
@@ -336,59 +337,196 @@ char *char_buffer::add_string (char *s, unsigned int length)
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:
- text_glob (style *s, char *string, unsigned int length,
- int min_vertical , int min_horizontal,
- int max_vertical , int max_horizontal,
- int is_html , int is_troff_command,
- int is_auto_image,
- int is_a_line , int thickness);
- text_glob (void);
- ~text_glob (void);
- int is_a_line (void);
- int is_a_tag (void);
- int is_raw (void);
- int is_eol (void);
- int is_auto_img (void);
- int is_br (void);
+ 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;
- char *text_string;
+ const char *text_string;
unsigned int text_length;
int minv, minh, maxv, maxh;
- int is_raw_command; // should the text be sent directly to the device?
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 *string, unsigned int length,
+text_glob::text_glob (style *s, char *str, int length,
int min_vertical, int min_horizontal,
int max_vertical, int max_horizontal,
- int is_html, int is_troff_command,
- int is_auto_image,
- int is_a_line, int line_thickness)
- : text_style(*s), text_string(string), text_length(length),
+ 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_raw_command(is_html), is_tag(is_troff_command), is_img_auto(is_auto_image),
- is_line(is_a_line), thickness(line_thickness)
+ 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_raw_command(FALSE), is_tag(FALSE), is_line(FALSE), thickness(0)
+ 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;
}
/*
@@ -397,7 +535,7 @@ text_glob::~text_glob ()
int text_glob::is_a_line (void)
{
- return( is_line );
+ return is_line;
}
/*
@@ -406,7 +544,7 @@ int text_glob::is_a_line (void)
int text_glob::is_a_tag (void)
{
- return( is_tag );
+ return is_tag;
}
/*
@@ -419,12 +557,121 @@ int text_glob::is_eol (void)
}
/*
- * is_raw - returns TRUE if glob contains raw html.
+ * 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_raw (void)
+int text_glob::is_po (void)
{
- return( is_raw_command );
+ 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) );
}
/*
@@ -434,16 +681,82 @@ int text_glob::is_raw (void)
int text_glob::is_auto_img (void)
{
- return( is_img_auto );
+ 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) );
+ 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;
}
/*
@@ -502,6 +815,8 @@ public:
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);
@@ -569,6 +884,7 @@ void list::add (text_glob *in, int line_number, int min_vertical, int min_horizo
if (head == 0) {
head = t;
tail = t;
+ ptr = t;
t->left = t;
t->right = t;
} else {
@@ -719,7 +1035,7 @@ text_glob* list::move_right_get_data (void)
/*
* move_left_get_data - returns the datum referenced via ptr and moves
- * ptr right.
+ * ptr right.
*/
text_glob* list::move_left_get_data (void)
@@ -733,21 +1049,55 @@ text_glob* list::move_left_get_data (void)
}
/*
+ * 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, char *string, unsigned int length,
+ void add (style *s, const string &str,
int line_number,
int min_vertical, int min_horizontal,
int max_vertical, int max_horizontal);
- void add_html (style *s, char *string, unsigned int length,
+ 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_tag (style *s, char *string, unsigned int length,
+ void add_and_encode (style *s, const string &str,
int line_number,
int min_vertical, int min_horizontal,
int max_vertical, int max_horizontal);
@@ -755,6 +1105,7 @@ public:
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
@@ -767,32 +1118,34 @@ page::page()
{
}
-void page::add (style *s, char *string, unsigned int length,
- int line_number,
- int min_vertical, int min_horizontal,
- int max_vertical, int max_horizontal)
+/*
+ * insert_tag - inserts a tag after the current position.
+ */
+
+void page::insert_tag (const string &str)
{
- if (length > 0) {
- text_glob *g=new text_glob(s, buffer.add_string(string, length), length,
- min_vertical, min_horizontal, max_vertical, max_horizontal,
- FALSE, FALSE, FALSE, FALSE, 0);
- glyphs.add(g, line_number, min_vertical, min_horizontal, max_vertical, max_horizontal);
+ 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_html - add a raw html command, for example mailto, line, background, image etc.
+ * add - add html text to the list of glyphs.
*/
-void page::add_html (style *s, char *string, unsigned int length,
- int line_number,
- int min_vertical, int min_horizontal,
- int max_vertical, int max_horizontal)
+void page::add (style *s, const string &str,
+ int line_number,
+ int min_vertical, int min_horizontal,
+ int max_vertical, int max_horizontal)
{
- if (length > 0) {
- text_glob *g=new text_glob(s, buffer.add_string(string, length), length,
- min_vertical, min_horizontal, max_vertical, max_horizontal,
- TRUE, FALSE, FALSE, FALSE, 0);
+ 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);
}
}
@@ -801,17 +1154,23 @@ void page::add_html (style *s, char *string, unsigned int length,
* add_tag - adds a troff tag, for example: .tl .sp .br
*/
-void page::add_tag (style *s, char *string, unsigned int length,
+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 (length > 0) {
- text_glob *g=new text_glob(s, buffer.add_string(string, length), length,
- min_vertical, min_horizontal, max_vertical, max_horizontal,
- FALSE, TRUE,
- (strncmp(string, "html-tag:.auto-image", 20) == 0),
- FALSE, 0);
+ 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);
}
}
@@ -826,29 +1185,115 @@ void page::add_line (style *s,
int thickness)
{
if (y1 == y2) {
- text_glob *g = new text_glob(s, "", 0,
- min(y1, y2), min(x1, y2), max(y1, y2), max(x1, x2),
- FALSE, TRUE, FALSE, FALSE, thickness);
+ 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
}
/*
@@ -895,12 +1340,13 @@ public:
int has_been_written;
int has_been_found;
- char text[MAX_STRING_LENGTH];
+ int with_h1;
+ string text;
};
title_desc::title_desc ()
- : has_been_written(FALSE), has_been_found(FALSE)
+ : has_been_written(FALSE), has_been_found(FALSE), with_h1(FALSE)
{
}
@@ -918,7 +1364,7 @@ public:
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?
- char header_buffer[MAX_STRING_LENGTH]; // current header text
+ string header_buffer; // current header text
void write_headings (FILE *f, int force);
};
@@ -948,9 +1394,13 @@ void header_desc::write_headings (FILE *f, int force)
do {
g = headers.get_data();
fputs("<a href=\"#", f);
- if (simple_anchors)
- fprintf(f, ANCHOR_TEMPLATE, h);
- else
+ 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);
@@ -968,16 +1418,18 @@ class html_printer : public printer {
simple_output html;
int res;
int space_char_index;
+ int space_width;
int no_of_printed_pages;
int paper_length;
- enum { SBUF_SIZE = 8192 };
- char sbuf[SBUF_SIZE];
- int sbuf_len;
+ 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;
@@ -986,21 +1438,22 @@ class html_printer : public printer {
int line_thickness;
int output_line_thickness;
unsigned char output_space_code;
- string defs;
char *inside_font_style;
int page_number;
title_desc title;
- title_desc indent; // use title class to remember $1 of .ip
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;
@@ -1008,6 +1461,7 @@ class html_printer : public printer {
int pointsize;
int vertical_spacing;
int line_number;
+ color *background;
void flush_sbuf ();
void set_style (const style &);
@@ -1020,19 +1474,15 @@ class html_printer : public printer {
void set_line_thickness (const environment *);
void terminate_current_font (void);
void flush_font (void);
- void add_char_to_sbuf (unsigned char code);
- void add_to_sbuf (unsigned char code, const char *name);
+ void add_to_sbuf (int index, const string &s);
void write_title (int in_head);
- void determine_diacritical_mark (const char *name, const environment *env);
- int sbuf_continuation (unsigned char code, const char *name, const environment *env, int w);
- char *remove_last_char_from_sbuf ();
- int seen_backwards_escape (char *s, int l);
+ 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 translate_to_html (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);
@@ -1043,6 +1493,7 @@ class html_printer : public printer {
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);
@@ -1067,19 +1518,42 @@ class html_printer : public printer {
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 ();
+ 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()
@@ -1092,7 +1566,7 @@ static void usage(FILE *stream);
void html_printer::set_style(const style &sty)
{
const char *fontname = sty.f->get_name();
- if (fontname == 0)
+ if (fontname == NULL)
fatal("no internalname specified for font");
#if 0
@@ -1100,6 +1574,33 @@ void html_printer::set_style(const style &sty)
#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();
@@ -1127,8 +1628,6 @@ void html_printer::emit_raw (text_glob *g)
determine_space(g);
current_paragraph->do_emittext(g->text_string, g->text_length);
} else {
- int in_table=current_paragraph->is_in_table();
-
current_paragraph->done_para();
switch (next_tag) {
@@ -1136,10 +1635,10 @@ void html_printer::emit_raw (text_glob *g)
current_paragraph->do_para("align=center");
break;
case LEFT:
- current_paragraph->do_para("align=left");
+ current_paragraph->do_para(&html, "align=left", indentation, pageoffset, linelength);
break;
case RIGHT:
- current_paragraph->do_para("align=right");
+ current_paragraph->do_para(&html, "align=right", indentation, pageoffset, linelength);
break;
default:
fatal("unknown enumeration");
@@ -1148,13 +1647,14 @@ void html_printer::emit_raw (text_glob *g)
current_paragraph->done_para();
next_tag = INLINE;
supress_sub_sup = TRUE;
-#if defined(INDENTATION)
- if (in_table) {
- stop();
- current_paragraph->do_indent(NULL, 0, pageoffset, linelength);
- current_paragraph->do_indent(indent.text, indentation, pageoffset, linelength);
+ if (indentation > 0) {
+ /*
+ * restore indentation
+ */
+ int newin = indentation;
+ indentation = 0;
+ do_indent(newin, pageoffset, linelength);
}
-#endif
}
}
@@ -1165,16 +1665,16 @@ void html_printer::emit_raw (text_glob *g)
void html_printer::do_center (char *arg)
{
int n = atoi(arg);
-
current_paragraph->do_break();
- current_paragraph->done_para();
- supress_sub_sup = TRUE;
-
+
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();
}
}
@@ -1229,23 +1729,16 @@ static int exists (const char *filename)
* providing that the image exists.
*/
-static char *generate_img_src (const char *filename)
+static string &generate_img_src (const char *filename)
{
- static char buffer[MAX_STRING_LENGTH];
+ string *s = new string("");
while (filename && (filename[0] == ' ')) {
filename++;
}
- if (exists(filename)) {
- strcpy(buffer, "<img src=\"");
- strncat(buffer, filename, MAX_STRING_LENGTH-strlen("<img src=\"")-1);
- if (strlen(buffer) < MAX_STRING_LENGTH-3) {
- strncat(buffer, "\">", 3);
- }
- return( (char *)&buffer );
- } else {
- return( 0 );
- }
+ if (exists(filename))
+ *s += string("<img src=\"") + filename + "\">";
+ return *s;
}
/*
@@ -1258,19 +1751,30 @@ static char *generate_img_src (const char *filename)
void html_printer::do_auto_image (text_glob *g, const char *filename)
{
- char *buffer = generate_img_src(filename);
+ string buffer = generate_img_src(filename);
- if (buffer) {
+ if (! buffer.empty()) {
/*
* utilize emit_raw by creating a new text_glob.
*/
text_glob h = *g;
- h.text_string = buffer;
- h.text_length = strlen(buffer);
+ h.text_string = buffer.contents();
+ h.text_length = buffer.length();
emit_raw(&h);
- } else {
+ } else
next_tag = INLINE;
+}
+
+/*
+ * outstanding_eol - call do_eol, n, times.
+ */
+
+void html_printer::outstanding_eol (int n)
+{
+ while (n > 0) {
+ do_eol();
+ n--;
}
}
@@ -1282,7 +1786,7 @@ void html_printer::do_title (void)
{
text_glob *t;
int removed_from_head;
- char buf[MAX_STRING_LENGTH];
+ int eol_ce = 0;
if (page_number == 1) {
int found_title_start = FALSE;
@@ -1292,44 +1796,43 @@ void html_printer::do_title (void)
t = page_contents->glyphs.get_data();
removed_from_head = FALSE;
if (t->is_auto_img()) {
- char *img=generate_img_src((char *)(t->text_string + 20));
+ string img = generate_img_src((char *)(t->text_string + 20));
- if (img) {
- if (found_title_start) {
- strcat(title.text, " ");
- }
+ if (! img.empty()) {
+ if (found_title_start)
+ title.text += " ";
found_title_start = TRUE;
title.has_been_found = TRUE;
- strcat(title.text, img);
+ 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_raw_command) {
- /* skip raw commands
+ } 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) {
- strcat(title.text, " ");
- str_translate_to_html(t->text_style.f, buf, MAX_STRING_LENGTH, t->text_string, t->text_length, TRUE);
- strcat(title.text, buf);
- 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()));
+ 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 {
- str_translate_to_html(t->text_style.f, buf, MAX_STRING_LENGTH, t->text_string, t->text_length, TRUE);
- strcpy((char *)title.text, buf);
+ 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 */
@@ -1338,20 +1841,19 @@ void html_printer::do_title (void)
}
} while ((! page_contents->glyphs.is_equal_to_head()) || (removed_from_head));
}
- // page_contents->glyphs.move_left(); /* move backwards to last word */
+ outstanding_eol(eol_ce);
}
}
void html_printer::write_header (void)
{
- if (strlen(header.header_buffer) > 0) {
+ 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();
- current_paragraph->done_table();
supress_sub_sup = TRUE;
if (cutoff_heading+2 > header.header_level) {
@@ -1359,12 +1861,13 @@ void html_printer::write_header (void)
header.no_of_headings++;
style st;
- text_glob *h=new text_glob(&st,
- header.headings.add_string(header.header_buffer, strlen(header.header_buffer)),
- strlen(header.header_buffer),
- header.no_of_headings, header.header_level,
- header.no_of_headings, header.header_level,
- FALSE, FALSE, FALSE, FALSE, FALSE);
+ 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,
@@ -1374,26 +1877,45 @@ void html_printer::write_header (void)
html.nl().put_string("<a name=\"");
if (simple_anchors) {
- char buffer[MAX_LINE_LENGTH];
+ string buffer(ANCHOR_TEMPLATE);
- sprintf(buffer, ANCHOR_TEMPLATE, header.no_of_headings);
- html.put_string(buffer);
+ 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();
}
- // 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();
+ 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("");
+ current_paragraph->do_para(&html, "", indentation, pageoffset, linelength);
}
}
@@ -1401,9 +1923,10 @@ void html_printer::determine_header_level (int level)
{
if (level == 0) {
int i;
- int l=strlen(header.header_buffer);
- for (i=0; ((i<l) && ((header.header_buffer[i] == '.') || is_digit(header.header_buffer[i]))) ; 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++;
}
@@ -1420,35 +1943,33 @@ void html_printer::do_heading (char *arg)
{
text_glob *g;
text_glob *l = 0;
- char buf[MAX_STRING_LENGTH];
int level=atoi(arg);
- strcpy(header.header_buffer, "");
+ 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()) {
- char *img=generate_img_src((char *)(g->text_string + 20));
+ string img=generate_img_src((char *)(g->text_string + 20));
- if (img) {
+ if (! img.empty()) {
simple_anchors = TRUE; // we cannot use full heading anchors with images
- if (l != 0) {
- strcat(header.header_buffer, " ");
- }
+ if (l != 0)
+ header.header_buffer += " ";
+
l = g;
- strcat(header.header_buffer, img);
+ header.header_buffer += img;
}
- } else if (! (g->is_a_line() || g->is_a_tag() || g->is_raw())) {
+ } else if (! (g->is_a_line() || g->is_a_tag())) {
/*
- * we ignore raw commands when constructing a heading
+ * we ignore tags commands when constructing a heading
*/
- if (l != 0) {
- strcat(header.header_buffer, " ");
- }
+ if (l != 0)
+ header.header_buffer += " ";
l = g;
- str_translate_to_html(g->text_style.f, buf, MAX_STRING_LENGTH, g->text_string, g->text_length, TRUE);
- strcat(header.header_buffer, (char *)buf);
+
+ header.header_buffer += string(g->text_string, g->text_length);
}
page_contents->glyphs.move_right();
g = page_contents->glyphs.get_data();
@@ -1478,22 +1999,20 @@ int html_printer::is_courier_until_eol (void)
page_contents->glyphs.move_right();
do {
g = page_contents->glyphs.get_data();
- if (! is_font_courier(g->text_style.f)) {
+ if (! g->is_a_tag() && (! is_font_courier(g->text_style.f)))
result = FALSE;
- }
page_contents->glyphs.move_right();
- } while ((result) &&
+ } while (result &&
(! page_contents->glyphs.is_equal_to_head()) &&
- (! g->is_eol()));
+ (! g->is_fi()) && (! g->is_eol()));
/*
* now restore our previous position.
*/
- while (page_contents->glyphs.get_data() != orig) {
+ while (page_contents->glyphs.get_data() != orig)
page_contents->glyphs.move_left();
- }
}
- return( result );
+ return result;
}
/*
@@ -1502,12 +2021,11 @@ int html_printer::is_courier_until_eol (void)
void html_printer::do_linelength (char *arg)
{
-#if defined(INDENTATION)
- if (fill_on) {
- linelength = atoi(arg);
- current_paragraph->do_indent(indent.text, indentation, pageoffset, linelength);
- }
-#endif
+ if (max_linelength == -1)
+ max_linelength = atoi(arg);
+
+ if (fill_on)
+ do_indent(indentation, pageoffset, atoi(arg));
}
/*
@@ -1516,12 +2034,8 @@ void html_printer::do_linelength (char *arg)
void html_printer::do_pageoffset (char *arg)
{
-#if defined(INDENTATION)
- pageoffset = atoi(arg);
- if (fill_on) {
- current_paragraph->do_indent(indent.text, indentation, pageoffset, linelength);
- }
-#endif
+ if (fill_on)
+ do_indent(indentation, atoi(arg), linelength);
}
/*
@@ -1530,12 +2044,8 @@ void html_printer::do_pageoffset (char *arg)
void html_printer::do_indentation (char *arg)
{
-#if defined(INDENTATION)
- if (fill_on) {
- indentation = atoi(arg);
- current_paragraph->do_indent(indent.text, indentation, pageoffset, linelength);
- }
-#endif
+ if (fill_on)
+ do_indent(atoi(arg), pageoffset, linelength);
}
/*
@@ -1544,81 +2054,47 @@ void html_printer::do_indentation (char *arg)
void html_printer::do_tempindent (char *arg)
{
-#if defined(INDENTATION)
if (fill_on) {
end_tempindent = 1;
prev_indent = indentation;
- indentation = atoi(arg);
- current_paragraph->do_indent(indent.text, indentation, pageoffset, linelength);
+ do_indent(atoi(arg), pageoffset, linelength);
}
-#endif
}
/*
- * do_indentedparagraph - handle the .ip tag, this buffers the next line
- * and passes this to text-text as the left hand
- * column table entry.
+ * shutdown_table - shuts down the current table.
*/
-void html_printer::do_indentedparagraph (void)
+void html_printer::shutdown_table (void)
{
-#if defined(INDENTATION)
- text_glob *t;
- int removed_from_head;
- char buf[MAX_STRING_LENGTH];
- int found_indent_start = FALSE;
+ 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;
+ }
+}
- indent.has_been_found = FALSE;
- indent.text[0] = (char)0;
+/*
+ * 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.
+ */
- 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()) {
- char *img=generate_img_src((char *)(t->text_string + 20));
-
- if (img) {
- if (found_indent_start) {
- strcat(indent.text, " ");
- }
- found_indent_start = TRUE;
- strcat(indent.text, img);
- }
- page_contents->glyphs.sub_move_right(); /* move onto next word */
- } else if (t->is_raw_command) {
- /* skip raw commands
- */
- page_contents->glyphs.sub_move_right(); /* move onto next word */
- } else if (t->is_a_tag() && (strncmp(t->text_string, "html-tag:.br", 12) == 0)) {
- /* end of indented para found, but move back so that we read this tag and process it
- */
- page_contents->glyphs.move_left(); /* move backwards to last word */
- indent.has_been_found = TRUE;
- return;
- } else if (t->is_a_tag()) {
- page_contents->glyphs.sub_move_right(); /* move onto next word */
- } else if (found_indent_start) {
- strcat(indent.text, " ");
- str_translate_to_html(t->text_style.f, buf, MAX_STRING_LENGTH, t->text_string, t->text_length, TRUE);
- strcat(indent.text, buf);
- 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 {
- str_translate_to_html(t->text_style.f, buf, MAX_STRING_LENGTH, t->text_string, t->text_length, TRUE);
- strcpy((char *)indent.text, buf);
- found_indent_start = TRUE;
- indent.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));
+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);
}
- // page_contents->glyphs.move_left(); /* move backwards to last word */
-#endif
}
/*
@@ -1650,13 +2126,12 @@ void html_printer::do_fill (int on)
supress_sub_sup = TRUE;
if (fill_on != on) {
- if (on) {
- current_paragraph->done_pre();
- } else {
+ if (on)
+ current_paragraph->do_para("");
+ else
current_paragraph->do_pre();
- }
+ fill_on = on;
}
- fill_on = on;
}
/*
@@ -1666,14 +2141,25 @@ void html_printer::do_fill (int on)
void html_printer::do_eol (void)
{
if (! fill_on) {
- current_paragraph->do_newline();
- current_paragraph->do_break();
+ 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) {
- current_paragraph->do_break();
- }
+ if (end_center > 1)
+ if (current_paragraph->emitted_text())
+ current_paragraph->do_break();
+
end_center--;
if (end_center == 0) {
current_paragraph->done_para();
@@ -1689,7 +2175,6 @@ void html_printer::do_eol (void)
void html_printer::do_flush (void)
{
current_paragraph->done_para();
- current_paragraph->done_table();
}
/*
@@ -1699,12 +2184,9 @@ void html_printer::do_flush (void)
void html_printer::do_links (void)
{
current_paragraph->done_para();
- current_paragraph->done_table();
auto_links = FALSE; /* from now on only emit under user request */
-#if !defined(DEBUGGING)
file_list.add_new_file(xtmpfile());
html.set_file(file_list.get_file());
-#endif
}
/*
@@ -1715,20 +2197,106 @@ void html_printer::do_links (void)
void html_printer::do_break (void)
{
current_paragraph->do_break();
-#if defined(INDENTATION)
if (end_tempindent > 0) {
end_tempindent--;
- if (end_tempindent == 0) {
- indentation = prev_indent;
- current_paragraph->do_indent(indent.text, indentation, pageoffset, linelength);
- }
+ if (end_tempindent == 0)
+ do_indent(prev_indent, pageoffset, linelength);
}
-#endif
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.
*/
@@ -1741,8 +2309,13 @@ void html_printer::troff_tag (text_glob *g)
if (g->is_eol()) {
do_eol();
+ } else if (g->is_eol_ce()) {
+ do_eol_ce();
} else if (strncmp(t, ".sp", 3) == 0) {
- current_paragraph->do_space();
+ 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();
@@ -1761,6 +2334,11 @@ void html_printer::troff_tag (text_glob *g)
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);
@@ -1784,10 +2362,25 @@ void html_printer::troff_tag (text_glob *g)
} else if (strncmp(t, ".vs", 3) == 0) {
char *a = (char *)t+3;
do_verticalspacing(a);
- } else if (strncmp(t, ".ip", 3) == 0) {
- do_indentedparagraph();
+ } 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();
}
}
@@ -1813,18 +2406,15 @@ void html_printer::flush_globs (void)
do {
g = page_contents->glyphs.get_data();
- if (strcmp(g->text_string, "XXXXXXX") == 0) {
+ if (strcmp(g->text_string, "XXXXXXX") == 0)
stop();
- }
- if (g->is_raw()) {
- emit_raw(g);
- } else if (g->is_a_tag()) {
+ if (g->is_a_tag()) {
troff_tag(g);
} else if (g->is_a_line()) {
emit_line(g);
} else {
- translate_to_html(g);
+ emit_html(g);
}
/*
* after processing the title (and removing it) the glyph list might be empty
@@ -1836,29 +2426,474 @@ void html_printer::flush_globs (void)
}
}
+/*
+ * 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();
+ page_contents->dump_page();
+ lookahead_for_tables();
+ page_contents->dump_page();
+
flush_globs();
current_paragraph->done_para();
- current_paragraph->done_table();
// 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 glyth is ajoining then no space emitted.
+ * If last glyph is ajoining then no space emitted.
*/
void html_printer::determine_space (text_glob *g)
{
if (current_paragraph->is_in_pre()) {
- int space_width = sbuf_style.f->get_space_width(sbuf_style.point_size);
/*
* .nf has been specified
*/
@@ -1902,7 +2937,16 @@ void html_printer::end_font (const char *fontname)
current_paragraph->done_italic();
} else if (strcmp(fontname, "CR") == 0) {
current_paragraph->done_tt();
- current_paragraph->done_pre();
+ } 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();
}
}
@@ -1928,6 +2972,25 @@ void html_printer::start_font (const char *fontname)
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();
}
}
@@ -1986,6 +3049,11 @@ void html_printer::do_font (text_glob *g)
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);
+ }
}
/*
@@ -2070,18 +3138,14 @@ void html_printer::do_sup_or_sub (text_glob *g)
}
/*
- * translate_to_html - translates a textual string into html text
+ * emit_html - write out the html text
*/
-void html_printer::translate_to_html (text_glob *g)
+void html_printer::emit_html (text_glob *g)
{
- char buf[MAX_STRING_LENGTH];
-
do_font(g);
determine_space(g);
- str_translate_to_html(g->text_style.f, buf, MAX_STRING_LENGTH,
- g->text_string, g->text_length, TRUE);
- current_paragraph->do_emittext(buf, strlen(buf));
+ current_paragraph->do_emittext(g->text_string, g->text_length);
output_vpos = g->minv;
output_hpos = g->maxh;
output_vpos_max = g->maxv;
@@ -2094,18 +3158,26 @@ void html_printer::translate_to_html (text_glob *g)
void html_printer::flush_sbuf()
{
- if (sbuf_len > 0) {
+ 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, sbuf_len,
+ 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;
- sbuf_len = 0;
+ last_sbuf_length = 0;
+ sbuf_prev_hpos = sbuf_end_hpos;
+ overstrike_detected = FALSE;
+ sbuf.clear();
}
}
@@ -2119,6 +3191,7 @@ 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,
@@ -2126,6 +3199,7 @@ void html_printer::draw(int code, int *p, int np, const environment *env)
} else {
error("2 arguments required for line");
}
+# endif
break;
case 't':
{
@@ -2143,125 +3217,30 @@ void html_printer::draw(int code, int *p, int np, const environment *env)
}
case 'P':
- // fall through
+ break;
case 'p':
- {
-#if 0
- if (np & 1) {
- error("even number of arguments required for polygon");
- break;
- }
- if (np == 0) {
- error("no arguments for polygon");
- break;
- }
- // firstly lets add our current position to polygon
- int oh=env->hpos;
- int ov=env->vpos;
- int i=0;
-
- while (i<np) {
- p[i+0] += oh;
- p[i+1] += ov;
- oh = p[i+0];
- ov = p[i+1];
- i += 2;
- }
- // now store polygon in page
- page_contents->add_polygon(code, np, p, env->hpos, env->vpos, env->size, fill);
-#endif
- }
break;
case 'E':
- // fall through
+ break;
case 'e':
-#if 0
- if (np != 2) {
- error("2 arguments required for ellipse");
- break;
- }
- page_contents->add_line(code,
- env->hpos, env->vpos-p[1]/2, env->hpos+p[0], env->vpos+p[1]/2,
- env->size, fill);
-#endif
break;
case 'C':
- // fill circle
-
+ break;
case 'c':
- {
-#if 0
- // troff adds an extra argument to C
- if (np != 1 && !(code == 'C' && np == 2)) {
- error("1 argument required for circle");
- break;
- }
- page_contents->add_line(code,
- env->hpos, env->vpos-p[0]/2, env->hpos+p[0], env->vpos+p[0]/2,
- env->size, fill);
-#endif
- }
break;
case 'a':
- {
-#if 0
- if (np == 4) {
- double c[2];
-
- if (adjust_arc_center(p, c)) {
- page_contents->add_arc('a', env->hpos, env->vpos, p, c, env->size, fill);
- } else {
- // a straignt line
- page_contents->add_line('l', env->hpos, env->vpos, p[0]+p[2], p[1]+p[3], env->size, fill);
- }
- } else {
- error("4 arguments required for arc");
- }
-#endif
- }
break;
case '~':
- {
-#if 0
- if (np & 1) {
- error("even number of arguments required for spline");
- break;
- }
- if (np == 0) {
- error("no arguments for spline");
- break;
- }
- // firstly lets add our current position to spline
- int oh=env->hpos;
- int ov=env->vpos;
- int i=0;
-
- while (i<np) {
- p[i+0] += oh;
- p[i+1] += ov;
- oh = p[i+0];
- ov = p[i+1];
- i += 2;
- }
- page_contents->add_spline('~', env->hpos, env->vpos, np, p, env->size, fill);
-#endif
- }
break;
case 'f':
- {
-#if 0
- if (np != 1 && np != 2) {
- error("1 argument required for fill");
- break;
- }
- fill = p[0];
- if (fill < 0 || fill > FILL_MAX) {
- // This means fill with the current color.
- fill = FILL_MAX + 1;
- }
-#endif
- break;
- }
+ 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));
@@ -2272,7 +3251,8 @@ void html_printer::draw(int code, int *p, int np, const environment *env)
html_printer::html_printer()
: html(0, MAX_LINE_LENGTH),
no_of_printed_pages(0),
- sbuf_len(0),
+ last_sbuf_length(0),
+ overstrike_detected(FALSE),
output_hpos(-1),
output_vpos(-1),
output_vpos_max(-1),
@@ -2282,21 +3262,22 @@ html_printer::html_printer()
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),
- line_number(0)
+ pointsize(0),
+ line_number(0),
+ background(default_background)
{
-#if defined(DEBUGGING)
- file_list.add_new_file(stdout);
-#else
file_list.add_new_file(xtmpfile());
-#endif
html.set_file(file_list.get_file());
if (font::hor != 24)
fatal("horizontal resolution must be 24");
@@ -2316,6 +3297,7 @@ html_printer::html_printer()
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)
@@ -2325,174 +3307,65 @@ html_printer::html_printer()
}
/*
- * add_char_to_sbuf - adds a single character to the sbuf.
- */
-
-void html_printer::add_char_to_sbuf (unsigned char code)
-{
- if (sbuf_len < SBUF_SIZE) {
- sbuf[sbuf_len] = code;
- sbuf_len++;
- } else {
- fatal("need to increase SBUF_SIZE");
- }
-}
-
-/*
* add_to_sbuf - adds character code or name to the sbuf.
*/
-void html_printer::add_to_sbuf (unsigned char code, const char *name)
+void html_printer::add_to_sbuf (int index, const string &s)
{
- if (name == 0) {
- add_char_to_sbuf(code);
- } else {
- if (sbuf_style.f != NULL) {
- char *html_glyph = get_html_translation(sbuf_style.f, name);
+ if (sbuf_style.f == NULL)
+ return;
- if (html_glyph == NULL) {
- add_char_to_sbuf(code);
- } else {
- int l = strlen(html_glyph);
- int i;
+ char *html_glyph = NULL;
+ unsigned int code = sbuf_style.f->get_code(index);
- // Escape the name, so that "&" doesn't get expanded to "&amp;"
- // later during translate_to_html.
- add_char_to_sbuf('\\'); add_char_to_sbuf('(');
+ 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);
- for (i=0; i<l; i++) {
- add_char_to_sbuf(html_glyph[i]);
- }
- add_char_to_sbuf('\\'); add_char_to_sbuf(')');
- }
- }
- }
+ last_sbuf_length = sbuf.length();
+ if (html_glyph == NULL)
+ sbuf += ((char)code);
+ else
+ sbuf += html_glyph;
}
-int html_printer::sbuf_continuation (unsigned char code, const char *name,
+int html_printer::sbuf_continuation (int index, const char *name,
const environment *env, int w)
{
- if (sbuf_end_hpos == env->hpos) {
- add_to_sbuf(code, name);
+ /*
+ * 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 );
+ return TRUE;
} else {
- if ((sbuf_len < SBUF_SIZE-1) && (env->hpos >= sbuf_end_hpos) &&
+ 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
*/
- int space_width = sbuf_style.f->get_space_width(sbuf_style.point_size);
- if (env->hpos-sbuf_end_hpos < space_width/2) {
- add_to_sbuf(code, name);
+ 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 TRUE;
}
}
}
- return( FALSE );
-}
-
-/*
- * seen_backwards_escape - returns TRUE if we can see a escape at position i..l in s
- */
-
-int html_printer::seen_backwards_escape (char *s, int l)
-{
- /*
- * this is tricky so it is broken into components for clarity
- * (we let the compiler put in all back into a complex expression)
- */
- if ((l>0) && (sbuf[l] == '(') && (sbuf[l-1] == '\\')) {
- /*
- * ok seen '\(' but we must now check for '\\('
- */
- if ((l>1) && (sbuf[l-2] == '\\')) {
- /*
- * escaped the escape
- */
- return( FALSE );
- } else {
- return( TRUE );
- }
- } else {
- return( FALSE );
- }
-}
-
-/*
- * reverse - return reversed string.
- */
-
-char *reverse (char *s)
-{
- int i=0;
- int j=strlen(s)-1;
- char t;
-
- while (i<j) {
- t = s[i];
- s[i] = s[j];
- s[j] = t;
- i++;
- j--;
- }
- return( s );
-}
-
-/*
- * remove_last_char_from_sbuf - removes the last character from sbuf.
- */
-
-char *html_printer::remove_last_char_from_sbuf ()
-{
- int l=sbuf_len;
- static char last[MAX_STRING_LENGTH];
-
- if (l>0) {
- l--;
- if ((sbuf[l] == ')') && (l>0) && (sbuf[l-1] == '\\')) {
- /*
- * found terminating escape
- */
- int i=0;
-
- l -= 2;
- while ((l>0) && (! seen_backwards_escape(sbuf, l))) {
- if (sbuf[l] == '\\') {
- if (sbuf[l-1] == '\\') {
- last[i] = sbuf[l];
- i++;
- l--;
- }
- } else {
- last[i] = sbuf[l];
- i++;
- }
- l--;
- }
- last[i] = (char)0;
- sbuf_len = l;
- if (seen_backwards_escape(sbuf, l)) {
- sbuf_len--;
- }
- return( reverse(last) );
- } else {
- if ((sbuf[l] == '\\') && (l>0) && (sbuf[l-1] == '\\')) {
- l -= 2;
- sbuf_len = l;
- return( "\\" );
- } else {
- sbuf_len--;
- last[0] = sbuf[sbuf_len];
- last[1] = (char)0;
- return( last );
- }
- }
- } else {
- return( NULL );
- }
+ return FALSE ;
}
/*
@@ -2500,149 +3373,57 @@ char *html_printer::remove_last_char_from_sbuf ()
* return the device encoding for such character.
*/
-char *get_html_translation (font *f, const char *name)
+char *get_html_translation (font *f, const string &name)
{
- int index;
+ int index;
- if ((f == 0) || (name == 0) || (strcmp(name, "") == 0)) {
- return( NULL );
- } else {
- index = f->name_to_index((char *)name);
+ 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);
- return( NULL );
- } else {
- if (f->contains(index)) {
- return( (char *)f->get_special_device_encoding(index) );
- } else {
- return( NULL );
- }
- }
+ 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;
}
}
/*
- * to_unicode - returns a unicode translation of char, ch.
- */
-
-static char *to_unicode (unsigned char ch)
-{
- static char buf[20];
-
- sprintf(buf, "&#%u;", (unsigned int)ch);
- return( buf );
-}
-
-/*
- * char_translate_to_html - convert a single non escaped character
- * into the appropriate html character.
+ * 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 char_translate_to_html (font *f, char *buf, int buflen, unsigned char ch, int b, int and_single)
+int html_printer::overstrike(int index, const char *name, const environment *env, int w)
{
- if (and_single) {
- int t, l;
- char *translation;
- char name[2];
-
- name[0] = ch;
- name[1] = (char)0;
- translation = get_html_translation(f, name);
- if ((translation == NULL) && (ch >= UNICODE_DESC_START)) {
- translation = to_unicode(ch);
- }
- if (translation) {
- l = strlen(translation);
- t = max(0, min(l, buflen-b));
- strncpy(&buf[b], translation, t);
- b += t;
- } else {
- if (b<buflen) {
- buf[b] = ch;
- b++;
- }
- }
- } else {
+ if ((env->hpos < sbuf_end_hpos)
+ || ((sbuf_kern != 0) && (sbuf_end_hpos - sbuf_kern < env->hpos))) {
/*
- * do not attempt to encode single characters
+ * at this point we have detected an overlap
*/
- if (b<buflen) {
- buf[b] = ch;
- b++;
- }
- }
- return( b );
-}
-
-/*
- * str_translate_to_html - converts a string, str, into html text. It places
- * the output input buffer, buf. It truncates string, str, if
- * there is not enough space in buf.
- * It looks up the html character encoding of single characters
- * if, and_single, is TRUE. Characters such as < > & etc.
- */
-
-void str_translate_to_html (font *f, char *buf, int buflen, char *str, int len, int and_single)
-{
- char *translation;
- int e;
- char escaped_char[MAX_STRING_LENGTH];
- int l;
- int i=0;
- int b=0;
- int t=0;
-
-#if 0
- if (strcmp(str, "``@,;:\\\\()[]''") == 0) {
- stop();
- }
-#endif
- while (str[i] != (char)0) {
- if ((str[i]=='\\') && (i+1<len)) {
- i++; // skip the leading backslash
- if (str[i] == '(') {
- // start of escape
- i++;
- e = 0;
- while ((str[i] != (char)0) &&
- (! ((str[i] == '\\') && (i+1<len) && (str[i+1] == ')')))) {
- if (str[i] == '\\') {
- i++;
- }
- escaped_char[e] = str[i];
- e++;
- i++;
- }
- if ((str[i] == '\\') && (i+1<len) && (str[i+1] == ')')) {
- i += 2;
- }
- escaped_char[e] = (char)0;
- if (e > 0) {
- translation = get_html_translation(f, escaped_char);
- if (translation) {
- l = strlen(translation);
- t = max(0, min(l, buflen-b));
- strncpy(&buf[b], translation, t);
- b += t;
- } else {
- int index=f->name_to_index(escaped_char);
-
- if (f->contains(index) && (index != 0)) {
- buf[b] = f->get_code(index);
- b++;
- }
- }
- }
- } else {
- b = char_translate_to_html(f, buf, buflen, str[i], b, and_single);
- i++;
- }
+ 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 {
- b = char_translate_to_html(f, buf, buflen, str[i], b, and_single);
- i++;
+ /* 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;
}
}
- buf[min(b, buflen)] = (char)0;
+ return FALSE ;
}
/*
@@ -2652,33 +3433,25 @@ void str_translate_to_html (font *f, char *buf, int buflen, char *str, int len,
void html_printer::set_char(int i, font *f, const environment *env, int w, const char *name)
{
- unsigned char code = f->get_code(i);
-
-#if 0
- if (code == ' ') {
- stop();
- }
-#endif
- style sty(f, env->size, env->height, env->slant, env->fontno);
+ 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_len > 0) && (sbuf_len < SBUF_SIZE) && (sty == sbuf_style) &&
- (sbuf_vpos == env->vpos) && (sbuf_continuation(code, name, env, w))) {
+ if (((! sbuf.empty()) && (sty == sbuf_style) && (sbuf_vpos == env->vpos))
+ && (sbuf_continuation(i, name, env, w) || overstrike(i, name, env, w)))
return;
- } else {
- flush_sbuf();
- sbuf_len = 0;
- add_to_sbuf(code, name);
- sbuf_end_hpos = env->hpos + w;
- sbuf_start_hpos = env->hpos;
- sbuf_vpos = env->vpos;
- sbuf_style = sty;
- sbuf_kern = 0;
- }
+
+ 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;
}
/*
@@ -2694,9 +3467,11 @@ void html_printer::write_title (int in_head)
html.put_string("</title>").nl().nl();
} else {
title.has_been_written = TRUE;
- html.put_string("<h1 align=center>");
- html.put_string(title.text);
- html.put_string("</h1>").nl().nl();
+ 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'
@@ -2731,9 +3506,7 @@ void html_printer::begin_page(int n)
output_vpos = -1;
output_vpos_max = -1;
current_paragraph = new html_text(&html);
-#if defined(INDENTATION)
- current_paragraph->do_indent(indent.text, indentation, pageoffset, linelength);
-#endif
+ do_indent(indentation, pageoffset, linelength);
current_paragraph->do_para("");
}
@@ -2748,47 +3521,62 @@ 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, so for the moment I'll leave this commented out.
- * If requested we could always emit it if a command line switch
- * was present.
- *
- * fputs("<!doctype html public \"-//IETF//DTD HTML 4.0//EN\">\n", stdout);
+ * 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);
- fputs("<body>\n\n", stdout);
+ do_body();
+
write_title(FALSE);
header.write_headings(stdout, FALSE);
write_rule();
- {
- html.begin_comment("Creator : ")
- .put_string("groff ")
- .put_string("version ")
- .put_string(Version_string)
- .end_comment();
- }
- {
-#ifdef LONG_FOR_TIME_T
- long
-#else
- time_t
-#endif
- t = time(0);
- html.begin_comment("CreationDate: ")
- .put_string(ctime(&t), strlen(ctime(&t))-1)
- .end_comment();
- }
#if defined(DEBUGGING)
html.begin_comment("Total number of pages: ").put_string(i_to_a(no_of_printed_pages)).end_comment();
#endif
@@ -2825,13 +3613,13 @@ void html_printer::special(char *s, const environment *env, char type)
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);
+ 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 */
- char buf[MAX_STRING_LENGTH];
font *f=sbuf_style.f;
if (f == NULL) {
@@ -2839,28 +3627,26 @@ void html_printer::special(char *s, const environment *env, char type)
f = font::load_font("TR", &found);
}
- str_translate_to_html(f, buf, MAX_STRING_LENGTH,
- &s[5], strlen(s)-5, FALSE);
/*
* need to pass rest of string through to html output during flush
*/
- page_contents->add_html(&sbuf_style, buf, strlen(buf),
- line_number,
- env->vpos-env->size*r/72, env->hpos,
- env->vpos , env->hpos);
+ 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 width.
+ * 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, s, strlen(s),
+ page_contents->add_tag(&sbuf_style, string(s),
line_number,
env->vpos-env->size*r/72, env->hpos,
env->vpos , env->hpos);
@@ -2879,15 +3665,24 @@ int main(int argc, char **argv)
{ "version", no_argument, 0, 'v' },
{ NULL, 0, 0, 0 }
};
- while ((c = getopt_long(argc, argv, "o:i:I:D:F:vd?lrn", long_options, NULL))
+ 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;
- }
+ 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;
@@ -2897,9 +3692,19 @@ int main(int argc, char **argv)
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;
@@ -2935,6 +3740,6 @@ int main(int argc, char **argv)
static void usage(FILE *stream)
{
- fprintf(stream, "usage: %s [-vld?n] [-D dir] [-I image_stem] [-F dir] [files ...]\n",
+ fprintf(stream, "usage: %s [-vblnh] [-D dir] [-I image_stem] [-F dir] [files ...]\n",
program_name);
}
diff --git a/contrib/groff/src/devices/grolbp/Makefile.sub b/contrib/groff/src/devices/grolbp/Makefile.sub
index d60008b..d8000d1 100644
--- a/contrib/groff/src/devices/grolbp/Makefile.sub
+++ b/contrib/groff/src/devices/grolbp/Makefile.sub
@@ -1,6 +1,6 @@
-PROG=grolbp
+PROG=grolbp$(EXEEXT)
MAN1=grolbp.n
XLIBS=$(LIBDRIVER) $(LIBGROFF)
MLIB=$(LIBM)
-OBJS=lbp.o
+OBJS=lbp.$(OBJEXT)
CCSRCS=$(srcdir)/lbp.cc
diff --git a/contrib/groff/src/devices/grolbp/grolbp.man b/contrib/groff/src/devices/grolbp/grolbp.man
index d567c1a..6685c4f 100644
--- a/contrib/groff/src/devices/grolbp/grolbp.man
+++ b/contrib/groff/src/devices/grolbp/grolbp.man
@@ -3,7 +3,7 @@
.\" vim: set syntax=nroff :
.\" The above line should set vim into nroff mode
.ig
-Copyright (C) 1994-2000 Free Software Foundation, Inc.
+Copyright (C) 1994-2000, 2002 Free Software Foundation, Inc.
Permission is granted to make and distribute verbatim copies of
this manual provided the copyright notice and this permission notice
@@ -35,11 +35,14 @@ program.
.el .TP "\\$1"
..
.TH GROLBP @MAN1EXT@ "@MDATE@" "Groff Version @VERSION@"
+.
.SH NAME
grolbp \- groff driver for Canon CAPSL printers (LBP-4 and LBP-8 series laser printers).
+.
.SH SYNOPSIS
.nr a \n(.j
.ad l
+.nh
.nr i \n(.i
.in +\w'\fBgrolbp 'u
.ti \niu
@@ -58,6 +61,8 @@ grolbp \- groff driver for Canon CAPSL printers (LBP-4 and LBP-8 series laser pr
.OP \-\-papersize= paper_size
.OP \-o orientation
.OP \-\-orientation= orientation
+.OP \-w width
+.OP \-\-linewidth= width
.OP \-F dir
.OP \-\-fontdir= dir
.OP \-h
@@ -65,6 +70,8 @@ grolbp \- groff driver for Canon CAPSL printers (LBP-4 and LBP-8 series laser pr
.RI "[\ " files\|.\|.\|. "\ ]"
.br
.ad \na
+.hy
+.
.SH DESCRIPTION
.B grolbp
is a driver for
@@ -111,6 +118,14 @@ Print the document with
.I orientation
orientation, which must be `portrait' or `landscape'.
.TP
+.BI \-w width
+.TQ
+.BI \-\-linewidth= width
+Set the default line thickness to
+.I width
+thousandths of an em.
+If this option isn't specified, the line thickness defaults to 0.04\~em.
+.TP
.B \-v
.TQ
.B \-\-version
@@ -120,8 +135,11 @@ Print the version number.
.TQ
.BI \-\-fontdir= dir
Prepend directory
-.IB dir /devlbp
-to the search path for font and device description files.
+.IB dir /dev name
+to the search path for font and device description files;
+.I name
+is the name of the device, usually
+.BR lbp .
.TP
.B \-h
.TQ
@@ -160,74 +178,35 @@ precedence over the contents of the
.B DESC
file (this applies to the page orientation too).
.PP
-To set the paper size in the
-.B DESC
-file, insert in that file a line containing
-.B papersize
-.IR desired_papersize ,
-where
-.I desired_papersize
-is:
-.IP \(bu 4
-One of the recognized paper sizes: `a4', `letter', `legal' or `executive'.
-.IP \(bu 4
-A custom defined paper size, as described in the
-.B CUSTOM PAPER SIZES
-subsection below.
-.IP \(bu 4
-The name of a file (e.g.
-.IR /etc/papersize )
-whose first line must be the desired paper size in one of the above formats.
-.PP
-If there are various papersize lines in the
+See
+.BR groff_font (@MAN1EXT@)
+how to set the paper dimensions in the
.B DESC
-file, only the first valid one is used.
+file.
.PP
To set the paper size in the command line, add
.sp 1
.in +2m
-.BI \-p \ desired_papersize
+.BI \-p \ paper-size
.in -2m
.sp 1
or
.sp 1
.in +2m
-.BI \-\-papersize= desired_papersize
+.BI \-\-papersize= paper-size
.in -2m
.sp 1
to the other
.B grolbp
options, where
-.B desired_papersize
+.I paper-size
is in the same format as in the
.B DESC
file.
.PP
-Paper sizes are case insensitive (i.e., `A4' is the same as `a4').
-.PP
If no paper size is specified in the
.B DESC
file or the command line, a default size of A4 is used.
-.TP
-.SH CUSTOM PAPER SIZES
-Custom defined paper sizes are in the form
-.BI cust length x width
-where
-.I length
-and
-.I width
-are the dimensions of the paper you want to to use, specified in printer
-units (1/300 of an inch).
-For instance, to print in a postcard sized paper which is two inches long
-and four inches wide you can insert a line containing
-.sp 1
-.in +2m
-.B papersize cust600x1200
-.in -2m
-.sp 1
-at the beginning of the
-.B DESC
-file.
.SH PAGE ORIENTATION
As with the page size, the orientation of the printed page
.RB ( portrait
@@ -247,7 +226,7 @@ file, insert a line with the following content:
.RB [ portrait | landscape ]
.in -2m
.sp 1
-As with paper sizes, only the first valid orientation command in the
+Only the first valid orientation command in the
.B DESC
file is used.
.PP
diff --git a/contrib/groff/src/devices/grolbp/lbp.cc b/contrib/groff/src/devices/grolbp/lbp.cc
index ec8c7b1..76db32a 100644
--- a/contrib/groff/src/devices/grolbp/lbp.cc
+++ b/contrib/groff/src/devices/grolbp/lbp.cc
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 1994, 2000, 2001 Free Software Foundation, Inc.
+/* 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.
@@ -30,16 +30,22 @@ TODO
#include "driver.h"
#include "lbp.h"
#include "charset.h"
+#include "paper.h"
#include "nonposix.h"
extern "C" const char *Version_string;
-static short int papersize = -1, // papersize
- orientation = -1 , // orientation
- paperlength = 0, // Custom Paper size
- paperwidth = 0,
- ncopies = 1; // Number of copies
+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:
@@ -55,7 +61,7 @@ private:
class lbp_printer : public printer {
public:
- lbp_printer();
+ 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);
@@ -64,7 +70,7 @@ public:
font *make_font(const char *);
void end_of_line();
private:
- void set_line_thickness(int size, int dot = 0);
+ 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);
@@ -79,38 +85,27 @@ private:
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
+// 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;
-
-};
+ p = strtok(*pcadena, delim);
+ *pcadena = strtok(NULL, delim);
+ return p;
+}
#endif
-#ifndef HAVE_STRDUP
-// Ditto with OS/390 and strdup
-static char *strdup(const char *s)
-{
- char *result;
-
- result = (char *)malloc(strlen(s)+1);
- if (result != NULL) strcpy(result,s);
- return result;
-
-}; // strdup
-
-#endif
lbp_font::lbp_font(const char *nm)
: font(nm)
{
@@ -124,12 +119,12 @@ 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
+ f->is_scalable = 1; // Default is that fonts are scalable
if (!f->load()) {
- delete f;
- return 0;
- }
- return f;
+ delete f;
+ return 0;
+ }
+ return f;
}
@@ -138,64 +133,75 @@ void lbp_font::handle_unknown_font_command(const char *command,
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 Recongnize bitmaped fonts by the first character of it's name
- if (arg[0] == 'N') this->is_scalable = 0;
- // fprintf(stderr,"Loading font \"%s\" \n",arg);
- }; // if (strcmp(command, "lbpname")
- // fprintf(stderr,"Loading font %s \"%s\" in %s at %d\n",command,arg,filename,lineno);
-};
+ 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]);
+ for (i = 0; i < sizeof(symset); i++)
+ lbpputc(symset[i]);
lbpputs("\033[100;0 D");
- return ;
-};
+ return;
+}
-lbp_printer::lbp_printer()
+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),
- line_thickness(-1)
+ req_linethickness(-1)
{
#ifdef SET_BINARY
- SET_BINARY(fileno(stdout));
+ 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
- if (papersize < 0) papersize = 14; // Default paper size is A4
- 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;
-};
+ 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()
{
@@ -209,460 +215,415 @@ void lbp_printer::begin_page(int)
void lbp_printer::end_page(int)
{
- if (vdminited()) vdmflush();
+ if (vdminited())
+ vdmflush();
lbpputc('\f');
cur_hpos = -1;
}
void lbp_printer::end_of_line()
{
- cur_hpos = -1; // force absolute motion
+ 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.
-// nam[strlen(f->lbpname)-2]; // The font name without other data.
- int cpi; // The font size in characters per inch
- // (Bitmaped fonts are monospaced).
-
-
- /* Bitmap font selection is ugly in this printer, so don't expect
- this function to be elegant. */
-
+ 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 avaiable 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 were only two bitmaped fonts shiped with the printer.
- if (!strcasecmp(nam,"courier"))
- { // Courier font
- if (siz >= 12) cpi = 10;
- else cpi = 17;
- };
- if (!strcasecmp(nam,"elite"))
- { // Elite font
- if (siz >= 10) cpi = 12;
- else cpi = 17;
- };
-
+ 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);
+ sprintf(bfont_name, "%c%s%d", ori, nam, cpi);
else
- sprintf(bfont_name,"%c%s%d%c",ori,nam,cpi,type);
-
+ sprintf(bfont_name, "%c%s%d%c", ori, nam, cpi, type);
return bfont_name;
-
-}; // lbp_printer::font_name
+}
-void lbp_printer::set_char(int index, font *f, const environment *env, int w, const char *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*300)/72));
- } else
- { // Bitmaped font
- lbpprintf("\033Pz%s.IBML\033\\\n",font_name(psf,env->size));
- };
- lbpputs("\033)' 1"); // Select IBML and IBMR1 symbol set
- cur_size = env->size;
+ // 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*300)/72));
- }; // if ( cur_symbol_set == 3 )
+ 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*300)/72));
- lbpputs("\033(\"!!0\033)\"!!1"); // Select symbol font
- break;
- case 4: lbpputs("\033)\"! 1\033(\"!$2"); // Select PS symbol set
- break;
- }; // switch (symbol_set)
-
-// if (symbol_set == 1) lbpputs("\033(d"); // Select wp54 symbol set
-// else lbpputs("\033('$2\033)' 1"); // Select IBML and IBMR1 symbol sets
+ 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));
+ lbpprintf("\033Pz%s.IBML\033\\\n", font_name(cur_font, env->size));
else
- lbpprintf("\033[%d C",(int)((env->size*300)/72));
+ 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");
+ 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()
+void lbp_printer::vdmstart()
{
FILE *f;
static int changed_origin = 0;
-
- errno = 0;
- f = tmpfile();
- // f = fopen("/tmp/gtmp","w+");
- if (f == NULL) perror("Openinig temp file");
- vdminit(f);
- if (!changed_origin) { // we should change the origin only one time
- changed_origin = 1;
- vdmorigin(-63,0);
- };
- vdmlinewidth(line_thickness);
-
-};
+ 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);
- /* lets copy the vdm code to the output */
+ /* 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;
-
-}; // lbp_printer::vdmflush
-
-inline void
-lbp_printer::setfillmode(int mode)
+ 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;
- };
-}; // setfillmode
+ 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)
+inline void lbp_printer::polygon(int hpos, int vpos, int np, int *p)
{
- //int points[np+2],i;
- 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);
-};
+ 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)
{
- 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;
- } // if (np != ...
- if (p[0] == 0) line_thickness = 1;
- if (p[0] < 0) // Default = 1 point
- line_thickness = (int)(env->size*30/72);
- line_thickness = (int)((abs(p[0])*env->size)/10);
- if ((line_thickness > 16 ) && (!vdminited()))
- { /* for greater thickness we must use VDM */
- vdmstart();
- /* vdmlinewidth(line_thickness); already done in
- * vdmstart() */
- };
- if (vdminited()) vdmlinewidth(line_thickness);
- // fprintf(stderr,"\nthickness: %d == %d, size %d\n",
- // p[0],line_thickness,env->size );
- } // else
- 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] == 1)
- 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;
- }; // if (p[0] >= 0 && p[0] <= 1000)
- break;
- default:
- error("unrecognised drawing command `%1'", char(code));
- break;
- }; // switch (code)
- return ;
-};
+ 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;
+ return new lbp_printer(user_papersize, user_paperwidth, user_paperlength);
}
-static struct
-{
- const char *name;
- int code;
-} papersizes[] =
-{{ "A4", 14 },
-{ "letter", 30 },
-{ "legal", 32 },
-{ "executive", 40 },
-};
-
+static struct {
+ const char *name;
+ int code;
+} lbp_papersizes[] =
+ {{ "A4", 14 },
+ { "letter", 30 },
+ { "legal", 32 },
+ { "executive", 40 },
+ };
-static int set_papersize(const char *papersize)
+static int set_papersize(const char *paperformat)
{
unsigned int i;
-
// First test for a standard (i.e. supported directly by the printer)
- // papersize
- for (i = 0 ; i < sizeof(papersizes)/sizeof(papersizes[0]); i++)
+ // paper size
+ for (i = 0 ; i < sizeof(lbp_papersizes) / sizeof(lbp_papersizes[0]); i++)
{
- if (strcasecmp(papersizes[i].name,papersize) == 0)
- return papersizes[i].code;
- };
-
- // Now test for a custom papersize
- if (strncasecmp("cust",papersize,4) == 0)
- {
- char *p ,
- *p1,
- *papsize;
-
- p = papsize = strdup(&papersize[4]);
- if (papsize == NULL) return -1;
- p1 = strsep(&p,"x");
- if (p == NULL)
- { // let's test for an uppercase x
- p = papsize ;
- p1 = strsep(&p,"X");
- if (p == NULL) { free(papsize); return -1;};
- }; // if (p1 == NULL)
- paperlength = atoi(p1);
- if (paperlength == 0) { free(papsize); return -1;};
- paperwidth = atoi(p);
- if (paperwidth == 0) { free(papsize); return -1;};
- free(papsize);
- return 82;
- }; // if (strcnasecmp("cust",papersize,4) == 0)
-
- return -1;
-};
-
-static int handle_papersize_command(const char *arg)
-{
- int n = set_papersize(arg);
-
- if (n < 0)
- { // If is not a standard nor custom paper size
- // let's see if it's a file (i.e /etc/papersize )
- FILE *f = fopen(arg,"r");
- if (f != NULL)
- { // the file exists and is readable
- char psize[255],*p;
- fgets(psize,254,f);
- fclose(f);
- // set_papersize doesn't like the trailing \n
- p = psize; while (*p) p++;
- if (*(--p) == '\n') *p = 0x00;
-
- n = set_papersize(psize);
- }; // if (f != NULL)
- }; // if (n < 0)
-
- return n;
-}; // handle_papersize_command
-
+ 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)
{
- // papersize command
- if (strcasecmp(command, "papersize") == 0) {
- // We give priority to command line options
- if (papersize > 0) return;
- if (arg == 0)
- error_with_file_and_line(filename, lineno,
- "`papersize' command requires an argument");
- else
- {
- int n = handle_papersize_command(arg);
- if (n < 0)
- error_with_file_and_line(filename, lineno,
- "unknown paper size `%1'", arg);
- else
- papersize = n;
-
- }; // if (arg == 0) ... else ...
- }; // if (strcasecmp(command, "papersize")
-
- // orientation command
+ // orientation command
if (strcasecmp(command, "orientation") == 0) {
// We give priority to command line options
- if (orientation > 0) return;
+ if (orientation > 0)
+ return;
if (arg == 0)
error_with_file_and_line(filename, lineno,
- "`papersize' command requires an argument");
+ "`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,
- "`orientation' command requires an argument");
- };
- }; // if (arg == 0) ... else ...
- }; // if (strcasecmp(command, "orientation") == 0)
-};
+ 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' },
@@ -670,97 +631,110 @@ static struct option long_options[] = {
{ "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] "\
- " [files ...]\n"\
- " -o --orientation=[portrait|landscape]\n"\
- " -v --version\n"\
- " -c --copies=numcopies\n"\
- " -l --landscape\n"\
- " -p --papersize=paper_size\n"\
- " -F --fontdir=dir\n"\
- " -h --help\n",
+ "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);
-}; // usage
+}
int main(int argc, char **argv)
{
- if (program_name == NULL) program_name = strdup(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:h",\
- long_options, &option_index);
- switch (c) {
- case 'F' : font::command_line_font_dir(optarg);
- break;
- case 'p' : {
- int n = handle_papersize_command(optarg);
- if (n < 0)
- error("unknown paper size `%1'", optarg);
- else
- papersize = n;
- 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 'h' : usage(stdout);
- exit(0);
- break;
- case '?' : usage(stderr);
- exit(1);
- break;
-
- }; // switch (c)
- }; // while (c > 0 )
-
- if (optind >= argc)
- do_file("-");
-
- while (optind < argc) {
- do_file(argv[optind++]);
- };
-
- lbpputs("\033c\033<");
- return 0;
-};
+ 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/grolbp/lbp.h b/contrib/groff/src/devices/grolbp/lbp.h
index cacf3ea..3b8a941 100644
--- a/contrib/groff/src/devices/grolbp/lbp.h
+++ b/contrib/groff/src/devices/grolbp/lbp.h
@@ -1,5 +1,5 @@
// -*- C -*-
-/* Copyright (C) 1994, 2000 Free Software Foundation, Inc.
+/* Copyright (C) 1994, 2000, 2001 Free Software Foundation, Inc.
Written by Francisco Andrés Verdú <pandres@dragonet.es>
groff is free software; you can redistribute it and/or modify it under
diff --git a/contrib/groff/src/devices/grolj4/Makefile.sub b/contrib/groff/src/devices/grolj4/Makefile.sub
index bbb0cff..21c3780 100644
--- a/contrib/groff/src/devices/grolj4/Makefile.sub
+++ b/contrib/groff/src/devices/grolj4/Makefile.sub
@@ -1,6 +1,6 @@
-PROG=grolj4
+PROG=grolj4$(EXEEXT)
MAN1=grolj4.n
XLIBS=$(LIBDRIVER) $(LIBGROFF)
MLIB=$(LIBM)
-OBJS=lj4.o
+OBJS=lj4.$(OBJEXT)
CCSRCS=$(srcdir)/lj4.cc
diff --git a/contrib/groff/src/devices/grolj4/grolj4.man b/contrib/groff/src/devices/grolj4/grolj4.man
index 414ad78..267c621 100644
--- a/contrib/groff/src/devices/grolj4/grolj4.man
+++ b/contrib/groff/src/devices/grolj4/grolj4.man
@@ -1,5 +1,5 @@
.ig
-Copyright (C) 1994-2000, 2001 Free Software Foundation, Inc.
+Copyright (C) 1994-2000, 2001, 2002 Free Software Foundation, Inc.
Permission is granted to make and distribute verbatim copies of
this manual provided the copyright notice and this permission notice
@@ -59,7 +59,7 @@ There is an additional drawing command available:
.BI \eD'R\ dh\ dv '
Draw a rule (solid black rectangle), with one corner
at the current position, and the diagonally opposite corner
-at the current position
+at the current position
.RI +( dh , dv ).
Afterwards the current position will be at the opposite corner. This
generates a PCL fill rectangle command, and so will work on
@@ -77,7 +77,7 @@ copies of each page.
Print the document with a landscape orientation.
.TP
.BI "\-d [" n ]
-Use duplex mode
+Use duplex mode
.IR n :
1\ is long-side binding; 2\ is short-side binding;
default is\ 1.
@@ -94,17 +94,20 @@ Print the version number.
.BI \-w n
Set the default line thickness to
.I n
-thousandths of an em.
+thousandths of an em.
+If this option isn't specified, the line thickness defaults to 0.04\~em.
.TP
.BI \-F dir
Prepend directory
-.IB dir /devlj4
-to the search path for font and device description files.
+.IB dir /dev name
+to the search path for font and device description files;
+.I name
+is the name of the device, usually
+.BR lj4 .
.LP
The following four commands are available additionally in the
-.B DESC
-file:
-.TP
+font description files:
+.TP
.BI pclweight \ N
The integer value
.I N
diff --git a/contrib/groff/src/devices/grolj4/lj4.cc b/contrib/groff/src/devices/grolj4/lj4.cc
index 6829acb..0c3150d 100644
--- a/contrib/groff/src/devices/grolj4/lj4.cc
+++ b/contrib/groff/src/devices/grolj4/lj4.cc
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 1994, 2000, 2001 Free Software Foundation, Inc.
+/* Copyright (C) 1994, 2000, 2001, 2002 Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
This file is part of groff.
@@ -55,7 +55,7 @@ static struct {
{ "dl", 90, 71, 59 },
};
-static int paper_size = -1;
+static int user_paper_size = -1;
static int landscape_flag = 0;
static int duplex_flag = 0;
@@ -76,6 +76,8 @@ 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();
@@ -158,7 +160,7 @@ void lj4_font::handle_unknown_font_command(const char *command,
class lj4_printer : public printer {
public:
- lj4_printer();
+ 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);
@@ -184,6 +186,7 @@ private:
double pen_width;
double hpgl_scale;
int hpgl_inited;
+ int paper_size;
};
inline
@@ -207,7 +210,7 @@ void lj4_printer::hpgl_end()
fputs(";\033%0A", stdout);
}
-lj4_printer::lj4_printer()
+lj4_printer::lj4_printer(int ps)
: cur_hpos(-1),
cur_font(0),
cur_size(0),
@@ -221,11 +224,19 @@ lj4_printer::lj4_printer()
font::res);
fputs("\033E", stdout); // reset
if (font::res != 300)
- printf("\033&u%dD", font::res); // unit of measure
+ printf("\033&u%dD", font::res); // unit of measure
if (ncopies > 0)
printf("\033&l%uX", ncopies);
- if (paper_size < 0)
- paper_size = 0; // default to letter
+ 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
@@ -266,7 +277,8 @@ 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)
+void lj4_printer::set_char(int index, font *f, const environment *env,
+ int w, const char *name)
{
int code = f->get_code(index);
@@ -502,6 +514,9 @@ void lj4_printer::draw(int code, int *p, int np, const environment *env)
printf("FT10,%d", p[0]/10);
hpgl_end();
break;
+ case 'F':
+ // not implemented yet
+ break;
case 't':
{
if (np == 0) {
@@ -531,8 +546,8 @@ void lj4_printer::hpgl_init()
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
+ "\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
@@ -565,7 +580,7 @@ font *lj4_printer::make_font(const char *nm)
printer *make_printer()
{
- return new lj4_printer;
+ return new lj4_printer(user_paper_size);
}
static
@@ -580,25 +595,6 @@ int lookup_paper_size(const char *s)
return -1;
}
-static
-void handle_unknown_desc_command(const char *command, const char *arg,
- const char *filename, int lineno)
-{
- if (strcmp(command, "papersize") == 0) {
- if (arg == 0)
- error_with_file_and_line(filename, lineno,
- "`papersize' command requires an argument");
- else if (paper_size < 0) {
- int n = lookup_paper_size(arg);
- if (n < 0)
- error_with_file_and_line(filename, lineno,
- "unknown paper size `%1'", arg);
- else
- paper_size = n;
- }
- }
-}
-
static void usage(FILE *stream);
extern "C" int optopt, optind;
@@ -608,7 +604,6 @@ int main(int argc, char **argv)
program_name = argv[0];
static char stderr_buf[BUFSIZ];
setbuf(stderr, stderr_buf);
- font::set_unknown_desc_command_handler(handle_unknown_desc_command);
int c;
static const struct option long_options[] = {
{ "help", no_argument, 0, CHAR_MAX + 1 },
@@ -644,7 +639,7 @@ int main(int argc, char **argv)
if (n < 0)
error("unknown paper size `%1'", optarg);
else
- paper_size = n;
+ user_paper_size = n;
break;
}
case 'v':
diff --git a/contrib/groff/src/devices/grops/Makefile.sub b/contrib/groff/src/devices/grops/Makefile.sub
index 4182527..ee2e6d1 100644
--- a/contrib/groff/src/devices/grops/Makefile.sub
+++ b/contrib/groff/src/devices/grops/Makefile.sub
@@ -1,10 +1,10 @@
-PROG=grops
+PROG=grops$(EXEEXT)
MAN1=grops.n
XLIBS=$(LIBDRIVER) $(LIBGROFF)
MLIB=$(LIBM)
OBJS=\
- ps.o \
- psrm.o
+ ps.$(OBJEXT) \
+ psrm.$(OBJEXT)
CCSRCS=\
$(srcdir)/ps.cc \
$(srcdir)/psrm.cc
diff --git a/contrib/groff/src/devices/grops/TODO b/contrib/groff/src/devices/grops/TODO
index da67973..7ab3b69 100644
--- a/contrib/groff/src/devices/grops/TODO
+++ b/contrib/groff/src/devices/grops/TODO
@@ -6,9 +6,6 @@ Generate %%For comment.
Generate %%Title comment.
-For efficiency it might be better to have the printer interface have
-support for the t and u commands.
-
Angles in arc command: don't generate more digits after the decimal
point than are necessary.
diff --git a/contrib/groff/src/devices/grops/grops.man b/contrib/groff/src/devices/grops/grops.man
index e9c6be4..e7d2305 100644
--- a/contrib/groff/src/devices/grops/grops.man
+++ b/contrib/groff/src/devices/grops/grops.man
@@ -1,5 +1,5 @@
.ig
-Copyright (C) 1989-2000, 2001 Free Software Foundation, Inc.
+Copyright (C) 1989-2000, 2001, 2002 Free Software Foundation, Inc.
Permission is granted to make and distribute verbatim copies of
this manual provided the copyright notice and this permission notice
@@ -16,15 +16,25 @@ versions, except that this permission notice may be included in
translations approved by the Free Software Foundation instead of in
the original English.
..
+.
+.mso www.tmac
+.
+.
.\" Like TP, but if specified indent is more than half
.\" the current line-length - indent, use the default indent.
.de Tp
.ie \\n(.$=0:((0\\$1)*2u>(\\n(.lu-\\n(.iu)) .TP
.el .TP "\\$1"
..
+.
+.
.TH GROPS @MAN1EXT@ "@MDATE@" "Groff Version @VERSION@"
+.
+.
.SH NAME
grops \- PostScript driver for groff
+.
+.
.SH SYNOPSIS
.nr a \n(.j
.ad l
@@ -32,43 +42,55 @@ grops \- PostScript driver for groff
.in +\w'\fBgrops 'u
.ti \niu
.B grops
+.
.de OP
-.ie \\n(.$-1 .RI "[\ \fB\\$1\fP" "\\$2" "\ ]"
+.ie \\n(.$-1 .RI "[\ \fB\\$1\fP" "\%\\$2" "\ ]"
.el .RB "[\ " "\\$1" "\ ]"
..
+.
.OP \-glmv
.OP \-b n
.OP \-c n
-.OP \-w n
.OP \-F dir
+.OP \-p papersize
.OP \-P prologue
+.OP \-w n
.RI "[\ " files\|.\|.\|. "\ ]"
.br
.ad \na
+.
.PP
It is possible to have whitespace between a command line option and its
parameter.
+.
+.
.SH DESCRIPTION
.B grops
translates the output of GNU
.B troff
to PostScript.
+.
Normally
.B grops
should be invoked by using the groff command
with a
.B \-Tps
option.
+.
.if '@DEVICE@'ps' (Actually, this is the default for groff.)
+.
If no files are given,
.B grops
will read the standard input.
+.
A filename of
.B \-
will also cause
.B grops
to read the standard input.
+.
PostScript output is written to the standard output.
+.
When
.B grops
is run by
@@ -79,22 +101,29 @@ using the
.B groff
.B \-P
option.
+.
+.
.SH OPTIONS
.TP
.BI \-b n
Workaround broken spoolers and previewers.
+.
Normally
.B grops
produces output that conforms
the Document Structuring Conventions version 3.0.
+.
Unfortunately some spoolers and previewers can't handle such output.
-The value of
+.
+The value of\~\c
.I n
controls what
.B grops
does to its output acceptable to such programs.
-A value of 0 will cause grops not to employ any workarounds.
-Add 1 if no
+.
+A value of\~0 will cause grops not to employ any workarounds.
+.
+Add\~1 if no
.B %%BeginDocumentSetup
and
.B %%EndDocumentSetup
@@ -105,10 +134,12 @@ anything between the
comment and the first
.B %%Page
comment.
-Add 2 if lines in included files beginning with
+.
+Add\~2 if lines in included files beginning with
.B %!
should be stripped out; this is needed for Sun's pageview previewer.
-Add 4 if
+.
+Add\~4 if
.BR %%Page ,
.BR %%Trailer
and
@@ -120,63 +151,97 @@ don't understand the
and
.B %%EndDocument
comments.
-Add 8 if the first line of the PostScript output should be
+.
+Add\~8 if the first line of the PostScript output should be
.B %!PS-Adobe-2.0
rather than
.BR %!PS-Adobe-3.0 ;
this is needed when using Sun's Newsprint with a printer that requires
page reversal.
+.
The default value can be specified by a
+.
.RS
.IP
.BI broken\ n
+.
.LP
command in the DESC file.
-Otherwise the default value is 0.
+.
+Otherwise the default value is\~0.
.RE
+.
.TP
.BI \-c n
Print
.I n
copies of each page.
+.
+.TP
+.BI \-F dir
+Prepend directory
+.IB dir /dev name
+to the search path for prologue, font, and device description files;
+.I name
+is the name of the device, usually
+.BR ps .
+.
.TP
.BI \-g
Guess the page length.
+.
This generates PostScript code that guesses the page length.
+.
The guess will be correct only if the imageable area is vertically
centered on the page.
+.
This option allows you to generate documents that can be printed
both on letter (8.5\(mu11) paper and on A4 paper without change.
+.
.TP
.B \-l
Print the document in landscape format.
+.
.TP
.B \-m
Turn manual feed on for the document.
+.
.TP
-.BI \-F dir
-Prepend directory
-.IB dir /dev name
-to the search path for prologue, font, and device description files;
-.I name
-is the name of the device, usually
-.BR ps .
+.BI \-p paper-size
+Set physical dimension of output medium.
+.
+This overrides the
+.B papersize
+and
+.B paperlength
+commands in the
+.B DESC
+file; it accepts the same arguments as the
+.B papersize
+command.
+.
.TP
.BI \-P prologue-file
Use the file
.I prologue-file
(in the font path) as the prologue instead of the default prologue file
.BR prologue .
+.
This option overrides the environment variable
.SM GROPS_PROLOGUE.
+.
.TP
.BI \-w n
Lines should be drawn using a thickness of
-.I n
+.IR n \~\c
thousandths of an em.
+If this option is not given, the line thickness defaults to 0.04\~em.
+.
.TP
.B \-v
Print the version number.
+.
+.
.SH USAGE
There are styles called
.BR R ,
@@ -184,7 +249,8 @@ There are styles called
.BR B ,
and
.B BI
-mounted at font positions 1 to 4.
+mounted at font positions 1 to\~4.
+.
The fonts are grouped into families
.BR A ,
.BR BM ,
@@ -193,245 +259,313 @@ The fonts are grouped into families
.BR HN ,
.BR N ,
.B P
-and
+and\~\c
.B T
having members in each of these styles:
+.
.de FT
.if '\\*(.T'ps' .ft \\$1
..
+.
+.RS
.TP
.B AR
.FT AR
AvantGarde-Book
.FT
+.
.TP
.B AI
.FT AI
AvantGarde-BookOblique
.FT
+.
.TP
.B AB
.FT AB
AvantGarde-Demi
.FT
+.
.TP
.B ABI
.FT ABI
AvantGarde-DemiOblique
.FT
+.
.TP
.B BMR
.FT BMR
Bookman-Light
.FT
+.
.TP
.B BMI
.FT BMI
Bookman-LightItalic
.FT
+.
.TP
.B BMB
.FT BMB
Bookman-Demi
.FT
+.
.TP
.B BMBI
.FT BMBI
Bookman-DemiItalic
.FT
+.
.TP
.B CR
.FT CR
Courier
.FT
+.
.TP
.B CI
.FT CI
Courier-Oblique
.FT
+.
.TP
.B CB
.FT CB
Courier-Bold
.FT
+.
.TP
.B CBI
.FT CBI
Courier-BoldOblique
.FT
+.
.TP
.B HR
.FT HR
Helvetica
.FT
+.
.TP
.B HI
.FT HI
Helvetica-Oblique
.FT
+.
.TP
.B HB
.FT HB
Helvetica-Bold
.FT
+.
.TP
.B HBI
.FT HBI
Helvetica-BoldOblique
.FT
+.
.TP
.B HNR
.FT HNR
Helvetica-Narrow
.FT
+.
.TP
.B HNI
.FT HNI
Helvetica-Narrow-Oblique
.FT
+.
.TP
.B HNB
.FT HNB
Helvetica-Narrow-Bold
.FT
+.
.TP
.B HNBI
.FT HNBI
Helvetica-Narrow-BoldOblique
.FT
+.
.TP
.B NR
.FT NR
NewCenturySchlbk-Roman
.FT
+.
.TP
.B NI
.FT NI
NewCenturySchlbk-Italic
.FT
+.
.TP
.B NB
.FT NB
NewCenturySchlbk-Bold
.FT
+.
.TP
.B NBI
.FT NBI
NewCenturySchlbk-BoldItalic
.FT
+.
.TP
.B PR
.FT PR
Palatino-Roman
.FT
+.
.TP
.B PI
.FT PI
Palatino-Italic
.FT
+.
.TP
.B PB
.FT PB
Palatino-Bold
.FT
+.
.TP
.B PBI
.FT PBI
Palatino-BoldItalic
.FT
+.
.TP
.B TR
.FT TR
Times-Roman
.FT
+.
.TP
.B TI
.FT TI
Times-Italic
.FT
+.
.TP
.B TB
.FT TB
Times-Bold
.FT
+.
.TP
.B TBI
.FT TBI
Times-BoldItalic
.FT
+.RE
+.
.LP
There is also the following font which is not a member of a family:
+.
+.RS
.TP
.B ZCMI
.FT ZCMI
ZapfChancery-MediumItalic
.FT
+.RE
+.
.LP
There are also some special fonts called
.B SS
-and
+and\~\c
.BR S .
+.
Zapf Dingbats is available as
.BR ZD
and a reversed version of ZapfDingbats (with symbols pointing in the opposite
direction) is available as
.BR ZDR ;
most characters in these fonts are unnamed and must be accessed using
-.BR \eN .
+.BR \[rs]N .
+.
+.LP
+The default color for
+.B \[rs]m
+and
+.B \[rs]M
+is black; for colors defined in the `rgb' color space,
+.B setrgbcolor
+is used, for `cmy' and `cmyk'
+.BR setcmykcolor ,
+and for `gray'
+.BR setgray .
+.
.LP
.B grops
-understands various X commands produced using the
-.B \eX
+understands various X\~commands produced using the
+.B \[rs]X
escape sequence;
.B grops
will only interpret commands that begin with a
.B ps:
tag.
+.
.TP
-.BI \eX'ps:\ exec\ code '
+.BI \[rs]X'ps:\ exec\ code '
This executes the arbitrary PostScript commands in
.IR code .
+.
The PostScript currentpoint will be set to the position of the
-.B \eX
+.B \[rs]X
command before executing
.IR code .
+.
The origin will be at the top left corner of the page,
-and y coordinates will increase down the page.
-A procedure
+and y\~coordinates will increase down the page.
+.
+A procedure\~\c
.B u
will be defined that converts groff units
to the coordinate system in effect.
+.
For example,
+.
.RS
.IP
.B
\&.nr x 1i
.br
.B
-\eX'ps: exec \enx u 0 rlineto stroke'
+\[rs]X'ps: exec \[rs]nx u 0 rlineto stroke'
.br
.RE
+.
.IP
will draw a horizontal line one inch long.
+.
.I code
may make changes to the graphics state,
but any changes will persist only to the
end of the page.
+.
A dictionary containing the definitions specified by the
.B def
and
.B mdef
will be on top of the dictionary stack.
+.
If your code adds definitions to this dictionary,
you should allocate space for them using
-.BI \eX'ps\ mdef \ n '\fR.
+.BI \[rs]X'ps\ mdef \ n '\fR.
+.
Any definitions will persist only until the end of the page.
+.
If you use the
-.B \eY
+.B \[rs]Y
escape sequence with an argument that names a macro,
.I code
can extend over multiple lines.
+.
For example,
+.
.RS
.IP
.nf
@@ -439,63 +573,74 @@ For example,
\&.nr x 1i
\&.de y
\&ps: exec
-\&\enx u 0 rlineto
+\&\[rs]nx u 0 rlineto
\&stroke
\&..
-\&\eYy
+\&\[rs]Yy
.fi
.ft R
+.
.LP
is another way to draw a horizontal line one inch long.
.RE
+.
.TP
-.BI \eX'ps:\ file\ name '
+.BI \[rs]X'ps:\ file\ name '
This is the same as the
.B exec
command except that the PostScript code is read from file
.IR name .
+.
.TP
-.BI \eX'ps:\ def\ code '
+.BI \[rs]X'ps:\ def\ code '
Place a PostScript definition contained in
.I code
in the prologue.
+.
There should be at most one definition per
-.B \eX
+.B \[rs]X
command.
+.
Long definitions can be split over several
-.B \eX
+.B \[rs]X
commands;
all the
.I code
arguments are simply joined together separated by newlines.
+.
The definitions are placed in a dictionary which is automatically
pushed on the dictionary stack when an
.B exec
command is executed.
+.
If you use the
-.B \eY
+.B \[rs]Y
escape sequence with an argument that names a macro,
.I code
can extend over multiple lines.
+.
.TP
-.BI \eX'ps:\ mdef\ n\ code '
+.BI \[rs]X'ps:\ mdef\ n\ code '
Like
.BR def ,
except that
.I code
may contain up to
-.I n
+.IR n \~\c
definitions.
+.
.B grops
needs to know how many definitions
.I code
contains
so that it can create an appropriately sized PostScript dictionary
to contain them.
+.
.TP
-.BI \eX'ps:\ import\ file\ llx\ lly\ urx\ ury\ width\ \fR[\fP\ height\ \fR]\fP '
+.BI \[rs]X'ps:\ import\ file\ llx\ lly\ urx\ ury\ width\ \fR[\fP\ height\ \fR]\fP '
Import a PostScript graphic from
.IR file .
+.
The arguments
.IR llx ,
.IR lly ,
@@ -507,26 +652,29 @@ coordinate system; they should all be integers;
.I llx
and
.I lly
-are the x and y coordinates of the lower left
+are the x and y\~coordinates of the lower left
corner of the graphic;
.I urx
and
.I ury
-are the x and y coordinates of the upper right corner of the graphic;
+are the x and y\~coordinates of the upper right corner of the graphic;
.I width
and
.I height
are integers that give the desired width and height in groff
units of the graphic.
+.
The graphic will be scaled so that it has this width and height
and translated so that the lower left corner of the graphic is
located at the position associated with
-.B \eX
+.B \[rs]X
command.
+.
If the height argument is omitted it will be scaled uniformly in the
-x and y directions so that it has the specified width.
+x and y\~directions so that it has the specified width.
+.
Note that the contents of the
-.B \eX
+.B \[rs]X
command are not interpreted by
.BR troff ;
so vertical space for the graphic is not automatically added,
@@ -535,6 +683,7 @@ and the
and
.I height
arguments are not allowed to have attached scaling indicators.
+.
If the PostScript file complies with the Adobe Document Structuring
Conventions and contains a
.B %%BoundingBox
@@ -542,6 +691,7 @@ comment, then the bounding box can be automatically
extracted from within groff by using the
.B psbb
request.
+.
.RS
.LP
The
@@ -551,10 +701,11 @@ macros (which are automatically loaded when
is run by the groff command) include a
.B PSPIC
macro which allows a picture to be easily imported.
+.
This has the format
.IP
-\&\fB.PSPIC\fP [ \fB\-L\fP | \fB-R\fP | \fB\-I\fP \fIn\fP ]\ \"
-\fI\|file\fP [ \fIwidth\fP [ \fIheight\fP ]]
+\&\fB.PSPIC\fP [\fB\-L\fP|\fB-R\fP|\fB\-I\fP \fIn\fP]\ \fI\|file\fP [\fIwidth\fP [\fIheight\fP]]
+.
.LP
.I file
is the name of the file containing the illustration;
@@ -562,42 +713,49 @@ is the name of the file containing the illustration;
and
.I height
give the desired width and height of the graphic.
+.
The
.I width
and
.I height
arguments may have scaling indicators attached;
-the default scaling indicator is
+the default scaling indicator is\~\c
.BR i .
+.
This macro will scale the graphic uniformly
-in the x and y directions so that it is no more than
+in the x and y\~directions so that it is no more than
.I width
wide
and
.I height
high.
+.
By default, the graphic will be horizontally centered.
+.
The
.BI \-L
and
.BI \-R
cause the graphic to be left-aligned and right-aligned
respectively.
+.
The
.B \-I
-option causes the graphic to be indented by
+option causes the graphic to be indented by\~\c
.IR n .
.RE
+.
.TP
-.B \eX'ps:\ invis'
+.B \[rs]X'ps:\ invis'
.br
.ns
.TP
-.B \eX'ps:\ endinvis'
+.B \[rs]X'ps:\ endinvis'
No output will be generated for text and drawing commands
that are bracketed with these
-.B \eX
+.B \[rs]X
commands.
+.
These commands are intended for use when output from
.B troff
will be previewed before being processed with
@@ -605,71 +763,94 @@ will be previewed before being processed with
if the previewer is unable to display certain characters
or other constructs, then other substitute characters or constructs
can be used for previewing by bracketing them with these
-.B \eX
+.B \[rs]X
commands.
+.
.RS
.LP
For example,
.B gxditview
is not able to display a proper
-.B \e(em
+.B \[rs](em
character because the standard X11 fonts do not provide it;
this problem can be overcome by executing the following
request
+.
.IP
.ft B
.nf
-\&.char \e(em \eX'ps: invis'\e
-\eZ'\ev'-.25m'\eh'.05m'\eD'l .9m 0'\eh'.05m''\e
-\eX'ps: endinvis'\e(em
+\&.char \[rs](em \[rs]X'ps: invis'\[rs]
+\[rs]Z'\[rs]v'-.25m'\[rs]h'.05m'\[rs]D'l .9m 0'\[rs]h'.05m''\[rs]
+\[rs]X'ps: endinvis'\[rs](em
.ft
.fi
+.
.LP
In this case,
.B gxditview
will be unable to display the
-.B \e(em
+.B \[rs](em
character and will draw the line,
whereas
.B grops
will print the
-.B \e(em
+.B \[rs](em
character
and ignore the line.
.RE
+.
.LP
The input to
.B grops
must be in the format output by
.BR @g@troff (@MAN1EXT@).
+.
This is described in
.BR groff_out (@MAN5EXT@).
+.
In addition the device and font description files for the device used
must meet certain requirements.
+.
The device and font description files supplied for
.B ps
device meet all these requirements.
+.
.BR afmtodit (@MAN1EXT@)
can be used to create font files from AFM files.
-The resolution must be an integer multiple of 72 times the
+.
+The resolution must be an integer multiple of\~72 times the
.BR sizescale .
+.
The
.B ps
device uses a resolution of 72000 and a sizescale of 1000.
+.
The device description file should contain a command
.IP
.BI paperlength\ n
.LP
which says that output should be generated which is suitable for
printing on a page whose length is
-.I n
+.IR n \~\c
machine units.
+.
+Common values are 792000 for letter paper and 841890 for paper in A4 format.
+.
+Alternatively, it can contain
+.IP
+.BI papersize\ string
+.LP
+to specify a paper size; see
+.BR groff_font (@MAN5EXT@)
+for more information.
+.
Each font description file must contain a command
.IP
.BI internalname\ psname
.LP
which says that the PostScript name of the font is
.IR psname .
+.
It may also contain a command
.IP
.BI encoding\ enc_file
@@ -688,36 +869,48 @@ is the PostScript name of the character,
and
.I code
is its position in the encoding expressed as a decimal integer.
+.
+Lines starting with
+.B #
+and blank lines are ignored.
+.
The code for each character given in the font file must correspond
to the code for the character in encoding file, or to the code in the default
encoding for the font if the PostScript font is not to be reencoded.
+.
This code can be used with the
-.B \eN
+.B \[rs]N
escape sequence in
.B troff
to select the character,
even if the character does not have a groff name.
+.
Every character in the font file must exist in the PostScript font, and
the widths given in the font file must match the widths used
in the PostScript font.
+.
.B grops
will assume that a character with a groff name of
.B space
is blank (makes no marks on the page);
it can make use of such a character to generate more efficient and
compact PostScript output.
+.
.LP
.B grops
can automatically include the downloadable fonts necessary
to print the document.
+.
Any downloadable fonts which should, when required, be included by
.B grops
must be listed in the file
.BR @FONTDIR@/devps/download ;
this should consist of lines of the form
+.
.IP
.I
-font filename
+font filename
+.
.LP
where
.I font
@@ -732,9 +925,12 @@ fields may be separated by tabs or spaces;
.I filename
will be searched for using the same mechanism that is used
for groff font metric files.
+.
The
.B download
-file itself will also be searched for using this mechanism.
+file itself will also be searched for using this mechanism;
+currently, only the first found file in the font path is used.
+.
.LP
If the file containing a downloadable font or imported document
conforms to the Adobe Document Structuring Conventions,
@@ -742,11 +938,14 @@ then
.B grops
will interpret any comments in the files sufficiently to ensure that its
own output is conforming.
+.
It will also supply any needed font resources that are listed in the
.B download
file
as well as any needed file resources.
+.
It is also able to handle inter-resource dependencies.
+.
For example, suppose that you have a downloadable font called Garamond,
and also a downloadable font called Garamond-Outline
which depends on Garamond
@@ -754,12 +953,14 @@ which depends on Garamond
and change the PaintType),
then it is necessary for Garamond to be appear before Garamond-Outline
in the PostScript document.
+.
.B grops
will handle this automatically
provided that the downloadable font file for Garamond-Outline
indicates its dependence on Garamond by means of
the Document Structuring Conventions,
for example by beginning with the following lines
+.
.IP
.B
%!PS-Adobe-3.0 Resource-Font
@@ -772,19 +973,23 @@ for example by beginning with the following lines
.br
.B
%%IncludeResource: font Garamond
+.
.LP
In this case both Garamond and Garamond-Outline would need to be listed
in the
.B download
file.
+.
A downloadable font should not include its own name in a
.B %%DocumentSuppliedResources
comment.
+.
.LP
.B grops
will not interpret
.B %%DocumentFonts
comments.
+.
The
.BR %%DocumentNeededResources ,
.BR %%DocumentSuppliedResources ,
@@ -802,6 +1007,38 @@ and
.BR %%EndFont
comments)
should be used.
+.
+.
+.SS TrueType fonts
+TrueType fonts can be used with
+.B grops
+if converted first to
+.B "Type 42"
+format, an especial PostScript wrapper equivalent to the
+PFA format mentioned in
+.BR pfbtops (@MAN1EXT@).
+There are several different methods to generate a type42
+wrapper and most of them involve the use of a PostScript
+interpreter such as Ghostscript \(em see
+.BR gs (1).
+Yet, the easiest method involves the use of the application
+.BR ttftot42 .
+This program uses
+.BR freetype (3)
+(version 1.3.1) to generate type42
+font wrappers and well-formed AFM files that can be fed to
+the
+.BR afmtodit (@MAN1EXT@)
+script to create appropriate metric files.
+The resulting font wrappers should be added to the
+.B download
+file.
+.B ttftot42
+source code can be downloaded from
+.URL ftp://\:www.giga.or.at/\:pub/\:nih/\:ttftot42/ \
+ ftp://\:www.giga.or.at/\:pub/\:nih/\:ttftot42/ .
+.
+.
.SH ENVIRONMENT
.TP
.SM
@@ -814,29 +1051,37 @@ will use the file
.I foo
(in the font path) instead of the default prologue file
.BR prologue .
+.
The option
.B \-P
overrides this environment variable.
+.
+.
.SH FILES
.Tp \w'\fB@FONTDIR@/devps/download'u+2n
.B @FONTDIR@/devps/DESC
Device description file.
+.
.TP
.BI @FONTDIR@/devps/ F
Font description file for font
.IR F .
+.
.TP
.B @FONTDIR@/devps/download
List of downloadable fonts.
+.
.TP
.B @FONTDIR@/devps/text.enc
Encoding used for text fonts.
+.
.TP
.B @MACRODIR@/ps.tmac
Macros for use with
.BR grops ;
automatically loaded by
.BR troffrc
+.
.TP
.B @MACRODIR@/pspic.tmac
Definition of
@@ -844,13 +1089,17 @@ Definition of
macro,
automatically loaded by
.BR ps.tmac .
+.
.TP
.B @MACRODIR@/psold.tmac
Macros to disable use of characters not present in older
PostScript printers (e.g. `eth' or `thorn').
+.
.TP
.BI /tmp/grops XXXXXX
Temporary file.
+.
+.
.SH "SEE ALSO"
.BR afmtodit (@MAN1EXT@),
.BR groff (@MAN1EXT@),
diff --git a/contrib/groff/src/devices/grops/ps.cc b/contrib/groff/src/devices/grops/ps.cc
index a467f04..47d1f65 100644
--- a/contrib/groff/src/devices/grops/ps.cc
+++ b/contrib/groff/src/devices/grops/ps.cc
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001
+/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001, 2002
Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
@@ -23,6 +23,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "stringclass.h"
#include "cset.h"
#include "nonposix.h"
+#include "paper.h"
#include "ps.h"
#include <time.h>
@@ -42,6 +43,7 @@ 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;
@@ -319,7 +321,7 @@ ps_output &ps_output::put_fix_number(int i)
ps_output &ps_output::put_float(double d)
{
char buf[128];
- sprintf(buf, "%.4f", d);
+ sprintf(buf, "%.3g", d);
int len = strlen(buf);
if (col > 0 && col + len + need_space > max_line_length) {
putc('\n', fp);
@@ -354,6 +356,26 @@ ps_output &ps_output::put_symbol(const char *s)
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);
@@ -476,13 +498,13 @@ class ps_printer : public printer {
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;
- int fill;
unsigned char output_space_code;
enum { MAX_DEFINED_STYLES = 50 };
style defined_styles[MAX_DEFINED_STYLES];
@@ -504,13 +526,15 @@ class ps_printer : public printer {
void do_file(char *, const environment *);
void do_invis(char *, const environment *);
void do_endinvis(char *, const environment *);
- void set_line_thickness(const environment *);
- void fill_path();
+ 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();
+ 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);
@@ -521,14 +545,14 @@ public:
void end_of_line();
};
-ps_printer::ps_printer()
+// `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),
- fill(FILL_MAX + 1),
ndefined_styles(0),
next_encoding_index(0),
ndefs(0),
@@ -553,9 +577,12 @@ ps_printer::ps_printer()
res = r;
out.set_fixed_point(point);
space_char_index = font::name_to_index("space");
- paper_length = font::paperlength;
+ 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;
+ paper_length = 11 * font::res;
equalise_spaces = font::res >= 72000;
}
@@ -590,7 +617,8 @@ void ps_printer::set_char(int i, font *f, const environment *env, int w, const c
if (sbuf_len > 0) {
if (sbuf_len < SBUF_SIZE
&& sty == sbuf_style
- && sbuf_vpos == env->vpos) {
+ && sbuf_vpos == env->vpos
+ && sbuf_color == *env->col) {
if (sbuf_end_hpos == env->hpos) {
sbuf[sbuf_len++] = code;
sbuf_end_hpos += w + sbuf_kern;
@@ -645,6 +673,8 @@ void ps_printer::set_char(int i, font *f, const environment *env, int w, const c
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)
@@ -693,7 +723,8 @@ void ps_printer::define_encoding(const char *encoding, int encoding_index)
a_delete vec[i];
}
}
- out.put_delimiter(']').put_symbol("def");
+ out.put_delimiter(']')
+ .put_symbol("def");
}
void ps_printer::reencode_font(ps_font *f)
@@ -759,18 +790,60 @@ void ps_printer::set_style(const style &sty)
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)
+ 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");
+ 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");
+ out.put_literal_symbol("SC")
+ .put_number(c)
+ .put_symbol("def");
}
void ps_printer::end_of_line()
@@ -863,39 +936,43 @@ void ps_printer::flush_sbuf()
sbuf_len = 0;
}
-
-void ps_printer::set_line_thickness(const environment *env)
+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");
+ 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");
+ 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()
+void ps_printer::fill_path(const environment *env)
{
- if (fill > FILL_MAX)
- out.put_symbol("BL");
+ if (sbuf_color == *env->fill)
+ out.put_symbol("FL");
else
- out.put_float(transform_fill(fill)).put_symbol("FL");
+ 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':
@@ -911,11 +988,10 @@ void ps_printer::draw(int code, int *p, int np, const environment *env)
.put_fix_number(env->vpos)
.put_fix_number(p[0]/2)
.put_symbol("DC");
- if (fill_flag) {
- fill_path();
- }
+ if (fill_flag)
+ fill_path(env);
else {
- set_line_thickness(env);
+ set_line_thickness_and_color(env);
out.put_symbol("ST");
}
break;
@@ -924,7 +1000,7 @@ void ps_printer::draw(int code, int *p, int np, const environment *env)
error("2 arguments required for line");
break;
}
- set_line_thickness(env);
+ 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)
@@ -944,11 +1020,10 @@ void ps_printer::draw(int code, int *p, int np, const environment *env)
.put_fix_number(env->hpos + p[0]/2)
.put_fix_number(env->vpos)
.put_symbol("DE");
- if (fill_flag) {
- fill_path();
- }
+ if (fill_flag)
+ fill_path(env);
else {
- set_line_thickness(env);
+ set_line_thickness_and_color(env);
out.put_symbol("ST");
}
break;
@@ -973,11 +1048,10 @@ void ps_printer::draw(int code, int *p, int np, const environment *env)
.put_fix_number(p[i+1])
.put_symbol("RL");
out.put_symbol("CL");
- if (fill_flag) {
- fill_path();
- }
+ if (fill_flag)
+ fill_path(env);
else {
- set_line_thickness(env);
+ set_line_thickness_and_color(env);
out.put_symbol("ST");
}
break;
@@ -1015,7 +1089,7 @@ void ps_printer::draw(int code, int *p, int np, const environment *env)
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(env);
+ set_line_thickness_and_color(env);
out.put_symbol("ST");
}
break;
@@ -1025,7 +1099,7 @@ void ps_printer::draw(int code, int *p, int np, const environment *env)
error("4 arguments required for arc");
break;
}
- set_line_thickness(env);
+ set_line_thickness_and_color(env);
double c[2];
if (adjust_arc_center(p, c))
out.put_fix_number(env->hpos + int(c[0]))
@@ -1043,60 +1117,47 @@ void ps_printer::draw(int code, int *p, int np, const environment *env)
}
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 'f':
- {
+ if (np == 0)
+ line_thickness = -1;
+ else {
+ // troff gratuitously adds an extra 0
if (np != 1 && np != 2) {
- error("1 argument required for fill");
+ error("0 or 1 argument required for thickness");
break;
}
- fill = p[0];
- if (fill < 0 || fill > FILL_MAX) {
- // This means fill with the current color.
- fill = FILL_MAX + 1;
- }
- 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();
+ 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");
- out.put_symbol("BP");
- out.simple_comment("EndPageSetup");
+ 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");
@@ -1111,9 +1172,9 @@ font *ps_printer::make_font(const char *nm)
ps_printer::~ps_printer()
{
- out.simple_comment("Trailer");
- out.put_symbol("end");
- out.simple_comment("EOF");
+ 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);
@@ -1142,8 +1203,12 @@ ps_printer::~ps_printer()
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();
+ 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,
@@ -1164,7 +1229,8 @@ ps_printer::~ps_printer()
out.simple_comment("BeginSetup");
}
rm.document_setup(out);
- out.put_symbol(dict_name).put_symbol("begin");
+ out.put_symbol(dict_name)
+ .put_symbol("begin");
if (ndefs > 0)
ndefs += DEFS_DICT_SPARE;
out.put_literal_symbol(defs_dict_name)
@@ -1184,8 +1250,12 @@ ps_printer::~ps_printer()
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("#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");
@@ -1246,7 +1316,7 @@ void ps_printer::special(char *arg, const environment *env, char type)
for (; *p != '\0' && *p != ' ' && *p != '\n'; p++)
;
if (*command == '\0') {
- error("X command without `ps:' tag ignored");
+ error("empty X command ignored");
return;
}
for (unsigned int i = 0; i < sizeof(proc_table)/sizeof(proc_table[0]); i++)
@@ -1474,7 +1544,7 @@ void ps_printer::do_endinvis(char *, const environment *)
printer *make_printer()
{
- return new ps_printer;
+ return new ps_printer(user_paper_length);
}
static void usage(FILE *stream);
@@ -1491,21 +1561,23 @@ int main(int argc, char **argv)
{ "version", no_argument, 0, 'v' },
{ NULL, 0, 0, 0 }
};
- while ((c = getopt_long(argc, argv, "F:P:glmc:w:vb:", long_options, NULL))
+ while ((c = getopt_long(argc, argv, "b:c:F:glmp:P:vw:", long_options, NULL))
!= EOF)
switch(c) {
- case 'v':
- {
- printf("GNU grops (groff) version %s\n", Version_string);
- exit(0);
- break;
- }
+ 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;
@@ -1515,8 +1587,9 @@ int main(int argc, char **argv)
case 'm':
manual_feed_flag = 1;
break;
- case 'F':
- font::command_line_font_dir(optarg);
+ 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";
@@ -1526,17 +1599,16 @@ int main(int argc, char **argv)
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 'b':
- // XXX check this
- broken_flags = atoi(optarg);
- bflag = 1;
- break;
case CHAR_MAX + 1: // --help
usage(stdout);
exit(0);
diff --git a/contrib/groff/src/devices/grops/ps.h b/contrib/groff/src/devices/grops/ps.h
index 6e78597..0e149fc 100644
--- a/contrib/groff/src/devices/grops/ps.h
+++ b/contrib/groff/src/devices/grops/ps.h
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+/* Copyright (C) 1989, 1990, 1991, 1992, 2002 Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
This file is part of groff.
@@ -26,6 +26,7 @@ public:
ps_output &put_fix_number(int);
ps_output &put_float(double);
ps_output &put_symbol(const char *);
+ ps_output &put_color(unsigned int);
ps_output &put_literal_symbol(const char *);
ps_output &set_fixed_point(int);
ps_output &simple_comment(const char *);
diff --git a/contrib/groff/src/devices/grops/psrm.cc b/contrib/groff/src/devices/grops/psrm.cc
index 5f232c0..f2177da 100644
--- a/contrib/groff/src/devices/grops/psrm.cc
+++ b/contrib/groff/src/devices/grops/psrm.cc
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001
+/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001, 2002
Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
@@ -389,7 +389,7 @@ static int ps_get_line(char *buf, FILE *fp)
int err = 0;
while (c != '\r' && c != '\n' && c != EOF) {
if ((c < 0x1b && !white_space(c)) || c == 0x7f)
- error("illegal input character code %1", int(c));
+ error("invalid input character code %1", int(c));
else if (i < PS_LINE_MAX)
buf[i++] = c;
else if (!err) {
@@ -724,6 +724,32 @@ int read_one_of(const char **ptr, const char **s, int n)
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)
{
@@ -790,6 +816,7 @@ int resource_manager::do_begin_data(const char *ptr, int, FILE *fp,
}
} 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");
@@ -826,11 +853,12 @@ int resource_manager::do_begin_binary(const char *ptr, int, FILE *fp,
if (cc != '\n')
current_lineno++;
if (cc != EOF)
- ungetc(c, fp);
+ 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");
diff --git a/contrib/groff/src/devices/grotty/Makefile.sub b/contrib/groff/src/devices/grotty/Makefile.sub
index 91d3908..8802674 100644
--- a/contrib/groff/src/devices/grotty/Makefile.sub
+++ b/contrib/groff/src/devices/grotty/Makefile.sub
@@ -1,6 +1,6 @@
-PROG=grotty
+PROG=grotty$(EXEEXT)
MAN1=grotty.n
XLIBS=$(LIBDRIVER) $(LIBGROFF)
MLIB=$(LIBM)
-OBJS=tty.o
+OBJS=tty.$(OBJEXT)
CCSRCS=$(srcdir)/tty.cc
diff --git a/contrib/groff/src/devices/grotty/tty.cc b/contrib/groff/src/devices/grotty/tty.cc
index d13adbf..81183b8 100644
--- a/contrib/groff/src/devices/grotty/tty.cc
+++ b/contrib/groff/src/devices/grotty/tty.cc
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 1989-2000, 2001 Free Software Foundation, Inc.
+/* Copyright (C) 1989-2000, 2001, 2002 Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
This file is part of groff.
@@ -23,6 +23,8 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
extern "C" const char *Version_string;
+#define putstring(s) fputs(s, stdout)
+
#ifndef SHRT_MIN
#define SHRT_MIN (-32768)
#endif
@@ -39,18 +41,42 @@ 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 old_drawing_scheme = 0;
enum {
UNDERLINE_MODE = 0x01,
BOLD_MODE = 0x02,
VDRAW_MODE = 0x04,
HDRAW_MODE = 0x08,
- CU_MODE = 0x10
+ 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"
+// 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;
@@ -109,10 +135,13 @@ public:
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); }
+ inline int order() {
+ return mode & (VDRAW_MODE|HDRAW_MODE|CU_MODE|COLOR_CHANGE); }
};
glyph *glyph::free_list = 0;
@@ -146,14 +175,26 @@ class tty_printer : public printer {
int nlines;
int cached_v;
int cached_vpos;
- void add_char(unsigned int, int, int, unsigned char);
+ 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 *);
@@ -162,10 +203,35 @@ public:
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()
@@ -173,15 +239,64 @@ 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
+ 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, ((tty_font *)f)->get_mode());
+ 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, unsigned char 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.
@@ -221,12 +336,14 @@ void tty_printer::add_char(unsigned int c, int h, int v, unsigned char mode)
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 CU specials before HDRAW characters
- // before VDRAW characters before normal characters at each hpos, and
- // otherwise in order of occurrence.
+ // 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)
@@ -239,8 +356,51 @@ void tty_printer::add_char(unsigned int c, int h, int v, unsigned char mode)
void tty_printer::special(char *arg, const environment *env, char type)
{
- if (type == 'u')
- add_char(*arg - '0', env->hpos, env->vpos, CU_MODE);
+ 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)
@@ -260,7 +420,7 @@ void tty_printer::draw(int code, int *p, int np, const environment *env)
len = -len;
}
while (len >= 0) {
- add_char('|', env->hpos, v, VDRAW_MODE);
+ add_char('|', env->hpos, v, env->col, env->fill, VDRAW_MODE);
len -= font::vert;
v += font::vert;
}
@@ -274,7 +434,7 @@ void tty_printer::draw(int code, int *p, int np, const environment *env)
len = -len;
}
while (len >= 0) {
- add_char('-', h, env->vpos, HDRAW_MODE);
+ add_char('-', h, env->vpos, env->col, env->fill, HDRAW_MODE);
len -= font::hor;
h += font::hor;
}
@@ -302,14 +462,37 @@ void tty_printer::put_char(unsigned int wc)
do *++p = (unsigned char)(((wc >> (6 * --count)) & 0x3f) | 0x80);
while (count > 0);
*++p = '\0';
- fputs(buf, stdout);
+ putstring(buf);
}
- else {
+ else
putchar(wc);
- }
}
-int cu_flag = 0;
+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
+ 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)
{
@@ -345,6 +528,10 @@ void tty_printer::end_page(int page_length)
}
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) {
@@ -376,34 +563,79 @@ void tty_printer::end_page(int page_length)
int next_tab_pos = ((hpos + TAB_WIDTH) / TAB_WIDTH) * TAB_WIDTH;
if (next_tab_pos > p->hpos)
break;
- if (cu_flag) {
- putchar('_');
- putchar('\b');
+ if (cu_flag)
+ make_underline();
+ else if (!old_drawing_scheme && is_underline) {
+ if (italic_flag)
+ putstring(SGR_NO_ITALIC);
+ else
+ putstring(SGR_NO_UNDERLINE);
+ is_underline = 0;
}
putchar('\t');
hpos = next_tab_pos;
}
}
for (; hpos < p->hpos; hpos++) {
- if (cu_flag) {
- putchar('_');
- putchar('\b');
+ if (cu_flag)
+ make_underline();
+ else if (!old_drawing_scheme && is_underline) {
+ if (italic_flag)
+ putstring(SGR_NO_ITALIC);
+ else
+ putstring(SGR_NO_UNDERLINE);
+ is_underline = 0;
}
putchar(' ');
}
}
assert(hpos == p->hpos);
- if (p->mode & UNDERLINE_MODE) {
- putchar('_');
- putchar('\b');
+ 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
+ putstring(SGR_NO_UNDERLINE);
+ is_underline = 0;
}
- if (p->mode & BOLD_MODE) {
- put_char(p->code);
- putchar('\b');
+ 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) {
@@ -432,6 +664,8 @@ 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[] = {
@@ -439,19 +673,25 @@ int main(int argc, char **argv)
{ "version", no_argument, 0, 'v' },
{ NULL, 0, 0, 0 }
};
- while ((c = getopt_long(argc, argv, "F:vhfbuoBUd", long_options, NULL))
+ while ((c = getopt_long(argc, argv, "F:vhfbciuoBUd", long_options, NULL))
!= EOF)
switch(c) {
case 'v':
- {
- printf("GNU grotty (groff) version %s\n", Version_string);
- exit(0);
- break;
- }
+ 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;
@@ -493,6 +733,13 @@ int main(int argc, char **argv)
default:
assert(0);
}
+ if (old_drawing_scheme)
+ italic_flag = 0;
+ else {
+ bold_underline_mode = BOLD_MODE|UNDERLINE_MODE;
+ bold_flag = 1;
+ underline_flag = 1;
+ }
if (optind >= argc)
do_file("-");
else {
@@ -505,6 +752,6 @@ int main(int argc, char **argv)
static void usage(FILE *stream)
{
- fprintf(stream, "usage: %s [-hfvbuodBU] [-F dir] [files ...]\n",
+ fprintf(stream, "usage: %s [-hfvbciuodBU] [-F dir] [files ...]\n",
program_name);
}
diff --git a/contrib/groff/src/include/Makefile.sub b/contrib/groff/src/include/Makefile.sub
index cee00d3..620d345 100644
--- a/contrib/groff/src/include/Makefile.sub
+++ b/contrib/groff/src/include/Makefile.sub
@@ -2,14 +2,16 @@ HDRS=\
assert.h \
cmap.h \
cset.h \
+ color.h \
device.h \
driver.h \
errarg.h \
error.h \
font.h \
+ geometry.h \
getopt.h \
groff-getopt.h \
- htmlindicate.h \
+ htmlhint.h \
index.h \
lib.h \
macropath.h \
@@ -22,7 +24,6 @@ HDRS=\
searchpath.h \
stringclass.h
GENHDRS=defs.h
-CLEANADD=$(GENHDRS)
all depend: $(GENHDRS)
diff --git a/contrib/groff/src/include/color.h b/contrib/groff/src/include/color.h
new file mode 100644
index 0000000..6888da1
--- /dev/null
+++ b/contrib/groff/src/include/color.h
@@ -0,0 +1,87 @@
+// -*- C++ -*-
+
+/* <groff_src_dir>/src/include/color.h
+
+Last update: 10 Apr 2002
+
+Copyright (C) 2001, 2002 Free Software Foundation, Inc.
+ Written by Gaius Mulley <gaius@glam.ac.uk>
+
+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 <stddef.h>
+
+enum color_scheme {DEFAULT, CMY, CMYK, RGB, GRAY};
+
+class color {
+private:
+ color_scheme scheme;
+ unsigned int components[4];
+
+ int read_encoding(const color_scheme, const char * const,
+ const size_t);
+
+public:
+ enum {MAX_COLOR_VAL = 0xffff};
+ color() : scheme(DEFAULT){}
+ color(const color * const);
+
+ int operator==(const color & c) const;
+ int operator!=(const color & c) const;
+
+ int is_default() { return scheme == DEFAULT; }
+
+ // set color from given color component values
+ void set_default();
+ void set_rgb(const unsigned int r, const unsigned int g,
+ const unsigned int b);
+ void set_cmy(const unsigned int c, const unsigned int m,
+ const unsigned int y);
+ void set_cmyk(const unsigned int c, const unsigned int m,
+ const unsigned int y, const unsigned int k);
+ void set_gray(const unsigned int g);
+
+ // set color from a color string
+ int read_rgb(const char * const s);
+ int read_cmy(const char * const s);
+ int read_cmyk(const char * const s);
+ int read_gray(const char * const s);
+
+ // Return the actual color scheme and retrieve the color components
+ // into a predefined vector (of length at least 4).
+ color_scheme get_components(unsigned int *c) const;
+
+ // retrieve the components of a color
+ void get_rgb(unsigned int *r, unsigned int *g, unsigned int *b) const;
+ void get_cmy(unsigned int *c, unsigned int *m, unsigned int *y) const;
+ void get_cmyk(unsigned int *c, unsigned int *m,
+ unsigned int *y, unsigned int *k) const;
+ void get_gray(unsigned int *g) const;
+};
+
+#define Cyan components[0]
+#define Magenta components[1]
+#define Yellow components[2]
+#define Black components[3]
+
+#define Red components[0]
+#define Green components[1]
+#define Blue components[2]
+
+#define Gray components[0]
+
+extern color default_color;
diff --git a/contrib/groff/src/include/config.hin b/contrib/groff/src/include/config.hin
new file mode 100644
index 0000000..850e317
--- /dev/null
+++ b/contrib/groff/src/include/config.hin
@@ -0,0 +1,150 @@
+/* src/include/config.hin. Generated automatically from configure.ac by autoheader. */
+
+/* Define if your C++ doesn't understand `delete []'. */
+#undef ARRAY_DELETE_NEEDS_SIZE
+
+/* Define if you have a C++ <limits.h>. */
+#undef HAVE_CC_LIMITS_H
+
+/* Define if you have a C++ <osfcn.h>. */
+#undef HAVE_CC_OSFCN_H
+
+/* Define if you have the <dirent.h> header file. */
+#undef HAVE_DIRENT_H
+
+/* Define if you have the `fmod' function. */
+#undef HAVE_FMOD
+
+/* Define if you have the `getcwd' function. */
+#undef HAVE_GETCWD
+
+/* Define if you have the `getpagesize' function. */
+#undef HAVE_GETPAGESIZE
+
+/* Define if you have the `gettimeofday' function. */
+#undef HAVE_GETTIMEOFDAY
+
+/* Define if you have the <limits.h> header file. */
+#undef HAVE_LIMITS_H
+
+/* Define if you have the <math.h> header file. */
+#undef HAVE_MATH_H
+
+/* Define if you have mkstemp(). */
+#undef HAVE_MKSTEMP
+
+/* Define if you have a working `mmap' system call. */
+#undef HAVE_MMAP
+
+/* Define if you have the `putenv' function. */
+#undef HAVE_PUTENV
+
+/* Define if you have the `rename' function. */
+#undef HAVE_RENAME
+
+/* Define if you have the `snprintf' function. */
+#undef HAVE_SNPRINTF
+
+/* Define if you have the `isatty' function. */
+#undef HAVE_ISATTY
+
+/* Define if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define if you have the `strcasecmp' function. */
+#undef HAVE_STRCASECMP
+
+/* Define if you have the `strerror' function. */
+#undef HAVE_STRERROR
+
+/* Define if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define if you have the `strncasecmp' function. */
+#undef HAVE_STRNCASECMP
+
+/* Define if you have the `strsep' function. */
+#undef HAVE_STRSEP
+
+/* Define if you have the `strtol' function. */
+#undef HAVE_STRTOL
+
+/* Define if <math.h> defines struct exception. */
+#undef HAVE_STRUCT_EXCEPTION
+
+/* Define if you have the <sys/dir.h> header file. */
+#undef HAVE_SYS_DIR_H
+
+/* Define if you have sys_errlist in <errno.h> or in <stdio.h>. */
+#undef HAVE_SYS_ERRLIST
+
+/* Define if you have sysnerr in <errno.h> or <stdio.h>. */
+#undef HAVE_SYS_NERR
+
+/* Define if you have the <sys/time.h> header file. */
+#undef HAVE_SYS_TIME_H
+
+/* Define if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define if the host's encoding is EBCDIC. */
+#undef IS_EBCDIC_HOST
+
+/* Define if localtime() takes a long * not a time_t *. */
+#undef LONG_FOR_TIME_T
+
+/* Define if your C++ doesn't declare gettimeofday(). */
+#undef NEED_DECLARATION_GETTIMEOFDAY
+
+/* Define if your C++ doesn't declare hypot(). */
+#undef NEED_DECLARATION_HYPOT
+
+/* Define if your C++ doesn't declare pclose(). */
+#undef NEED_DECLARATION_PCLOSE
+
+/* Define if your C++ doesn't declare popen(). */
+#undef NEED_DECLARATION_POPEN
+
+/* Define if your C++ doesn't declare putenv(). */
+#undef NEED_DECLARATION_PUTENV
+
+/* Define if your C++ doesn't declare strcasecmp(). */
+#undef NEED_DECLARATION_STRCASECMP
+
+/* Define if your C++ doesn't declare strncasecmp(). */
+#undef NEED_DECLARATION_STRNCASECMP
+
+/* Define if the printer's page size is A4. */
+#undef PAGEA4
+
+/* Define as the return type of signal handlers (`int' or `void'). */
+#undef RETSIGTYPE
+
+/* Define if srand() returns void not int. */
+#undef RET_TYPE_SRAND_IS_VOID
+
+/* Define if `sys_siglist' is declared by <signal.h> or <unistd.h>. */
+#undef SYS_SIGLIST_DECLARED
+
+/* Define if your C++ compiler uses a traditional (Reiser) preprocessor. */
+#undef TRADITIONAL_CPP
+
+/* Define if the 0200 bit of the status returned by wait() indicates whether a
+ core image was produced for a process that was terminated by a signal. */
+#undef WCOREFLAG
+
+/* Define if -D_POSIX_SOURCE is necessary. */
+#undef _POSIX_SOURCE
+
+/* Define if you have ISC 3.x or 4.x. */
+#undef _SYSV3
+
+/* Define uintmax_t to `unsigned long' or `unsigned long long' if <inttypes.h>
+ does not exist. */
+#undef uintmax_t
diff --git a/contrib/groff/src/include/driver.h b/contrib/groff/src/include/driver.h
index 97eb891..d957928 100644
--- a/contrib/groff/src/include/driver.h
+++ b/contrib/groff/src/include/driver.h
@@ -1,5 +1,6 @@
// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992, 2000 Free Software Foundation, Inc.
+/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001
+ Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
This file is part of groff.
@@ -18,7 +19,8 @@ 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 <stdio.h>
+#include "lib.h"
+
#include <ctype.h>
#include <stdlib.h>
#include <stddef.h>
@@ -29,7 +31,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "error.h"
#include "font.h"
#include "printer.h"
-#include "lib.h"
+#include "geometry.h"
void do_file(const char *);
extern printer *pr;
diff --git a/contrib/groff/src/include/errarg.h b/contrib/groff/src/include/errarg.h
index 0c7957c..08af44a 100644
--- a/contrib/groff/src/include/errarg.h
+++ b/contrib/groff/src/include/errarg.h
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+/* Copyright (C) 1989, 1990, 1991, 1992, 2002 Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
This file is part of groff.
@@ -19,10 +19,11 @@ with groff; see the file COPYING. If not, write to the Free Software
Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
class errarg {
- enum { EMPTY, STRING, CHAR, INTEGER, DOUBLE } type;
+ enum { EMPTY, STRING, CHAR, INTEGER, UNSIGNED_INTEGER, DOUBLE } type;
union {
const char *s;
int n;
+ unsigned int u;
char c;
double d;
};
@@ -32,6 +33,7 @@ class errarg {
errarg(char);
errarg(unsigned char);
errarg(int);
+ errarg(unsigned int);
errarg(double);
int empty() const;
void print() const;
@@ -43,4 +45,3 @@ extern void errprint(const char *,
const errarg &arg1 = empty_errarg,
const errarg &arg2 = empty_errarg,
const errarg &arg3 = empty_errarg);
-
diff --git a/contrib/groff/src/include/font.h b/contrib/groff/src/include/font.h
index 099f97b..43bf121 100644
--- a/contrib/groff/src/include/font.h
+++ b/contrib/groff/src/include/font.h
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+/* Copyright (C) 1989, 1990, 1991, 1992, 2002 Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
This file is part of groff.
@@ -54,6 +54,8 @@ public:
const char *get_name();
const char *get_internal_name();
+ static int scan_papersize(const char *, const char **, double *, double *);
+
static font *load_font(const char *, int *not_found = 0);
static void command_line_font_dir(const char *path);
static FILE *open_file(const char *name, char **pathp);
@@ -69,6 +71,7 @@ public:
static int unitwidth;
static int paperwidth;
static int paperlength;
+ static const char *papersize;
static int biggestfont;
static int spare2;
static int sizescale;
@@ -107,6 +110,7 @@ private:
void compact();
static int scale(int w, int pointsize);
+ static int unit_scale(double *value, char unit);
virtual void handle_unknown_font_command(const char *command,
const char *arg,
const char *file, int lineno);
diff --git a/contrib/groff/src/include/geometry.h b/contrib/groff/src/include/geometry.h
new file mode 100644
index 0000000..d425f15
--- /dev/null
+++ b/contrib/groff/src/include/geometry.h
@@ -0,0 +1,27 @@
+// -*- C++ -*-
+/* Copyright (C) 2001 Free Software Foundation, Inc.
+ Written by Gaius Mulley <gaius@glam.ac.uk>
+
+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. */
+
+int adjust_arc_center(const int *, double *);
+void check_output_arc_limits(int x, int y,
+ int xv1, int yv1,
+ int xv2, int yv2,
+ double c0, double c1,
+ int *minx, int *maxx,
+ int *miny, int *maxy);
diff --git a/contrib/groff/src/include/getopt.h b/contrib/groff/src/include/getopt.h
index c2f0180..4283c35 100644
--- a/contrib/groff/src/include/getopt.h
+++ b/contrib/groff/src/include/getopt.h
@@ -3,19 +3,19 @@
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
The GNU C Library 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
- Library General Public License for more details.
+ Lesser General Public License for more details.
- You should have received a copy of the GNU Library General Public
- License along with the GNU C Library; see the file COPYING.LIB. If not,
- write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
#ifndef _GETOPT_H
@@ -142,20 +142,21 @@ struct option
/* Many other libraries have conflicting prototypes for getopt, with
differences in the consts, in stdlib.h. To avoid compilation
errors, only prototype getopt for the GNU C library. */
-extern int getopt (int __argc, char *const *__argv, const char *__shortopts);
+extern int getopt (int ___argc, char *const *___argv, const char *__shortopts);
# else /* not __GNU_LIBRARY__ */
extern int getopt ();
# endif /* __GNU_LIBRARY__ */
# ifndef __need_getopt
-extern int getopt_long (int __argc, char *const *__argv, const char *__shortopts,
+extern int getopt_long (int ___argc, char *const *___argv,
+ const char *__shortopts,
const struct option *__longopts, int *__longind);
-extern int getopt_long_only (int __argc, char *const *__argv,
+extern int getopt_long_only (int ___argc, char *const *___argv,
const char *__shortopts,
const struct option *__longopts, int *__longind);
/* Internal only. Users should not call this directly. */
-extern int _getopt_internal (int __argc, char *const *__argv,
+extern int _getopt_internal (int ___argc, char *const *___argv,
const char *__shortopts,
const struct option *__longopts, int *__longind,
int __long_only);
diff --git a/contrib/groff/src/include/html-strings.h b/contrib/groff/src/include/html-strings.h
index 710e8d7..23a36d1 100644
--- a/contrib/groff/src/include/html-strings.h
+++ b/contrib/groff/src/include/html-strings.h
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 2001 Free Software Foundation, Inc.
+/* Copyright (C) 2001, 2002 Free Software Foundation, Inc.
Written by Gaius Mulley (gaius@glam.ac.uk).
This file is part of groff.
@@ -25,7 +25,3 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#define HTML_IMAGE_INLINE_BEGIN "\\O[HTML-IMAGE-INLINE-BEGIN]"
#define HTML_IMAGE_INLINE_END "\\O[HTML-IMAGE-INLINE-END]"
-#define HTML_IMAGE_CENTERED ".HTML-IMAGE"
-#define HTML_IMAGE_RIGHT ".HTML-IMAGE-RIGHT"
-#define HTML_IMAGE_LEFT ".HTML-IMAGE-LEFT"
-#define HTML_IMAGE_END ".HTML-IMAGE-END"
diff --git a/contrib/groff/src/include/htmlhint.h b/contrib/groff/src/include/htmlhint.h
new file mode 100644
index 0000000..f1f46f7
--- /dev/null
+++ b/contrib/groff/src/include/htmlhint.h
@@ -0,0 +1,37 @@
+// -*- C++ -*-
+/* Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
+ Written by Gaius Mulley <gaius@glam.ac.uk>
+
+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. */
+
+#ifndef HTMLINDICATE_H
+#define HTMLINDICATE_H
+
+/*
+ * html_begin_suppress - suppresses output for the html device
+ * and resets the min/max registers for -Tps.
+ * Only called for inline images (such as eqn).
+ *
+ */
+extern void html_begin_suppress();
+
+/*
+ * html_end_suppress - end the suppression of output.
+ */
+extern void html_end_suppress();
+
+#endif
diff --git a/contrib/groff/src/include/lib.h b/contrib/groff/src/include/lib.h
index db5277c..c6468e0 100644
--- a/contrib/groff/src/include/lib.h
+++ b/contrib/groff/src/include/lib.h
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 1989-2000, 2001 Free Software Foundation, Inc.
+/* Copyright (C) 1989-2000, 2001, 2002 Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
This file is part of groff.
@@ -18,20 +18,30 @@ 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. */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
extern "C" {
#ifndef HAVE_STRERROR
char *strerror(int);
#endif
const char *i_to_a(int);
+ const char *ui_to_a(unsigned int);
const char *if_to_a(int, int);
}
-/* stdio.h on IRIX, OSF/1, and UWIN includes getopt.h */
+/* stdio.h on IRIX, OSF/1, emx, and UWIN include getopt.h */
+/* unistd.h on CYGWIN includes getopt.h */
#if !(defined(__sgi) \
|| (defined(__osf__) && defined(__alpha)) \
- || defined(_UWIN))
+ || defined(_UWIN) \
+ || defined(__EMX__) \
+ || defined(__CYGWIN__))
#include <groff-getopt.h>
+#else
+#include <getopt.h>
#endif
char *strsave(const char *s);
@@ -43,31 +53,54 @@ int is_prime(unsigned);
#include <strings.h>
#endif
-FILE *xtmpfile(char **namep = 0, char *postfix = 0, int do_unlink = 1);
-char *xtmptemplate(char *extension = 0);
+#ifndef HAVE_SNPRINTF
+#include <stdarg.h>
+extern "C" {
+ int snprintf(char *, size_t, const char *, /*args*/ ...);
+ int vsnprintf(char *, size_t, const char *, va_list);
+}
+#endif
+
+#ifndef HAVE_MKSTEMP
+/* since mkstemp() is defined as a real C++ function if taken from
+ groff's mkstemp.cc we need a declaration */
+int mkstemp(char *tmpl);
+#endif /* HAVE_MKSTEMP */
-#ifdef NEED_DECLARATION_POPEN
+int mksdir(char *tmpl);
-extern "C" { FILE *popen(const char *, const char *); }
+FILE *xtmpfile(char **namep = 0,
+ const char *postfix_long = 0, const char *postfix_short = 0,
+ int do_unlink = 1);
+char *xtmptemplate(const char *postfix_long, const char *postfix_short);
+#ifdef NEED_DECLARATION_POPEN
+extern "C" { FILE *popen(const char *, const char *); }
#endif /* NEED_DECLARATION_POPEN */
#ifdef NEED_DECLARATION_PCLOSE
-
extern "C" { int pclose (FILE *); }
-
#endif /* NEED_DECLARATION_PCLOSE */
size_t file_name_max(const char *fname);
int interpret_lf_args(const char *p);
-extern char illegal_char_table[];
+extern char invalid_char_table[];
-inline int illegal_input_char(int c)
+inline int invalid_input_char(int c)
{
- return c >= 0 && illegal_char_table[c];
+ return c >= 0 && invalid_char_table[c];
+}
+
+#ifdef HAVE_STRCASECMP
+#ifdef NEED_DECLARATION_STRCASECMP
+extern "C" {
+ // Ultrix4.3's string.h fails to declare this.
+ int strcasecmp(const char *, const char *);
}
+#endif /* NEED_DECLARATION_STRCASECMP */
+#endif /* HAVE_STRCASECMP */
#if !defined(_AIX) && !defined(sinix) && !defined(__sinix__)
#ifdef HAVE_STRNCASECMP
diff --git a/contrib/groff/src/include/nonposix.h b/contrib/groff/src/include/nonposix.h
index abd7d1e..86aa2e0 100644
--- a/contrib/groff/src/include/nonposix.h
+++ b/contrib/groff/src/include/nonposix.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000 Free Software Foundation, Inc.
+/* Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
Written by Eli Zaretskii (eliz@is.elta.co.il)
This file is part of groff.
@@ -24,11 +24,10 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
# ifndef _WIN32
# define _WIN32
# endif
-# define setmode(f,m) _setmode(f,m)
#endif
#if defined(__MSDOS__) \
- || (defined(_WIN32) && !defined(_UWIN) && !defined(__CYGWIN32__))
+ || (defined(_WIN32) && !defined(_UWIN) && !defined(__CYGWIN__))
/* Binary I/O nuisances. Note: "setmode" is right for DJGPP and
Borland; Windows compilers might need _setmode or some such. */
@@ -37,17 +36,21 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
# ifdef HAVE_UNISTD_H
# include <unistd.h>
# endif
-# define SET_BINARY(f) do {if (!isatty(f)) setmode(f,O_BINARY);} while(0)
-# define FOPEN_RB "rb"
-# define FOPEN_WB "wb"
-# define FOPEN_RWB "wb+"
# ifdef _MSC_VER
# define POPEN_RT "rt"
# define POPEN_WT "wt"
# define popen(c,m) _popen(c,m)
# define pclose(p) _pclose(p)
# define getpid() (1)
+# define mkdir(p,m) _mkdir(p)
+# define setmode(f,m) _setmode(f,m)
+# define WAIT(s,p,m) _cwait(s,p,m)
+# define creat(p,m) _creat(p,m)
# endif
+# define SET_BINARY(f) do {if (!isatty(f)) setmode(f,O_BINARY);} while(0)
+# define FOPEN_RB "rb"
+# define FOPEN_WB "wb"
+# define FOPEN_RWB "wb+"
# ifndef O_BINARY
# ifdef _O_BINARY
# define O_BINARY (_O_BINARY)
@@ -135,3 +138,12 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#ifndef NULL_DEV
# define NULL_DEV "/dev/null"
#endif
+#ifndef GS_NAME
+# define GS_NAME "gs"
+#endif
+#ifndef WAIT
+# define WAIT(s,p,m) wait(s)
+#endif
+#ifndef _WAIT_CHILD
+# define _WAIT_CHILD 0
+#endif
diff --git a/contrib/groff/src/include/paper.h b/contrib/groff/src/include/paper.h
new file mode 100644
index 0000000..7a01fc2
--- /dev/null
+++ b/contrib/groff/src/include/paper.h
@@ -0,0 +1,37 @@
+// -*- C++ -*-
+/* Copyright (C) 2002 Free Software Foundation, Inc.
+ Written by Werner Lemberg (wl@gnu.org)
+
+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. */
+
+struct paper {
+ char *name;
+ double length; // in PS points
+ double width; // in PS points
+};
+
+// global constructor
+static class papersize_init {
+ static int initialised;
+public:
+ papersize_init();
+} _papersize_init;
+
+// A0-A7, B0-B7, C0-C7, D0-D7, 8 American paper sizes, 1 special size */
+#define NUM_PAPERSIZES 4*8 + 8 + 1
+
+extern paper papersizes[];
diff --git a/contrib/groff/src/include/posix.h b/contrib/groff/src/include/posix.h
index 1b7d5cd..e7f38cd 100644
--- a/contrib/groff/src/include/posix.h
+++ b/contrib/groff/src/include/posix.h
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 1992, 2000 Free Software Foundation, Inc.
+/* Copyright (C) 1992, 2000, 2001 Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
This file is part of groff.
@@ -42,6 +42,14 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#define S_IROTH 0004
#endif
+#ifndef S_IWUSR
+#define S_IWUSR 0200
+#endif
+
+#ifndef S_IXUSR
+#define S_IXUSR 0100
+#endif
+
#ifndef S_ISREG
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
#endif
@@ -49,3 +57,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#ifndef O_RDONLY
#define O_RDONLY 0
#endif
+
+#ifndef HAVE_ISATTY
+#define isatty(n) (1)
+#endif
diff --git a/contrib/groff/src/include/printer.h b/contrib/groff/src/include/printer.h
index beae4d9..4d5cbf5 100644
--- a/contrib/groff/src/include/printer.h
+++ b/contrib/groff/src/include/printer.h
@@ -1,22 +1,42 @@
// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992, 2001 Free Software Foundation, Inc.
- Written by James Clark (jjc@jclark.com)
-This file is part of groff.
+// <groff_src_dir>/src/include/printer.h
-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.
+/* Copyright (C) 1989, 1990, 1991, 1992, 2001, 2002
+ Free Software Foundation, Inc.
-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.
+ Written by James Clark (jjc@jclark.com)
-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. */
+ Last update: 12 Apr 2002
+
+ 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.
+*/
+
+/* Description
+
+ The class `printer' performs the postprocessing. Each
+ postprocessor only need to implement a derived class of `printer' and
+ a suitable function `make_printer' for the device-dependent tasks.
+ Then the methods of class `printer' are called automatically by
+ `do_file()' in `input.cc'.
+*/
+
+#include "color.h"
struct environment {
int fontno;
@@ -25,6 +45,8 @@ struct environment {
int vpos;
int height;
int slant;
+ color *col;
+ color *fill;
};
struct font;
@@ -45,17 +67,22 @@ public:
int *widthp = 0);
void set_special_char(const char *nm, const environment *env,
int *widthp = 0);
- void set_numbered_char(int n, const environment *env, int *widthp = 0);
+ void set_numbered_char(int n, const environment *env,
+ int *widthp = 0);
int set_char_and_width(const char *nm, const environment *env,
int *widthp, font **f);
font *get_font_from_index(int fontno);
virtual void draw(int code, int *p, int np, const environment *env);
+ // perform change of line color (text, outline) in the print-out
+ virtual void change_color(const environment * const env);
+ // perform change of fill color in the print-out
+ virtual void change_fill_color(const environment * const env);
virtual void begin_page(int) = 0;
virtual void end_page(int page_length) = 0;
virtual font *make_font(const char *nm);
virtual void end_of_line();
- virtual void special(char *arg, const environment *env, char type = 'p');
- static int adjust_arc_center(const int *, double *);
+ virtual void special(char *arg, const environment *env,
+ char type = 'p');
protected:
font_pointer_list *font_list;
diff --git a/contrib/groff/src/include/stringclass.h b/contrib/groff/src/include/stringclass.h
index be3a044..c6295b0 100644
--- a/contrib/groff/src/include/stringclass.h
+++ b/contrib/groff/src/include/stringclass.h
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+/* Copyright (C) 1989, 1990, 1991, 1992, 2002 Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
This file is part of groff.
@@ -67,6 +67,7 @@ public:
const char *contents() const;
int search(char) const;
char *extract() const;
+ void remove_spaces();
void clear();
void move(string &);
@@ -122,7 +123,7 @@ inline int string::operator*() const
inline const char *string::contents() const
{
- return ptr;
+ return ptr;
}
inline string operator+(const string &s1, const string &s2)
diff --git a/contrib/groff/src/libs/libbib/Makefile.sub b/contrib/groff/src/libs/libbib/Makefile.sub
index 482f01a..6e59d64 100644
--- a/contrib/groff/src/libs/libbib/Makefile.sub
+++ b/contrib/groff/src/libs/libbib/Makefile.sub
@@ -1,10 +1,10 @@
LIB=bib
OBJS=\
- common.o \
- index.o \
- linear.o \
- search.o \
- map.o
+ common.$(OBJEXT) \
+ index.$(OBJEXT) \
+ linear.$(OBJEXT) \
+ search.$(OBJEXT) \
+ map.$(OBJEXT)
CCSRCS=\
$(srcdir)/common.cc \
$(srcdir)/index.cc \
diff --git a/contrib/groff/src/libs/libbib/index.cc b/contrib/groff/src/libs/libbib/index.cc
index 4d836a0..3633df1 100644
--- a/contrib/groff/src/libs/libbib/index.cc
+++ b/contrib/groff/src/libs/libbib/index.cc
@@ -18,13 +18,12 @@ 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 <stdio.h>
-#include <string.h>
+#include "lib.h"
+
#include <stdlib.h>
#include <errno.h>
#include "posix.h"
-#include "lib.h"
#include "cset.h"
#include "cmap.h"
#include "errarg.h"
diff --git a/contrib/groff/src/libs/libbib/linear.cc b/contrib/groff/src/libs/libbib/linear.cc
index a8c2a55..1dd902b 100644
--- a/contrib/groff/src/libs/libbib/linear.cc
+++ b/contrib/groff/src/libs/libbib/linear.cc
@@ -1,5 +1,6 @@
// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001
+ Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
This file is part of groff.
@@ -18,14 +19,13 @@ 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 "lib.h"
-#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <errno.h>
#include "posix.h"
-#include "lib.h"
#include "errarg.h"
#include "error.h"
#include "cset.h"
diff --git a/contrib/groff/src/libs/libbib/map.c b/contrib/groff/src/libs/libbib/map.c
index ee5d008..4d878a2 100644
--- a/contrib/groff/src/libs/libbib/map.c
+++ b/contrib/groff/src/libs/libbib/map.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001
+ Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
This file is part of groff.
@@ -17,6 +18,12 @@ 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 <stdlib.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
#ifdef HAVE_MMAP
#include <sys/types.h>
diff --git a/contrib/groff/src/libs/libbib/search.cc b/contrib/groff/src/libs/libbib/search.cc
index 1e027c6..2223fb6 100644
--- a/contrib/groff/src/libs/libbib/search.cc
+++ b/contrib/groff/src/libs/libbib/search.cc
@@ -1,5 +1,6 @@
// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001
+ Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
This file is part of groff.
@@ -18,13 +19,13 @@ 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 "lib.h"
+
#include <stdlib.h>
-#include <string.h>
#include <assert.h>
#include <errno.h>
#include "posix.h"
-#include "lib.h"
#include "errarg.h"
#include "error.h"
#include "nonposix.h"
diff --git a/contrib/groff/src/libs/libdriver/Makefile.sub b/contrib/groff/src/libs/libdriver/Makefile.sub
index d50f060..547b8c0 100644
--- a/contrib/groff/src/libs/libdriver/Makefile.sub
+++ b/contrib/groff/src/libs/libdriver/Makefile.sub
@@ -1,7 +1,7 @@
LIB=driver
OBJS=\
- input.o \
- printer.o
+ input.$(OBJEXT) \
+ printer.$(OBJEXT)
CCSRCS=\
$(srcdir)/input.cc \
$(srcdir)/printer.cc
diff --git a/contrib/groff/src/libs/libdriver/input.cc b/contrib/groff/src/libs/libdriver/input.cc
index e19841c..a02c139 100644
--- a/contrib/groff/src/libs/libdriver/input.cc
+++ b/contrib/groff/src/libs/libdriver/input.cc
@@ -1,504 +1,1814 @@
// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992, 2001 Free Software Foundation, Inc.
- Written by James Clark (jjc@jclark.com)
-This file is part of groff.
+// <groff_src_dir>/src/libs/libdriver/input.cc
-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.
+/* Copyright (C) 1989, 1990, 1991, 1992, 2001, 2002
+ Free Software Foundation, Inc.
-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.
+ Written by James Clark (jjc@jclark.com)
+ Major rewrite 2001 by Bernd Warken (bwarken@mayn.de)
-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. */
+ Last update: 12 Apr 2002
+
+ This file is part of groff, the GNU roff text processing system.
+
+ 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.
+*/
+
+/* Description
+
+ This file implements the parser for the intermediate groff output,
+ see groff_out(5), and does the printout for the given device.
+
+ All parsed information is processed within the function do_file() by
+ using the global object `pr' of class `printer'. So a device
+ postprocessor just needs to fill in the methods for the class
+ `printer' without having to worry about the syntax of the
+ intermediate output format. Consequently, the programming of groff
+ postprocessors is similar to the development of device-drivers.
+
+ The prototyping for this file is done in driver.h (and error.h).
+
+ Postprocessor programs must deallocate the global variables `pr' and
+ `device' using `delete', and `current_filename' using
+ `free((char *))'.
+*/
+
+/* Changes of the 2001 rewrite of this file.
+
+ The interface to the outside and the handling of the global
+ variables was not changed, but internally many necessary changes
+ were performed.
+
+ The main aim for this rewrite is to provide a first step towards
+ making groff fully compatible with classical troff without pain.
+
+ Bugs fixed
+ - Unknown subcommands of `D' and `x' are now ignored like in the
+ classical case, but a warning is issued. This was also
+ implemented for the other commands.
+ - A warning is emitted if `x stop' is missing.
+ - `DC' and `DE' commands didn't position to the right end after
+ drawing (now they do), see discussion below.
+ - So far, `x stop' was ignored. Now it terminates the processing
+ of the current intermediate output file like the classical troff.
+ - The command `c' didn't check correctly on white-space.
+ - The environment stack wasn't suitable for the color extensions
+ (replaced by a class).
+ - The old groff parser could only handle a prologue with the first
+ 3 lines having a fixed structure, while classical troff specified
+ the sequence of the first 3 commands without further
+ restrictions. Now the parser is smart about additional
+ white space, comments, and empty lines in the prologue.
+ - The old parser allowed space characters only as syntactical
+ separators, while classical troff had tab characters as well.
+ Now any sequence of tabs and/or spaces is a syntactical
+ separator between commands and/or arguments.
+ - Range checks for numbers implemented.
+
+ New and improved features
+ - The color commands `m' and `DF' are added.
+ - The old color command `Df' is now converted and delegated to `DFg'.
+ - The command `F' is implemented as `use intended file name'. It
+ checks whether its argument agrees with the file name used so far,
+ otherwise a warning is issued. Then the new name is remembered
+ and used for the following error messages.
+ - For the positioning after drawing commands, an alternative, easier
+ scheme is provided, but not yet activated; it can be chosen by
+ undefining the preprocessor macro STUPID_DRAWING_POSITIONING.
+ It extends the rule of the classical troff output language in a
+ logical way instead of the rather strange actual positioning.
+ For details, see the discussion below.
+ - For the `D' commands that only set the environment, the calling of
+ pr->send_draw() was removed because this doesn't make sense for
+ the `DF' commands; the (changed) environment is sent with the
+ next command anyway.
+ - Error handling was clearly separated into warnings and fatal.
+ - The error behavior on additional arguments for `D' and `x'
+ commands with a fixed number of arguments was changed from being
+ ignored (former groff) to issue a warning and ignore (now), see
+ skip_line_x(). No fatal was chosen because both string and
+ integer arguments can occur.
+ - The gtroff program issues a trailing dummy integer argument for
+ some drawing commands with an odd number of arguments to make the
+ number of arguments even, e.g. the DC and Dt commands; this is
+ honored now.
+ - All D commands with a variable number of args expect an even
+ number of trailing integer arguments, so fatal on error was
+ implemented.
+ - Disable environment stack and the commands `{' and `}' by making
+ them conditional on macro USE_ENV_STACK; actually, this is
+ undefined by default. There isn't any known application for these
+ features.
+
+ Cosmetics
+ - Nested `switch' commands are avoided by using more functions.
+ Dangerous 'fall-through's avoided.
+ - Commands and functions are sorted alphabetically (where possible).
+ - Dynamic arrays/buffers are now implemented as container classes.
+ - Some functions had an ugly return structure; this has been
+ streamlined by using classes.
+ - Use standard C math functions for number handling, so getting rid
+ of differences to '0'.
+ - The macro `IntArg' has been created for an easier transition
+ to guaranteed 32 bits integers (`int' is enough for GNU, while
+ ANSI only guarantees `long int' to have a length of 32 bits).
+ - The many usages of type `int' are differentiated by using `Char',
+ `bool', and `IntArg' where appropriate.
+ - To ease the calls of the local utility functions, the parser
+ variables `current_file', `npages', and `current_env'
+ (formerly env) were made global to the file (formerly they were
+ local to the do_file() function)
+ - Various comments were added.
+
+ TODO
+ - Get rid of the stupid drawing positioning.
+ - Can the `Dt' command be completely handled by setting environment
+ within do_file() instead of sending to pr?
+ - Integer arguments must be >= 32 bits, use conditional #define.
+ - Add scaling facility for classical device independence and
+ non-groff devices. Classical troff output had a quasi device
+ independence by scaling the intermediate output to the resolution
+ of the postprocessor device if different from the one specified
+ with `x T', groff have not. So implement full quasi device
+ indepedence, including the mapping of the strange classical
+ devices to the postprocessor device (seems to be reasonably
+ easy).
+ - The external, global pointer variables are not optimally handled.
+ - `pr' isn't used outside besides initialization and deletion.
+ So it could be replaced by a static local variable. For
+ example, a wrapper class `Postprocessor' for class `printer' with
+ internal make_printer() and automatic clean-up would make sense.
+ - The global variables `current_filename' and `current_lineno' are
+ only used for error reporting. So implement a static class
+ `Error' (`::' calls).
+ - The global `device' is the name used during the formatting
+ process; there should be a new variable for the device name used
+ during the postprocessing.
+ - Implement the B-spline drawing `D~' for all graphical devices.
+ - Make `environment' a class with an overflow check for its members
+ and a delete method to get rid of delete_current_env().
+ - Implement the `EnvStack' to use `new' instead of `malloc'.
+ - The class definitions of this document could go into a new file.
+ - The comments in this section should go to a `Changelog' or some
+ `README' file in this directory.
+*/
+
+/*
+ Discussion of the positioning by drawing commands
+
+ There was some confusion about the positioning of the graphical
+ pointer at the printout after having executed a `D' command.
+ The classical troff manual of Osanna & Kernighan specified,
+
+ `The position after a graphical object has been drawn is
+ at its end; for circles and ellipses, the "end" is at the
+ right side.'
+
+ From this, it follows that
+ - all open figures (args, splines, and lines) should position at their
+ final point.
+ - all circles and ellipses should position at their right-most point
+ (as if 2 halves had been drawn).
+ - all closed figures apart from circles and ellipses shouldn't change
+ the position because they return to their origin.
+ - all setting commands should not change position because they do not
+ draw any graphical object.
+
+ In the case of the open figures, this means that the horizontal
+ displacement is the sum of all odd arguments and the vertical offset
+ the sum of all even arguments, called the alternate arguments sum
+ displacement in the following.
+
+ Unfortunately, groff did not implement this simple rule. The former
+ documentation in groff_out(5) differed from the source code, and
+ neither of them is compatible with the classical rule.
+
+ The former groff_out(5) specified to use the alternative arguments
+ sum displacement for calculating the drawing positioning of
+ non-classical commands, including the `Dt' command (setting-only)
+ and closed polygons. Applying this to the new groff color commands
+ will lead to disaster. For their arguments can take large values (>
+ 65000). On low resolution devices, the displacement of such large
+ values will corrupt the display or kill the printer. So the
+ nonsense specification has come to a natural end anyway.
+
+ The groff source code, however, had no positioning for the
+ setting-only commands (esp. `Dt'), the right-end positioning for
+ outlined circles and ellipses, and the alternative argument sum
+ displacement for all other commands (including filled circles and
+ ellipses).
+
+ The reason why no one seems to have suffered from this mayhem so
+ far is that the graphical objects are usually generated by
+ preprocessors like pic that do not depend on the automatic
+ positioning. When using the low level `\D' escape sequences or `D'
+ output commands, the strange positionings can be circumvented by
+ absolute positionings or by tricks like `\Z'.
+
+ So doing an exorcism on the strange, incompatible displacements might
+ not harm any existing documents, but will make the usage of the
+ graphical escape sequences and commands natural.
+
+ That's why the rewrite of this file returned to the reasonable,
+ classical specification with its clear end-of-drawing rule that is
+ suitable for all cases. But a macro STUPID_DRAWING_POSITIONING is
+ provided for testing the funny former behavior.
+
+ The new rule implies the following behavior.
+ - Setting commands (`Dt', `Df', `DF') and polygons (`Dp' and `DP')
+ do not change position now.
+ - Filled circles and ellipses (`DC' and `DE') position at their
+ most right point (outlined ones `Dc' and `De' did this anyway).
+ - As before, all open graphical objects position to their final
+ drawing point (alternate sum of the command arguments).
+
+*/
+
+#ifndef STUPID_DRAWING_POSITIONING
+// uncomment next line if all non-classical D commands shall position
+// to the strange alternate sum of args displacement
+#define STUPID_DRAWING_POSITIONING
+#endif
+
+// Decide whether the commands `{' and `}' for different environments
+// should be used.
+#undef USE_ENV_STACK
#include "driver.h"
#include "device.h"
-#include "cset.h"
-const char *current_filename=0;
-int current_lineno;
-const char *device = 0;
-FILE *current_file;
+#include <stdlib.h>
+#include <errno.h>
+#include <ctype.h>
+#include <math.h>
+
+
+/**********************************************************************
+ local types
+ **********************************************************************/
+
+// integer type used in the fields of struct environment (see printer.h)
+typedef int EnvInt;
-int get_integer(); // don't read the newline
-int possibly_get_integer(int *);
-char *get_string(int is_long = 0);
-void skip_line();
+// integer arguments of groff_out commands, must be >= 32 bits
+typedef int IntArg;
-struct environment_list {
- environment env;
- environment_list *next;
+// color components of groff_out color commands, must be >= 32 bits
+typedef unsigned int ColorArg;
+
+// Array for IntArg values.
+class IntArray {
+ size_t num_allocated;
+ size_t num_stored;
+ IntArg *data;
+public:
+ IntArray(void);
+ IntArray(const size_t);
+ ~IntArray(void);
+ const IntArg operator[](const size_t i) const
+ {
+ if (i >= num_stored || i < 0)
+ fatal("index out of range");
+ return (const IntArg) data[i];
+ }
+ void append(IntArg);
+ const IntArg * const
+ get_data(void) const { return (const IntArg * const) data; }
+ const size_t len(void) const { return num_stored; }
+};
+
+// Characters read from the input queue.
+class Char {
+ int data;
+public:
+ Char(void) : data('\0') {}
+ Char(const int c) : data(c) {}
+ bool operator==(char c) const { return (data == c) ? true : false; }
+ bool operator==(int c) const { return (data == c) ? true : false; }
+ bool operator==(const Char c) const
+ { return (data == c.data) ? true : false; }
+ bool operator!=(char c) const { return !(*this == c); }
+ bool operator!=(int c) const { return !(*this == c); }
+ bool operator!=(const Char c) const { return !(*this == c); }
+ operator int() const { return (int) data; }
+ operator unsigned char() const { return (unsigned char) data; }
+ operator char() const { return (char) data; }
+};
+
+// Buffer for string arguments (Char, not char).
+class StringBuf {
+ size_t num_allocated;
+ size_t num_stored;
+ Char *data; // not terminated by '\0'
+public:
+ StringBuf(void); // allocate without storing
+ ~StringBuf(void);
+ void append(const Char); // append character to `data'
+ char *make_string(void); // return new copy of `data' with '\0'
+ bool is_empty(void) { // true if none stored
+ return (num_stored > 0) ? false : true;
+ }
+ void reset(void); // set `num_stored' to 0
+};
- environment_list(const environment &, environment_list *);
+#ifdef USE_ENV_STACK
+class EnvStack {
+ environment **data;
+ size_t num_allocated;
+ size_t num_stored;
+public:
+ EnvStack(void);
+ ~EnvStack(void);
+ environment *pop(void);
+ void push(environment *e);
};
+#endif // USE_ENV_STACK
+
+
+/**********************************************************************
+ external variables
+ **********************************************************************/
+
+// exported as extern by error.h (called from driver.h)
+// needed for error messages (see ../libgroff/error.cc)
+const char *current_filename = 0; // printable name of the current file
+int current_lineno = 0; // current line number of printout
+
+// exported as extern by device.h;
+const char *device = 0; // cancel former init with literal
+
+// from driver.h; pr is kept between several runs of do_file()
+// extern printer *pr;
+
+// Note:
+//
+// We rely on an implementation of the `new' operator which aborts
+// gracefully if it can't allocate memory (e.g. from libgroff/new.cc).
+
+
+/**********************************************************************
+ static local variables
+ **********************************************************************/
+
+FILE *current_file = 0; // current input stream for parser
+
+// npages: number of pages processed so far (including current page),
+// _not_ the page number in the printout (can be set with `p').
+int npages = 0;
+
+const ColorArg
+COLORARG_MAX = (ColorArg) 65536U; // == 0xFFFF + 1 == 0x10000
+
+const IntArg
+INTARG_MAX = (IntArg) 0x7FFFFFFF; // maximal signed 32 bits number
+
+// parser environment, created and deleted by each run of do_file()
+environment *current_env = 0;
-environment_list::environment_list(const environment &e, environment_list *p)
-: env(e), next(p)
+#ifdef USE_ENV_STACK
+const size_t
+envp_size = sizeof(environment *);
+#endif // USE_ENV_STACK
+
+
+/**********************************************************************
+ function declarations
+ **********************************************************************/
+
+// utility functions
+ColorArg color_from_Df_command(IntArg);
+ // transform old color into new
+void delete_current_env(void); // delete global var current_env
+void fatal_command(char); // abort for invalid command
+inline Char get_char(void); // read next character from input stream
+ColorArg get_color_arg(void); // read in argument for new color cmds
+IntArray *get_D_fixed_args(const size_t);
+ // read in fixed number of integer
+ // arguments
+IntArray *get_D_fixed_args_odd_dummy(const size_t);
+ // read in a fixed number of integer
+ // arguments plus optional dummy
+IntArray *get_D_variable_args(void);
+ // variable, even number of int args
+char *get_extended_arg(void); // argument for `x X' (several lines)
+IntArg get_integer_arg(void); // read in next integer argument
+IntArray *get_possibly_integer_args();
+ // 0 or more integer arguments
+char *get_string_arg(void); // read in next string arg, ended by WS
+inline bool is_space_or_tab(const Char);
+ // test on space/tab char
+Char next_arg_begin(void); // skip white space on current line
+Char next_command(void); // go to next command, evt. diff. line
+inline bool odd(const int); // test if integer is odd
+void position_to_end_of_args(const IntArray * const);
+ // positioning after drawing
+void remember_filename(const char *);
+ // set global current_filename
+void send_draw(const Char, const IntArray * const);
+ // call pr->draw
+void skip_line(void); // unconditionally skip to next line
+bool skip_line_checked(void); // skip line, false if args are left
+void skip_line_fatal(void); // skip line, fatal if args are left
+void skip_line_warn(void); // skip line, warn if args are left
+void skip_line_D(void); // skip line in D commands
+void skip_line_x(void); // skip line in x commands
+void skip_to_end_of_line(void); // skip to the end of the current line
+inline void unget_char(const Char);
+ // restore character onto input
+
+// parser subcommands
+void parse_color_command(color *);
+ // color sub(sub)commands m and DF
+void parse_D_command(void); // graphical subcommands
+bool parse_x_command(void); // device controller subcommands
+
+
+/**********************************************************************
+ class methods
+ **********************************************************************/
+
+#ifdef USE_ENV_STACK
+EnvStack::EnvStack(void)
{
+ num_allocated = 4;
+ // allocate pointer to array of num_allocated pointers to environment
+ data = (environment **) malloc(envp_size * num_allocated);
+ if (data == 0)
+ fatal("could not allocate environment data");
+ num_stored = 0;
}
-inline int get_char()
+EnvStack::~EnvStack(void)
{
- return getc(current_file);
+ for (size_t i = 0; i < num_stored; i++)
+ delete data[i];
+ free(data);
}
-/*
- * remember_filename - is needed as get_string might overwrite the
- * filename eventually.
- */
+// return top element from stack and decrease stack pointer
+//
+// the calling function must take care of properly deleting the result
+environment *
+EnvStack::pop(void)
+{
+ num_stored--;
+ environment *result = data[num_stored];
+ data[num_stored] = 0;
+ return result;
+}
-void remember_filename(const char *filename)
+// copy argument and push this onto the stack
+void
+EnvStack::push(environment *e)
{
- if (current_filename != 0) {
- free((char *)current_filename);
+ environment *e_copy = new environment;
+ if (num_stored >= num_allocated) {
+ environment **old_data = data;
+ num_allocated *= 2;
+ data = (environment **) malloc(envp_size * num_allocated);
+ if (data == 0)
+ fatal("could not allocate data");
+ for (size_t i = 0; i < num_stored; i++)
+ data[i] = old_data[i];
+ free(old_data);
}
- if (strcmp(filename, "-") == 0) {
- filename = "<standard input>";
+ e_copy->col = new color;
+ e_copy->fill = new color;
+ *e_copy->col = *e->col;
+ *e_copy->fill = *e->fill;
+ e_copy->fontno = e->fontno;
+ e_copy->height = e->height;
+ e_copy->hpos = e->hpos;
+ e_copy->size = e->size;
+ e_copy->slant = e->slant;
+ e_copy->vpos = e->vpos;
+ data[num_stored] = e_copy;
+ num_stored++;
+}
+#endif // USE_ENV_STACK
+
+IntArray::IntArray(void)
+{
+ num_allocated = 4;
+ data = new IntArg[num_allocated];
+ num_stored = 0;
+}
+
+IntArray::IntArray(const size_t n)
+{
+ if (n <= 0)
+ fatal("number of integers to be allocated must be > 0");
+ num_allocated = n;
+ data = new IntArg[num_allocated];
+ num_stored = 0;
+}
+
+IntArray::~IntArray(void)
+{
+ a_delete data;
+}
+
+void
+IntArray::append(IntArg x)
+{
+ if (num_stored >= num_allocated) {
+ IntArg *old_data = data;
+ num_allocated *= 2;
+ data = new IntArg[num_allocated];
+ for (size_t i = 0; i < num_stored; i++)
+ data[i] = old_data[i];
+ a_delete old_data;
}
- current_filename = (const char *)malloc(strlen(filename) + 1);
- if (current_filename == 0) {
- fatal("can't malloc space for filename");
+ data[num_stored] = x;
+ num_stored++;
+}
+
+StringBuf::StringBuf(void)
+{
+ num_stored = 0;
+ num_allocated = 128;
+ data = new Char[num_allocated];
+}
+
+StringBuf::~StringBuf(void)
+{
+ a_delete data;
+}
+
+void
+StringBuf::append(const Char c)
+{
+ if (num_stored >= num_allocated) {
+ Char *old_data = data;
+ num_allocated *= 2;
+ data = new Char[num_allocated];
+ for (size_t i = 0; i < num_stored; i++)
+ data[i] = old_data[i];
+ a_delete old_data;
}
- strcpy((char *)current_filename, (char *)filename);
+ data[num_stored] = c;
+ num_stored++;
}
-void do_file(const char *filename)
+char *
+StringBuf::make_string(void)
{
- int npages = 0;
- if (filename[0] == '-' && filename[1] == '\0') {
- remember_filename(filename);
- current_file = stdin;
+ char *result = new char[num_stored + 1];
+ for (size_t i = 0; i < num_stored; i++)
+ result[i] = (char) data[i];
+ result[num_stored] = '\0';
+ return result;
+}
+
+void
+StringBuf::reset(void)
+{
+ num_stored = 0;
+}
+
+/**********************************************************************
+ utility functions
+ **********************************************************************/
+
+//////////////////////////////////////////////////////////////////////
+/* color_from_Df_command:
+ Process the gray shade setting command Df.
+
+ Transform Df style color into DF style color.
+ Df color: 0-1000, 0 is white
+ DF color: 0-65536, 0 is black
+
+ The Df command is obsoleted by command DFg, but kept for
+ compatibility.
+
+ XXX: Add proper handling for values < 0 or > 1000 as documented in
+ groff_out(5).
+*/
+ColorArg
+color_from_Df_command(IntArg Df_gray)
+{
+ if (Df_gray <= 0)
+ return COLORARG_MAX;
+ if (Df_gray >= 1000)
+ return 0;
+ return ColorArg((1000-Df_gray) * COLORARG_MAX / 1000); // scaling
+}
+
+//////////////////////////////////////////////////////////////////////
+/* delete_current_env():
+ Delete global variable current_env and its pointer members.
+
+ This should be a class method of environment.
+*/
+void delete_current_env(void)
+{
+ delete current_env->col;
+ delete current_env->fill;
+ delete current_env;
+}
+
+//////////////////////////////////////////////////////////////////////
+/* fatal_command():
+ Emit error message about invalid command and abort.
+*/
+void
+fatal_command(char command)
+{
+ fatal("`%1' command invalid before first `p' command", command);
+}
+
+//////////////////////////////////////////////////////////////////////
+/* get_char():
+ Retrieve the next character from the input queue.
+
+ Return: The retrieved character (incl. EOF), converted to Char.
+*/
+inline Char
+get_char(void)
+{
+ return (Char) getc(current_file);
+}
+
+//////////////////////////////////////////////////////////////////////
+/* get_color_arg():
+ Retrieve an argument suitable for the color commands m and DF.
+
+ Return: The retrieved color argument.
+*/
+ColorArg
+get_color_arg(void)
+{
+ IntArg x = get_integer_arg();
+ if (x < 0 || x > (IntArg)COLORARG_MAX) {
+ error("color component argument out of range");
+ x = 0;
}
- else {
- errno = 0;
- current_file = fopen(filename, "r");
- if (current_file == 0) {
- error("can't open `%1'", filename);
- return;
+ return (ColorArg) x;
+}
+
+//////////////////////////////////////////////////////////////////////
+/* get_D_fixed_args():
+ Get a fixed number of integer arguments for D commands.
+
+ Fatal if wrong number of arguments.
+ Too many arguments on the line raise a warning.
+ A line skip is done.
+
+ number: In-parameter, the number of arguments to be retrieved.
+ ignore: In-parameter, ignore next argument -- GNU troff always emits
+ pairs of parameters for `D' extensions added by groff.
+ Default is `false'.
+
+ Return: New IntArray containing the arguments.
+*/
+IntArray *
+get_D_fixed_args(const size_t number)
+{
+ if (number <= 0)
+ fatal("requested number of arguments must be > 0");
+ IntArray *args = new IntArray(number);
+ for (size_t i = 0; i < number; i++)
+ args->append(get_integer_arg());
+ skip_line_D();
+ return args;
+}
+
+//////////////////////////////////////////////////////////////////////
+/* get_D_fixed_args_odd_dummy():
+ Get a fixed number of integer arguments for D commands and optionally
+ ignore a dummy integer argument if the requested number is odd.
+
+ The gtroff program adds a dummy argument to some commands to get
+ an even number of arguments.
+ Error if the number of arguments differs from the scheme above.
+ A line skip is done.
+
+ number: In-parameter, the number of arguments to be retrieved.
+
+ Return: New IntArray containing the arguments.
+*/
+IntArray *
+get_D_fixed_args_odd_dummy(const size_t number)
+{
+ if (number <= 0)
+ fatal("requested number of arguments must be > 0");
+ IntArray *args = new IntArray(number);
+ for (size_t i = 0; i < number; i++)
+ args->append(get_integer_arg());
+ if (odd(number)) {
+ IntArray *a = get_possibly_integer_args();
+ if (a->len() > 1)
+ error("too many arguments");
+ delete a;
+ }
+ skip_line_D();
+ return args;
+}
+
+//////////////////////////////////////////////////////////////////////
+/* get_D_variable_args():
+ Get a variable even number of integer arguments for D commands.
+
+ Get as many integer arguments as possible from the rest of the
+ current line.
+ - The arguments are separated by an arbitrary sequence of space or
+ tab characters.
+ - A comment, a newline, or EOF indicates the end of processing.
+ - Error on non-digit characters different from these.
+ - A final line skip is performed (except for EOF).
+
+ Return: New IntArray of the retrieved arguments.
+*/
+IntArray *
+get_D_variable_args()
+{
+ IntArray *args = get_possibly_integer_args();
+ size_t n = args->len();
+ if (n <= 0)
+ error("no arguments found");
+ if (odd(n))
+ error("even number of arguments expected");
+ skip_line_D();
+ return args;
+}
+
+//////////////////////////////////////////////////////////////////////
+/* get_extended_arg():
+ Retrieve extended arg for `x X' command.
+
+ - Skip leading spaces and tabs, error on EOL or newline.
+ - Return everything before the next NL or EOF ('#' is not a comment);
+ as long as the following line starts with '+' this is returned
+ as well, with the '+' replaced by a newline.
+ - Final line skip is always performed.
+
+ Return: Allocated (new) string of retrieved text argument.
+*/
+char *
+get_extended_arg(void)
+{
+ StringBuf buf = StringBuf();
+ Char c = next_arg_begin();
+ while ((int) c != EOF) {
+ if ((int) c == '\n') {
+ current_lineno++;
+ c = get_char();
+ if ((int) c == '+')
+ buf.append((Char) '\n');
+ else {
+ unget_char(c); // first character of next line
+ break;
+ }
}
- remember_filename(filename);
+ else
+ buf.append(c);
+ c = get_char();
}
- environment env;
- env.vpos = -1;
- env.hpos = -1;
- env.fontno = -1;
- env.height = 0;
- env.slant = 0;
- environment_list *env_list = 0;
- current_lineno = 1;
- int command;
- char *s;
- command = get_char();
- if (command == EOF)
- return;
- if (command != 'x')
- fatal("the first command must be `x T'");
- s = get_string();
- if (s[0] != 'T')
- fatal("the first command must be `x T'");
- char *dev = get_string();
- if (pr == 0) {
- device = strsave(dev);
- if (!font::load_desc())
- fatal("sorry, I can't continue");
+ return buf.make_string();
+}
+
+//////////////////////////////////////////////////////////////////////
+/* get_integer_arg(): Retrieve integer argument.
+
+ Skip leading spaces and tabs, collect an optional '-' and all
+ following decimal digits (at least one) up to the next non-digit,
+ which is restored onto the input queue.
+
+ Fatal error on all other situations.
+
+ Return: Retrieved integer.
+*/
+IntArg
+get_integer_arg(void)
+{
+ StringBuf buf = StringBuf();
+ Char c = next_arg_begin();
+ if ((int) c == '-') {
+ buf.append(c);
+ c = get_char();
}
- else {
- if (device == 0 || strcmp(device, dev) != 0)
- fatal("all files must use the same device");
+ if (!isdigit((int) c))
+ error("integer argument expected");
+ while (isdigit((int) c)) {
+ buf.append(c);
+ c = get_char();
}
- skip_line();
- env.size = 10*font::sizescale;
- command = get_char();
- if (command != 'x')
- fatal("the second command must be `x res'");
- s = get_string();
- if (s[0] != 'r')
- fatal("the second command must be `x res'");
- int n = get_integer();
- if (n != font::res)
- fatal("resolution does not match");
- n = get_integer();
- if (n != font::hor)
- fatal("horizontal resolution does not match");
- n = get_integer();
- if (n != font::vert)
- fatal("vertical resolution does not match");
- skip_line();
- command = get_char();
- if (command != 'x')
- fatal("the third command must be `x init'");
- s = get_string();
- if (s[0] != 'i')
- fatal("the third command must be `x init'");
- skip_line();
- if (pr == 0)
- pr = make_printer();
- while ((command = get_char()) != EOF) {
- switch (command) {
- case 's':
- env.size = get_integer();
- if (env.height == env.size)
- env.height = 0;
- break;
- case 'f':
- env.fontno = get_integer();
- break;
- case 'F':
- remember_filename(get_string());
- break;
- case 'C':
- {
- if (npages == 0)
- fatal("`C' command illegal before first `p' command");
- char *s = get_string();
- pr->set_special_char(s, &env);
+ // c is not a digit
+ unget_char(c);
+ char *s = buf.make_string();
+ errno = 0;
+ long int number = strtol(s, 0, 10);
+ if (errno != 0
+ || number > INTARG_MAX || number < -INTARG_MAX) {
+ error("integer argument too large");
+ number = 0;
+ }
+ delete s;
+ return (IntArg) number;
+}
+
+//////////////////////////////////////////////////////////////////////
+/* get_possibly_integer_args():
+ Parse the rest of the input line as a list of integer arguments.
+
+ Get as many integer arguments as possible from the rest of the
+ current line, even none.
+ - The arguments are separated by an arbitrary sequence of space or
+ tab characters.
+ - A comment, a newline, or EOF indicates the end of processing.
+ - Error on non-digit characters different from these.
+ - No line skip is performed.
+
+ Return: New IntArray of the retrieved arguments.
+*/
+IntArray *
+get_possibly_integer_args()
+{
+ bool done = false;
+ StringBuf buf = StringBuf();
+ Char c = get_char();
+ IntArray *args = new IntArray();
+ while (!done) {
+ buf.reset();
+ while (is_space_or_tab(c))
+ c = get_char();
+ if (c == '-') {
+ Char c1 = get_char();
+ if (isdigit((int) c1)) {
+ buf.append(c);
+ c = c1;
}
- break;
- case 'N':
- {
- if (npages == 0)
- fatal("`N' command illegal before first `p' command");
- pr->set_numbered_char(get_integer(), &env);
+ else
+ unget_char(c1);
+ }
+ while (isdigit((int) c)) {
+ buf.append(c);
+ c = get_char();
+ }
+ if (!buf.is_empty()) {
+ char *s = buf.make_string();
+ errno = 0;
+ long int x = strtol(s, 0, 10);
+ if (errno
+ || x > INTARG_MAX || x < -INTARG_MAX) {
+ error("invalid integer argument, set to 0");
+ x = 0;
}
+ args->append((IntArg) x);
+ delete s;
+ }
+ // Here, c is not a digit.
+ // Terminate on comment, end of line, or end of file, while
+ // space or tab indicate continuation; otherwise error.
+ switch((int) c) {
+ case '#':
+ skip_to_end_of_line();
+ done = true;
break;
- case 'H':
- env.hpos = get_integer();
+ case '\n':
+ done = true;
+ unget_char(c);
break;
- case 'h':
- env.hpos += get_integer();
+ case EOF:
+ done = true;
break;
- case 'V':
- env.vpos = get_integer();
+ case ' ':
+ case '\t':
break;
- case 'v':
- env.vpos += get_integer();
+ default:
+ error("integer argument expected");
break;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- {
- int c = get_char();
- if (!csdigit(c))
- fatal("digit expected");
- env.hpos += (command - '0')*10 + (c - '0');
- }
- // fall through
- case 'c':
- {
- if (npages == 0)
- fatal("`c' command illegal before first `p' command");
- int c = get_char();
- if (c == EOF)
- fatal("missing argument to `c' command");
- pr->set_ascii_char(c, &env);
- }
+ }
+ }
+ return args;
+}
+
+//////////////////////////////////////////////////////////////////////
+/* get_string_arg():
+ Retrieve string arg.
+
+ - Skip leading spaces and tabs; error on EOL or newline.
+ - Return all following characters before the next space, tab,
+ newline, or EOF character (in-word '#' is not a comment character).
+ - The terminating space, tab, newline, or EOF character is restored
+ onto the input queue, so no line skip.
+
+ Return: Retrieved string as char *, allocated by 'new'.
+*/
+char *
+get_string_arg(void)
+{
+ StringBuf buf = StringBuf();
+ Char c = next_arg_begin();
+ while (!is_space_or_tab(c)
+ && c != Char('\n') && c != Char(EOF)) {
+ buf.append(c);
+ c = get_char();
+ }
+ unget_char(c); // restore white space
+ return buf.make_string();
+}
+
+//////////////////////////////////////////////////////////////////////
+/* is_space_or_tab():
+ Test a character if it is a space or tab.
+
+ c: In-parameter, character to be tested.
+
+ Return: True, if c is a space or tab character, false otherwise.
+*/
+inline bool
+is_space_or_tab(const Char c)
+{
+ return (c == Char(' ') || c == Char('\t')) ? true : false;
+}
+
+//////////////////////////////////////////////////////////////////////
+/* next_arg_begin():
+ Return first character of next argument.
+
+ Skip space and tab characters; error on newline or EOF.
+
+ Return: The first character different from these (including '#').
+*/
+Char
+next_arg_begin(void)
+{
+ Char c;
+ while (1) {
+ c = get_char();
+ switch ((int) c) {
+ case ' ':
+ case '\t':
break;
- case 'n':
- if (npages == 0)
- fatal("`n' command illegal before first `p' command");
- pr->end_of_line();
- (void)get_integer();
- (void)get_integer();
+ case '\n':
+ case EOF:
+ error("missing argument");
break;
- case 'w':
+ default: // first essential character
+ return c;
+ }
+ }
+}
+
+//////////////////////////////////////////////////////////////////////
+/* next_command():
+ Find the first character of the next command.
+
+ Skip spaces, tabs, comments (introduced by #), and newlines.
+
+ Return: The first character different from these (including EOF).
+*/
+Char
+next_command(void)
+{
+ Char c;
+ while (1) {
+ c = get_char();
+ switch ((int) c) {
case ' ':
+ case '\t':
break;
case '\n':
current_lineno++;
break;
- case 'p':
- if (npages)
- pr->end_page(env.vpos);
- npages++;
- pr->begin_page(get_integer());
- env.vpos = 0;
- break;
- case '{':
- env_list = new environment_list(env, env_list);
- break;
- case '}':
- if (!env_list) {
- fatal("can't pop");
- }
- else {
- env = env_list->env;
- environment_list *tem = env_list;
- env_list = env_list->next;
- delete tem;
- }
- break;
- case 'u':
- {
- if (npages == 0)
- fatal("`u' command illegal before first `p' command");
- int kern = get_integer();
- int c = get_char();
- while (c == ' ')
- c = get_char();
- while (c != EOF) {
- if (c == '\n') {
- current_lineno++;
- break;
- }
- int w;
- pr->set_ascii_char(c, &env, &w);
- env.hpos += w + kern;
- c = get_char();
- if (c == ' ')
- break;
- }
- }
- break;
- case 't':
- {
- if (npages == 0)
- fatal("`t' command illegal before first `p' command");
- int c;
- while ((c = get_char()) != EOF && c != ' ') {
- if (c == '\n') {
- current_lineno++;
- break;
- }
- int w;
- pr->set_ascii_char(c, &env, &w);
- env.hpos += w;
- }
- }
- break;
- case '#':
- skip_line();
- break;
- case 'D':
- {
- if (npages == 0)
- fatal("`D' command illegal before first `p' command");
- int c;
- while ((c = get_char()) == ' ')
- ;
- int n;
- int *p = 0;
- int szp = 0;
- int np;
- for (np = 0; possibly_get_integer(&n); np++) {
- if (np >= szp) {
- if (szp == 0) {
- szp = 16;
- p = new int[szp];
- }
- else {
- int *oldp = p;
- p = new int[szp*2];
- memcpy(p, oldp, szp*sizeof(int));
- szp *= 2;
- a_delete oldp;
- }
- }
- p[np] = n;
- }
- pr->draw(c, p, np, &env);
- if (c == 'e') {
- if (np > 0)
- env.hpos += p[0];
- }
- else if (c == 'f' || c == 't')
- ;
- else {
- int i;
- for (i = 0; i < np/2; i++) {
- env.hpos += p[i*2];
- env.vpos += p[i*2 + 1];
- }
- // there might be an odd number of characters
- if (i*2 < np)
- env.hpos += p[i*2];
- }
- a_delete p;
- skip_line();
- }
- break;
- case 'x':
- {
- char *s = get_string();
- int suppress_skip = 0;
- switch (s[0]) {
- case 'i':
- error("duplicate `x init' command");
- break;
- case 'T':
- error("duplicate `x T' command");
- break;
- case 'r':
- error("duplicate `x res' command");
- break;
- case 'p':
- break;
- case 's':
- break;
- case 't':
- break;
- case 'f':
- {
- int n = get_integer();
- char *name = get_string();
- pr->load_font(n, name);
- }
- break;
- case 'H':
- env.height = get_integer();
- if (env.height == env.size)
- env.height = 0;
- break;
- case 'S':
- env.slant = get_integer();
- break;
- case 'X':
- if (npages == 0)
- fatal("`x X' command illegal before first `p' command");
- pr->special(get_string(1), &env);
- suppress_skip = 1;
- break;
- case 'u':
- // .cu
- pr->special(get_string(), &env, 'u');
- break;
- default:
- error("unrecognised x command `%1'", s);
- }
- if (!suppress_skip)
- skip_line();
- }
- break;
- default:
- error("unrecognised command code %1", int(command));
+ case '#': // comment
skip_line();
break;
+ default: // EOF or first essential character
+ return c;
}
}
- if (npages)
- pr->end_page(env.vpos);
}
-int get_integer()
+//////////////////////////////////////////////////////////////////////
+/* odd():
+ Test whether argument is an odd number.
+
+ n: In-parameter, the integer to be tested.
+
+ Return: True if odd, false otherwise.
+*/
+inline bool
+odd(const int n)
+{
+ return (n & 1 == 1) ? true : false;
+}
+
+//////////////////////////////////////////////////////////////////////
+/* position_to_end_of_args():
+ Move graphical pointer to end of drawn figure.
+
+ This is used by the D commands that draw open geometrical figures.
+ The algorithm simply sums up all horizontal displacements (arguments
+ with even number) for the horizontal component. Similarly, the
+ vertical component is the sum of the odd arguments.
+
+ args: In-parameter, the arguments of a former drawing command.
+*/
+void
+position_to_end_of_args(const IntArray * const args)
{
- int c = get_char();
- while (c == ' ')
- c = get_char();
- int neg = 0;
- if (c == '-') {
- neg = 1;
+ size_t i;
+ const size_t n = args->len();
+ for (i = 0; i < n; i += 2)
+ current_env->hpos += (*args)[i];
+ for (i = 1; i < n; i += 2)
+ current_env->vpos += (*args)[i];
+}
+
+//////////////////////////////////////////////////////////////////////
+/* remember_filename():
+ Set global variable current_filename.
+
+ The actual filename is stored in current_filename. This is used by
+ the postprocessors, expecting the name "<standard input>" for stdin.
+
+ filename: In-out-parameter; is changed to the new value also.
+*/
+void
+remember_filename(const char *filename)
+{
+ char *fname;
+ if (strcmp(filename, "-") == 0)
+ fname = "<standard input>";
+ else
+ fname = (char *) filename;
+ size_t len = strlen(fname) + 1;
+ if (current_filename != 0)
+ free((char *)current_filename);
+ current_filename = (const char *) malloc(len);
+ if (current_filename == 0)
+ fatal("can't malloc space for filename");
+ strncpy((char *)current_filename, (char *)fname, len);
+}
+
+//////////////////////////////////////////////////////////////////////
+/* send_draw():
+ Call draw method of printer class.
+
+ subcmd: Letter of actual D subcommand.
+ args: Array of integer arguments of actual D subcommand.
+*/
+void
+send_draw(const Char subcmd, const IntArray * const args)
+{
+ EnvInt n = (EnvInt) args->len();
+ pr->draw((int) subcmd, (IntArg *) args->get_data(), n, current_env);
+}
+
+//////////////////////////////////////////////////////////////////////
+/* skip_line():
+ Go to next line within the input queue.
+
+ Skip the rest of the current line, including the newline character.
+ The global variable current_lineno is adjusted.
+ No errors are raised.
+*/
+void
+skip_line(void)
+{
+ Char c = get_char();
+ while (1) {
+ if (c == '\n') {
+ current_lineno++;
+ break;
+ }
+ if (c == EOF)
+ break;
c = get_char();
}
- if (!csdigit(c))
- fatal("integer expected");
- int total = 0;
- do {
- total = total*10;
- if (neg)
- total -= c - '0';
- else
- total += c - '0';
- c = get_char();
- } while (csdigit(c));
- if (c != EOF)
- ungetc(c, current_file);
- return total;
}
-int possibly_get_integer(int *res)
+//////////////////////////////////////////////////////////////////////
+/* skip_line_checked ():
+ Check that there aren't any arguments left on the rest of the line,
+ then skip line.
+
+ Spaces, tabs, and a comment are allowed before newline or EOF.
+ All other characters raise an error.
+*/
+bool
+skip_line_checked(void)
{
- int c = get_char();
- while (c == ' ')
- c = get_char();
- int neg = 0;
- if (c == '-') {
- neg = 1;
+ bool ok = true;
+ Char c = get_char();
+ while (is_space_or_tab(c))
c = get_char();
+ switch((int) c) {
+ case '#': // comment
+ skip_line();
+ break;
+ case '\n':
+ current_lineno++;
+ break;
+ case EOF:
+ break;
+ default:
+ ok = false;
+ skip_line();
+ break;
}
- if (!csdigit(c)) {
- if (c != EOF)
- ungetc(c, current_file);
- return 0;
+ return ok;
+}
+
+//////////////////////////////////////////////////////////////////////
+/* skip_line_fatal ():
+ Fatal error if arguments left, otherwise skip line.
+
+ Spaces, tabs, and a comment are allowed before newline or EOF.
+ All other characters trigger the error.
+*/
+void
+skip_line_fatal(void)
+{
+ bool ok = skip_line_checked();
+ if (!ok) {
+ current_lineno--;
+ error("too many arguments");
+ current_lineno++;
+ }
+}
+
+//////////////////////////////////////////////////////////////////////
+/* skip_line_warn ():
+ Skip line, but warn if arguments are left on actual line.
+
+ Spaces, tabs, and a comment are allowed before newline or EOF.
+ All other characters raise a warning
+*/
+void
+skip_line_warn(void)
+{
+ bool ok = skip_line_checked();
+ if (!ok) {
+ current_lineno--;
+ warning("too many arguments on current line");
+ current_lineno++;
}
- int total = 0;
- do {
- total = total*10;
- if (neg)
- total -= c - '0';
- else
- total += c - '0';
- c = get_char();
- } while (csdigit(c));
- if (c != EOF)
- ungetc(c, current_file);
- *res = total;
- return 1;
}
+//////////////////////////////////////////////////////////////////////
+/* skip_line_D ():
+ Skip line in `D' commands.
-char *get_string(int is_long)
+ Decide whether in case of an additional argument a fatal error is
+ raised (the documented classical behavior), only a warning is
+ issued, or the line is just skipped (former groff behavior).
+ Actually decided for the warning.
+*/
+void
+skip_line_D(void)
{
- static char *buf;
- static int buf_size;
- int c = get_char();
- while (c == ' ')
+ skip_line_warn();
+ // or: skip_line_fatal();
+ // or: skip_line();
+}
+
+//////////////////////////////////////////////////////////////////////
+/* skip_line_x ():
+ Skip line in `x' commands.
+
+ Decide whether in case of an additional argument a fatal error is
+ raised (the documented classical behavior), only a warning is
+ issued, or the line is just skipped (former groff behavior).
+ Actually decided for the warning.
+*/
+void
+skip_line_x(void)
+{
+ skip_line_warn();
+ // or: skip_line_fatal();
+ // or: skip_line();
+}
+
+//////////////////////////////////////////////////////////////////////
+/* skip_to_end_of_line():
+ Go to the end of the current line.
+
+ Skip the rest of the current line, excluding the newline character.
+ The global variable current_lineno is not changed.
+ No errors are raised.
+*/
+void
+skip_to_end_of_line(void)
+{
+ Char c = get_char();
+ while (1) {
+ if (c == '\n') {
+ unget_char(c);
+ return;
+ }
+ if (c == EOF)
+ return;
c = get_char();
- for (int i = 0;; i++) {
- if (i >= buf_size) {
- if (buf_size == 0) {
- buf_size = 16;
- buf = new char[buf_size];
+ }
+}
+
+//////////////////////////////////////////////////////////////////////
+/* unget_char(c):
+ Restore character c onto input queue.
+
+ Write a character back onto the input stream.
+ EOF is gracefully handled.
+
+ c: In-parameter; character to be pushed onto the input queue.
+*/
+inline void
+unget_char(const Char c)
+{
+ if (c != EOF) {
+ int ch = (int) c;
+ if (ungetc(ch, current_file) == EOF)
+ fatal("could not unget character");
+ }
+}
+
+
+/**********************************************************************
+ parser subcommands
+ **********************************************************************/
+
+//////////////////////////////////////////////////////////////////////
+/* parse_color_command:
+ Process the commands m and DF, but not Df.
+
+ col: In-out-parameter; the color object to be set, must have
+ been initialized before.
+*/
+void
+parse_color_command(color *col)
+{
+ ColorArg gray = 0;
+ ColorArg red = 0, green = 0, blue = 0;
+ ColorArg cyan = 0, magenta = 0, yellow = 0, black = 0;
+ Char subcmd = next_arg_begin();
+ switch((int) subcmd) {
+ case 'c': // DFc or mc: CMY
+ cyan = get_color_arg();
+ magenta = get_color_arg();
+ yellow = get_color_arg();
+ col->set_cmy(cyan, magenta, yellow);
+ break;
+ case 'd': // DFd or md: set default color
+ col->set_default();
+ break;
+ case 'g': // DFg or mg: gray
+ gray = get_color_arg();
+ col->set_gray(gray);
+ break;
+ case 'k': // DFk or mk: CMYK
+ cyan = get_color_arg();
+ magenta = get_color_arg();
+ yellow = get_color_arg();
+ black = get_color_arg();
+ col->set_cmyk(cyan, magenta, yellow, black);
+ break;
+ case 'r': // DFr or mr: RGB
+ red = get_color_arg();
+ green = get_color_arg();
+ blue = get_color_arg();
+ col->set_rgb(red, green, blue);
+ break;
+ default:
+ error("invalid color scheme `%1'", (int) subcmd);
+ break;
+ } // end of color subcommands
+}
+
+//////////////////////////////////////////////////////////////////////
+/* parse_D_command():
+ Parse the subcommands of graphical command D.
+
+ This is the part of the do_file() parser that scans the graphical
+ subcommands.
+ - Error on lacking or wrong arguments.
+ - Warning on too many arguments.
+ - Line is always skipped.
+*/
+void
+parse_D_command()
+{
+ Char subcmd = next_arg_begin();
+ switch((int) subcmd) {
+ case '~': // D~: draw B-spline
+ // actually, this isn't available for some postprocessors
+ // fall through
+ default: // unknown options are passed to device
+ {
+ IntArray *args = get_D_variable_args();
+ send_draw(subcmd, args);
+ position_to_end_of_args(args);
+ delete args;
+ break;
+ }
+ case 'a': // Da: draw arc
+ {
+ IntArray *args = get_D_fixed_args(4);
+ send_draw(subcmd, args);
+ position_to_end_of_args(args);
+ delete args;
+ break;
+ }
+ case 'c': // Dc: draw circle line
+ {
+ IntArray *args = get_D_fixed_args(1);
+ send_draw(subcmd, args);
+ // move to right end
+ current_env->hpos += (*args)[0];
+ delete args;
+ break;
+ }
+ case 'C': // DC: draw solid circle
+ {
+ IntArray *args = get_D_fixed_args_odd_dummy(1);
+ send_draw(subcmd, args);
+ // move to right end
+ current_env->hpos += (*args)[0];
+ delete args;
+ break;
+ }
+ case 'e': // De: draw ellipse line
+ case 'E': // DE: draw solid ellipse
+ {
+ IntArray *args = get_D_fixed_args(2);
+ send_draw(subcmd, args);
+ // move to right end
+ current_env->hpos += (*args)[0];
+ delete args;
+ break;
+ }
+ case 'f': // Df: set fill gray; obsoleted by DFg
+ {
+ IntArg arg = get_integer_arg();
+ if ((arg >= 0) && (arg <= 1000)) {
+ // convert arg and treat it like DFg
+ ColorArg gray = color_from_Df_command(arg);
+ current_env->fill->set_gray(gray);
}
else {
- char *old_buf = buf;
- int old_size = buf_size;
- buf_size *= 2;
- buf = new char[buf_size];
- memcpy(buf, old_buf, old_size);
- a_delete old_buf;
+ // set fill color to the same value as the current outline color
+ delete current_env->fill;
+ current_env->fill = new color(current_env->col);
}
+ pr->change_fill_color(current_env);
+ // skip unused `vertical' component (\D'...' always emits pairs)
+ (void) get_integer_arg();
+ // no positioning
+ skip_line_x();
+ break;
}
- if ((!is_long && (c == ' ' || c == '\n')) || c == EOF) {
- buf[i] = '\0';
+ case 'F': // DF: set fill color, several formats
+ parse_color_command(current_env->fill);
+ pr->change_fill_color(current_env);
+ // no positioning (setting-only command)
+ skip_line_x();
+ break;
+ case 'l': // Dl: draw line
+ {
+ IntArray *args = get_D_fixed_args(2);
+ send_draw(subcmd, args);
+ position_to_end_of_args(args);
+ delete args;
break;
}
- if (is_long && c == '\n') {
- current_lineno++;
- c = get_char();
- if (c == '+')
- c = '\n';
+ case 'p': // Dp: draw closed polygon line
+ case 'P': // DP: draw solid closed polygon
+ {
+ IntArray *args = get_D_variable_args();
+ send_draw(subcmd, args);
+# ifdef STUPID_DRAWING_POSITIONING
+ // final args positioning
+ position_to_end_of_args(args);
+# endif
+ delete args;
+ break;
+ }
+ case 't': // Dt: set line thickness
+ {
+ IntArray *args = get_D_fixed_args_odd_dummy(1);
+ send_draw(subcmd, args);
+# ifdef STUPID_DRAWING_POSITIONING
+ // final args positioning
+ position_to_end_of_args(args);
+# endif
+ // no positioning?
+ delete args;
+ break;
+ }
+ } // end of D subcommands
+}
+
+//////////////////////////////////////////////////////////////////////
+/* parse_x_command():
+ Parse subcommands of the device control command x.
+
+ This is the part of the do_file() parser that scans the device
+ controlling commands.
+ - Error on duplicate prologue commands.
+ - Error on wrong or lacking arguments.
+ - Warning on too many arguments.
+ - Line is always skipped.
+
+ Globals:
+ - current_env: is set by many subcommands.
+ - npages: page counting variable
+
+ Return: boolean in the meaning of `stopped'
+ - true if parsing should be stopped (`x stop').
+ - false if parsing should continue.
+*/
+bool
+parse_x_command(void)
+{
+ bool stopped = false;
+ char *subcmd_str = get_string_arg();
+ char subcmd = subcmd_str[0];
+ switch (subcmd) {
+ case 'f': // x font: mount font
+ {
+ IntArg n = get_integer_arg();
+ char *name = get_string_arg();
+ pr->load_font(n, name);
+ delete name;
+ skip_line_x();
+ break;
+ }
+ case 'F': // x Filename: set filename for errors
+ {
+ char *str_arg = get_string_arg();
+ if (str_arg == 0)
+ warning("empty argument for `x F' command");
else {
- buf[i] = '\0';
- break;
+ remember_filename(str_arg);
+ delete str_arg;
}
- }
- buf[i] = c;
- c = get_char();
+ break;
+ }
+ case 'H': // x Height: set character height
+ current_env->height = get_integer_arg();
+ if (current_env->height == current_env->size)
+ current_env->height = 0;
+ skip_line_x();
+ break;
+ case 'i': // x init: initialize device
+ error("duplicate `x init' command");
+ skip_line_x();
+ break;
+ case 'p': // x pause: pause device
+ skip_line_x();
+ break;
+ case 'r': // x res: set resolution
+ error("duplicate `x res' command");
+ skip_line_x();
+ break;
+ case 's': // x stop: stop device
+ stopped = true;
+ skip_line_x();
+ break;
+ case 'S': // x Slant: set slant
+ current_env->slant = get_integer_arg();
+ skip_line_x();
+ break;
+ case 't': // x trailer: generate trailer info
+ skip_line_x();
+ break;
+ case 'T': // x Typesetter: set typesetter
+ error("duplicate `x T' command");
+ skip_line();
+ break;
+ case 'u': // x underline: from .cu
+ {
+ char *str_arg = get_string_arg();
+ pr->special(str_arg, current_env, 'u');
+ delete str_arg;
+ skip_line_x();
+ break;
+ }
+ case 'X': // x X: send uninterpretedly to device
+ {
+ char *str_arg = get_extended_arg(); // includes line skip
+ if (npages <= 0)
+ error("`x X' command invalid before first `p' command");
+ else
+ pr->special(str_arg, current_env);
+ delete str_arg;
+ break;
+ }
+ default: // ignore unknown x commands, but warn
+ warning("unknown command `x %1'", subcmd);
+ skip_line();
}
- if (c != EOF)
- ungetc(c, current_file);
- return buf;
+ delete subcmd_str;
+ return stopped;
}
-void skip_line()
+
+/**********************************************************************
+ exported part (by driver.h)
+ **********************************************************************/
+
+////////////////////////////////////////////////////////////////////////
+/* do_file():
+ Parse and postprocess groff intermediate output.
+
+ filename: "-" for standard input, normal file name otherwise
+*/
+void
+do_file(const char *filename)
{
- int c;
- while ((c = get_char()) != EOF)
- if (c == '\n') {
- current_lineno++;
- break;
+ Char command;
+ bool stopped = false; // terminating condition
+
+#ifdef USE_ENV_STACK
+ EnvStack env_stack = EnvStack();
+#endif // USE_ENV_STACK
+
+ // setup of global variables
+ npages = 0;
+ current_lineno = 1;
+ // `pr' is initialized after the prologue.
+ // `device' is set by the 1st prologue command.
+
+ if (filename[0] == '-' && filename[1] == '\0')
+ current_file = stdin;
+ else {
+ errno = 0;
+ current_file = fopen(filename, "r");
+ if (errno != 0 || current_file == 0) {
+ error("can't open file `%1'", filename);
+ return;
}
+ }
+ remember_filename(filename);
+
+ if (current_env != 0)
+ delete_current_env();
+ current_env = new environment;
+ current_env->col = new color;
+ current_env->fill = new color;
+ current_env->fontno = -1;
+ current_env->height = 0;
+ current_env->hpos = -1;
+ current_env->slant = 0;
+ current_env->size = 0;
+ current_env->vpos = -1;
+
+ // parsing of prologue (first 3 commands)
+ {
+ char *str_arg;
+ IntArg int_arg;
+
+ // 1st command `x T'
+ command = next_command();
+ if ((int) command == EOF)
+ return;
+ if ((int) command != 'x')
+ fatal("the first command must be `x T'");
+ str_arg = get_string_arg();
+ if (str_arg[0] != 'T')
+ fatal("the first command must be `x T'");
+ delete str_arg;
+ char *tmp_dev = get_string_arg();
+ if (pr == 0) { // note: `pr' initialized after prologue
+ device = tmp_dev;
+ if (!font::load_desc())
+ fatal("couldn't load DESC file, can't continue");
+ }
+ else {
+ if (device == 0 || strcmp(device, tmp_dev) != 0)
+ fatal("all files must use the same device");
+ delete tmp_dev;
+ }
+ skip_line_x(); // ignore further arguments
+ current_env->size = 10 * font::sizescale;
+
+ // 2nd command `x res'
+ command = next_command();
+ if ((int) command != 'x')
+ fatal("the second command must be `x res'");
+ str_arg = get_string_arg();
+ if (str_arg[0] != 'r')
+ fatal("the second command must be `x res'");
+ delete str_arg;
+ int_arg = get_integer_arg();
+ EnvInt font_res = font::res;
+ if (int_arg != font_res)
+ fatal("resolution does not match");
+ int_arg = get_integer_arg();
+ if (int_arg != font::hor)
+ fatal("minimum horizontal motion does not match");
+ int_arg = get_integer_arg();
+ if (int_arg != font::vert)
+ fatal("minimum vertical motion does not match");
+ skip_line_x(); // ignore further arguments
+
+ // 3rd command `x init'
+ command = next_command();
+ if (command != 'x')
+ fatal("the third command must be `x init'");
+ str_arg = get_string_arg();
+ if (str_arg[0] != 'i')
+ fatal("the third command must be `x init'");
+ delete str_arg;
+ skip_line_x();
+ }
+
+ // parsing of body
+ if (pr == 0)
+ pr = make_printer();
+ while (!stopped) {
+ command = next_command();
+ if (command == EOF)
+ break;
+ // spaces, tabs, comments, and newlines are skipped here
+ switch ((int) command) {
+ case '#': // #: comment, ignore up to end of line
+ skip_line();
+ break;
+#ifdef USE_ENV_STACK
+ case '{': // {: start a new environment (a copy)
+ env_stack.push(current_env);
+ break;
+ case '}': // }: pop previous env from stack
+ delete_current_env();
+ current_env = env_stack.pop();
+ break;
+#endif // USE_ENV_STACK
+ case '0': // ddc: obsolete jump and print command
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ { // expect 2 digits and a character
+ char s[3];
+ Char c = next_arg_begin();
+ if (npages <= 0)
+ fatal_command(command);
+ if (!isdigit((int) c)) {
+ error("digit expected");
+ c = 0;
+ }
+ s[0] = (char) command;
+ s[1] = (char) c;
+ s[2] = '\0';
+ errno = 0;
+ long int x = strtol(s, 0, 10);
+ if (errno != 0)
+ error("couldn't convert 2 digits");
+ EnvInt hor_pos = (EnvInt) x;
+ current_env->hpos += hor_pos;
+ c = next_arg_begin();
+ if ((int) c == '\n' || (int) c == EOF)
+ error("character argument expected");
+ else
+ pr->set_ascii_char((unsigned char) c, current_env);
+ break;
+ }
+ case 'c': // c: print ascii char without moving
+ {
+ if (npages <= 0)
+ fatal_command(command);
+ Char c = next_arg_begin();
+ if (c == '\n' || c == EOF)
+ error("missing argument to `c' command");
+ else
+ pr->set_ascii_char((unsigned char) c, current_env);
+ break;
+ }
+ case 'C': // C: print named special character
+ {
+ if (npages <= 0)
+ fatal_command(command);
+ char *str_arg = get_string_arg();
+ pr->set_special_char(str_arg, current_env);
+ delete str_arg;
+ break;
+ }
+ case 'D': // drawing commands
+ if (npages <= 0)
+ fatal_command(command);
+ parse_D_command();
+ break;
+ case 'f': // f: set font to number
+ current_env->fontno = get_integer_arg();
+ break;
+ case 'F': // F: obsolete, replaced by `x F'
+ {
+ char *str_arg = get_string_arg();
+ remember_filename(str_arg);
+ delete str_arg;
+ break;
+ }
+ case 'h': // h: relative horizontal move
+ current_env->hpos += (EnvInt) get_integer_arg();
+ break;
+ case 'H': // H: absolute horizontal positioning
+ current_env->hpos = (EnvInt) get_integer_arg();
+ break;
+ case 'm': // m: glyph color
+ parse_color_command(current_env->col);
+ pr->change_color(current_env);
+ break;
+ case 'n': // n: print end of line
+ // ignore two arguments (historically)
+ if (npages <= 0)
+ fatal_command(command);
+ pr->end_of_line();
+ (void) get_integer_arg();
+ (void) get_integer_arg();
+ break;
+ case 'N': // N: print char with given int code
+ if (npages <= 0)
+ fatal_command(command);
+ pr->set_numbered_char(get_integer_arg(), current_env);
+ break;
+ case 'p': // p: start new page with given number
+ if (npages > 0)
+ pr->end_page(current_env->vpos);
+ npages++; // increment # of processed pages
+ pr->begin_page(get_integer_arg());
+ current_env->vpos = 0;
+ break;
+ case 's': // s: set point size
+ current_env->size = get_integer_arg();
+ if (current_env->height == current_env->size)
+ current_env->height = 0;
+ break;
+ case 't': // t: print a text word
+ {
+ char c;
+ if (npages <= 0)
+ fatal_command(command);
+ char *str_arg = get_string_arg();
+ size_t i = 0;
+ while ((c = str_arg[i++]) != '\0') {
+ EnvInt w;
+ pr->set_ascii_char((unsigned char) c, current_env, &w);
+ current_env->hpos += w;
+ }
+ delete str_arg;
+ break;
+ }
+ case 'u': // u: print spaced word
+ {
+ char c;
+ if (npages <= 0)
+ fatal_command(command);
+ EnvInt kern = (EnvInt) get_integer_arg();
+ char *str_arg = get_string_arg();
+ size_t i = 0;
+ while ((c = str_arg[i++]) != '\0') {
+ EnvInt w;
+ pr->set_ascii_char((unsigned char) c, current_env, &w);
+ current_env->hpos += w + kern;
+ }
+ delete str_arg;
+ break;
+ }
+ case 'v': // v: relative vertical move
+ current_env->vpos += (EnvInt) get_integer_arg();
+ break;
+ case 'V': // V: absolute vertical positioning
+ current_env->vpos = (EnvInt) get_integer_arg();
+ break;
+ case 'w': // w: inform about paddable space
+ break;
+ case 'x': // device controlling commands
+ stopped = parse_x_command();
+ break;
+ default:
+ warning("unrecognized command `%1'", (unsigned char) command);
+ skip_line();
+ break;
+ } // end of switch
+ } // end of while
+
+ // end of file reached
+ if (npages > 0)
+ pr->end_page(current_env->vpos);
+ fclose(current_file);
+ // If `stopped' is not `true' here then there wasn't any `x stop'.
+ if (!stopped)
+ warning("no final `x stop' command");
+ delete_current_env();
}
diff --git a/contrib/groff/src/libs/libdriver/printer.cc b/contrib/groff/src/libs/libdriver/printer.cc
index 4d66f7b..c97e2ce 100644
--- a/contrib/groff/src/libs/libdriver/printer.cc
+++ b/contrib/groff/src/libs/libdriver/printer.cc
@@ -1,22 +1,30 @@
// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992, 2001 Free Software Foundation, Inc.
- Written by James Clark (jjc@jclark.com)
-This file is part of groff.
+// <groff_src_dir>/src/libs/libdriver/printer.cc
-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.
+/* Copyright (C) 1989, 1990, 1991, 1992, 2001, 2002
+ Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
-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.
+ Last update: 12 Apr 2002
-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. */
+ 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"
@@ -105,6 +113,14 @@ void printer::draw(int, int *, int, const environment *)
{
}
+void printer::change_color(const environment *)
+{
+}
+
+void printer::change_fill_color(const environment *)
+{
+}
+
void printer::set_ascii_char(unsigned char c, const environment *env,
int *widthp)
{
@@ -126,13 +142,12 @@ void printer::set_special_char(const char *nm, const environment *env,
int *widthp)
{
font *f;
- int w;
+ int w;
int i = set_char_and_width(nm, env, &w, &f);
if (i != -1) {
set_char(i, f, env, w, nm);
- if (widthp) {
+ if (widthp)
*widthp = w;
- }
}
}
@@ -199,73 +214,3 @@ font *printer::get_font_from_index(int fontno)
else
return(0);
}
-
-// This utility function adjusts the specified center of the
-// arc so that it is equidistant between the specified start
-// and end points. (p[0], p[1]) is a vector from the current
-// point to the center; (p[2], p[3]) is a vector from the
-// center to the end point. If the center can be adjusted,
-// a vector from the current point to the adjusted center is
-// stored in c[0], c[1] and 1 is returned. Otherwise 0 is
-// returned.
-
-#if 1
-int printer::adjust_arc_center(const int *p, double *c)
-{
- // We move the center along a line parallel to the line between
- // the specified start point and end point so that the center
- // is equidistant between the start and end point.
- // It can be proved (using Lagrange multipliers) that this will
- // give the point nearest to the specified center that is equidistant
- // between the start and end point.
-
- double x = p[0] + p[2]; // (x, y) is the end point
- double y = p[1] + p[3];
- double n = x*x + y*y;
- if (n != 0) {
- c[0]= double(p[0]);
- c[1] = double(p[1]);
- double k = .5 - (c[0]*x + c[1]*y)/n;
- c[0] += k*x;
- c[1] += k*y;
- return 1;
- }
- else
- return 0;
-}
-#else
-int printer::adjust_arc_center(const int *p, double *c)
-{
- int x = p[0] + p[2]; // (x, y) is the end point
- int y = p[1] + p[3];
- // Start at the current point; go in the direction of the specified
- // center point until we reach a point that is equidistant between
- // the specified starting point and the specified end point. Place
- // the center of the arc there.
- double n = p[0]*double(x) + p[1]*double(y);
- if (n > 0) {
- double k = (double(x)*x + double(y)*y)/(2.0*n);
- // (cx, cy) is our chosen center
- c[0] = k*p[0];
- c[1] = k*p[1];
- return 1;
- }
- else {
- // We would never reach such a point. So instead start at the
- // specified end point of the arc. Go towards the specified
- // center point until we reach a point that is equidistant between
- // the specified start point and specified end point. Place
- // the center of the arc there.
- n = p[2]*double(x) + p[3]*double(y);
- if (n > 0) {
- double k = 1 - (double(x)*x + double(y)*y)/(2.0*n);
- // (c[0], c[1]) is our chosen center
- c[0] = p[0] + k*p[2];
- c[1] = p[1] + k*p[3];
- return 1;
- }
- else
- return 0;
- }
-}
-#endif
diff --git a/contrib/groff/src/libs/libgroff/Makefile.sub b/contrib/groff/src/libs/libgroff/Makefile.sub
index ff5c655..ff6bd00 100644
--- a/contrib/groff/src/libs/libgroff/Makefile.sub
+++ b/contrib/groff/src/libs/libgroff/Makefile.sub
@@ -1,42 +1,48 @@
LIB=groff
OBJS=\
- assert.o \
- change_lf.o \
- cmap.o \
- cset.o \
- device.o \
- errarg.o \
- error.o \
- fatal.o \
- filename.o \
- font.o \
- fontfile.o \
- getopt.o \
- getopt1.o \
- htmlindicate.o \
- illegal.o \
- lf.o \
- lineno.o \
- macropath.o \
- maxfilename.o \
- nametoindex.o \
- new.o \
- prime.o \
- progname.o \
- ptable.o \
- searchpath.o \
- string.o \
- strsave.o \
- tmpfile.o \
- iftoa.o \
- itoa.o \
- matherr.o \
- version.o \
+ assert.$(OBJEXT) \
+ change_lf.$(OBJEXT) \
+ cmap.$(OBJEXT) \
+ color.$(OBJEXT) \
+ cset.$(OBJEXT) \
+ device.$(OBJEXT) \
+ errarg.$(OBJEXT) \
+ error.$(OBJEXT) \
+ fatal.$(OBJEXT) \
+ filename.$(OBJEXT) \
+ font.$(OBJEXT) \
+ fontfile.$(OBJEXT) \
+ geometry.$(OBJEXT) \
+ getopt.$(OBJEXT) \
+ getopt1.$(OBJEXT) \
+ htmlhint.$(OBJEXT) \
+ invalid.$(OBJEXT) \
+ lf.$(OBJEXT) \
+ lineno.$(OBJEXT) \
+ macropath.$(OBJEXT) \
+ maxfilename.$(OBJEXT) \
+ mksdir.$(OBJEXT) \
+ nametoindex.$(OBJEXT) \
+ new.$(OBJEXT) \
+ paper.$(OBJEXT) \
+ prime.$(OBJEXT) \
+ progname.$(OBJEXT) \
+ ptable.$(OBJEXT) \
+ searchpath.$(OBJEXT) \
+ string.$(OBJEXT) \
+ strsave.$(OBJEXT) \
+ tmpfile.$(OBJEXT) \
+ tmpname.$(OBJEXT) \
+ iftoa.$(OBJEXT) \
+ itoa.$(OBJEXT) \
+ matherr.$(OBJEXT) \
+ version.$(OBJEXT) \
$(LIBOBJS)
CCSRCS=\
$(srcdir)/assert.cc \
$(srcdir)/change_lf.cc \
$(srcdir)/cmap.cc \
+ $(srcdir)/color.cc \
$(srcdir)/cset.cc \
$(srcdir)/device.cc \
$(srcdir)/errarg.cc \
@@ -45,14 +51,18 @@ CCSRCS=\
$(srcdir)/filename.cc \
$(srcdir)/font.cc \
$(srcdir)/fontfile.cc \
- $(srcdir)/htmlindicate.cc \
- $(srcdir)/illegal.cc \
+ $(srcdir)/geometry.cc \
+ $(srcdir)/htmlhint.cc \
+ $(srcdir)/invalid.cc \
$(srcdir)/lf.cc \
$(srcdir)/lineno.cc \
$(srcdir)/macropath.cc \
$(srcdir)/maxfilename.cc \
+ $(srcdir)/mksdir.cc \
+ $(srcdir)/mkstemp.cc \
$(srcdir)/nametoindex.cc \
$(srcdir)/new.cc \
+ $(srcdir)/paper.cc \
$(srcdir)/prime.cc \
$(srcdir)/progname.cc \
$(srcdir)/ptable.cc \
@@ -60,6 +70,7 @@ CCSRCS=\
$(srcdir)/string.cc \
$(srcdir)/strsave.cc \
$(srcdir)/tmpfile.cc \
+ $(srcdir)/tmpname.cc \
version.cc
CSRCS=\
$(srcdir)/fmod.c \
@@ -71,16 +82,22 @@ CSRCS=\
$(srcdir)/matherr.c \
$(srcdir)/putenv.c \
$(srcdir)/strerror.c \
- $(srcdir)/strtol.c
+ $(srcdir)/strtol.c \
+ $(srcdir)/../snprintf/snprintf.c
GENSRCS=\
version.cc
-version=`cat $(top_srcdir)/VERSION`
-revision=`cat $(top_srcdir)/REVISION`
+src_version=`cat $(top_srcdir)/VERSION`
+src_revision=`cat $(top_srcdir)/REVISION`
version.cc: $(top_srcdir)/VERSION $(top_srcdir)/REVISION
@echo Making version.cc
- @echo const char \*version_string = \"$(version)\"\; >$@
- @echo const char \*revision_string = \"$(revision)\"\; >>$@
- @echo extern \"C\" const char \*Version_string = \"$(version).$(revision)\"\; | \
+ @echo const char \*version_string = \"$(src_version)\"\; >$@
+ @echo const char \*revision_string = \"$(src_revision)\"\; >>$@
+ @echo extern \"C\" const char \*Version_string = \"$(src_version).$(src_revision)\"\; | \
sed -e 's/\.0\"/\"/' >>$@
+
+# We have to avoid $(COMPILE.c) since we must not use groff's `assert.h'
+snprintf.$(OBJEXT): $(srcdir)/../snprintf/snprintf.c
+ $(CC) -c $(CDEFINES) $(CFLAGS) $(CPPFLAGS) \
+ $(srcdir)/../snprintf/snprintf.c
diff --git a/contrib/groff/src/libs/libgroff/color.cc b/contrib/groff/src/libs/libgroff/color.cc
new file mode 100644
index 0000000..68e604c
--- /dev/null
+++ b/contrib/groff/src/libs/libgroff/color.cc
@@ -0,0 +1,363 @@
+// -*- C++ -*-
+
+/* <groff_src_dir>/src/libs/libgroff/color.cc
+
+Last update: 10 Apr 2002
+
+Copyright (C) 2001, 2002 Free Software Foundation, Inc.
+ Written by Gaius Mulley <gaius@glam.ac.uk>
+
+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 "color.h"
+#include "cset.h"
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <assert.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include "errarg.h"
+#include "error.h"
+
+static inline unsigned int
+min(const unsigned int a, const unsigned int b)
+{
+ if (a < b)
+ return a;
+ else
+ return b;
+}
+
+color::color(const color * const c)
+{
+ scheme = c->scheme;
+ components[0] = c->components[0];
+ components[1] = c->components[1];
+ components[2] = c->components[2];
+ components[3] = c->components[3];
+}
+
+int color::operator==(const color & c) const
+{
+ if (scheme != c.scheme)
+ return 0;
+ switch (scheme) {
+ case DEFAULT:
+ break;
+ case RGB:
+ if (Red != c.Red || Green != c.Green || Blue != c.Blue)
+ return 0;
+ break;
+ case CMYK:
+ if (Cyan != c.Cyan || Magenta != c.Magenta
+ || Yellow != c.Yellow || Black != c.Black)
+ return 0;
+ break;
+ case GRAY:
+ if (Gray != c.Gray)
+ return 0;
+ break;
+ case CMY:
+ if (Cyan != c.Cyan || Magenta != c.Magenta || Yellow != c.Yellow)
+ return 0;
+ break;
+ }
+ return 1;
+}
+
+int color::operator!=(const color & c) const
+{
+ return !(*this == c);
+}
+
+color_scheme color::get_components(unsigned int *c) const
+{
+#if 0
+ if (sizeof (c) < sizeof (unsigned int) * 4)
+ fatal("argument is not big enough to store 4 color components");
+#endif
+ c[0] = components[0];
+ c[1] = components[1];
+ c[2] = components[2];
+ c[3] = components[3];
+ return scheme;
+}
+
+void color::set_default()
+{
+ scheme = DEFAULT;
+}
+
+// (0, 0, 0) is black
+
+void color::set_rgb(const unsigned int r, const unsigned int g,
+ const unsigned int b)
+{
+ scheme = RGB;
+ Red = min(MAX_COLOR_VAL, r);
+ Green = min(MAX_COLOR_VAL, g);
+ Blue = min(MAX_COLOR_VAL, b);
+}
+
+// (0, 0, 0) is white
+
+void color::set_cmy(const unsigned int c, const unsigned int m,
+ const unsigned int y)
+{
+ scheme = CMY;
+ Cyan = min(MAX_COLOR_VAL, c);
+ Magenta = min(MAX_COLOR_VAL, m);
+ Yellow = min(MAX_COLOR_VAL, y);
+}
+
+// (0, 0, 0, 0) is white
+
+void color::set_cmyk(const unsigned int c, const unsigned int m,
+ const unsigned int y, const unsigned int k)
+{
+ scheme = CMYK;
+ Cyan = min(MAX_COLOR_VAL, c);
+ Magenta = min(MAX_COLOR_VAL, m);
+ Yellow = min(MAX_COLOR_VAL, y);
+ Black = min(MAX_COLOR_VAL, k);
+}
+
+// (0) is black
+
+void color::set_gray(const unsigned int g)
+{
+ scheme = GRAY;
+ Gray = min(MAX_COLOR_VAL, g);
+}
+
+/*
+ * atoh - computes the decimal value of a hexadecimal number string.
+ * `length' characters of `s' are read. Returns 1 if successful.
+ */
+
+static int atoh(unsigned int *result,
+ const char * const s, const size_t length)
+{
+ size_t i = 0;
+ unsigned int val = 0;
+ while ((i < length) && csxdigit(s[i])) {
+ if (csdigit(s[i]))
+ val = val*0x10 + (s[i]-'0');
+ else if (csupper(s[i]))
+ val = val*0x10 + (s[i]-'A') + 10;
+ else
+ val = val*0x10 + (s[i]-'a') + 10;
+ i++;
+ }
+ if (i != length)
+ return 0;
+ *result = val;
+ return 1;
+}
+
+/*
+ * read_encoding - set color from a hexadecimal color string.
+ *
+ * Use color scheme `cs' to parse `n' color components from string `s'.
+ * Returns 1 if successful.
+ */
+
+int color::read_encoding(const color_scheme cs, const char * const s,
+ const size_t n)
+{
+ size_t hex_length = 2;
+ scheme = cs;
+ char *p = (char *) s;
+ p++;
+ if (*p == '#') {
+ hex_length = 4;
+ p++;
+ }
+ for (size_t i = 0; i < n; i++) {
+ if (!atoh(&(components[i]), p, hex_length))
+ return 0;
+ if (hex_length == 2)
+ components[i] *= 0x101; // scale up -- 0xff should become 0xffff
+ p += hex_length;
+ }
+ return 1;
+}
+
+int color::read_rgb(const char * const s)
+{
+ return read_encoding(RGB, s, 3);
+}
+
+int color::read_cmy(const char * const s)
+{
+ return read_encoding(CMY, s, 3);
+}
+
+int color::read_cmyk(const char * const s)
+{
+ return read_encoding(CMYK, s, 4);
+}
+
+int color::read_gray(const char * const s)
+{
+ return read_encoding(GRAY, s, 1);
+}
+
+void
+color::get_rgb(unsigned int *r, unsigned int *g, unsigned int *b) const
+{
+ switch (scheme) {
+ case RGB:
+ *r = Red;
+ *g = Green;
+ *b = Blue;
+ break;
+ case CMY:
+ *r = MAX_COLOR_VAL - Cyan;
+ *g = MAX_COLOR_VAL - Magenta;
+ *b = MAX_COLOR_VAL - Yellow;
+ break;
+ case CMYK:
+ *r = MAX_COLOR_VAL
+ - min(MAX_COLOR_VAL,
+ Cyan * (MAX_COLOR_VAL - Black) / MAX_COLOR_VAL + Black);
+ *g = MAX_COLOR_VAL
+ - min(MAX_COLOR_VAL,
+ Magenta * (MAX_COLOR_VAL - Black) / MAX_COLOR_VAL + Black);
+ *b = MAX_COLOR_VAL
+ - min(MAX_COLOR_VAL,
+ Yellow * (MAX_COLOR_VAL - Black) / MAX_COLOR_VAL + Black);
+ break;
+ case GRAY:
+ *r = *g = *b = Gray;
+ break;
+ default:
+ assert(0);
+ break;
+ }
+}
+
+void
+color::get_cmy(unsigned int *c, unsigned int *m, unsigned int *y) const
+{
+ switch (scheme) {
+ case RGB:
+ *c = MAX_COLOR_VAL - Red;
+ *m = MAX_COLOR_VAL - Green;
+ *y = MAX_COLOR_VAL - Blue;
+ break;
+ case CMY:
+ *c = Cyan;
+ *m = Magenta;
+ *y = Yellow;
+ break;
+ case CMYK:
+ *c = min(MAX_COLOR_VAL,
+ Cyan * (MAX_COLOR_VAL - Black) / MAX_COLOR_VAL + Black);
+ *m = min(MAX_COLOR_VAL,
+ Magenta * (MAX_COLOR_VAL - Black) / MAX_COLOR_VAL + Black);
+ *y = min(MAX_COLOR_VAL,
+ Yellow * (MAX_COLOR_VAL - Black) / MAX_COLOR_VAL + Black);
+ break;
+ case GRAY:
+ *c = *m = *y = MAX_COLOR_VAL - Gray;
+ break;
+ default:
+ assert(0);
+ break;
+ }
+}
+
+void color::get_cmyk(unsigned int *c, unsigned int *m,
+ unsigned int *y, unsigned int *k) const
+{
+ switch (scheme) {
+ case RGB:
+ *k = min(MAX_COLOR_VAL - Red,
+ min(MAX_COLOR_VAL - Green, MAX_COLOR_VAL - Blue));
+ if (MAX_COLOR_VAL == *k) {
+ *c = MAX_COLOR_VAL;
+ *m = MAX_COLOR_VAL;
+ *y = MAX_COLOR_VAL;
+ }
+ else {
+ *c = (MAX_COLOR_VAL * (MAX_COLOR_VAL - Red - *k))
+ / (MAX_COLOR_VAL - *k);
+ *m = (MAX_COLOR_VAL * (MAX_COLOR_VAL - Green - *k))
+ / (MAX_COLOR_VAL - *k);
+ *y = (MAX_COLOR_VAL * (MAX_COLOR_VAL - Blue - *k))
+ / (MAX_COLOR_VAL - *k);
+ }
+ break;
+ case CMY:
+ *k = min(Cyan, min(Magenta, Yellow));
+ if (MAX_COLOR_VAL == *k) {
+ *c = MAX_COLOR_VAL;
+ *m = MAX_COLOR_VAL;
+ *y = MAX_COLOR_VAL;
+ }
+ else {
+ *c = (MAX_COLOR_VAL * (Cyan - *k)) / (MAX_COLOR_VAL - *k);
+ *m = (MAX_COLOR_VAL * (Magenta - *k)) / (MAX_COLOR_VAL - *k);
+ *y = (MAX_COLOR_VAL * (Yellow - *k)) / (MAX_COLOR_VAL - *k);
+ }
+ break;
+ case CMYK:
+ *c = Cyan;
+ *m = Magenta;
+ *y = Yellow;
+ *k = Black;
+ break;
+ case GRAY:
+ *c = *m = *y = 0;
+ *k = MAX_COLOR_VAL - Gray;
+ break;
+ default:
+ assert(0);
+ break;
+ }
+}
+
+// we use `0.222r + 0.707g + 0.071b' (this is the ITU standard)
+// as an approximation for gray
+
+void color::get_gray(unsigned int *g) const
+{
+ switch (scheme) {
+ case RGB:
+ *g = (222*Red + 707*Green + 71*Blue) / 1000;
+ break;
+ case CMY:
+ *g = MAX_COLOR_VAL - (222*Cyan + 707*Magenta + 71*Yellow) / 1000;
+ break;
+ case CMYK:
+ *g = (MAX_COLOR_VAL - (222*Cyan + 707*Magenta + 71*Yellow) / 1000)
+ * (MAX_COLOR_VAL - Black);
+ break;
+ case GRAY:
+ *g = Gray;
+ break;
+ default:
+ assert(0);
+ break;
+ }
+}
+
+color default_color;
diff --git a/contrib/groff/src/libs/libgroff/errarg.cc b/contrib/groff/src/libs/libgroff/errarg.cc
index f8075ea..2ddc0cc 100644
--- a/contrib/groff/src/libs/libgroff/errarg.cc
+++ b/contrib/groff/src/libs/libgroff/errarg.cc
@@ -1,5 +1,6 @@
// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992, 2000 Free Software Foundation, Inc.
+/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2002
+ Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
This file is part of groff.
@@ -31,14 +32,14 @@ errarg::errarg() : type(EMPTY)
{
}
-errarg::errarg(unsigned char cc) : type(CHAR)
+errarg::errarg(int nn) : type(INTEGER)
{
- c = cc;
+ n = nn;
}
-errarg::errarg(int nn) : type(INTEGER)
+errarg::errarg(unsigned int uu) : type(UNSIGNED_INTEGER)
{
- n = nn;
+ u = uu;
}
errarg::errarg(char cc) : type(CHAR)
@@ -46,6 +47,11 @@ errarg::errarg(char cc) : type(CHAR)
c = cc;
}
+errarg::errarg(unsigned char cc) : type(CHAR)
+{
+ c = cc;
+}
+
errarg::errarg(double dd) : type(DOUBLE)
{
d = dd;
@@ -58,6 +64,7 @@ int errarg::empty() const
extern "C" {
const char *i_to_a(int);
+ const char *ui_to_a(unsigned int);
}
void errarg::print() const
@@ -66,6 +73,9 @@ void errarg::print() const
case INTEGER:
fputs(i_to_a(n), stderr);
break;
+ case UNSIGNED_INTEGER:
+ fputs(ui_to_a(u), stderr);
+ break;
case CHAR:
putc(c, stderr);
break;
diff --git a/contrib/groff/src/libs/libgroff/font.cc b/contrib/groff/src/libs/libgroff/font.cc
index aa602b4..69e46e1 100644
--- a/contrib/groff/src/libs/libgroff/font.cc
+++ b/contrib/groff/src/libs/libgroff/font.cc
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001
+/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001, 2002
Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
@@ -19,8 +19,8 @@ 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 <stdio.h>
-#include <string.h>
+#include "lib.h"
+
#include <ctype.h>
#include <assert.h>
#include <math.h>
@@ -29,7 +29,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "error.h"
#include "cset.h"
#include "font.h"
-#include "lib.h"
+#include "paper.h"
const char *const WS = " \t\n\r";
@@ -94,13 +94,12 @@ text_file::~text_file()
fclose(fp);
}
-
int text_file::next()
{
if (fp == 0)
return 0;
if (buf == 0) {
- buf = new char [128];
+ buf = new char[128];
size = 128;
}
for (;;) {
@@ -109,8 +108,8 @@ int text_file::next()
int c = getc(fp);
if (c == EOF)
break;
- if (illegal_input_char(c))
- error("illegal input character code `%1'", int(c));
+ if (invalid_input_char(c))
+ error("invalid input character code `%1'", int(c));
else {
if (i + 1 >= size) {
char *old_buf = buf;
@@ -161,6 +160,9 @@ font::font(const char *s)
font::~font()
{
+ for (int i = 0; i < ch_used; i++)
+ if (ch[i].special_device_coding)
+ a_delete ch[i].special_device_coding;
a_delete ch;
a_delete ch_index;
if (kern_hash_table) {
@@ -206,6 +208,34 @@ inline int font::scale(int w, int sz)
return sz == unitwidth ? w : scale_round(w, sz, unitwidth);
}
+int font::unit_scale(double *value, char unit)
+{
+ // we scale everything to inch
+ double divisor = 0;
+ switch (unit) {
+ case 'i':
+ divisor = 1;
+ break;
+ case 'p':
+ divisor = 72;
+ break;
+ case 'P':
+ divisor = 6;
+ break;
+ case 'c':
+ divisor = 2.54;
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ if (divisor) {
+ *value /= divisor;
+ return 1;
+ }
+ return 0;
+}
+
int font::get_skew(int c, int point_size, int sl)
{
int h = get_height(c, point_size);
@@ -303,7 +333,7 @@ int font::get_space_width(int point_size)
}
font_kern_list::font_kern_list(int c1, int c2, int n, font_kern_list *p)
- : i1(c1), i2(c2), amount(n), next(p)
+: i1(c1), i2(c2), amount(n), next(p)
{
}
@@ -472,6 +502,58 @@ static char *trim_arg(char *p)
return p;
}
+int font::scan_papersize(const char *p,
+ const char **size, double *length, double *width)
+{
+ double l, w;
+ char lu[2], wu[2];
+ const char *pp = p;
+ int test_file = 1;
+ char line[255];
+again:
+ if (csdigit(*pp)) {
+ if (sscanf(pp, "%lf%1[ipPc],%lf%1[ipPc]", &l, lu, &w, wu) == 4
+ && l > 0 && w > 0
+ && unit_scale(&l, lu[0]) && unit_scale(&w, wu[0])) {
+ if (length)
+ *length = l;
+ if (width)
+ *width = w;
+ if (size)
+ *size = "custom";
+ return 1;
+ }
+ }
+ else {
+ int i;
+ for (i = 0; i < NUM_PAPERSIZES; i++)
+ if (strcasecmp(papersizes[i].name, pp) == 0) {
+ if (length)
+ *length = papersizes[i].length;
+ if (width)
+ *width = papersizes[i].width;
+ if (size)
+ *size = papersizes[i].name;
+ return 1;
+ }
+ if (test_file) {
+ FILE *f = fopen(p, "r");
+ if (f) {
+ fgets(line, 254, f);
+ fclose(f);
+ test_file = 0;
+ char *linep = strchr(line, '\0');
+ // skip final newline, if any
+ if (*(--linep) == '\n')
+ *linep = '\0';
+ pp = line;
+ goto again;
+ }
+ }
+ }
+ return 0;
+}
+
// If the font can't be found, then if not_found is non-NULL, it will be set
// to 1 otherwise a message will be printed.
@@ -586,12 +668,12 @@ int font::load(int *not_found)
}
int i1 = name_to_index(c1);
if (i1 < 0) {
- t.error("illegal character `%1'", c1);
+ t.error("invalid character `%1'", c1);
return 0;
}
int i2 = name_to_index(c2);
if (i2 < 0) {
- t.error("illegal character `%1'", c2);
+ t.error("invalid character `%1'", c2);
return 0;
}
add_kern(i1, i2, n);
@@ -624,7 +706,7 @@ int font::load(int *not_found)
}
int index = name_to_index(nm);
if (index < 0) {
- t.error("illegal character `%1'", nm);
+ t.error("invalid character `%1'", nm);
return 0;
}
copy_entry(index, last_index);
@@ -671,20 +753,15 @@ int font::load(int *not_found)
t.error("bad code `%1' for character `%2'", p, nm);
return 0;
}
-
p = strtok(0, WS);
if ((p == NULL) || (strcmp(p, "--") == 0)) {
metric.special_device_coding = NULL;
- } else {
- char *name=(char *)malloc(strlen(p)+1);
-
- if (name == NULL) {
- fatal("malloc failed while reading character encoding");
- }
+ }
+ else {
+ char *name = new char[strlen(p) + 1];
strcpy(name, p);
metric.special_device_coding = name;
}
-
if (strcmp(nm, "---") == 0) {
last_index = number_to_index(metric.code);
add_entry(last_index, metric);
@@ -692,7 +769,7 @@ int font::load(int *not_found)
else {
last_index = name_to_index(nm);
if (last_index < 0) {
- t.error("illegal character `%1'", nm);
+ t.error("invalid character `%1'", nm);
return 0;
}
add_entry(last_index, metric);
@@ -736,7 +813,6 @@ static struct {
{ "sizescale", &font::sizescale }
};
-
int font::load_desc()
{
int nfonts = 0;
@@ -769,15 +845,6 @@ int font::load_desc()
return 0;
}
}
- else if (strcmp("tcommand", p) == 0) {
- tcommand = 1;
- }
- else if (strcmp("pass_filenames", p) == 0) {
- pass_filenames = 1;
- }
- else if (strcmp("use_charnames_in_special", p) == 0) {
- use_charnames_in_special = 1;
- }
else if (strcmp("family", p) == 0) {
p = strtok(0, WS);
if (!p) {
@@ -815,6 +882,31 @@ int font::load_desc()
}
font_name_table[nfonts] = 0;
}
+ else if (strcmp("papersize", p) == 0) {
+ p = strtok(0, WS);
+ if (!p) {
+ t.error("papersize command requires an argument");
+ return 0;
+ }
+ int found_paper = 0;
+ while (p) {
+ double unscaled_paperwidth, unscaled_paperlength;
+ if (scan_papersize(p, &papersize, &unscaled_paperlength,
+ &unscaled_paperwidth)) {
+ paperwidth = int(unscaled_paperwidth * res + 0.5);
+ paperlength = int(unscaled_paperlength * res + 0.5);
+ found_paper = 1;
+ break;
+ }
+ p = strtok(0, WS);
+ }
+ if (!found_paper) {
+ t.error("bad paper size");
+ return 0;
+ }
+ }
+ else if (strcmp("pass_filenames", p) == 0)
+ pass_filenames = 1;
else if (strcmp("sizes", p) == 0) {
int n = 16;
sizes = new int[n];
@@ -885,6 +977,10 @@ int font::load_desc()
style_table[i++] = tem;
}
}
+ else if (strcmp("tcommand", p) == 0)
+ tcommand = 1;
+ else if (strcmp("use_charnames_in_special", p) == 0)
+ use_charnames_in_special = 1;
else if (strcmp("charset", p) == 0)
break;
else if (unknown_desc_command_handler) {
diff --git a/contrib/groff/src/libs/libgroff/fontfile.cc b/contrib/groff/src/libs/libgroff/fontfile.cc
index cc1ad2c..8502d12 100644
--- a/contrib/groff/src/libs/libgroff/fontfile.cc
+++ b/contrib/groff/src/libs/libgroff/fontfile.cc
@@ -1,5 +1,6 @@
// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+/* 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.
@@ -18,13 +19,12 @@ 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 <stdio.h>
-#include <string.h>
+#include "lib.h"
+
#include <assert.h>
#include <stdlib.h>
#include <errno.h>
#include "font.h"
-#include "lib.h"
#include "searchpath.h"
#include "device.h"
#include "defs.h"
@@ -39,6 +39,7 @@ int font::vert = 1;
int font::unitwidth = 0;
int font::paperwidth = 0;
int font::paperlength = 0;
+const char *font::papersize = 0;
int font::biggestfont = 0;
int font::spare2 = 0;
int font::sizescale = 1;
diff --git a/contrib/groff/src/libs/libgroff/geometry.cc b/contrib/groff/src/libs/libgroff/geometry.cc
new file mode 100644
index 0000000..58a94a4
--- /dev/null
+++ b/contrib/groff/src/libs/libgroff/geometry.cc
@@ -0,0 +1,286 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001, 2002
+ Free Software Foundation, Inc.
+ Written by Gaius Mulley <gaius@glam.ac.uk>
+ using adjust_arc_center() from printer.cc, written by James Clark.
+
+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 <stdio.h>
+#include <math.h>
+
+#undef MAX
+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
+
+#undef MIN
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+
+
+// This utility function adjusts the specified center of the
+// arc so that it is equidistant between the specified start
+// and end points. (p[0], p[1]) is a vector from the current
+// point to the center; (p[2], p[3]) is a vector from the
+// center to the end point. If the center can be adjusted,
+// a vector from the current point to the adjusted center is
+// stored in c[0], c[1] and 1 is returned. Otherwise 0 is
+// returned.
+
+#if 1
+int adjust_arc_center(const int *p, double *c)
+{
+ // We move the center along a line parallel to the line between
+ // the specified start point and end point so that the center
+ // is equidistant between the start and end point.
+ // It can be proved (using Lagrange multipliers) that this will
+ // give the point nearest to the specified center that is equidistant
+ // between the start and end point.
+
+ double x = p[0] + p[2]; // (x, y) is the end point
+ double y = p[1] + p[3];
+ double n = x*x + y*y;
+ if (n != 0) {
+ c[0]= double(p[0]);
+ c[1] = double(p[1]);
+ double k = .5 - (c[0]*x + c[1]*y)/n;
+ c[0] += k*x;
+ c[1] += k*y;
+ return 1;
+ }
+ else
+ return 0;
+}
+#else
+int printer::adjust_arc_center(const int *p, double *c)
+{
+ int x = p[0] + p[2]; // (x, y) is the end point
+ int y = p[1] + p[3];
+ // Start at the current point; go in the direction of the specified
+ // center point until we reach a point that is equidistant between
+ // the specified starting point and the specified end point. Place
+ // the center of the arc there.
+ double n = p[0]*double(x) + p[1]*double(y);
+ if (n > 0) {
+ double k = (double(x)*x + double(y)*y)/(2.0*n);
+ // (cx, cy) is our chosen center
+ c[0] = k*p[0];
+ c[1] = k*p[1];
+ return 1;
+ }
+ else {
+ // We would never reach such a point. So instead start at the
+ // specified end point of the arc. Go towards the specified
+ // center point until we reach a point that is equidistant between
+ // the specified start point and specified end point. Place
+ // the center of the arc there.
+ n = p[2]*double(x) + p[3]*double(y);
+ if (n > 0) {
+ double k = 1 - (double(x)*x + double(y)*y)/(2.0*n);
+ // (c[0], c[1]) is our chosen center
+ c[0] = p[0] + k*p[2];
+ c[1] = p[1] + k*p[3];
+ return 1;
+ }
+ else
+ return 0;
+ }
+}
+#endif
+
+
+/*
+ * check_output_arc_limits - works out the smallest box that will encompass
+ * an arc defined by an origin (x, y) and two
+ * vectors (p0, p1) and (p2, p3).
+ * (x1, y1) -> start of arc
+ * (x1, y1) + (xv1, yv1) -> center of circle
+ * (x1, y1) + (xv1, yv1) + (xv2, yv2) -> end of arc
+ *
+ * Works out in which quadrant the arc starts and
+ * stops, and from this it determines the x, y
+ * max/min limits. The arc is drawn clockwise.
+ *
+ * [I'm sure there is a better way to do this, but
+ * I don't know how. Please can someone let me
+ * know or "improve" this function.]
+ */
+
+void check_output_arc_limits(int x1, int y1,
+ int xv1, int yv1,
+ int xv2, int yv2,
+ double c0, double c1,
+ int *minx, int *maxx,
+ int *miny, int *maxy)
+{
+ int radius = (int)sqrt(c0*c0 + c1*c1);
+ int x2 = x1 + xv1 + xv2; // end of arc is (x2, y2)
+ int y2 = y1 + yv1 + yv2;
+
+ // firstly lets use the `circle' limitation
+ *minx = x1 + xv1 - radius;
+ *maxx = x1 + xv1 + radius;
+ *miny = y1 + yv1 - radius;
+ *maxy = y1 + yv1 + radius;
+
+ /* now to see which min/max can be reduced and increased for the limits of
+ * the arc
+ *
+ * Q2 | Q1
+ * -----+-----
+ * Q3 | Q4
+ *
+ *
+ * NB. (x1+xv1, y1+yv1) is at the origin
+ *
+ * below we ask a nested question
+ * (i) from which quadrant does the first vector start?
+ * (ii) into which quadrant does the second vector go?
+ * from the 16 possible answers we determine the limits of the arc
+ */
+ if (xv1 > 0 && yv1 > 0) {
+ // first vector in Q3
+ if (xv2 >= 0 && yv2 >= 0 ) {
+ // second in Q1
+ *maxx = x2;
+ *miny = y1;
+ }
+ else if (xv2 < 0 && yv2 >= 0) {
+ // second in Q2
+ *maxx = x2;
+ *miny = y1;
+ }
+ else if (xv2 >= 0 && yv2 < 0) {
+ // second in Q4
+ *miny = MIN(y1, y2);
+ }
+ else if (xv2 < 0 && yv2 < 0) {
+ // second in Q3
+ if (x1 >= x2) {
+ *minx = x2;
+ *maxx = x1;
+ *miny = MIN(y1, y2);
+ *maxy = MAX(y1, y2);
+ }
+ else {
+ // xv2, yv2 could all be zero?
+ }
+ }
+ }
+ else if (xv1 > 0 && yv1 < 0) {
+ // first vector in Q2
+ if (xv2 >= 0 && yv2 >= 0) {
+ // second in Q1
+ *maxx = MAX(x1, x2);
+ *minx = MIN(x1, x2);
+ *miny = y1;
+ }
+ else if (xv2 < 0 && yv2 >= 0) {
+ // second in Q2
+ if (x1 < x2) {
+ *maxx = x2;
+ *minx = x1;
+ *miny = MIN(y1, y2);
+ *maxy = MAX(y1, y2);
+ }
+ else {
+ // otherwise almost full circle anyway
+ }
+ }
+ else if (xv2 >= 0 && yv2 < 0) {
+ // second in Q4
+ *miny = y2;
+ *minx = x1;
+ }
+ else if (xv2 < 0 && yv2 < 0) {
+ // second in Q3
+ *minx = MIN(x1, x2);
+ }
+ }
+ else if (xv1 <= 0 && yv1 <= 0) {
+ // first vector in Q1
+ if (xv2 >= 0 && yv2 >= 0) {
+ // second in Q1
+ if (x1 < x2) {
+ *minx = x1;
+ *maxx = x2;
+ *miny = MIN(y1, y2);
+ *maxy = MAX(y1, y2);
+ }
+ else {
+ // nearly full circle
+ }
+ }
+ else if (xv2 < 0 && yv2 >= 0) {
+ // second in Q2
+ *maxy = MAX(y1, y2);
+ }
+ else if (xv2 >= 0 && yv2 < 0) {
+ // second in Q4
+ *miny = MIN(y1, y2);
+ *maxy = MAX(y1, y2);
+ *minx = MIN(x1, x2);
+ }
+ else if (xv2 < 0 && yv2 < 0) {
+ // second in Q3
+ *minx = x2;
+ *maxy = y1;
+ }
+ }
+ else if (xv1 <= 0 && yv1 > 0) {
+ // first vector in Q4
+ if (xv2 >= 0 && yv2 >= 0) {
+ // second in Q1
+ *maxx = MAX(x1, x2);
+ }
+ else if (xv2 < 0 && yv2 >= 0) {
+ // second in Q2
+ *maxy = MAX(y1, y2);
+ *maxx = MAX(x1, x2);
+ }
+ else if (xv2 >= 0 && yv2 < 0) {
+ // second in Q4
+ if (x1 >= x2) {
+ *miny = MIN(y1, y2);
+ *maxy = MAX(y1, y2);
+ *minx = MIN(x1, x2);
+ *maxx = MAX(x2, x2);
+ }
+ else {
+ // nearly full circle
+ }
+ }
+ else if (xv2 < 0 && yv2 < 0) {
+ // second in Q3
+ *maxy = MAX(y1, y2);
+ *minx = MIN(x1, x2);
+ *maxx = MAX(x1, x2);
+ }
+ }
+
+ // this should *never* happen but if it does it means a case above is wrong
+ // this code is only present for safety sake
+ if (*maxx < *minx) {
+ fprintf(stderr, "assert failed *minx > *maxx\n");
+ fflush(stderr);
+ *maxx = *minx;
+ }
+ if (*maxy < *miny) {
+ fprintf(stderr, "assert failed *miny > *maxy\n");
+ fflush(stderr);
+ *maxy = *miny;
+ }
+}
diff --git a/contrib/groff/src/libs/libgroff/getopt.c b/contrib/groff/src/libs/libgroff/getopt.c
index 0ecad38..289d137 100644
--- a/contrib/groff/src/libs/libgroff/getopt.c
+++ b/contrib/groff/src/libs/libgroff/getopt.c
@@ -2,24 +2,24 @@
NOTE: getopt is now part of the C library, so if you don't know what
"Keep this file name-space clean" means, talk to drepper@gnu.org
before changing it!
-
- Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 2000
+ Copyright (C) 1987,88,89,90,91,92,93,94,95,96,98,99,2000,2001,2002
Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
The GNU C Library 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
- Library General Public License for more details.
+ Lesser General Public License for more details.
- You should have received a copy of the GNU Library General Public
- License along with the GNU C Library; see the file COPYING.LIB. If not,
- write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>.
Ditto for AIX 3.2 and <stdlib.h>. */
@@ -78,7 +78,7 @@
#ifndef _
/* This is for other GNU distributions with internationalized messages. */
-# if defined HAVE_LIBINTL_H || defined _LIBC
+# if (HAVE_LIBINTL_H && ENABLE_NLS) || defined _LIBC
# include <libintl.h>
# ifndef _
# define _(msgid) gettext (msgid)
@@ -86,6 +86,13 @@
# else
# define _(msgid) (msgid)
# endif
+# if defined _LIBC && defined USE_IN_LIBIO
+# include <wchar.h>
+# endif
+#endif
+
+#ifndef attribute_hidden
+# define attribute_hidden
#endif
/* This version of `getopt' appears to the caller like standard Unix `getopt'
@@ -131,7 +138,7 @@ int optind = 1;
causes problems with re-calling getopt as programs generally don't
know that. */
-int __getopt_initialized;
+int __getopt_initialized attribute_hidden;
/* The next char to be scanned in the option-element
in which the last option character we returned was found.
@@ -250,41 +257,34 @@ static int first_nonopt;
static int last_nonopt;
#ifdef _LIBC
+/* Stored original parameters.
+ XXX This is no good solution. We should rather copy the args so
+ that we can compare them later. But we must not use malloc(3). */
+extern int __libc_argc;
+extern char **__libc_argv;
+
/* Bash 2.0 gives us an environment variable containing flags
indicating ARGV elements that should not be considered arguments. */
+# ifdef USE_NONOPTION_FLAGS
/* Defined in getopt_init.c */
extern char *__getopt_nonoption_flags;
static int nonoption_flags_max_len;
static int nonoption_flags_len;
+# endif
-static int original_argc;
-static char *const *original_argv;
-
-/* Make sure the environment variable bash 2.0 puts in the environment
- is valid for the getopt call we must make sure that the ARGV passed
- to getopt is that one passed to the process. */
-static void
-__attribute__ ((unused))
-store_args_and_env (int argc, char *const *argv)
-{
- /* XXX This is no good solution. We should rather copy the args so
- that we can compare them later. But we must not use malloc(3). */
- original_argc = argc;
- original_argv = argv;
-}
-# ifdef text_set_element
-text_set_element (__libc_subinit, store_args_and_env);
-# endif /* text_set_element */
-
-# define SWAP_FLAGS(ch1, ch2) \
+# ifdef USE_NONOPTION_FLAGS
+# define SWAP_FLAGS(ch1, ch2) \
if (nonoption_flags_len > 0) \
{ \
char __tmp = __getopt_nonoption_flags[ch1]; \
__getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \
__getopt_nonoption_flags[ch2] = __tmp; \
}
+# else
+# define SWAP_FLAGS(ch1, ch2)
+# endif
#else /* !_LIBC */
# define SWAP_FLAGS(ch1, ch2)
#endif /* _LIBC */
@@ -316,7 +316,7 @@ exchange (argv)
It leaves the longer segment in the right place overall,
but it consists of two parts that need to be swapped next. */
-#ifdef _LIBC
+#if defined _LIBC && defined USE_NONOPTION_FLAGS
/* First make sure the handling of the `__getopt_nonoption_flags'
string can work normally. Our top argument must be in the range
of the string. */
@@ -420,9 +420,9 @@ _getopt_initialize (argc, argv, optstring)
else
ordering = PERMUTE;
-#ifdef _LIBC
+#if defined _LIBC && defined USE_NONOPTION_FLAGS
if (posixly_correct == NULL
- && argc == original_argc && argv == original_argv)
+ && argc == __libc_argc && argv == __libc_argv)
{
if (nonoption_flags_max_len == 0)
{
@@ -539,7 +539,7 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
Either it does not have option syntax, or there is an environment flag
from the shell indicating it is not an option. The later information
is only used when the used in the GNU libc. */
-#ifdef _LIBC
+#if defined _LIBC && defined USE_NONOPTION_FLAGS
# define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0' \
|| (optind < nonoption_flags_len \
&& __getopt_nonoption_flags[optind] == '1'))
@@ -685,8 +685,26 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
if (ambig && !exact)
{
if (print_errors)
- fprintf (stderr, _("%s: option `%s' is ambiguous\n"),
- argv[0], argv[optind]);
+ {
+#if defined _LIBC && defined USE_IN_LIBIO
+ char *buf;
+
+ if (__asprintf (&buf, _("%s: option `%s' is ambiguous\n"),
+ argv[0], argv[optind]) >= 0)
+ {
+
+ if (_IO_fwide (stderr, 0) > 0)
+ __fwprintf (stderr, L"%s", buf);
+ else
+ fputs (buf, stderr);
+
+ free (buf);
+ }
+#else
+ fprintf (stderr, _("%s: option `%s' is ambiguous\n"),
+ argv[0], argv[optind]);
+#endif
+ }
nextchar += strlen (nextchar);
optind++;
optopt = 0;
@@ -707,16 +725,50 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
{
if (print_errors)
{
+#if defined _LIBC && defined USE_IN_LIBIO
+ char *buf;
+ int n;
+#endif
+
if (argv[optind - 1][1] == '-')
- /* --option */
- fprintf (stderr,
- _("%s: option `--%s' doesn't allow an argument\n"),
- argv[0], pfound->name);
+ {
+ /* --option */
+#if defined _LIBC && defined USE_IN_LIBIO
+ n = __asprintf (&buf, _("\
+%s: option `--%s' doesn't allow an argument\n"),
+ argv[0], pfound->name);
+#else
+ fprintf (stderr, _("\
+%s: option `--%s' doesn't allow an argument\n"),
+ argv[0], pfound->name);
+#endif
+ }
else
- /* +option or -option */
- fprintf (stderr,
- _("%s: option `%c%s' doesn't allow an argument\n"),
- argv[0], argv[optind - 1][0], pfound->name);
+ {
+ /* +option or -option */
+#if defined _LIBC && defined USE_IN_LIBIO
+ n = __asprintf (&buf, _("\
+%s: option `%c%s' doesn't allow an argument\n"),
+ argv[0], argv[optind - 1][0],
+ pfound->name);
+#else
+ fprintf (stderr, _("\
+%s: option `%c%s' doesn't allow an argument\n"),
+ argv[0], argv[optind - 1][0], pfound->name);
+#endif
+ }
+
+#if defined _LIBC && defined USE_IN_LIBIO
+ if (n >= 0)
+ {
+ if (_IO_fwide (stderr, 0) > 0)
+ __fwprintf (stderr, L"%s", buf);
+ else
+ fputs (buf, stderr);
+
+ free (buf);
+ }
+#endif
}
nextchar += strlen (nextchar);
@@ -732,9 +784,27 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
else
{
if (print_errors)
- fprintf (stderr,
- _("%s: option `%s' requires an argument\n"),
- argv[0], argv[optind - 1]);
+ {
+#if defined _LIBC && defined USE_IN_LIBIO
+ char *buf;
+
+ if (__asprintf (&buf, _("\
+%s: option `%s' requires an argument\n"),
+ argv[0], argv[optind - 1]) >= 0)
+ {
+ if (_IO_fwide (stderr, 0) > 0)
+ __fwprintf (stderr, L"%s", buf);
+ else
+ fputs (buf, stderr);
+
+ free (buf);
+ }
+#else
+ fprintf (stderr,
+ _("%s: option `%s' requires an argument\n"),
+ argv[0], argv[optind - 1]);
+#endif
+ }
nextchar += strlen (nextchar);
optopt = pfound->val;
return optstring[0] == ':' ? ':' : '?';
@@ -760,14 +830,45 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
{
if (print_errors)
{
+#if defined _LIBC && defined USE_IN_LIBIO
+ char *buf;
+ int n;
+#endif
+
if (argv[optind][1] == '-')
- /* --option */
- fprintf (stderr, _("%s: unrecognized option `--%s'\n"),
- argv[0], nextchar);
+ {
+ /* --option */
+#if defined _LIBC && defined USE_IN_LIBIO
+ n = __asprintf (&buf, _("%s: unrecognized option `--%s'\n"),
+ argv[0], nextchar);
+#else
+ fprintf (stderr, _("%s: unrecognized option `--%s'\n"),
+ argv[0], nextchar);
+#endif
+ }
else
- /* +option or -option */
- fprintf (stderr, _("%s: unrecognized option `%c%s'\n"),
- argv[0], argv[optind][0], nextchar);
+ {
+ /* +option or -option */
+#if defined _LIBC && defined USE_IN_LIBIO
+ n = __asprintf (&buf, _("%s: unrecognized option `%c%s'\n"),
+ argv[0], argv[optind][0], nextchar);
+#else
+ fprintf (stderr, _("%s: unrecognized option `%c%s'\n"),
+ argv[0], argv[optind][0], nextchar);
+#endif
+ }
+
+#if defined _LIBC && defined USE_IN_LIBIO
+ if (n >= 0)
+ {
+ if (_IO_fwide (stderr, 0) > 0)
+ __fwprintf (stderr, L"%s", buf);
+ else
+ fputs (buf, stderr);
+
+ free (buf);
+ }
+#endif
}
nextchar = (char *) "";
optind++;
@@ -790,13 +891,42 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
{
if (print_errors)
{
+#if defined _LIBC && defined USE_IN_LIBIO
+ char *buf;
+ int n;
+#endif
+
if (posixly_correct)
- /* 1003.2 specifies the format of this message. */
- fprintf (stderr, _("%s: illegal option -- %c\n"),
- argv[0], c);
+ {
+ /* 1003.2 specifies the format of this message. */
+#if defined _LIBC && defined USE_IN_LIBIO
+ n = __asprintf (&buf, _("%s: illegal option -- %c\n"),
+ argv[0], c);
+#else
+ fprintf (stderr, _("%s: illegal option -- %c\n"), argv[0], c);
+#endif
+ }
else
- fprintf (stderr, _("%s: invalid option -- %c\n"),
- argv[0], c);
+ {
+#if defined _LIBC && defined USE_IN_LIBIO
+ n = __asprintf (&buf, _("%s: invalid option -- %c\n"),
+ argv[0], c);
+#else
+ fprintf (stderr, _("%s: invalid option -- %c\n"), argv[0], c);
+#endif
+ }
+
+#if defined _LIBC && defined USE_IN_LIBIO
+ if (n >= 0)
+ {
+ if (_IO_fwide (stderr, 0) > 0)
+ __fwprintf (stderr, L"%s", buf);
+ else
+ fputs (buf, stderr);
+
+ free (buf);
+ }
+#endif
}
optopt = c;
return '?';
@@ -825,8 +955,24 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
if (print_errors)
{
/* 1003.2 specifies the format of this message. */
+#if defined _LIBC && defined USE_IN_LIBIO
+ char *buf;
+
+ if (__asprintf (&buf,
+ _("%s: option requires an argument -- %c\n"),
+ argv[0], c) >= 0)
+ {
+ if (_IO_fwide (stderr, 0) > 0)
+ __fwprintf (stderr, L"%s", buf);
+ else
+ fputs (buf, stderr);
+
+ free (buf);
+ }
+#else
fprintf (stderr, _("%s: option requires an argument -- %c\n"),
argv[0], c);
+#endif
}
optopt = c;
if (optstring[0] == ':')
@@ -872,8 +1018,25 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
if (ambig && !exact)
{
if (print_errors)
- fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"),
- argv[0], argv[optind]);
+ {
+#if defined _LIBC && defined USE_IN_LIBIO
+ char *buf;
+
+ if (__asprintf (&buf, _("%s: option `-W %s' is ambiguous\n"),
+ argv[0], argv[optind]) >= 0)
+ {
+ if (_IO_fwide (stderr, 0) > 0)
+ __fwprintf (stderr, L"%s", buf);
+ else
+ fputs (buf, stderr);
+
+ free (buf);
+ }
+#else
+ fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"),
+ argv[0], argv[optind]);
+#endif
+ }
nextchar += strlen (nextchar);
optind++;
return '?';
@@ -890,9 +1053,27 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
else
{
if (print_errors)
- fprintf (stderr, _("\
+ {
+#if defined _LIBC && defined USE_IN_LIBIO
+ char *buf;
+
+ if (__asprintf (&buf, _("\
+%s: option `-W %s' doesn't allow an argument\n"),
+ argv[0], pfound->name) >= 0)
+ {
+ if (_IO_fwide (stderr, 0) > 0)
+ __fwprintf (stderr, L"%s", buf);
+ else
+ fputs (buf, stderr);
+
+ free (buf);
+ }
+#else
+ fprintf (stderr, _("\
%s: option `-W %s' doesn't allow an argument\n"),
- argv[0], pfound->name);
+ argv[0], pfound->name);
+#endif
+ }
nextchar += strlen (nextchar);
return '?';
@@ -905,9 +1086,27 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
else
{
if (print_errors)
- fprintf (stderr,
- _("%s: option `%s' requires an argument\n"),
- argv[0], argv[optind - 1]);
+ {
+#if defined _LIBC && defined USE_IN_LIBIO
+ char *buf;
+
+ if (__asprintf (&buf, _("\
+%s: option `%s' requires an argument\n"),
+ argv[0], argv[optind - 1]) >= 0)
+ {
+ if (_IO_fwide (stderr, 0) > 0)
+ __fwprintf (stderr, L"%s", buf);
+ else
+ fputs (buf, stderr);
+
+ free (buf);
+ }
+#else
+ fprintf (stderr,
+ _("%s: option `%s' requires an argument\n"),
+ argv[0], argv[optind - 1]);
+#endif
+ }
nextchar += strlen (nextchar);
return optstring[0] == ':' ? ':' : '?';
}
@@ -954,9 +1153,25 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
if (print_errors)
{
/* 1003.2 specifies the format of this message. */
+#if defined _LIBC && defined USE_IN_LIBIO
+ char *buf;
+
+ if (__asprintf (&buf, _("\
+%s: option requires an argument -- %c\n"),
+ argv[0], c) >= 0)
+ {
+ if (_IO_fwide (stderr, 0) > 0)
+ __fwprintf (stderr, L"%s", buf);
+ else
+ fputs (buf, stderr);
+
+ free (buf);
+ }
+#else
fprintf (stderr,
_("%s: option requires an argument -- %c\n"),
argv[0], c);
+#endif
}
optopt = c;
if (optstring[0] == ':')
diff --git a/contrib/groff/src/libs/libgroff/getopt1.c b/contrib/groff/src/libs/libgroff/getopt1.c
index 3d264f2..22a7efb 100644
--- a/contrib/groff/src/libs/libgroff/getopt1.c
+++ b/contrib/groff/src/libs/libgroff/getopt1.c
@@ -4,19 +4,19 @@
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
The GNU C Library 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
- Library General Public License for more details.
+ Lesser General Public License for more details.
- You should have received a copy of the GNU Library General Public
- License along with the GNU C Library; see the file COPYING.LIB. If not,
- write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
#ifdef HAVE_CONFIG_H
#include <config.h>
diff --git a/contrib/groff/src/libs/libgroff/htmlhint.cc b/contrib/groff/src/libs/libgroff/htmlhint.cc
new file mode 100644
index 0000000..3015767
--- /dev/null
+++ b/contrib/groff/src/libs/libgroff/htmlhint.cc
@@ -0,0 +1,59 @@
+/* Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
+ Written by Gaius Mulley (gaius@glam.ac.uk)
+
+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 "lib.h"
+
+#include <stddef.h>
+#include <stdlib.h>
+
+#include "nonposix.h"
+#include "stringclass.h"
+#include "html-strings.h"
+
+/*
+ * This file contains a very simple set of routines which might
+ * be shared by preprocessors. It allows a preprocessor to indicate
+ * when an inline image should be created.
+ * This string is intercepted by pre-grohtml and substituted for
+ * the image name and suppression escapes.
+ *
+ * pre-html runs troff twice, once with -Thtml and once with -Tps.
+ * troff -Thtml device driver emits a <src='image'.png> tag
+ * and the postscript device driver works out the min/max limits
+ * of the graphic region. These region limits are read by pre-html
+ * and an image is generated via troff -Tps -> gs -> png
+ */
+
+/*
+ * html_begin_suppress - emit a start of image tag which will be seen
+ * by pre-html.
+ */
+void html_begin_suppress()
+{
+ put_string(HTML_IMAGE_INLINE_BEGIN, stdout);
+}
+
+/*
+ * html_end_suppress - emit an end of image tag which will be seen
+ * by pre-html.
+ */
+void html_end_suppress()
+{
+ put_string(HTML_IMAGE_INLINE_END, stdout);
+}
diff --git a/contrib/groff/src/libs/libgroff/invalid.cc b/contrib/groff/src/libs/libgroff/invalid.cc
new file mode 100644
index 0000000..f36894a
--- /dev/null
+++ b/contrib/groff/src/libs/libgroff/invalid.cc
@@ -0,0 +1,60 @@
+/* Copyright (C) 2000, 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 "lib.h"
+
+// Table of invalid input characters.
+
+char invalid_char_table[256]= {
+#ifndef IS_EBCDIC_HOST
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+#else
+ 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1,
+ 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+#endif
+};
diff --git a/contrib/groff/src/libs/libgroff/itoa.c b/contrib/groff/src/libs/libgroff/itoa.c
index 72826b7..245c7df 100644
--- a/contrib/groff/src/libs/libgroff/itoa.c
+++ b/contrib/groff/src/libs/libgroff/itoa.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 1989, 1990, 1991, 1992, 2000 Free Software Foundation, Inc.
+/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2002
+ Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
This file is part of groff.
@@ -18,6 +19,7 @@ with groff; see the file COPYING. If not, write to the Free Software
Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#define INT_DIGITS 19 /* enough for 64 bit integer */
+#define UINT_DIGITS 20
char *i_to_a(i)
int i;
@@ -41,3 +43,16 @@ char *i_to_a(i)
}
return p;
}
+
+char *ui_to_a(i)
+ unsigned int i;
+{
+ /* Room for UINT_DIGITS digits and '\0' */
+ static char buf[UINT_DIGITS + 1];
+ char *p = buf + UINT_DIGITS; /* points to terminating '\0' */
+ do {
+ *--p = '0' + (i % 10);
+ i /= 10;
+ } while (i != 0);
+ return p;
+}
diff --git a/contrib/groff/src/libs/libgroff/matherr.c b/contrib/groff/src/libs/libgroff/matherr.c
index b0097b8..757a540 100644
--- a/contrib/groff/src/libs/libgroff/matherr.c
+++ b/contrib/groff/src/libs/libgroff/matherr.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+/* Copyright (C) 1989, 1990, 1991, 1992, 2001 Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
This file is part of groff.
@@ -17,6 +17,10 @@ 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. */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
#include <math.h>
#include <errno.h>
diff --git a/contrib/groff/src/libs/libgroff/maxfilename.cc b/contrib/groff/src/libs/libgroff/maxfilename.cc
index c5a03d7..341cf92 100644
--- a/contrib/groff/src/libs/libgroff/maxfilename.cc
+++ b/contrib/groff/src/libs/libgroff/maxfilename.cc
@@ -20,6 +20,8 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* file_name_max(dir) does the same as pathconf(dir, _PC_NAME_MAX) */
+#include "lib.h"
+
#include <sys/types.h>
#ifdef HAVE_UNISTD_H
diff --git a/contrib/groff/src/libs/libgroff/mksdir.cc b/contrib/groff/src/libs/libgroff/mksdir.cc
new file mode 100644
index 0000000..bf4d300
--- /dev/null
+++ b/contrib/groff/src/libs/libgroff/mksdir.cc
@@ -0,0 +1,34 @@
+/* Copyright (C) 2001 Free Software Foundation, Inc.
+ Written by Werner Lemberg (wl@gnu.org)
+
+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. */
+
+
+/* This file is heavily based on the file mkstemp.c which is part of the
+ fileutils package. */
+
+
+extern int gen_tempname(char *, int = 0);
+
+/* Generate a unique temporary directory name from TEMPLATE.
+ The last six characters of TEMPLATE must be "XXXXXX";
+ they are replaced with a string that makes the filename unique.
+ Then open the directory and return a fd. */
+int mksdir(char *tmpl)
+{
+ return gen_tempname(tmpl, 1);
+}
diff --git a/contrib/groff/src/libs/libgroff/mkstemp.cc b/contrib/groff/src/libs/libgroff/mkstemp.cc
new file mode 100644
index 0000000..cd2717c
--- /dev/null
+++ b/contrib/groff/src/libs/libgroff/mkstemp.cc
@@ -0,0 +1,34 @@
+/* Copyright (C) 2001 Free Software Foundation, Inc.
+ Written by Werner Lemberg (wl@gnu.org)
+
+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. */
+
+
+/* This file is heavily based on the file mkstemp.c which is part of the
+ fileutils package. */
+
+
+extern int gen_tempname(char *, int);
+
+/* Generate a unique temporary file name from TEMPLATE.
+ The last six characters of TEMPLATE must be "XXXXXX";
+ they are replaced with a string that makes the filename unique.
+ Then open the file and return a fd. */
+int mkstemp(char *tmpl)
+{
+ return gen_tempname(tmpl, 0);
+}
diff --git a/contrib/groff/src/libs/libgroff/nametoindex.cc b/contrib/groff/src/libs/libgroff/nametoindex.cc
index 578ff34..7c94b25 100644
--- a/contrib/groff/src/libs/libgroff/nametoindex.cc
+++ b/contrib/groff/src/libs/libgroff/nametoindex.cc
@@ -1,5 +1,6 @@
// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992, 2000 Free Software Foundation, Inc.
+/* 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.
@@ -18,12 +19,11 @@ 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 <stdio.h>
-#include <string.h>
+#include "lib.h"
+
#include <ctype.h>
#include <assert.h>
#include <stdlib.h>
-#include "lib.h"
#include "errarg.h"
#include "error.h"
#include "font.h"
@@ -45,7 +45,6 @@ private:
int ascii_index[256];
int small_number_index[NSMALL];
PTABLE(int) table;
- int lookup_char(const char *, int);
};
character_indexer::character_indexer()
diff --git a/contrib/groff/src/libs/libgroff/new.cc b/contrib/groff/src/libs/libgroff/new.cc
index 8d98591..4975149 100644
--- a/contrib/groff/src/libs/libgroff/new.cc
+++ b/contrib/groff/src/libs/libgroff/new.cc
@@ -1,4 +1,4 @@
-/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+/* Copyright (C) 1989, 1990, 1991, 1992, 2001 Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
This file is part of groff.
@@ -17,9 +17,10 @@ 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 "lib.h"
+
#include <stddef.h>
#include <stdlib.h>
-#include <string.h>
#include "posix.h"
#include "nonposix.h"
diff --git a/contrib/groff/src/libs/libgroff/paper.cc b/contrib/groff/src/libs/libgroff/paper.cc
new file mode 100644
index 0000000..d79733e
--- /dev/null
+++ b/contrib/groff/src/libs/libgroff/paper.cc
@@ -0,0 +1,84 @@
+// -*- C++ -*-
+/* Copyright (C) 2002
+ Free Software Foundation, Inc.
+ Written by Werner Lemberg (wl@gnu.org)
+
+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 "lib.h"
+#include "paper.h"
+
+paper papersizes[NUM_PAPERSIZES];
+
+// length and width in mm
+static void add_iso_paper(char series, int offset,
+ int start_length, int start_width)
+{
+ int length = start_length;
+ int width = start_width;
+ for (int i = 0; i < 8; i++)
+ {
+ char *p = new char[3];
+ p[0] = series;
+ p[1] = '0' + i;
+ p[2] = '\0';
+ papersizes[offset + i].name = p;
+ // convert mm to inch
+ papersizes[offset + i].length = (double)length / 25.4;
+ papersizes[offset + i].width = (double)width / 25.4;
+ // after division by two, values must be rounded down to the next
+ // integer (as specified by ISO)
+ int tmp = width;
+ width = length;
+ length = tmp / 2;
+ }
+}
+
+// length and width in inch
+static void add_american_paper(const char *name, int index,
+ double length, double width )
+{
+ char *p = new char[strlen(name) + 1];
+ strcpy(p, name);
+ papersizes[index].name = p;
+ papersizes[index].length = length;
+ papersizes[index].width = width;
+}
+
+int papersize_init::initialised = 0;
+
+papersize_init::papersize_init()
+{
+ if (initialised)
+ return;
+ initialised = 1;
+ add_iso_paper('a', 0, 1189, 841);
+ add_iso_paper('b', 8, 1414, 1000);
+ add_iso_paper('c', 16, 1297, 917);
+ add_iso_paper('d', 24, 1090, 771);
+ add_american_paper("letter", 32, 11, 8.5);
+ add_american_paper("legal", 33, 14, 8.5);
+ add_american_paper("tabloid", 34, 17, 11);
+ add_american_paper("ledger", 35, 11, 17);
+ add_american_paper("statement", 36, 8.5, 5.5);
+ add_american_paper("executive", 37, 10, 7.5);
+ // the next three entries are for grolj4
+ add_american_paper("com10", 38, 9.5, 4.125);
+ add_american_paper("monarch", 39, 7.5, 3.875);
+ // this is an ISO format, but it easier to use add_american_paper
+ add_american_paper("dl", 40, 220/25.4, 110/25.4);
+}
diff --git a/contrib/groff/src/libs/libgroff/putenv.c b/contrib/groff/src/libs/libgroff/putenv.c
index c1ca671..2091f3b 100644
--- a/contrib/groff/src/libs/libgroff/putenv.c
+++ b/contrib/groff/src/libs/libgroff/putenv.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991 Free Software Foundation, Inc.
+/* Copyright (C) 1991, 2001 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -18,6 +18,10 @@ Cambridge, MA 02139, USA. */
/* Hacked slightly by jjc@jclark.com for groff. */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
#include <string.h>
#ifdef __STDC__
diff --git a/contrib/groff/src/libs/libgroff/searchpath.cc b/contrib/groff/src/libs/libgroff/searchpath.cc
index f4e2b90..1f8b233 100644
--- a/contrib/groff/src/libs/libgroff/searchpath.cc
+++ b/contrib/groff/src/libs/libgroff/searchpath.cc
@@ -1,5 +1,6 @@
// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992, 2000 Free Software Foundation, Inc.
+/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001
+ Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
This file is part of groff.
@@ -18,12 +19,11 @@ 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 <stdio.h>
-#include <string.h>
+#include "lib.h"
+
#include <stdlib.h>
#include <assert.h>
-#include "lib.h"
#include "searchpath.h"
#include "nonposix.h"
diff --git a/contrib/groff/src/libs/libgroff/strerror.c b/contrib/groff/src/libs/libgroff/strerror.c
index 69089f1..be2d1f3 100644
--- a/contrib/groff/src/libs/libgroff/strerror.c
+++ b/contrib/groff/src/libs/libgroff/strerror.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+/* Copyright (C) 1989, 1990, 1991, 1992, 2001 Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
This file is part of groff.
@@ -17,6 +17,10 @@ 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. */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
#include <stdio.h>
#define INT_DIGITS 19 /* enough for 64 bit integer */
diff --git a/contrib/groff/src/libs/libgroff/string.cc b/contrib/groff/src/libs/libgroff/string.cc
index 4bcd4cc..2ef547e 100644
--- a/contrib/groff/src/libs/libgroff/string.cc
+++ b/contrib/groff/src/libs/libgroff/string.cc
@@ -1,5 +1,6 @@
// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+/* Copyright (C) 1989, 1990, 1991, 1992, 2001, 2002
+ Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
This file is part of groff.
@@ -18,10 +19,10 @@ 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 <stdio.h>
-#include "stringclass.h"
#include "lib.h"
+#include "stringclass.h"
+
static char *salloc(int len, int *sizep);
static void sfree(char *ptr, int size);
static char *sfree_alloc(char *ptr, int size, int len, int *sizep);
@@ -290,10 +291,39 @@ char *string::extract() const
for (i = 0; i < n; i++)
if (p[i] != '\0')
*r++ = p[i];
- q[n] = '\0';
+ *r = '\0';
return q;
}
+void string::remove_spaces()
+{
+ int l = len - 1;
+ while (l >= 0 && ptr[l] == ' ')
+ l--;
+ char *p = ptr;
+ if (l > 0)
+ while (*p == ' ') {
+ p++;
+ l--;
+ }
+ if (len - 1 != l) {
+ if (l >= 0) {
+ len = l + 1;
+ char *tmp = new char[len];
+ memcpy(tmp, p, len);
+ a_delete ptr;
+ ptr = tmp;
+ }
+ else {
+ len = 0;
+ if (ptr) {
+ a_delete ptr;
+ ptr = 0;
+ }
+ }
+ }
+}
+
void put_string(const string &s, FILE *fp)
{
int len = s.length();
diff --git a/contrib/groff/src/libs/libgroff/strtol.c b/contrib/groff/src/libs/libgroff/strtol.c
index 61ce70e..46b1702 100644
--- a/contrib/groff/src/libs/libgroff/strtol.c
+++ b/contrib/groff/src/libs/libgroff/strtol.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 1989, 1990, 1991, 1992, 2000 Free Software Foundation, Inc.
+/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001
+ Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
This file is part of groff.
@@ -17,6 +18,10 @@ 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. */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
#include <string.h>
#include <ctype.h>
#include <errno.h>
diff --git a/contrib/groff/src/libs/libgroff/tmpfile.cc b/contrib/groff/src/libs/libgroff/tmpfile.cc
index 8508c59..41b7f06 100644
--- a/contrib/groff/src/libs/libgroff/tmpfile.cc
+++ b/contrib/groff/src/libs/libgroff/tmpfile.cc
@@ -19,23 +19,16 @@ 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 <stdio.h>
+#include "lib.h"
+
#include <errno.h>
-#include <string.h>
#include <stdlib.h>
#include "posix.h"
-#include "lib.h"
#include "errarg.h"
#include "error.h"
#include "nonposix.h"
-#ifndef HAVE_MKSTEMP_PROTO
-extern "C" {
- extern int mkstemp (char *);
-}
-#endif
-
// If this is set, create temporary files there
#define GROFF_TMPDIR_ENVVAR "GROFF_TMPDIR"
// otherwise if this is set, create temporary files there
@@ -48,11 +41,49 @@ extern "C" {
# define DEFAULT_TMPDIR "/tmp"
#endif
// Use this as the prefix for temporary filenames.
-#ifdef __MSDOS__
-#define TMPFILE_PREFIX ""
-#else
-#define TMPFILE_PREFIX "groff"
-#endif
+#define TMPFILE_PREFIX_SHORT ""
+#define TMPFILE_PREFIX_LONG "groff"
+
+char *tmpfile_prefix;
+size_t tmpfile_prefix_len;
+int use_short_postfix = 0;
+
+struct temp_init {
+ temp_init();
+ ~temp_init();
+} _temp_init;
+
+temp_init::temp_init()
+{
+ const char *tem = getenv(GROFF_TMPDIR_ENVVAR);
+ if (!tem) {
+ tem = getenv(TMPDIR_ENVVAR);
+ if (!tem)
+ tem = DEFAULT_TMPDIR;
+ }
+ size_t tem_len = strlen(tem);
+ const char *tem_end = tem + tem_len - 1;
+ int need_slash = strchr(DIR_SEPS, *tem_end) == NULL ? 1 : 0;
+ char *tem2 = new char[tem_len + need_slash + 1];
+ strcpy(tem2, tem);
+ if (need_slash)
+ strcat(tem2, "/");
+ const char *tem3 = TMPFILE_PREFIX_LONG;
+ if (file_name_max(tem2) <= 14) {
+ tem3 = TMPFILE_PREFIX_SHORT;
+ use_short_postfix = 1;
+ }
+ tmpfile_prefix_len = tem_len + need_slash + strlen(tem3);
+ tmpfile_prefix = new char[tmpfile_prefix_len + 1];
+ strcpy(tmpfile_prefix, tem2);
+ strcat(tmpfile_prefix, tem3);
+ a_delete tem2;
+}
+
+temp_init::~temp_init()
+{
+ a_delete tmpfile_prefix;
+}
/*
* Generate a temporary name template with a postfix
@@ -62,85 +93,67 @@ extern "C" {
* only the *template* is returned.
*/
-char *xtmptemplate(char *postfix)
+char *xtmptemplate(const char *postfix_long, const char *postfix_short)
{
- const char *dir = getenv(GROFF_TMPDIR_ENVVAR);
+ const char *postfix = use_short_postfix ? postfix_short : postfix_long;
int postlen = 0;
-
if (postfix)
postlen = strlen(postfix);
-
- if (!dir) {
- dir = getenv(TMPDIR_ENVVAR);
- if (!dir)
- dir = DEFAULT_TMPDIR;
- }
-
- size_t dir_len = strlen(dir);
- const char *dir_end = dir + dir_len - 1;
- int needs_slash = strchr(DIR_SEPS, *dir_end) == NULL;
- char *templ = new char[strlen(dir) + needs_slash
- + sizeof(TMPFILE_PREFIX) - 1 + 6 + 1 + postlen];
- strcpy(templ, dir);
- if (needs_slash)
- strcat(templ, "/");
- strcat(templ, TMPFILE_PREFIX);
+ char *templ = new char[tmpfile_prefix_len + postlen + 6 + 1];
+ strcpy(templ, tmpfile_prefix);
if (postlen > 0)
strcat(templ, postfix);
strcat(templ, "XXXXXX");
-
- return( templ );
+ return templ;
}
// The trick with unlinking the temporary file while it is still in
// use is not portable, it will fail on MS-DOS and most MS-Windows
// filesystems. So it cannot be used on non-Posix systems.
-// Instead, we maintain a list of files to be deleted on exit, and
-// register an atexit function that will remove them all in one go.
+// Instead, we maintain a list of files to be deleted on exit.
// This should be portable to all platforms.
-static struct xtmpfile_list {
- struct xtmpfile_list *next;
- char fname[1];
-} *xtmpfiles_to_delete;
+struct xtmpfile_list {
+ char *fname;
+ xtmpfile_list *next;
+ xtmpfile_list(char *fn) : fname(fn), next(0) {}
+};
+
+xtmpfile_list *xtmpfiles_to_delete = 0;
-static void remove_tmp_files()
+struct xtmpfile_list_init {
+ ~xtmpfile_list_init();
+} _xtmpfile_list_init;
+
+xtmpfile_list_init::~xtmpfile_list_init()
{
- struct xtmpfile_list *p = xtmpfiles_to_delete;
-
- while (p) {
- if (unlink(p->fname) < 0)
- error("cannot unlink `%1': %2", p->fname, strerror(errno));
- struct xtmpfile_list *old = p;
- p = p->next;
- free(old);
+ xtmpfile_list *x = xtmpfiles_to_delete;
+ while (x != 0) {
+ if (unlink(x->fname) < 0)
+ error("cannot unlink `%1': %2", x->fname, strerror(errno));
+ xtmpfile_list *tmp = x;
+ x = x->next;
+ a_delete tmp->fname;
+ delete tmp;
}
}
static void add_tmp_file(const char *name)
{
- if (xtmpfiles_to_delete == NULL)
- atexit(remove_tmp_files);
-
- struct xtmpfile_list *p
- = (struct xtmpfile_list *)malloc(sizeof(struct xtmpfile_list)
- + strlen (name));
- if (p == NULL) {
- error("cannot unlink `%1': %2", name, strerror(errno));
- return;
- }
- p->next = xtmpfiles_to_delete;
- strcpy(p->fname, name);
- xtmpfiles_to_delete = p;
+ char *s = new char[strlen(name)+1];
+ strcpy(s, name);
+ xtmpfile_list *x = new xtmpfile_list(s);
+ x->next = xtmpfiles_to_delete;
+ xtmpfiles_to_delete = x;
}
// Open a temporary file and with fatal error on failure.
-FILE *xtmpfile(char **namep, char *postfix, int do_unlink)
+FILE *xtmpfile(char **namep,
+ const char *postfix_long, const char *postfix_short,
+ int do_unlink)
{
- char *templ = xtmptemplate(postfix);
-
-#ifdef HAVE_MKSTEMP
+ char *templ = xtmptemplate(postfix_long, postfix_short);
errno = 0;
int fd = mkstemp(templ);
if (fd < 0)
@@ -149,17 +162,9 @@ FILE *xtmpfile(char **namep, char *postfix, int do_unlink)
FILE *fp = fdopen(fd, FOPEN_RWB); // many callers of xtmpfile use binary I/O
if (!fp)
fatal("fdopen: %1", strerror(errno));
-#else /* not HAVE_MKSTEMP */
- if (!mktemp(templ) || !templ[0])
- fatal("cannot create file name for temporary file");
- errno = 0;
- FILE *fp = fopen(templ, FOPEN_RWB);
- if (!fp)
- fatal("cannot open `%1': %2", templ, strerror(errno));
-#endif /* not HAVE_MKSTEMP */
if (do_unlink)
add_tmp_file(templ);
- if ((namep != 0) && ((*namep) != 0))
+ if (namep)
*namep = templ;
else
a_delete templ;
diff --git a/contrib/groff/src/libs/libgroff/tmpname.cc b/contrib/groff/src/libs/libgroff/tmpname.cc
new file mode 100644
index 0000000..213b0ee
--- /dev/null
+++ b/contrib/groff/src/libs/libgroff/tmpname.cc
@@ -0,0 +1,116 @@
+/* Copyright (C) 2001 Free Software Foundation, Inc.
+ Written by Werner Lemberg (wl@gnu.org)
+
+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. */
+
+
+/* This file is heavily based on the function __gen_tempname() in the
+ file tempname.c which is part of the fileutils package. */
+
+
+#include "lib.h"
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <time.h>
+
+#include "posix.h"
+#include "nonposix.h"
+
+#ifndef TMP_MAX
+# define TMP_MAX 238328
+#endif
+
+#if HAVE_SYS_TIME_H
+# include <sys/time.h>
+#endif
+
+#ifdef HAVE_GETTIMEOFDAY
+#ifdef NEED_DECLARATION_GETTIMEOFDAY
+extern "C" {
+ int gettimeofday(struct timeval *, void *);
+}
+#endif
+#endif
+
+#if HAVE_STDINT_H
+# include <stdint.h>
+#endif
+
+/* Use the widest available unsigned type if uint64_t is not
+ available. The algorithm below extracts a number less than 62**6
+ (approximately 2**35.725) from uint64_t, so ancient hosts where
+ uintmax_t is only 32 bits lose about 3.725 bits of randomness,
+ which is better than not having mkstemp at all. */
+#if !defined UINT64_MAX && !defined uint64_t
+# define uint64_t uintmax_t
+#endif
+
+/* These are the characters used in temporary filenames. */
+static const char letters[] =
+"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+
+int gen_tempname(char *tmpl, int dir)
+{
+ static uint64_t value;
+
+ size_t len = strlen(tmpl);
+ if (len < 6 || strcmp(&tmpl[len - 6], "XXXXXX"))
+ return -1; /* EINVAL */
+
+ /* This is where the Xs start. */
+ char *XXXXXX = &tmpl[len - 6];
+
+ /* Get some more or less random data. */
+#if HAVE_GETTIMEOFDAY
+ timeval tv;
+ gettimeofday(&tv, NULL);
+ uint64_t random_time_bits = ((uint64_t)tv.tv_usec << 16) ^ tv.tv_sec;
+#else
+ uint64_t random_time_bits = time(NULL);
+#endif
+ value += random_time_bits ^ getpid();
+
+ for (int count = 0; count < TMP_MAX; value += 7777, ++count) {
+ uint64_t v = value;
+
+ /* Fill in the random bits. */
+ XXXXXX[0] = letters[v % 62];
+ v /= 62;
+ XXXXXX[1] = letters[v % 62];
+ v /= 62;
+ XXXXXX[2] = letters[v % 62];
+ v /= 62;
+ XXXXXX[3] = letters[v % 62];
+ v /= 62;
+ XXXXXX[4] = letters[v % 62];
+ v /= 62;
+ XXXXXX[5] = letters[v % 62];
+
+ int fd = dir ? mkdir(tmpl, S_IRUSR | S_IWUSR | S_IXUSR)
+ : open(tmpl, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
+
+ if (fd >= 0)
+ return fd;
+ else if (errno != EEXIST)
+ return -1;
+ }
+
+ /* We got out of the loop because we ran out of combinations to try. */
+ return -1; /* EEXIST */
+}
diff --git a/contrib/groff/src/preproc/eqn/Makefile.sub b/contrib/groff/src/preproc/eqn/Makefile.sub
index 20421e1c..6997290 100644
--- a/contrib/groff/src/preproc/eqn/Makefile.sub
+++ b/contrib/groff/src/preproc/eqn/Makefile.sub
@@ -1,22 +1,22 @@
-PROG=eqn
+PROG=eqn$(EXEEXT)
MAN1=eqn.n neqn.n
XLIBS=$(LIBGROFF)
OBJS=\
- eqn.o \
- main.o \
- lex.o \
- box.o \
- limit.o \
- list.o \
- over.o \
- text.o \
- script.o \
- mark.o \
- other.o \
- delim.o \
- sqrt.o \
- pile.o \
- special.o
+ eqn.$(OBJEXT) \
+ main.$(OBJEXT) \
+ lex.$(OBJEXT) \
+ box.$(OBJEXT) \
+ limit.$(OBJEXT) \
+ list.$(OBJEXT) \
+ over.$(OBJEXT) \
+ text.$(OBJEXT) \
+ script.$(OBJEXT) \
+ mark.$(OBJEXT) \
+ other.$(OBJEXT) \
+ delim.$(OBJEXT) \
+ sqrt.$(OBJEXT) \
+ pile.$(OBJEXT) \
+ special.$(OBJEXT)
CCSRCS=\
$(srcdir)/main.cc \
$(srcdir)/lex.cc \
@@ -37,8 +37,8 @@ HDRS=\
$(srcdir)/eqn.h \
$(srcdir)/pbox.h
GRAM=$(srcdir)/eqn.y
-YTABC=$(srcdir)/eqn.cc
-YTABH=$(srcdir)/eqn_tab.h
+YTABC=eqn.cc
+YTABH=eqn_tab.h
NAMEPREFIX=$(g)
CLEANADD=neqn
diff --git a/contrib/groff/src/preproc/eqn/box.cc b/contrib/groff/src/preproc/eqn/box.cc
index 4e61b5d..41d8dff 100644
--- a/contrib/groff/src/preproc/eqn/box.cc
+++ b/contrib/groff/src/preproc/eqn/box.cc
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+/* Copyright (C) 1989, 1990, 1991, 1992, 2002 Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
This file is part of groff.
@@ -232,7 +232,7 @@ void start_string()
void output_string()
{
- printf("\\*[" LINE_STRING "]\n");
+ printf("\\*(" LINE_STRING "\n");
}
void restore_compatibility()
@@ -259,7 +259,7 @@ void set_script_size()
if (script_size_reduction >= 0)
printf(".ps \\n[.s]-%d>?%d\n", script_size_reduction, minimum_size);
else
- printf(".ps (u;\\n[.s]*7+5/10>?%d)*1z\n", minimum_size);
+ printf(".ps (u;\\n[.ps]*7+5/10>?%d)\n", minimum_size);
}
int box::next_uid = 0;
@@ -281,7 +281,7 @@ void box::top_level()
printf(".ft\n");
printf(".nr " SAVED_PREV_FONT_REG " \\n[.f]\n");
printf(".ft %s\n", get_gfont());
- printf(".nr " SAVED_SIZE_REG " \\n[.s]z\n");
+ printf(".nr " SAVED_SIZE_REG " \\n[.ps]\n");
if (gsize > 0) {
char buf[INT_DIGITS + 1];
sprintf(buf, "%d", gsize);
@@ -299,7 +299,7 @@ void box::top_level()
printf(".nr " MARK_WIDTH_REG " 0\\n[" WIDTH_FORMAT "]\n", b->uid);
}
else if (r == FOUND_LINEUP)
- printf(".if r" SAVED_MARK_REG " .as " LINE_STRING " \\h'\\n["
+ printf(".if r" SAVED_MARK_REG " .as1 " LINE_STRING " \\h'\\n["
SAVED_MARK_REG "]u-\\n[" MARK_REG "]u'\n");
else
assert(r == FOUND_NOTHING);
@@ -311,9 +311,9 @@ void box::top_level()
"\\R'" SAVED_INLINE_FONT_REG " \\\\n[.f]'"
"\\fP"
"\\R'" SAVED_INLINE_PREV_FONT_REG " \\\\n[.f]'"
- "\\R'" SAVED_INLINE_SIZE_REG " \\\\n[.s]z'"
+ "\\R'" SAVED_INLINE_SIZE_REG " \\\\n[.ps]'"
"\\s0"
- "\\R'" SAVED_INLINE_PREV_SIZE_REG " \\\\n[.s]z'"
+ "\\R'" SAVED_INLINE_PREV_SIZE_REG " \\\\n[.ps]'"
"\n"
".ds " RESTORE_FONT_STRING " "
"\\f[\\\\n[" SAVED_INLINE_PREV_FONT_REG "]]"
@@ -321,14 +321,14 @@ void box::top_level()
"\\s'\\\\n[" SAVED_INLINE_PREV_SIZE_REG "]u'"
"\\s'\\\\n[" SAVED_INLINE_SIZE_REG "]u'"
"\n");
- printf(".as " LINE_STRING " \\&\\E*[" SAVE_FONT_STRING "]");
+ printf(".as1 " LINE_STRING " \\&\\E*[" SAVE_FONT_STRING "]");
printf("\\f[%s]", get_gfont());
printf("\\s'\\En[" SAVED_SIZE_REG "]u'");
current_roman_font = get_grfont();
b->output();
printf("\\E*[" RESTORE_FONT_STRING "]\n");
if (r == FOUND_LINEUP)
- printf(".if r" SAVED_MARK_REG " .as " LINE_STRING " \\h'\\n["
+ printf(".if r" SAVED_MARK_REG " .as1 " LINE_STRING " \\h'\\n["
MARK_WIDTH_REG "]u-\\n[" SAVED_MARK_REG "]u-(\\n["
WIDTH_FORMAT "]u-\\n[" MARK_REG "]u)'\n",
b->uid);
@@ -351,20 +351,20 @@ void box::extra_space()
if (positive_space >= 0 || negative_space >= 0) {
if (positive_space > 0)
printf(".if !\\n[" EQN_NO_EXTRA_SPACE_REG "] "
- ".as " LINE_STRING " \\x'-%dM'\n", positive_space);
+ ".as1 " LINE_STRING " \\x'-%dM'\n", positive_space);
if (negative_space > 0)
printf(".if !\\n[" EQN_NO_EXTRA_SPACE_REG "] "
- ".as " LINE_STRING " \\x'%dM'\n", negative_space);
+ ".as1 " LINE_STRING " \\x'%dM'\n", negative_space);
positive_space = negative_space = -1;
}
else {
printf(".if !\\n[" EQN_NO_EXTRA_SPACE_REG "] "
- ".if \\n[" HEIGHT_FORMAT "]>%dM .as " LINE_STRING
+ ".if \\n[" HEIGHT_FORMAT "]>%dM .as1 " LINE_STRING
" \\x'-(\\n[" HEIGHT_FORMAT
"]u-%dM)'\n",
uid, body_height, uid, body_height);
printf(".if !\\n[" EQN_NO_EXTRA_SPACE_REG "] "
- ".if \\n[" DEPTH_FORMAT "]>%dM .as " LINE_STRING
+ ".if \\n[" DEPTH_FORMAT "]>%dM .as1 " LINE_STRING
" \\x'\\n[" DEPTH_FORMAT
"]u-%dM'\n",
uid, body_depth, uid, body_depth);
diff --git a/contrib/groff/src/preproc/eqn/eqn.h b/contrib/groff/src/preproc/eqn/eqn.h
index 70b1927..ee25f03 100644
--- a/contrib/groff/src/preproc/eqn/eqn.h
+++ b/contrib/groff/src/preproc/eqn/eqn.h
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+/* Copyright (C) 1989, 1990, 1991, 1992, 2001 Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
This file is part of groff.
@@ -18,15 +18,14 @@ 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 <stdio.h>
-#include <string.h>
+#include "lib.h"
+
#include <assert.h>
#include <stdlib.h>
#include <errno.h>
#include "cset.h"
#include "errarg.h"
#include "error.h"
-#include "lib.h"
#include "box.h"
diff --git a/contrib/groff/src/preproc/eqn/eqn.man b/contrib/groff/src/preproc/eqn/eqn.man
index bc7dc7e..6d0733c 100644
--- a/contrib/groff/src/preproc/eqn/eqn.man
+++ b/contrib/groff/src/preproc/eqn/eqn.man
@@ -42,7 +42,7 @@ the original English.
.el .RB "[\ " "\\$1" "\ ]"
..
.OP \-rvCNR
-.OP \-d cc
+.OP \-d xy
.OP \-T name
.OP \-M dir
.OP \-f F
@@ -97,6 +97,16 @@ it does not support low-resolution, typewriter-like devices
(although it may work adequately for very simple input).
.SH OPTIONS
.TP
+.BI \-d xy
+Specify delimiters
+.I x
+and
+.I y
+for the left and right end, respectively, of in-line equations.
+Any
+.B delim
+statements in the source file overrides this.
+.TP
.B \-C
Recognize
.B .EQ
@@ -456,7 +466,7 @@ by drawing a diagonal line through it.
.IP
.nf
.ft B
-.ne 6+\n(.Vu
+.if t .ne 6+\n(.Vu
\&.EQ
define cancel 'special Ca'
\&.EN
@@ -475,7 +485,7 @@ Here's a more complicated construct that draws a box round an expression:
.IP
.nf
.ft B
-.ne 11+\n(.Vu
+.if t .ne 11+\n(.Vu
\&.EQ
define box 'special Bx'
\&.EN
diff --git a/contrib/groff/src/preproc/eqn/lex.cc b/contrib/groff/src/preproc/eqn/lex.cc
index e14053d..4e62f86 100644
--- a/contrib/groff/src/preproc/eqn/lex.cc
+++ b/contrib/groff/src/preproc/eqn/lex.cc
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001
+/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001, 2002
Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
@@ -371,8 +371,8 @@ int file_input::read_line()
int c = getc(fp);
if (c == EOF)
break;
- else if (illegal_input_char(c))
- lex_error("illegal input character code %1", c);
+ else if (invalid_input_char(c))
+ lex_error("invalid input character code %1", c);
else {
line += char(c);
if (c == '\n')
@@ -467,7 +467,7 @@ int top_input::get_location(char **fnp, int *lnp)
return 1;
}
-// Character representing $1. Must be illegal input character.
+// Character representing $1. Must be invalid input character.
#define ARG1 14
argument_macro_input::argument_macro_input(const char *body, int ac,
diff --git a/contrib/groff/src/preproc/eqn/limit.cc b/contrib/groff/src/preproc/eqn/limit.cc
index 046885d..c8b5587 100644
--- a/contrib/groff/src/preproc/eqn/limit.cc
+++ b/contrib/groff/src/preproc/eqn/limit.cc
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+/* Copyright (C) 1989, 1990, 1991, 1992, 2002 Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
This file is part of groff.
@@ -55,10 +55,10 @@ limit_box::~limit_box()
int limit_box::compute_metrics(int style)
{
- printf(".nr " SIZE_FORMAT " \\n[.s]\n", uid);
+ printf(".nr " SIZE_FORMAT " \\n[.ps]\n", uid);
if (!(style <= SCRIPT_STYLE && one_size_reduction_flag))
set_script_size();
- printf(".nr " SMALL_SIZE_FORMAT " \\n[.s]\n", uid);
+ printf(".nr " SMALL_SIZE_FORMAT " \\n[.ps]\n", uid);
int res = 0;
int mark_uid = -1;
if (from != 0) {
@@ -75,7 +75,7 @@ int limit_box::compute_metrics(int style)
res = r;
}
}
- printf(".ps \\n[" SIZE_FORMAT "]\n", uid);
+ printf(".ps \\n[" SIZE_FORMAT "]u\n", uid);
int r = p->compute_metrics(style);
p->compute_subscript_kern();
if (res && r)
@@ -139,7 +139,7 @@ int limit_box::compute_metrics(int style)
void limit_box::output()
{
- printf("\\s[\\n[" SMALL_SIZE_FORMAT "]]", uid);
+ printf("\\s[\\n[" SMALL_SIZE_FORMAT "]u]", uid);
if (to != 0) {
printf("\\Z" DELIMITER_CHAR);
printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid);
@@ -158,7 +158,7 @@ void limit_box::output()
from->output();
printf(DELIMITER_CHAR);
}
- printf("\\s[\\n[" SIZE_FORMAT "]]", uid);
+ printf("\\s[\\n[" SIZE_FORMAT "]u]", uid);
printf("\\Z" DELIMITER_CHAR);
printf("\\h'\\n[" LEFT_WIDTH_FORMAT "]u"
"-(\\n[" WIDTH_FORMAT "]u/2u)'",
diff --git a/contrib/groff/src/preproc/eqn/main.cc b/contrib/groff/src/preproc/eqn/main.cc
index f53ffa3..dabac5f 100644
--- a/contrib/groff/src/preproc/eqn/main.cc
+++ b/contrib/groff/src/preproc/eqn/main.cc
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001
+/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001, 2002
Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
@@ -24,8 +24,9 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "device.h"
#include "searchpath.h"
#include "macropath.h"
-#include "htmlindicate.h"
+#include "htmlhint.h"
#include "pbox.h"
+#include "ctype.h"
#define STARTUP_FILE "eqnrc"
@@ -44,9 +45,6 @@ int one_size_reduction_flag = 0;
int compatible_flag = 0;
int no_newline_in_delim_flag = 0;
int html = 0;
-// if we encounter a region marked as an image then we
-// do not mark up inline equations.
-int suppress_html = 0;
int read_line(FILE *fp, string *p)
@@ -54,10 +52,10 @@ int read_line(FILE *fp, string *p)
p->clear();
int c = -1;
while ((c = getc(fp)) != EOF) {
- if (!illegal_input_char(c))
+ if (!invalid_input_char(c))
*p += char(c);
else
- error("illegal input character code `%1'", c);
+ error("invalid input character code `%1'", c);
if (c == '\n')
break;
}
@@ -81,33 +79,12 @@ void do_file(FILE *fp, const char *filename)
if (interpret_lf_args(linebuf.contents() + 3))
current_lineno--;
}
- else if (linebuf.length() >= 12
- && linebuf[0] == '.' && linebuf[1] == 'H' && linebuf[2] == 'T'
- && linebuf[3] == 'M' && linebuf[4] == 'L' && linebuf[5] == '-'
- && linebuf[6] == 'I' && linebuf[7] == 'M' && linebuf[8] == 'A'
- && linebuf[9] == 'G' && linebuf[10] == 'E'
- && linebuf[11] == '\n') {
- put_string(linebuf, stdout);
- suppress_html++;
- }
- else if (linebuf.length() >= 16
- && linebuf[0] == '.' && linebuf[1] == 'H' && linebuf[2] == 'T'
- && linebuf[3] == 'M' && linebuf[4] == 'L' && linebuf[5] == '-'
- && linebuf[6] == 'I' && linebuf[7] == 'M' && linebuf[8] == 'A'
- && linebuf[9] == 'G' && linebuf[10] == 'E' && linebuf[11] == '-'
- && linebuf[12] == 'E' && linebuf[13] == 'N' && linebuf[14] == 'D'
- && linebuf[15] == '\n') {
- put_string(linebuf, stdout);
- suppress_html--;
- }
else if (linebuf.length() >= 4
&& linebuf[0] == '.'
&& linebuf[1] == 'E'
&& linebuf[2] == 'Q'
&& (linebuf[3] == ' ' || linebuf[3] == '\n'
|| compatible_flag)) {
- if (html && (suppress_html == 0))
- graphic_start(0);
put_string(linebuf, stdout);
int start_lineno = current_lineno + 1;
str.clear();
@@ -132,15 +109,13 @@ void do_file(FILE *fp, const char *filename)
non_empty_flag = 0;
inline_flag = 0;
yyparse();
+ restore_compatibility();
if (non_empty_flag) {
printf(".lf %d\n", current_lineno - 1);
output_string();
}
- restore_compatibility();
printf(".lf %d\n", current_lineno);
put_string(linebuf, stdout);
- if (html && (suppress_html == 0))
- graphic_end();
}
else if (start_delim != '\0' && linebuf.search(start_delim) >= 0
&& inline_equation(fp, linebuf, str))
@@ -190,21 +165,22 @@ static int inline_equation(FILE *fp, string &linebuf, string &str)
}
str += ptr;
if (!read_line(fp, &linebuf))
- fatal("end of file before `%1'", end_delim);
+ fatal("unterminated `%1' at line %2, looking for `%3'",
+ start_delim, start_lineno, end_delim);
linebuf += '\0';
ptr = &linebuf[0];
}
str += '\0';
- if (html && (suppress_html == 0)) {
- printf(".as %s ", LINE_STRING);
- graphic_start(1);
+ if (html) {
+ printf(".as1 %s ", LINE_STRING);
+ html_begin_suppress();
printf("\n");
}
init_lex(str.contents(), current_filename, start_lineno);
yyparse();
- if (html && (suppress_html == 0)) {
- printf(".as %s ", LINE_STRING);
- graphic_end();
+ if (html) {
+ printf(".as1 %s ", LINE_STRING);
+ html_end_suppress();
printf("\n");
}
start = delim_search(ptr, start_delim);
@@ -216,9 +192,9 @@ static int inline_equation(FILE *fp, string &linebuf, string &str)
break;
}
}
+ restore_compatibility();
printf(".lf %d\n", current_lineno);
output_string();
- restore_compatibility();
printf(".lf %d\n", current_lineno + 1);
return 1;
}
@@ -311,9 +287,9 @@ int main(int argc, char **argv)
case 'd':
if (optarg[0] == '\0' || optarg[1] == '\0')
error("-d requires two character argument");
- else if (illegal_input_char(optarg[0]))
+ else if (invalid_input_char(optarg[0]))
error("bad delimiter `%1'", optarg[0]);
- else if (illegal_input_char(optarg[1]))
+ else if (invalid_input_char(optarg[1]))
error("bad delimiter `%1'", optarg[1]);
else {
start_delim = optarg[0];
diff --git a/contrib/groff/src/preproc/eqn/other.cc b/contrib/groff/src/preproc/eqn/other.cc
index eb9e50a..c052f52 100644
--- a/contrib/groff/src/preproc/eqn/other.cc
+++ b/contrib/groff/src/preproc/eqn/other.cc
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+/* Copyright (C) 1989, 1990, 1991, 1992, 2002 Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
This file is part of groff.
@@ -392,11 +392,11 @@ size_box::size_box(char *s, box *pp) : pointer_box(pp), size(s)
int size_box::compute_metrics(int style)
{
- printf(".nr " SIZE_FORMAT " \\n[.s]\n", uid);
+ printf(".nr " SIZE_FORMAT " \\n[.ps]\n", uid);
printf(".ps %s\n", size);
- printf(".nr " SMALL_SIZE_FORMAT " \\n[.s]\n", uid);
+ printf(".nr " SMALL_SIZE_FORMAT " \\n[.ps]\n", uid);
int r = p->compute_metrics(style);
- printf(".ps \\n[" SIZE_FORMAT "]\n", uid);
+ printf(".ps \\n[" SIZE_FORMAT "]u\n", uid);
printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]\n", uid, p->uid);
printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n", uid, p->uid);
printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid);
@@ -405,9 +405,9 @@ int size_box::compute_metrics(int style)
void size_box::output()
{
- printf("\\s[\\n[" SMALL_SIZE_FORMAT "]]", uid);
+ printf("\\s[\\n[" SMALL_SIZE_FORMAT "]u]", uid);
p->output();
- printf("\\s[\\n[" SIZE_FORMAT "]]", uid);
+ printf("\\s[\\n[" SIZE_FORMAT "]u]", uid);
}
size_box::~size_box()
diff --git a/contrib/groff/src/preproc/eqn/over.cc b/contrib/groff/src/preproc/eqn/over.cc
index 4c544d1..279efc8 100644
--- a/contrib/groff/src/preproc/eqn/over.cc
+++ b/contrib/groff/src/preproc/eqn/over.cc
@@ -1,5 +1,6 @@
// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992, 2001 Free Software Foundation, Inc.
+/* Copyright (C) 1989, 1990, 1991, 1992, 2001, 2002
+ Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
This file is part of groff.
@@ -61,9 +62,9 @@ int over_box::compute_metrics(int style)
{
if (reduce_size) {
style = script_style(style);
- printf(".nr " SIZE_FORMAT " \\n[.s]\n", uid);
+ printf(".nr " SIZE_FORMAT " \\n[.ps]\n", uid);
set_script_size();
- printf(".nr " SMALL_SIZE_FORMAT " \\n[.s]\n", uid);
+ printf(".nr " SMALL_SIZE_FORMAT " \\n[.ps]\n", uid);
}
int mark_uid = 0;
int res = num->compute_metrics(style);
@@ -77,7 +78,7 @@ int over_box::compute_metrics(int style)
res = r;
}
if (reduce_size)
- printf(".ps \\n[" SIZE_FORMAT "]\n", uid);
+ printf(".ps \\n[" SIZE_FORMAT "]u\n", uid);
printf(".nr " WIDTH_FORMAT " (\\n[" WIDTH_FORMAT "]>?\\n[" WIDTH_FORMAT "]",
uid, num->uid, den->uid);
// allow for \(ru being wider than both the numerator and denominator
@@ -118,7 +119,7 @@ int over_box::compute_metrics(int style)
void over_box::output()
{
if (reduce_size)
- printf("\\s[\\n[" SMALL_SIZE_FORMAT "]]", uid);
+ printf("\\s[\\n[" SMALL_SIZE_FORMAT "]u]", uid);
#ifdef USE_Z
printf("\\Z" DELIMITER_CHAR);
#endif
@@ -165,7 +166,7 @@ void over_box::output()
printf("\\v'-\\n[" SUB_LOWER_FORMAT "]u'", uid);
#endif
if (reduce_size)
- printf("\\s[\\n[" SIZE_FORMAT "]]", uid);
+ printf("\\s[\\n[" SIZE_FORMAT "]u]", uid);
// draw the line
printf("\\h'%dM'", null_delimiter_space);
printf("\\v'-%dM'", axis_height);
diff --git a/contrib/groff/src/preproc/eqn/script.cc b/contrib/groff/src/preproc/eqn/script.cc
index 7c2e6c2..62a05b4 100644
--- a/contrib/groff/src/preproc/eqn/script.cc
+++ b/contrib/groff/src/preproc/eqn/script.cc
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+/* Copyright (C) 1989, 1990, 1991, 1992, 2002 Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
This file is part of groff.
@@ -73,10 +73,10 @@ int script_box::compute_metrics(int style)
{
int res = p->compute_metrics(style);
p->compute_subscript_kern();
- printf(".nr " SIZE_FORMAT " \\n[.s]\n", uid);
+ printf(".nr " SIZE_FORMAT " \\n[.ps]\n", uid);
if (!(style <= SCRIPT_STYLE && one_size_reduction_flag))
set_script_size();
- printf(".nr " SMALL_SIZE_FORMAT " \\n[.s]\n", uid);
+ printf(".nr " SMALL_SIZE_FORMAT " \\n[.ps]\n", uid);
if (sub != 0)
sub->compute_metrics(cramped_style(script_style(style)));
if (sup != 0)
@@ -92,7 +92,7 @@ int script_box::compute_metrics(int style)
printf(".nr " SUB_LOWER_FORMAT " \\n[" DEPTH_FORMAT "]+%dM\n",
uid, p->uid, sub_drop);
}
- printf(".ps \\n[" SIZE_FORMAT "]\n", uid);
+ printf(".ps \\n[" SIZE_FORMAT "]u\n", uid);
if (sup == 0) {
assert(sub != 0);
// 18b
@@ -171,18 +171,18 @@ void script_box::output()
if (sup != 0) {
printf("\\Z" DELIMITER_CHAR);
printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid);
- printf("\\s[\\n[" SMALL_SIZE_FORMAT "]]", uid);
+ printf("\\s[\\n[" SMALL_SIZE_FORMAT "]u]", uid);
sup->output();
- printf("\\s[\\n[" SIZE_FORMAT "]]", uid);
+ printf("\\s[\\n[" SIZE_FORMAT "]u]", uid);
printf(DELIMITER_CHAR);
}
if (sub != 0) {
printf("\\Z" DELIMITER_CHAR);
printf("\\v'\\n[" SUB_LOWER_FORMAT "]u'", uid);
- printf("\\s[\\n[" SMALL_SIZE_FORMAT "]]", uid);
+ printf("\\s[\\n[" SMALL_SIZE_FORMAT "]u]", uid);
printf("\\h'-\\n[" SUB_KERN_FORMAT "]u'", p->uid);
sub->output();
- printf("\\s[\\n[" SIZE_FORMAT "]]", uid);
+ printf("\\s[\\n[" SIZE_FORMAT "]u]", uid);
printf(DELIMITER_CHAR);
}
printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u'",
diff --git a/contrib/groff/src/preproc/eqn/sqrt.cc b/contrib/groff/src/preproc/eqn/sqrt.cc
index 6109ffe..bffa4f2 100644
--- a/contrib/groff/src/preproc/eqn/sqrt.cc
+++ b/contrib/groff/src/preproc/eqn/sqrt.cc
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+/* Copyright (C) 1989, 1990, 1991, 1992, 2002 Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
This file is part of groff.
@@ -54,7 +54,7 @@ int sqrt_box::compute_metrics(int style)
"]+%dM+(%dM/4)\n",
p->uid, p->uid, default_rule_thickness,
(style > SCRIPT_STYLE ? x_height : default_rule_thickness));
- printf(".nr " SIZE_FORMAT " \\n[.s]\n", uid);
+ printf(".nr " SIZE_FORMAT " \\n[.ps]\n", uid);
printf(".ds " SQRT_STRING_FORMAT " " SQRT_CHAR "\n", uid);
printf(".ds " BAR_STRING " " RADICAL_EXTENSION_CHAR "\n");
printf(".nr " SQRT_WIDTH_FORMAT
@@ -84,8 +84,8 @@ int sqrt_box::compute_metrics(int style)
// Determine the maximum point size
printf(".ps 1000\n");
- printf(".nr " MAX_SIZE_REG " \\n[.s]\n");
- printf(".ps \\n[" SIZE_FORMAT "]\n", uid);
+ printf(".nr " MAX_SIZE_REG " \\n[.ps]\n");
+ printf(".ps \\n[" SIZE_FORMAT "]u\n", uid);
// We define a macro that will increase the current point size
// until we get a radical sign that's tall enough or we reach
// the maximum point size.
@@ -93,7 +93,7 @@ int sqrt_box::compute_metrics(int style)
".nr " SQRT_WIDTH_FORMAT
" 0\\w" DELIMITER_CHAR "\\*[" SQRT_STRING_FORMAT "]" DELIMITER_CHAR "\n"
".if \\\\n[rst]-\\\\n[rsb]-%dM<\\n[" TEMP_REG "]"
- "&(\\\\n[.s]<\\n[" MAX_SIZE_REG "]) \\{"
+ "&(\\\\n[.ps]<\\n[" MAX_SIZE_REG "]) \\{"
".ps +1\n"
"." TEMP_MACRO "\n"
".\\}\n"
@@ -103,7 +103,7 @@ int sqrt_box::compute_metrics(int style)
printf(".\\}\\}\n");
- printf(".nr " SMALL_SIZE_FORMAT " \\n[.s]\n", uid);
+ printf(".nr " SMALL_SIZE_FORMAT " \\n[.ps]\n", uid);
// set TEMP_REG to the amount by which the radical sign is too big
printf(".nr " TEMP_REG " \\n[rst]-\\n[rsb]-%dM-\\n[" TEMP_REG "]\n",
default_rule_thickness);
@@ -143,17 +143,17 @@ int sqrt_box::compute_metrics(int style)
uid, p->uid, uid);
// put a bit of extra space above the bar
printf(".nr " HEIGHT_FORMAT " +%dM\n", uid, default_rule_thickness);
- printf(".ps \\n[" SIZE_FORMAT "]\n", uid);
+ printf(".ps \\n[" SIZE_FORMAT "]u\n", uid);
return r;
}
void sqrt_box::output()
{
printf("\\Z" DELIMITER_CHAR);
- printf("\\s[\\n[" SMALL_SIZE_FORMAT "]]", uid);
+ printf("\\s[\\n[" SMALL_SIZE_FORMAT "]u]", uid);
printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid);
printf("\\*[" SQRT_STRING_FORMAT "]", uid);
- printf("\\s[\\n[" SIZE_FORMAT "]]", uid);
+ printf("\\s[\\n[" SIZE_FORMAT "]u]", uid);
printf(DELIMITER_CHAR);
printf("\\Z" DELIMITER_CHAR);
diff --git a/contrib/groff/src/preproc/grn/Makefile.sub b/contrib/groff/src/preproc/grn/Makefile.sub
index ffa0ad2..d180803 100644
--- a/contrib/groff/src/preproc/grn/Makefile.sub
+++ b/contrib/groff/src/preproc/grn/Makefile.sub
@@ -1,12 +1,12 @@
-PROG=grn
+PROG=grn$(EXEEXT)
MAN1=grn.n
MLIB=$(LIBM)
XLIBS=$(LIBGROFF)
OBJS=\
- hdb.o \
- hpoint.o \
- hgraph.o \
- main.o
+ hdb.$(OBJEXT) \
+ hpoint.$(OBJEXT) \
+ hgraph.$(OBJEXT) \
+ main.$(OBJEXT)
CCSRCS=\
$(srcdir)/hdb.cc \
$(srcdir)/hpoint.cc \
diff --git a/contrib/groff/src/preproc/grn/README b/contrib/groff/src/preproc/grn/README
index b5b9fc9..7ac685e 100644
--- a/contrib/groff/src/preproc/grn/README
+++ b/contrib/groff/src/preproc/grn/README
@@ -16,7 +16,15 @@ because the gremlin editor uses the conventional spline
algorithm. The Berkeley grn has the choice of different
stipples. Here, only different shades of gray will be painted
depending on the gremlin file. It is possible to upgrade this at
-a later time. (Daniel Senderowicz <daniel@synchrods.com> 12/28/99)
+a later time. (Daniel Senderowicz <daniel@synchrods.com> 12/28/99)
+
+=====================================================================
+
+Gremlin produces three types of curves: B-Splines, interpolated
+curves and Bezier. As the original Berkeley grn, now groff grn
+will honor B-Splines and interpolated curves. Bezier curves will
+be printed as B-Splines. (Daniel Senderowicz <daniel@synchrods.com>
+10/04/02)
=====================================================================
diff --git a/contrib/groff/src/preproc/grn/gprint.h b/contrib/groff/src/preproc/grn/gprint.h
index b25305b..b9df60e 100644
--- a/contrib/groff/src/preproc/grn/gprint.h
+++ b/contrib/groff/src/preproc/grn/gprint.h
@@ -38,6 +38,8 @@
#define ARC 4
#define CURVE 5
#define POLYGON 6
+#define BSPLINE 7
+#define BEZIER 8
#define TOPLEFT 10
#define TOPCENT 11
#define TOPRIGHT 12
diff --git a/contrib/groff/src/preproc/grn/grn.man b/contrib/groff/src/preproc/grn/grn.man
index 82e43cf..9722145 100644
--- a/contrib/groff/src/preproc/grn/grn.man
+++ b/contrib/groff/src/preproc/grn/grn.man
@@ -1,6 +1,6 @@
'\" t
.ig
-Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
Permission is granted to make and distribute verbatim copies of
this manual provided the copyright notice and this permission notice
@@ -46,7 +46,7 @@ the original English.
.BI \-F dir
]
[
-.IR file\.\.\.
+.IR file\.\.\.\&
]
.PP
It is possible to have whitespace between a command line option and its
@@ -131,8 +131,11 @@ for subdirectories
.RI ( name
is the name of the device) for the
.B DESC
-file before the normal
-.BR @FONTDIR@ .
+file before the default font directories
+.BR @LOCALFONTDIR@ ,
+.BR @FONTDIR@ ,
+and
+.BR @LEGACYFONTDIR@ .
.TP
.B \-C
Recognize
@@ -217,7 +220,7 @@ confusion with
There is
.I no
default for stipples (unless one is set by the default command), and it is
-illegal to include a
+invalid to include a
.I gremlin
picture with polygons without specifying a
stipple font.
@@ -408,7 +411,6 @@ format is the use of names for picture objects (e.g., POLYGON, CURVE)
instead of numbers.
Files representing the same picture are shown in Table 1 in each format.
.sp
-.DS
.TS
center, tab(@);
l lw(0.1i) l.
@@ -435,7 +437,6 @@ css.
.sp
Table 1. File examples
.TE
-.DE
.sp
.IP \(bu
The first line of each
@@ -479,6 +480,8 @@ The stuff on this line really isn't all that important; a value of ``1 0.00
.IP \(bu
The rest of the file consists of zero or more element specifications.
After the last element specification is a line containing the string ``-1''.
+.IP \(bu
+Lines longer than 127 characters are chopped to this limit.
.SH ELEMENT SPECIFICATIONS
.IP \(bu
The first line of each element contains a single decimal number giving the
@@ -489,7 +492,6 @@ version) or its ASCII name
version).
See Table 2.
.sp
-.DS
.TS
center, tab(@);
css
@@ -505,6 +507,8 @@ nll.
4@ARC@arc
5@CURVE@curve
6@POLYGON@polygon
+7@BSPLINE@b-spline
+8@BEZIER@B\['e]zier
10@TOPLEFT@top-left-justified text
11@TOPCENT@top-center-justified text
12@TOPRIGHT@top-right-justified text
@@ -517,7 +521,6 @@ css.
Table 2.
Type Specifications in \fIgremlin\fP Files
.TE
-.DE
.sp
.IP \(bu
After the object type comes a variable number of lines, each specifying a
@@ -536,7 +539,6 @@ brush and size for the element.
The brush determines the style in which things are drawn.
For vectors, arcs, and curves there are six legal brush values:
.sp
-.DS
.TS
center, tab(@);
ncw(0.1i)l.
@@ -547,13 +549,11 @@ ncw(0.1i)l.
5 \(mi@@thin solid lines
6 \(mi@@medium solid lines
.TE
-.DE
.sp
For polygons, one more value, 0, is legal.
It specifies a polygon with an invisible border.
For text, the brush selects a font as follows:
.sp
-.DS
.TS
center, tab(@);
ncw(0.1i)l.
@@ -562,7 +562,6 @@ ncw(0.1i)l.
3 \(mi@@bold (B font in groff)
4 \(mi@@special (S font in groff)
.TE
-.DE
.sp
If you're using
.I @g@grn
@@ -570,9 +569,9 @@ to run your pictures through
.IR groff ,
the font is really just a starting font:
The text string can contain formatting sequences like
-``\\fI''
+``\efI''
or
-``\\d''
+``\ed''
which may change the font (as well as do many other things).
For text, the size field is a decimal value between 1 and 4.
It selects the size of the font in which the text will be drawn.
diff --git a/contrib/groff/src/preproc/grn/hdb.cc b/contrib/groff/src/preproc/grn/hdb.cc
index fd5bb48..648a535 100644
--- a/contrib/groff/src/preproc/grn/hdb.cc
+++ b/contrib/groff/src/preproc/grn/hdb.cc
@@ -15,6 +15,7 @@
#include "error.h"
#define MAXSTRING 128
+#define MAXSTRING_S "127"
/* imports from main.cc */
@@ -89,7 +90,7 @@ DBRead(register FILE *file)
SUNFILE = FALSE;
elist = DBInit();
- (void) fscanf(file, "%s\n", string);
+ (void) fscanf(file, "%" MAXSTRING_S "s%*[^\n]\n", string);
if (strcmp(string, "gremlinfile")) {
if (strcmp(string, "sungremlinfile")) {
error("`%1' is not a gremlin file", gremlinfile);
@@ -103,10 +104,10 @@ DBRead(register FILE *file)
done = FALSE;
while (!done) {
- /* if (fscanf(file,"%s\n", string) == EOF) */
+ /* if (fscanf(file,"%" MAXSTRING_S "s\n", string) == EOF) */
/* I changed the scanf format because the element */
/* can have two words (e.g. CURVE SPLINE) */
- if (fscanf(file, "\n%[^\n]\n", string) == EOF) {
+ if (fscanf(file, "\n%" MAXSTRING_S "[^\n]%*[^\n]\n", string) == EOF) {
error("`%1', error in file format", gremlinfile);
return (elist);
}
@@ -210,8 +211,20 @@ DBGetType(register char *s)
case 'A':
return (ARC);
case 'C':
- if (s[1] == 'U')
- return (CURVE);
+ if (s[1] == 'U') {
+ if (s[5] == '\n')
+ return (CURVE);
+ switch (s[7]) {
+ case 'S':
+ return(BSPLINE);
+ case 'E':
+ fprintf(stderr,
+ "Warning: Bezier Curves will be printed as B-Splines\n");
+ return(BSPLINE);
+ default:
+ return(CURVE);
+ }
+ }
switch (s[4]) {
case 'L':
return (CENTLEFT);
diff --git a/contrib/groff/src/preproc/grn/hgraph.cc b/contrib/groff/src/preproc/grn/hgraph.cc
index 7963720..d307faa 100644
--- a/contrib/groff/src/preproc/grn/hgraph.cc
+++ b/contrib/groff/src/preproc/grn/hgraph.cc
@@ -4,6 +4,8 @@
* to troff input.
*/
+#include "lib.h"
+
#include "gprint.h"
#ifdef NEED_DECLARATION_HYPOT
@@ -58,12 +60,13 @@ void tmove2(int px, int py);
void doarc(POINT cp, POINT sp, int angle);
void tmove(POINT * ptr);
void cr();
-void drawwig(POINT * ptr);
+void drawwig(POINT * ptr, int type);
void HGtline(int x1, int y1);
void dx(double x);
void dy(double y);
void HGArc(register int cx, register int cy, int px, int py, int angle);
void picurve(register int *x, register int *y, int npts);
+void HGCurve(int *x, int *y, int numpoints);
void Paramaterize(int x[], int y[], float h[], int n);
void PeriodicSpline(float h[], int z[],
float dz[], float d2z[], float d3z[],
@@ -126,8 +129,14 @@ HGPrintElt(ELT *element,
break;
case CURVE:
- length = 0; /* keep track of line length */
- drawwig(p1);
+ length = 0; /* keep track of line length */
+ drawwig(p1, CURVE);
+ cr();
+ break;
+
+ case BSPLINE:
+ length = 0; /* keep track of line length */
+ drawwig(p1, BSPLINE);
cr();
break;
@@ -533,16 +542,17 @@ line(int px,
/*----------------------------------------------------------------------------
- | Routine: drawwig (ptr)
+ | Routine: drawwig (ptr, type)
|
| Results: The point sequence found in the structure pointed by ptr is
| placed in integer arrays for further manipulation by the
- | existing routing. With the proper parameters, HGCurve is
- | called.
+ | existing routing. With the corresponding type parameter,
+ | either picurve or HGCurve are called.
*----------------------------------------------------------------------------*/
void
-drawwig(POINT * ptr)
+drawwig(POINT * ptr,
+ int type)
{
register int npts; /* point list index */
int x[MAXPOINTS], y[MAXPOINTS]; /* point list */
@@ -552,8 +562,10 @@ drawwig(POINT * ptr)
y[npts] = (int) (ptr->y * troffscale);
}
if (--npts) {
- /* HGCurve(&x[0], &y[0], npts); */ /*Gremlin looks different, so... */
- picurve(&x[0], &y[0], npts);
+ if (type == CURVE) /* Use the 2 different types of curves */
+ HGCurve(&x[0], &y[0], npts);
+ else
+ picurve(&x[0], &y[0], npts);
}
}
diff --git a/contrib/groff/src/preproc/grn/main.cc b/contrib/groff/src/preproc/grn/main.cc
index efb33a9..9b09ea6 100644
--- a/contrib/groff/src/preproc/grn/main.cc
+++ b/contrib/groff/src/preproc/grn/main.cc
@@ -67,9 +67,10 @@
*/
+#include "lib.h"
+
#include <ctype.h>
#include <stdlib.h>
-#include <string.h>
#include "gprint.h"
#include "device.h"
@@ -77,7 +78,6 @@
#include "searchpath.h"
#include "macropath.h"
-#include "lib.h"
#include "errarg.h"
#include "error.h"
#include "defs.h"
@@ -848,7 +848,7 @@ interpret(char *line)
if (par > 0.0)
xscale *= par;
else
- error("illegal scale value on line %1", linenum);
+ error("invalid scale value on line %1", linenum);
break;
case 'f': /* file */
diff --git a/contrib/groff/src/preproc/html/Makefile.sub b/contrib/groff/src/preproc/html/Makefile.sub
index 8ecd332..5da6d43 100644
--- a/contrib/groff/src/preproc/html/Makefile.sub
+++ b/contrib/groff/src/preproc/html/Makefile.sub
@@ -1,6 +1,6 @@
-PROG=pre-grohtml
+PROG=pre-grohtml$(EXEEXT)
# MAN1=pre-grohtml.n
MAN1=
XLIBS=$(LIBGROFF)
-OBJS=pre-html.o pushbackbuffer.o
-CCSRCS=$(srcdir)/pre-html.cc $(srcdir)/pushbackbuffer.cc
+OBJS=pre-html.$(OBJEXT) pushback.$(OBJEXT)
+CCSRCS=$(srcdir)/pre-html.cc $(srcdir)/pushback.cc
diff --git a/contrib/groff/src/preproc/html/pre-html.cc b/contrib/groff/src/preproc/html/pre-html.cc
index 2a36740..e7364dd 100644
--- a/contrib/groff/src/preproc/html/pre-html.cc
+++ b/contrib/groff/src/preproc/html/pre-html.cc
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+/* Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
Written by Gaius Mulley (gaius@glam.ac.uk).
This file is part of groff.
@@ -20,18 +20,21 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#define PREHTMLC
-#include <stdio.h>
+#include "lib.h"
+
#include <signal.h>
#include <ctype.h>
#include <assert.h>
#include <stdlib.h>
#include <errno.h>
-#include "lib.h"
#include "errarg.h"
#include "error.h"
#include "stringclass.h"
#include "posix.h"
#include "defs.h"
+#include "searchpath.h"
+#include "paper.h"
+#include "font.h"
#include <errno.h>
#include <sys/types.h>
@@ -53,32 +56,27 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
extern "C" const char *Version_string;
#include "pre-html.h"
-#include "pushbackbuffer.h"
+#include "pushback.h"
#include "html-strings.h"
-#define POSTSCRIPTRES 72000 // maybe there is a better way to find this? --fixme--
-#define DEFAULT_IMAGE_RES 80 // 80 pixels per inch resolution
-#define DEFAULT_VERTICAL_OFFSET 45 // DEFAULT_VERTICAL_OFFSET/72 of an inch
+#define DEFAULT_LINE_LENGTH 7 // inches wide
+#define DEFAULT_IMAGE_RES 100 // number of pixels per inch resolution
#define IMAGE_BOARDER_PIXELS 0
-#define MAX_WIDTH 8 // inches
#define INLINE_LEADER_CHAR '\\'
-#define MAX_RETRIES 4096 // number of different page directory names to try before giving up
-#define TRANSPARENT "-background \"#FFF\" -transparent \"#FFF\""
+#define TRANSPARENT "-background white -transparent white"
+#define MIN_ALPHA_BITS 0
+#define MAX_ALPHA_BITS 4
-#ifdef __MSDOS__
-#define PAGE_TEMPLATE "pg"
-#define PS_TEMPLATE "ps"
-#define REGION_TEMPLATE "rg"
-#else
-#define PAGE_TEMPLATE "-page-"
-#define PS_TEMPLATE "-ps-"
-#define REGION_TEMPLATE "-regions-"
-#endif
+#define PAGE_TEMPLATE_SHORT "pg"
+#define PAGE_TEMPLATE_LONG "-page-"
+#define PS_TEMPLATE_SHORT "ps"
+#define PS_TEMPLATE_LONG "-ps-"
+#define REGION_TEMPLATE_SHORT "rg"
+#define REGION_TEMPLATE_LONG "-regions-"
#if 0
# define DEBUGGING
-# define DEBUG_HTML
#endif
#if !defined(TRUE)
@@ -88,31 +86,41 @@ extern "C" const char *Version_string;
# define FALSE (1==0)
#endif
-void stop() {}
-
typedef enum {CENTERED, LEFT, RIGHT, INLINE} IMAGE_ALIGNMENT;
-static int stdoutfd = 1; // output file descriptor - normally 1 but might move
+static int postscriptRes =-1; // postscript resolution, dots per inch
+static int stdoutfd = 1; // output file descriptor - normally 1 but might move
// -1 means closed
-static int copyofstdoutfd =-1; // a copy of stdout, so we can restore stdout when
+static int copyofstdoutfd =-1; // a copy of stdout, so we can restore stdout when
// writing to post-html
-static char *psFileName = NULL; // name of postscript file
-static char *regionFileName = NULL; // name of file containing all image regions
-static char *imagePageStem = NULL; // stem of all files containing page images
-static char *image_device = "pnmraw";
-static int image_res = DEFAULT_IMAGE_RES;
-static int vertical_offset= DEFAULT_VERTICAL_OFFSET;
-static char *image_template = NULL; // image template filename
-static int troff_arg = 0; // troff arg index
-static char *command_prefix = NULL; // optional prefix for some installations.
-static char *troff_command = NULL;
-static char *image_dir = NULL; // user specified image directory
+static char *psFileName = NULL; // name of postscript file
+static char *psPageName = NULL; // name of file containing postscript current page
+static char *regionFileName = NULL; // name of file containing all image regions
+static char *imagePageName = NULL; // name of bitmap image containing current page
+static char *image_device = "pnmraw";
+static int image_res = DEFAULT_IMAGE_RES;
+static int vertical_offset = 0;
+static char *image_template = NULL; // image template filename
+static char *macroset_template= NULL; // image template passed to troff by -D
+static int troff_arg = 0; // troff arg index
+static char *image_dir = NULL; // user specified image directory
+static int textAlphaBits = MAX_ALPHA_BITS;
+static int graphicAlphaBits = MAX_ALPHA_BITS;
+static char *antiAlias = NULL; // antialias arguments we pass to gs.
+static int show_progress = FALSE; // should we display page numbers as they are processed?
+static int currentPageNo = -1; // current image page number
#if defined(DEBUGGING)
static int debug = FALSE;
static char *troffFileName = NULL; // output of pre-html output which is sent to troff -Tps
static char *htmlFileName = NULL; // output of pre-html output which is sent to troff -Thtml
#endif
+static char *linebuf = NULL; // for scanning devps/DESC
+static int linebufsize = 0;
+
+const char *const FONT_ENV_VAR = "GROFF_FONT_PATH";
+static search_path font_path(FONT_ENV_VAR, FONTPATH, 0, 0);
+
/*
* Images are generated via postscript, gs and the pnm utilities.
@@ -132,12 +140,80 @@ static int do_file(const char *filename);
void sys_fatal (const char *s)
{
- fprintf(stderr, "%s: %s: %s", program_name, s, strerror(errno));
+ fatal("%1: %2", s, strerror(errno));
+}
+
+/*
+ * get_line - copies a line (w/o newline) from a file to the global line buffer
+ */
+
+int get_line (FILE *f)
+{
+ if (f == 0)
+ return 0;
+ if (linebuf == 0) {
+ linebuf = new char[128];
+ linebufsize = 128;
+ }
+ int i = 0;
+ // skip leading whitespace
+ for (;;) {
+ int c = getc(f);
+ if (c == EOF)
+ return 0;
+ if (c != ' ' && c != '\t') {
+ ungetc(c, f);
+ break;
+ }
+ }
+ for (;;) {
+ int c = getc(f);
+ if (c == EOF)
+ break;
+ if (i + 1 >= linebufsize) {
+ char *old_linebuf = linebuf;
+ linebuf = new char[linebufsize * 2];
+ memcpy(linebuf, old_linebuf, linebufsize);
+ a_delete old_linebuf;
+ linebufsize *= 2;
+ }
+ linebuf[i++] = c;
+ if (c == '\n') {
+ i--;
+ break;
+ }
+ }
+ linebuf[i] = '\0';
+ return 1;
+}
+
+/*
+ * get_resolution - returns the postscript resolution from devps/DESC
+ */
+
+static unsigned int get_resolution (void)
+{
+ char *pathp;
+ FILE *f;
+ unsigned int res;
+ f = font_path.open_file("devps/DESC", &pathp);
+ if (f == 0)
+ fatal("can't open devps/DESC");
+ while (get_line(f)) {
+ int n = sscanf(linebuf, "res %u", &res);
+ if (n >= 1) {
+ fclose(f);
+ return res;
+ }
+ }
+ fatal("can't find `res' keyword in devps/DESC");
+ return 0;
}
/*
* html_system - a wrapper for system()
*/
+
void html_system(const char *s, int redirect_stdout)
{
// Redirect standard error to the null device. This is more
@@ -160,16 +236,10 @@ void html_system(const char *s, int redirect_stdout)
fprintf(stderr, "Calling `%s' failed\n", s);
else if (status)
fprintf(stderr, "Calling `%s' returned status %d\n", s, status);
+ close(save_stderr);
+ close(save_stdout);
}
-#if 0
-
-/*
- * if/when vsnprintf becomes available on all *NIX machines we can use this function,
- * until then we must use the more complex function below which performs hand built
- * %d, %s and %%.
- */
-
/*
* make_message - taken from man printf(3), creates a string via malloc
* and places the result of the va args into string.
@@ -194,9 +264,7 @@ make_message (const char *fmt, ...)
/* If that worked, return the string. */
if (n > -1 && n < size) {
if (size > n+1) {
- np = strdup(p);
- if (np == NULL)
- sys_fatal("strdup");
+ np = strsave(p);
free(p);
return np;
}
@@ -214,142 +282,6 @@ make_message (const char *fmt, ...)
p = np; /* use realloc'ed, p */
}
}
-#else
-
-/*
- * lengthOfintToStr - returns the length of the proposed string value of i.
- * Hand built log10.
- */
-
-int
-lengthOfintToStr (int i)
-{
- int n=0;
-
- if (i < 0)
- sys_fatal("expecting positive integer value");
-
- do {
- i /= 10;
- n++;
- } while (i > 0);
- return n;
-}
-
-/*
- * intToStr - returns a string containing the positive value of i.
- * (int i is assumed to be positive).
- */
-
-char *
-intToStr (int i)
-{
- int n=lengthOfintToStr(i)+1;
- char *p = (char *)malloc(n);
-
- if (p == NULL)
- sys_fatal("malloc");
-
- if (i < 0)
- sys_fatal("expecting positive integer value");
-
- n--;
- p[n] = (char)0;
- do {
- n--;
- p[n] = (char)((i % 10) + (int)'0');
- i /= 10;
- } while (i > 0);
- return( p );
-}
-
-/*
- * make_message - returns a string built from a format specifier.
- * This function does not use vsnprintf; it only
- * understands primitive %%, %s, and %d specifiers.
- */
-
-char *
-make_message (const char *fmt, ...)
-{
- char *p = strdup(fmt); /* so we can splat a nul anywhere in the string */
- char *np;
- char *l;
- char *s;
- char *num;
- int search=0;
- va_list ap;
-
- if (p == NULL)
- sys_fatal("strdup");
-
- va_start(ap, fmt);
- while (p) {
- int lenp=strlen(p);
- char *f = strchr(p+search, '%');
-
- search = f-p;
- np = p;
-
- if (f == NULL) {
- va_end(ap);
- return p;
- }
- switch (*(f+1)) {
-
- case 'd':
- l = strdup(f+2);
- if (l == NULL)
- sys_fatal("strdup");
- *f = (char)0;
- num = intToStr(va_arg(ap, int));
- np = (char *)malloc(strlen(p)+strlen(num)+strlen(l)+1);
- if (np == NULL)
- sys_fatal("malloc");
- strcpy(np, p);
- strcat(np, num);
- strcat(np, l);
- search += strlen(np)-lenp;
- free(num);
- free(l);
- break;
- case 's':
- /* concat */
- l = f+2;
- if (l == NULL)
- sys_fatal("strdup");
- s = va_arg(ap, char *);
- *f = (char)0;
- np = (char *)malloc(strlen(l)+1+strlen(p)+strlen(s));
- if (np == NULL)
- sys_fatal("malloc");
- strcpy(np, p);
- strcat(np, s);
- strcat(np, l);
- search += strlen(s);
- break;
- case '%':
- /* remove one of the two % that we have seen */
- *f = (char)0;
- l = f+1;
- np = (char *)malloc(strlen(l)+1+strlen(p));
- if (np == NULL)
- sys_fatal("malloc");
- strcpy(np, p);
- strcat(np, l);
- search++;
- break;
- default:
- sys_fatal("unexpected format specifier");
- return NULL;
- }
- free(p);
- p = np;
- }
- va_end(ap);
- return NULL;
-}
-#endif
/*
* the class and methods for retaining ascii text
@@ -385,7 +317,7 @@ public:
void write_upto_newline (char_block **t, int *i, int is_html);
int can_see(char_block **t, int *i, char *string);
int skip_spaces(char_block **t, int *i);
- void skip_to_newline(char_block **t, int *i);
+ void skip_until_newline(char_block **t, int *i);
private:
char_block *head;
char_block *tail;
@@ -473,13 +405,12 @@ static void writeString (char *s)
}
/*
- * makeFileName - creates the image filename template.
+ * makeFileName - creates the image filename template
+ * and the macroset image template.
*/
static void makeFileName (void)
{
- char *s;
-
if ((image_dir != NULL) && (strchr(image_dir, '%') != NULL)) {
error("cannot use a `%%' within the image directory name");
exit(1);
@@ -499,19 +430,35 @@ static void makeFileName (void)
}
if (image_template == NULL)
- s = make_message("%sgrohtml-%d", image_dir, (int)getpid());
- else {
- s = make_message("%s%s", image_dir, image_template);
- }
- if (s == NULL)
+ macroset_template = make_message("%sgrohtml-%d", image_dir, (int)getpid());
+ else
+ macroset_template = make_message("%s%s", image_dir, image_template);
+
+ if (macroset_template == NULL)
sys_fatal("make_message");
- image_template = (char *)malloc(strlen("-%d")+strlen(s)+1);
+ image_template = (char *)malloc(strlen("-%d")+strlen(macroset_template)+1);
if (image_template == NULL)
sys_fatal("malloc");
- strcpy(image_template, s);
+ strcpy(image_template, macroset_template);
strcat(image_template, "-%d");
- free(s);
+}
+
+/*
+ * setupAntiAlias - sets up the antialias string, used when we call gs.
+ */
+
+static void setupAntiAlias (void)
+{
+ if (textAlphaBits == 0 && graphicAlphaBits == 0)
+ antiAlias = make_message(" ");
+ else if (textAlphaBits == 0)
+ antiAlias = make_message("-dGraphicsAlphaBits=%d ", graphicAlphaBits);
+ else if (graphicAlphaBits == 0)
+ antiAlias = make_message("-dTextAlphaBits=%d ", textAlphaBits);
+ else
+ antiAlias = make_message("-dTextAlphaBits=%d -dGraphicsAlphaBits=%d ",
+ textAlphaBits, graphicAlphaBits);
}
/*
@@ -521,7 +468,7 @@ static void makeFileName (void)
static void checkImageDir (void)
{
if ((image_dir != NULL) && (strcmp(image_dir, "") != 0))
- if (! ((mkdir(image_dir, 0700) == 0) || (errno == EEXIST))) {
+ if (! ((mkdir(image_dir, 0777) == 0) || (errno == EEXIST))) {
error("cannot create directory `%1'", image_dir);
exit(1);
}
@@ -533,17 +480,19 @@ static void checkImageDir (void)
static void write_end_image (int is_html)
{
- if (is_html) {
- /*
- * emit image name and enable output
- */
- writeString("\\O[2]\\O[1]\\O[4]\n");
- } else {
- /*
- * postscript, therefore emit image boundaries
- */
- writeString("\\O[2]\\O[4]\n");
- }
+ /*
+ * if we are producing html then these
+ * emit image name and enable output
+ * else
+ * we are producing images
+ * in which case these generate image
+ * boundaries
+ */
+ writeString("\\O[4]\\O[2]");
+ if (is_html)
+ writeString("\\O[1]");
+ else
+ writeString("\\O[0]");
}
/*
@@ -556,36 +505,29 @@ static void write_end_image (int is_html)
static void write_start_image (IMAGE_ALIGNMENT pos, int is_html)
{
- if (pos == INLINE) {
- writeString("\\O[3]\\O[5 ");
- writeString(image_template); writeString(".png]");
- } else {
- writeString(".begin \\{\\\n");
- switch (pos) {
-
- case LEFT:
- writeString(". image l ");
- break;
- case RIGHT:
- writeString(". image r ");
- break;
- case CENTERED:
- default:
- writeString(". image c ");
- }
- writeString(image_template); writeString(".png\n");
- if (! is_html) {
- writeString(".bp\n");
- writeString(".tl ''''\n");
- }
- writeString("\\}\n");
+ writeString("\\O[5");
+ switch (pos) {
+
+ case INLINE:
+ writeString("i");
+ break;
+ case LEFT:
+ writeString("l");
+ break;
+ case RIGHT:
+ writeString("r");
+ break;
+ case CENTERED:
+ default:
+ writeString("c");
+ break;
}
- if (is_html) {
- writeString("\\O[0]\n");
- } else {
+ writeString(image_template); writeString(".png]");
+ if (is_html)
+ writeString("\\O[0]\\O[3]");
+ else
// reset min/max registers
- writeString("\\O[0]\\O[1]\n");
- }
+ writeString("\\O[1]\\O[3]");
}
/*
@@ -690,11 +632,11 @@ int char_buffer::skip_spaces(char_block **t, int *i)
}
/*
- * skip_to_newline - skips all characters until a newline is seen.
- * The newline is also consumed.
+ * skip_until_newline - skips all characters until a newline is seen.
+ * The newline is not consumed.
*/
-void char_buffer::skip_to_newline (char_block **t, int *i)
+void char_buffer::skip_until_newline (char_block **t, int *i)
{
int j=*i;
@@ -702,17 +644,10 @@ void char_buffer::skip_to_newline (char_block **t, int *i)
while ((j < (*t)->used) && ((*t)->buffer[j] != '\n')) {
j++;
}
- if ((j < (*t)->used) && ((*t)->buffer[j] == '\n')) {
- j++;
- }
if (j == (*t)->used) {
*i = 0;
- if ((*t)->buffer[j-1] == '\n') {
- *t = (*t)->next;
- } else {
- *t = (*t)->next;
- skip_to_newline(t, i);
- }
+ *t = (*t)->next;
+ skip_until_newline(t, i);
} else {
// newline was seen
*i = j;
@@ -731,24 +666,7 @@ void char_buffer::write_file_troff (void)
if (t != NULL) {
do {
- /*
- * remember to check the shortest string last
- */
- if (can_see(&t, &i, HTML_IMAGE_END)) {
- write_end_image(FALSE);
- skip_to_newline(&t, &i);
- } else if (can_see(&t, &i, HTML_IMAGE_LEFT)) {
- write_start_image(LEFT, FALSE);
- skip_to_newline(&t, &i);
- } else if (can_see(&t, &i, HTML_IMAGE_RIGHT)) {
- write_start_image(RIGHT, FALSE);
- skip_to_newline(&t, &i);
- } else if (can_see(&t, &i, HTML_IMAGE_CENTERED)) {
- write_start_image(CENTERED, FALSE);
- skip_to_newline(&t, &i);
- } else {
- write_upto_newline(&t, &i, FALSE);
- }
+ write_upto_newline(&t, &i, FALSE);
} while (t != NULL);
}
if (close(stdoutfd) < 0)
@@ -820,6 +738,10 @@ public:
imageList();
~imageList();
void add(int x1, int y1, int x2, int y2, int page, int res, int maxx, char *name);
+ void createImages (void);
+ int createPage (int pageno);
+ void createImage (imageItem *i);
+ int getMaxX (int pageno);
};
/*
@@ -845,82 +767,76 @@ imageList::~imageList ()
}
/*
- * createAllPages - creates a set of images, one per page.
+ * createPage - creates one image of, page pageno, from the postscript file.
*/
-static int createAllPages (void)
+int imageList::createPage (int pageno)
{
- char buffer[4096];
char *s;
- int retries = MAX_RETRIES;
- imagePageStem = xtmptemplate(PAGE_TEMPLATE);
- strcpy(buffer, imagePageStem);
+ if (currentPageNo == pageno)
+ return 0;
- do {
- if (mktemp(imagePageStem) == NULL) {
- sys_fatal("mktemp");
- return -1;
- }
- if (mkdir(imagePageStem, 0700) == 0) break;
- if (errno == EEXIST) {
- // directory already exists, try another name
- retries--;
- if (retries == 0) {
- // time to give up
- sys_fatal("mkdir");
- return -1;
- }
- } else {
- // another error, quit
- sys_fatal("mkdir");
- return -1;
- }
- strcpy(imagePageStem, buffer);
- } while (1);
+ if (currentPageNo >= 1) {
+ /*
+ * we need to unlink the files which change each time a new page is processed.
+ * The final unlink is done by xtmpfile when pre-grohtml exits.
+ */
+ unlink(imagePageName);
+ unlink(psPageName);
+ }
+
+ if (show_progress) {
+ fprintf(stderr, "[%d] ", pageno);
+ fflush(stderr);
+ }
+#if defined(DEBUGGING)
+ if (debug)
+ fprintf(stderr, "creating page %d\n", pageno);
+#endif
+
+ s = make_message("psselect -q -p%d %s %s\n",
+ pageno, psFileName, psPageName);
+
+ if (s == NULL)
+ sys_fatal("make_message");
+#if defined(DEBUGGING)
+ if (debug) {
+ fwrite(s, sizeof(char), strlen(s), stderr);
+ fflush(stderr);
+ }
+#endif
+ html_system(s, 1);
+
s = make_message("echo showpage | "
- "gs%s -q -dSAFER -sDEVICE=%s -r%d "
- "-sOutputFile=%s/%%d %s -",
+ "gs%s -q -dBATCH -dSAFER "
+ "-dDEVICEHEIGHTPOINTS=792 "
+ "-dDEVICEWIDTHPOINTS=%d -dFIXEDMEDIA=true "
+ "-sDEVICE=%s -r%d %s "
+ "-sOutputFile=%s %s -\n",
EXE_EXT,
+ (getMaxX(pageno) * image_res) / postscriptRes,
image_device,
image_res,
- imagePageStem,
- psFileName);
+ antiAlias,
+ imagePageName,
+ psPageName);
if (s == NULL)
sys_fatal("make_message");
#if defined(DEBUGGING)
- fwrite(s, sizeof(char), strlen(s), stderr);
- fflush(stderr);
+ if (debug) {
+ fwrite(s, sizeof(char), strlen(s), stderr);
+ fflush(stderr);
+ }
#endif
html_system(s, 1);
- free(s);
+ a_delete s;
+ currentPageNo = pageno;
return 0;
}
/*
- * removeAllPages - removes all page images.
- */
-
-static void removeAllPages (void)
-{
-#if !defined(DEBUGGING)
- char *s=NULL;
- int i=1;
-
- do {
- if (s)
- free(s);
- s = make_message("%s/%d", imagePageStem, i);
- if (s == NULL)
- sys_fatal("make_message");
- i++;
- } while (unlink(s) == 0);
- rmdir(imagePageStem);
-#endif
-}
-
-/*
* min - returns the minimum of two numbers.
*/
@@ -947,38 +863,63 @@ int max (int x, int y)
}
/*
+ * getMaxX - returns the largest right hand position for any image on, pageno
+ */
+
+int imageList::getMaxX (int pageno)
+{
+ imageItem *h = head;
+ int x = postscriptRes * DEFAULT_LINE_LENGTH;
+
+ while (h != NULL) {
+ if (h->pageNo == pageno)
+ x = max(h->X2, x);
+ h = h->next;
+ }
+ return x;
+}
+
+/*
* createImage - generates a minimal png file from the set of page images.
*/
-static void createImage (imageItem *i)
+void imageList::createImage (imageItem *i)
{
if (i->X1 != -1) {
char *s;
- int x1 = max(min(i->X1, i->X2)*image_res/POSTSCRIPTRES-1*IMAGE_BOARDER_PIXELS, 0);
- int y1 = max((image_res*vertical_offset/72)+min(i->Y1, i->Y2)*image_res/POSTSCRIPTRES-IMAGE_BOARDER_PIXELS, 0);
- int x2 = max(i->X1, i->X2)*image_res/POSTSCRIPTRES+1*IMAGE_BOARDER_PIXELS;
- int y2 = (image_res*vertical_offset/72)+max(i->Y1, i->Y2)*image_res/POSTSCRIPTRES+1*IMAGE_BOARDER_PIXELS;
-
- s = make_message("pnmcut%s %d %d %d %d < %s/%d | pnmtopng%s %s > %s \n",
- EXE_EXT,
- x1, y1, x2-x1+1, y2-y1+1,
- imagePageStem,
- i->pageNo,
- EXE_EXT,
- TRANSPARENT,
- i->imageName);
- if (s == NULL)
- sys_fatal("make_message");
+ int x1 = max(min(i->X1, i->X2)*image_res/postscriptRes-1*IMAGE_BOARDER_PIXELS, 0);
+ int y1 = max((image_res*vertical_offset/72)+min(i->Y1, i->Y2)*image_res/postscriptRes-IMAGE_BOARDER_PIXELS, 0);
+ int x2 = max(i->X1, i->X2)*image_res/postscriptRes+1*IMAGE_BOARDER_PIXELS;
+ int y2 = (image_res*vertical_offset/72)+(max(i->Y1, i->Y2)*image_res/postscriptRes)+1+IMAGE_BOARDER_PIXELS;
+ if (createPage(i->pageNo) == 0) {
+ s = make_message("pnmcut%s %d %d %d %d < %s | pnmcrop -quiet | pnmtopng%s %s > %s \n",
+ EXE_EXT,
+ x1, y1, x2-x1+1, y2-y1+1,
+ imagePageName,
+ EXE_EXT,
+ TRANSPARENT,
+ i->imageName);
+ if (s == NULL)
+ sys_fatal("make_message");
#if defined(DEBUGGING)
- fprintf(stderr, s);
+ if (debug) {
+ fprintf(stderr, s);
+ fflush(stderr);
+ }
#endif
- html_system(s, 0);
- free(s);
+ html_system(s, 0);
+ a_delete s;
+ } else {
+ fprintf(stderr, "failed to generate image of page %d\n", i->pageNo);
+ fflush(stderr);
+ }
#if defined(DEBUGGING)
} else {
- fprintf(stderr, "ignoring image as x1 coord is -1\n");
- fflush(stderr);
+ if (debug) {
+ fprintf(stderr, "ignoring image as x1 coord is -1\n");
+ fflush(stderr);
+ }
#endif
}
}
@@ -998,7 +939,20 @@ void imageList::add (int x1, int y1, int x2, int y2, int page, int res, int maxx
tail->next = i;
tail = i;
}
- createImage(i);
+}
+
+/*
+ * createImages - foreach image descriptor on the imageList, create the actual image.
+ */
+
+void imageList::createImages (void)
+{
+ imageItem *h = head;
+
+ while (h != NULL) {
+ createImage(h);
+ h = h->next;
+ }
}
static imageList listOfImages; // list of images defined by the region file.
@@ -1011,31 +965,12 @@ static imageList listOfImages; // list of images defined by the region file.
void char_buffer::write_file_html (void)
{
- char_block *t =head;
+ char_block *t=head;
int i=0;
if (t != NULL) {
- stop();
do {
- /*
- * remember to check the shortest string last
- */
- if (can_see(&t, &i, HTML_IMAGE_END)) {
- write_end_image(TRUE);
- skip_to_newline(&t, &i);
- } else if (can_see(&t, &i, HTML_IMAGE_LEFT)) {
- write_start_image(LEFT, TRUE);
- skip_to_newline(&t, &i);
- } else if (can_see(&t, &i, HTML_IMAGE_RIGHT)) {
- write_start_image(RIGHT, TRUE);
- skip_to_newline(&t, &i);
- } else if (can_see(&t, &i, HTML_IMAGE_CENTERED)) {
- stop();
- write_start_image(CENTERED, TRUE);
- skip_to_newline(&t, &i);
- } else {
- write_upto_newline(&t, &i, TRUE);
- }
+ write_upto_newline(&t, &i, TRUE);
} while (t != NULL);
}
if (close(stdoutfd) < 0)
@@ -1067,9 +1002,9 @@ static void generateImages (char *regionFileName)
int y1 = f->readInt();
int x2 = f->readInt();
int y2 = f->readInt();
- int maxx = max(f->readInt(), MAX_WIDTH*image_res);
+ int maxx = f->readInt();
char *name = f->readString();
- int res = POSTSCRIPTRES; // --fixme-- prefer (f->readInt()) providing that troff can discover the value
+ int res = postscriptRes;
listOfImages.add(x1, y1, x2, y2, page, res, maxx, name);
while ((f->putPB(f->getPB()) != '\n') &&
(f->putPB(f->getPB()) != eof)) {
@@ -1085,6 +1020,13 @@ static void generateImages (char *regionFileName)
fputc(f->getPB(), stderr);
}
}
+
+ listOfImages.createImages();
+ if (show_progress) {
+ fprintf(stderr, "done\n");
+ fflush(stderr);
+ }
+ delete f;
}
/*
@@ -1123,7 +1065,7 @@ static void waitForChild (PID_T pid)
PID_T waitpd;
int status;
- waitpd = wait(&status);
+ waitpd = WAIT(&status, pid, _WAIT_CHILD);
if (waitpd != pid)
sys_fatal("wait");
}
@@ -1132,7 +1074,7 @@ static void waitForChild (PID_T pid)
* alterDeviceTo - if toImage is set then the arg list is altered to include
* IMAGE_DEVICE and we invoke groff rather than troff.
* else
- * set -Thtml and troff
+ * set -Thtml and groff
*/
static void alterDeviceTo (int argc, char *argv[], int toImage)
@@ -1154,8 +1096,68 @@ static void alterDeviceTo (int argc, char *argv[], int toImage)
}
i++;
}
- argv[troff_arg] = troff_command; /* use troff */
+ argv[troff_arg] = "groff"; /* use groff -Z */
+ }
+}
+
+/*
+ * addZ - appends -Z onto the command list for groff.
+ */
+
+char **addZ (int argc, char *argv[])
+{
+ char **new_argv = (char **)malloc((argc+2)*sizeof(char *));
+ int i=0;
+
+ if (new_argv == NULL)
+ sys_fatal("malloc");
+
+ if (argc > 0) {
+ new_argv[i] = argv[i];
+ i++;
+ }
+ new_argv[i] = "-Z";
+ while (i<argc) {
+ new_argv[i+1] = argv[i];
+ i++;
}
+ argc++;
+ new_argv[argc] = NULL;
+ return new_argv;
+}
+
+/*
+ * addRegDef - appends a defined register or string onto the command list for troff.
+ */
+
+char **addRegDef (int argc, char *argv[], const char *numReg)
+{
+ char **new_argv = (char **)malloc((argc+2)*sizeof(char *));
+ int i=0;
+
+ if (new_argv == NULL)
+ sys_fatal("malloc");
+
+ while (i<argc) {
+ new_argv[i] = argv[i];
+ i++;
+ }
+ new_argv[argc] = strdup(numReg);
+ argc++;
+ new_argv[argc] = NULL;
+ return new_argv;
+}
+
+/*
+ * dump_args - display the argument list.
+ */
+
+void dump_args (int argc, char *argv[])
+{
+ fprintf(stderr, " %d arguments:", argc);
+ for (int i=0; i<argc; i++)
+ fprintf(stderr, " %s", argv[i]);
+ fprintf(stderr, "\n");
}
/*
@@ -1167,19 +1169,23 @@ int char_buffer::do_html(int argc, char *argv[])
{
int pdes[2];
PID_T pid;
-
- if (pipe(pdes) < 0)
- sys_fatal("pipe");
+ string s;
alterDeviceTo(argc, argv, 0);
- argv += troff_arg; // skip all arguments up to troff/groff
+ argv += troff_arg; // skip all arguments up to groff
argc -= troff_arg;
+ argv = addZ(argc, argv);
+ argc++;
+
+ s = "-dwww-image-template=";
+ s += macroset_template; // do not combine these statements otherwise they will not work
+ s += '\0'; // the trailing '\0' is ignored
+ argv = addRegDef(argc, argv, s.contents());
+ argc++;
+
+ if (pipe(pdes) < 0)
+ sys_fatal("pipe");
-#if defined(DEBUG_HTML)
- write_file_html();
- writeString("--------------- troff --------------------------\n");
- write_file_troff();
-#else
pid = fork();
if (pid < 0)
sys_fatal("fork");
@@ -1216,30 +1222,7 @@ int char_buffer::do_html(int argc, char *argv[])
write_file_html();
waitForChild(pid);
}
-#endif
- return( 0 );
-}
-
-/*
- * addps4html - appends -rps4html=1 onto the command list for troff.
- */
-
-char **addps4html (int argc, char *argv[])
-{
- char **new_argv = (char **)malloc((argc+2)*sizeof(char *));
- int i=0;
-
- if (new_argv == NULL)
- sys_fatal("malloc");
-
- while (i<argc) {
- new_argv[i] = argv[i];
- i++;
- }
- new_argv[argc] = "-rps4html=1";
- argc++;
- new_argv[argc] = NULL;
- return( new_argv );
+ return 0;
}
/*
@@ -1250,16 +1233,27 @@ int char_buffer::do_image(int argc, char *argv[])
{
PID_T pid;
int pdes[2];
-
- if (pipe(pdes) < 0)
- sys_fatal("pipe");
+ string s;
alterDeviceTo(argc, argv, 1);
argv += troff_arg; // skip all arguments up to troff/groff
argc -= troff_arg;
- argv = addps4html(argc, argv);
+ argv = addRegDef(argc, argv, "-rps4html=1");
+ argc++;
+
+ s = "-dwww-image-template=";
+ s += macroset_template;
+ s += '\0';
+ argv = addRegDef(argc, argv, s.contents());
+ argc++;
+
+ // override local settings and produce a page size letter postscript file
+ argv = addRegDef(argc, argv, "-P-pletter");
argc++;
+ if (pipe(pdes) < 0)
+ sys_fatal("pipe");
+
pid = fork();
if (pid == 0) {
// child
@@ -1295,7 +1289,7 @@ int char_buffer::do_image(int argc, char *argv[])
write_file_troff();
waitForChild(pid);
}
- return( 0 );
+ return 0;
}
static char_buffer inputFile;
@@ -1315,44 +1309,96 @@ void usage(FILE *stream)
}
/*
- * scanArguments - scans for -P-i, -P-o, -P-D and -P-I arguments.
+ * scanArguments - scans for all arguments including -P-i, -P-o, -P-D and -P-I. It returns
+ * the argument index of the first non option.
*/
int scanArguments (int argc, char **argv)
{
- int i=1;
-
- while (i<argc) {
- if (strncmp(argv[i], "-D", 2) == 0) {
- image_dir = (char *)(argv[i]+2);
- } else if (strncmp(argv[i], "-I", 2) == 0) {
- image_template = (char *)(argv[i]+2);
- } else if (strncmp(argv[i], "-i", 2) == 0) {
- image_res = atoi((char *)(argv[i]+2));
- } else if (strncmp(argv[i], "-o", 2) == 0) {
- vertical_offset = atoi((char *)(argv[i]+2));
- } else if ((strcmp(argv[i], "-v") == 0)
- || (strcmp(argv[i], "--version") == 0)) {
+ const char *command_prefix = getenv("GROFF_COMMAND_PREFIX");
+ if (!command_prefix)
+ command_prefix = PROG_PREFIX;
+ char *troff_name = new char[strlen(command_prefix) + strlen("troff") + 1];
+ strcpy(troff_name, command_prefix);
+ strcat(troff_name, "troff");
+ int c, i;
+ 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 pre-grohtml (groff) version %s\n", Version_string);
exit(0);
- } else if ((strcmp(argv[i], "-h") == 0)
- || (strcmp(argv[i], "--help") == 0)
- || (strcmp(argv[i], "-?") == 0)) {
- usage(stdout);
- exit(0);
- } else if (strcmp(argv[i], troff_command) == 0) {
- /* remember troff argument number */
- troff_arg = i;
+ case 'a':
+ textAlphaBits = min(max(MIN_ALPHA_BITS, atoi(optarg)), MAX_ALPHA_BITS);
+ if (textAlphaBits == 3) {
+ error("cannot use 3 bits of antialiasing information");
+ exit(1);
+ }
+ break;
+ case 'g':
+ graphicAlphaBits = min(max(MIN_ALPHA_BITS, atoi(optarg)), MAX_ALPHA_BITS);
+ if (graphicAlphaBits == 3) {
+ error("cannot use 3 bits of antialiasing information");
+ exit(1);
+ }
+ break;
+ case 'b':
+ // handled by post-grohtml (set background color to white)
+ break;
+ case 'D':
+ image_dir = optarg;
+ break;
+ case 'I':
+ image_template = optarg;
+ break;
+ case 'i':
+ image_res = atoi(optarg);
+ break;
+ case 'F':
+ font_path.command_line_dir(optarg);
+ break;
+ case 'o':
+ vertical_offset = atoi(optarg);
+ break;
+ case 'p':
+ show_progress = TRUE;
+ break;
+ case 'd':
#if defined(DEBUGGING)
- } else if (strcmp(argv[i], "-d") == 0) {
debug = TRUE;
#endif
- } else if (argv[i][0] != '-') {
- return( i );
+ break;
+ case 'h':
+ // handled by post-grohtml
+ break;
+ case CHAR_MAX + 1: // --help
+ usage(stdout);
+ exit(0);
+ break;
+ case '?':
+ usage(stderr);
+ exit(1);
+ break;
+ default:
+ break;
}
+
+ i = optind;
+ while (i < argc) {
+ if (strcmp(argv[i], troff_name) == 0)
+ troff_arg = i;
+ else if (argv[i][0] != '-')
+ return i;
i++;
}
- return( argc );
+ a_delete troff_name;
+
+ return argc;
}
/*
@@ -1364,58 +1410,57 @@ static int makeTempFiles (void)
#if defined(DEBUGGING)
psFileName = "/tmp/prehtml-ps";
regionFileName = "/tmp/prehtml-region";
- imagePageStem = "/tmp/prehtml-page";
+ imagePageName = "/tmp/prehtml-page";
+ psPageName = "/tmp/prehtml-psn";
troffFileName = "/tmp/prehtml-troff";
htmlFileName = "/tmp/prehtml-html";
#else
- int fd;
-
- if ((fd = mkstemp(psFileName = xtmptemplate(PS_TEMPLATE))) == -1) {
- sys_fatal("mkstemp");
+ FILE *f;
+
+ /* psPageName contains a single page of postscript */
+ f = xtmpfile(&psPageName,
+ PS_TEMPLATE_LONG, PS_TEMPLATE_SHORT,
+ TRUE);
+ if (f == NULL) {
+ sys_fatal("xtmpfile");
return -1;
}
- close(fd);
- if ((fd = mkstemp(regionFileName = xtmptemplate(REGION_TEMPLATE))) == -1) {
- sys_fatal("mkstemp");
- unlink(psFileName);
+ fclose(f);
+
+ /* imagePageName contains a bitmap image of the single postscript page */
+ f = xtmpfile(&imagePageName,
+ PAGE_TEMPLATE_LONG, PAGE_TEMPLATE_SHORT,
+ TRUE);
+ if (f == NULL) {
+ sys_fatal("xtmpfile");
return -1;
}
- close(fd);
-#endif
- return 0;
-}
-
-/*
- * removeTempFiles - remove the temporary files
- */
+ fclose(f);
+
+ /* psFileName contains a postscript file of the complete document */
+ f = xtmpfile(&psFileName,
+ PS_TEMPLATE_LONG, PS_TEMPLATE_SHORT,
+ TRUE);
+ if (f == NULL) {
+ sys_fatal("xtmpfile");
+ return -1;
+ }
+ fclose(f);
+
+ /* regionFileName contains a list of the images and their boxed coordinates */
+ f = xtmpfile(&regionFileName,
+ REGION_TEMPLATE_LONG, REGION_TEMPLATE_SHORT,
+ TRUE);
+ if (f == NULL) {
+ sys_fatal("xtmpfile");
+ return -1;
+ }
+ fclose(f);
-static void removeTempFiles (void)
-{
-#if !defined(DEBUGGING)
- unlink(psFileName);
- unlink(regionFileName);
#endif
+ return 0;
}
-/*
- * findPrefix - finds the optional prefix to the groff utilities.
- * It also builds the 'troff' executable name.
- */
-
-static void findPrefix (void)
-{
- command_prefix = getenv("GROFF_COMMAND_PREFIX");
- if (!command_prefix)
- command_prefix = PROG_PREFIX;
- troff_command = (char *)malloc(strlen("troff")+strlen(command_prefix)+1);
- if (troff_command == NULL)
- sys_fatal("malloc");
-
- strcpy(troff_command, command_prefix);
- strcat(troff_command, "troff");
-}
-
-
int main(int argc, char **argv)
{
program_name = argv[0];
@@ -1423,8 +1468,9 @@ int main(int argc, char **argv)
int found=0;
int ok=1;
- findPrefix();
+ postscriptRes = get_resolution();
i = scanArguments(argc, argv);
+ setupAntiAlias();
checkImageDir();
makeFileName();
while (i < argc) {
@@ -1448,14 +1494,9 @@ int main(int argc, char **argv)
return 1;
ok = inputFile.do_image(argc, argv);
if (ok == 0) {
- ok = createAllPages();
- if (ok == 0) {
- generateImages(regionFileName);
- ok = inputFile.do_html(argc, argv);
- removeAllPages();
- }
+ generateImages(regionFileName);
+ ok = inputFile.do_html(argc, argv);
}
- removeTempFiles();
return ok;
}
diff --git a/contrib/groff/src/preproc/html/pushback.cc b/contrib/groff/src/preproc/html/pushback.cc
new file mode 100644
index 0000000..d18c5e2
--- /dev/null
+++ b/contrib/groff/src/preproc/html/pushback.cc
@@ -0,0 +1,333 @@
+// -*- C++ -*-
+/* Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+ Written by Gaius Mulley (gaius@glam.ac.uk).
+
+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 "lib.h"
+
+#include <signal.h>
+#include <ctype.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <errno.h>
+#include "errarg.h"
+#include "error.h"
+#include "stringclass.h"
+#include "posix.h"
+#include "nonposix.h"
+
+#include <errno.h>
+#include <sys/types.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "pushback.h"
+#include "pre-html.h"
+
+#if !defined(TRUE)
+# define TRUE (1==1)
+#endif
+
+#if !defined(FALSE)
+# define FALSE (1==0)
+#endif
+
+# define ERROR(X) (void)(fprintf(stderr, "%s:%d error %s\n", __FILE__, __LINE__, X) && \
+ (fflush(stderr)) && localexit(1))
+
+
+#define MAXPUSHBACKSTACK 4096 /* maximum number of character that can be pushed back */
+
+
+/*
+ * constructor for pushBackBuffer
+ */
+
+pushBackBuffer::pushBackBuffer (char *filename)
+{
+ charStack = (char *)malloc(MAXPUSHBACKSTACK);
+ if (charStack == 0) {
+ sys_fatal("malloc");
+ }
+ stackPtr = 0; /* index to push back stack */
+ debug = 0;
+ verbose = 0;
+ eofFound = FALSE;
+ lineNo = 1;
+ if (strcmp(filename, "") != 0) {
+ stdIn = dup(0);
+ close(0);
+ if (open(filename, O_RDONLY) != 0) {
+ sys_fatal("when trying to open file");
+ } else {
+ fileName = filename;
+ }
+ }
+}
+
+pushBackBuffer::~pushBackBuffer ()
+{
+ int old;
+
+ if (charStack != 0) {
+ free(charStack);
+ }
+ close(0);
+ /* restore stdin in file descriptor 0 */
+ old = dup(stdIn);
+ close(stdIn);
+}
+
+/*
+ * localexit - wraps exit with a return code to aid the ERROR macro.
+ */
+
+int localexit (int i)
+{
+ exit(i);
+ return( 1 );
+}
+
+/*
+ * getPB - returns a character, possibly a pushed back character.
+ */
+
+char pushBackBuffer::getPB (void)
+{
+ if (stackPtr>0) {
+ stackPtr--;
+ return( charStack[stackPtr] );
+ } else {
+ char ch;
+
+ if (read(0, &ch, 1) == 1) {
+ if (verbose) {
+ printf("%c", ch);
+ }
+ if (ch == '\n') {
+ lineNo++;
+ }
+ return( ch );
+ } else {
+ eofFound = TRUE;
+ return( eof );
+ }
+ }
+}
+
+/*
+ * putPB - pushes a character onto the push back stack.
+ * The same character is returned.
+ */
+
+char pushBackBuffer::putPB (char ch)
+{
+ if (stackPtr<MAXPUSHBACKSTACK) {
+ charStack[stackPtr] = ch ;
+ stackPtr++;
+ } else {
+ ERROR("max push back stack exceeded, increase MAXPUSHBACKSTACK constant");
+ }
+ return( ch );
+}
+
+/*
+ * isWhite - returns TRUE if a white character is found. This character is NOT consumed.
+ */
+
+static int isWhite (char ch)
+{
+ return( (ch==' ') || (ch == '\t') || (ch == '\n') );
+}
+
+/*
+ * skipToNewline - skips characters until a newline is seen.
+ */
+
+void pushBackBuffer::skipToNewline (void)
+{
+ char ch;
+
+ while ((putPB(getPB()) != '\n') && (! eofFound)) {
+ ch = getPB();
+ }
+}
+
+/*
+ * skipUntilToken - skips until a token is seen
+ */
+
+void pushBackBuffer::skipUntilToken (void)
+{
+ char ch;
+
+ while ((isWhite(putPB(getPB())) || (putPB(getPB()) == '#')) && (! eofFound)) {
+ ch = getPB();
+ if (ch == '#') {
+ skipToNewline();
+ }
+ }
+}
+
+/*
+ * isString - returns TRUE if the string, s, matches the pushed back string.
+ * if TRUE is returned then this string is consumed, otherwise it is
+ * left alone.
+ */
+
+int pushBackBuffer::isString (char *s)
+{
+ int length=strlen(s);
+ int i=0;
+
+ while ((i<length) && (putPB(getPB())==s[i])) {
+ if (getPB() != s[i]) {
+ ERROR("assert failed");
+ }
+ i++;
+ }
+ if (i==length) {
+ return( TRUE );
+ } else {
+ i--;
+ while (i>=0) {
+ if (putPB(s[i]) != s[i]) {
+ ERROR("assert failed");
+ }
+ i--;
+ }
+ }
+ return( FALSE );
+}
+
+/*
+ * isDigit - returns TRUE if the character, ch, is a digit.
+ */
+
+static int isDigit (char ch)
+{
+ return( ((ch>='0') && (ch<='9')) );
+}
+
+/*
+ * isHexDigit - returns TRUE if the character, ch, is a hex digit.
+ */
+
+#if 0
+static int isHexDigit (char ch)
+{
+ return( (isDigit(ch)) || ((ch>='a') && (ch<='f')) );
+}
+#endif
+
+/*
+ * readInt - returns an integer from the input stream.
+ */
+
+int pushBackBuffer::readInt (void)
+{
+ int c =0;
+ int i =0;
+ int s =1;
+ char ch=getPB();
+
+ while (isWhite(ch)) {
+ ch=getPB();
+ }
+ // now read integer
+
+ if (ch == '-') {
+ s = -1;
+ ch = getPB();
+ }
+ while (isDigit(ch)) {
+ i *= 10;
+ if ((ch>='0') && (ch<='9')) {
+ i += (int)(ch-'0');
+ }
+ ch = getPB();
+ c++;
+ }
+ if (ch != putPB(ch)) {
+ ERROR("assert failed");
+ }
+ return( i*s );
+}
+
+/*
+ * convertToFloat - converts integers, a and b into a.b
+ */
+
+static float convertToFloat (int a, int b)
+{
+ int c=10;
+ float f;
+
+ while (b>c) {
+ c *= 10;
+ }
+ f = ((float)a) + (((float)b)/((float)c));
+ return( f );
+}
+
+/*
+ * readNumber - returns a float representing the word just read.
+ */
+
+float pushBackBuffer::readNumber (void)
+{
+ int i;
+ char ch;
+
+ i = readInt();
+ if ((ch = getPB()) == '.') {
+ return convertToFloat(i, readInt());
+ }
+ putPB(ch);
+ return (float)i;
+}
+
+/*
+ * readString - reads a string terminated by white space
+ * and returns a malloced area of memory containing
+ * a copy of the characters.
+ */
+
+char *pushBackBuffer::readString (void)
+{
+ char buffer[MAXPUSHBACKSTACK];
+ char *string = 0;
+ int i=0;
+ char ch=getPB();
+
+ while (isWhite(ch)) {
+ ch=getPB();
+ }
+ while ((i < MAXPUSHBACKSTACK) && (! isWhite(ch)) && (! eofFound)) {
+ buffer[i] = ch;
+ i++;
+ ch = getPB();
+ }
+ if (i < MAXPUSHBACKSTACK) {
+ buffer[i] = (char)0;
+ string = (char *)malloc(strlen(buffer)+1);
+ strcpy(string, buffer);
+ }
+ return( string );
+}
diff --git a/contrib/groff/src/preproc/html/pushback.h b/contrib/groff/src/preproc/html/pushback.h
new file mode 100644
index 0000000..93cb3f1
--- /dev/null
+++ b/contrib/groff/src/preproc/html/pushback.h
@@ -0,0 +1,54 @@
+// -*- C -*-
+/* Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+ Written by Gaius Mulley (gaius@glam.ac.uk).
+
+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. */
+
+
+#define eof (char)-1
+
+
+/*
+ * defines the class and methods implemented within pushbackbuffer.cc
+ */
+
+class pushBackBuffer
+{
+ private:
+ char *charStack;
+ int stackPtr; /* index to push back stack */
+ int debug;
+ int verbose;
+ int eofFound;
+ char *fileName;
+ int lineNo;
+ int stdIn;
+
+ public:
+ pushBackBuffer (char *);
+ ~ pushBackBuffer ();
+ char getPB (void);
+ char putPB (char ch);
+ void skipUntilToken (void);
+ void skipToNewline (void);
+ float readNumber (void);
+ int readInt (void);
+ char *readString (void);
+ int isString (char *string);
+};
+
+
diff --git a/contrib/groff/src/preproc/pic/Makefile.sub b/contrib/groff/src/preproc/pic/Makefile.sub
index f1e2927..05c47a1 100644
--- a/contrib/groff/src/preproc/pic/Makefile.sub
+++ b/contrib/groff/src/preproc/pic/Makefile.sub
@@ -1,16 +1,16 @@
-PROG=pic
+PROG=pic$(EXEEXT)
MAN1=pic.n
XLIBS=$(LIBGROFF)
MLIB=$(LIBM)
OBJS=\
- pic.o \
- lex.o \
- main.o \
- object.o \
- common.o \
- troff.o \
- tex.o
- # fig.o
+ pic.$(OBJEXT) \
+ lex.$(OBJEXT) \
+ main.$(OBJEXT) \
+ object.$(OBJEXT) \
+ common.$(OBJEXT) \
+ troff.$(OBJEXT) \
+ tex.$(OBJEXT)
+ # fig.$(OBJEXT)
CCSRCS=\
$(srcdir)/lex.cc \
$(srcdir)/main.cc \
@@ -26,6 +26,6 @@ HDRS=\
$(srcdir)/position.h \
$(srcdir)/text.h
GRAM=$(srcdir)/pic.y
-YTABC=$(srcdir)/pic.cc
-YTABH=$(srcdir)/pic_tab.h
+YTABC=pic.cc
+YTABH=pic_tab.h
NAMEPREFIX=$(g)
diff --git a/contrib/groff/src/preproc/pic/common.cc b/contrib/groff/src/preproc/pic/common.cc
index e83ef31..5075e93 100644
--- a/contrib/groff/src/preproc/pic/common.cc
+++ b/contrib/groff/src/preproc/pic/common.cc
@@ -437,7 +437,6 @@ void common_output::dot_line(const position &start, const position &end,
}
}
-
void common_output::solid_rounded_box(const position &cent,
const distance &dim, double rad,
const line_type &lt)
diff --git a/contrib/groff/src/preproc/pic/common.h b/contrib/groff/src/preproc/pic/common.h
index 25a6e10..90b65fa 100644
--- a/contrib/groff/src/preproc/pic/common.h
+++ b/contrib/groff/src/preproc/pic/common.h
@@ -63,6 +63,10 @@ public:
const line_type &, double) = 0;
void rounded_box(const position &, const distance &, double,
const line_type &, double);
+ void set_color(char *, char *) = 0;
+ void reset_color() = 0;
+ char *get_last_filled() = 0;
+ char *get_outline_color() = 0;
};
int compute_arc_center(const position &start, const position &cent,
diff --git a/contrib/groff/src/preproc/pic/lex.cc b/contrib/groff/src/preproc/pic/lex.cc
index 5b6d439..14a4cc3 100644
--- a/contrib/groff/src/preproc/pic/lex.cc
+++ b/contrib/groff/src/preproc/pic/lex.cc
@@ -1,5 +1,6 @@
// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992, 2000 Free Software Foundation, Inc.
+/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2002
+ Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
This file is part of groff.
@@ -83,8 +84,8 @@ int file_input::read_line()
int c = getc(fp);
if (c == EOF)
break;
- else if (illegal_input_char(c))
- lex_error("illegal input character code %1", c);
+ else if (invalid_input_char(c))
+ lex_error("invalid input character code %1", c);
else {
line += char(c);
if (c == '\n')
@@ -153,7 +154,7 @@ int macro_input::peek()
return (unsigned char)*p;
}
-// Character representing $1. Must be illegal input character.
+// Character representing $1. Must be invalid input character.
#define ARG1 14
char *process_body(const char *body)
@@ -446,6 +447,10 @@ int lookup_keyword(const char *str, int len)
{ "center", CENTER },
{ "chop", CHOP },
{ "circle", CIRCLE },
+ { "color", COLORED },
+ { "colored", COLORED },
+ { "colour", COLORED },
+ { "coloured", COLORED },
{ "command", COMMAND },
{ "copy", COPY },
{ "cos", COS },
@@ -457,6 +462,7 @@ int lookup_keyword(const char *str, int len)
{ "do", DO },
{ "dotted", DOTTED },
{ "down", DOWN },
+ { "east", EAST },
{ "ellipse", ELLIPSE },
{ "else", ELSE },
{ "end", END },
@@ -480,7 +486,10 @@ int lookup_keyword(const char *str, int len)
{ "max", K_MAX },
{ "min", K_MIN },
{ "move", MOVE },
+ { "north", NORTH },
{ "of", OF },
+ { "outline", OUTLINED },
+ { "outlined", OUTLINED },
{ "plot", PLOT },
{ "print", PRINT },
{ "rad", RADIUS },
@@ -491,8 +500,10 @@ int lookup_keyword(const char *str, int len)
{ "rjust", RJUST },
{ "same", SAME },
{ "sh", SH },
+ { "shaded", SHADED },
{ "sin", SIN },
{ "solid", SOLID },
+ { "south", SOUTH },
{ "spline", SPLINE },
{ "sprintf", SPRINTF },
{ "sqrt", SQRT },
@@ -510,6 +521,7 @@ int lookup_keyword(const char *str, int len)
{ "up", UP },
{ "upper", UPPER },
{ "way", WAY },
+ { "west", WEST },
{ "wid", WIDTH },
{ "width", WIDTH },
{ "with", WITH },
@@ -953,7 +965,7 @@ int get_token(int lookup_flag)
double factor = 1.0;
for (;;) {
c = input_stack::peek_char();
- if (!c == EOF || !csdigit(c))
+ if (c == EOF || !csdigit(c))
break;
input_stack::get_char();
context_buffer += char(c);
@@ -1618,8 +1630,8 @@ simple_file_input::~simple_file_input()
int simple_file_input::get()
{
int c = getc(fp);
- while (illegal_input_char(c)) {
- error("illegal input character code %1", c);
+ while (invalid_input_char(c)) {
+ error("invalid input character code %1", c);
c = getc(fp);
}
if (c == '\n')
@@ -1630,8 +1642,8 @@ int simple_file_input::get()
int simple_file_input::peek()
{
int c = getc(fp);
- while (illegal_input_char(c)) {
- error("illegal input character code %1", c);
+ while (invalid_input_char(c)) {
+ error("invalid input character code %1", c);
c = getc(fp);
}
if (c != EOF)
@@ -1816,6 +1828,46 @@ int yylex()
}
else
return t;
+ case NORTH:
+ // recognise NORTH only before OF
+ old_context_buffer = context_buffer;
+ lookahead_token = get_token(1);
+ if (lookahead_token != OF) {
+ yylval.str = strsave("north");
+ return VARIABLE;
+ }
+ else
+ return t;
+ case SOUTH:
+ // recognise SOUTH only before OF
+ old_context_buffer = context_buffer;
+ lookahead_token = get_token(1);
+ if (lookahead_token != OF) {
+ yylval.str = strsave("south");
+ return VARIABLE;
+ }
+ else
+ return t;
+ case EAST:
+ // recognise EAST only before OF
+ old_context_buffer = context_buffer;
+ lookahead_token = get_token(1);
+ if (lookahead_token != OF) {
+ yylval.str = strsave("east");
+ return VARIABLE;
+ }
+ else
+ return t;
+ case WEST:
+ // recognise WEST only before OF
+ old_context_buffer = context_buffer;
+ lookahead_token = get_token(1);
+ if (lookahead_token != OF) {
+ yylval.str = strsave("west");
+ return VARIABLE;
+ }
+ else
+ return t;
case TOP:
// recognise TOP only before OF
old_context_buffer = context_buffer;
diff --git a/contrib/groff/src/preproc/pic/main.cc b/contrib/groff/src/preproc/pic/main.cc
index b795d48..124cbd5 100644
--- a/contrib/groff/src/preproc/pic/main.cc
+++ b/contrib/groff/src/preproc/pic/main.cc
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 1989-1992, 2000, 2001 Free Software Foundation, Inc.
+/* Copyright (C) 1989-1992, 2000, 2001, 2002 Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
This file is part of groff.
@@ -80,8 +80,8 @@ int top_input::get()
return c;
}
int c = getc(fp);
- while (illegal_input_char(c)) {
- error("illegal input character code %1", int(c));
+ while (invalid_input_char(c)) {
+ error("invalid input character code %1", int(c));
c = getc(fp);
bol = 0;
}
@@ -152,8 +152,8 @@ int top_input::peek()
if (push_back[0] != EOF)
return push_back[0];
int c = getc(fp);
- while (illegal_input_char(c)) {
- error("illegal input character code %1", int(c));
+ while (invalid_input_char(c)) {
+ error("invalid input character code %1", int(c));
c = getc(fp);
bol = 0;
}
@@ -476,7 +476,7 @@ void usage(FILE *stream)
#endif
}
-#ifdef __MSDOS__
+#if defined(__MSDOS__) || defined(__EMX__)
static char *fix_program_name(char *arg, char *dflt)
{
if (!arg)
@@ -499,13 +499,13 @@ static char *fix_program_name(char *arg, char *dflt)
*p = 'a' + (*p - 'A');
return prog;
}
-#endif /* __MSDOS__ */
+#endif /* __MSDOS__ || __EMX__ */
int main(int argc, char **argv)
{
-#ifdef __MSDOS__
+#if defined(__MSDOS__) || defined(__EMX__)
argv[0] = fix_program_name(argv[0], "pic");
-#endif /* __MSDOS__ */
+#endif /* __MSDOS__ || __EMX__ */
program_name = argv[0];
static char stderr_buf[BUFSIZ];
setbuf(stderr, stderr_buf);
diff --git a/contrib/groff/src/preproc/pic/object.cc b/contrib/groff/src/preproc/pic/object.cc
index 6b34633..fd25371 100644
--- a/contrib/groff/src/preproc/pic/object.cc
+++ b/contrib/groff/src/preproc/pic/object.cc
@@ -1,5 +1,6 @@
// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+/* Copyright (C) 1989, 1990, 1991, 1992, 2001, 2002
+ Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
This file is part of groff.
@@ -53,14 +54,6 @@ void output::set_args(const char *s)
args = strsave(s);
}
-void output::command(const char *, const char *, int)
-{
-}
-
-void output::set_location(const char *, int)
-{
-}
-
int output::supports_filled_polygons()
{
return 0;
@@ -219,7 +212,8 @@ struct arrow_head_type {
};
void draw_arrow(const position &pos, const distance &dir,
- const arrow_head_type &aht, const line_type &lt)
+ const arrow_head_type &aht, const line_type &lt,
+ char *outline_color_for_fill)
{
double hyp = hypot(dir);
if (hyp == 0.0) {
@@ -237,8 +231,9 @@ void draw_arrow(const position &pos, const distance &dir,
v[0] = pos;
v[1] = pos + base + n;
v[2] = pos + base - n;
- // A value > 1 means fill with the current color.
- out->polygon(v, 3, slt, 2.0);
+ // fill with outline color
+ out->set_color(outline_color_for_fill, outline_color_for_fill);
+ out->polygon(v, 3, slt, 1);
}
else {
position v[2];
@@ -549,6 +544,8 @@ class graphic_object : public object {
int aligned;
protected:
line_type lt;
+ char *outline_color;
+ char *color_fill;
public:
graphic_object();
~graphic_object();
@@ -559,10 +556,14 @@ public:
void set_dashed(double);
void set_thickness(double);
void set_invisible();
+ void set_outline_color(char *);
+ char *get_outline_color();
virtual void set_fill(double);
+ virtual void set_fill_color(char *);
};
-graphic_object::graphic_object() : ntext(0), text(0), aligned(0)
+graphic_object::graphic_object()
+: ntext(0), text(0), aligned(0), outline_color(0), color_fill(0)
{
}
@@ -587,6 +588,21 @@ void graphic_object::set_fill(double)
{
}
+void graphic_object::set_fill_color(char *c)
+{
+ color_fill = c;
+}
+
+void graphic_object::set_outline_color(char *c)
+{
+ outline_color = c;
+}
+
+char *graphic_object::get_outline_color()
+{
+ return outline_color;
+}
+
void graphic_object::set_invisible()
{
lt.type = line_type::invisible;
@@ -622,8 +638,11 @@ void graphic_object::print_text()
if (d.x != 0.0 || d.y != 0.0)
angle = atan2(d.y, d.x);
}
- if (text != 0)
+ if (text != 0) {
+ out->set_color(color_fill, get_outline_color());
out->text(center(), text, ntext, angle);
+ out->reset_color();
+ }
}
graphic_object::~graphic_object()
@@ -676,12 +695,14 @@ public:
closed_object(const position &);
object_type type() = 0;
void set_fill(double);
+ void set_fill_color(char *fill);
protected:
double fill; // < 0 if not filled
+ char *color_fill; // = 0 if not colored
};
closed_object::closed_object(const position &pos)
-: rectangle_object(pos), fill(-1.0)
+: rectangle_object(pos), fill(-1.0), color_fill(0)
{
}
@@ -691,6 +712,10 @@ void closed_object::set_fill(double f)
fill = f;
}
+void closed_object::set_fill_color(char *fill)
+{
+ color_fill = fill;
+}
class box_object : public closed_object {
double xrad;
@@ -738,8 +763,9 @@ position box_object::south_west()
void box_object::print()
{
- if (lt.type == line_type::invisible && fill < 0.0)
+ if (lt.type == line_type::invisible && fill < 0.0 && color_fill == 0)
return;
+ out->set_color(color_fill, graphic_object::get_outline_color());
if (xrad == 0.0) {
distance dim2 = dim/2.0;
position vec[4];
@@ -753,6 +779,7 @@ void box_object::print()
distance abs_dim(fabs(dim.x), fabs(dim.y));
out->rounded_box(cent, abs_dim, fabs(xrad), lt, fill);
}
+ out->reset_color();
}
graphic_object *object_spec::make_box(position *curpos, direction *dirp)
@@ -990,9 +1017,11 @@ ellipse_object::ellipse_object(const position &d)
void ellipse_object::print()
{
- if (lt.type == line_type::invisible && fill < 0.0)
+ if (lt.type == line_type::invisible && fill < 0.0 && color_fill == 0)
return;
+ out->set_color(color_fill, graphic_object::get_outline_color());
out->ellipse(cent, dim, lt, fill);
+ out->reset_color();
}
graphic_object *object_spec::make_ellipse(position *curpos, direction *dirp)
@@ -1037,9 +1066,11 @@ circle_object::circle_object(double diam)
void circle_object::print()
{
- if (lt.type == line_type::invisible && fill < 0.0)
+ if (lt.type == line_type::invisible && fill < 0.0 && color_fill == 0)
return;
+ out->set_color(color_fill, graphic_object::get_outline_color());
out->circle(cent, dim.x/2.0, lt, fill);
+ out->reset_color();
}
graphic_object *object_spec::make_circle(position *curpos, direction *dirp)
@@ -1098,7 +1129,7 @@ graphic_object *object_spec::make_move(position *curpos, direction *dirp)
// No need to look at at since `at' attribute sets `from' attribute.
position startpos = (flags & HAS_FROM) ? from : *curpos;
if (!(flags & HAS_SEGMENT)) {
- if ((flags && IS_SAME) && have_last_move)
+ if ((flags & IS_SAME) && have_last_move)
segment_pos = last_move;
else {
switch (dir) {
@@ -1222,11 +1253,14 @@ void line_object::print()
{
if (lt.type == line_type::invisible)
return;
+ out->set_color(0, graphic_object::get_outline_color());
out->line(strt, v, n, lt);
if (arrow_at_start)
- draw_arrow(strt, strt-v[0], aht, lt);
+ draw_arrow(strt, strt-v[0], aht, lt, graphic_object::get_outline_color());
if (arrow_at_end)
- draw_arrow(en, v[n-1] - (n > 1 ? v[n - 2] : strt), aht, lt);
+ draw_arrow(en, v[n-1] - (n > 1 ? v[n - 2] : strt), aht, lt,
+ graphic_object::get_outline_color());
+ out->reset_color();
}
void line_object::update_bounding_box(bounding_box *p)
@@ -1289,11 +1323,14 @@ void spline_object::print()
{
if (lt.type == line_type::invisible)
return;
+ out->set_color(0, graphic_object::get_outline_color());
out->spline(strt, v, n, lt);
if (arrow_at_start)
- draw_arrow(strt, strt-v[0], aht, lt);
+ draw_arrow(strt, strt-v[0], aht, lt, graphic_object::get_outline_color());
if (arrow_at_end)
- draw_arrow(en, v[n-1] - (n > 1 ? v[n - 2] : strt), aht, lt);
+ draw_arrow(en, v[n-1] - (n > 1 ? v[n - 2] : strt), aht, lt,
+ graphic_object::get_outline_color());
+ out->reset_color();
}
line_object::~line_object()
@@ -1500,6 +1537,7 @@ void arc_object::print()
{
if (lt.type == line_type::invisible)
return;
+ out->set_color(0, graphic_object::get_outline_color());
if (clockwise)
out->arc(en, cent, strt, lt);
else
@@ -1508,14 +1546,15 @@ void arc_object::print()
position c = cent - strt;
draw_arrow(strt,
(clockwise ? position(c.y, -c.x) : position(-c.y, c.x)),
- aht, lt);
+ aht, lt, graphic_object::get_outline_color());
}
if (arrow_at_end) {
position e = en - cent;
draw_arrow(en,
(clockwise ? position(e.y, -e.x) : position(-e.y, e.x)),
- aht, lt);
+ aht, lt, graphic_object::get_outline_color());
}
+ out->reset_color();
}
inline double max(double a, double b)
@@ -1708,13 +1747,19 @@ object *object_spec::make_object(position *curpos, direction *dirp)
else
lookup_variable("linethick", &th);
obj->set_thickness(th);
+ if (flags & IS_OUTLINED)
+ obj->set_outline_color(outlined);
if (flags & (IS_DEFAULT_FILLED|IS_FILLED)) {
- if (flags & IS_DEFAULT_FILLED)
- lookup_variable("fillval", &fill);
- if (fill < 0.0)
- error("bad fill value %1", fill);
- else
- obj->set_fill(fill);
+ if (flags & IS_SHADED)
+ obj->set_fill_color(shaded);
+ else {
+ if (flags & IS_DEFAULT_FILLED)
+ lookup_variable("fillval", &fill);
+ if (fill < 0.0)
+ error("bad fill value %1", fill);
+ else
+ obj->set_fill(fill);
+ }
}
}
return obj;
@@ -1737,18 +1782,28 @@ string_list::~string_list()
a_delete str;
}
-/* A path is used to hold the argument to the with attribute. For example,
-`.nw' or `.A.s' or `.A'. The major operation on a path is to take a
-place and follow the path through the place to place within the place.
-Note that `.A.B.C.sw' will work. */
+/* A path is used to hold the argument to the `with' attribute. For
+ example, `.nw' or `.A.s' or `.A'. The major operation on a path is to
+ take a place and follow the path through the place to place within the
+ place. Note that `.A.B.C.sw' will work.
+
+ For compatibility with DWB pic, `with' accepts positions also (this
+ is incorrectly documented in CSTR 116). */
path::path(corner c)
-: crn(c), label_list(0), ypath(0)
+: crn(c), label_list(0), ypath(0), is_position(0)
{
}
+path::path(position p)
+: crn(0), label_list(0), ypath(0), is_position(1)
+{
+ pos.x = p.x;
+ pos.y = p.y;
+}
+
path::path(char *l, corner c)
-: crn(c), ypath(0)
+: crn(c), ypath(0), is_position(0)
{
label_list = new string_list(l);
}
@@ -1786,6 +1841,12 @@ void path::set_ypath(path *p)
int path::follow(const place &pl, place *result) const
{
+ if (is_position) {
+ result->x = pos.x;
+ result->y = pos.y;
+ result->obj = 0;
+ return 1;
+ }
const place *p = &pl;
for (string_list *lb = label_list; lb; lb = lb->next)
if (p->obj == 0 || (p = p->obj->find_label(lb->str)) == 0) {
@@ -1795,9 +1856,9 @@ int path::follow(const place &pl, place *result) const
if (crn == 0 || p->obj == 0)
*result = *p;
else {
- position pos = ((p->obj)->*(crn))();
- result->x = pos.x;
- result->y = pos.y;
+ position ps = ((p->obj)->*(crn))();
+ result->x = ps.x;
+ result->y = ps.y;
result->obj = 0;
}
if (ypath) {
diff --git a/contrib/groff/src/preproc/pic/object.h b/contrib/groff/src/preproc/pic/object.h
index 2748e81..98937f93 100644
--- a/contrib/groff/src/preproc/pic/object.h
+++ b/contrib/groff/src/preproc/pic/object.h
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+/* Copyright (C) 1989, 1990, 1991, 1992, 2002 Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
This file is part of groff.
@@ -76,11 +76,14 @@ struct place {
struct string_list;
class path {
+ position pos;
corner crn;
string_list *label_list;
path *ypath;
+ int is_position;
public:
path(corner = 0);
+ path(position);
path(char *, corner = 0);
~path();
void append(corner);
@@ -150,6 +153,8 @@ const unsigned long HAS_THICKNESS = 01000000;
const unsigned long IS_FILLED = 02000000;
const unsigned long IS_DEFAULT_FILLED = 04000000;
const unsigned long IS_ALIGNED = 010000000;
+const unsigned long IS_SHADED = 020000000;
+const unsigned long IS_OUTLINED = 040000000;
struct segment {
int is_absolute;
@@ -183,6 +188,8 @@ struct object_spec {
double end_chop;
double thickness;
double fill;
+ char *shaded;
+ char *outlined;
direction dir;
segment *segment_list;
position segment_pos;
diff --git a/contrib/groff/src/preproc/pic/output.h b/contrib/groff/src/preproc/pic/output.h
index ac490db..a0a8331 100644
--- a/contrib/groff/src/preproc/pic/output.h
+++ b/contrib/groff/src/preproc/pic/output.h
@@ -55,8 +55,12 @@ public:
const line_type &, double) = 0;
virtual void rounded_box(const position &, const distance &, double,
const line_type &, double) = 0;
- virtual void command(const char *, const char *, int);
- virtual void set_location(const char *, int);
+ virtual void command(const char *, const char *, int) = 0;
+ virtual void set_location(const char *, int) {}
+ virtual void set_color(char *, char *) = 0;
+ virtual void reset_color() = 0;
+ virtual char *get_last_filled() = 0;
+ virtual char *get_outline_color() = 0;
virtual int supports_filled_polygons();
virtual void begin_block(const position &ll, const position &ur);
virtual void end_block();
diff --git a/contrib/groff/src/preproc/pic/pic.h b/contrib/groff/src/preproc/pic/pic.h
index 36c36d1..0a092fe 100644
--- a/contrib/groff/src/preproc/pic/pic.h
+++ b/contrib/groff/src/preproc/pic/pic.h
@@ -1,5 +1,6 @@
// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992, 2000 Free Software Foundation, Inc.
+/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001
+ Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
This file is part of groff.
@@ -18,8 +19,8 @@ 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 <stdio.h>
-#include <string.h>
+#include "lib.h"
+
#include <math.h>
#include <stdlib.h>
#include <errno.h>
@@ -32,7 +33,6 @@ extern "C" {
#include "assert.h"
#include "cset.h"
-#include "lib.h"
#include "stringclass.h"
#include "errarg.h"
#include "error.h"
diff --git a/contrib/groff/src/preproc/pic/pic.man b/contrib/groff/src/preproc/pic/pic.man
index ea53074..406246f 100644
--- a/contrib/groff/src/preproc/pic/pic.man
+++ b/contrib/groff/src/preproc/pic/pic.man
@@ -1,5 +1,5 @@
.ig
-Copyright (C) 1989-2000, 2001 Free Software Foundation, Inc.
+Copyright (C) 1989-2000, 2001, 2002 Free Software Foundation, Inc.
Permission is granted to make and distribute verbatim copies of
this manual provided the copyright notice and this permission notice
@@ -16,30 +16,43 @@ versions, except that this permission notice may be included in
translations approved by the Free Software Foundation instead of in
the original English.
..
+.
+.
.\" Like TP, but if specified indent is more than half
.\" the current line-length - indent, use the default indent.
.de Tp
.ie \\n(.$=0:((0\\$1)*2u>(\\n(.lu-\\n(.iu)) .TP
.el .TP "\\$1"
..
+.
.ie t .ds tx T\h'-.1667m'\v'.224m'E\v'-.224m'\h'-.125m'X
-.el .ds tx TeX
+.el .ds tx TeX
+.
.ie \n(.g .ds ic \/
-.el .ds ic \^
+.el .ds ic \^
+.
.\" The BSD man macros can't handle " in arguments to font change macros,
.\" so use \(ts instead of ".
.tr \(ts"
+.
+.
.TH @G@PIC @MAN1EXT@ "@MDATE@" "Groff Version @VERSION@"
+.
+.
.SH NAME
+.
@g@pic \- compile pictures for troff or TeX
+.
+.
.SH SYNOPSIS
+.
.B @g@pic
[
.B \-nvCSU
]
[
.I filename
-\&.\|.\|.
+\&.\|.\|.\&
]
.br
.B @g@pic
@@ -49,9 +62,12 @@ the original English.
]
[
.I filename
-\&.\|.\|.
+\&.\|.\|.\&
]
+.
+.
.SH DESCRIPTION
+.
This manual page describes the GNU version of
.BR pic ,
which is part of the groff document formatting system.
@@ -80,7 +96,10 @@ When the macro package being used does not supply such definitions
appropriate definitions can be obtained with
.BR \-mpic :
these will center each picture.
+.
+.
.SH OPTIONS
+.
Options that do not take arguments may be grouped behind a single
.BR \- .
The special option
@@ -89,6 +108,7 @@ can be used to mark the end of the options.
A filename of
.B \-
refers to the standard input.
+.
.TP
.B \-C
Recognize
@@ -96,6 +116,7 @@ Recognize
and
.B .PE
even when followed by a character other than space or newline.
+.
.TP
.B \-S
Safer mode; do not execute
@@ -103,10 +124,12 @@ Safer mode; do not execute
commands.
This can be useful when operating on untrustworthy input.
(enabled by default)
+.
.TP
.B \-U
Unsafe mode; revert the default option
.BR \-S .
+.
.TP
.B \-n
Don't use the groff extensions to the troff drawing commands.
@@ -119,9 +142,11 @@ The
option also causes
.B pic
not to use zero-length lines to draw dots in troff mode.
+.
.TP
.B \-t
\*(tx mode.
+.
.TP
.B \-c
Be more compatible with
@@ -151,21 +176,26 @@ specified by use of the
attribute or by setting the
.B linethick
variable.
+.
.TP
.B \-v
Print the version number.
+.
.TP
.B \-z
In \*(tx mode draw dots using zero-length lines.
+.
.LP
The following options supported by other versions of
.B pic
are ignored:
+.
.TP
.B \-D
Draw all lines using the \eD escape sequence.
.B pic
always does this.
+.
.TP
.BI \-T \ dev
Generate output for the
@@ -177,15 +207,24 @@ This is unnecessary because the
output generated by
.B pic
is device-independent.
+.
+.
.SH USAGE
+.
This section describes only the differences between GNU
.B pic
and the original version of
.BR pic .
Many of these differences also apply to newer versions of Unix
.BR pic .
-.SS \*(tx mode
+A complete documentation is available in the file
.LP
+.RS
+.B @DOCDIR@/pic.ms
+.RE
+.
+.SS \*(tx mode
+.
\*(tx mode is enabled by the
.B \-t
option.
@@ -225,7 +264,9 @@ change the value of
.BR \ebaselineskip .
Anything else may well produce undesirable results; use at your own risk.
Lines beginning with a period are not given any special treatment.
+.
.SS Commands
+.
.TP
\fBfor\fR \fIvariable\fR \fB=\fR \fIexpr1\fR \fBto\fR \fIexpr2\fR \
[\fBby\fR [\fB*\fR]\fIexpr3\fR] \fBdo\fR \fIX\fR \fIbody\fR \fIX\fR
@@ -259,6 +300,7 @@ will instead be multiplied by
.I X
can be any character not occurring in
.IR body .
+.
.TP
\fBif\fR \fIexpr\fR \fBthen\fR \fIX\fR \fIif-true\fR \fIX\fR \
[\fBelse\fR \fIY\fR \fIif-false\fR \fIY\fR]
@@ -274,6 +316,7 @@ can be any character not occurring in
.I Y
can be any character not occurring in
.IR if-false .
+.
.TP
\fBprint\fR \fIarg\fR\|.\|.\|.
Concatenate the arguments and print as a line on stderr.
@@ -281,18 +324,20 @@ Each
.I arg
must be an expression, a position, or text.
This is useful for debugging.
+.
.TP
\fBcommand\fR \fIarg\fR\|.\|.\|.
Concatenate the arguments
-and pass them through as a line to troff or\*(tx.
+and pass them through as a line to troff or \*(tx.
Each
.I arg
must be an expression, a position, or text.
This has a similar effect to a line beginning with
-.B .
+.B .\&
or
.BR \e ,
but allows the values of variables to be passed through.
+.
.TP
\fBsh\fR \fIX\fR \fIcommand\fR \fIX\fR
Pass
@@ -301,11 +346,13 @@ to a shell.
.I X
can be any character not occurring in
.IR command .
+.
.TP
\fBcopy\fR \fB"\fIfilename\fB"\fR
Include
.I filename
at this point in the file.
+.
.TP
\fBcopy\fR [\fB"\fIfilename\fB"\fR] \fBthru\fR \fIX\fR \fIbody\fR \fIX\fR \
[\fBuntil\fR \fB"\fIword\*(ic\fB"\fR]
@@ -377,12 +424,13 @@ The commands to be performed for each line can also be taken
from a macro defined earlier by giving the name of the macro
as the argument to
.BR thru .
+.
.LP
.B reset
.br
.ns
.TP
-\fBreset\fI variable1\fB,\fI variable2 .\^.\^.
+\fBreset\fI variable1\fR[\fB,\fR]\fI variable2 .\^.\^.
Reset pre-defined variables
.IR variable1 ,
.I variable2
@@ -393,6 +441,7 @@ Note that assigning a value to
.B scale
also causes all pre-defined variables that control dimensions
to be reset to their default values times the new value of scale.
+.
.TP
\fBplot\fR \fIexpr\fR [\fB"\fItext\*(ic\fB"\fR]
This is a text object which is constructed by using
@@ -412,24 +461,48 @@ Be very careful that you specify an appropriate format string;
does only very limited checking of the string.
This is deprecated in favour of
.BR sprintf .
+.
.TP
-.IB variable := expr
+.IB variable\ := \ expr
This is similar to
.B =
except
.I variable
must already be defined,
-and the value of
+and
+.I expr
+will be assigned to
.I variable
-will be changed only in the innermost block in which it is defined.
+without creating a variable local to the current block.
(By contrast,
.B =
defines the variable in the current block if it is not already defined there,
-and then changes the value in the current block.)
+and then changes the value in the current block only.)
+For example, the following:
+.RS
+.IP
+.ft B
+.nf
+\&.PS
+x = 3
+y = 3
+[
+ x := 5
+ y = 5
+]
+print x " " y
+\&.PE
+.ft
+.fi
+.RE
+.IP
+prints
+.BR 5\ 3 .
+.
.LP
Arguments of the form
.IP
-.IR X\ anything\ X
+.I X anything X
.LP
are also allowed to be of the form
.IP
@@ -447,8 +520,11 @@ or imbalanced occurrences of
.B {
and
.BR } .
+.
.SS Expressions
+.
The syntax for expressions has been significantly extended:
+.
.LP
.IB x\ ^\ y
(exponentiation)
@@ -463,7 +539,9 @@ The syntax for expressions has been significantly extended:
(base 10)
.br
.BI exp( x )
-(base 10, ie 10\v'-.4m'\fIx\*(ic\fR\v'.4m')
+(base 10, ie
+.ie t 10\v'-.4m'\fIx\*(ic\fR\v'.4m')
+.el 10^\fIx\fR)
.br
.BI sqrt( x )
.br
@@ -506,11 +584,13 @@ deprecated)
.br
\fB"\fIstr1\*(ic\fB" != "\fIstr2\*(ic\fB"\fR
.br
+.
.LP
String comparison expressions must be parenthesised in some contexts
to avoid ambiguity.
+.
.SS Other Changes
-.LP
+.
A bare expression,
.IR expr ,
is acceptable as an attribute;
@@ -523,13 +603,19 @@ For example
.IP
.B line 2i
.LP
-means draw a line 2 inches long in the current direction.
+means draw a line 2\ inches long in the current direction.
+The `i' (or `I') character is ignored; to use another measurement unit,
+set the
+.I scale
+variable to an appropriate value.
+.
.LP
The maximum width and height of the picture are taken from the variables
.B maxpswid
and
.BR maxpsht .
Initially these have values 8.5 and 11.
+.
.LP
Scientific notation is allowed for numbers.
For example
@@ -537,6 +623,7 @@ For example
.B
x = 5e\-2
.RE
+.
.LP
Text attributes can be compounded.
For example,
@@ -545,6 +632,7 @@ For example,
"foo" above ljust
.RE
is legal.
+.
.LP
There is no limit to the depth to which blocks can be examined.
For example,
@@ -556,12 +644,15 @@ For example,
circle at last [\^].A.B.C
.RE
is acceptable.
+.
.LP
Arcs now have compass points
determined by the circle of which the arc is a part.
+.
.LP
Circles and arcs can be dotted or dashed.
In \*(tx mode splines can be dotted or dashed.
+.
.LP
Boxes can have rounded corners.
The
@@ -576,8 +667,9 @@ attribute is given, a radius of
is used.
Initially,
.B boxrad
-has a value of 0.
+has a value of\ 0.
A box with rounded corners can be dotted or dashed.
+.
.LP
The
.B .PS
@@ -587,13 +679,15 @@ If the width of zero is specified the width will be ignored in computing
the scaling factor for the picture.
Note that GNU
.B pic
-will always scale a picture by the same amount vertically as horizontally.
+will always scale a picture by the same amount vertically as well as
+horizontally.
This is different from the
.SM DWB
2.0
.B pic
which may scale a picture by a different amount vertically than
horizontally if a height is specified.
+.
.LP
Each text object has an invisible box associated with it.
The compass points of a text object are determined by this box.
@@ -611,8 +705,9 @@ Initially
and
.B textht
have a value of 0.
+.
.LP
-In places where a quoted text string can be used,
+In (almost all) places where a quoted text string can be used,
an expression of the form
.IP
.BI sprintf(\(ts format \(ts,\ arg ,\fR.\|.\|.\fB)
@@ -622,14 +717,8 @@ this will produce the arguments formatted according to
.IR format ,
which should be a string as described in
.BR printf (3)
-appropriate for the number of arguments supplied,
-using only the
-.BR e ,
-.BR f ,
-.B g
-or
-.B %
-format characters.
+appropriate for the number of arguments supplied.
+.
.LP
The thickness of the lines used to draw objects is controlled by the
.B linethick
@@ -663,9 +752,10 @@ value of the
variable, nor by the width or height given in the
.B .PS
line.
+.
.LP
Boxes (including boxes with rounded corners),
-circles and ellipses can be filled by giving then an attribute of
+circles and ellipses can be filled by giving them an attribute of
.BR fill [ ed ].
This takes an optional argument of an expression with a value between
0 and 1; 0 will fill it with white, 1 with black, values in between
@@ -683,16 +773,48 @@ The invisible attribute does not affect the filling of objects.
Any text associated with a filled object will be added after the
object has been filled, so that the text will not be obscured
by the filling.
+.
+.LP
+Three additional modifiers are available to specify colored objects:
+.BR outline [ d ]
+sets the color of the outline,
+.B shaded
+the fill color, and
+.BR colo [ u ] r [ ed ]
+sets both.
+All three keywords expect a suffix specifying the color, for example
+.RS
+.LP
+.B circle shaded """green""" outline """black"""
+.RE
+.LP
+Currently, color support isn't available in \*(tx mode.
+Predefined color names for
+.B groff
+are in the device macro files, for example
+.BR ps.tmac ;
+additional colors can be defined with the
+.B .defcolor
+request (see the manual page of
+.BR @g@troff (@MAN1EXT@)
+for more details).
+.LP
+.B pic
+assumes that at the beginning of a picture both glyph and fill color are
+set to the default value.
+.
.LP
Arrow heads will be drawn as solid triangles if the variable
.B arrowhead
-is non-zero and either \*(tx mode is enabled or
-the
-.B \-x
-option has been given.
+is non-zero and either \*(tx mode is enabled or the
+.B \-n
+option has not been given.
Initially
.B arrowhead
-has a value of 1.
+has a value of\ 1.
+Note that solid arrow heads are always filled with the current outline
+color.
+.
.LP
The troff output of
.B pic
@@ -702,11 +824,12 @@ The
option is therefore redundant.
All numbers are taken to be in inches; numbers are never interpreted
to be in troff machine units.
+.
.LP
Objects can have an
.B aligned
attribute.
-This will only work when the postprocessor is
+This will only work if the postprocessor is
.BR grops .
Any text associated with an object having the
.B aligned
@@ -715,6 +838,7 @@ so that it is aligned in the direction from the start point
to the end point of the object.
Note that this attribute will have no effect for objects whose start and
end points are coincident.
+.
.LP
In places where
.IB n th
@@ -729,13 +853,17 @@ and the
.BR th .
For example,
.IP
-.B
+.ft B
.nf
for i = 1 to 4 do {
line from `i'th box.nw to `i+1'th box.se
}
+.ft
.fi
+.
+.
.SH CONVERSION
+.
To obtain a stand-alone picture from a
.B pic
file, enclose your
@@ -749,6 +877,7 @@ requests;
configuration commands may be added at the beginning of the file, but no
.B roff
text.
+.
.LP
It is necessary to feed this file into
.B groff
@@ -774,6 +903,7 @@ Alternatively, you can define your own requests, e.g. to do nothing:
.ft
.fi
.RE
+.
.LP
.B groff
itself does not provide direct conversion into other graphics file
@@ -806,6 +936,7 @@ Call
.RE
.LP
for a list of the available devices.
+.
.LP
As the Encapsulated PostScript File Format
.B EPS
@@ -827,7 +958,10 @@ file can be then converted to virtually any graphics format using the tools
of the
.B netpbm
package .
+.
+.
.SH FILES
+.
.Tp \w'\fB@MACRODIR@/pic.tmac'u+3n
.B
@MACRODIR@/pic.tmac
@@ -836,7 +970,10 @@ Example definitions of the
and
.B PE
macros.
+.
+.
.SH "SEE ALSO"
+.
.BR @g@troff (@MAN1EXT@),
.BR groff_out (@MAN5EXT@),
.BR tex (1),
@@ -851,7 +988,7 @@ Tpic: Pic for \*(tx
Brian W. Kernighan,
PIC \(em A Graphics Language for Typesetting (User Manual).
AT&T Bell Laboratories, Computing Science Technical Report No.\ 116
-<URL:http://cm.bell-labs.com/cm/cs/cstr/116.ps.gz>
+<http://cm.bell-labs.com/cm/cs/cstr/116.ps.gz>
(revised May, 1991).
.LP
.B ps2eps
@@ -866,14 +1003,16 @@ W. Richard Stevens - Turning PIC Into HTML
W. Richard Stevens - Examples of picMacros
.br
<http://www.kohala.com/start/troff/pic.examples.ps>
+.
+.
.SH BUGS
-.LP
-Input characters that are illegal for
+.
+Input characters that are invalid for
.B groff
(ie those with
.SM ASCII
-code 0 or between 013 and 037 octal or between 0200 and 0237 octal)
-are rejected even in \*(tx mode.
+code 0, or 013 octal, or between 015 and 037 octal, or between 0200 and 0237
+octal) are rejected even in \*(tx mode.
.LP
The interpretation of
.B fillval
diff --git a/contrib/groff/src/preproc/pic/pic.y b/contrib/groff/src/preproc/pic/pic.y
index c0a7315..15b6b3f 100644
--- a/contrib/groff/src/preproc/pic/pic.y
+++ b/contrib/groff/src/preproc/pic/pic.y
@@ -1,4 +1,4 @@
-/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001
+/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001, 2002
Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
@@ -202,6 +202,10 @@ char *do_sprintf(const char *form, const double *v, int nv);
%token GREATEREQUAL
%token LEFT_CORNER
%token RIGHT_CORNER
+%token NORTH
+%token SOUTH
+%token EAST
+%token WEST
%token CENTER
%token END
%token START
@@ -210,6 +214,9 @@ char *do_sprintf(const char *form, const double *v, int nv);
%token PLOT
%token THICKNESS
%token FILL
+%token COLORED
+%token OUTLINED
+%token SHADED
%token ALIGNED
%token SPRINTF
%token COMMAND
@@ -217,6 +224,8 @@ char *do_sprintf(const char *form, const double *v, int nv);
%token DEFINE
%token UNDEF
+%left '.'
+
/* this ensures that plot 17 "%g" parses as (plot 17 "%g") */
%left PLOT
%left TEXT SPRINTF
@@ -231,12 +240,14 @@ box "foo" above ljust == box ("foo" above ljust)
/* Give attributes that take an optional expression a higher
precedence than left and right, so that eg `line chop left'
parses properly. */
-%left CHOP SOLID DASHED DOTTED UP DOWN FILL
+%left CHOP SOLID DASHED DOTTED UP DOWN FILL COLORED OUTLINED
%left LABEL
%left VARIABLE NUMBER '(' SIN COS ATAN2 LOG EXP SQRT K_MAX K_MIN INT RAND SRAND LAST
%left ORDINAL HERE '`'
+%left BOX CIRCLE ELLIPSE ARC LINE ARROW SPLINE '['
+
/* these need to be lower than '-' */
%left HEIGHT RADIUS WIDTH DIAMETER FROM TO AT THICKNESS
@@ -244,7 +255,7 @@ parses properly. */
works */
%left DOT_N DOT_E DOT_W DOT_S DOT_NE DOT_SE DOT_NW DOT_SW DOT_C
%left DOT_START DOT_END TOP BOTTOM LEFT_CORNER RIGHT_CORNER
-%left UPPER LOWER CENTER START END
+%left UPPER LOWER NORTH SOUTH EAST WEST CENTER START END
%left ','
%left OROR
@@ -350,7 +361,7 @@ placeless_element:
{
fprintf(stderr, "%s\n", $2.str);
a_delete $2.str;
- fflush(stderr);
+ fflush(stderr);
}
| SH
{ delim_flag = 1; }
@@ -433,11 +444,20 @@ placeless_element:
reset_variables:
RESET VARIABLE
- { reset($2); a_delete $2; }
+ {
+ reset($2);
+ a_delete $2;
+ }
| reset_variables VARIABLE
- { reset($2); a_delete $2; }
+ {
+ reset($2);
+ a_delete $2;
+ }
| reset_variables ',' VARIABLE
- { reset($3); a_delete $3; }
+ {
+ reset($3);
+ a_delete $3;
+ }
;
print_args:
@@ -462,7 +482,7 @@ print_args:
;
print_arg:
- expr %prec ','
+ expr %prec ','
{
$$.str = new char[GDIGITS + 1];
sprintf($$.str, "%g", $1);
@@ -471,19 +491,24 @@ print_arg:
}
| text
{ $$ = $1; }
- | position %prec ','
+ | position %prec ','
{
$$.str = new char[GDIGITS + 2 + GDIGITS + 1];
sprintf($$.str, "%g, %g", $1.x, $1.y);
$$.filename = 0;
$$.lineno = 0;
}
+ ;
simple_if:
IF any_expr THEN
{ delim_flag = 1; }
DELIMITED
- { delim_flag = 0; $$.x = $2; $$.body = $5; }
+ {
+ delim_flag = 0;
+ $$.x = $2;
+ $$.body = $5;
+ }
;
until:
@@ -532,11 +557,20 @@ text_expr:
optional_by:
/* empty */
- { $$.val = 1.0; $$.is_multiplicative = 0; }
+ {
+ $$.val = 1.0;
+ $$.is_multiplicative = 0;
+ }
| BY expr
- { $$.val = $2; $$.is_multiplicative = 0; }
+ {
+ $$.val = $2;
+ $$.is_multiplicative = 0;
+ }
| BY '*' expr
- { $$.val = $3; $$.is_multiplicative = 1; }
+ {
+ $$.val = $3;
+ $$.is_multiplicative = 1;
+ }
;
element:
@@ -555,7 +589,11 @@ element:
}
}
| LABEL ':' optional_separator element
- { $$ = $4; define_label($1, & $$); a_delete $1; }
+ {
+ $$ = $4;
+ define_label($1, & $$);
+ a_delete $1;
+ }
| LABEL ':' optional_separator position_not_place
{
$$.obj = 0;
@@ -603,17 +641,11 @@ optional_element:
object_spec:
BOX
- {
- $$ = new object_spec(BOX_OBJECT);
- }
+ { $$ = new object_spec(BOX_OBJECT); }
| CIRCLE
- {
- $$ = new object_spec(CIRCLE_OBJECT);
- }
+ { $$ = new object_spec(CIRCLE_OBJECT); }
| ELLIPSE
- {
- $$ = new object_spec(ELLIPSE_OBJECT);
- }
+ { $$ = new object_spec(ELLIPSE_OBJECT); }
| ARC
{
$$ = new object_spec(ARC_OBJECT);
@@ -647,7 +679,7 @@ object_spec:
lookup_variable("linewid", & $$->segment_width);
$$->dir = current_direction;
}
- | text %prec TEXT
+ | text %prec TEXT
{
$$ = new object_spec(TEXT_OBJECT);
$$->text = new text_item($1.str, $1.filename, $1.lineno);
@@ -715,7 +747,7 @@ object_spec:
$$->radius = $3/2.0;
$$->flags |= HAS_RADIUS;
}
- | object_spec expr %prec HEIGHT
+ | object_spec expr %prec HEIGHT
{
$$ = $1;
$$->flags |= HAS_SEGMENT;
@@ -830,6 +862,15 @@ object_spec:
$$->flags |= HAS_WITH;
$$->with = $3;
}
+ | object_spec WITH position %prec ','
+ {
+ $$ = $1;
+ $$->flags |= HAS_WITH;
+ position pos;
+ pos.x = $3.x;
+ pos.y = $3.y;
+ $$->with = new path(pos);
+ }
| object_spec BY expr_pair
{
$$ = $1;
@@ -888,6 +929,29 @@ object_spec:
$$->flags |= IS_FILLED;
$$->fill = $3;
}
+ | object_spec SHADED text
+ {
+ $$ = $1;
+ $$->flags |= (IS_SHADED | IS_FILLED);
+ $$->shaded = new char[strlen($3.str)+1];
+ strcpy($$->shaded, $3.str);
+ }
+ | object_spec COLORED text
+ {
+ $$ = $1;
+ $$->flags |= (IS_SHADED | IS_OUTLINED | IS_FILLED);
+ $$->shaded = new char[strlen($3.str)+1];
+ strcpy($$->shaded, $3.str);
+ $$->outlined = new char[strlen($3.str)+1];
+ strcpy($$->outlined, $3.str);
+ }
+ | object_spec OUTLINED text
+ {
+ $$ = $1;
+ $$->flags |= IS_OUTLINED;
+ $$->outlined = new char[strlen($3.str)+1];
+ strcpy($$->outlined, $3.str);
+ }
| object_spec CHOP
{
$$ = $1;
@@ -956,7 +1020,7 @@ object_spec:
$$ = $1;
$$->flags &= ~IS_CLOCKWISE;
}
- | object_spec text %prec TEXT
+ | object_spec text %prec TEXT
{
$$ = $1;
text_item **p;
@@ -1019,9 +1083,7 @@ object_spec:
text:
TEXT
- {
- $$ = $1;
- }
+ { $$ = $1; }
| SPRINTF '(' TEXT sprintf_args ')'
{
$$.filename = $3.filename;
@@ -1108,13 +1170,17 @@ between:
expr_pair:
expr ',' expr
- { $$.x = $1; $$.y = $3; }
+ {
+ $$.x = $1;
+ $$.y = $3;
+ }
| '(' expr_pair ')'
{ $$ = $2; }
;
place:
- label %prec CHOP /* line at A left == line (at A) left */
+ /* line at A left == line (at A) left */
+ label %prec CHOP
{ $$ = $1; }
| label corner
{
@@ -1154,9 +1220,7 @@ label:
a_delete $1;
}
| nth_primitive
- {
- $$.obj = $1;
- }
+ { $$.obj = $1; }
| label '.' LABEL
{
path pth($3);
@@ -1176,7 +1240,7 @@ ordinal:
;
optional_ordinal_last:
- LAST
+ LAST
{ $$ = 1; }
| ordinal LAST
{ $$ = $1; }
@@ -1238,9 +1302,7 @@ object_type:
label_path:
'.' LABEL
- {
- $$ = new path($2);
- }
+ { $$ = new path($2); }
| label_path '.' LABEL
{
$$ = $1;
@@ -1249,17 +1311,12 @@ label_path:
;
relative_path:
- corner
- {
- $$ = new path($1);
- }
+ corner %prec CHOP
+ { $$ = new path($1); }
/* give this a lower precedence than LEFT and RIGHT so that
[A: box] with .A left == [A: box] with (.A left) */
-
- | label_path %prec TEXT
- {
- $$ = $1;
- }
+ | label_path %prec TEXT
+ { $$ = $1; }
| label_path corner
{
$$ = $1;
@@ -1269,9 +1326,7 @@ relative_path:
path:
relative_path
- {
- $$ = $1;
- }
+ { $$ = $1; }
| '(' relative_path ',' relative_path ')'
{
$$ = $2;
@@ -1355,6 +1410,14 @@ corner:
{ $$ = &object::north_east; }
| LOWER RIGHT_CORNER
{ $$ = &object::south_east; }
+ | NORTH
+ { $$ = &object::north; }
+ | SOUTH
+ { $$ = &object::south; }
+ | EAST
+ { $$ = &object::east; }
+ | WEST
+ { $$ = &object::west; }
| CENTER
{ $$ = &object::center; }
| START
@@ -1444,7 +1507,7 @@ expr:
YYABORT;
}
}
- | '-' expr %prec '!'
+ | '-' expr %prec '!'
{ $$ = -$2; }
| '(' any_expr ')'
{ $$ = $2; }
@@ -1521,7 +1584,10 @@ expr:
$$ = (rand() & 0x7fff) / double(0x8000);
}
| SRAND '(' any_expr ')'
- { $$ = 0; srand((unsigned int)$3); }
+ {
+ $$ = 0;
+ srand((unsigned int)$3);
+ }
| expr '<' expr
{ $$ = ($1 < $3); }
| expr LESSEQUAL expr
@@ -1754,23 +1820,7 @@ char *format_number(const char *form, double n)
{
if (form == 0)
form = "%g";
- else {
- // this is a fairly feeble attempt at validation of the format
- int nspecs = 0;
- for (const char *p = form; *p != '\0'; p++)
- if (*p == '%') {
- if (p[1] == '%')
- p++;
- else
- nspecs++;
- }
- if (nspecs > 1) {
- lex_error("bad format `%1'", form);
- return strsave(form);
- }
- }
- sprintf(sprintf_buf, form, n);
- return strsave(sprintf_buf);
+ return do_sprintf(form, &n, 1);
}
char *do_sprintf(const char *form, const double *v, int nv)
@@ -1792,18 +1842,20 @@ char *do_sprintf(const char *form, const double *v, int nv)
if (*form == '%') {
one_format += *form++;
one_format += '\0';
- sprintf(sprintf_buf, one_format.contents());
+ snprintf(sprintf_buf, sizeof(sprintf_buf),
+ "%s", one_format.contents());
}
else {
if (i >= nv) {
- lex_error("too few arguments to sprintf");
+ lex_error("too few arguments to snprintf");
result += one_format;
result += form;
break;
}
one_format += *form++;
one_format += '\0';
- sprintf(sprintf_buf, one_format.contents(), v[i++]);
+ snprintf(sprintf_buf, sizeof(sprintf_buf),
+ one_format.contents(), v[i++]);
}
one_format.clear();
result += sprintf_buf;
diff --git a/contrib/groff/src/preproc/pic/tex.cc b/contrib/groff/src/preproc/pic/tex.cc
index 2a91b62..a9192ac 100644
--- a/contrib/groff/src/preproc/pic/tex.cc
+++ b/contrib/groff/src/preproc/pic/tex.cc
@@ -42,6 +42,10 @@ public:
void circle(const position &, double rad, const line_type &, double);
void ellipse(const position &, const distance &, const line_type &, double);
void command(const char *, const char *, int);
+ void set_color(char *, char *);
+ void reset_color();
+ char *get_last_filled();
+ char *get_outline_color();
int supports_filled_polygons();
private:
position upper_left;
@@ -350,6 +354,28 @@ void tex_output::dot(const position &pos, const line_type &lt)
}
}
+void tex_output::set_color(char *, char *)
+{
+ /* not implemented yet */
+}
+
+void tex_output::reset_color()
+{
+ /* not implemented yet */
+}
+
+char *tex_output::get_last_filled()
+{
+ /* not implemented yet */
+ return NULL;
+}
+
+char *tex_output::get_outline_color()
+{
+ /* not implemented yet */
+ return NULL;
+}
+
class tpic_output : public tex_output {
public:
tpic_output();
diff --git a/contrib/groff/src/preproc/pic/troff.cc b/contrib/groff/src/preproc/pic/troff.cc
index 62fe540..7ee7293 100644
--- a/contrib/groff/src/preproc/pic/troff.cc
+++ b/contrib/groff/src/preproc/pic/troff.cc
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001
+/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001, 2002
Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
@@ -21,7 +21,6 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "pic.h"
#include "common.h"
-#include "htmlindicate.h"
const double RELATIVE_THICKNESS = -1.0;
@@ -37,6 +36,9 @@ class simple_output : public common_output {
virtual void simple_polygon(int, const position *, int) = 0;
virtual void line_thickness(double) = 0;
virtual void set_fill(double) = 0;
+ virtual void set_color(char *, char *) = 0;
+ virtual void reset_color() = 0;
+ virtual char *get_last_filled() = 0;
void dot(const position &, const line_type &) = 0;
public:
void start_picture(double sc, const position &ll, const position &ur) = 0;
@@ -140,11 +142,10 @@ void simple_output::spline(const position &start, const position *v, int n,
void simple_output::polygon(const position *v, int n,
const line_type &lt, double fill)
{
- if (driver_extension_flag) {
- if (fill >= 0.0) {
+ if (driver_extension_flag && ((fill >= 0.0) || (get_last_filled() != 0))) {
+ if (get_last_filled() == 0)
set_fill(fill);
- simple_polygon(1, v, n);
- }
+ simple_polygon(1, v, n);
}
if (lt.type == line_type::solid && driver_extension_flag) {
line_thickness(lt.thickness);
@@ -159,8 +160,9 @@ void simple_output::polygon(const position *v, int n,
void simple_output::circle(const position &cent, double rad,
const line_type &lt, double fill)
{
- if (driver_extension_flag && fill >= 0.0) {
- set_fill(fill);
+ if (driver_extension_flag && ((fill >= 0.0) || (get_last_filled() != 0))) {
+ if (get_last_filled() == 0)
+ set_fill(fill);
simple_circle(1, cent, rad);
}
line_thickness(lt.thickness);
@@ -184,8 +186,9 @@ void simple_output::circle(const position &cent, double rad,
void simple_output::ellipse(const position &cent, const distance &dim,
const line_type &lt, double fill)
{
- if (driver_extension_flag && fill >= 0.0) {
- set_fill(fill);
+ if (driver_extension_flag && ((fill >= 0.0) || (get_last_filled() != 0))) {
+ if (get_last_filled() == 0)
+ set_fill(fill);
simple_ellipse(1, cent, dim);
}
if (lt.type != line_type::invisible)
@@ -212,6 +215,8 @@ class troff_output : public simple_output {
double scale;
double last_line_thickness;
double last_fill;
+ char *last_filled; // color
+ char *last_outlined; // color
public:
troff_output();
~troff_output();
@@ -229,6 +234,10 @@ public:
void simple_polygon(int, const position *, int);
void line_thickness(double p);
void set_fill(double);
+ void set_color(char *, char *);
+ void reset_color();
+ char *get_last_filled();
+ char *get_outline_color();
position transform(const position &);
};
@@ -238,7 +247,8 @@ output *make_troff_output()
}
troff_output::troff_output()
-: last_filename(0), last_line_thickness(BAD_THICKNESS), last_fill(-1.0)
+: last_filename(0), last_line_thickness(BAD_THICKNESS),
+ last_fill(-1.0), last_filled(0), last_outlined(0)
{
}
@@ -269,7 +279,6 @@ void troff_output::start_picture(double sc,
scale = compute_scale(sc, ll, ur);
height = (ur.y - ll.y)/scale;
double width = (ur.x - ll.x)/scale;
- graphic_start(0);
printf(".PS %.3fi %.3fi", height, width);
if (args)
printf(" %s\n", args);
@@ -288,6 +297,7 @@ void troff_output::finish_picture()
{
line_thickness(BAD_THICKNESS);
last_fill = -1.0; // force it to be reset for each picture
+ reset_color();
if (!flyback_flag)
printf(".sp %.3fi+1\n", height);
printf(".if \\n(" FILL_REG " .fi\n");
@@ -296,7 +306,6 @@ void troff_output::finish_picture()
// this is a little gross
set_location(current_filename, current_lineno);
fputs(flyback_flag ? ".PF\n" : ".PE\n", stdout);
- graphic_end();
}
void troff_output::command(const char *s,
@@ -472,6 +481,54 @@ void troff_output::set_fill(double f)
printf("\\D'f %du'\\h'%du'\n.sp -1\n", int(f*FILL_MAX), -int(f*FILL_MAX));
last_fill = f;
}
+ if (last_filled) {
+ free(last_filled);
+ last_filled = 0;
+ printf("\\M[]\n.sp -1\n");
+ }
+}
+
+void troff_output::set_color(char *color_fill, char *color_outlined)
+{
+ if (driver_extension_flag) {
+ if (last_filled || last_outlined) {
+ reset_color();
+ }
+ if (color_fill) {
+ printf("\\M[%s]\n.sp -1\n", color_fill);
+ last_filled = strdup(color_fill);
+ }
+ if (color_outlined) {
+ printf("\\m[%s]\n.sp -1\n", color_outlined);
+ last_outlined = strdup(color_outlined);
+ }
+ }
+}
+
+void troff_output::reset_color()
+{
+ if (driver_extension_flag) {
+ if (last_filled) {
+ printf("\\M[]\n.sp -1\n");
+ free(last_filled);
+ last_filled = 0;
+ }
+ if (last_outlined) {
+ printf("\\m[]\n.sp -1\n");
+ free(last_outlined);
+ last_outlined = 0;
+ }
+ }
+}
+
+char *troff_output::get_last_filled()
+{
+ return last_filled;
+}
+
+char *troff_output::get_outline_color()
+{
+ return last_outlined;
}
const double DOT_AXIS = .044;
diff --git a/contrib/groff/src/preproc/refer/Makefile.sub b/contrib/groff/src/preproc/refer/Makefile.sub
index 1631b5e..9f4a53b 100644
--- a/contrib/groff/src/preproc/refer/Makefile.sub
+++ b/contrib/groff/src/preproc/refer/Makefile.sub
@@ -1,13 +1,13 @@
-PROG=refer
+PROG=refer$(EXEEXT)
MAN1=refer.n
XLIBS=$(LIBBIB) $(LIBGROFF)
MLIB=$(LIBM)
OBJS=\
- command.o \
- label.o \
- ref.o \
- refer.o \
- token.o
+ command.$(OBJEXT) \
+ label.$(OBJEXT) \
+ ref.$(OBJEXT) \
+ refer.$(OBJEXT) \
+ token.$(OBJEXT)
CCSRCS=\
$(srcdir)/command.cc \
$(srcdir)/ref.cc \
@@ -19,5 +19,5 @@ HDRS=\
$(srcdir)/command.h \
$(srcdir)/ref.h
GRAM=$(srcdir)/label.y
-YTABC=$(srcdir)/label.cc
+YTABC=label.cc
NAMEPREFIX=$(g)
diff --git a/contrib/groff/src/preproc/refer/command.cc b/contrib/groff/src/preproc/refer/command.cc
index bf88c89d..a7c6bfb 100644
--- a/contrib/groff/src/preproc/refer/command.cc
+++ b/contrib/groff/src/preproc/refer/command.cc
@@ -1,5 +1,6 @@
// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992, 2001 Free Software Foundation, Inc.
+/* Copyright (C) 1989, 1990, 1991, 1992, 2001, 2002
+ Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
This file is part of groff.
@@ -193,9 +194,9 @@ void input_stack::push_file(const char *fn)
}
if (c == EOF)
break;
- if (illegal_input_char(c))
+ if (invalid_input_char(c))
error_with_file_and_line(fn, lineno,
- "illegal input character code %1", int(c));
+ "invalid input character code %1", int(c));
else {
buf += c;
if (c == '\n') {
diff --git a/contrib/groff/src/preproc/refer/refer.cc b/contrib/groff/src/preproc/refer/refer.cc
index c39def7..33df35c 100644
--- a/contrib/groff/src/preproc/refer/refer.cc
+++ b/contrib/groff/src/preproc/refer/refer.cc
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 1989-1992, 2000, 2001 Free Software Foundation, Inc.
+/* Copyright (C) 1989-1992, 2000, 2001, 2002 Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
This file is part of groff.
@@ -445,8 +445,8 @@ static void do_file(const char *filename)
line += '\n';
break;
}
- if (illegal_input_char(c))
- error("illegal input character code %1", c);
+ if (invalid_input_char(c))
+ error("invalid input character code %1", c);
else {
line += c;
if (c == '\n')
@@ -476,8 +476,8 @@ static void do_file(const char *filename)
int d = getc(fp);
if (d == ']') {
while ((d = getc(fp)) != '\n' && d != EOF) {
- if (illegal_input_char(d))
- error("illegal input character code %1", d);
+ if (invalid_input_char(d))
+ error("invalid input character code %1", d);
else
post += d;
}
@@ -486,8 +486,8 @@ static void do_file(const char *filename)
if (d != EOF)
ungetc(d, fp);
}
- if (illegal_input_char(c))
- error("illegal input character code %1", c);
+ if (invalid_input_char(c))
+ error("invalid input character code %1", c);
else
str += c;
start_of_line = (c == '\n');
@@ -580,8 +580,8 @@ static void do_file(const char *filename)
"missing `.R2' line");
break;
}
- if (illegal_input_char(c))
- error("illegal input character code %1", int(c));
+ if (invalid_input_char(c))
+ error("invalid input character code %1", int(c));
else {
line += c;
start_of_line = c == '\n';
@@ -1113,8 +1113,8 @@ void do_bib(const char *filename)
int c = getc(fp);
if (c == EOF)
break;
- if (illegal_input_char(c)) {
- error("illegal input character code %1", c);
+ if (invalid_input_char(c)) {
+ error("invalid input character code %1", c);
continue;
}
switch (state) {
diff --git a/contrib/groff/src/preproc/refer/refer.h b/contrib/groff/src/preproc/refer/refer.h
index f0ab3cd..e1e0c6d 100644
--- a/contrib/groff/src/preproc/refer/refer.h
+++ b/contrib/groff/src/preproc/refer/refer.h
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+/* Copyright (C) 1989, 1990, 1991, 1992, 2001 Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
This file is part of groff.
@@ -18,15 +18,14 @@ 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 <stdio.h>
+#include "lib.h"
+
#include <stdlib.h>
#include <assert.h>
-#include <string.h>
#include <errno.h>
#include "errarg.h"
#include "error.h"
-#include "lib.h"
#include "stringclass.h"
#include "cset.h"
#include "cmap.h"
diff --git a/contrib/groff/src/preproc/soelim/Makefile.sub b/contrib/groff/src/preproc/soelim/Makefile.sub
index 77007e2..4b59ab6 100644
--- a/contrib/groff/src/preproc/soelim/Makefile.sub
+++ b/contrib/groff/src/preproc/soelim/Makefile.sub
@@ -1,6 +1,6 @@
-PROG=soelim
+PROG=soelim$(EXEEXT)
MAN1=soelim.n
XLIBS=$(LIBGROFF)
-OBJS=soelim.o
+OBJS=soelim.$(OBJEXT)
CCSRCS=$(srcdir)/soelim.cc
NAMEPREFIX=$(g)
diff --git a/contrib/groff/src/preproc/soelim/soelim.cc b/contrib/groff/src/preproc/soelim/soelim.cc
index a604004..006b04a 100644
--- a/contrib/groff/src/preproc/soelim/soelim.cc
+++ b/contrib/groff/src/preproc/soelim/soelim.cc
@@ -18,13 +18,12 @@ 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 <stdio.h>
+#include "lib.h"
+
#include <ctype.h>
-#include <string.h>
#include <assert.h>
#include <stdlib.h>
#include <errno.h>
-#include "lib.h"
#include "errarg.h"
#include "error.h"
#include "stringclass.h"
diff --git a/contrib/groff/src/preproc/tbl/Makefile.sub b/contrib/groff/src/preproc/tbl/Makefile.sub
index 224baff..fb14818 100644
--- a/contrib/groff/src/preproc/tbl/Makefile.sub
+++ b/contrib/groff/src/preproc/tbl/Makefile.sub
@@ -1,9 +1,9 @@
-PROG=tbl
+PROG=tbl$(EXEEXT)
MAN1=tbl.n
XLIBS=$(LIBGROFF)
OBJS=\
- main.o \
- table.o
+ main.$(OBJEXT) \
+ table.$(OBJEXT)
CCSRCS=\
$(srcdir)/main.cc \
$(srcdir)/table.cc
diff --git a/contrib/groff/src/preproc/tbl/main.cc b/contrib/groff/src/preproc/tbl/main.cc
index b1b14a7..dc0bdce 100644
--- a/contrib/groff/src/preproc/tbl/main.cc
+++ b/contrib/groff/src/preproc/tbl/main.cc
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001
+/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001, 2002
Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
@@ -20,7 +20,6 @@ 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 "table.h"
-#include "htmlindicate.h"
#define MAX_POINT_SIZE 99
#define MAX_VERTICAL_SPACING 72
@@ -110,7 +109,7 @@ int table_input::get()
else {
state = MIDDLE;
if (c == '\0') {
- error("illegal input character code 0");
+ error("invalid input character code 0");
break;
}
}
@@ -139,7 +138,7 @@ int table_input::get()
current_lineno++;
}
else if (c == '\0') {
- error("illegal input character code 0");
+ error("invalid input character code 0");
break;
}
return c;
@@ -221,8 +220,6 @@ void process_input_file(FILE *fp)
break;
case HAD_TS:
if (c == ' ' || c == '\n' || compatible_flag) {
- printf(".if '\\*(.T'html' \\X(table-start(\n");
- html_begin_suppress(0);
putchar('.');
putchar('T');
putchar('S');
@@ -244,16 +241,12 @@ void process_input_file(FILE *fp)
fputs(".TE", stdout);
while ((c = getc(fp)) != '\n') {
if (c == EOF) {
- printf(".if '\\*(.T'html' \\X(table-end(\n");
- html_end_suppress(0);
putchar('\n');
return;
}
putchar(c);
}
putchar('\n');
- printf(".if '\\*(.T'html' \\X(table-end(\n");
- html_end_suppress(0);
current_lineno++;
}
}
@@ -453,34 +446,39 @@ options *process_options(table_input &in)
}
else if (strieq(p, "center") || strieq(p, "centre")) {
if (arg)
- error("`center' option does not take a argument");
+ error("`center' option does not take an argument");
opt->flags |= table::CENTER;
}
else if (strieq(p, "expand")) {
if (arg)
- error("`expand' option does not take a argument");
+ error("`expand' option does not take an argument");
opt->flags |= table::EXPAND;
}
else if (strieq(p, "box") || strieq(p, "frame")) {
if (arg)
- error("`box' option does not take a argument");
+ error("`box' option does not take an argument");
opt->flags |= table::BOX;
}
else if (strieq(p, "doublebox") || strieq(p, "doubleframe")) {
if (arg)
- error("`doublebox' option does not take a argument");
+ error("`doublebox' option does not take an argument");
opt->flags |= table::DOUBLEBOX;
}
else if (strieq(p, "allbox")) {
if (arg)
- error("`allbox' option does not take a argument");
+ error("`allbox' option does not take an argument");
opt->flags |= table::ALLBOX;
}
else if (strieq(p, "nokeep")) {
if (arg)
- error("`nokeep' option does not take a argument");
+ error("`nokeep' option does not take an argument");
opt->flags |= table::NOKEEP;
}
+ else if (strieq(p, "nospaces")) {
+ if (arg)
+ error("`nospaces' option does not take an argument");
+ opt->flags |= table::NOSPACES;
+ }
else if (strieq(p, "decimalpoint")) {
if (!arg)
error("`decimalpoint' option requires argument in parentheses");
@@ -1214,6 +1212,8 @@ table *process_data(table_input &in, format *f, options *opt)
int ln = current_lineno;
if (c == '\n')
--ln;
+ if ((opt->flags & table::NOSPACES))
+ input_entry.remove_spaces();
while (col < ncolumns
&& line_format[col].type == FORMAT_SPAN) {
tbl->add_entry(current_row, col, "", &line_format[col],
@@ -1385,7 +1385,7 @@ table *process_data(table_input &in, format *f, options *opt)
f = newf;
}
if (line.length() >= 3
- && line[0] == '.' && line[1] == 'f' && line[2] == 'f') {
+ && line[0] == '.' && line[1] == 'l' && line[2] == 'f') {
line += '\0';
interpret_lf_args(line.contents() + 3);
}
diff --git a/contrib/groff/src/preproc/tbl/table.h b/contrib/groff/src/preproc/tbl/table.h
index ca55b80..69959b8 100644
--- a/contrib/groff/src/preproc/tbl/table.h
+++ b/contrib/groff/src/preproc/tbl/table.h
@@ -1,5 +1,6 @@
// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+/* Copyright (C) 1989, 1990, 1991, 1992, 2001, 2002
+ Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
This file is part of groff.
@@ -18,7 +19,8 @@ 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 <stdio.h>
+#include "lib.h"
+
#include <stdlib.h>
#include <assert.h>
#include <ctype.h>
@@ -29,7 +31,6 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "stringclass.h"
#include "errarg.h"
#include "error.h"
-#include "lib.h"
struct inc_number {
short inc;
@@ -127,7 +128,8 @@ public:
BOX = 04,
ALLBOX = 010,
DOUBLEBOX = 020,
- NOKEEP = 040
+ NOKEEP = 040,
+ NOSPACES = 0100
};
table(int nc, unsigned flags, int linesize, char decimal_point_char);
~table();
diff --git a/contrib/groff/src/preproc/tbl/tbl.man b/contrib/groff/src/preproc/tbl/tbl.man
index 42dac25..f661fde 100644
--- a/contrib/groff/src/preproc/tbl/tbl.man
+++ b/contrib/groff/src/preproc/tbl/tbl.man
@@ -1,5 +1,5 @@
.ig
-Copyright (C) 1989-1995, 2001 Free Software Foundation, Inc.
+Copyright (C) 1989-1995, 2001, 2002 Free Software Foundation, Inc.
Permission is granted to make and distribute verbatim copies of
this manual provided the copyright notice and this permission notice
@@ -19,14 +19,18 @@ the original English.
.TH @G@TBL @MAN1EXT@ "@MDATE@" "Groff Version @VERSION@"
.SH NAME
@g@tbl \- format tables for troff
+.
+.
.SH SYNOPSIS
.B @g@tbl
[
.B \-Cv
]
[
-.IR files \|.\|.\|.
+.IR files \|.\|.\|.\&
]
+.
+.
.SH DESCRIPTION
This manual page describes the GNU version of
.BR tbl ,
@@ -53,6 +57,8 @@ will be read.
A filename of
.B \-
will cause the standard input to be read.
+.
+.
.SH OPTIONS
.TP
.B \-C
@@ -64,47 +70,297 @@ even when followed by a character other than space or newline.
.TP
.B \-v
Print the version number.
+.
+.
.SH USAGE
-Only the differences between GNU
.B tbl
-and Unix
-.B tbl
-are described here.
-.LP
+expects to find table descriptions wrapped in the
+.B .TS
+(table start) and
+.B .TE
+(table end) macros.
+The line immediately following the
+.B .TS
+macro may contain any of the following global options (ignoring the case
+of characters -- Unix tbl only accepts options with all characters lowercase
+or all characters uppercase):
+.
+.TP
+.B center
+Centers the table (default is left-justified).
+The alternative keyword name
+.B centre
+is also recognized (this is a GNU tbl extension).
+.
+.TP
+.BI delim( xy )
+Use
+.I x
+and
+.I y
+as start and end delimiters for
+.BR @g@eqn (@MAN1EXT@).
+.
+.TP
+.B expand
+Makes the table as wide as the current line length.
+.
+.TP
+.B box
+Encloses the table in a box.
+.
+.TP
+.B doublebox
+Encloses the table in a double box.
+.
+.TP
+.B allbox
+Encloses each item of the table in a box.
+.
+.TP
+.B frame
+Same as box (GNU tbl only).
+.
+.TP
+.B doubleframe
+Same as doublebox (GNU tbl only).
+.
+.TP
+.BI tab( x )
+Uses the character
+.I x
+instead of a tab to separate items in a line of input data.
+.
+.TP
+.BI linesize( n )
+Sets lines or rules (e.g. from
+.BR box )
+in
+.IR n -point
+type.
+.
+.TP
+.B nokeep
+Don't use diversions to prevent page breaks (GNU tbl only).
Normally
.B tbl
attempts to prevent undesirable breaks in the table by using diversions.
-This can sometimes interact badly with macro packages' own use of diversions,
-when footnotes, for example, are used.
-The
-.B nokeep
-option tells
-.B tbl
-not to try and prevent breaks in this way.
+This can sometimes interact badly with macro packages' own use of
+diversions, when footnotes, for example, are used.
+.
+.TP
+.BI decimalpoint( c )
+Set the character to be recognized as the decimal point in numeric
+columns (GNU tbl only).
+.
+.TP
+.B nospaces
+Ignore leading and trailing spaces in data items (GNU tbl only).
+.
.LP
-The
-.B decimalpoint
-option specifies the character to be recognized as the decimal
-point character in place of the default period.
-It takes an argument in parentheses, which must be a single
-character, as for the
+The global options must end with a semicolon.
+There might be whitespace after an option and its argument in parentheses.
+.LP
+After global options come lines describing the format of each line of
+the table.
+Each such format line describes one line of the table itself, except that
+the last format line (which you must end with a period) describes all
+remaining lines of the table.
+A single key character describes each column of each line of the table.
+You may run format specs for multiple lines together on the same line by
+separating them with commas.
+.LP
+You may follow each key character with specifiers that determine the font
+and point size of the corresponding item, that determine column width,
+inter-column spacing, etc.
+.LP
+The longest format line defines the number of columns in the table; missing
+format descriptors at the end of format lines are assumed to be `L'.
+Extra columns in the data (which have no corresponding format entry) are
+ignored.
+.LP
+The available key characters are:
+.
+.TP
+c,C
+Centers item within the column.
+.
+.TP
+r,R
+Right-justifies item within the column.
+.
+.TP
+l,L
+Left-justifies item within the column.
+.
+.TP
+n,N
+Numerically justifies item in the column: Units positions of numbers are
+aligned vertically.
+.
+.TP
+s,S
+Spans previous item on the left into this column.
+.
+.TP
+a,A
+Centers longest line in this column and then left-justifies all other lines
+in this column with respect to that centered line.
+.
+.TP
+^
+Spans down entry from previous row in this column.
+.
+.TP
+_,-
+Replaces this entry with a horizontal line.
+.
+.TP
+=
+.
+Replaces this entry with a double horizontal line.
+.
+.TP
+|
+The corresponding column becomes a vertical rule (if two of these are
+adjacent, a double vertical rule).
+.
+.LP
+A vertical bar to the left of the first key-letter or to the right of the
+last one produces a line at the edge of the table.
+.LP
+Here are the specifiers that can appear in suffixes to column key letters:
+.
+.TP
+b,B
+Short form of fB (make affected entries bold).
+.
+.TP
+i,I
+Short form of fI (make affected entries italic).
+.
+.TP
+t,T
+Start an item vertically spanning rows at the top of its range rather than
+vertically centering it.
+.
+.TP
+d,D
+Start an item vertically spanning rows at the bottom of its range rather
+than vertically centering it (GNU tbl only).
+.
+.TP
+v,V
+Followed by a number, this indicates the vertical line spacing to be used in
+a multi-line table entry.
+If signed, the current vertical line spacing is incremented or decremented
+(using a signed number instead of a signed digit is a GNU tbl extension).
+A vertical line spacing specifier followed by a column separation number
+must be separated by one or more blanks.
+No effect if the corresponding table entry isn't a text block.
+.
+.TP
+f,F
+Either of these specifiers may be followed by a font name (either one or two
+characters long), font number (a single digit), or long name in parentheses
+(the last form is a GNU tbl extension).
+A one-letter font name must be separated by one or more blanks from whatever
+follows.
+.
+.TP
+p,P
+Followed by a number, this does a point size change for the affected fields.
+If signed, the current point size is incremented or decremented (using a
+signed number instead of a signed digit is a GNU tbl extension).
+A point size specifier followed by a column separation number must be
+separated by one or more blanks.
+.
+.TP
+w,W
+Minimal column width value.
+Must be followed either by a
+.BR @g@troff (@MAN1EXT@)
+width expression in parentheses or a unitless integer.
+If no unit is given, en units are used.
+Also used as the default line length for included text blocks.
+If used multiple times, the last entry takes effect.
+.
+.TP
+e,E
+Make equally-spaced columns.
+.
+.TP
+u,U
+Move the corresponding column up one half-line.
+.
+.TP
+z,Z
+Ignore the corresponding column for width-calculation purposes.
+.
+.LP
+A number suffix on a key character is interpreted as a column
+separation in ens (multiplied in proportion if the
+.B expand
+option is on).
+Default separation is 3n.
+.LP
+The format lines are followed by lines containing the actual data for the
+table, followed finally by
+.BR .TE .
+Within such data lines, items are normally separated by tab characters (or
+the character specified with the
.B tab
-option.
+option).
+Long input lines can be broken across multiple lines if the last character
+on the line is `\e' (which vanishes after concatenation).
.LP
-The
-.B f
-format modifier can be followed by an arbitrary length
-font name in parentheses.
-.LP
-There is a
-.B d
-format modifier which means that a vertically spanning entry
-should be aligned at the bottom of its range.
-.LP
-There is no limit on the number of columns in a table, nor any limit
-on the number of text blocks.
-All the lines of a table are considered in deciding column
-widths, not just the first 200.
+A dot starting a line, followed by anything but a digit is handled as a
+troff command, passed through without changes.
+The table position is unchanged in this case.
+.LP
+If a data line consists of only `_' or `=', a single or double line,
+respectively, is drawn across the table at that point; if a single item in a
+data line consists of only `_' or `=', then that item is replaced by a
+single or double line, joining its neighbours.
+If a data item consists only of `\e_' or `\e=', a single or double line,
+respectively, is drawn across the field at that point which does not join
+its neighbours.
+.LP
+A data item consisting only of `\eRx' (`x' any character) is replaced by
+repetitions of character `x' as wide as the column (not joining its
+neighbours).
+.LP
+A data item consisting only of `\e^' indicates that the field immediately
+above spans downward over this row.
+.LP
+A text block can be used to enter data as a single entry which would be
+too long as a simple string between tabs.
+It is started with `T{' and closed with `T}'.
+The latter must start a line, probably followed by other data columns
+(separated with tabs).
+.LP
+To change the data format within a table, use the
+.B .T&
+command (at the start of a line).
+It is followed by format and data lines (but no global options) similar to
+the
+.B .TS
+request.
+.
+.
+.SH "INTERACTION WITH @G@EQN"
+.BR @g@tbl (@MAN1EXT@)
+should always be called before
+.BR @g@eqn (@MAN1EXT@)
+.RB ( groff (@MAN1EXT@)
+automatically takes care of the correct order of preprocessors).
+.
+.
+.SH "GNU TBL ENHANCEMENTS"
+There is no limit on the number of columns in a table, nor any limit on the
+number of text blocks.
+All the lines of a table are considered in deciding column widths, not just
+the first 200.
Table continuation
.RB ( .T& )
lines are not restricted to the first 200 lines.
@@ -113,13 +369,15 @@ Numeric and alphabetic items may appear in the same column.
.LP
Numeric and alphabetic items may span horizontally.
.LP
-.B tbl
-uses register, string, macro and diversion names beginning with
+.B @g@tbl
+uses register, string, macro and diversion names beginning with the digit\~\c
.BR 3 .
When using
-.B tbl
-you should avoid using any names beginning with a
+.B @g@tbl
+you should avoid using any names beginning with a\~\c
.BR 3 .
+.
+.
.SH BUGS
You should use
.BR .TS\ H / .TH
@@ -157,7 +415,7 @@ instead of
.BR bp .
.LP
Using \ea directly in a table to get leaders will not work.
-This is correct behaviour: \ea is a
+This is correct behaviour: \ea is an
.B uninterpreted
leader.
To get leaders use a real leader, either by using a control A or like
@@ -173,6 +431,14 @@ A\e*a;B
\&.TE
.ft
.fi
+.
+.
+.SH REFERENCE
+Lesk, M.E.: "TBL -- A Program to Format Tables".
+For copyright reasons it cannot be included in the groff distribution,
+but copies can be found with a title search on the World Wide Web.
+.
+.
.SH "SEE ALSO"
.BR groff (@MAN1EXT@),
.BR @g@troff (@MAN1EXT@)
diff --git a/contrib/groff/src/roff/groff/Makefile.sub b/contrib/groff/src/roff/groff/Makefile.sub
index 42ae221..3b26caa 100644
--- a/contrib/groff/src/roff/groff/Makefile.sub
+++ b/contrib/groff/src/roff/groff/Makefile.sub
@@ -1,8 +1,8 @@
-PROG=groff
+PROG=groff$(EXEEXT)
MAN1=groff.n
XLIBS=$(LIBGROFF)
MLIB=$(LIBM)
-OBJS=groff.o pipeline.o
+OBJS=groff.$(OBJEXT) pipeline.$(OBJEXT)
CCSRCS=$(srcdir)/groff.cc
CSRCS=$(srcdir)/pipeline.c
HDRS=$(srcdir)/pipeline.h
diff --git a/contrib/groff/src/roff/groff/groff.cc b/contrib/groff/src/roff/groff/groff.cc
index 7e95c33..49104b2 100644
--- a/contrib/groff/src/roff/groff/groff.cc
+++ b/contrib/groff/src/roff/groff/groff.cc
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 1989-2000, 2001 Free Software Foundation, Inc.
+/* Copyright (C) 1989-2000, 2001, 2002 Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
This file is part of groff.
@@ -20,13 +20,12 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
// A front end for groff.
-#include <stdio.h>
-#include <string.h>
+#include "lib.h"
+
#include <stdlib.h>
#include <signal.h>
#include <errno.h>
-#include "lib.h"
#include "assert.h"
#include "errarg.h"
#include "error.h"
@@ -50,6 +49,7 @@ extern "C" {
}
#endif /* NEED_DECLARATION_PUTENV */
+// The number of commands must be in sync with MAX_COMMANDS in pipeline.h
const int SOELIM_INDEX = 0;
const int REFER_INDEX = SOELIM_INDEX + 1;
const int GRAP_INDEX = REFER_INDEX + 1;
@@ -77,6 +77,7 @@ public:
const char *get_name();
void append_arg(const char *, const char * = 0);
void insert_arg(const char *);
+ void insert_args(string s);
void clear_args();
char **get_argv();
void print(int is_last, FILE *fp);
@@ -125,7 +126,7 @@ int main(int argc, char **argv)
{ NULL, 0, 0, 0 }
};
while ((opt = getopt_long(argc, argv,
- "abCd:eEf:F:gGhiI:lL:m:M:n:No:pP:r:RsStT:UvVw:W:XzZ",
+ "abcCd:eEf:F:gGhiI:lL:m:M:n:No:pP:r:RsStT:UvVw:W:XzZ",
long_options, NULL))
!= EOF) {
char buf[3];
@@ -178,7 +179,7 @@ int main(int argc, char **argv)
vflag = 1;
{
printf("GNU groff version %s\n", Version_string);
- printf("Copyright (C) 1989-2001 Free Software Foundation, Inc.\n"
+ printf("Copyright (C) 2002 Free Software Foundation, Inc.\n"
"GNU groff comes with ABSOLUTELY NO WARRANTY.\n"
"You may redistribute copies of groff and its subprograms\n"
"under the terms of the GNU General Public License.\n"
@@ -208,6 +209,9 @@ int main(int argc, char **argv)
case 'b':
commands[TROFF_INDEX].append_arg(buf);
break;
+ case 'c':
+ commands[TROFF_INDEX].append_arg(buf);
+ break;
case 'S':
safer_flag = 1;
break;
@@ -280,19 +284,14 @@ int main(int argc, char **argv)
fatal("invalid device `%1'", device);
if (!postdriver)
fatal("no `postpro' command in DESC file for device `%1'", device);
-
- if (predriver) {
+ if (predriver && !zflag) {
commands[TROFF_INDEX].insert_arg(commands[TROFF_INDEX].get_name());
- const char *p = Pargs.contents();
- const char *end = p + Pargs.length();
- while (p < end) {
- // pass the device arguments to the predrivers as well
- commands[TROFF_INDEX].insert_arg(p);
- p = strchr(p, '\0') + 1;
- }
commands[TROFF_INDEX].set_name(predriver);
+ // pass the device arguments to the predrivers as well
+ commands[TROFF_INDEX].insert_args(Pargs);
+ if (vflag)
+ commands[TROFF_INDEX].insert_arg("-v");
}
-
const char *real_driver = 0;
if (Xflag) {
real_driver = postdriver;
@@ -549,6 +548,27 @@ void possible_command::insert_arg(const char *s)
args = str;
}
+void possible_command::insert_args(string s)
+{
+ const char *p = s.contents();
+ const char *end = p + s.length();
+ int l = 0;
+ if (p >= end)
+ return;
+ // find the total number of arguments in our string
+ do {
+ l++;
+ p = strchr(p, '\0') + 1;
+ } while (p < end);
+ // now insert each argument preserving the order
+ for (int i = l - 1; i >= 0; i--) {
+ p = s.contents();
+ for (int j = 0; j < i; j++)
+ p = strchr(p, '\0') + 1;
+ insert_arg(p);
+ }
+}
+
void possible_command::build_argv()
{
if (argv)
@@ -658,7 +678,7 @@ char **possible_command::get_argv()
void synopsis(FILE *stream)
{
fprintf(stream,
-"usage: %s [-abeghilpstvzCENRSUVXZ] [-Fdir] [-mname] [-Tdev] [-ffam]\n"
+"usage: %s [-abceghilpstvzCENRSUVXZ] [-Fdir] [-mname] [-Tdev] [-ffam]\n"
" [-wname] [-Wname] [-Mdir] [-dcs] [-rcn] [-nnum] [-olist] [-Parg]\n"
" [-Larg] [-Idir] [files...]\n",
program_name);
@@ -696,6 +716,7 @@ void help()
"-E\tinhibit all errors\n"
"-b\tprint backtraces with errors or warnings\n"
"-l\tspool the output\n"
+"-c\tdisable color output\n"
"-C\tenable compatibility mode\n"
"-V\tprint commands on stdout instead of running them\n"
"-Parg\tpass arg to the postprocessor\n"
diff --git a/contrib/groff/src/roff/groff/pipeline.c b/contrib/groff/src/roff/groff/pipeline.c
index f26608f..59480dd 100644
--- a/contrib/groff/src/roff/groff/pipeline.c
+++ b/contrib/groff/src/roff/groff/pipeline.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001
+/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001, 2002
Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
@@ -18,14 +18,9 @@ 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. */
-/*
-Compile options are:
-
--DWCOREFLAG=0200 (or whatever)
--DHAVE_SYS_SIGLIST
--DSYS_SIGLIST_DECLARED
--DHAVE_UNISTD_H
-*/
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
#include <stdio.h>
#include <signal.h>
@@ -41,6 +36,14 @@ Compile options are:
extern char *strerror();
#endif
+#ifndef HAVE_STRCASECMP
+#define strcasecmp(a,b) strcmp((a),(b))
+#endif
+
+#ifndef HAVE_STRNCASECMP
+#define strncasecmp(a,b,c) strncmp((a),(b),(c))
+#endif
+
#ifdef _POSIX_VERSION
#include <sys/wait.h>
@@ -104,7 +107,8 @@ static char *i_to_a P((int));
via temporary files... */
#if defined(__MSDOS__) \
- || (defined(_WIN32) && !defined(_UWIN) && !defined(__CYGWIN32__))
+ || (defined(_WIN32) && !defined(_UWIN) && !defined(__CYGWIN__)) \
+ || defined(__EMX__)
#include <process.h>
#include <fcntl.h>
diff --git a/contrib/groff/src/roff/groff/pipeline.h b/contrib/groff/src/roff/groff/pipeline.h
index abb4b0c..52bff85 100644
--- a/contrib/groff/src/roff/groff/pipeline.h
+++ b/contrib/groff/src/roff/groff/pipeline.h
@@ -1,4 +1,5 @@
-/* Copyright (C) 1989, 1990, 1991, 1992, 2000 Free Software Foundation, Inc.
+/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2002
+ Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
This file is part of groff.
@@ -24,7 +25,7 @@ extern "C" {
#endif
/* run_pipeline can handle at most this many commands */
-#define MAX_COMMANDS 10
+#define MAX_COMMANDS 12
/* Children exit with this status if execvp fails. */
#define EXEC_FAILED_EXIT_STATUS 0xff
diff --git a/contrib/groff/src/roff/grog/Makefile.sub b/contrib/groff/src/roff/grog/Makefile.sub
index 85e2ad5..d199ac9 100644
--- a/contrib/groff/src/roff/grog/Makefile.sub
+++ b/contrib/groff/src/roff/grog/Makefile.sub
@@ -3,7 +3,14 @@ CLEANADD=grog
all: grog
-grog: grog.pl grog.sh
+grog: grog.sh
+ rm -f $@
+ sed -e "s|@g@|$(g)|g" \
+ -e "s|@VERSION@|$(version)$(revision)|" \
+ -e $(SH_SCRIPT_SED_CMD) $(srcdir)/grog.sh >$@
+ chmod +x $@
+
+grog.old: grog.pl grog.sh
if test -n "$(PERLPATH)" && test -f "$(PERLPATH)"; then \
rm -f $@; \
sed -e "s|/usr/bin/perl|$(PERLPATH)|" \
diff --git a/contrib/groff/src/roff/grog/grog.man b/contrib/groff/src/roff/grog/grog.man
index 8cd0bb2..e1ab74e 100644
--- a/contrib/groff/src/roff/grog/grog.man
+++ b/contrib/groff/src/roff/grog/grog.man
@@ -1,5 +1,5 @@
.ig
-Copyright (C) 1989-2000, 2001 Free Software Foundation, Inc.
+Copyright (C) 1989-2000, 2001, 2002 Free Software Foundation, Inc.
Permission is granted to make and distribute verbatim copies of
this manual provided the copyright notice and this permission notice
@@ -23,10 +23,10 @@ grog \- guess options for groff command
.B grog
[
.BI \- option
-\|.\|.\|.
+\|.\|.\|.\&
]
[
-.IR files \|.\|.\|.
+.IR files\ \|.\|.\|.\&
]
.SH DESCRIPTION
.B grog
@@ -39,6 +39,7 @@ options
.BR \-man ,
.BR \-me ,
.BR \-mm ,
+.BR \-mom ,
.BR \-ms ,
.BR \-mdoc,
.BR \-mdoc-old,
diff --git a/contrib/groff/src/roff/grog/grog.pl b/contrib/groff/src/roff/grog/grog.pl
index a61106c..07fa7a4 100644
--- a/contrib/groff/src/roff/grog/grog.pl
+++ b/contrib/groff/src/roff/grog/grog.pl
@@ -19,13 +19,9 @@ while ($ARGV[0] =~ /^-./) {
push(@command, $arg);
}
-if (@ARGV) {
- foreach $arg (@ARGV) {
- &process($arg, 0);
- }
-}
-else {
- &process("-", 0);
+@ARGV = ('-') unless @ARGV;
+foreach $arg (@ARGV) {
+ &process($arg, 0);
}
sub process {
@@ -81,10 +77,18 @@ sub process {
}
}
}
- elsif (/^\.R1$sp/ || /^\.\[$sp/) {
+ elsif (/^\.R1$sp/) {
$refer++;
$soelim++ if $level;
}
+ elsif (/^\.\[/) {
+ $refer_open++;
+ $soelim++ if $level;
+ }
+ elsif (/^\.\]/) {
+ $refer_close++;
+ $soelim++ if $level;
+ }
elsif (/^\.[PLI]P$sp/) {
$PP++;
}
@@ -144,6 +148,9 @@ sub process {
}
redo;
}
+ elsif (/^\.(PRINTSTYLE|START)$sp/) {
+ $mom++;
+ }
if (/^\.so$sp/) {
chop;
s/^.so *//;
@@ -166,6 +173,8 @@ sub help {
exit 0;
}
+$refer ||= $refer_open && $refer_close;
+
if ($pic || $tbl || $eqn || $grn || $grap || $refer) {
$s = "-";
$s .= "s" if $soelim;
@@ -185,6 +194,9 @@ if ($me > 0) {
elsif ($SH > 0 && $TH > 0) {
push(@command, "-man");
}
+else ($mom > 0) {
+ push(@command, "-mom");
+}
elsif ($PP > 0) {
push(@command, "-ms");
}
diff --git a/contrib/groff/src/roff/grog/grog.sh b/contrib/groff/src/roff/grog/grog.sh
index ae269af..3999d77 100644
--- a/contrib/groff/src/roff/grog/grog.sh
+++ b/contrib/groff/src/roff/grog/grog.sh
@@ -29,19 +29,21 @@ do
esac
done
-egrep -h "^\.(P|PS|[PLI]P|[pnil]p|sh|Dd|Tp|Dp|De|Cx|Cl|Oo|.* Oo|Oc|.* Oc|TS|EQ|TH|SH|so|\[|R1|GS|G1|PH|SA)$sp" $* \
+egrep -h "^\.(\[|\])|((P|PS|[PLI]P|[pnil]p|sh|Dd|Tp|Dp|De|Cx|Cl|Oo|.* Oo|Oc|.* Oc|TS|EQ|TH|SH|so|\[|R1|GS|G1|PH|SA)$sp)" $* \
| sed -e '/^\.so/s/^.*$/.SO_START\
&\
.SO_END/' \
| $soelim \
-| egrep '^\.(P|PS|[PLI]P|[pnil]p|sh|Dd|Tp|Dp|De|Cx|Cl|Oo|.* Oo|Oc|.* Oc|TS|EQ|TH|SH|\[|R1|GS|G1|PH|SA|SO_START|SO_END)' \
+| egrep '^\.(P|PS|[PLI]P|[pnil]p|sh|Dd|Tp|Dp|De|Cx|Cl|Oo|.* Oo|Oc|.* Oc|TS|EQ|TH|SH|\[|\]|R1|GS|G1|PH|SA|SO_START|SO_END)' \
| awk '
/^\.SO_START$/ { so = 1 }
/^\.SO_END$/ { so = 0 }
/^\.TS/ { tbl++; if (so > 0) soelim++ }
/^\.PS([ 0-9.<].*)?$/ { pic++; if (so > 0) soelim++ }
/^\.EQ/ { eqn++; if (so > 0) soelim++ }
-/^\.(R1|\[)/ { refer++; if (so > 0) soelim++ }
+/^\.R1/ { refer++; if (so > 0) soelim++ }
+/^\.\[/ {refer_start++; if (so > 0) soelim++ }
+/^\.\]/ {refer_end++; if (so > 0) soelim++ }
/^\.GS/ { grn++; if (so > 0) soelim++ }
/^\.G1/ { grap++; pic++; if (so > 0) soelim++ }
/^\.TH/ { TH++ }
@@ -69,11 +71,13 @@ egrep -h "^\.(P|PS|[PLI]P|[pnil]p|sh|Dd|Tp|Dp|De|Cx|Cl|Oo|.* Oo|Oc|.* Oc|TS|EQ|T
Oo--
}
}
+/^\.(PRINTSTYLE|START)/ { mom++ }
END {
if (files ~ /^-/)
files = "-- " files
printf "groff"
+ refer = refer || (refer_start && refer_end)
if (pic > 0 || tbl > 0 || grn > 0 || grap > 0 || eqn > 0 || refer > 0) {
printf " -"
if (soelim > 0) printf "s"
@@ -88,6 +92,8 @@ END {
printf " -me"
else if (SH > 0 && TH > 0)
printf " -man"
+ else if (mom > 0)
+ printf " -mom"
else if (PP > 0)
printf " -ms"
else if (P > 0 || mm > 0)
diff --git a/contrib/groff/src/roff/troff/Makefile.sub b/contrib/groff/src/roff/troff/Makefile.sub
index e883959..e889cdd 100644
--- a/contrib/groff/src/roff/troff/Makefile.sub
+++ b/contrib/groff/src/roff/troff/Makefile.sub
@@ -1,17 +1,17 @@
-PROG=troff
+PROG=troff$(EXEEXT)
MAN1=troff.n
XLIBS=$(LIBGROFF)
MLIB=$(LIBM)
OBJS=\
- env.o \
- node.o \
- input.o \
- div.o \
- symbol.o \
- dictionary.o \
- reg.o \
- number.o \
- majorminor.o
+ env.$(OBJEXT) \
+ node.$(OBJEXT) \
+ input.$(OBJEXT) \
+ div.$(OBJEXT) \
+ symbol.$(OBJEXT) \
+ dictionary.$(OBJEXT) \
+ reg.$(OBJEXT) \
+ number.$(OBJEXT) \
+ majorminor.$(OBJEXT)
CCSRCS=\
$(srcdir)/env.cc \
$(srcdir)/node.cc \
diff --git a/contrib/groff/src/roff/troff/TODO b/contrib/groff/src/roff/troff/TODO
index 6660597..49aa0eb 100644
--- a/contrib/groff/src/roff/troff/TODO
+++ b/contrib/groff/src/roff/troff/TODO
@@ -83,9 +83,6 @@ Then is you ask for R at pointsize 16, groff will first look for
R.display and then R. Probably necessary to be able to specify a
separate unitwidth for each sizesuffix (eg. for X).
-Variant of `.it' for which a line interrupted with \c counts as one
-input line.
-
Make it possible to suppress hyphenation on a word-by-word basis.
(Perhaps store hyphenation flags in tfont.)
diff --git a/contrib/groff/src/roff/troff/charinfo.h b/contrib/groff/src/roff/troff/charinfo.h
index a4ecd57..b907ae4 100644
--- a/contrib/groff/src/roff/troff/charinfo.h
+++ b/contrib/groff/src/roff/troff/charinfo.h
@@ -1,5 +1,6 @@
// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+/* Copyright (C) 1989, 1990, 1991, 1992, 2001, 2002
+ Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
This file is part of groff.
@@ -30,9 +31,13 @@ class charinfo {
unsigned char hyphenation_code;
unsigned char flags;
unsigned char ascii_code;
+ unsigned char asciify_code;
char not_found;
- char transparent_translate; // non-zero means translation applies to
+ char transparent_translate; // non-zero means translation applies
// to transparent throughput
+ char translate_input; // non-zero means that asciify_code is
+ // active for .asciify (set by .trin)
+ char fallback;
public:
enum {
ENDS_SENTENCE = 1,
@@ -61,19 +66,24 @@ public:
int transparent();
unsigned char get_hyphenation_code();
unsigned char get_ascii_code();
+ unsigned char get_asciify_code();
void set_hyphenation_code(unsigned char);
void set_ascii_code(unsigned char);
+ void set_asciify_code(unsigned char);
+ void set_translation_input();
+ int get_translation_input();
charinfo *get_translation(int = 0);
- void set_translation(charinfo *, int);
+ void set_translation(charinfo *, int, int);
void set_flags(unsigned char);
void set_special_translation(int, int);
int get_special_translation(int = 0);
- macro *set_macro(macro *);
+ macro *set_macro(macro *, int = 0);
macro *get_macro();
int first_time_not_found();
void set_number(int);
int get_number();
int numbered();
+ int is_fallback();
symbol *get_symbol();
};
@@ -116,6 +126,11 @@ inline int charinfo::numbered()
return flags & NUMBERED;
}
+inline int charinfo::is_fallback()
+{
+ return fallback;
+}
+
inline charinfo *charinfo::get_translation(int transparent_throughput)
{
return (transparent_throughput && !transparent_translate
@@ -133,6 +148,11 @@ inline unsigned char charinfo::get_ascii_code()
return ascii_code;
}
+inline unsigned char charinfo::get_asciify_code()
+{
+ return (translate_input ? asciify_code : 0);
+}
+
inline void charinfo::set_flags(unsigned char c)
{
flags = c;
@@ -143,6 +163,16 @@ inline int charinfo::get_index()
return index;
}
+inline void charinfo::set_translation_input()
+{
+ translate_input = 1;
+}
+
+inline int charinfo::get_translation_input()
+{
+ return translate_input;
+}
+
inline int charinfo::get_special_translation(int transparent_throughput)
{
return (transparent_throughput && !transparent_translate
diff --git a/contrib/groff/src/roff/troff/dictionary.cc b/contrib/groff/src/roff/troff/dictionary.cc
index bca3845..a70ebb0 100644
--- a/contrib/groff/src/roff/troff/dictionary.cc
+++ b/contrib/groff/src/roff/troff/dictionary.cc
@@ -138,7 +138,7 @@ int dictionary_iterator::get(symbol *sp, void **vp)
}
object_dictionary_iterator::object_dictionary_iterator(object_dictionary &od)
- : di(od.d)
+: di(od.d)
{
}
diff --git a/contrib/groff/src/roff/troff/div.cc b/contrib/groff/src/roff/troff/div.cc
index c885ca8..14c7399 100644
--- a/contrib/groff/src/roff/troff/div.cc
+++ b/contrib/groff/src/roff/troff/div.cc
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001
+/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001, 2002
Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
@@ -410,7 +410,7 @@ void top_level_diversion::output(node *nd, int retain_size,
void top_level_diversion::transparent_output(unsigned char c)
{
if (before_first_page && begin_page())
- // This can only happen with the transparent() request.
+ // This can only happen with the .output request.
fatal("sorry, I didn't manage to begin the first page in time: use an explicit .br request");
const char *s = asciify(c);
while (*s)
@@ -467,7 +467,7 @@ void top_level_diversion::space(vunits n, int forced)
}
trap::trap(symbol s, vunits n, trap *p)
- : next(p), position(n), nm(s)
+: next(p), position(n), nm(s)
{
}
@@ -641,7 +641,7 @@ void page_offset()
n = topdiv->prev_page_offset;
topdiv->prev_page_offset = topdiv->page_offset;
topdiv->page_offset = n;
- curenv->add_html_tag(".po", n.to_units());
+ curenv->add_html_tag(0, ".po", n.to_units());
skip_line();
}
@@ -760,7 +760,7 @@ void space_request()
else
// The line might have had line spacing that was truncated.
truncated_space += n;
- curenv->add_html_tag(".sp", n.to_units());
+ curenv->add_html_tag(1, ".sp", n.to_units());
tok.next();
}
@@ -769,7 +769,7 @@ void blank_line()
curenv->do_break();
if (!trap_sprung_flag && !curdiv->no_space_mode) {
curdiv->space(curenv->get_vertical_spacing());
- curenv->add_html_tag(".sp", 1);
+ curenv->add_html_tag(1, ".sp", 1);
} else
truncated_space += curenv->get_vertical_spacing();
}
@@ -791,8 +791,13 @@ void need_space()
void page_number()
{
int n;
- if (has_arg() && get_integer(&n, topdiv->get_page_number()))
- topdiv->set_next_page_number(n);
+
+ // the ps4html register is set if we are using -Tps
+ // to generate images for html
+ reg *r = (reg *)number_reg_dictionary.lookup("ps4html");
+ if (r == NULL)
+ if (has_arg() && get_integer(&n, topdiv->get_page_number()))
+ topdiv->set_next_page_number(n);
skip_line();
}
@@ -828,7 +833,7 @@ void flush_output()
curenv->do_break();
if (the_output)
the_output->flush();
- curenv->add_html_tag(".fl");
+ curenv->add_html_tag(1, ".fl");
tok.next();
}
diff --git a/contrib/groff/src/roff/troff/div.h b/contrib/groff/src/roff/troff/div.h
index 3b726c3..31b9af3 100644
--- a/contrib/groff/src/roff/troff/div.h
+++ b/contrib/groff/src/roff/troff/div.h
@@ -152,5 +152,7 @@ void push_page_ejector();
void continue_page_eject();
void handle_first_page_transition();
void blank_line();
+void begin_page();
+void end_diversions();
extern void cleanup_and_exit(int);
diff --git a/contrib/groff/src/roff/troff/env.cc b/contrib/groff/src/roff/troff/env.cc
index c0743441..40c9e3c 100644
--- a/contrib/groff/src/roff/troff/env.cc
+++ b/contrib/groff/src/roff/troff/env.cc
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001
+/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001, 2002
Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
@@ -31,6 +31,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "reg.h"
#include "charinfo.h"
#include "macropath.h"
+#include "input.h"
#include <math.h>
symbol default_family("T");
@@ -299,7 +300,8 @@ node *environment::make_char_node(charinfo *ci)
void environment::add_node(node *n)
{
- assert(n != 0);
+ if (n == 0)
+ return;
if (current_tab || current_field)
n->freeze_space();
if (interrupted) {
@@ -392,7 +394,7 @@ void environment::space_newline()
width_total += x;
return;
}
- add_node(new word_space_node(x, w));
+ add_node(new word_space_node(x, get_fill_color(), w));
possibly_break_line(0, spread_flag);
spread_flag = 0;
}
@@ -426,6 +428,7 @@ void environment::space(hunits space_width, hunits sentence_space_width)
return;
}
add_node(new word_space_node(x,
+ get_fill_color(),
new width_list(space_width,
sentence_space_width)));
possibly_break_line(0, spread_flag);
@@ -438,7 +441,7 @@ void environment::set_font(symbol nm)
{
if (interrupted)
return;
- if (nm == symbol("P")) {
+ if (nm == symbol("P") || nm.is_empty()) {
if (family->make_definite(prev_fontno) < 0)
return;
int tem = fontno;
@@ -479,7 +482,9 @@ void environment::set_font(int n)
void environment::set_family(symbol fam)
{
- if (fam.is_null()) {
+ if (interrupted)
+ return;
+ if (fam.is_null() || fam.is_empty()) {
if (prev_family->make_definite(fontno) < 0)
return;
font_family *tem = family;
@@ -532,6 +537,42 @@ void environment::set_char_slant(int n)
char_slant = n;
}
+color *environment::get_prev_glyph_color()
+{
+ return prev_glyph_color;
+}
+
+color *environment::get_glyph_color()
+{
+ return glyph_color;
+}
+
+color *environment::get_prev_fill_color()
+{
+ return prev_fill_color;
+}
+
+color *environment::get_fill_color()
+{
+ return fill_color;
+}
+
+void environment::set_glyph_color(color *c)
+{
+ if (interrupted)
+ return;
+ curenv->prev_glyph_color = curenv->glyph_color;
+ curenv->glyph_color = c;
+}
+
+void environment::set_fill_color(color *c)
+{
+ if (interrupted)
+ return;
+ curenv->prev_fill_color = curenv->fill_color;
+ curenv->fill_color = c;
+}
+
environment::environment(symbol nm)
: dummy(0),
prev_line_length((units_per_inch*13)/2),
@@ -565,6 +606,7 @@ environment::environment(symbol nm)
underline_lines(0),
underline_spaces(0),
input_trap_count(0),
+ continued_input_trap(0),
line(0),
prev_text_length(0),
width_total(0),
@@ -597,9 +639,12 @@ environment::environment(symbol nm)
#ifdef WIDOW_CONTROL
widow_control(0),
#endif /* WIDOW_CONTROL */
- need_eol(0),
ignore_next_eol(0),
emitted_node(0),
+ glyph_color(&default_color),
+ prev_glyph_color(&default_color),
+ fill_color(&default_color),
+ prev_fill_color(&default_color),
name(nm),
control_char('.'),
no_break_control_char('\''),
@@ -651,6 +696,7 @@ environment::environment(const environment *e)
underline_lines(0),
underline_spaces(0),
input_trap_count(0),
+ continued_input_trap(0),
line(0),
prev_text_length(e->prev_text_length),
width_total(0),
@@ -683,8 +729,12 @@ environment::environment(const environment *e)
#ifdef WIDOW_CONTROL
widow_control(e->widow_control),
#endif /* WIDOW_CONTROL */
- need_eol(0),
ignore_next_eol(0),
+ emitted_node(0),
+ glyph_color(e->glyph_color),
+ prev_glyph_color(e->prev_glyph_color),
+ fill_color(e->fill_color),
+ prev_fill_color(e->prev_fill_color),
name(e->name), // so that eg `.if "\n[.ev]"0"' works
control_char(e->control_char),
no_break_control_char(e->no_break_control_char),
@@ -725,6 +775,7 @@ void environment::copy(const environment *e)
underline_lines = 0;
underline_spaces = 0;
input_trap_count = 0;
+ continued_input_trap = 0;
prev_text_length = e->prev_text_length;
width_total = 0;
space_total = 0;
@@ -765,6 +816,12 @@ void environment::copy(const environment *e)
hyphenation_space = e->hyphenation_space;
hyphenation_margin = e->hyphenation_margin;
composite = 0;
+ ignore_next_eol = e->ignore_next_eol;
+ emitted_node = e->emitted_node;
+ glyph_color= e->glyph_color;
+ prev_glyph_color = e->prev_glyph_color;
+ fill_color = e->fill_color;
+ prev_fill_color = e->prev_fill_color;
}
environment::~environment()
@@ -1107,13 +1164,54 @@ void point_size()
if (n <= 0)
n = 1;
curenv->set_size(n);
- curenv->add_html_tag(".ps", n);
+ curenv->add_html_tag(1, ".ps", n);
}
else
curenv->set_size(0);
skip_line();
}
+void override_sizes()
+{
+ int n = 16;
+ int *sizes = new int[n];
+ int i = 0;
+ char *buf = read_string();
+ if (!buf)
+ return;
+ char *p = strtok(buf, " \t");
+ for (;;) {
+ if (!p)
+ break;
+ int lower, upper;
+ switch (sscanf(p, "%d-%d", &lower, &upper)) {
+ case 1:
+ upper = lower;
+ // fall through
+ case 2:
+ if (lower <= upper && lower >= 0)
+ break;
+ // fall through
+ default:
+ warning(WARN_RANGE, "bad size range `%1'", p);
+ return;
+ }
+ if (i + 2 > n) {
+ int *old_sizes = sizes;
+ sizes = new int[n*2];
+ memcpy(sizes, old_sizes, n*sizeof(int));
+ n *= 2;
+ a_delete old_sizes;
+ }
+ sizes[i++] = lower;
+ if (lower == 0)
+ break;
+ sizes[i++] = upper;
+ p = strtok(0, " \t");
+ }
+ font_size::init_size_table(sizes);
+}
+
void space_size()
{
int n;
@@ -1134,7 +1232,8 @@ void fill()
if (break_flag)
curenv->do_break();
curenv->fill = 1;
- curenv->add_html_tag(".fi");
+ curenv->add_html_tag(1, ".fi");
+ curenv->add_html_tag(0, ".br");
tok.next();
}
@@ -1144,11 +1243,10 @@ void no_fill()
tok.next();
if (break_flag)
curenv->do_break();
-
curenv->fill = 0;
- curenv->add_html_tag(".nf");
- curenv->ignore_next_eol = 1;
- curenv->add_html_tag(".po", topdiv->get_page_offset().to_units());
+ curenv->add_html_tag(1, ".nf");
+ curenv->add_html_tag(0, ".br");
+ curenv->add_html_tag(0, ".po", topdiv->get_page_offset().to_units());
tok.next();
}
@@ -1165,7 +1263,7 @@ void center()
curenv->do_break();
curenv->right_justify_lines = 0;
curenv->center_lines = n;
- curenv->add_html_tag(".ce", n);
+ curenv->add_html_tag(1, ".ce", n);
tok.next();
}
@@ -1182,7 +1280,7 @@ void right_justify()
curenv->do_break();
curenv->center_lines = 0;
curenv->right_justify_lines = n;
- curenv->add_html_tag(".rj", n);
+ curenv->add_html_tag(1, ".rj", n);
tok.next();
}
@@ -1199,7 +1297,7 @@ void line_length()
temp = curenv->prev_line_length;
curenv->prev_line_length = curenv->line_length;
curenv->line_length = temp;
- curenv->add_html_tag(".ll", temp.to_units());
+ curenv->add_html_tag(1, ".ll", temp.to_units());
skip_line();
}
@@ -1286,7 +1384,8 @@ void indent()
curenv->have_temporary_indent = 0;
curenv->prev_indent = curenv->indent;
curenv->indent = temp;
- curenv->add_html_tag(".in", temp.to_units());
+ if (break_flag)
+ curenv->add_html_tag(1, ".in", temp.to_units());
tok.next();
}
@@ -1307,7 +1406,7 @@ void temporary_indent()
if (!err) {
curenv->temporary_indent = temp;
curenv->have_temporary_indent = 1;
- curenv->add_html_tag(".ti", temp.to_units());
+ curenv->add_html_tag(1, ".ti", temp.to_units());
}
tok.next();
}
@@ -1562,6 +1661,11 @@ void environment::newline()
if (x > H0)
saved_indent += x/2;
to_be_output = line;
+ if (is_html) {
+ node *n = make_html_tag("eol.ce");
+ n->next = to_be_output;
+ to_be_output = n;
+ }
to_be_output_width = width_total;
line = 0;
}
@@ -1583,12 +1687,21 @@ void environment::newline()
}
input_line_start = line == 0 ? H0 : width_total;
if (to_be_output) {
+ if (is_html && !fill) {
+ if (curdiv == topdiv) {
+ node *n = make_html_tag("eol");
+
+ n->next = to_be_output;
+ to_be_output = n;
+ }
+ }
output_line(to_be_output, to_be_output_width);
hyphen_line_count = 0;
}
if (input_trap_count > 0) {
- if (--input_trap_count == 0)
- spring_trap(input_trap);
+ if (!(continued_input_trap && prev_line_interrupted))
+ if (--input_trap_count == 0)
+ spring_trap(input_trap);
}
}
@@ -1598,7 +1711,7 @@ void environment::output_line(node *n, hunits width)
if (margin_character_flags) {
hunits d = line_length + margin_character_distance - saved_indent - width;
if (d > 0) {
- n = new hmotion_node(d, n);
+ n = new hmotion_node(d, get_fill_color(), n);
width += d;
}
margin_character_flags &= ~MARGIN_CHARACTER_NEXT;
@@ -1621,7 +1734,7 @@ void environment::output_line(node *n, hunits width)
n = tem;
}
if (!saved_indent.is_zero())
- nn = new hmotion_node(saved_indent, nn);
+ nn = new hmotion_node(saved_indent, get_fill_color(), nn);
width += saved_indent;
if (no_number_count > 0)
--no_number_count;
@@ -1629,11 +1742,11 @@ void environment::output_line(node *n, hunits width)
hunits w = (line_number_digit_width
*(3+line_number_indent+number_text_separation));
if (next_line_number % line_number_multiple != 0)
- nn = new hmotion_node(w, nn);
+ nn = new hmotion_node(w, get_fill_color(), nn);
else {
hunits x = w;
- nn = new hmotion_node(number_text_separation*line_number_digit_width,
- nn);
+ nn = new hmotion_node(number_text_separation * line_number_digit_width,
+ get_fill_color(), nn);
x -= number_text_separation*line_number_digit_width;
char buf[30];
sprintf(buf, "%3d", next_line_number);
@@ -1646,7 +1759,7 @@ void environment::output_line(node *n, hunits width)
gn->next = nn;
nn = gn;
}
- nn = new hmotion_node(x, nn);
+ nn = new hmotion_node(x, get_fill_color(), nn);
}
width += w;
++next_line_number;
@@ -1789,7 +1902,7 @@ breakpoint *environment::choose_breakpoint()
}
if (best_bp) {
if (!best_bp_fits)
- warning(WARN_BREAK, "can't break line");
+ output_warning(WARN_BREAK, "can't break line");
return best_bp;
}
return 0;
@@ -1875,6 +1988,14 @@ static void distribute_space(node *n, int nspaces, hunits desired_space,
static int reverse = 0;
if (force_reverse || reverse)
n = node_list_reverse(n);
+ if (!force_reverse && nspaces > 0 && spread_limit >= 0
+ && desired_space.to_units() > 0) {
+ hunits em = curenv->get_size();
+ double Ems = (double)desired_space.to_units() / nspaces
+ / (em.is_zero() ? hresolution : em.to_units());
+ if (Ems > spread_limit)
+ output_warning(WARN_BREAK, "spreading %1m per space", Ems);
+ }
for (node *tem = n; tem; tem = tem->next)
tem->spread_space(&nspaces, &desired_space);
if (force_reverse || reverse)
@@ -1909,6 +2030,9 @@ void environment::possibly_break_line(int start_here, int forced)
case ADJUST_BOTH:
if (bp->nspaces != 0)
extra_space_width = target_text_length - bp->width;
+ else if (bp->width > 0 && target_text_length > 0
+ && target_text_length > bp->width)
+ output_warning(WARN_BREAK, "cannot adjust line");
break;
case ADJUST_CENTER:
saved_indent += (target_text_length - bp->width)/2;
@@ -2013,32 +2137,15 @@ void environment::final_break()
}
/*
- * add_html_tag_eol - add an end of line tag if appropriate.
- */
-
-void environment::add_html_tag_eol()
-{
- if (is_html) {
- if (ignore_next_eol > 0)
- ignore_next_eol--;
- else if (need_eol > 0) {
- need_eol--;
- add_html_tag("eol");
- }
- else if (!fill && emitted_node) {
- add_html_tag("eol");
- emitted_node = 0;
- }
- }
-}
-
-/*
* add_html_tag - emits a special html-tag: to help post-grohtml understand
* the key troff commands
*/
-void environment::add_html_tag(const char *name)
+void environment::add_html_tag(int force, const char *name)
{
+ if (!force && (curdiv != topdiv))
+ return;
+
if (is_html) {
/*
* need to emit tag for post-grohtml
@@ -2049,9 +2156,11 @@ void environment::add_html_tag(const char *name)
macro *m = new macro;
m->append_str("html-tag:");
for (const char *p = name; *p; p++)
- if (!illegal_input_char((unsigned char)*p))
+ if (!invalid_input_char((unsigned char)*p))
m->append(*p);
- add_node(new special_node(*m));
+ curdiv->output(new special_node(*m), 1, 0, 0, 0);
+ if (strcmp(name, ".nf") == 0)
+ curenv->ignore_next_eol = 1;
}
}
@@ -2061,18 +2170,12 @@ void environment::add_html_tag(const char *name)
* of i.
*/
-void environment::add_html_tag(const char *name, int i)
+void environment::add_html_tag(int force, const char *name, int i)
{
- if (is_html) {
- if (strcmp(name, ".ce") == 0) {
- if (i == 0)
- need_eol = 0;
- else {
- need_eol = i;
- ignore_next_eol = 1; // since the .ce creates an eol
- }
- }
+ if (!force && (curdiv != topdiv))
+ return;
+ if (is_html) {
/*
* need to emit tag for post-grohtml
* but we check to see whether we can emit specials
@@ -2082,13 +2185,12 @@ void environment::add_html_tag(const char *name, int i)
macro *m = new macro;
m->append_str("html-tag:");
for (const char *p = name; *p; p++)
- if (!illegal_input_char((unsigned char)*p))
+ if (!invalid_input_char((unsigned char)*p))
m->append(*p);
m->append(' ');
m->append_int(i);
- // output_pending_lines();
- output(new special_node(*m), !fill, 0, 0, 0);
- // output_pending_lines();
+ node *n = new special_node(*m);
+ curdiv->output(n, 1, 0, 0, 0);
}
}
@@ -2096,8 +2198,11 @@ void environment::add_html_tag(const char *name, int i)
* add_html_tag_tabs - emits the tab settings for post-grohtml
*/
-void environment::add_html_tag_tabs()
+void environment::add_html_tag_tabs(int force)
{
+ if (!force && (curdiv != topdiv))
+ return;
+
if (is_html) {
/*
* need to emit tag for post-grohtml
@@ -2115,24 +2220,62 @@ void environment::add_html_tag_tabs()
switch (t) {
case TAB_LEFT:
m->append_str(" L ");
- m->append_int(d.to_units());
+ m->append_int(l.to_units());
break;
case TAB_CENTER:
m->append_str(" C ");
- m->append_int(d.to_units());
+ m->append_int(l.to_units());
break;
case TAB_RIGHT:
m->append_str(" R ");
- m->append_int(d.to_units());
+ m->append_int(l.to_units());
break;
case TAB_NONE:
break;
}
} while ((t != TAB_NONE) && (l < get_line_length()));
- output_pending_lines();
- output(new special_node(*m), !fill, 0, 0, 0);
- output_pending_lines();
+ curdiv->output(new special_node(*m), 1, 0, 0, 0);
+ }
+}
+
+node *environment::make_html_tag(const char *name, int i)
+{
+ if (is_html) {
+ /*
+ * need to emit tag for post-grohtml
+ * but we check to see whether we can emit specials
+ */
+ if (curdiv == topdiv && topdiv->before_first_page)
+ topdiv->begin_page();
+ macro *m = new macro;
+ m->append_str("html-tag:");
+ for (const char *p = name; *p; p++)
+ if (!invalid_input_char((unsigned char)*p))
+ m->append(*p);
+ m->append(' ');
+ m->append_int(i);
+ return new special_node(*m);
}
+ return 0;
+}
+
+node *environment::make_html_tag(const char *name)
+{
+ if (is_html) {
+ /*
+ * need to emit tag for post-grohtml
+ * but we check to see whether we can emit specials
+ */
+ if (curdiv == topdiv && topdiv->before_first_page)
+ topdiv->begin_page();
+ macro *m = new macro;
+ m->append_str("html-tag:");
+ for (const char *p = name; *p; p++)
+ if (!invalid_input_char((unsigned char)*p))
+ m->append(*p);
+ return new special_node(*m);
+ }
+ return 0;
}
void environment::do_break(int spread)
@@ -2144,7 +2287,8 @@ void environment::do_break(int spread)
if (current_tab)
wrap_up_tab();
if (line) {
- line = new space_node(H0, line); // this is so that hyphenation works
+ // this is so that hyphenation works
+ line = new space_node(H0, get_fill_color(), line);
space_total++;
possibly_break_line(0, spread);
}
@@ -2191,7 +2335,7 @@ void do_break_request(int spread)
tok.next();
if (break_flag) {
curenv->do_break(spread);
- curenv->add_html_tag(".br");
+ curenv->add_html_tag(0, ".br");
}
tok.next();
}
@@ -2228,6 +2372,10 @@ void title()
curenv->char_slant = env.char_slant;
curenv->fontno = env.fontno;
curenv->prev_fontno = env.prev_fontno;
+ curenv->glyph_color = env.glyph_color;
+ curenv->prev_glyph_color = env.prev_glyph_color;
+ curenv->fill_color = env.fill_color;
+ curenv->prev_fill_color = env.prev_fill_color;
node *n = 0;
node *p = part[2];
while (p != 0) {
@@ -2239,7 +2387,7 @@ void title()
hunits title_length(curenv->title_length);
hunits f = title_length - part_width[1];
hunits f2 = f/2;
- n = new hmotion_node(f2 - part_width[2], n);
+ n = new hmotion_node(f2 - part_width[2], curenv->get_fill_color(), n);
p = part[1];
while (p != 0) {
node *tem = p;
@@ -2247,7 +2395,7 @@ void title()
tem->next = n;
n = tem;
}
- n = new hmotion_node(f - f2 - part_width[0], n);
+ n = new hmotion_node(f - f2 - part_width[0], curenv->get_fill_color(), n);
p = part[0];
while (p != 0) {
node *tem = p;
@@ -2302,9 +2450,11 @@ void no_adjust()
skip_line();
}
-void input_trap()
+void do_input_trap(int continued)
{
curenv->input_trap_count = 0;
+ if (continued)
+ curenv->continued_input_trap = 1;
int n;
if (has_arg() && get_integer(&n)) {
if (n <= 0)
@@ -2321,6 +2471,16 @@ void input_trap()
skip_line();
}
+void input_trap()
+{
+ do_input_trap(0);
+}
+
+void input_trap_continued()
+{
+ do_input_trap(1);
+}
+
/* tabs */
// must not be R or C or L or a legitimate part of a number expression
@@ -2371,7 +2531,7 @@ tab::tab(hunits x, tab_type t) : next(0), pos(x), type(t)
}
tab_stops::tab_stops(hunits distance, tab_type type)
- : initial_list(0)
+: initial_list(0)
{
repeated_list = new tab(distance, type);
}
@@ -2383,12 +2543,21 @@ tab_stops::~tab_stops()
tab_type tab_stops::distance_to_next_tab(hunits curpos, hunits *distance)
{
+ hunits nextpos;
+
+ return distance_to_next_tab(curpos, distance, &nextpos);
+}
+
+tab_type tab_stops::distance_to_next_tab(hunits curpos, hunits *distance,
+ hunits *nextpos)
+{
hunits lastpos = 0;
tab *tem;
for (tem = initial_list; tem && tem->pos <= curpos; tem = tem->next)
lastpos = tem->pos;
if (tem) {
*distance = tem->pos - curpos;
+ *nextpos = tem->pos;
return tem->type;
}
if (repeated_list == 0)
@@ -2399,6 +2568,7 @@ tab_type tab_stops::distance_to_next_tab(hunits curpos, hunits *distance)
lastpos = tem->pos;
if (tem) {
*distance = tem->pos + base - curpos;
+ *nextpos = tem->pos + base;
return tem->type;
}
assert(lastpos > 0);
@@ -2476,7 +2646,7 @@ tab_stops::tab_stops() : initial_list(0), repeated_list(0)
}
tab_stops::tab_stops(const tab_stops &ts)
- : initial_list(0), repeated_list(0)
+: initial_list(0), repeated_list(0)
{
tab **p = &initial_list;
tab *t = ts.initial_list;
@@ -2573,7 +2743,7 @@ void set_tabs()
}
}
curenv->tabs = tabs;
- curenv->add_html_tag_tabs();
+ curenv->add_html_tag_tabs(1);
skip_line();
}
@@ -2605,6 +2775,14 @@ tab_type environment::distance_to_next_tab(hunits *distance)
: curenv->tabs.distance_to_next_tab(get_input_line_position(), distance);
}
+tab_type environment::distance_to_next_tab(hunits *distance, hunits *leftpos)
+{
+ return line_tabs
+ ? curenv->tabs.distance_to_next_tab(get_text_length(), distance, leftpos)
+ : curenv->tabs.distance_to_next_tab(get_input_line_position(), distance,
+ leftpos);
+}
+
void field_characters()
{
field_delimiter_char = get_optional_char();
@@ -2683,7 +2861,7 @@ node *environment::make_tab_node(hunits d, node *next)
leader_node = 0;
}
if (!leader_node)
- return new hmotion_node(d, 1, 0, next);
+ return new hmotion_node(d, 1, 0, get_fill_color(), next);
node *n = new hline_node(d, leader_node, next);
leader_node = 0;
return n;
@@ -2692,31 +2870,34 @@ node *environment::make_tab_node(hunits d, node *next)
void environment::handle_tab(int is_leader)
{
hunits d;
+ hunits abs;
if (current_tab)
wrap_up_tab();
charinfo *ci = is_leader ? leader_char : tab_char;
delete leader_node;
leader_node = ci ? make_char_node(ci) : 0;
- tab_type t = distance_to_next_tab(&d);
+ tab_type t = distance_to_next_tab(&d, &abs);
switch (t) {
case TAB_NONE:
return;
case TAB_LEFT:
- add_html_tag("tab left");
add_node(make_tab_node(d));
+ add_node(make_html_tag("tab L", abs.to_units()));
return;
case TAB_RIGHT:
+ add_node(make_html_tag("tab R", abs.to_units()));
+ break;
case TAB_CENTER:
- add_html_tag("tab center");
- tab_width = 0;
- tab_distance = d;
- tab_contents = 0;
- current_tab = t;
- tab_field_spaces = 0;
- return;
+ add_node(make_html_tag("tab C", abs.to_units()));
+ break;
default:
assert(0);
}
+ tab_width = 0;
+ tab_distance = d;
+ tab_contents = 0;
+ current_tab = t;
+ tab_field_spaces = 0;
}
void environment::start_field()
@@ -2792,13 +2973,13 @@ void environment::wrap_up_field()
void environment::add_padding()
{
if (current_tab) {
- tab_contents = new space_node(H0, tab_contents);
+ tab_contents = new space_node(H0, get_fill_color(), tab_contents);
tab_field_spaces++;
}
else {
if (line == 0)
start_line();
- line = new space_node(H0, line);
+ line = new space_node(H0, get_fill_color(), line);
field_spaces++;
}
}
@@ -2921,6 +3102,12 @@ const char *environment::get_font_family_string()
return family->nm.contents();
}
+const char *environment::get_font_name_string()
+{
+ symbol f = get_font_name(fontno, this);
+ return f.contents();
+}
+
const char *environment::get_name_string()
{
return name.contents();
@@ -3001,12 +3188,14 @@ const char *environment::get_requested_point_size_string()
void init_env_requests()
{
init_request("it", input_trap);
+ init_request("itc", input_trap_continued);
init_request("ad", adjust);
init_request("na", no_adjust);
init_request("ev", environment_switch);
init_request("evc", environment_copy);
init_request("lt", title_length);
init_request("ps", point_size);
+ init_request("sizes", override_sizes);
init_request("ft", font_change);
init_request("fam", family_change);
init_request("ss", space_size);
@@ -3070,6 +3259,7 @@ void init_env_requests()
init_int_env_reg(".ss", get_space_size);
init_int_env_reg(".sss", get_sentence_space_size);
init_string_env_reg(".fam", get_font_family_string);
+ init_string_env_reg(".fn", get_font_name_string);
init_string_env_reg(".ev", get_name_string);
init_int_env_reg(".hy", get_hyphenation_flags);
init_int_env_reg(".hlm", get_hyphen_line_max);
@@ -3118,14 +3308,15 @@ class hyphen_trie : private trie {
void do_match(int i, void *v);
void do_delete(void *v);
void insert_pattern(const char *pat, int patlen, int *num);
+ void insert_hyphenation(dictionary ex, const char *pat, int patlen);
+ int hpf_getc(FILE *f);
public:
hyphen_trie() {}
~hyphen_trie() {}
void hyphenate(const char *word, int len, int *hyphens);
- void read_patterns_file(const char *name);
+ void read_patterns_file(const char *name, int append, dictionary ex);
};
-
struct hyphenation_language {
symbol name;
dictionary exceptions;
@@ -3150,7 +3341,8 @@ static void set_hyphenation_language()
skip_line();
}
-const int WORD_MAX = 1024;
+const int WORD_MAX = 256; // we use unsigned char for offsets in
+ // hyphenation exceptions
static void hyphen_word()
{
@@ -3189,7 +3381,7 @@ static void hyphen_word()
pos[npos] = 0;
buf[i] = 0;
unsigned char *tem = new unsigned char[npos + 1];
- memcpy(tem, pos, npos+1);
+ memcpy(tem, pos, npos + 1);
tem = (unsigned char *)current_language->exceptions.lookup(symbol(buf),
tem);
if (tem)
@@ -3290,6 +3482,33 @@ void hyphen_trie::insert_pattern(const char *pat, int patlen, int *num)
insert(pat, patlen, op);
}
+void hyphen_trie::insert_hyphenation(dictionary ex, const char *pat,
+ int patlen)
+{
+ char buf[WORD_MAX + 1];
+ unsigned char pos[WORD_MAX + 2];
+ int i = 0, j = 0;
+ int npos = 0;
+ while (j < patlen) {
+ unsigned char c = pat[j++];
+ if (c == '-') {
+ if (i > 0 && (npos == 0 || pos[npos - 1] != i))
+ pos[npos++] = i;
+ }
+ else
+ buf[i++] = hpf_code_table[c];
+ }
+ if (i > 0) {
+ pos[npos] = 0;
+ buf[i] = 0;
+ unsigned char *tem = new unsigned char[npos + 1];
+ memcpy(tem, pos, npos + 1);
+ tem = (unsigned char *)ex.lookup(symbol(buf), tem);
+ if (tem)
+ a_delete tem;
+ }
+}
+
void hyphen_trie::hyphenate(const char *word, int len, int *hyphens)
{
int j;
@@ -3324,10 +3543,78 @@ void hyphen_trie::do_delete(void *v)
delete tem;
}
}
-
-void hyphen_trie::read_patterns_file(const char *name)
+
+/* We use very simple rules to parse TeX's hyphenation patterns.
+
+ . `%' starts a comment even if preceded by `\'.
+
+ . No support for digraphs and like `\$'.
+
+ . `^^xx' (`x' is 0-9 or a-f), and `^^x' (character code of `x' in the
+ range 0-127) are recognized; other use of `^' causes an error.
+
+ . No macro expansion.
+
+ . We check for the expression `\patterns{...}' (possibly with
+ whitespace before and after the braces). Everything between the
+ braces is taken as hyphenation patterns. Consequently, `{' and `}'
+ are not allowed in patterns.
+
+ . Similarly, `\hyphenation{...}' gives a list of hyphenation
+ exceptions.
+
+ . `\endinput' is recognized also.
+
+ . For backwards compatibility, if `\patterns' is missing, the
+ whole file is treated as a list of hyphenation patterns (only
+ recognizing `%' as the start of a comment.
+
+*/
+
+int hyphen_trie::hpf_getc(FILE *f)
+{
+ int c = getc(f);
+ int c1;
+ int cc = 0;
+ if (c != '^')
+ return c;
+ c = getc(f);
+ if (c != '^')
+ goto fail;
+ c = getc(f);
+ c1 = getc(f);
+ if (((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f'))
+ && ((c1 >= '0' && c1 <= '9') || (c1 >= 'a' && c1 <= 'f'))) {
+ if (c >= '0' && c <= '9')
+ c -= '0';
+ else
+ c = c - 'a' + 10;
+ if (c1 >= '0' && c1 <= '9')
+ c1 -= '0';
+ else
+ c1 = c1 - 'a' + 10;
+ cc = c * 16 + c1;
+ }
+ else {
+ ungetc(c1, f);
+ if (c >= 0 && c <= 63)
+ cc = c + 64;
+ else if (c >= 64 && c <= 127)
+ cc = c - 64;
+ else
+ goto fail;
+ }
+ return cc;
+fail:
+ error("invalid ^, ^^x, or ^^xx character in hyphenation patterns file");
+ return c;
+}
+
+void hyphen_trie::read_patterns_file(const char *name, int append,
+ dictionary ex)
{
- clear();
+ if (!append)
+ clear();
char buf[WORD_MAX];
int num[WORD_MAX+1];
errno = 0;
@@ -3337,32 +3624,111 @@ void hyphen_trie::read_patterns_file(const char *name)
error("can't find hyphenation patterns file `%1'", name);
return;
}
- int c = getc(fp);
+ int c = hpf_getc(fp);
+ int have_patterns = 0; // we've seen \patterns
+ int final_pattern = 0; // 1 if we have a trailing closing brace
+ int have_hyphenation = 0; // we've seen \hyphenation
+ int final_hyphenation = 0; // 1 if we have a trailing closing brace
+ int have_keyword = 0; // we've seen either \patterns or \hyphenation
+ int traditional = 0; // don't handle \patterns
for (;;) {
for (;;) {
- if (c == '%') {
+ if (c == '%') { // skip comments
do {
c = getc(fp);
} while (c != EOF && c != '\n');
}
if (c == EOF || !csspace(c))
break;
- c = getc(fp);
+ c = hpf_getc(fp);
+ }
+ if (c == EOF) {
+ if (have_keyword || traditional) // we are done
+ break;
+ else { // rescan file in `traditional' mode
+ rewind(fp);
+ traditional = 1;
+ c = hpf_getc(fp);
+ continue;
+ }
}
- if (c == EOF)
- break;
int i = 0;
num[0] = 0;
- do {
- if (csdigit(c))
- num[i] = c - '0';
- else {
- buf[i++] = c;
- num[i] = 0;
+ if (!(c == '{' || c == '}')) { // skip braces at line start
+ do { // scan patterns
+ if (csdigit(c))
+ num[i] = c - '0';
+ else {
+ buf[i++] = c;
+ num[i] = 0;
+ }
+ c = hpf_getc(fp);
+ } while (i < WORD_MAX && c != EOF && !csspace(c)
+ && c != '%' && c != '{' && c != '}');
+ }
+ if (!traditional) {
+ if (i >= 9 && !strncmp(buf + i - 9, "\\patterns", 9)) {
+ while (csspace(c))
+ c = hpf_getc(fp);
+ if (c == '{') {
+ if (have_patterns || have_hyphenation)
+ error("`{' not allowed inside of \\patterns or \\hyphenation");
+ else {
+ have_patterns = 1;
+ have_keyword = 1;
+ }
+ c = hpf_getc(fp);
+ continue;
+ }
+ }
+ else if (i >= 12 && !strncmp(buf + i - 12, "\\hyphenation", 12)) {
+ while (csspace(c))
+ c = hpf_getc(fp);
+ if (c == '{') {
+ if (have_patterns || have_hyphenation)
+ error("`{' not allowed inside of \\patterns or \\hyphenation");
+ else {
+ have_hyphenation = 1;
+ have_keyword = 1;
+ }
+ c = hpf_getc(fp);
+ continue;
+ }
+ }
+ else if (strstr(buf, "\\endinput")) {
+ if (have_patterns || have_hyphenation)
+ error("found \\endinput inside of %1 group",
+ have_patterns ? "\\patterns" : "\\hyphenation");
+ break;
+ }
+ else if (c == '}') {
+ if (have_patterns) {
+ have_patterns = 0;
+ if (i > 0)
+ final_pattern = 1;
+ }
+ else if (have_hyphenation) {
+ have_hyphenation = 0;
+ if (i > 0)
+ final_hyphenation = 1;
+ }
+ c = hpf_getc(fp);
}
- c = getc(fp);
- } while (i < WORD_MAX && c != EOF && !csspace(c) && c != '%');
- insert_pattern(buf, i, num);
+ else if (c == '{') // skipped if not starting \patterns
+ c = hpf_getc(fp); // or \hyphenation
+ }
+ if (i > 0) {
+ if (have_patterns || final_pattern || traditional) {
+ for (int j = 0; j < i; j++)
+ buf[j] = hpf_code_table[buf[j]];
+ insert_pattern(buf, i, num);
+ final_pattern = 0;
+ }
+ else if (have_hyphenation || final_hyphenation) {
+ insert_hyphenation(ex, buf, i);
+ final_hyphenation = 0;
+ }
+ }
}
fclose(fp);
a_delete path;
@@ -3419,18 +3785,30 @@ void hyphenate(hyphen_list *h, unsigned flags)
}
}
-static void hyphenation_patterns_file()
+static void do_hyphenation_patterns_file(int append)
{
symbol name = get_long_name(1);
if (!name.is_null()) {
if (!current_language)
error("no current hyphenation language");
else
- current_language->patterns.read_patterns_file(name.contents());
+ current_language->patterns.read_patterns_file(
+ name.contents(), append,
+ current_language->exceptions);
}
skip_line();
}
+static void hyphenation_patterns_file()
+{
+ do_hyphenation_patterns_file(0);
+}
+
+static void hyphenation_patterns_file_append()
+{
+ do_hyphenation_patterns_file(1);
+}
+
class hyphenation_language_reg : public reg {
public:
const char *get_string();
@@ -3446,5 +3824,6 @@ void init_hyphen_requests()
init_request("hw", hyphen_word);
init_request("hla", set_hyphenation_language);
init_request("hpf", hyphenation_patterns_file);
+ init_request("hpfa", hyphenation_patterns_file_append);
number_reg_dictionary.define(".hla", new hyphenation_language_reg);
}
diff --git a/contrib/groff/src/roff/troff/env.h b/contrib/groff/src/roff/troff/env.h
index 851a9a0..43a4c97 100644
--- a/contrib/groff/src/roff/troff/env.h
+++ b/contrib/groff/src/roff/troff/env.h
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001
+/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001, 2002
Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
@@ -85,6 +85,7 @@ public:
~tab_stops();
void operator=(const tab_stops &);
tab_type distance_to_next_tab(hunits pos, hunits *distance);
+ tab_type distance_to_next_tab(hunits curpos, hunits *distance, hunits *leftpos);
void clear();
void add_tab(hunits pos, tab_type type, int repeated);
const char *to_string();
@@ -140,6 +141,7 @@ class environment {
int underline_spaces;
symbol input_trap;
int input_trap_count;
+ int continued_input_trap;
node *line; // in reverse order
hunits prev_text_length;
hunits width_total;
@@ -181,11 +183,15 @@ class environment {
#ifdef WIDOW_CONTROL
int widow_control;
#endif /* WIDOW_CONTROL */
- int need_eol;
int ignore_next_eol;
int emitted_node; // have we emitted a node since the last html eol tag?
+ color *glyph_color;
+ color *prev_glyph_color;
+ color *fill_color;
+ color *prev_fill_color;
tab_type distance_to_next_tab(hunits *);
+ tab_type distance_to_next_tab(hunits *distance, hunits *leftpos);
void start_line();
void output_line(node *, hunits);
void output(node *nd, int retain_size, vunits vs, vunits post_vs,
@@ -261,6 +267,12 @@ public:
int get_center_lines();
int get_right_justify_lines();
int get_prev_line_interrupted() { return prev_line_interrupted; }
+ color *get_fill_color();
+ color *get_glyph_color();
+ color *get_prev_glyph_color();
+ color *get_prev_fill_color();
+ void set_glyph_color(color *c);
+ void set_fill_color(color *c);
node *make_char_node(charinfo *);
node *extract_output_line();
void width_registers();
@@ -277,10 +289,11 @@ public:
void possibly_break_line(int start_here = 0, int forced = 0);
void do_break(int spread = 0); // .br
void final_break();
- void add_html_tag_eol();
- void add_html_tag(const char *);
- void add_html_tag(const char *, int);
- void add_html_tag_tabs();
+ void add_html_tag(int, const char *);
+ void add_html_tag(int, const char *, int);
+ void add_html_tag_tabs(int);
+ node *make_html_tag(const char *name, int i);
+ node *make_html_tag(const char *);
void newline();
void handle_tab(int is_leader = 0); // do a tab or leader
void add_node(node *);
@@ -291,6 +304,7 @@ public:
void space(hunits, hunits);
void space_newline();
const char *get_font_family_string();
+ const char *get_font_name_string();
const char *get_name_string();
const char *get_point_size_string();
const char *get_requested_point_size_string();
@@ -311,7 +325,7 @@ public:
friend void indent();
friend void temporary_indent();
friend void do_underline(int);
- friend void input_trap();
+ friend void do_input_trap(int);
friend void set_tabs();
friend void margin_character();
friend void no_number();
@@ -343,7 +357,12 @@ extern void push_env(int);
void init_environments();
void read_hyphen_file(const char *name);
+void title();
+
+extern double spread_limit;
extern int break_flag;
extern symbol default_family;
extern int translate_space_to_dummy;
+
+extern unsigned char hpf_code_table[];
diff --git a/contrib/groff/src/roff/troff/input.cc b/contrib/groff/src/roff/troff/input.cc
index 54aaa3f..7a90e4b 100644
--- a/contrib/groff/src/roff/troff/input.cc
+++ b/contrib/groff/src/roff/troff/input.cc
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001
+/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001, 2002
Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
@@ -36,7 +36,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "defs.h"
#include "input.h"
-// Needed for getpid().
+// Needed for getpid() and isatty()
#include "posix.h"
#include "nonposix.h"
@@ -47,17 +47,6 @@ extern "C" {
}
#endif /* NEED_DECLARATION_PUTENV */
-#ifdef ISATTY_MISSING
-#undef isatty
-#define isatty(n) (1)
-#else /* not ISATTY_MISSING */
-#ifndef isatty
-extern "C" {
- int isatty(int);
-}
-#endif /* not isatty */
-#endif /* not ISATTY_MISSING */
-
#define MACRO_PREFIX "tmac."
#define MACRO_POSTFIX ".tmac"
#define INITIAL_STARTUP_FILE "troffrc"
@@ -86,17 +75,19 @@ void copy_file();
#ifdef COLUMN
void vjustify();
#endif /* COLUMN */
-void transparent();
void transparent_file();
+void process_input_stack();
const char *program_name = 0;
token tok;
int break_flag = 0;
+int color_flag = 1; // colors are on by default
static int backtrace_flag = 0;
#ifndef POPEN_MISSING
char *pipe_command = 0;
#endif
charinfo *charset_table[256];
+unsigned char hpf_code_table[256];
static int warning_mask = DEFAULT_WARNING_MASK;
static int inhibit_errors = 0;
@@ -114,9 +105,18 @@ int suppress_output_flag = 0;
int is_html = 0;
int begin_level = 0; // number of nested .begin requests
+int have_input = 0; // whether \f, \H, \R, \s, or \S has
+ // been processed in token::next()
int tcommand_flag = 0;
int safer_flag = 1; // safer by default
+int have_string_arg = 0; // whether we have \*[foo bar...]
+
+double spread_limit = -3.0 - 1.0; // negative means deactivated
+
+double warn_scale;
+char warn_scaling_indicator;
+
search_path *mac_path = &safer_macro_path;
static int get_copy(node**, int = 0);
@@ -125,8 +125,11 @@ static void copy_mode_error(const char *,
const errarg & = empty_errarg,
const errarg & = empty_errarg);
-static symbol read_escape_name();
+enum read_mode { ALLOW_EMPTY, WITH_ARGS, NO_ARGS };
+static symbol read_escape_name(read_mode mode = NO_ARGS);
+static symbol read_long_escape_name(read_mode mode = NO_ARGS);
static void interpolate_string(symbol);
+static void interpolate_string_with_args(symbol);
static void interpolate_macro(symbol);
static void interpolate_number_format(symbol);
static void interpolate_environment_variable(symbol);
@@ -135,7 +138,6 @@ static void interpolate_arg(symbol);
static request_or_macro *lookup_request(symbol);
static int get_delim_number(units *, int);
static int get_delim_number(units *, int, units);
-static symbol get_delim_file_name();
static int get_line_arg(units *res, int si, charinfo **cp);
static int read_size(int *);
static symbol get_delim_name();
@@ -185,7 +187,7 @@ void restore_escape_char()
class input_iterator {
public:
input_iterator();
- virtual ~input_iterator();
+ virtual ~input_iterator() {}
int get(node **);
friend class input_stack;
protected:
@@ -197,15 +199,13 @@ private:
virtual int peek();
virtual int has_args() { return 0; }
virtual int nargs() { return 0; }
- virtual input_iterator *get_arg(int) { return NULL; }
- virtual int get_location(int, const char **, int *)
- { return 0; }
+ virtual input_iterator *get_arg(int) { return 0; }
+ virtual int get_location(int, const char **, int *) { return 0; }
virtual void backtrace() {}
- virtual int set_location(const char *, int)
- { return 0; }
+ virtual int set_location(const char *, int) { return 0; }
virtual int next_file(FILE *, const char *) { return 0; }
virtual void shift(int) {}
- virtual int is_boundary() { return 0; }
+ virtual int is_boundary() {return 0; }
virtual int internal_level() { return 0; }
virtual int is_file() { return 0; }
virtual int is_macro() { return 0; }
@@ -218,10 +218,6 @@ input_iterator::input_iterator()
{
}
-input_iterator::~input_iterator()
-{
-}
-
int input_iterator::fill(node **)
{
return EOF;
@@ -253,6 +249,7 @@ class file_iterator : public input_iterator {
const char *filename;
int popened;
int newline_flag;
+ int seen_escape;
enum { BUF_SIZE = 512 };
unsigned char buf[BUF_SIZE];
void close();
@@ -269,7 +266,8 @@ public:
};
file_iterator::file_iterator(FILE *f, const char *fn, int po)
-: fp(f), lineno(1), filename(fn), popened(po), newline_flag(0)
+: fp(f), lineno(1), filename(fn), popened(po),
+ newline_flag(0), seen_escape(0)
{
if ((font::use_charnames_in_special) && (fn != 0)) {
if (!the_output)
@@ -307,6 +305,7 @@ int file_iterator::next_file(FILE *f, const char *s)
fp = f;
lineno = 1;
newline_flag = 0;
+ seen_escape = 0;
popened = 0;
ptr = 0;
eptr = 0;
@@ -315,10 +314,8 @@ int file_iterator::next_file(FILE *f, const char *s)
int file_iterator::fill(node **)
{
- if (newline_flag) {
- curenv->add_html_tag_eol();
+ if (newline_flag)
lineno++;
- }
newline_flag = 0;
unsigned char *p = buf;
ptr = p;
@@ -327,14 +324,16 @@ int file_iterator::fill(node **)
int c = getc(fp);
if (c == EOF)
break;
- if (illegal_input_char(c))
- warning(WARN_INPUT, "illegal input character code %1", int(c));
+ if (invalid_input_char(c))
+ warning(WARN_INPUT, "invalid input character code %1", int(c));
else {
*p++ = c;
if (c == '\n') {
+ seen_escape = 0;
newline_flag = 1;
break;
}
+ seen_escape = (c == '\\');
}
}
if (p > buf) {
@@ -350,8 +349,8 @@ int file_iterator::fill(node **)
int file_iterator::peek()
{
int c = getc(fp);
- while (illegal_input_char(c)) {
- warning(WARN_INPUT, "illegal input character code %1", int(c));
+ while (invalid_input_char(c)) {
+ warning(WARN_INPUT, "invalid input character code %1", int(c));
c = getc(fp);
}
if (c != EOF)
@@ -517,7 +516,7 @@ void input_stack::push(input_iterator *in)
input_iterator *input_stack::get_arg(int i)
{
input_iterator *p;
- for (p = top; p != NULL; p = p->next)
+ for (p = top; p != 0; p = p->next)
if (p->has_args())
return p->get_arg(i);
return 0;
@@ -677,21 +676,25 @@ void shift()
skip_line();
}
-static int get_char_for_escape_name()
+static int get_char_for_escape_name(int allow_space = 0)
{
- int c = get_copy(NULL);
+ int c = get_copy(0);
switch (c) {
case EOF:
copy_mode_error("end of input in escape name");
return '\0';
default:
- if (!illegal_input_char(c))
+ if (!invalid_input_char(c))
break;
// fall through
case '\n':
if (c == '\n')
input_stack::push(make_temp_iterator("\n"));
+ // fall through
case ' ':
+ if (c == ' ' && allow_space)
+ break;
+ // fall through
case '\t':
case '\001':
case '\b':
@@ -716,20 +719,25 @@ static symbol read_two_char_escape_name()
return symbol(buf);
}
-static symbol read_long_escape_name()
+static symbol read_long_escape_name(read_mode mode)
{
int start_level = input_stack::get_level();
char abuf[ABUF_SIZE];
char *buf = abuf;
int buf_size = ABUF_SIZE;
int i = 0;
+ int c;
+ int have_char = 0;
for (;;) {
- int c = get_char_for_escape_name();
+ c = get_char_for_escape_name(have_char && mode == WITH_ARGS);
if (c == 0) {
if (buf != abuf)
a_delete buf;
return NULL_SYMBOL;
}
+ have_char = 1;
+ if (mode == WITH_ARGS && c == ' ')
+ break;
if (i + 2 > buf_size) {
if (buf == abuf) {
buf = new char[ABUF_SIZE*2];
@@ -749,10 +757,13 @@ static symbol read_long_escape_name()
buf[i++] = c;
}
buf[i] = 0;
+ if (c == ' ')
+ have_string_arg = 1;
if (buf == abuf) {
if (i == 0) {
- copy_mode_error("empty escape name");
- return NULL_SYMBOL;
+ if (mode != ALLOW_EMPTY)
+ copy_mode_error("empty escape name");
+ return EMPTY_SYMBOL;
}
return symbol(abuf);
}
@@ -763,7 +774,7 @@ static symbol read_long_escape_name()
}
}
-static symbol read_escape_name()
+static symbol read_escape_name(read_mode mode)
{
int c = get_char_for_escape_name();
if (c == 0)
@@ -771,7 +782,7 @@ static symbol read_escape_name()
if (c == '(')
return read_two_char_escape_name();
if (c == '[' && !compatible_flag)
- return read_long_escape_name();
+ return read_long_escape_name(mode);
char buf[2];
buf[0] = c;
buf[1] = '\0';
@@ -826,131 +837,137 @@ static int get_copy(node **nd, int defining)
case 0:
return escape_char;
case '"':
- (void)input_stack::get(NULL);
- while ((c = input_stack::get(NULL)) != '\n' && c != EOF)
+ (void)input_stack::get(0);
+ while ((c = input_stack::get(0)) != '\n' && c != EOF)
;
return c;
case '#': // Like \" but newline is ignored.
- (void)input_stack::get(NULL);
- while ((c = input_stack::get(NULL)) != '\n')
+ (void)input_stack::get(0);
+ while ((c = input_stack::get(0)) != '\n')
if (c == EOF)
return EOF;
break;
case '$':
{
- (void)input_stack::get(NULL);
+ (void)input_stack::get(0);
symbol s = read_escape_name();
- if (!s.is_null())
+ if (!(s.is_null() || s.is_empty()))
interpolate_arg(s);
break;
}
case '*':
{
- (void)input_stack::get(NULL);
- symbol s = read_escape_name();
- if (!s.is_null())
- interpolate_string(s);
+ (void)input_stack::get(0);
+ symbol s = read_escape_name(WITH_ARGS);
+ if (!(s.is_null() || s.is_empty())) {
+ if (have_string_arg) {
+ have_string_arg = 0;
+ interpolate_string_with_args(s);
+ }
+ else
+ interpolate_string(s);
+ }
break;
}
case 'a':
- (void)input_stack::get(NULL);
+ (void)input_stack::get(0);
return '\001';
case 'e':
- (void)input_stack::get(NULL);
+ (void)input_stack::get(0);
return ESCAPE_e;
case 'E':
- (void)input_stack::get(NULL);
+ (void)input_stack::get(0);
return ESCAPE_E;
case 'n':
{
- (void)input_stack::get(NULL);
+ (void)input_stack::get(0);
int inc;
symbol s = read_increment_and_escape_name(&inc);
- if (!s.is_null())
+ if (!(s.is_null() || s.is_empty()))
interpolate_number_reg(s, inc);
break;
}
case 'g':
{
- (void)input_stack::get(NULL);
- symbol s = read_escape_name();
- if (!s.is_null())
+ (void)input_stack::get(0);
+ symbol s = read_escape_name();
+ if (!(s.is_null() || s.is_empty()))
interpolate_number_format(s);
- break;
+ break;
}
case 't':
- (void)input_stack::get(NULL);
+ (void)input_stack::get(0);
return '\t';
case 'V':
{
- (void)input_stack::get(NULL);
+ (void)input_stack::get(0);
symbol s = read_escape_name();
- if (!s.is_null())
+ if (!(s.is_null() || s.is_empty()))
interpolate_environment_variable(s);
break;
}
case '\n':
- (void)input_stack::get(NULL);
+ (void)input_stack::get(0);
if (defining)
return ESCAPE_NEWLINE;
break;
case ' ':
- (void)input_stack::get(NULL);
+ (void)input_stack::get(0);
return ESCAPE_SPACE;
case '~':
- (void)input_stack::get(NULL);
+ (void)input_stack::get(0);
return ESCAPE_TILDE;
case ':':
- (void)input_stack::get(NULL);
+ (void)input_stack::get(0);
return ESCAPE_COLON;
case '|':
- (void)input_stack::get(NULL);
+ (void)input_stack::get(0);
return ESCAPE_BAR;
case '^':
- (void)input_stack::get(NULL);
+ (void)input_stack::get(0);
return ESCAPE_CIRCUMFLEX;
case '{':
- (void)input_stack::get(NULL);
+ (void)input_stack::get(0);
return ESCAPE_LEFT_BRACE;
case '}':
- (void)input_stack::get(NULL);
+ (void)input_stack::get(0);
return ESCAPE_RIGHT_BRACE;
case '`':
- (void)input_stack::get(NULL);
+ (void)input_stack::get(0);
return ESCAPE_LEFT_QUOTE;
case '\'':
- (void)input_stack::get(NULL);
+ (void)input_stack::get(0);
return ESCAPE_RIGHT_QUOTE;
case '-':
- (void)input_stack::get(NULL);
+ (void)input_stack::get(0);
return ESCAPE_HYPHEN;
case '_':
- (void)input_stack::get(NULL);
+ (void)input_stack::get(0);
return ESCAPE_UNDERSCORE;
case 'c':
- (void)input_stack::get(NULL);
+ (void)input_stack::get(0);
return ESCAPE_c;
case '!':
- (void)input_stack::get(NULL);
+ (void)input_stack::get(0);
return ESCAPE_BANG;
case '?':
- (void)input_stack::get(NULL);
+ (void)input_stack::get(0);
return ESCAPE_QUESTION;
case '&':
- (void)input_stack::get(NULL);
+ (void)input_stack::get(0);
return ESCAPE_AMPERSAND;
case ')':
- (void)input_stack::get(NULL);
+ (void)input_stack::get(0);
return ESCAPE_RIGHT_PARENTHESIS;
case '.':
- (void)input_stack::get(NULL);
+ (void)input_stack::get(0);
return c;
case '%':
- (void)input_stack::get(NULL);
+ (void)input_stack::get(0);
return ESCAPE_PERCENT;
default:
if (c == escape_char) {
- (void)input_stack::get(NULL);
+ (void)input_stack::get(0);
return c;
}
else
@@ -1004,27 +1021,255 @@ int non_interpreted_char_node::interpret(macro *mac)
static void do_width();
static node *do_non_interpreted();
static node *do_special();
-static node *do_suppress();
+static node *do_suppress(symbol nm);
static void do_register();
+dictionary color_dictionary(501);
+static symbol default_symbol("default");
+
+static color *lookup_color(symbol nm)
+{
+ assert(!nm.is_null());
+ if (nm == default_symbol)
+ return &default_color;
+ color *c = (color *)color_dictionary.lookup(nm);
+ if (c == 0)
+ warning(WARN_COLOR, "`%1' not defined", nm.contents());
+ return c;
+}
+
+void do_glyph_color(symbol nm)
+{
+ if (nm.is_null())
+ return;
+ if (nm.is_empty())
+ curenv->set_glyph_color(curenv->get_prev_glyph_color());
+ else {
+ color *tem = lookup_color(nm);
+ if (tem)
+ curenv->set_glyph_color(tem);
+ else
+ (void)color_dictionary.lookup(nm, new color);
+ }
+}
+
+void do_fill_color(symbol nm)
+{
+ if (nm.is_null())
+ return;
+ if (nm.is_empty())
+ curenv->set_fill_color(curenv->get_prev_fill_color());
+ else {
+ color *tem = lookup_color(nm);
+ if (tem)
+ curenv->set_fill_color(tem);
+ else
+ (void)color_dictionary.lookup(nm, new color);
+ }
+}
+
+static unsigned int get_color_element(const char *scheme, const char *col)
+{
+ units val;
+ if (!get_number(&val, 'f')) {
+ warning(WARN_COLOR, "%1 in %2 definition set to 0", col, scheme);
+ tok.next();
+ return 0;
+ }
+ if (val < 0) {
+ warning(WARN_RANGE, "%1 cannot be negative: set to 0", col);
+ return 0;
+ }
+ if (val > color::MAX_COLOR_VAL+1) {
+ warning(WARN_RANGE, "%1 cannot be greater than 1", col);
+ // we change 0x10000 to 0xffff
+ return color::MAX_COLOR_VAL;
+ }
+ return (unsigned int)val;
+}
+
+static color *read_rgb()
+{
+ symbol component = get_long_name(0);
+ if (component.is_null()) {
+ warning(WARN_COLOR, "missing rgb color values");
+ return 0;
+ }
+ const char *s = component.contents();
+ color *col = new color;
+ if (*s == '#') {
+ if (!col->read_rgb(s)) {
+ warning(WARN_COLOR, "expecting rgb color definition not `%1'", s);
+ delete col;
+ return 0;
+ }
+ }
+ else {
+ input_stack::push(make_temp_iterator(" "));
+ input_stack::push(make_temp_iterator(s));
+ tok.next();
+ unsigned int r = get_color_element("rgb color", "red component");
+ unsigned int g = get_color_element("rgb color", "green component");
+ unsigned int b = get_color_element("rgb color", "blue component");
+ col->set_rgb(r, g, b);
+ }
+ return col;
+}
+
+static color *read_cmy()
+{
+ symbol component = get_long_name(0);
+ if (component.is_null()) {
+ warning(WARN_COLOR, "missing cmy color values");
+ return 0;
+ }
+ const char *s = component.contents();
+ color *col = new color;
+ if (*s == '#') {
+ if (!col->read_cmy(s)) {
+ warning(WARN_COLOR, "expecting cmy color definition not `%1'", s);
+ delete col;
+ return 0;
+ }
+ }
+ else {
+ input_stack::push(make_temp_iterator(" "));
+ input_stack::push(make_temp_iterator(s));
+ tok.next();
+ unsigned int c = get_color_element("cmy color", "cyan component");
+ unsigned int m = get_color_element("cmy color", "magenta component");
+ unsigned int y = get_color_element("cmy color", "yellow component");
+ col->set_cmy(c, m, y);
+ }
+ return col;
+}
+
+static color *read_cmyk()
+{
+ symbol component = get_long_name(0);
+ if (component.is_null()) {
+ warning(WARN_COLOR, "missing cmyk color values");
+ return 0;
+ }
+ const char *s = component.contents();
+ color *col = new color;
+ if (*s == '#') {
+ if (!col->read_cmyk(s)) {
+ warning(WARN_COLOR, "`expecting a cmyk color definition not `%1'", s);
+ delete col;
+ return 0;
+ }
+ }
+ else {
+ input_stack::push(make_temp_iterator(" "));
+ input_stack::push(make_temp_iterator(s));
+ tok.next();
+ unsigned int c = get_color_element("cmyk color", "cyan component");
+ unsigned int m = get_color_element("cmyk color", "magenta component");
+ unsigned int y = get_color_element("cmyk color", "yellow component");
+ unsigned int k = get_color_element("cmyk color", "black component");
+ col->set_cmyk(c, m, y, k);
+ }
+ return col;
+}
+
+static color *read_gray()
+{
+ symbol component = get_long_name(0);
+ if (component.is_null()) {
+ warning(WARN_COLOR, "missing gray values");
+ return 0;
+ }
+ const char *s = component.contents();
+ color *col = new color;
+ if (*s == '#') {
+ if (!col->read_gray(s)) {
+ warning(WARN_COLOR, "`expecting a gray definition not `%1'", s);
+ delete col;
+ return 0;
+ }
+ }
+ else {
+ input_stack::push(make_temp_iterator("\n"));
+ input_stack::push(make_temp_iterator(s));
+ tok.next();
+ unsigned int g = get_color_element("gray", "gray value");
+ col->set_gray(g);
+ }
+ return col;
+}
+
+static void activate_color()
+{
+ int n;
+ if (has_arg() && get_integer(&n))
+ color_flag = n != 0;
+ else
+ color_flag = 1;
+ skip_line();
+}
+
+static void define_color()
+{
+ symbol color_name = get_long_name(1);
+ if (color_name.is_null()) {
+ skip_line();
+ return;
+ }
+ if (color_name == default_symbol) {
+ warning(WARN_COLOR, "default color can't be redefined");
+ skip_line();
+ return;
+ }
+ symbol style = get_long_name(1);
+ if (style.is_null()) {
+ skip_line();
+ return;
+ }
+ color *col;
+ if (strcmp(style.contents(), "rgb") == 0)
+ col = read_rgb();
+ else if (strcmp(style.contents(), "cmyk") == 0)
+ col = read_cmyk();
+ else if (strcmp(style.contents(), "gray") == 0)
+ col = read_gray();
+ else if (strcmp(style.contents(), "grey") == 0)
+ col = read_gray();
+ else if (strcmp(style.contents(), "cmy") == 0)
+ col = read_cmy();
+ else {
+ warning(WARN_COLOR,
+ "unknown color space `%1'; use rgb, cmyk, gray or cmy",
+ style.contents());
+ skip_line();
+ return;
+ }
+ if (col)
+ (void)color_dictionary.lookup(color_name, col);
+ skip_line();
+}
+
static node *do_overstrike()
{
token start;
overstrike_node *on = new overstrike_node;
+ int start_level = input_stack::get_level();
start.next();
- tok.next();
- while (tok != start) {
+ for (;;) {
+ tok.next();
if (tok.newline() || tok.eof()) {
warning(WARN_DELIM, "missing closing delimiter");
break;
}
+ if (tok == start
+ && (compatible_flag || input_stack::get_level() == start_level))
+ break;
charinfo *ci = tok.get_char(1);
if (ci) {
node *n = curenv->make_char_node(ci);
if (n)
on->overstrike(n);
}
- tok.next();
}
return on;
}
@@ -1034,8 +1279,9 @@ static node *do_bracket()
token start;
bracket_node *bn = new bracket_node;
start.next();
- tok.next();
- while (tok != start) {
+ int start_level = input_stack::get_level();
+ for (;;) {
+ tok.next();
if (tok.eof()) {
warning(WARN_DELIM, "missing closing delimiter");
break;
@@ -1045,13 +1291,15 @@ static node *do_bracket()
input_stack::push(make_temp_iterator("\n"));
break;
}
+ if (tok == start
+ && (compatible_flag || input_stack::get_level() == start_level))
+ break;
charinfo *ci = tok.get_char(1);
if (ci) {
node *n = curenv->make_char_node(ci);
if (n)
bn->bracket(n);
}
- tok.next();
}
return bn;
}
@@ -1164,7 +1412,7 @@ static node *do_zero_width()
&& (compatible_flag || input_stack::get_level() == start_level))
break;
if (!tok.add_to_node_list(&rev))
- error("illegal token in argument to \\Z");
+ error("invalid token in argument to \\Z");
}
node *n = 0;
while (rev) {
@@ -1326,8 +1574,7 @@ void token::next()
return;
case ESCAPE_SPACE:
ESCAPE_SPACE:
- type = TOKEN_NODE;
- nd = new space_char_hmotion_node(curenv->get_space_width());
+ type = TOKEN_UNSTRETCHABLE_SPACE;
return;
case ESCAPE_TILDE:
ESCAPE_TILDE:
@@ -1335,10 +1582,7 @@ void token::next()
return;
case ESCAPE_COLON:
ESCAPE_COLON:
- type = TOKEN_NODE;
- nd = new space_node(H0);
- nd->freeze_space();
- nd->is_escape_colon();
+ type = TOKEN_ZERO_WIDTH_BREAK;
return;
case ESCAPE_e:
ESCAPE_e:
@@ -1349,12 +1593,14 @@ void token::next()
case ESCAPE_BAR:
ESCAPE_BAR:
type = TOKEN_NODE;
- nd = new hmotion_node(curenv->get_narrow_space_width());
+ nd = new hmotion_node(curenv->get_narrow_space_width(),
+ curenv->get_fill_color());
return;
case ESCAPE_CIRCUMFLEX:
ESCAPE_CIRCUMFLEX:
type = TOKEN_NODE;
- nd = new hmotion_node(curenv->get_half_narrow_space_width());
+ nd = new hmotion_node(curenv->get_half_narrow_space_width(),
+ curenv->get_fill_color());
return;
case ESCAPE_NEWLINE:
break;
@@ -1447,7 +1693,7 @@ void token::next()
}
else {
handle_escape_char:
- cc = input_stack::get(NULL);
+ cc = input_stack::get(0);
switch(cc) {
case '(':
nm = read_two_char_escape_name();
@@ -1470,7 +1716,8 @@ void token::next()
case ' ':
goto ESCAPE_SPACE;
case '0':
- nd = new hmotion_node(curenv->get_digit_width());
+ nd = new hmotion_node(curenv->get_digit_width(),
+ curenv->get_fill_color());
type = TOKEN_NODE;
return;
case '|':
@@ -1497,7 +1744,7 @@ void token::next()
case ':':
goto ESCAPE_COLON;
case '"':
- while ((cc = input_stack::get(NULL)) != '\n' && cc != EOF)
+ while ((cc = input_stack::get(0)) != '\n' && cc != EOF)
;
if (cc == '\n')
type = TOKEN_NEWLINE;
@@ -1505,7 +1752,7 @@ void token::next()
type = TOKEN_EOF;
return;
case '#': // Like \" but newline is ignored.
- while ((cc = input_stack::get(NULL)) != '\n')
+ while ((cc = input_stack::get(0)) != '\n')
if (cc == EOF) {
type = TOKEN_EOF;
return;
@@ -1514,15 +1761,21 @@ void token::next()
case '$':
{
symbol nm = read_escape_name();
- if (!nm.is_null())
+ if (!(nm.is_null() || nm.is_empty()))
interpolate_arg(nm);
break;
}
case '*':
{
- symbol nm = read_escape_name();
- if (!nm.is_null())
- interpolate_string(nm);
+ symbol nm = read_escape_name(WITH_ARGS);
+ if (!(nm.is_null() || nm.is_empty())) {
+ if (have_string_arg) {
+ have_string_arg = 0;
+ interpolate_string_with_args(nm);
+ }
+ else
+ interpolate_string(nm);
+ }
break;
}
case 'a':
@@ -1551,7 +1804,8 @@ void token::next()
return;
case 'd':
type = TOKEN_NODE;
- nd = new vmotion_node(curenv->get_size()/2);
+ nd = new vmotion_node(curenv->get_size() / 2,
+ curenv->get_fill_color());
return;
case 'D':
nd = read_draw_node();
@@ -1565,23 +1819,33 @@ void token::next()
goto handle_escape_char;
case 'f':
{
- symbol s = read_escape_name();
+ symbol s = read_escape_name(ALLOW_EMPTY);
if (s.is_null())
break;
const char *p;
for (p = s.contents(); *p != '\0'; p++)
if (!csdigit(*p))
break;
- if (*p)
+ if (*p || s.is_empty())
curenv->set_font(s);
else
curenv->set_font(atoi(s.contents()));
+ if (!compatible_flag)
+ have_input = 1;
+ break;
+ }
+ case 'F':
+ {
+ symbol s = read_escape_name(ALLOW_EMPTY);
+ if (s.is_null())
+ break;
+ curenv->set_family(s);
break;
}
case 'g':
{
symbol s = read_escape_name();
- if (!s.is_null())
+ if (!(s.is_null() || s.is_empty()))
interpolate_number_format(s);
break;
}
@@ -1589,15 +1853,27 @@ void token::next()
if (!get_delim_number(&x, 'm'))
break;
type = TOKEN_NODE;
- nd = new hmotion_node(x);
+ nd = new hmotion_node(x, curenv->get_fill_color());
return;
case 'H':
- if (get_delim_number(&x, 'z', curenv->get_requested_point_size()))
- curenv->set_char_height(x);
+ // don't take height increments relative to previous height if
+ // in compatibility mode
+ if (!compatible_flag && curenv->get_char_height())
+ {
+ if (get_delim_number(&x, 'z', curenv->get_char_height()))
+ curenv->set_char_height(x);
+ }
+ else
+ {
+ if (get_delim_number(&x, 'z', curenv->get_requested_point_size()))
+ curenv->set_char_height(x);
+ }
+ if (!compatible_flag)
+ have_input = 1;
break;
case 'k':
nm = read_escape_name();
- if (nm.is_null())
+ if (nm.is_null() || nm.is_empty())
break;
type = TOKEN_MARK_INPUT;
return;
@@ -1617,11 +1893,21 @@ void token::next()
nd = new vline_node(x, n);
return;
}
+ case 'm':
+ do_glyph_color(read_escape_name(ALLOW_EMPTY));
+ if (!compatible_flag)
+ have_input = 1;
+ break;
+ case 'M':
+ do_fill_color(read_escape_name(ALLOW_EMPTY));
+ if (!compatible_flag)
+ have_input = 1;
+ break;
case 'n':
{
int inc;
symbol nm = read_increment_and_escape_name(&inc);
- if (!nm.is_null())
+ if (!(nm.is_null() || nm.is_empty()))
interpolate_number_reg(nm, inc);
break;
}
@@ -1635,7 +1921,7 @@ void token::next()
type = TOKEN_NODE;
return;
case 'O':
- nd = do_suppress();
+ nd = do_suppress(read_escape_name());
if (!nd)
break;
type = TOKEN_NODE;
@@ -1645,18 +1931,24 @@ void token::next()
return;
case 'r':
type = TOKEN_NODE;
- nd = new vmotion_node(-curenv->get_size());
+ nd = new vmotion_node(-curenv->get_size(), curenv->get_fill_color());
return;
case 'R':
do_register();
+ if (!compatible_flag)
+ have_input = 1;
break;
case 's':
if (read_size(&x))
curenv->set_size(x);
+ if (!compatible_flag)
+ have_input = 1;
break;
case 'S':
if (get_delim_number(&x, 0))
curenv->set_char_slant(x);
+ if (!compatible_flag)
+ have_input = 1;
break;
case 't':
type = TOKEN_NODE;
@@ -1664,18 +1956,19 @@ void token::next()
return;
case 'u':
type = TOKEN_NODE;
- nd = new vmotion_node(-curenv->get_size()/2);
+ nd = new vmotion_node(-curenv->get_size() / 2,
+ curenv->get_fill_color());
return;
case 'v':
if (!get_delim_number(&x, 'v'))
break;
type = TOKEN_NODE;
- nd = new vmotion_node(x);
+ nd = new vmotion_node(x, curenv->get_fill_color());
return;
case 'V':
- {
+ {
symbol nm = read_escape_name();
- if (!nm.is_null())
+ if (!(nm.is_null() || nm.is_empty()))
interpolate_environment_variable(nm);
break;
}
@@ -1697,7 +1990,7 @@ void token::next()
case 'Y':
{
symbol s = read_escape_name();
- if (s.is_null())
+ if (s.is_null() || s.is_empty())
break;
request_or_macro *p = lookup_request(s);
macro *m = p->to_macro();
@@ -1712,9 +2005,9 @@ void token::next()
case 'z':
{
next();
- if (type == TOKEN_NODE)
- nd = new zero_width_node(nd);
- else {
+ if (type == TOKEN_NODE)
+ nd = new zero_width_node(nd);
+ else {
charinfo *ci = get_char(1);
if (ci == 0)
break;
@@ -1723,7 +2016,7 @@ void token::next()
break;
nd = new zero_width_node(gn);
type = TOKEN_NODE;
- }
+ }
return;
}
case 'Z':
@@ -1741,7 +2034,7 @@ void token::next()
case '[':
if (!compatible_flag) {
nm = read_long_escape_name();
- if (nm.is_null())
+ if (nm.is_null() || nm.is_empty())
break;
type = TOKEN_SPECIAL;
return;
@@ -1817,6 +2110,7 @@ int token::delimiter(int err)
case TOKEN_NODE:
case TOKEN_SPACE:
case TOKEN_STRETCHABLE_SPACE:
+ case TOKEN_UNSTRETCHABLE_SPACE:
case TOKEN_TAB:
case TOKEN_NEWLINE:
if (err)
@@ -1871,12 +2165,16 @@ const char *token::description()
return "`\\p'";
case TOKEN_STRETCHABLE_SPACE:
return "`\\~'";
+ case TOKEN_UNSTRETCHABLE_SPACE:
+ return "`\\ '";
case TOKEN_TAB:
return "a tab character";
case TOKEN_TRANSPARENT:
return "`\\!'";
case TOKEN_TRANSPARENT_DUMMY:
return "`\\)'";
+ case TOKEN_ZERO_WIDTH_BREAK:
+ return "`\\:'";
case TOKEN_EOF:
return "end of input";
default:
@@ -2015,19 +2313,21 @@ void exit_troff()
tok.next();
process_input_stack();
end_diversions();
- done_end_macro = 1;
- topdiv->set_ejecting();
- static unsigned char buf[2] = { LAST_PAGE_EJECTOR, '\0' };
- input_stack::push(make_temp_iterator((char *)buf));
- topdiv->space(topdiv->get_page_length(), 1);
- tok.next();
- process_input_stack();
- seen_last_page_ejector = 1; // should be set already
- topdiv->set_ejecting();
- push_page_ejector();
- topdiv->space(topdiv->get_page_length(), 1);
- tok.next();
- process_input_stack();
+ if (topdiv->get_page_length() > 0) {
+ done_end_macro = 1;
+ topdiv->set_ejecting();
+ static unsigned char buf[2] = { LAST_PAGE_EJECTOR, '\0' };
+ input_stack::push(make_temp_iterator((char *)buf));
+ topdiv->space(topdiv->get_page_length(), 1);
+ tok.next();
+ process_input_stack();
+ seen_last_page_ejector = 1; // should be set already
+ topdiv->set_ejecting();
+ push_page_ejector();
+ topdiv->space(topdiv->get_page_length(), 1);
+ tok.next();
+ process_input_stack();
+ }
// This will only happen if a trap-invoked macro starts a diversion,
// or if vertical position traps have been disabled.
cleanup_and_exit(0);
@@ -2095,7 +2395,7 @@ inline int possibly_handle_first_page_transition()
static int transparent_translate(int cc)
{
- if (!illegal_input_char(cc)) {
+ if (!invalid_input_char(cc)) {
charinfo *ci = charset_table[cc];
switch (ci->get_special_translation(1)) {
case charinfo::TRANSLATE_SPACE:
@@ -2230,9 +2530,9 @@ void process_input_stack()
case token::TOKEN_CHAR:
{
unsigned char ch = tok.c;
- if (bol &&
- (ch == curenv->control_char
- || ch == curenv->no_break_control_char)) {
+ if (bol && !have_input
+ && (ch == curenv->control_char
+ || ch == curenv->no_break_control_char)) {
break_flag = ch == curenv->control_char;
// skip tabs as well as spaces here
do {
@@ -2244,6 +2544,7 @@ void process_input_stack()
else
interpolate_macro(nm);
suppress_next = 1;
+ have_input = 0;
}
else {
if (possibly_handle_first_page_transition())
@@ -2286,11 +2587,13 @@ void process_input_stack()
}
case token::TOKEN_NEWLINE:
{
- if (bol && !curenv->get_prev_line_interrupted())
+ if (bol && !have_input
+ && !curenv->get_prev_line_interrupted())
trapping_blank_line();
else {
curenv->newline();
bol = 1;
+ have_input = 0;
}
break;
}
@@ -2318,6 +2621,7 @@ void process_input_stack()
break;
}
suppress_next = 1;
+ have_input = 0;
break;
}
case token::TOKEN_SPACE:
@@ -2326,6 +2630,9 @@ void process_input_stack()
;
else if (bol && !curenv->get_prev_line_interrupted()) {
int nspaces = 0;
+ // save space_width now so that it isn't changed by \f or \s
+ // which we wouldn't notice here
+ hunits space_width = curenv->get_space_width();
do {
nspaces += tok.nspaces();
tok.next();
@@ -2335,8 +2642,8 @@ void process_input_stack()
else {
push_token(tok);
curenv->do_break();
- curenv->add_node(new hmotion_node(curenv->get_space_width()
- * nspaces));
+ curenv->add_node(new hmotion_node(space_width * nspaces,
+ curenv->get_fill_color()));
bol = 0;
}
}
@@ -2375,6 +2682,7 @@ void process_input_stack()
{
trap_bol_stack.push(bol);
bol = 1;
+ have_input = 0;
break;
}
case token::TOKEN_END_TRAP:
@@ -2388,9 +2696,9 @@ void process_input_stack()
way to do it. Doing an output_pending_lines() whenever a
TOKEN_END_TRAP is detected doesn't work: for example,
- .wh -1i x
- .de x
- 'bp
+ .wh -1i x
+ .de x
+ 'bp
..
.wh -.5i y
.de y
@@ -2401,8 +2709,8 @@ void process_input_stack()
.sp |\n(.pu-1i-.5v
a\%very\%very\%long\%word
- will print all but the first lines from the word immediately
- after the footer, rather than on the next page. */
+ will print all but the first lines from the word immediately
+ after the footer, rather than on the next page. */
if (trap_bol_stack.is_empty())
curenv->output_pending_lines();
@@ -2468,6 +2776,8 @@ public:
char_list();
~char_list();
void append(unsigned char);
+ void set(unsigned char, int);
+ unsigned char get(int);
int length();
private:
unsigned char *ptr;
@@ -2514,6 +2824,44 @@ void char_list::append(unsigned char c)
len++;
}
+void char_list::set(unsigned char c, int offset)
+{
+ assert(len > offset);
+ // optimization for access at the end
+ int boundary = len - len % char_block::SIZE;
+ if (offset >= boundary) {
+ *(tail->s + offset - boundary) = c;
+ return;
+ }
+ char_block *tem = head;
+ int l = 0;
+ for (;;) {
+ l += char_block::SIZE;
+ if (l > offset) {
+ *(tem->s + offset % char_block::SIZE) = c;
+ return;
+ }
+ tem = tem->next;
+ }
+}
+
+unsigned char char_list::get(int offset)
+{
+ assert(len > offset);
+ // optimization for access at the end
+ int boundary = len - len % char_block::SIZE;
+ if (offset >= boundary)
+ return *(tail->s + offset - boundary);
+ char_block *tem = head;
+ int l = 0;
+ for (;;) {
+ l += char_block::SIZE;
+ if (l > offset)
+ return *(tem->s + offset % char_block::SIZE);
+ tem = tem->next;
+ }
+}
+
class node_list {
node *head;
node *tail;
@@ -2586,12 +2934,14 @@ macro::macro()
filename = 0;
lineno = 0;
}
- length = 0;
+ len = 0;
+ empty_macro = 1;
p = 0;
}
macro::macro(const macro &m)
-: p(m.p), filename(m.filename), lineno(m.lineno), length(m.length)
+: p(m.p), filename(m.filename), lineno(m.lineno), len(m.len),
+ empty_macro(m.empty_macro)
{
if (p != 0)
p->count++;
@@ -2607,7 +2957,8 @@ macro &macro::operator=(const macro &m)
p = m.p;
filename = m.filename;
lineno = m.lineno;
- length = m.length;
+ len = m.len;
+ empty_macro = m.empty_macro;
return *this;
}
@@ -2616,14 +2967,34 @@ void macro::append(unsigned char c)
assert(c != 0);
if (p == 0)
p = new macro_header;
- if (p->cl.length() != length) {
- macro_header *tem = p->copy(length);
+ if (p->cl.length() != len) {
+ macro_header *tem = p->copy(len);
if (--(p->count) <= 0)
delete p;
p = tem;
}
p->cl.append(c);
- ++length;
+ ++len;
+ if (c != COMPATIBLE_SAVE && c != COMPATIBLE_RESTORE)
+ empty_macro = 0;
+}
+
+void macro::set(unsigned char c, int offset)
+{
+ assert(p != 0);
+ assert(c != 0);
+ p->cl.set(c, offset);
+}
+
+unsigned char macro::get(int offset)
+{
+ assert(p != 0);
+ return p->cl.get(offset);
+}
+
+int macro::length()
+{
+ return len;
}
void macro::append_str(const char *s)
@@ -2643,15 +3014,16 @@ void macro::append(node *n)
assert(n != 0);
if (p == 0)
p = new macro_header;
- if (p->cl.length() != length) {
- macro_header *tem = p->copy(length);
+ if (p->cl.length() != len) {
+ macro_header *tem = p->copy(len);
if (--(p->count) <= 0)
delete p;
p = tem;
}
p->cl.append(0);
p->nl.append(n);
- ++length;
+ ++len;
+ empty_macro = 0;
}
void macro::append_unsigned(unsigned int i)
@@ -2673,7 +3045,7 @@ void macro::append_int(int i)
void macro::print_size()
{
- errprint("%1", length);
+ errprint("%1", len);
}
// make a copy of the first n bytes
@@ -2740,9 +3112,10 @@ public:
};
string_iterator::string_iterator(const macro &m, const char *p, symbol s)
-: mac(m), how_invoked(p), newline_flag(0), lineno(1), nm(s)
+: mac(m), how_invoked(p),
+ newline_flag(0), lineno(1), nm(s)
{
- count = mac.length;
+ count = mac.len;
if (count != 0) {
bp = mac.p->cl.head;
nd = mac.p->nl.head;
@@ -2811,8 +3184,6 @@ int string_iterator::peek()
if (count <= 0)
return EOF;
const unsigned char *p = eptr;
- if (count <= 0)
- return EOF;
if (p >= bp->s + char_block::SIZE) {
p = bp->next->s;
}
@@ -2940,7 +3311,7 @@ input_iterator *make_temp_iterator(const char *s)
}
}
-// this is used when macros are interpolated using the .macro_name notation
+// this is used when macros with arguments are interpolated
struct arg_list {
macro mac;
@@ -3012,11 +3383,11 @@ void macro_iterator::shift(int n)
int operator==(const macro &m1, const macro &m2)
{
- if (m1.length != m2.length)
+ if (m1.len != m2.len)
return 0;
string_iterator iter1(m1);
string_iterator iter2(m2);
- int n = m1.length;
+ int n = m1.len;
while (--n >= 0) {
node *nd1 = 0;
int c1 = iter1.get(&nd1);
@@ -3084,7 +3455,7 @@ static void decode_args(macro_iterator *mi)
if (!tok.newline() && !tok.eof()) {
node *n;
int c = get_copy(&n);
- for (;;) {
+ for (;;) {
while (c == ' ')
c = get_copy(&n);
if (c == '\n' || c == EOF)
@@ -3126,6 +3497,56 @@ static void decode_args(macro_iterator *mi)
}
}
+static void decode_string_args(macro_iterator *mi)
+{
+ node *n;
+ int c = get_copy(&n);
+ for (;;) {
+ while (c == ' ')
+ c = get_copy(&n);
+ if (c == '\n' || c == EOF) {
+ error("missing `]'");
+ break;
+ }
+ if (c == ']')
+ break;
+ macro arg;
+ int quote_input_level = 0;
+ int done_tab_warning = 0;
+ if (c == '\"') {
+ quote_input_level = input_stack::get_level();
+ c = get_copy(&n);
+ }
+ while (c != EOF && c != '\n'
+ && !(c == ']' && quote_input_level == 0)
+ && !(c == ' ' && quote_input_level == 0)) {
+ if (quote_input_level > 0 && c == '\"'
+ && input_stack::get_level() == quote_input_level) {
+ c = get_copy(&n);
+ if (c == '"') {
+ arg.append(c);
+ c = get_copy(&n);
+ }
+ else
+ break;
+ }
+ else {
+ if (c == 0)
+ arg.append(n);
+ else {
+ if (c == '\t' && quote_input_level == 0 && !done_tab_warning) {
+ warning(WARN_TAB, "tab character in unquoted string argument");
+ done_tab_warning = 1;
+ }
+ arg.append(c);
+ }
+ c = get_copy(&n);
+ }
+ }
+ mi->add_arg(arg);
+ }
+}
+
void macro::invoke(symbol nm)
{
macro_iterator *mi = new macro_iterator(nm, *this);
@@ -3141,7 +3562,7 @@ macro *macro::to_macro()
int macro::empty()
{
- return length == 0;
+ return empty_macro == 1;
}
macro_iterator::macro_iterator(symbol s, macro &m, const char *how_invoked)
@@ -3209,16 +3630,16 @@ void read_request()
int reading_from_terminal = isatty(fileno(stdin));
int had_prompt = 0;
if (!tok.newline() && !tok.eof()) {
- int c = get_copy(NULL);
+ int c = get_copy(0);
while (c == ' ')
- c = get_copy(NULL);
+ c = get_copy(0);
while (c != EOF && c != '\n' && c != ' ') {
- if (!illegal_input_char(c)) {
+ if (!invalid_input_char(c)) {
if (reading_from_terminal)
fputc(c, stderr);
had_prompt = 1;
}
- c = get_copy(NULL);
+ c = get_copy(0);
}
if (c == ' ') {
tok.make_space();
@@ -3234,8 +3655,8 @@ void read_request()
int nl = 0;
int c;
while ((c = getchar()) != EOF) {
- if (illegal_input_char(c))
- warning(WARN_INPUT, "illegal input character code %1", int(c));
+ if (invalid_input_char(c))
+ warning(WARN_INPUT, "invalid input character code %1", int(c));
else {
if (c == '\n') {
if (nl)
@@ -3254,7 +3675,10 @@ void read_request()
tok.next();
}
-void do_define_string(int append)
+enum define_mode { DEFINE_NORMAL, DEFINE_APPEND, DEFINE_IGNORE };
+enum calling_mode { CALLING_NORMAL, CALLING_INDIRECT, CALLING_DISABLE_COMP };
+
+void do_define_string(define_mode mode, calling_mode calling)
{
symbol nm;
node *n;
@@ -3282,8 +3706,10 @@ void do_define_string(int append)
macro mac;
request_or_macro *rm = (request_or_macro *)request_dictionary.lookup(nm);
macro *mm = rm ? rm->to_macro() : 0;
- if (append && mm)
+ if (mode == DEFINE_APPEND && mm)
mac = *mm;
+ if (calling == CALLING_DISABLE_COMP)
+ mac.append(COMPATIBLE_SAVE);
while (c != '\n' && c != EOF) {
if (c == 0)
mac.append(n);
@@ -3295,21 +3721,33 @@ void do_define_string(int append)
mm = new macro;
request_dictionary.define(nm, mm);
}
+ if (calling == CALLING_DISABLE_COMP)
+ mac.append(COMPATIBLE_RESTORE);
*mm = mac;
tok.next();
}
void define_string()
{
- do_define_string(0);
+ do_define_string(DEFINE_NORMAL, CALLING_NORMAL);
+}
+
+void define_nocomp_string()
+{
+ do_define_string(DEFINE_NORMAL, CALLING_DISABLE_COMP);
}
void append_string()
{
- do_define_string(1);
+ do_define_string(DEFINE_APPEND, CALLING_NORMAL);
}
-void define_character()
+void append_nocomp_string()
+{
+ do_define_string(DEFINE_APPEND, CALLING_DISABLE_COMP);
+}
+
+void do_define_character(int fallback)
{
node *n;
int c;
@@ -3343,12 +3781,22 @@ void define_character()
m->append((unsigned char)c);
c = get_copy(&n);
}
- m = ci->set_macro(m);
+ m = ci->set_macro(m, fallback);
if (m)
delete m;
tok.next();
}
+void define_character()
+{
+ do_define_character(0);
+}
+
+void define_fallback_character()
+{
+ do_define_character(1);
+}
+
static void remove_character()
{
tok.skip();
@@ -3371,13 +3819,26 @@ static void interpolate_string(symbol nm)
request_or_macro *p = lookup_request(nm);
macro *m = p->to_macro();
if (!m)
- error("you can only invoke a string using \\*");
+ error("you can only invoke a string or macro using \\*");
else {
string_iterator *si = new string_iterator(*m, "string", nm);
input_stack::push(si);
}
}
+static void interpolate_string_with_args(symbol s)
+{
+ request_or_macro *p = lookup_request(s);
+ macro *m = p->to_macro();
+ if (!m)
+ error("you can only invoke a string or macro using \\*");
+ else {
+ macro_iterator *mi = new macro_iterator(s, *m);
+ decode_string_args(mi);
+ input_stack::push(mi);
+ }
+}
+
/* This class is used for the implementation of \$@. It is used for
each of the closing double quotes. It artificially increases the
input level by 2, so that the closing double quote will appear to have
@@ -3473,9 +3934,6 @@ void handle_initial_title()
// this should be local to define_macro, but cfront 1.2 doesn't support that
static symbol dot_symbol(".");
-enum define_mode { DEFINE_NORMAL, DEFINE_APPEND, DEFINE_IGNORE };
-enum calling_mode { CALLING_NORMAL, CALLING_INDIRECT, CALLING_DISABLE_COMP };
-
void do_define_macro(define_mode mode, calling_mode calling)
{
symbol nm, term;
@@ -3537,11 +3995,17 @@ void do_define_macro(define_mode mode, calling_mode calling)
const char *s = term.contents();
int d = 0;
// see if it matches term
- int i;
- for (i = 0; s[i] != 0; i++) {
- d = get_copy(&n);
- if ((unsigned char)s[i] != d)
- break;
+ int i = 0;
+ if (s[0] != 0) {
+ while ((d = get_copy(&n)) == ' ' || d == '\t')
+ ;
+ if ((unsigned char)s[0] == d) {
+ for (i = 1; s[i] != 0; i++) {
+ d = get_copy(&n);
+ if ((unsigned char)s[i] != d)
+ break;
+ }
+ }
}
if (s[i] == 0
&& ((i == 2 && compatible_flag)
@@ -3625,6 +4089,11 @@ void append_macro()
do_define_macro(DEFINE_APPEND, CALLING_NORMAL);
}
+void append_indirect_macro()
+{
+ do_define_macro(DEFINE_APPEND, CALLING_INDIRECT);
+}
+
void append_nocomp_macro()
{
do_define_macro(DEFINE_APPEND, CALLING_DISABLE_COMP);
@@ -3680,75 +4149,121 @@ void chop_macro()
macro *m = p->to_macro();
if (!m)
error("cannot chop request");
- else if (m->length == 0)
+ else if (m->empty())
error("cannot chop empty macro");
- else
- m->length -= 1;
+ else {
+ int have_restore = 0;
+ // we have to check for additional save/restore pairs which could be
+ // there due to empty am1 requests.
+ for (;;) {
+ if (m->get(m->len - 1) != COMPATIBLE_RESTORE)
+ break;
+ have_restore = 1;
+ m->len -= 1;
+ if (m->get(m->len - 1) != COMPATIBLE_SAVE)
+ break;
+ have_restore = 0;
+ m->len -= 1;
+ if (m->len == 0)
+ break;
+ }
+ if (m->len == 0)
+ error("cannot chop empty macro");
+ else {
+ if (have_restore)
+ m->set(COMPATIBLE_RESTORE, m->len - 1);
+ else
+ m->len -= 1;
+ }
+ }
}
skip_line();
}
-void substring_macro()
+void substring_request()
{
- int start;
+ int start; // 0, 1, ..., n-1 or -1, -2, ...
symbol s = get_name(1);
if (!s.is_null() && get_integer(&start)) {
request_or_macro *p = lookup_request(s);
macro *m = p->to_macro();
if (!m)
- error("cannot substring request");
+ error("cannot apply `substring' on a request");
else {
- if (start <= 0)
- start += m->length;
- else
- start--;
- int end = 0;
+ int end = -1;
if (!has_arg() || get_integer(&end)) {
- if (end <= 0)
- end += m->length;
- else
- end--;
+ int real_length = 0; // 1, 2, ..., n
+ string_iterator iter1(*m);
+ for (int l = 0; l < m->len; l++) {
+ int c = iter1.get(0);
+ if (c == COMPATIBLE_SAVE || c == COMPATIBLE_RESTORE)
+ continue;
+ if (c == EOF)
+ break;
+ real_length++;
+ }
+ if (start < 0)
+ start += real_length;
+ if (end < 0)
+ end += real_length;
if (start > end) {
int tem = start;
start = end;
end = tem;
}
- if (start >= m->length || start == end) {
- m->length = 0;
+ if (start >= real_length || end < 0) {
+ warning(WARN_RANGE,
+ "start and end index of substring out of range");
+ m->len = 0;
if (m->p) {
if (--(m->p->count) <= 0)
delete m->p;
m->p = 0;
}
+ skip_line();
+ return;
}
- else if (start == 0)
- m->length = end;
- else {
- string_iterator iter(*m);
- int i;
- for (i = 0; i < start; i++)
- if (iter.get(0) == EOF)
- break;
- macro mac;
- for (; i < end; i++) {
- node *nd;
- int c = iter.get(&nd);
- if (c == EOF)
- break;
- if (c == 0)
- mac.append(nd);
- else
- mac.append((unsigned char)c);
- }
- *m = mac;
+ if (start < 0) {
+ warning(WARN_RANGE,
+ "start index of substring out of range, set to 0");
+ start = 0;
+ }
+ if (end >= real_length) {
+ warning(WARN_RANGE,
+ "end index of substring out of range, set to string length");
+ end = real_length - 1;
}
+ // now extract the substring
+ string_iterator iter(*m);
+ int i;
+ for (i = 0; i < start; i++) {
+ int c = iter.get(0);
+ while (c == COMPATIBLE_SAVE || c == COMPATIBLE_RESTORE)
+ c = iter.get(0);
+ if (c == EOF)
+ break;
+ }
+ macro mac;
+ for (; i <= end; i++) {
+ node *nd;
+ int c = iter.get(&nd);
+ while (c == COMPATIBLE_SAVE || c == COMPATIBLE_RESTORE)
+ c = iter.get(0);
+ if (c == EOF)
+ break;
+ if (c == 0)
+ mac.append(nd);
+ else
+ mac.append((unsigned char)c);
+ }
+ *m = mac;
}
}
}
skip_line();
}
-void length_macro()
+void length_request()
{
symbol ret;
ret = get_name(1);
@@ -3778,12 +4293,12 @@ void length_macro()
++len;
c = get_copy(&n);
}
- tok.next();
reg *r = (reg*)number_reg_dictionary.lookup(ret);
if (r)
r->set_value(len);
else
set_number_reg(ret, len);
+ tok.next();
}
void asciify_macro()
@@ -3900,19 +4415,20 @@ static int get_line_arg(units *n, int si, charinfo **cp)
{
token start;
start.next();
- if (start.delimiter(1)) {
- tok.next();
- if (get_number(n, si)) {
- if (tok.dummy() || tok.transparent_dummy())
- tok.next();
- if (start != tok) {
- *cp = tok.get_char(1);
- tok.next();
- }
- if (start != tok)
- warning(WARN_DELIM, "closing delimiter does not match");
- return 1;
+ int start_level = input_stack::get_level();
+ if (!start.delimiter(1))
+ return 0;
+ tok.next();
+ if (get_number(n, si)) {
+ if (tok.dummy() || tok.transparent_dummy())
+ tok.next();
+ if (!(start == tok && input_stack::get_level() == start_level)) {
+ *cp = tok.get_char(1);
+ tok.next();
}
+ if (!(start == tok && input_stack::get_level() == start_level))
+ warning(WARN_DELIM, "closing delimiter does not match");
+ return 1;
}
return 0;
}
@@ -4085,65 +4601,6 @@ static symbol get_delim_name()
}
}
-static symbol get_delim_file_name()
-{
- token start;
- start.next();
- if (start.eof()) {
- error("end of input at start of delimited file name");
- return NULL_SYMBOL;
- }
- if (start.newline()) {
- error("can't delimit file name with a newline");
- return NULL_SYMBOL;
- }
- int start_level = input_stack::get_level();
- char abuf[ABUF_SIZE];
- char *buf = abuf;
- int buf_size = ABUF_SIZE;
- int i = 0;
- for (;;) {
- if (i + 1 > buf_size) {
- if (buf == abuf) {
- buf = new char[ABUF_SIZE*2];
- memcpy(buf, abuf, buf_size);
- buf_size = ABUF_SIZE*2;
- }
- else {
- char *old_buf = buf;
- buf = new char[buf_size*2];
- memcpy(buf, old_buf, buf_size);
- buf_size *= 2;
- a_delete old_buf;
- }
- }
- tok.next();
- if (tok.ch() == ']' && input_stack::get_level() == start_level)
- break;
- if ((buf[i] = tok.ch()) == 0) {
- error("missing delimiter (got %1)", tok.description());
- if (buf != abuf)
- a_delete buf;
- return NULL_SYMBOL;
- }
- i++;
- }
- buf[i] = '\0';
- if (buf == abuf) {
- if (i == 0) {
- error("empty delimited file name");
- return NULL_SYMBOL;
- }
- else
- return symbol(buf);
- }
- else {
- symbol s(buf);
- a_delete buf;
- return s;
- }
-}
-
// Implement \R
static void do_register()
@@ -4331,9 +4788,14 @@ static void encode_char(macro *mac, char c)
mac->append(')');
}
}
- else {
- error("%1 is illegal within \\X", tok.description());
- }
+ else if (tok.stretchable_space()
+ || tok.unstretchable_space())
+ mac->append(' ');
+ else if (!(tok.hyphen_indicator()
+ || tok.dummy()
+ || tok.transparent_dummy()
+ || tok.zero_width_break()))
+ error("%1 is invalid within \\X", tok.description());
}
else {
if ((font::use_charnames_in_special) && (c == '\\')) {
@@ -4380,29 +4842,48 @@ node *do_special()
return new special_node(mac);
}
-node *do_suppress()
+void output_request()
{
+ if (!tok.newline() && !tok.eof()) {
+ int c;
+ for (;;) {
+ c = get_copy(0);
+ if (c == '"') {
+ c = get_copy(0);
+ break;
+ }
+ if (c != ' ' && c != '\t')
+ break;
+ }
+ for (; c != '\n' && c != EOF; c = get_copy(0))
+ topdiv->transparent_output(c);
+ topdiv->transparent_output('\n');
+ }
tok.next();
- int c = tok.ch();
- if (c != '[') {
- error("argument(s) of \\O must be enclosed in brackets (got %1)",
- char(c));
+}
+
+extern int image_no; // from node.cc
+
+static node *do_suppress(symbol nm)
+{
+ if (nm.is_null() || nm.is_empty()) {
+ error("expecting an argument to escape \\O");
return 0;
}
- tok.next();
- c = tok.ch();
- tok.next();
- switch (c) {
+ const char *s = nm.contents();
+ switch (*s) {
case '0':
- if (begin_level == 1)
+ if (begin_level == 0)
+ // suppress generation of glyphs
return new suppress_node(0, 0);
break;
case '1':
- if (begin_level == 1)
+ if (begin_level == 0)
+ // enable generation of glyphs
return new suppress_node(1, 0);
break;
case '2':
- if (begin_level == 1)
+ if (begin_level == 0)
return new suppress_node(1, 1);
break;
case '3':
@@ -4411,20 +4892,33 @@ node *do_suppress()
case '4':
begin_level--;
break;
- case '5': {
- symbol filename = get_delim_file_name();
- tok.next();
- if (filename.is_null()) {
- error("missing filename as second argument to \\O");
- return 0;
+ case '5':
+ {
+ s++; // move over '5'
+ char position = *s;
+ if (*s == (char)0) {
+ error("missing position and filename in \\O");
+ return 0;
+ }
+ if (!(position == 'l'
+ || position == 'r'
+ || position == 'c'
+ || position == 'i')) {
+ error("l, r, c, or i position expected (got %1 in \\O)", position);
+ return 0;
+ }
+ s++; // onto image name
+ if (s == (char *)0) {
+ error("missing image name for \\O");
+ return 0;
+ }
+ image_no++;
+ if (begin_level == 0)
+ return new suppress_node(symbol(s), position, image_no);
}
- if (begin_level == 1)
- return new suppress_node(filename, 'i');
- return 0;
break;
- }
default:
- error("`%1' is an invalid argument to \\O", char(c));
+ error("`%1' is an invalid argument to \\O", *s);
}
return 0;
}
@@ -4434,7 +4928,7 @@ void special_node::tprint(troff_output_file *out)
tprint_start(out);
string_iterator iter(mac);
for (;;) {
- int c = iter.get(NULL);
+ int c = iter.get(0);
if (c == EOF)
break;
for (const char *s = ::asciify(c); *s; s++)
@@ -4484,7 +4978,7 @@ static void skip_alternative()
level++;
int c;
for (;;) {
- c = input_stack::get(NULL);
+ c = input_stack::get(0);
if (c == EOF)
break;
if (c == ESCAPE_LEFT_BRACE)
@@ -4492,7 +4986,7 @@ static void skip_alternative()
else if (c == ESCAPE_RIGHT_BRACE)
--level;
else if (c == escape_char && escape_char > 0)
- switch(input_stack::get(NULL)) {
+ switch(input_stack::get(0)) {
case '{':
++level;
break;
@@ -4500,7 +4994,7 @@ static void skip_alternative()
--level;
break;
case '"':
- while ((c = input_stack::get(NULL)) != '\n' && c != EOF)
+ while ((c = input_stack::get(0)) != '\n' && c != EOF)
;
}
/*
@@ -4574,6 +5068,16 @@ int do_if_request()
? request_dictionary.lookup(nm) != 0
: number_reg_dictionary.lookup(nm) != 0);
}
+ else if (c == 'm') {
+ tok.next();
+ symbol nm = get_long_name(1);
+ if (nm.is_null()) {
+ skip_alternative();
+ return 0;
+ }
+ result = (nm == default_symbol
+ || color_dictionary.lookup(nm) != 0);
+ }
else if (c == 'c') {
tok.next();
tok.skip();
@@ -4660,65 +5164,6 @@ void else_request()
}
}
-/*
- * begin - if this is the outermost html_begin request then execute the
- * rest of the line, else skip line
- */
-
-void begin()
-{
- begin_level++;
- if (begin_level == 1)
- begin_alternative();
- else
- skip_alternative();
-}
-
-/*
- * end - if this is the outermost html_end request then execute the
- * rest of the line, else skip line
- */
-
-void end()
-{
- begin_level--;
- if (begin_level == 0)
- begin_alternative();
- else
- skip_alternative();
- if (begin_level < 0)
- begin_level = 0;
-}
-
-/*
- * image - implements the directive `.image {l|r|c|i} filename'
- * which places the filename into a node which is later
- * written out
- *
- * . either as a special in the form of an image tag for -Thtml
- * . or as an image region definition for all other devices
- *
- */
-
-void image()
-{
- if (has_arg()) {
- char position = tok.ch();
- if (!(position == 'l'
- || position == 'r'
- || position == 'c'
- || position == 'i')) {
- error("l, r, c, or i expected (got %1)", tok.description());
- position = 'c';
- }
- tok.next();
- symbol filename = get_long_name(1);
- if (!filename.is_null())
- curenv->add_node(new suppress_node(filename, position));
- }
- skip_line();
-}
-
static int while_depth = 0;
static int while_break_flag = 0;
@@ -4766,7 +5211,7 @@ void while_request()
input_stack::push(new string_iterator(mac, "while loop"));
tok.next();
if (!do_if_request()) {
- while (input_stack::get(NULL) != EOF)
+ while (input_stack::get(0) != EOF)
;
break;
}
@@ -4790,7 +5235,7 @@ void while_break_request()
}
else {
while_break_flag = 1;
- while (input_stack::get(NULL) != EOF)
+ while (input_stack::get(0) != EOF)
;
tok.next();
}
@@ -4803,7 +5248,7 @@ void while_continue_request()
skip_line();
}
else {
- while (input_stack::get(NULL) != EOF)
+ while (input_stack::get(0) != EOF)
;
tok.next();
}
@@ -4846,12 +5291,12 @@ void pipe_source()
error("missing command");
else {
int c;
- while ((c = get_copy(NULL)) == ' ' || c == '\t')
+ while ((c = get_copy(0)) == ' ' || c == '\t')
;
int buf_size = 24;
char *buf = new char[buf_size];
int buf_used = 0;
- for (; c != '\n' && c != EOF; c = get_copy(NULL)) {
+ for (; c != '\n' && c != EOF; c = get_copy(0)) {
const char *s = asciify(c);
int slen = strlen(s);
if (buf_used + slen + 1> buf_size) {
@@ -4938,7 +5383,7 @@ int ps_get_line(char *buf, FILE *fp, const char* filename)
int err = 0;
while (c != '\r' && c != '\n' && c != EOF) {
if ((c < 0x1b && !white_space(c)) || c == 0x7f)
- error("illegal input character code %1 in `%2'", int(c), filename);
+ error("invalid input character code %1 in `%2'", int(c), filename);
else if (i < PS_LINE_MAX)
buf[i++] = c;
else if (!err) {
@@ -4991,14 +5436,15 @@ void do_ps_file(FILE *fp, const char* filename)
if (res == 1) {
assign_registers(bb.llx, bb.lly, bb.urx, bb.ury);
return;
- } else if (res == 2) {
+ }
+ else if (res == 2) {
bb_at_end = 1;
break;
}
else {
error("the arguments to the %%%%BoundingBox comment in `%1' are bad",
filename);
- return;
+ return;
}
}
}
@@ -5132,8 +5578,12 @@ const char *asciify(int c)
case ESCAPE_COLON:
buf[1] = ':';
break;
+ case COMPATIBLE_SAVE:
+ case COMPATIBLE_RESTORE:
+ buf[0] = '\0';
+ break;
default:
- if (illegal_input_char(c))
+ if (invalid_input_char(c))
buf[0] = '\0';
else
buf[0] = c;
@@ -5159,7 +5609,7 @@ const char *input_char_description(int c)
return "a node";
}
static char buf[sizeof("magic character code ") + 1 + INT_DIGITS];
- if (illegal_input_char(c)) {
+ if (invalid_input_char(c)) {
const char *s = asciify(c);
if (*s) {
buf[0] = '`';
@@ -5187,15 +5637,15 @@ void do_terminal(int newline, int string_like)
if (!tok.newline() && !tok.eof()) {
int c;
for (;;) {
- c = get_copy(NULL);
+ c = get_copy(0);
if (string_like && c == '"') {
- c = get_copy(NULL);
+ c = get_copy(0);
break;
}
if (c != ' ' && c != '\t')
break;
}
- for (; c != '\n' && c != EOF; c = get_copy(NULL))
+ for (; c != '\n' && c != EOF; c = get_copy(0))
fputs(asciify(c), stderr);
}
if (newline)
@@ -5278,7 +5728,9 @@ void close_request()
skip_line();
}
-void write_request()
+// .write and .writec
+
+void do_write_request(int newline)
{
symbol stream = get_name(1);
if (stream.is_null()) {
@@ -5292,17 +5744,28 @@ void write_request()
return;
}
int c;
- while ((c = get_copy(NULL)) == ' ')
+ while ((c = get_copy(0)) == ' ')
;
if (c == '"')
- c = get_copy(NULL);
- for (; c != '\n' && c != EOF; c = get_copy(NULL))
+ c = get_copy(0);
+ for (; c != '\n' && c != EOF; c = get_copy(0))
fputs(asciify(c), fp);
- fputc('\n', fp);
+ if (newline)
+ fputc('\n', fp);
fflush(fp);
tok.next();
}
+void write_request()
+{
+ do_write_request(1);
+}
+
+void write_request_continue()
+{
+ do_write_request(0);
+}
+
void write_macro_request()
{
symbol stream = get_name(1);
@@ -5338,6 +5801,47 @@ void write_macro_request()
skip_line();
}
+void warnscale_request()
+{
+ if (has_arg()) {
+ char c = tok.ch();
+ if (c == 'u')
+ warn_scale = 1.0;
+ else if (c == 'i')
+ warn_scale = (double)units_per_inch;
+ else if (c == 'c')
+ warn_scale = (double)units_per_inch / 2.54;
+ else if (c == 'p')
+ warn_scale = (double)units_per_inch / 72.0;
+ else if (c == 'P')
+ warn_scale = (double)units_per_inch / 6.0;
+ else {
+ warning(WARN_SCALE,
+ "invalid scaling indicator `%1', using `i' instead", c);
+ c = 'i';
+ }
+ warn_scaling_indicator = c;
+ }
+ skip_line();
+}
+
+void spreadwarn_request()
+{
+ hunits n;
+ if (has_arg() && get_hunits(&n, 'm')) {
+ if (n < 0)
+ n = 0;
+ hunits em = curenv->get_size();
+ spread_limit = (double)n.to_units()
+ / (em.is_zero() ? hresolution : em.to_units());
+ }
+ else
+ spread_limit = -spread_limit - 1; // no arg toggles on/off without
+ // changing value; we mirror at
+ // -0.5 to make zero a valid value
+ skip_line();
+}
+
static void init_charset_table()
{
char buf[16];
@@ -5369,7 +5873,13 @@ static void init_charset_table()
page_character = charset_table['%'];
}
-static void do_translate(int translate_transparent)
+static void init_hpf_code_table()
+{
+ for (int i = 0; i < 256; i++)
+ hpf_code_table[i] = i;
+}
+
+static void do_translate(int translate_transparent, int translate_input)
{
tok.skip();
while (!tok.newline() && !tok.eof()) {
@@ -5408,9 +5918,9 @@ static void do_translate(int translate_transparent)
if (ci2 == 0)
break;
if (ci1 == ci2)
- ci1->set_translation(0, translate_transparent);
+ ci1->set_translation(0, translate_transparent, translate_input);
else
- ci1->set_translation(ci2, translate_transparent);
+ ci1->set_translation(ci2, translate_transparent, translate_input);
}
tok.next();
}
@@ -5419,12 +5929,17 @@ static void do_translate(int translate_transparent)
void translate()
{
- do_translate(1);
+ do_translate(1, 0);
}
void translate_no_transparent()
{
- do_translate(0);
+ do_translate(0, 0);
+}
+
+void translate_input()
+{
+ do_translate(1, 1);
}
void char_flags()
@@ -5463,12 +5978,42 @@ void hyphenation_code()
break;
}
ci->set_hyphenation_code(c);
+ if (ci->get_translation()
+ && ci->get_translation()->get_translation_input())
+ ci->get_translation()->set_hyphenation_code(c);
tok.next();
tok.skip();
}
skip_line();
}
+void hyphenation_patterns_file_code()
+{
+ tok.skip();
+ while (!tok.newline() && !tok.eof()) {
+ int n1, n2;
+ if (get_integer(&n1) && (0 <= n1 && n1 <= 255)) {
+ if (!has_arg()) {
+ error("missing output hyphenation code");
+ break;
+ }
+ if (get_integer(&n2) && (0 <= n2 && n2 <= 255)) {
+ hpf_code_table[n1] = n2;
+ tok.skip();
+ }
+ else {
+ error("output hyphenation code must be integer in the range 0..255");
+ break;
+ }
+ }
+ else {
+ error("input hyphenation code must be integer in the range 0..255");
+ break;
+ }
+ }
+ skip_line();
+}
+
charinfo *token::get_char(int required)
{
if (type == TOKEN_CHAR)
@@ -5553,17 +6098,28 @@ int token::add_to_node_list(node **pp)
case TOKEN_RIGHT_BRACE:
break;
case TOKEN_SPACE:
- n = new hmotion_node(curenv->get_space_width());
+ n = new hmotion_node(curenv->get_space_width(),
+ curenv->get_fill_color());
break;
case TOKEN_SPECIAL:
*pp = (*pp)->add_char(get_charinfo(nm), curenv, &w, &s);
break;
case TOKEN_STRETCHABLE_SPACE:
- n = new unbreakable_space_node(curenv->get_space_width());
+ n = new unbreakable_space_node(curenv->get_space_width(),
+ curenv->get_fill_color());
+ break;
+ case TOKEN_UNSTRETCHABLE_SPACE:
+ n = new space_char_hmotion_node(curenv->get_space_width(),
+ curenv->get_fill_color());
break;
case TOKEN_TRANSPARENT_DUMMY:
n = new transparent_dummy_node;
break;
+ case TOKEN_ZERO_WIDTH_BREAK:
+ n = new space_node(H0, curenv->get_fill_color());
+ n->freeze_space();
+ n->is_escape_colon();
+ break;
default:
return 0;
}
@@ -5580,7 +6136,8 @@ void token::process()
return;
switch (type) {
case TOKEN_BACKSPACE:
- curenv->add_node(new hmotion_node(-curenv->get_space_width()));
+ curenv->add_node(new hmotion_node(-curenv->get_space_width(),
+ curenv->get_fill_color()));
break;
case TOKEN_CHAR:
curenv->add_char(charset_table[c]);
@@ -5631,7 +6188,7 @@ void token::process()
curenv->add_char(get_charinfo_by_number(val));
break;
case TOKEN_REQUEST:
- // handled in process_input_stack
+ // handled in process_input_stack()
break;
case TOKEN_RIGHT_BRACE:
break;
@@ -5645,7 +6202,12 @@ void token::process()
curenv->spread();
break;
case TOKEN_STRETCHABLE_SPACE:
- curenv->add_node(new unbreakable_space_node(curenv->get_space_width()));
+ curenv->add_node(new unbreakable_space_node(curenv->get_space_width(),
+ curenv->get_fill_color()));
+ break;
+ case TOKEN_UNSTRETCHABLE_SPACE:
+ curenv->add_node(new space_char_hmotion_node(curenv->get_space_width(),
+ curenv->get_fill_color()));
break;
case TOKEN_TAB:
curenv->handle_tab(0);
@@ -5655,6 +6217,14 @@ void token::process()
case TOKEN_TRANSPARENT_DUMMY:
curenv->add_node(new transparent_dummy_node);
break;
+ case TOKEN_ZERO_WIDTH_BREAK:
+ {
+ node *tmp = new space_node(H0, curenv->get_fill_color());
+ tmp->freeze_space();
+ tmp->is_escape_colon();
+ curenv->add_node(tmp);
+ break;
+ }
default:
assert(0);
}
@@ -5764,7 +6334,7 @@ void abort_request()
if (c == EOF || c == '\n')
fputs("User Abort.", stderr);
else {
- for (; c != '\n' && c != EOF; c = get_copy(NULL))
+ for (; c != '\n' && c != EOF; c = get_copy(0))
fputs(asciify(c), stderr);
}
fputc('\n', stderr);
@@ -5780,7 +6350,7 @@ char *read_string()
;
int i = 0;
while (c != '\n' && c != EOF) {
- if (!illegal_input_char(c)) {
+ if (!invalid_input_char(c)) {
if (i + 2 > len) {
char *tem = s;
s = new char[len*2];
@@ -5817,8 +6387,20 @@ void pipe_output()
skip_line();
}
else {
- if ((pipe_command = read_string()) == 0)
+ char *pc;
+ if ((pc = read_string()) == 0)
error("can't pipe to empty command");
+ if (pipe_command) {
+ char *s = new char[strlen(pipe_command) + strlen(pc) + 1 + 1];
+ strcpy(s, pipe_command);
+ strcat(s, "|");
+ strcat(s, pc);
+ a_delete pipe_command;
+ a_delete pc;
+ pipe_command = s;
+ }
+ else
+ pipe_command = pc;
}
#endif /* not POPEN_MISSING */
}
@@ -5897,8 +6479,8 @@ void transparent_file()
int c = getc(fp);
if (c == EOF)
break;
- if (illegal_input_char(c))
- warning(WARN_INPUT, "illegal input character code %1", int(c));
+ if (invalid_input_char(c))
+ warning(WARN_INPUT, "invalid input character code %1", int(c));
else {
curdiv->transparent_output(c);
bol = c == '\n';
@@ -6098,7 +6680,7 @@ static int evaluate_expression(const char *expr, units *res)
input_stack::push(make_temp_iterator(expr));
tok.next();
int success = get_number(res, 'u');
- while (input_stack::get(NULL) != EOF)
+ while (input_stack::get(0) != EOF)
;
return success;
}
@@ -6129,7 +6711,7 @@ static void set_string(const char *name, const char *value)
{
macro *m = new macro;
for (const char *p = value; *p; p++)
- if (!illegal_input_char((unsigned char)*p))
+ if (!invalid_input_char((unsigned char)*p))
m->append(*p);
request_dictionary.define(name, m);
}
@@ -6177,7 +6759,7 @@ static void add_string(const char *s, string_list **p)
void usage(FILE *stream, const char *prog)
{
fprintf(stream,
-"usage: %s -abivzCERU -wname -Wname -dcs -ffam -mname -nnum -olist\n"
+"usage: %s -abcivzCERU -wname -Wname -dcs -ffam -mname -nnum -olist\n"
" -rcn -Tname -Fdir -Mdir [files...]\n",
prog);
}
@@ -6213,10 +6795,10 @@ int main(int argc, char **argv)
static const struct option long_options[] = {
{ "help", no_argument, 0, CHAR_MAX + 1 },
{ "version", no_argument, 0, 'v' },
- { NULL, 0, 0, 0 }
+ { 0, 0, 0, 0 }
};
- while ((c = getopt_long(argc, argv, "abivw:W:zCEf:m:n:o:r:d:F:M:T:tqs:RU",
- long_options, NULL))
+ while ((c = getopt_long(argc, argv, "abcivw:W:zCEf:m:n:o:r:d:F:M:T:tqs:RU",
+ long_options, 0))
!= EOF)
switch(c) {
case 'v':
@@ -6232,6 +6814,9 @@ int main(int argc, char **argv)
break;
case 'C':
compatible_flag = 1;
+ // fall through
+ case 'c':
+ color_flag = 0;
break;
case 'M':
macro_path.command_line_dir(optarg);
@@ -6316,6 +6901,7 @@ int main(int argc, char **argv)
mac_path = &macro_path;
set_string(".T", device);
init_charset_table();
+ init_hpf_code_table();
if (!font::load_desc())
fatal("sorry, I can't continue");
units_per_inch = font::res;
@@ -6323,6 +6909,8 @@ int main(int argc, char **argv)
vresolution = font::vert;
sizescale = font::sizescale;
tcommand_flag = font::tcommand;
+ warn_scale = (double)units_per_inch;
+ warn_scaling_indicator = 'i';
if (!fflag && font::family != 0 && *font::family != '\0')
default_family = symbol(font::family);
font_size::init_size_table(font::sizes);
@@ -6347,7 +6935,6 @@ int main(int argc, char **argv)
init_column_requests();
#endif /* COLUMN */
init_node_requests();
- init_markup_requests();
number_reg_dictionary.define(".T", new constant_reg(tflag ? "1" : "0"));
init_registers();
init_reg_requests();
@@ -6408,6 +6995,9 @@ static void init_registers()
t = time(0);
// Use struct here to work around misfeature in old versions of g++.
struct tm *tt = localtime(&t);
+ set_number_reg("seconds", int(tt->tm_sec));
+ set_number_reg("minutes", int(tt->tm_min));
+ set_number_reg("hours", int(tt->tm_hour));
set_number_reg("dw", int(tt->tm_wday + 1));
set_number_reg("dy", int(tt->tm_mday));
set_number_reg("mo", int(tt->tm_mon + 1));
@@ -6458,120 +7048,126 @@ void get_output_registers(int *minx, int *miny, int *maxx, int *maxy)
*maxy = output_reg_maxy_contents;
}
-void init_markup_requests()
-{
- init_request("begin", begin);
- init_request("end", end);
- init_request("image", image);
-}
-
void init_input_requests()
{
- init_request("ds", define_string);
+ init_request("ab", abort_request);
+ init_request("als", alias_macro);
+ init_request("am", append_macro);
+ init_request("am1", append_nocomp_macro);
+ init_request("ami", append_indirect_macro);
init_request("as", append_string);
+ init_request("as1", append_nocomp_string);
+ init_request("asciify", asciify_macro);
+ init_request("backtrace", backtrace_request);
+ init_request("blm", blank_line_macro);
+ init_request("break", while_break_request);
+ init_request("cf", copy_file);
+ init_request("cflags", char_flags);
+ init_request("char", define_character);
+ init_request("chop", chop_macro);
+ init_request("close", close_request);
+ init_request("color", activate_color);
+ init_request("continue", while_continue_request);
+ init_request("cp", compatible);
init_request("de", define_macro);
- init_request("dei", define_indirect_macro);
init_request("de1", define_nocomp_macro);
- init_request("am", append_macro);
- init_request("am1", append_nocomp_macro);
+ init_request("defcolor", define_color);
+ init_request("dei", define_indirect_macro);
+ init_request("do", do_request);
+ init_request("ds", define_string);
+ init_request("ds1", define_nocomp_string);
+ init_request("ec", set_escape_char);
+ init_request("ecr", restore_escape_char);
+ init_request("ecs", save_escape_char);
+ init_request("el", else_request);
+ init_request("em", end_macro);
+ init_request("eo", escape_off);
+ init_request("ex", exit_request);
+ init_request("fchar", define_fallback_character);
+#ifdef WIDOW_CONTROL
+ init_request("fpl", flush_pending_lines);
+#endif /* WIDOW_CONTROL */
+ init_request("hcode", hyphenation_code);
+ init_request("hpfcode", hyphenation_patterns_file_code);
+ init_request("ie", if_else_request);
+ init_request("if", if_request);
init_request("ig", ignore);
- init_request("rm", remove_macro);
- init_request("rn", rename_macro);
+ init_request("length", length_request);
+ init_request("lf", line_file);
+ init_request("mso", macro_source);
init_request("nop", nop_request);
- init_request("if", if_request);
- init_request("ie", if_else_request);
- init_request("el", else_request);
- init_request("so", source);
init_request("nx", next_file);
- init_request("pm", print_macros);
- init_request("eo", escape_off);
- init_request("ec", set_escape_char);
- init_request("ecs", save_escape_char);
- init_request("ecr", restore_escape_char);
+ init_request("open", open_request);
+ init_request("opena", opena_request);
+ init_request("output", output_request);
init_request("pc", set_page_character);
+ init_request("pi", pipe_output);
+ init_request("pm", print_macros);
+ init_request("psbb", ps_bbox_request);
+#ifndef POPEN_MISSING
+ init_request("pso", pipe_source);
+#endif /* not POPEN_MISSING */
+ init_request("rchar", remove_character);
+ init_request("rd", read_request);
+ init_request("return", return_macro_request);
+ init_request("rm", remove_macro);
+ init_request("rn", rename_macro);
+ init_request("shift", shift);
+ init_request("so", source);
+ init_request("spreadwarn", spreadwarn_request);
+ init_request("substring", substring_request);
+ init_request("sy", system_request);
init_request("tm", terminal);
init_request("tm1", terminal1);
init_request("tmc", terminal_continue);
- init_request("ex", exit_request);
- init_request("return", return_macro_request);
- init_request("em", end_macro);
- init_request("blm", blank_line_macro);
init_request("tr", translate);
+ init_request("trf", transparent_file);
+ init_request("trin", translate_input);
init_request("trnt", translate_no_transparent);
- init_request("ab", abort_request);
- init_request("pi", pipe_output);
- init_request("cf", copy_file);
- init_request("sy", system_request);
- init_request("lf", line_file);
- init_request("cflags", char_flags);
- init_request("shift", shift);
- init_request("rd", read_request);
- init_request("cp", compatible);
- init_request("char", define_character);
- init_request("rchar", remove_character);
- init_request("hcode", hyphenation_code);
- init_request("while", while_request);
- init_request("break", while_break_request);
- init_request("continue", while_continue_request);
- init_request("als", alias_macro);
- init_request("backtrace", backtrace_request);
- init_request("chop", chop_macro);
- init_request("substring", substring_macro);
- init_request("length", length_macro);
- init_request("asciify", asciify_macro);
init_request("unformat", unformat_macro);
init_request("warn", warn_request);
- init_request("open", open_request);
- init_request("opena", opena_request);
- init_request("close", close_request);
+ init_request("while", while_request);
init_request("write", write_request);
+ init_request("writec", write_request_continue);
init_request("writem", write_macro_request);
- init_request("trf", transparent_file);
-#ifdef WIDOW_CONTROL
- init_request("fpl", flush_pending_lines);
-#endif /* WIDOW_CONTROL */
init_request("nroff", nroff_request);
init_request("troff", troff_request);
#ifdef COLUMN
init_request("vj", vjustify);
#endif /* COLUMN */
- init_request("mso", macro_source);
- init_request("do", do_request);
-#ifndef POPEN_MISSING
- init_request("pso", pipe_source);
-#endif /* not POPEN_MISSING */
- init_request("psbb", ps_bbox_request);
- number_reg_dictionary.define("systat", new variable_reg(&system_status));
- number_reg_dictionary.define("slimit",
- new variable_reg(&input_stack::limit));
+ init_request("warnscale", warnscale_request);
number_reg_dictionary.define(".$", new nargs_reg);
- number_reg_dictionary.define(".c", new lineno_reg);
- number_reg_dictionary.define("c.", new writable_lineno_reg);
- number_reg_dictionary.define(".F", new filename_reg);
number_reg_dictionary.define(".C", new constant_int_reg(&compatible_flag));
+ number_reg_dictionary.define(".F", new filename_reg);
number_reg_dictionary.define(".H", new constant_int_reg(&hresolution));
- number_reg_dictionary.define(".V", new constant_int_reg(&vresolution));
number_reg_dictionary.define(".R", new constant_reg("10000"));
- extern const char *major_version;
- number_reg_dictionary.define(".x", new constant_reg(major_version));
- extern const char *minor_version;
- number_reg_dictionary.define(".y", new constant_reg(minor_version));
+ number_reg_dictionary.define(".V", new constant_int_reg(&vresolution));
extern const char *revision;
number_reg_dictionary.define(".Y", new constant_reg(revision));
+ number_reg_dictionary.define(".c", new lineno_reg);
number_reg_dictionary.define(".g", new constant_reg("1"));
+ number_reg_dictionary.define(".color", new constant_int_reg(&color_flag));
number_reg_dictionary.define(".warn", new constant_int_reg(&warning_mask));
+ extern const char *major_version;
+ number_reg_dictionary.define(".x", new constant_reg(major_version));
+ extern const char *minor_version;
+ number_reg_dictionary.define(".y", new constant_reg(minor_version));
+ number_reg_dictionary.define("c.", new writable_lineno_reg);
number_reg_dictionary.define("llx", new variable_reg(&llx_reg_contents));
number_reg_dictionary.define("lly", new variable_reg(&lly_reg_contents));
- number_reg_dictionary.define("urx", new variable_reg(&urx_reg_contents));
- number_reg_dictionary.define("ury", new variable_reg(&ury_reg_contents));
- number_reg_dictionary.define("opminx",
- new variable_reg(&output_reg_minx_contents));
- number_reg_dictionary.define("opminy",
- new variable_reg(&output_reg_miny_contents));
number_reg_dictionary.define("opmaxx",
new variable_reg(&output_reg_maxx_contents));
number_reg_dictionary.define("opmaxy",
new variable_reg(&output_reg_maxy_contents));
+ number_reg_dictionary.define("opminx",
+ new variable_reg(&output_reg_minx_contents));
+ number_reg_dictionary.define("opminy",
+ new variable_reg(&output_reg_miny_contents));
+ number_reg_dictionary.define("slimit",
+ new variable_reg(&input_stack::limit));
+ number_reg_dictionary.define("systat", new variable_reg(&system_status));
+ number_reg_dictionary.define("urx", new variable_reg(&urx_reg_contents));
+ number_reg_dictionary.define("ury", new variable_reg(&ury_reg_contents));
}
object_dictionary request_dictionary(501);
@@ -6718,12 +7314,20 @@ static node *read_draw_node()
if (no_last_v)
error("even number of arguments needed for spline");
break;
+ case 'f':
+ if (npoints != 1 || !no_last_v) {
+ error("one argument needed for gray shade");
+ npoints = 1;
+ point[0].v = V0;
+ }
default:
// silently pass it through
break;
}
draw_node *dn = new draw_node(type, point, npoints,
- curenv->get_font_size());
+ curenv->get_font_size(),
+ curenv->get_glyph_color(),
+ curenv->get_fill_color());
a_delete point;
return dn;
}
@@ -6758,6 +7362,7 @@ static struct {
{ "mac", WARN_MAC },
{ "reg", WARN_REG },
{ "ig", WARN_IG },
+ { "color", WARN_COLOR },
{ "all", WARN_TOTAL & ~(WARN_DI | WARN_MAC | WARN_REG) },
{ "w", WARN_TOTAL },
{ "default", DEFAULT_WARNING_MASK },
@@ -6808,7 +7413,7 @@ static void copy_mode_error(const char *format,
error(format, arg1, arg2, arg3);
}
-enum error_type { WARNING, ERROR, FATAL };
+enum error_type { WARNING, OUTPUT_WARNING, ERROR, FATAL };
static void do_error(error_type type,
const char *format,
@@ -6837,6 +7442,18 @@ static void do_error(error_type type,
case WARNING:
fputs("warning: ", stderr);
break;
+ case OUTPUT_WARNING:
+ double fromtop = topdiv->get_vertical_position().to_units() / warn_scale;
+ fprintf(stderr, "warning [p %d, %.1f%c",
+ topdiv->get_page_number(), fromtop, warn_scaling_indicator);
+ if (topdiv != curdiv) {
+ double fromtop1 = curdiv->get_vertical_position().to_units()
+ / warn_scale;
+ fprintf(stderr, ", div `%s', %.1f%c",
+ curdiv->get_diversion_name(), fromtop1, warn_scaling_indicator);
+ }
+ fprintf(stderr, "]: ");
+ break;
}
errprint(format, arg1, arg2, arg3);
fputc('\n', stderr);
@@ -6859,6 +7476,20 @@ int warning(warning_type t,
return 0;
}
+int output_warning(warning_type t,
+ const char *format,
+ const errarg &arg1,
+ const errarg &arg2,
+ const errarg &arg3)
+{
+ if ((t & warning_mask) != 0) {
+ do_error(OUTPUT_WARNING, format, arg1, arg2, arg3);
+ return 1;
+ }
+ else
+ return 0;
+}
+
void error(const char *format,
const errarg &arg1,
const errarg &arg2,
@@ -6916,8 +7547,9 @@ int charinfo::next_index = 0;
charinfo::charinfo(symbol s)
: translation(0), mac(0), special_translation(TRANSLATE_NONE),
- hyphenation_code(0), flags(0), ascii_code(0), not_found(0),
- transparent_translate(1), nm(s)
+ hyphenation_code(0), flags(0), ascii_code(0), asciify_code(0),
+ not_found(0), transparent_translate(1), translate_input(0),
+ fallback(0), nm(s)
{
index = next_index++;
}
@@ -6927,9 +7559,18 @@ void charinfo::set_hyphenation_code(unsigned char c)
hyphenation_code = c;
}
-void charinfo::set_translation(charinfo *ci, int tt)
+void charinfo::set_translation(charinfo *ci, int tt, int ti)
{
translation = ci;
+ if (ci && ti) {
+ if (hyphenation_code != 0)
+ ci->set_hyphenation_code(hyphenation_code);
+ if (asciify_code != 0)
+ ci->set_asciify_code(asciify_code);
+ else if (ascii_code != 0)
+ ci->set_asciify_code(ascii_code);
+ ci->set_translation_input();
+ }
special_translation = TRANSLATE_NONE;
transparent_translate = tt;
}
@@ -6946,10 +7587,16 @@ void charinfo::set_ascii_code(unsigned char c)
ascii_code = c;
}
-macro *charinfo::set_macro(macro *m)
+void charinfo::set_asciify_code(unsigned char c)
+{
+ asciify_code = c;
+}
+
+macro *charinfo::set_macro(macro *m, int f)
{
macro *tem = mac;
mac = m;
+ fallback = f;
return tem;
}
diff --git a/contrib/groff/src/roff/troff/node.cc b/contrib/groff/src/roff/troff/node.cc
index 2d2d799..650bf0e 100644
--- a/contrib/groff/src/roff/troff/node.cc
+++ b/contrib/groff/src/roff/troff/node.cc
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001
+/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001, 2002
Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
@@ -19,11 +19,12 @@ 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 "troff.h"
+
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
-#include "troff.h"
#include "symbol.h"
#include "dictionary.h"
#include "hvunits.h"
@@ -35,6 +36,8 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "font.h"
#include "reg.h"
#include "input.h"
+#include "div.h"
+#include "geometry.h"
#include "nonposix.h"
@@ -60,8 +63,8 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
* debugging grohtml
*/
-static int image_no=0;
-static int suppress_start_page=0;
+int image_no = 0;
+static int suppress_start_page = 0;
#define STORE_WIDTH 1
@@ -147,6 +150,7 @@ public:
int get_bold(hunits *);
int is_special();
int is_style();
+ friend symbol get_font_name(int, environment *);
};
class tfont_spec {
@@ -234,6 +238,14 @@ inline int font_info::is_style()
return fm == 0;
}
+tfont *make_tfont(tfont_spec &spec)
+{
+ for (tfont *p = tfont::tfont_list; p; p = p->next)
+ if (*p == spec)
+ return p;
+ return new tfont(spec);
+}
+
// this is the current_font, fontno is where we found the character,
// presumably a special font
@@ -378,6 +390,15 @@ symbol font_info::get_name()
return internal_name;
}
+symbol get_font_name(int fontno, environment *env)
+{
+ symbol f = font_table[fontno]->get_name();
+ if (font_table[fontno]->is_style()) {
+ return concat(env->get_family()->nm, f);
+ }
+ return f;
+}
+
hunits font_info::get_space_width(font_size fs, int space_size)
{
if (is_constant_spaced == CONSTANT_SPACE_NONE)
@@ -626,14 +647,6 @@ inline int tfont::get_kern(charinfo *c1, charinfo *c2, hunits *res)
}
}
-tfont *make_tfont(tfont_spec &spec)
-{
- for (tfont *p = tfont::tfont_list; p; p = p->next)
- if (*p == spec)
- return p;
- return new tfont(spec);
-}
-
tfont *tfont::tfont_list = 0;
tfont::tfont(tfont_spec &spec) : tfont_spec(spec)
@@ -658,7 +671,7 @@ class real_output_file : public output_file {
int piped;
#endif
int printing; // decision via optional page list
- int output_on; // .output 1 or .output 0 requests
+ int output_on; // \O[0] or \O[1] escape calls
virtual void really_transparent_char(unsigned char) = 0;
virtual void really_print_line(hunits x, vunits y, node *n,
vunits before, vunits after, hunits width) = 0;
@@ -727,6 +740,8 @@ class troff_output_file : public real_output_file {
int current_slant;
int current_height;
tfont *current_tfont;
+ color *current_fill_color;
+ color *current_glyph_color;
int current_font_number;
symbol *font_position;
int nfont_positions;
@@ -739,6 +754,7 @@ class troff_output_file : public real_output_file {
void put(char c);
void put(unsigned char c);
void put(int i);
+ void put(unsigned int i);
void put(const char *s);
void set_font(tfont *tf);
void flush_tbuf();
@@ -746,13 +762,13 @@ public:
troff_output_file();
~troff_output_file();
void trailer(vunits page_length);
- void put_char(charinfo *ci, tfont *tf);
- void put_char_width(charinfo *ci, tfont *tf, hunits w, hunits k);
+ void put_char(charinfo *, tfont *, color *, color *);
+ void put_char_width(charinfo *, tfont *, color *, color *, hunits, hunits);
void right(hunits);
void down(vunits);
void moveto(hunits, vunits);
- void start_special(tfont *tf, int no_init_string = 0);
- void start_special(int no_init_string = 0);
+ void start_special(tfont *, color *, color *, int = 0);
+ void start_special();
void special_char(unsigned char c);
void end_special();
void word_marker();
@@ -763,9 +779,11 @@ public:
void really_put_filename(const char *filename);
void really_on();
void really_off();
- void draw(char, hvpair *, int, font_size);
+ void draw(char, hvpair *, int, font_size, color *, color *);
void determine_line_limits (char code, hvpair *point, int npoints);
void check_charinfo(tfont *tf, charinfo *ci);
+ void glyph_color(color *c);
+ void fill_color(color *c);
int get_hpos() { return hpos; }
int get_vpos() { return vpos; }
};
@@ -796,29 +814,29 @@ inline void troff_output_file::put(int i)
put_string(i_to_a(i), fp);
}
-void troff_output_file::start_special(tfont *tf, int no_init_string)
+inline void troff_output_file::put(unsigned int i)
{
- flush_tbuf();
+ put_string(ui_to_a(i), fp);
+}
- /*
- * although this is extremely unlikely to have an effect on other devices
- * this way is safer. Currently this is only needed for html.
- */
- if (is_html && tf) {
- if (tf != current_tfont)
- set_font(tf);
- }
+void troff_output_file::start_special(tfont *tf, color *gcol, color *fcol,
+ int no_init_string)
+{
+ flush_tbuf();
do_motion();
+ if (tf != current_tfont)
+ set_font(tf);
+ glyph_color(gcol);
+ fill_color(fcol);
if (!no_init_string)
put("x X ");
}
-void troff_output_file::start_special(int no_init_string)
+void troff_output_file::start_special()
{
flush_tbuf();
do_motion();
- if (!no_init_string)
- put("x X ");
+ put("x X ");
}
void troff_output_file::special_char(unsigned char c)
@@ -844,8 +862,7 @@ void troff_output_file::really_print_line(hunits x, vunits y, node *n,
{
moveto(x, y);
while (n != 0) {
- if (is_on() || (n->force_tprint()))
- n->tprint(this);
+ n->tprint(this);
n = n->next;
}
flush_tbuf();
@@ -864,7 +881,8 @@ void troff_output_file::really_print_line(hunits x, vunits y, node *n,
inline void troff_output_file::word_marker()
{
flush_tbuf();
- put('w');
+ if (is_on())
+ put('w');
}
inline void troff_output_file::right(hunits n)
@@ -920,6 +938,11 @@ void troff_output_file::do_motion()
void troff_output_file::flush_tbuf()
{
+ if (!is_on()) {
+ tbuf_len = 0;
+ return;
+ }
+
if (tbuf_len == 0)
return;
if (tbuf_kern == 0)
@@ -930,7 +953,7 @@ void troff_output_file::flush_tbuf()
put(' ');
}
check_output_limits(hpos, vpos);
- check_output_limits(hpos, vpos + current_size + current_height);
+ check_output_limits(hpos, vpos - current_size);
for (int i = 0; i < tbuf_len; i++)
put(tbuf[i]);
@@ -940,29 +963,37 @@ void troff_output_file::flush_tbuf()
void troff_output_file::check_charinfo(tfont *tf, charinfo *ci)
{
- int size = tf->get_size().to_scaled_points();
+ if (!is_on())
+ return;
+
int height = tf->get_char_height(ci).to_units();
int width = tf->get_width(ci).to_units()
+ tf->get_italic_correction(ci).to_units();
int depth = tf->get_char_depth(ci).to_units();
- check_output_limits(output_hpos,
- output_vpos - height);
- check_output_limits(output_hpos + width,
- output_vpos + size + depth);
+ check_output_limits(output_hpos, output_vpos - height);
+ check_output_limits(output_hpos + width, output_vpos + depth);
}
-void troff_output_file::put_char_width(charinfo *ci, tfont *tf, hunits w,
- hunits k)
+void troff_output_file::put_char_width(charinfo *ci, tfont *tf,
+ color *gcol, color *fcol,
+ hunits w, hunits k)
{
+ int kk = k.to_units();
+ if (!is_on()) {
+ flush_tbuf();
+ hpos += w.to_units() + kk;
+ return;
+ }
if (tf != current_tfont) {
flush_tbuf();
set_font(tf);
}
char c = ci->get_ascii_code();
- int kk = k.to_units();
if (c == '\0') {
flush_tbuf();
do_motion();
+ glyph_color(gcol);
+ fill_color(fcol);
check_charinfo(tf, ci);
if (ci->numbered()) {
put('N');
@@ -983,6 +1014,7 @@ void troff_output_file::put_char_width(charinfo *ci, tfont *tf, hunits w,
}
else if (tcommand_flag) {
if (tbuf_len > 0 && hpos == output_hpos && vpos == output_vpos
+ && gcol == current_glyph_color && fcol == current_fill_color
&& kk == tbuf_kern
&& tbuf_len < TBUF_SIZE) {
check_charinfo(tf, ci);
@@ -993,6 +1025,8 @@ void troff_output_file::put_char_width(charinfo *ci, tfont *tf, hunits w,
}
flush_tbuf();
do_motion();
+ glyph_color(gcol);
+ fill_color(fcol);
check_charinfo(tf, ci);
tbuf[tbuf_len++] = c;
output_hpos += w.to_units() + kk;
@@ -1004,7 +1038,9 @@ void troff_output_file::put_char_width(charinfo *ci, tfont *tf, hunits w,
int n = hpos - output_hpos;
check_charinfo(tf, ci);
// check_output_limits(output_hpos, output_vpos);
- if (vpos == output_vpos && n > 0 && n < 100 && !force_motion) {
+ if (vpos == output_vpos
+ && gcol == current_glyph_color && fcol == current_fill_color
+ && n > 0 && n < 100 && !force_motion) {
put(char(n/10 + '0'));
put(char(n%10 + '0'));
put(c);
@@ -1019,14 +1055,19 @@ void troff_output_file::put_char_width(charinfo *ci, tfont *tf, hunits w,
}
}
-void troff_output_file::put_char(charinfo *ci, tfont *tf)
+void troff_output_file::put_char(charinfo *ci, tfont *tf,
+ color *gcol, color *fcol)
{
flush_tbuf();
+ if (!is_on())
+ return;
if (tf != current_tfont)
set_font(tf);
char c = ci->get_ascii_code();
if (c == '\0') {
do_motion();
+ glyph_color(gcol);
+ fill_color(fcol);
if (ci->numbered()) {
put('N');
put(ci->get_number());
@@ -1045,7 +1086,9 @@ void troff_output_file::put_char(charinfo *ci, tfont *tf)
}
else {
int n = hpos - output_hpos;
- if (vpos == output_vpos && n > 0 && n < 100) {
+ if (vpos == output_vpos
+ && gcol == current_glyph_color && fcol == current_fill_color
+ && n > 0 && n < 100) {
put(char(n/10 + '0'));
put(char(n%10 + '0'));
put(c);
@@ -1053,6 +1096,8 @@ void troff_output_file::put_char(charinfo *ci, tfont *tf)
}
else {
do_motion();
+ glyph_color(gcol);
+ fill_color(fcol);
put('c');
put(c);
}
@@ -1115,12 +1160,112 @@ void troff_output_file::set_font(tfont *tf)
current_tfont = tf;
}
+void troff_output_file::fill_color(color *col)
+{
+ if ((current_fill_color == col) || !color_flag)
+ return;
+ flush_tbuf();
+ put("DF");
+ unsigned int components[4];
+ color_scheme cs;
+ cs = col->get_components(components);
+ switch (cs) {
+ case DEFAULT:
+ put('d');
+ break;
+ case RGB:
+ put("r ");
+ put(Red);
+ put(' ');
+ put(Green);
+ put(' ');
+ put(Blue);
+ break;
+ case CMY:
+ put("c ");
+ put(Cyan);
+ put(' ');
+ put(Magenta);
+ put(' ');
+ put(Yellow);
+ break;
+ case CMYK:
+ put("k ");
+ put(Cyan);
+ put(' ');
+ put(Magenta);
+ put(' ');
+ put(Yellow);
+ put(' ');
+ put(Black);
+ break;
+ case GRAY:
+ put("g ");
+ put(Gray);
+ break;
+ }
+ put('\n');
+ current_fill_color = col;
+}
+
+void troff_output_file::glyph_color(color *col)
+{
+ if ((current_glyph_color == col) || !color_flag)
+ return;
+ flush_tbuf();
+ put("m");
+ unsigned int components[4];
+ color_scheme cs;
+ cs = col->get_components(components);
+ switch (cs) {
+ case DEFAULT:
+ put('d');
+ break;
+ case RGB:
+ put("r ");
+ put(Red);
+ put(' ');
+ put(Green);
+ put(' ');
+ put(Blue);
+ break;
+ case CMY:
+ put("c ");
+ put(Cyan);
+ put(' ');
+ put(Magenta);
+ put(' ');
+ put(Yellow);
+ break;
+ case CMYK:
+ put("k ");
+ put(Cyan);
+ put(' ');
+ put(Magenta);
+ put(' ');
+ put(Yellow);
+ put(' ');
+ put(Black);
+ break;
+ case GRAY:
+ put("g ");
+ put(Gray);
+ break;
+ }
+ put('\n');
+ current_glyph_color = col;
+}
+
// determine_line_limits - works out the smallest box which will contain
// the entity, code, built from the point array.
void troff_output_file::determine_line_limits(char code, hvpair *point,
int npoints)
{
int i, x, y;
+
+ if (!is_on())
+ return;
+
switch (code) {
case 'c':
case 'C':
@@ -1157,8 +1302,37 @@ void troff_output_file::determine_line_limits(char code, hvpair *point,
check_output_limits(x, y);
}
break;
+ case 'a':
+ double c[2];
+ int p[4];
+ int minx, miny, maxx, maxy;
+ x = output_hpos;
+ y = output_vpos;
+ p[0] = point[0].h.to_units();
+ p[1] = point[0].v.to_units();
+ p[2] = point[1].h.to_units();
+ p[3] = point[1].v.to_units();
+ if (adjust_arc_center(p, c)) {
+ check_output_arc_limits(x, y,
+ p[0], p[1], p[2], p[3],
+ c[0], c[1],
+ &minx, &maxx, &miny, &maxy);
+ check_output_limits(minx, miny);
+ check_output_limits(maxx, maxy);
+ break;
+ }
+ // fall through
+ case 'l':
+ x = output_hpos;
+ y = output_vpos;
+ check_output_limits(x, y);
+ for (i = 0; i < npoints; i++) {
+ x += point[i].h.to_units();
+ y += point[i].v.to_units();
+ check_output_limits(x, y);
+ }
+ break;
default:
- // remember this doesn't work for arc.. yet
x = output_hpos;
y = output_vpos;
for (i = 0; i < npoints; i++) {
@@ -1170,34 +1344,37 @@ void troff_output_file::determine_line_limits(char code, hvpair *point,
}
void troff_output_file::draw(char code, hvpair *point, int npoints,
- font_size fsize)
+ font_size fsize, color *gcol, color *fcol)
{
+ int i;
flush_tbuf();
do_motion();
- int size = fsize.to_scaled_points();
- if (current_size != size) {
- put('s');
- put(size);
- put('\n');
- current_size = size;
- current_tfont = 0;
- }
- put('D');
- put(code);
- int i;
- if (code == 'c') {
- put(' ');
- put(point[0].h.to_units());
- }
- else
- for (i = 0; i < npoints; i++) {
- put(' ');
- put(point[i].h.to_units());
+ glyph_color(gcol);
+ fill_color(fcol);
+ if (is_on()) {
+ int size = fsize.to_scaled_points();
+ if (current_size != size) {
+ put('s');
+ put(size);
+ put('\n');
+ current_size = size;
+ current_tfont = 0;
+ }
+ put('D');
+ put(code);
+ if (code == 'c') {
put(' ');
- put(point[i].v.to_units());
+ put(point[0].h.to_units());
}
-
- determine_line_limits(code, point, npoints);
+ else
+ for (i = 0; i < npoints; i++) {
+ put(' ');
+ put(point[i].h.to_units());
+ put(' ');
+ put(point[i].v.to_units());
+ }
+ determine_line_limits(code, point, npoints);
+ }
for (i = 0; i < npoints; i++)
output_hpos += point[i].h.to_units();
@@ -1207,15 +1384,18 @@ void troff_output_file::draw(char code, hvpair *point, int npoints,
output_vpos += point[i].v.to_units();
vpos = output_vpos;
}
- put('\n');
+ if (is_on())
+ put('\n');
}
-void troff_output_file::really_on ()
+void troff_output_file::really_on()
{
flush_tbuf();
+ force_motion = 1;
+ do_motion();
}
-void troff_output_file::really_off ()
+void troff_output_file::really_off()
{
flush_tbuf();
}
@@ -1412,7 +1592,7 @@ int real_output_file::is_printing()
void real_output_file::begin_page(int pageno, vunits page_length)
{
printing = in_output_page_list(pageno);
- if (printing && output_on)
+ if (printing)
really_begin_page(pageno, page_length);
}
@@ -1454,9 +1634,8 @@ void real_output_file::really_put_filename(const char *filename)
void real_output_file::on()
{
really_on();
- if (output_on == 0) {
+ if (output_on == 0)
output_on = 1;
- }
}
void real_output_file::off()
@@ -1467,7 +1646,7 @@ void real_output_file::off()
int real_output_file::is_on()
{
- return( output_on );
+ return output_on;
}
void real_output_file::really_on()
@@ -1562,14 +1741,16 @@ class glyph_node : public charinfo_node {
static glyph_node *free_list;
protected:
tfont *tf;
+ color *gcol;
+ color *fcol; /* this is needed for grotty */
#ifdef STORE_WIDTH
hunits wid;
- glyph_node(charinfo *, tfont *, hunits, node * = 0);
+ glyph_node(charinfo *, tfont *, color *, color *, hunits, node * = 0);
#endif
public:
void *operator new(size_t);
void operator delete(void *);
- glyph_node(charinfo *, tfont *, node * = 0);
+ glyph_node(charinfo *, tfont *, color *, color *, node * = 0);
~glyph_node() {}
node *copy();
node *merge_glyph_node(glyph_node *);
@@ -1584,6 +1765,8 @@ public:
hunits skew();
hyphenation_type get_hyphenation_type();
tfont *get_tfont();
+ color *get_glyph_color();
+ color *get_fill_color();
void tprint(troff_output_file *);
void zero_width_tprint(troff_output_file *);
hyphen_list *get_hyphen_list(hyphen_list *ss = 0);
@@ -1602,12 +1785,14 @@ class ligature_node : public glyph_node {
node *n1;
node *n2;
#ifdef STORE_WIDTH
- ligature_node(charinfo *, tfont *, hunits, node *gn1, node *gn2, node *x = 0);
+ ligature_node(charinfo *, tfont *, color *, color *, hunits,
+ node *, node *, node * = 0);
#endif
public:
void *operator new(size_t);
void operator delete(void *);
- ligature_node(charinfo *, tfont *, node *gn1, node *gn2, node *x = 0);
+ ligature_node(charinfo *, tfont *, color *, color *,
+ node *, node *, node * = 0);
~ligature_node();
node *copy();
node *add_self(node *, hyphen_list **);
@@ -1708,8 +1893,8 @@ void ligature_node::operator delete(void *p)
delete[] (char *)p;
}
-glyph_node::glyph_node(charinfo *c, tfont *t, node *x)
-: charinfo_node(c, x), tf(t)
+glyph_node::glyph_node(charinfo *c, tfont *t, color *gc, color *fc, node *x)
+: charinfo_node(c, x), tf(t), gcol(gc), fcol(fc)
{
#ifdef STORE_WIDTH
wid = tf->get_width(ci);
@@ -1717,8 +1902,9 @@ glyph_node::glyph_node(charinfo *c, tfont *t, node *x)
}
#ifdef STORE_WIDTH
-glyph_node::glyph_node(charinfo *c, tfont *t, hunits w, node *x)
-: charinfo_node(c, x), tf(t), wid(w)
+glyph_node::glyph_node(charinfo *c, tfont *t,
+ color *gc, color *fc, hunits w, node *x)
+: charinfo_node(c, x), tf(t), gcol(gc), fcol(fc), wid(w)
{
}
#endif
@@ -1726,9 +1912,9 @@ glyph_node::glyph_node(charinfo *c, tfont *t, hunits w, node *x)
node *glyph_node::copy()
{
#ifdef STORE_WIDTH
- return new glyph_node(ci, tf, wid);
+ return new glyph_node(ci, tf, gcol, fcol, wid);
#else
- return new glyph_node(ci, tf);
+ return new glyph_node(ci, tf, gcol, fcol);
#endif
}
@@ -1779,6 +1965,26 @@ tfont *glyph_node::get_tfont()
return tf;
}
+color *node::get_glyph_color()
+{
+ return 0;
+}
+
+color *glyph_node::get_glyph_color()
+{
+ return gcol;
+}
+
+color *node::get_fill_color()
+{
+ return 0;
+}
+
+color *glyph_node::get_fill_color()
+{
+ return fcol;
+}
+
node *node::merge_glyph_node(glyph_node * /*gn*/)
{
return 0;
@@ -1786,12 +1992,12 @@ node *node::merge_glyph_node(glyph_node * /*gn*/)
node *glyph_node::merge_glyph_node(glyph_node *gn)
{
- if (tf == gn->tf) {
+ if (tf == gn->tf && gcol == gn->gcol && fcol == gn->fcol) {
charinfo *lig;
if ((lig = tf->get_lig(ci, gn->ci)) != 0) {
node *next1 = next;
next = 0;
- return new ligature_node(lig, tf, this, gn, next1);
+ return new ligature_node(lig, tf, gcol, fcol, this, gn, next1);
}
hunits kern;
if (tf->get_kern(ci, gn->ci, &kern)) {
@@ -1860,16 +2066,16 @@ void glyph_node::ascii_print(ascii_output_file *ascii)
ascii->outs(ci->nm.contents());
}
-ligature_node::ligature_node(charinfo *c, tfont *t,
+ligature_node::ligature_node(charinfo *c, tfont *t, color *gc, color *fc,
node *gn1, node *gn2, node *x)
-: glyph_node(c, t, x), n1(gn1), n2(gn2)
+: glyph_node(c, t, gc, fc, x), n1(gn1), n2(gn2)
{
}
#ifdef STORE_WIDTH
-ligature_node::ligature_node(charinfo *c, tfont *t, hunits w,
- node *gn1, node *gn2, node *x)
-: glyph_node(c, t, w, x), n1(gn1), n2(gn2)
+ligature_node::ligature_node(charinfo *c, tfont *t, color *gc, color *fc,
+ hunits w, node *gn1, node *gn2, node *x)
+: glyph_node(c, t, gc, fc, w, x), n1(gn1), n2(gn2)
{
}
#endif
@@ -1883,9 +2089,9 @@ ligature_node::~ligature_node()
node *ligature_node::copy()
{
#ifdef STORE_WIDTH
- return new ligature_node(ci, tf, wid, n1->copy(), n2->copy());
+ return new ligature_node(ci, tf, gcol, fcol, wid, n1->copy(), n2->copy());
#else
- return new ligature_node(ci, tf, n1->copy(), n2->copy());
+ return new ligature_node(ci, tf, gcol, fcol, n1->copy(), n2->copy());
#endif
}
@@ -1986,10 +2192,12 @@ node *kern_pair_node::add_discretionary_hyphen()
tfont *tf = n2->get_tfont();
if (tf) {
if (tf->contains(soft_hyphen_char)) {
+ color *gcol = n2->get_glyph_color();
+ color *fcol = n2->get_fill_color();
node *next1 = next;
next = 0;
node *n = copy();
- glyph_node *gn = new glyph_node(soft_hyphen_char, tf);
+ glyph_node *gn = new glyph_node(soft_hyphen_char, tf, gcol, fcol);
node *nn = n->merge_glyph_node(gn);
if (nn == 0) {
gn->next = n;
@@ -2121,10 +2329,12 @@ node *node::add_discretionary_hyphen()
if (!tf)
return new hyphen_inhibitor_node(this);
if (tf->contains(soft_hyphen_char)) {
+ color *gcol = get_glyph_color();
+ color *fcol = get_fill_color();
node *next1 = next;
next = 0;
node *n = copy();
- glyph_node *gn = new glyph_node(soft_hyphen_char, tf);
+ glyph_node *gn = new glyph_node(soft_hyphen_char, tf, gcol, fcol);
node *n1 = n->merge_glyph_node(gn);
if (n1 == 0) {
gn->next = n;
@@ -2362,8 +2572,9 @@ int italic_corrected_node::character_type()
class break_char_node : public node {
node *ch;
char break_code;
+ color *col;
public:
- break_char_node(node *, int, node * = 0);
+ break_char_node(node *, int, color *, node * = 0);
~break_char_node();
node *copy();
hunits width();
@@ -2387,8 +2598,8 @@ public:
int force_tprint();
};
-break_char_node::break_char_node(node *n, int c, node *x)
-: node(x), ch(n), break_code(c)
+break_char_node::break_char_node(node *n, int bc, color *c, node *x)
+: node(x), ch(n), break_code(bc), col(c)
{
}
@@ -2399,7 +2610,7 @@ break_char_node::~break_char_node()
node *break_char_node::copy()
{
- return new break_char_node(ch->copy(), break_code);
+ return new break_char_node(ch->copy(), break_code, col);
}
hunits break_char_node::width()
@@ -2431,13 +2642,13 @@ node *break_char_node::add_self(node *n, hyphen_list **p)
{
assert((*p)->hyphenation_code == 0);
if ((*p)->breakable && (break_code & 1)) {
- n = new space_node(H0, n);
+ n = new space_node(H0, col, n);
n->freeze_space();
}
next = n;
n = this;
if ((*p)->breakable && (break_code & 2)) {
- n = new space_node(H0, n);
+ n = new space_node(H0, col, n);
n->freeze_space();
}
hyphen_list *pp = *p;
@@ -2493,17 +2704,17 @@ node *vertical_size_node::copy()
node *hmotion_node::copy()
{
- return new hmotion_node(n, was_tab, unformat);
+ return new hmotion_node(n, was_tab, unformat, col);
}
node *space_char_hmotion_node::copy()
{
- return new space_char_hmotion_node(n);
+ return new space_char_hmotion_node(n, col);
}
node *vmotion_node::copy()
{
- return new vmotion_node(n);
+ return new vmotion_node(n, col);
}
node *dummy_node::copy()
@@ -2648,6 +2859,8 @@ node *bracket_node::copy()
bracket_node *on = new bracket_node;
node *last = 0;
node *tem;
+ if (list)
+ list->last = 0;
for (tem = list; tem; tem = tem->next) {
if (tem->next)
tem->next->last = tem;
@@ -2711,13 +2924,13 @@ inline void space_node::operator delete(void *p)
}
#endif
-space_node::space_node(hunits nn, node *p)
-: node(p), n(nn), set(0), was_escape_colon(0)
+space_node::space_node(hunits nn, color *c, node *p)
+: node(p), n(nn), set(0), was_escape_colon(0), col(c)
{
}
-space_node::space_node(hunits nn, int s, int flag, node *p)
-: node(p), n(nn), set(s), was_escape_colon(flag)
+space_node::space_node(hunits nn, int s, int flag, color *c, node *p)
+: node(p), n(nn), set(s), was_escape_colon(flag), col(c)
{
}
@@ -2729,7 +2942,7 @@ space_node::~space_node()
node *space_node::copy()
{
- return new space_node(n, set, was_escape_colon);
+ return new space_node(n, set, was_escape_colon, col);
}
int space_node::force_tprint()
@@ -3025,7 +3238,9 @@ void node::asciify(macro *m)
void glyph_node::asciify(macro *m)
{
- unsigned char c = ci->get_ascii_code();
+ unsigned char c = ci->get_asciify_code();
+ if (c == 0)
+ c = ci->get_ascii_code();
if (c != 0) {
m->append(c);
delete this;
@@ -3098,8 +3313,9 @@ void hmotion_node::asciify(macro *m)
m->append(this);
}
-space_char_hmotion_node::space_char_hmotion_node(hunits i, node *next)
-: hmotion_node(i, next)
+space_char_hmotion_node::space_char_hmotion_node(hunits i, color *c,
+ node *next)
+: hmotion_node(i, c, next)
{
}
@@ -3153,8 +3369,8 @@ int node::nbreaks()
return 0;
}
-breakpoint *space_node::get_breakpoints(hunits width, int ns, breakpoint *rest,
- int is_inner)
+breakpoint *space_node::get_breakpoints(hunits width, int ns,
+ breakpoint *rest, int is_inner)
{
if (next->discardable())
return rest;
@@ -3351,23 +3567,27 @@ special_node::special_node(const macro &m, int n)
font_size fs = curenv->get_font_size();
int char_height = curenv->get_char_height();
int char_slant = curenv->get_char_slant();
- int fontno = curenv->get_font();
- tf = font_table[fontno]->get_tfont(fs, char_height, char_slant,
- fontno);
+ int fontno = env_definite_font(curenv);
+ tf = font_table[fontno]->get_tfont(fs, char_height, char_slant, fontno);
if (curenv->is_composite())
tf = tf->get_plain();
+ gcol = curenv->get_glyph_color();
+ fcol = curenv->get_fill_color();
}
-special_node::special_node(const macro &m, tfont *t, int n)
-: mac(m), tf(t), no_init_string(n)
+special_node::special_node(const macro &m, tfont *t,
+ color *gc, color *fc, int n)
+: mac(m), tf(t), gcol(gc), fcol(fc), no_init_string(n)
{
}
int special_node::same(node *n)
{
- return ((mac == ((special_node *)n)->mac)
- && (tf == ((special_node *)n)->tf)
- && (no_init_string == ((special_node *)n)->no_init_string));
+ return mac == ((special_node *)n)->mac
+ && tf == ((special_node *)n)->tf
+ && gcol == ((special_node *)n)->gcol
+ && fcol == ((special_node *)n)->fcol
+ && no_init_string == ((special_node *)n)->no_init_string;
}
const char *special_node::type()
@@ -3387,12 +3607,12 @@ int special_node::force_tprint()
node *special_node::copy()
{
- return new special_node(mac, tf, no_init_string);
+ return new special_node(mac, tf, gcol, fcol, no_init_string);
}
void special_node::tprint_start(troff_output_file *out)
{
- out->start_special(get_tfont(), no_init_string);
+ out->start_special(tf, gcol, fcol, no_init_string);
}
void special_node::tprint_char(troff_output_file *out, unsigned char c)
@@ -3413,18 +3633,20 @@ tfont *special_node::get_tfont()
/* suppress_node */
suppress_node::suppress_node(int on_or_off, int issue_limits)
-: is_on(on_or_off), emit_limits(issue_limits), filename(0), position(0)
+: is_on(on_or_off), emit_limits(issue_limits),
+ filename(0), position(0), image_id(0)
{
}
-suppress_node::suppress_node(symbol f, char p)
-: is_on(2), emit_limits(0), filename(f), position(p)
+suppress_node::suppress_node(symbol f, char p, int id)
+: is_on(2), emit_limits(0), filename(f), position(p), image_id(id)
{
}
suppress_node::suppress_node(int issue_limits, int on_or_off,
- symbol f, char p)
-: is_on(on_or_off), emit_limits(issue_limits), filename(f), position(p)
+ symbol f, char p, int id)
+: is_on(on_or_off), emit_limits(issue_limits),
+ filename(f), position(p), image_id(id)
{
}
@@ -3433,8 +3655,8 @@ int suppress_node::same(node *n)
return ((is_on == ((suppress_node *)n)->is_on)
&& (emit_limits == ((suppress_node *)n)->emit_limits)
&& (filename == ((suppress_node *)n)->filename)
- && (position == ((suppress_node *)n)->position));
-;
+ && (position == ((suppress_node *)n)->position)
+ && (image_id == ((suppress_node *)n)->image_id));
}
const char *suppress_node::type()
@@ -3444,7 +3666,7 @@ const char *suppress_node::type()
node *suppress_node::copy()
{
- return new suppress_node(emit_limits, is_on, filename, position);
+ return new suppress_node(emit_limits, is_on, filename, position, image_id);
}
int get_reg_int(const char *p)
@@ -3483,6 +3705,7 @@ void suppress_node::put(troff_output_file *out, const char *s)
static char last_position = 0;
static const char *last_image_filename = 0;
+static int last_image_id = 0;
inline int min(int a, int b)
{
@@ -3508,22 +3731,23 @@ inline int min(int a, int b)
void suppress_node::tprint(troff_output_file *out)
{
- int current_page = get_reg_int("%");
+ int current_page = topdiv->get_page_number();
// firstly check to see whether this suppress node contains
// an image filename & position.
if (is_on == 2) {
// remember position and filename
last_position = position;
- last_image_filename = filename.contents();
+ last_image_filename = strdup(filename.contents());
+ last_image_id = image_id;
+ // printf("start of image and page = %d\n", current_page);
}
else {
// now check whether the suppress node requires us to issue limits.
if (emit_limits) {
char name[8192];
- image_no++;
// remember that the filename will contain a %d in which the
- // image_no is placed
- sprintf(name, last_image_filename, image_no);
+ // last_image_id is placed
+ sprintf(name, last_image_filename, last_image_id);
if (is_html) {
switch (last_position) {
case 'c':
@@ -3551,14 +3775,18 @@ void suppress_node::tprint(troff_output_file *out)
}
else {
// postscript (or other device)
- if (current_page != suppress_start_page)
+ if (suppress_start_page > 0 && current_page != suppress_start_page)
error("suppression limit registers span more than one page;\n"
"image description %1 will be wrong", image_no);
+ // if (topdiv->get_page_number() != suppress_start_page)
+ // fprintf(stderr, "end of image and topdiv page = %d and suppress_start_page = %d\n",
+ // topdiv->get_page_number(), suppress_start_page);
+
// remember that the filename will contain a %d in which the
// image_no is placed
fprintf(stderr,
"grohtml-info:page %d %d %d %d %d %d %s %d %d %s\n",
- current_page,
+ topdiv->get_page_number(),
get_reg_int("opminx"), get_reg_int("opminy"),
get_reg_int("opmaxx"), get_reg_int("opmaxy"),
// page offset + line length
@@ -3568,12 +3796,13 @@ void suppress_node::tprint(troff_output_file *out)
}
}
else {
- if (is_on)
+ if (is_on) {
out->on();
+ // lastly we reset the output registers
+ reset_output_registers(out->get_vpos());
+ }
else
out->off();
- // lastly we reset the output registers
- reset_output_registers(out->get_vpos());
suppress_start_page = current_page;
}
}
@@ -3670,7 +3899,9 @@ hyphenation_type composite_node::get_hyphenation_type()
void composite_node::asciify(macro *m)
{
- unsigned char c = ci->get_ascii_code();
+ unsigned char c = ci->get_asciify_code();
+ if (c == 0)
+ c = ci->get_ascii_code();
if (c != 0) {
m->append(c);
delete this;
@@ -3741,14 +3972,14 @@ width_list::width_list(width_list *w)
{
}
-word_space_node::word_space_node(hunits d, width_list *w, node *x)
-: space_node(d, x), orig_width(w), unformat(0)
+word_space_node::word_space_node(hunits d, color *c, width_list *w, node *x)
+: space_node(d, c, x), orig_width(w), unformat(0)
{
}
-word_space_node::word_space_node(hunits d, int s, width_list *w,
+word_space_node::word_space_node(hunits d, int s, color *c, width_list *w,
int flag, node *x)
-: space_node(d, s, 0, x), orig_width(w), unformat(flag)
+: space_node(d, s, 0, c, x), orig_width(w), unformat(flag)
{
}
@@ -3774,7 +4005,7 @@ node *word_space_node::copy()
w_new_curr = w_new_curr->next;
w_old_curr = w_old_curr->next;
}
- return new word_space_node(n, set, w_new, unformat);
+ return new word_space_node(n, set, col, w_new, unformat);
}
int word_space_node::set_unformat_flag()
@@ -3785,8 +4016,9 @@ int word_space_node::set_unformat_flag()
void word_space_node::tprint(troff_output_file *out)
{
+ out->fill_color(col);
out->word_marker();
- space_node::tprint(out);
+ out->right(n);
}
int word_space_node::merge_space(hunits h, hunits sw, hunits ssw)
@@ -3800,19 +4032,20 @@ int word_space_node::merge_space(hunits h, hunits sw, hunits ssw)
return 1;
}
-unbreakable_space_node::unbreakable_space_node(hunits d, node *x)
-: word_space_node(d, 0, x)
+unbreakable_space_node::unbreakable_space_node(hunits d, color *c, node *x)
+: word_space_node(d, c, 0, x)
{
}
-unbreakable_space_node::unbreakable_space_node(hunits d, int s, node *x)
-: word_space_node(d, s, 0, 0, x)
+unbreakable_space_node::unbreakable_space_node(hunits d, int s,
+ color *c, node *x)
+: word_space_node(d, s, c, 0, 0, x)
{
}
node *unbreakable_space_node::copy()
{
- return new unbreakable_space_node(n, set);
+ return new unbreakable_space_node(n, set, col);
}
int unbreakable_space_node::force_tprint()
@@ -3845,8 +4078,9 @@ hvpair::hvpair()
{
}
-draw_node::draw_node(char c, hvpair *p, int np, font_size s)
-: npoints(np), sz(s), code(c)
+draw_node::draw_node(char c, hvpair *p, int np, font_size s,
+ color *gc, color *fc)
+: npoints(np), sz(s), gcol(gc), fcol(fc), code(c)
{
point = new hvpair[npoints];
for (int i = 0; i < npoints; i++)
@@ -3856,7 +4090,8 @@ draw_node::draw_node(char c, hvpair *p, int np, font_size s)
int draw_node::same(node *n)
{
draw_node *nd = (draw_node *)n;
- if (code != nd->code || npoints != nd->npoints || sz != nd->sz)
+ if (code != nd->code || npoints != nd->npoints || sz != nd->sz
+ || gcol != nd->gcol || fcol != nd->fcol)
return 0;
for (int i = 0; i < npoints; i++)
if (point[i].h != nd->point[i].h || point[i].v != nd->point[i].v)
@@ -3900,12 +4135,12 @@ vunits draw_node::vertical_width()
node *draw_node::copy()
{
- return new draw_node(code, point, npoints, sz);
+ return new draw_node(code, point, npoints, sz, gcol, fcol);
}
void draw_node::tprint(troff_output_file *out)
{
- out->draw(code, point, npoints, sz);
+ out->draw(code, point, npoints, sz, gcol, fcol);
}
/* tprint methods */
@@ -3914,7 +4149,7 @@ void glyph_node::tprint(troff_output_file *out)
{
tfont *ptf = tf->get_plain();
if (ptf == tf)
- out->put_char_width(ci, ptf, width(), H0);
+ out->put_char_width(ci, ptf, gcol, fcol, width(), H0);
else {
hunits offset;
int bold = tf->get_bold(&offset);
@@ -3933,10 +4168,10 @@ void glyph_node::tprint(troff_output_file *out)
else
k = tf->get_track_kern();
if (bold) {
- out->put_char(ci, ptf);
+ out->put_char(ci, ptf, gcol, fcol);
out->right(offset);
}
- out->put_char_width(ci, ptf, w, k);
+ out->put_char_width(ci, ptf, gcol, fcol, w, k);
}
}
@@ -3954,10 +4189,10 @@ void glyph_node::zero_width_tprint(troff_output_file *out)
x = x/2;
out->right(x);
}
- out->put_char(ci, ptf);
+ out->put_char(ci, ptf, gcol, fcol);
if (bold) {
out->right(offset);
- out->put_char(ci, ptf);
+ out->put_char(ci, ptf, gcol, fcol);
out->right(-offset);
}
if (cs)
@@ -3995,20 +4230,23 @@ void hline_node::tprint(troff_output_file *out)
hunits xx = x - w;
hunits xx2 = xx/2;
out->right(xx2);
- n->tprint(out);
+ if (out->is_on())
+ n->tprint(out);
out->right(xx - xx2);
}
else {
hunits rem = x - w*i;
if (rem > H0)
if (n->overlaps_horizontally()) {
- n->tprint(out);
+ if (out->is_on())
+ n->tprint(out);
out->right(rem - w);
}
else
out->right(rem);
while (--i >= 0)
- n->tprint(out);
+ if (out->is_on())
+ n->tprint(out);
}
}
@@ -4037,11 +4275,13 @@ void vline_node::tprint(troff_output_file *out)
if (overlaps) {
n->zero_width_tprint(out);
out->down(-rem);
- n->tprint(out);
+ if (out->is_on())
+ n->tprint(out);
out->down(-h);
}
else {
- n->tprint(out);
+ if (out->is_on())
+ n->tprint(out);
out->down(-h - rem);
}
}
@@ -4062,7 +4302,8 @@ void vline_node::tprint(troff_output_file *out)
n->zero_width_tprint(out);
out->down(h);
}
- n->tprint(out);
+ if (out->is_on())
+ n->tprint(out);
}
}
}
@@ -4131,16 +4372,19 @@ void node::zero_width_tprint(troff_output_file *out)
void space_node::tprint(troff_output_file *out)
{
+ out->fill_color(col);
out->right(n);
}
void hmotion_node::tprint(troff_output_file *out)
{
+ out->fill_color(col);
out->right(n);
}
void vmotion_node::tprint(troff_output_file *out)
{
+ out->fill_color(col);
out->down(n);
}
@@ -4226,6 +4470,8 @@ node *make_glyph_node(charinfo *s, environment *env, int no_error_message = 0)
int fn = fontno;
int found = font_table[fontno]->contains(s);
if (!found) {
+ if (s->is_fallback())
+ return make_composite_node(s, env);
if (s->numbered()) {
if (!no_error_message)
warning(WARN_CHAR, "can't find numbered character %1",
@@ -4284,16 +4530,20 @@ node *make_glyph_node(charinfo *s, environment *env, int no_error_message = 0)
tfont *tf = font_table[fontno]->get_tfont(fs, char_height, char_slant, fn);
if (env->is_composite())
tf = tf->get_plain();
- return new glyph_node(s, tf);
+ color *gcol = env->get_glyph_color();
+ color *fcol = env->get_fill_color();
+ return new glyph_node(s, tf, gcol, fcol);
}
node *make_node(charinfo *ci, environment *env)
{
switch (ci->get_special_translation()) {
case charinfo::TRANSLATE_SPACE:
- return new space_char_hmotion_node(env->get_space_width());
+ return new space_char_hmotion_node(env->get_space_width(),
+ env->get_fill_color());
case charinfo::TRANSLATE_STRETCHABLE_SPACE:
- return new unbreakable_space_node(env->get_space_width());
+ return new unbreakable_space_node(env->get_space_width(),
+ env->get_fill_color());
case charinfo::TRANSLATE_DUMMY:
return new dummy_node;
case charinfo::TRANSLATE_HYPHEN_INDICATOR:
@@ -4304,7 +4554,7 @@ node *make_node(charinfo *ci, environment *env)
if (tem)
ci = tem;
macro *mac = ci->get_macro();
- if (mac)
+ if (mac && !ci->is_fallback())
return make_composite_node(ci, env);
else
return make_glyph_node(ci, env);
@@ -4333,11 +4583,14 @@ node *node::add_char(charinfo *ci, environment *env,
node *res;
switch (ci->get_special_translation()) {
case charinfo::TRANSLATE_SPACE:
- res = new space_char_hmotion_node(env->get_space_width(), this);
+ res = new space_char_hmotion_node(env->get_space_width(),
+ env->get_fill_color(), this);
*widthp += res->width();
return res;
case charinfo::TRANSLATE_STRETCHABLE_SPACE:
- res = new unbreakable_space_node(env->get_space_width(), this);
+ res = new unbreakable_space_node(env->get_space_width(),
+ env->get_fill_color(), this);
+ res->freeze_space();
*widthp += res->width();
*spacep += res->nspaces();
return res;
@@ -4350,7 +4603,7 @@ node *node::add_char(charinfo *ci, environment *env,
if (tem)
ci = tem;
macro *mac = ci->get_macro();
- if (mac) {
+ if (mac && !ci->is_fallback()) {
res = make_composite_node(ci, env);
if (res) {
res->next = this;
@@ -4385,7 +4638,7 @@ node *node::add_char(charinfo *ci, environment *env,
if (break_code) {
node *next1 = res->next;
res->next = 0;
- res = new break_char_node(res, break_code, next1);
+ res = new break_char_node(res, break_code, env->get_fill_color(), next1);
}
return res;
}
@@ -4453,7 +4706,8 @@ int vertical_size_node::force_tprint()
int hmotion_node::same(node *nd)
{
- return n == ((hmotion_node *)nd)->n;
+ return n == ((hmotion_node *)nd)->n
+ && col == ((hmotion_node *)nd)->col;
}
const char *hmotion_node::type()
@@ -4488,7 +4742,8 @@ hyphen_list *hmotion_node::get_hyphen_list(hyphen_list *tail)
int space_char_hmotion_node::same(node *nd)
{
- return n == ((space_char_hmotion_node *)nd)->n;
+ return n == ((space_char_hmotion_node *)nd)->n
+ && col == ((space_char_hmotion_node *)nd)->col;
}
const char *space_char_hmotion_node::type()
@@ -4517,7 +4772,8 @@ hyphen_list *space_char_hmotion_node::get_hyphen_list(hyphen_list *tail)
int vmotion_node::same(node *nd)
{
- return n == ((vmotion_node *)nd)->n;
+ return n == ((vmotion_node *)nd)->n
+ && col == ((vmotion_node *)nd)->col;
}
const char *vmotion_node::type()
@@ -4841,7 +5097,10 @@ int composite_node::force_tprint()
int glyph_node::same(node *nd)
{
- return ci == ((glyph_node *)nd)->ci && tf == ((glyph_node *)nd)->tf;
+ return ci == ((glyph_node *)nd)->ci
+ && tf == ((glyph_node *)nd)->tf
+ && gcol == ((glyph_node *)nd)->gcol
+ && fcol == ((glyph_node *)nd)->fcol;
}
const char *glyph_node::type()
@@ -4907,8 +5166,9 @@ int dbreak_node::force_tprint()
int break_char_node::same(node *nd)
{
- return (break_code == ((break_char_node *)nd)->break_code
- && same_node(ch, ((break_char_node *)nd)->ch));
+ return break_code == ((break_char_node *)nd)->break_code
+ && col == ((break_char_node *)nd)->col
+ && same_node(ch, ((break_char_node *)nd)->ch);
}
const char *break_char_node::type()
@@ -4938,7 +5198,9 @@ int line_start_node::force_tprint()
int space_node::same(node *nd)
{
- return n == ((space_node *)nd)->n && set == ((space_node *)nd)->set;
+ return n == ((space_node *)nd)->n
+ && set == ((space_node *)nd)->set
+ && col == ((space_node *)nd)->col;
}
const char *space_node::type()
@@ -4948,8 +5210,9 @@ const char *space_node::type()
int word_space_node::same(node *nd)
{
- return (n == ((word_space_node *)nd)->n
- && set == ((word_space_node *)nd)->set);
+ return n == ((word_space_node *)nd)->n
+ && set == ((word_space_node *)nd)->set
+ && col == ((word_space_node *)nd)->col;
}
const char *word_space_node::type()
@@ -4964,8 +5227,9 @@ int word_space_node::force_tprint()
int unbreakable_space_node::same(node *nd)
{
- return (n == ((unbreakable_space_node *)nd)->n
- && set == ((unbreakable_space_node *)nd)->set);
+ return n == ((unbreakable_space_node *)nd)->n
+ && set == ((unbreakable_space_node *)nd)->set
+ && col == ((unbreakable_space_node *)nd)->col;
}
const char *unbreakable_space_node::type()
@@ -5345,7 +5609,7 @@ int symbol_fontno(symbol s)
int is_good_fontno(int n)
{
- return n >= 0 && n < font_table_size && font_table[n] != NULL;
+ return n >= 0 && n < font_table_size && font_table[n] != 0;
}
int get_bold_fontno(int n)
diff --git a/contrib/groff/src/roff/troff/node.h b/contrib/groff/src/roff/troff/node.h
index a58afed..13295f4 100644
--- a/contrib/groff/src/roff/troff/node.h
+++ b/contrib/groff/src/roff/troff/node.h
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001
+/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001, 2002
Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
@@ -97,6 +97,8 @@ struct node {
virtual node *merge_glyph_node(glyph_node *);
virtual tfont *get_tfont();
+ virtual color *get_glyph_color();
+ virtual color *get_fill_color();
virtual void tprint(troff_output_file *);
virtual void zero_width_tprint(troff_output_file *);
@@ -106,11 +108,13 @@ struct node {
virtual const char *type() = 0;
};
-inline node::node() : next(0), last(0)
+inline node::node()
+: next(0), last(0)
{
}
-inline node::node(node *n) : next(n), last(0)
+inline node::node(node *n)
+: next(n), last(0)
{
}
@@ -152,9 +156,10 @@ protected:
hunits n;
char set;
char was_escape_colon;
- space_node(hunits, int, int, node * = 0);
+ color *col; /* for grotty */
+ space_node(hunits, int, int, color *, node * = 0);
public:
- space_node(hunits d, node *p = 0);
+ space_node(hunits, color *, node * = 0);
#if 0
~space_node();
void *operator new(size_t);
@@ -192,9 +197,9 @@ class word_space_node : public space_node {
protected:
width_list *orig_width;
unsigned char unformat;
- word_space_node(hunits, int, width_list *, int, node * = 0);
+ word_space_node(hunits, int, color *, width_list *, int, node * = 0);
public:
- word_space_node(hunits, width_list *, node * = 0);
+ word_space_node(hunits, color *, width_list *, node * = 0);
~word_space_node();
node *copy();
int reread(int *);
@@ -208,9 +213,9 @@ public:
};
class unbreakable_space_node : public word_space_node {
- unbreakable_space_node(hunits, int, node * = 0);
+ unbreakable_space_node(hunits, int, color *, node * = 0);
public:
- unbreakable_space_node(hunits, node * = 0);
+ unbreakable_space_node(hunits, color *, node * = 0);
node *copy();
int reread(int *);
int same(node *);
@@ -279,11 +284,12 @@ protected:
hunits n;
unsigned char was_tab;
unsigned char unformat;
+ color *col; /* for grotty */
public:
- hmotion_node(hunits i, node *next = 0)
- : node(next), n(i), was_tab(0), unformat(0) {}
- hmotion_node(hunits i, int flag1, int flag2, node *next = 0)
- : node(next), n(i), was_tab(flag1), unformat(flag2) {}
+ hmotion_node(hunits i, color *c, node *next = 0)
+ : node(next), n(i), was_tab(0), unformat(0), col(c) {}
+ hmotion_node(hunits i, int flag1, int flag2, color *c, node *next = 0)
+ : node(next), n(i), was_tab(flag1), unformat(flag2), col(c) {}
node *copy();
int reread(int *);
int set_unformat_flag();
@@ -301,7 +307,7 @@ public:
class space_char_hmotion_node : public hmotion_node {
public:
- space_char_hmotion_node(hunits i, node *next = 0);
+ space_char_hmotion_node(hunits, color *, node * = 0);
node *copy();
void ascii_print(ascii_output_file *);
void asciify(macro *);
@@ -315,8 +321,9 @@ public:
class vmotion_node : public node {
vunits n;
+ color *col; /* for grotty */
public:
- vmotion_node(vunits i) : n(i) {}
+ vmotion_node(vunits i, color *c) : n(i), col(c) {}
void tprint(troff_output_file *);
node *copy();
vunits vertical_width();
@@ -458,13 +465,15 @@ public:
class special_node : public node {
macro mac;
tfont *tf;
+ color *gcol;
+ color *fcol;
int no_init_string;
void tprint_start(troff_output_file *);
void tprint_char(troff_output_file *, unsigned char);
void tprint_end(troff_output_file *);
public:
special_node(const macro &, int = 0);
- special_node(const macro &, tfont *, int = 0);
+ special_node(const macro &, tfont *, color *, color *, int = 0);
node *copy();
void tprint(troff_output_file *);
int same(node *);
@@ -479,10 +488,11 @@ class suppress_node : public node {
int emit_limits; // must we issue the extent of the area written out?
symbol filename;
char position;
+ int image_id;
public:
suppress_node(int, int);
- suppress_node(symbol f, char p);
- suppress_node(int, int, symbol f, char p);
+ suppress_node(symbol f, char p, int id);
+ suppress_node(int, int, symbol f, char p, int id);
node *copy();
void tprint(troff_output_file *);
hunits width();
@@ -502,10 +512,12 @@ struct hvpair {
class draw_node : public node {
int npoints;
font_size sz;
+ color *gcol;
+ color *fcol;
char code;
hvpair *point;
public:
- draw_node(char, hvpair *, int, font_size);
+ draw_node(char, hvpair *, int, font_size, color *, color *);
~draw_node();
hunits width();
vunits vertical_width();
@@ -582,3 +594,4 @@ public:
};
font_family *lookup_family(symbol);
+symbol get_font_name(int, environment *);
diff --git a/contrib/groff/src/roff/troff/number.cc b/contrib/groff/src/roff/troff/number.cc
index 5393842..8fed342 100644
--- a/contrib/groff/src/roff/troff/number.cc
+++ b/contrib/groff/src/roff/troff/number.cc
@@ -1,5 +1,6 @@
// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992, 2001 Free Software Foundation, Inc.
+/* Copyright (C) 1989, 1990, 1991, 1992, 2001, 2002
+ Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
This file is part of groff.
@@ -234,7 +235,7 @@ static int start_number()
enum { OP_LEQ = 'L', OP_GEQ = 'G', OP_MAX = 'X', OP_MIN = 'N' };
-#define SCALE_INDICATOR_CHARS "icPmnpuvMsz"
+#define SCALE_INDICATOR_CHARS "icfPmnpuvMsz"
static int parse_term(units *v, int scale_indicator,
int parenthesised, int rigid);
@@ -320,6 +321,7 @@ static int parse_expr(units *v, int scale_indicator,
break;
case ':':
*v = *v > 0 || v2 > 0;
+ break;
case '+':
if (v2 < 0) {
if (*v < INT_MIN - v2)
@@ -590,6 +592,9 @@ static int parse_term(units *v, int scale_indicator,
if (divisor != 1)
*v /= divisor;
break;
+ case 'f':
+ *v = scale(*v, 65536, divisor);
+ break;
case 'p':
*v = scale(*v, units_per_inch, divisor*72);
break;
diff --git a/contrib/groff/src/roff/troff/request.h b/contrib/groff/src/roff/troff/request.h
index 5654b83..0433ac1 100644
--- a/contrib/groff/src/roff/troff/request.h
+++ b/contrib/groff/src/roff/troff/request.h
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001
+/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001, 2002
Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
@@ -48,7 +48,8 @@ class macro : public request_or_macro {
macro_header *p;
const char *filename; // where was it defined?
int lineno;
- int length;
+ int len;
+ int empty_macro;
public:
macro();
~macro();
@@ -59,13 +60,16 @@ public:
void append_unsigned(unsigned int i);
void append_int(int i);
void append_str(const char *);
+ void set(unsigned char, int);
+ unsigned char get(int);
+ int length();
void invoke(symbol);
macro *to_macro();
void print_size();
int empty();
friend class string_iterator;
friend void chop_macro();
- friend void substring_macro();
+ friend void substring_request();
friend int operator==(const macro &, const macro &);
};
diff --git a/contrib/groff/src/roff/troff/symbol.cc b/contrib/groff/src/roff/troff/symbol.cc
index ce09e39..09f4c98 100644
--- a/contrib/groff/src/roff/troff/symbol.cc
+++ b/contrib/groff/src/roff/troff/symbol.cc
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+/* Copyright (C) 1989, 1990, 1991, 1992, 2002 Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
This file is part of groff.
@@ -29,6 +29,7 @@ char *symbol::block = 0;
int symbol::block_size = 0;
const symbol NULL_SYMBOL;
+const symbol EMPTY_SYMBOL("");
#ifdef BLOCK_SIZE
#undef BLOCK_SIZE
@@ -38,9 +39,9 @@ const int BLOCK_SIZE = 1024;
// the table will increase in size as necessary
// the size will be chosen from the following array
// add some more if you want
-// I think it unlikely that we'll need more than a million symbols
static const unsigned int table_sizes[] = {
-101, 503, 1009, 2003, 3001, 4001, 5003, 10007, 20011, 40009, 80021, 160001, 500009, 1000003, 0
+ 101, 503, 1009, 2003, 3001, 4001, 5003, 10007, 20011, 40009, 80021,
+ 160001, 500009, 1000003, 1500007, 2000003, 0
};
const double FULL_MAX = 0.3; // don't let the table get more than this full
@@ -73,10 +74,14 @@ inline void unused(void *) { }
symbol::symbol(const char *p, int how)
{
- if (p == 0 || *p == 0) {
+ if (p == 0) {
s = 0;
return;
}
+ if (*p == 0) {
+ s = "";
+ return;
+ }
if (table == 0) {
table_size = table_sizes[0];
table = (const char **)new char*[table_size];
@@ -147,4 +152,3 @@ symbol concat(symbol s1, symbol s2)
a_delete buf;
return res;
}
-
diff --git a/contrib/groff/src/roff/troff/symbol.h b/contrib/groff/src/roff/troff/symbol.h
index 88e0fff..5b7c9b1 100644
--- a/contrib/groff/src/roff/troff/symbol.h
+++ b/contrib/groff/src/roff/troff/symbol.h
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+/* Copyright (C) 1989, 1990, 1991, 1992, 2002 Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
This file is part of groff.
@@ -36,10 +36,12 @@ public:
int operator !=(symbol) const;
const char *contents() const;
int is_null() const;
+ int is_empty() const;
};
extern const symbol NULL_SYMBOL;
+extern const symbol EMPTY_SYMBOL;
inline symbol::symbol() : s(0)
{
@@ -70,4 +72,9 @@ inline int symbol::is_null() const
return s == 0;
}
+inline int symbol::is_empty() const
+{
+ return s != 0 && *s == 0;
+}
+
symbol concat(symbol, symbol);
diff --git a/contrib/groff/src/roff/troff/token.h b/contrib/groff/src/roff/troff/token.h
index b87a0b1..59f2aa2 100644
--- a/contrib/groff/src/roff/troff/token.h
+++ b/contrib/groff/src/roff/troff/token.h
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001
+/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001, 2002
Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
@@ -51,14 +51,16 @@ class token {
TOKEN_REQUEST,
TOKEN_RIGHT_BRACE,
TOKEN_SPACE, // ` ' -- ordinary space
- TOKEN_SPECIAL, // a special character -- \' \` \- \(xx
+ TOKEN_SPECIAL, // a special character -- \' \` \- \(xx \[xxx]
TOKEN_SPREAD, // \p -- break and spread output line
TOKEN_STRETCHABLE_SPACE, // \~
+ TOKEN_UNSTRETCHABLE_SPACE, // `\ '
TOKEN_TAB, // tab
TOKEN_TRANSPARENT, // \!
TOKEN_TRANSPARENT_DUMMY, // \)
+ TOKEN_ZERO_WIDTH_BREAK, // \:
TOKEN_EOF // end of file
- } type;
+ } type;
public:
token();
~token();
@@ -71,6 +73,7 @@ public:
int nspaces(); // 1 if space, 2 if double space, 0 otherwise
int space(); // is the current token a space?
int stretchable_space(); // is the current token a stretchable space?
+ int unstretchable_space(); // is the current token an unstretchable space?
int white_space(); // is the current token space or tab?
int special(); // is the current token a special character?
int newline(); // is the current token a newline?
@@ -85,6 +88,7 @@ public:
int right_brace();
int page_ejector();
int hyphen_indicator();
+ int zero_width_break();
int operator==(const token &); // need this for delimiters, and for conditions
int operator!=(const token &); // ditto
unsigned char ch();
@@ -103,6 +107,7 @@ extern token tok; // the current token
extern symbol get_name(int required = 0);
extern symbol get_long_name(int required = 0);
extern charinfo *get_optional_char();
+extern char *read_string();
extern void check_missing_character();
extern void skip_line();
extern void handle_initial_title();
@@ -137,6 +142,11 @@ inline int token::stretchable_space()
return type == TOKEN_STRETCHABLE_SPACE;
}
+inline int token::unstretchable_space()
+{
+ return type == TOKEN_UNSTRETCHABLE_SPACE;
+}
+
inline int token::special()
{
return type == TOKEN_SPECIAL;
@@ -215,4 +225,9 @@ inline int token::hyphen_indicator()
return type == TOKEN_HYPHEN_INDICATOR;
}
+inline int token::zero_width_break()
+{
+ return type == TOKEN_ZERO_WIDTH_BREAK;
+}
+
int has_arg();
diff --git a/contrib/groff/src/roff/troff/troff.h b/contrib/groff/src/roff/troff/troff.h
index 254c626..80d9f0b 100644
--- a/contrib/groff/src/roff/troff/troff.h
+++ b/contrib/groff/src/roff/troff/troff.h
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001
+/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001, 2002
Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
@@ -20,16 +20,16 @@ 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 <stdio.h>
+#include "lib.h"
+
#include <ctype.h>
-#include <string.h>
#include <time.h>
#include <stddef.h>
#include <stdlib.h>
#include <errno.h>
-#include "lib.h"
#include "assert.h"
+#include "color.h"
#include "device.h"
#include "searchpath.h"
@@ -43,6 +43,7 @@ extern units units_per_inch;
extern int ascii_output_flag;
extern int suppress_output_flag;
+extern int color_flag;
extern int is_html;
extern int tcommand_flag;
@@ -76,13 +77,18 @@ enum warning_type {
WARN_ESCAPE = 0100000,
WARN_SPACE = 0200000,
WARN_FONT = 0400000,
- WARN_IG = 01000000
+ WARN_IG = 01000000,
+ WARN_COLOR = 02000000
// change WARN_TOTAL if you add more warning types
};
-const int WARN_TOTAL = 01777777;
+const int WARN_TOTAL = 02777777;
int warning(warning_type, const char *,
const errarg & = empty_errarg,
const errarg & = empty_errarg,
const errarg & = empty_errarg);
+int output_warning(warning_type, const char *,
+ const errarg & = empty_errarg,
+ const errarg & = empty_errarg,
+ const errarg & = empty_errarg);
diff --git a/contrib/groff/src/roff/troff/troff.man b/contrib/groff/src/roff/troff/troff.man
index ac746dc..19bb624 100644
--- a/contrib/groff/src/roff/troff/troff.man
+++ b/contrib/groff/src/roff/troff/troff.man
@@ -1,25 +1,44 @@
+'\" t
.ig
-Copyright (C) 1989-2000, 2001 Free Software Foundation, Inc.
+troff.man
-Permission is granted to make and distribute verbatim copies of
-this manual provided the copyright notice and this permission notice
-are preserved on all copies.
+Last update : 9 Jan 2002
-Permission is granted to copy and distribute modified versions of this
-manual under the conditions for verbatim copying, provided that the
-entire resulting derived work is distributed under the terms of a
-permission notice identical to this one.
+This file is part of groff, the GNU roff type-setting system.
-Permission is granted to copy and distribute translations of this
-manual into another language, under the above conditions for modified
-versions, except that this permission notice may be included in
-translations approved by the Free Software Foundation instead of in
-the original English.
+Copyright (C) 1989, 2000, 2001, 2002 Free Software Foundation, Inc.
+
+written by James Clark
+
+modified by Werner Lemberg <wl@gnu.org>
+ Bernd Warken <bwarken@mayn.de>
+
+Permission is granted to copy, distribute and/or modify this document
+under the terms of the GNU Free Documentation License, Version 1.1 or
+any later version published by the Free Software Foundation; with the
+Invariant Sections being this .ig-section and AUTHOR, with no
+Front-Cover Texts, and with no Back-Cover Texts.
+
+A copy of the Free Documentation License is included as a file called
+FDL in the main directory of the groff source package.
..
.
-.\" define a string tx for the TeX logo
-.ie t .ds tx T\h'-.1667m'\v'.224m'E\v'-.224m'\h'-.125m'X
-.el .ds tx TeX
+.
+.\" --------------------------------------------------------------------
+.\" Setup
+.\" --------------------------------------------------------------------
+.
+.mso www.tmac
+.
+.if n \{\
+. mso tty-char.tmac
+. ftr CR R
+. ftr CI I
+. ftr CB B
+.\}
+.
+.if '\*[.T]'dvi' \
+. ftr CB CW
.
.de TQ
.br
@@ -34,22 +53,19 @@ the original English.
.el .TP "\\$1"
..
.
-.\" The BSD man macros can't handle " in arguments to font change macros,
-.\" so use \(ts instead of ".
-.tr \(ts"
.
+.\" --------------------------------------------------------------------
+.\" Title
+.\" --------------------------------------------------------------------
.
.TH @G@TROFF @MAN1EXT@ "@MDATE@" "Groff Version @VERSION@"
-.
-.
.SH NAME
+@g@troff \- the troff processor of the groff text formatting system
.
.
-@g@troff \- format documents
-.
-.
+.\" --------------------------------------------------------------------
.SH SYNOPSIS
-.
+.\" --------------------------------------------------------------------
.
.nr a \n(.j
.ad l
@@ -61,90 +77,75 @@ the original English.
.ie \\n(.$-1 .RI "[\ \fB\\$1\fP" "\\$2" "\ ]"
.el .RB "[\ " "\\$1" "\ ]"
..
-.OP \-abivzCERU
-.OP \-w name
-.OP \-W name
+.OP \-abcivzCERU
.OP \-d cs
.OP \-f fam
+.OP \-F dir
.OP \-m name
+.OP \-M dir
.OP \-n num
.OP \-o list
.OP \-r cn
.OP \-T name
-.OP \-F dir
-.OP \-M dir
+.OP \-w name
+.OP \-W name
.RI "[\ " files\|.\|.\|. "\ ]"
.br
.ad \na
-.PP
-It is possible to have whitespace between a command line option and its
-parameter.
+.P
+It is possible to have whitespace between a command line option and
+its parameter.
.
.
+.\" --------------------------------------------------------------------
.SH DESCRIPTION
-.
+.\" --------------------------------------------------------------------
.
This manual page describes the GNU version of
-.BR troff ,
-which is part of the groff document formatting system.
-It is highly compatible with UNIX troff.
-Usually it should be invoked using the groff command, which will
-also run preprocessors and postprocessors in the appropriate
-order and with the appropriate options.
+.BR troff .
+It is part of the groff document formatting system.
.
+It is functionally compatible with UNIX troff, but has many extensions,
+see
+.BR \%groff_diff (@MAN7EXT@).
+Usually it should be invoked using the
+.BR groff (@MAN1EXT@)
+command which will also run preprocessors and postprocessors in the
+appropriate order and with the appropriate options.
.
-.SH OPTIONS
.
+.\" --------------------------------------------------------------------
+.SH OPTIONS
+.\" --------------------------------------------------------------------
.
.TP \w'\-dname=s'u+2n
.B \-a
Generate an
.SM ASCII
approximation of the typeset output.
+.
.TP
.B \-b
-Print a backtrace with each warning or error message. This backtrace
-should help track down the cause of the error. The line numbers given
-in the backtrace may not always be correct:
-.BR troff 's
-idea of line numbers
-gets confused by
+Print a backtrace with each warning or error message.
+.
+This backtrace should help track down the cause of the error.
+.
+The line numbers given in the backtrace may not always be correct, for
+.BR @g@troff 's
+idea of line numbers gets confused by
.B as
or
.B am
requests.
+.
.TP
-.B \-i
-Read the standard input after all the named input files have been
-processed.
-.TP
-.B \-v
-Print the version number.
-.TP
-.BI \-w name
-Enable warning
-.IR name .
-Available warnings are described in
-the Warnings subsection below.
-Multiple
-.B \-w
-options are allowed.
-.TP
-.BI \-W name
-Inhibit warning
-.IR name .
-Multiple
-.B \-W
-options are allowed.
-.TP
-.B \-E
-Inhibit all error messages.
-.TP
-.B \-z
-Suppress formatted output.
+.B \-c
+Disable color output (always disabled in compatibility mode).
+.
.TP
.B \-C
Enable compatibility mode.
+.
.TP
.BI \-d cs
.TQ
@@ -157,11 +158,42 @@ to be a string
.IR s ;
.I c
must be a one letter name.
+.
+.TP
+.B \-E
+Inhibit all error messages of
+.BR @g@troff .
+Note that this doesn't affect messages output to standard error by macro
+packages using the
+.B tm
+or
+.B tm1
+requests.
+.
.TP
.BI \-f fam
Use
.I fam
as the default font family.
+.
+.TP
+.BI \-F dir
+Search in directory (or directory path)
+.I dir
+for subdirectories
+.BI dev name
+.RI ( name
+is the name of the device) and there for the
+.B DESC
+file and font files.
+.I dir
+is scanned before all other font directories.
+.
+.TP
+.B \-i
+Read the standard input after all the named input files have been
+processed.
+.
.TP
.BI \-m name
Read in the file
@@ -169,36 +201,28 @@ Read in the file
If it isn't found, try
.BI tmac. name
instead.
+.
It will be first searched for in directories given with the
.B \-M
-command line option, then in directories given
-in the
+command line option, then in directories given in the
.B GROFF_TMAC_PATH
environment variable, then in the current directory (only if in unsafe
mode), the home directory, @SYSTEMMACRODIR@, @LOCALMACRODIR@, and
@MACRODIR@.
+.
.TP
-.B \-U
-Unsafe mode.
-This will enable the following requests:
-.BR .open ,
-.BR .opena ,
-.BR .pso ,
-.BR .sy ,
-and
-.BR .pi .
-For security reasons, these potentially dangerous requests are disabled
-otherwise. It will also add the current directory to the macro search path.
-.TP
-.B \-R
-Don't load
-.B troffrc
-and
-.BR troffrc-end .
+.BI \-M dir
+Search directory (or directory path)
+.I dir
+for macro files.
+.
+This is scanned before all other macro directories.
+.
.TP
.BI \-n num
Number the first page
.IR num .
+.
.TP
.BI \-o list
Output only pages in
@@ -218,8 +242,9 @@ means print every page up to
.IB n \-
means print every page from
.IR n .
-.B Troff
+.B @g@troff
will exit after printing the last page in the list.
+.
.TP
.BI \-r cn
.TQ
@@ -234,2227 +259,339 @@ to
must be a one character name;
.I n
can be any troff numeric expression.
+.
+.TP
+.B \-R
+Don't load
+.B troffrc
+and
+.BR troffrc-end .
+.
.TP
.BI \-T name
Prepare output for device
.IR name ,
rather than the default
.BR @DEVICE@ .
-.TP
-.BI \-F dir
-Search in directory (or directory path)
-.I dir
-for subdirectories
-.BI dev name
-.RI ( name
-is the name of the device) and there for the
-.B DESC
-file and font files.
-.I dir
-is scanned before all other font directories.
-.TP
-.BI \-M dir
-Search directory (or directory path)
-.I dir
-for macro files.
-This is scanned before all other macro directories.
-.
-.
-.SH USAGE
-.
-.
-Only the features not in UNIX troff are described here.
.
-.SS Long names
-.
-The names of number registers, fonts, strings/macros/diversions,
-special characters can be of any length. In escape sequences, where
-you can use
-.BI ( xx
-for a two character name, you can use
-.BI [ xxx ]
-for a name of arbitrary length:
-.TP
-.BI \e[ xxx ]
-Print the special character called
-.IR xxx .
-.TP
-.BI \ef[ xxx ]
-Set font
-.IR xxx .
.TP
-.BI \e*[ xxx ]
-Interpolate string
-.IR xxx .
-.TP
-.BI \en[ xxx ]
-Interpolate number register
-.IR xxx .
-.
-.SS Fractional pointsizes
-.
-A
-.I
-scaled point
-is equal to 1/sizescale
-points, where
-sizescale is specified in the
-.B DESC
-file (1 by default).
-There is a new scale indicator
-.B z
-which has the effect of multiplying by sizescale.
-Requests and escape sequences in troff
-interpret arguments that represent a pointsize as being in units
-of scaled points, but they evaluate each such argument
-using a default scale indicator of
-.BR z .
-Arguments treated in this way are
-the argument to the
-.B ps
-request,
-the third argument to the
-.B cs
-request,
-the second and fourth arguments to the
-.B tkf
-request,
-the argument to the
-.B \eH
-escape sequence,
-and those variants of the
-.B \es
-escape sequence that take a numeric expression as their argument.
-.LP
-For example, suppose sizescale is 1000;
-then a scaled point will be equivalent to a millipoint;
-the request
-.B .ps 10.25
-is equivalent to
-.B .ps 10.25z
-and so sets the pointsize to 10250 scaled points,
-which is equal to 10.25 points.
-.LP
-The number register
-.B \en[.s]
-returns the pointsize in points as decimal fraction.
-There is also a new number register
-.B \en[.ps]
-that returns the pointsize in scaled points.
-.LP
-It would make no sense to use the
-.B z
-scale indicator in a numeric expression
-whose default scale indicator was neither
-.B u
-nor
-.BR z ,
-and so
-.B troff
-disallows this.
-Similarly it would make no sense to use a scaling indicator
-other than
-.B z
-or
-.B u
-in a numeric expression whose default scale indicator was
-.BR z ,
-and so
-.B troff
-disallows this as well.
-.LP
-There is also new scale indicator
-.B s
-which multiplies by the number of units in a scaled point.
-So, for example,
-.B \en[.ps]s
-is equal to
-.BR 1m .
-Be sure not to confuse the
-.B s
-and
-.B z
-scale indicators.
-.
-.SS Numeric expressions
+.B \-U
+Unsafe mode.
.
-.LP
-Spaces are permitted in a number expression within parentheses.
-.LP
-.B M
-indicates a scale of 100ths of an em.
-.TP
-.IB e1 >? e2
-The maximum of
-.I e1
-and
-.IR e2 .
-.TP
-.IB e1 <? e2
-The minimum of
-.I e1
+This will enable the following requests:
+.BR open ,
+.BR opena ,
+.BR pso ,
+.BR sy ,
and
-.IR e2 .
-.TP
-.BI ( c ; e )
-Evaluate
-.I e
-using
-.I c
-as the default scaling indicator.
-If
-.I c
-is missing, ignore scaling indicators in the evaluation of
-.IR e .
+.BR pi .
+For security reasons, these potentially dangerous requests are disabled
+otherwise.
.
-.SS New escape sequences
+It will also add the current directory to the macro search path.
.
.TP
-.BI \eA' anything '
-This expands to
-.B 1
-or
-.B 0
-according as
-.I anything
-is or is not acceptable as the name of a string, macro, diversion,
-number register, environment or font.
-It will return
-.B 0
-if
-.I anything
-is empty.
-This is useful if you want to lookup user input in some sort of
-associative table.
-.TP
-.BI \eB' anything '
-This expands to
-.B 1
-or
-.B 0
-according as
-.I anything
-is or is not a valid numeric expression.
-It will return
-.B 0
-if
-.I anything
-is empty.
-.TP
-.BI \eC' xxx '
-Typeset character named
-.IR xxx .
-Normally it is more convenient to use
-.BI \e[ xxx ]\fR.
-But
-.B \eC
-has the advantage that it is compatible with recent versions of
-.SM UNIX
-and is available in compatibility mode.
-.TP
-.B \eE
-This is equivalent to an escape character,
-but it's not interpreted in copy-mode.
-For example, strings to start and end superscripting could be defined
-like this:
-.RS
-.IP
-\&.ds { \ev'\-.3m'\es'\eEn[.s]*6u/10u'
-.br
-\&.ds } \es0\ev'.3m'
-.LP
-The use of
-.B \eE
-ensures that these definitions will work even if
-.B \e*{
-gets interpreted in copy-mode
-(for example, by being used in a macro argument).
-.RE
-.TP
-.BI \eN' n '
-Typeset the character with code
-.I n
-in the current font.
-.I n
-can be any integer.
-Most devices only have characters with codes between 0 and 255.
-If the current font does not contain a character with that code,
-special fonts will
-.I not
-be searched.
-The
-.B \eN
-escape sequence can be conveniently used on conjunction with the
-.B char
-request:
-.RS
-.IP
-.B
-\&.char \e[phone] \ef(ZD\eN'37'
-.RE
-.IP
-The code of each character is given in the fourth column in the font
-description file after the
-.B charset
-command.
-It is possible to include unnamed characters in the font description
-file by using a name of
-.BR \-\-\- ;
-the
-.B \eN
-escape sequence is the only way to use these.
-.TP
-.BI \eR' name\ \(+-n '
-This has the same effect as
-.RS
-.IP
-.BI .nr\ name\ \(+-n
-.RE
-.TP
-.BI \es( nn
-.TQ
-.BI \es\(+-( nn
-Set the point size to
-.I nn
-points;
-.I nn
-must be exactly two digits.
-.TP
-.BI \es[\(+- n ]
-.TQ
-.BI \es\(+-[ n ]
-.TQ
-.BI \es'\(+- n '
-.TQ
-.BI \es\(+-' n '
-Set the point size to
-.I n
-scaled points;
-.I n
-is a numeric expression with a default scale indicator of
-.BR z .
-.TP
-.BI \eV x
-.TQ
-.BI \eV( xx
-.TQ
-.BI \eV[ xxx ]
-Interpolate the contents of the environment variable
-.IR xxx ,
-as returned by
-.BR getenv (3).
-.B \eV
-is interpreted in copy-mode.
-.TP
-.BI \eY x
-.TQ
-.BI \eY( xx
-.TQ
-.BI \eY[ xxx ]
-This is approximately equivalent to
-.BI \eX'\e*[ xxx ]'\fR.
-However the contents of the string or macro
-.I xxx
-are not interpreted;
-also it is permitted for
-.I xxx
-to have been defined as a macro and thus contain newlines
-(it is not permitted for the argument to
-.B \eX
-to contain newlines).
-The inclusion of newlines requires an extension to the UNIX troff output
-format, and will confuse drivers that do not know about this
-extension.
-.TP
-.BI \eZ' anything '
-Print anything and then restore the horizontal and vertical
-position;
-.I anything
-may not contain tabs or leaders.
-.TP
-.B \e$0
-The name by which the current macro was invoked.
-The
-.B als
-request can make a macro have more than one name.
-.TP
-.B \e$*
-In a macro, the concatenation of all the arguments separated by spaces.
-.TP
-.B \e$@
-In a macro, the concatenation of all the arguments with each surrounded by
-double quotes, and separated by spaces.
-.TP
-.BI \e$( nn
-.TQ
-.BI \e$[ nnn ]
-In a macro, this gives the
-.IR nn -th
-or
-.IR nnn -th
-argument.
-Macros can have an unlimited number of arguments.
-.TP
-.BI \e? anything \e?
-When used in a diversion, this will transparently embed
-.I anything
-in the diversion.
-.I anything
-is read in copy mode.
-When the diversion is reread,
-.I anything
-will be interpreted.
-.I anything
-may not contain newlines; use
-.B \e!\&
-if you want to embed newlines in a diversion.
-The escape sequence
-.B \e?\&
-is also recognised in copy mode and turned into a single internal
-code; it is this code that terminates
-.IR anything .
-Thus
-.RS
-.RS
-.ft B
-.nf
-.ne 15
-\&.nr x 1
-\&.nf
-\&.di d
-\e?\e\e?\e\e\e\e?\e\e\e\e\e\e\e\enx\e\e\e\e?\e\e?\e?
-\&.di
-\&.nr x 2
-\&.di e
-\&.d
-\&.di
-\&.nr x 3
-\&.di f
-\&.e
-\&.di
-\&.nr x 4
-\&.f
-.fi
-.ft
-.RE
-.RE
-.IP
-will print
-.BR 4 .
-.TP
-.B \e/
-This increases the width of the preceding character so that
-the spacing between that character and the following character
-will be correct if the following character is a roman character.
-For example, if an italic f is immediately followed by a roman
-right parenthesis, then in many fonts the top right portion of the f
-will overlap the top left of the right parenthesis producing \fIf\fR)\fR,
-which is ugly.
-Inserting
-.B \e/
-produces
-.ie \n(.g \fIf\/\fR)\fR
-.el \fIf\|\fR)\fR
-and avoids this problem.
-It is a good idea to use this escape sequence whenever an
-italic character is immediately followed by a roman character without any
-intervening space.
-.TP
-.B \e,
-This modifies the spacing of the following character so that the spacing
-between that character and the preceding character will correct if
-the preceding character is a roman character.
-For example, inserting
-.B \e,
-between the parenthesis and the f changes
-\fR(\fIf\fR to
-.ie \n(.g \fR(\,\fIf\fR.
-.el \fR(\^\fIf\fR.
-It is a good idea to use this escape sequence whenever a
-roman character is immediately followed by an italic character without any
-intervening space.
-.TP
-.B \e)
-Like
-.B \e&
-except that it behaves like a character declared with the
-.B cflags
-request to be transparent for the purposes of end of sentence recognition.
-.TP
-.B \e~
-This produces an unbreakable space that stretches like a normal inter-word
-space when a line is adjusted.
-.TP
-.B \e:
-This causes the insertion of a zero-width break point.
-It is equal to
-.B \e%
-but without insertion of a soft hyphen character.
-.TP
-.B \e#
-Everything up to and including the next newline is ignored.
-This is interpreted in copy mode.
-This is like
-.B \e"
-except that
-.B \e"
-does not ignore the terminating newline.
-.
-.SS New requests
+.B \-v
+Print the version number.
.
.TP
-.BI .aln\ xx\ yy
-Create an alias
-.I xx
-for number register object named
-.IR yy .
-The new name and the old name will be exactly equivalent.
-If
-.I yy
-is undefined, a warning of type
-.B reg
-will be generated, and the request will be ignored.
-.TP
-.BI .als\ xx\ yy
-Create an alias
-.I xx
-for request, string, macro, or diversion object named
-.IR yy .
-The new name and the old name will be exactly equivalent (it is similar to a
-hard rather than a soft link).
-If
-.I yy
-is undefined, a warning of type
-.B mac
-will be generated, and the request will be ignored.
-The
-.BR de ,
-.BR am ,
-.BR di ,
-.BR da ,
-.BR ds ,
-and
-.B as
-requests only create a new object if the name of the macro, diversion
-or string diversion is currently undefined or if it is defined to be a
-request; normally they modify the value of an existing object.
-.TP
-.BI .am1\ xx\ yy
-Similar to
-.BR .am ,
-but compatibility mode is switched off during execution.
-On entry, the current compatibility mode is saved and restored at exit.
-.TP
-.BI .asciify\ xx
-This request `unformats' the diversion
-.I xx
-in such a way that
-.SM ASCII
-and space characters (and some escape sequences) that were formatted and
-diverted into
-.I xx
-will be treated like ordinary input characters when
-.I xx
-is reread.
-Useful for diversions in conjunction with the
-.B .writem
-request.
-It can be also used for gross hacks; for example, this
-.RS
-.IP
-.ne 7v+\n(.Vu
-.ft B
-.nf
-\&.tr @.
-\&.di x
-\&@nr n 1
-\&.br
-\&.di
-\&.tr @@
-\&.asciify x
-\&.x
-.fi
-.RE
-.IP
-will set register
-.B n
-to 1.
-Note that glyph information (font, font size, etc.) is not preserved; use
-.B .unformat
-instead.
-.TP
-.B .backtrace
-Print a backtrace of the input stack on stderr.
-.TP
-.BI .blm\ xx
-Set the blank line macro to
-.IR xx .
-If there is a blank line macro,
-it will be invoked when a blank line is encountered instead of the usual
-troff behaviour.
-.TP
-.BI .box\ xx
-.TQ
-.BI .boxa\ xx
-These requests are similar to the
-.B di
-and
-.B da
-requests with the exception that a partially filled line will not become
-part of the diversion (i.e., the diversion always starts with a new line)
-but restored after ending the diversion, discarding the partially filled
-line which possibly comes from the diversion.
-.TP
-.B .break
-Break out of a while loop.
-See also the
-.B while
-and
-.B continue
-requests.
-Be sure not to confuse this with the
-.B br
-request.
-.TP
-.B .brp
-This is the same as
-.BR \ep .
-.TP
-.BI .cflags\ n\ c1\ c2\|.\|.\|.
-Characters
-.IR c1 ,
-.IR c2 ,\|.\|.\|.
-have properties determined by
-.IR n ,
-which is ORed from the following:
-.RS
-.TP
-1
-the character ends sentences
-(initially characters
-.B .?!\&
-have this property);
-.TP
-2
-lines can be broken before the character
-(initially no characters have this property);
-a line will not be broken at a character with this property
-unless the characters on each side both have non-zero
-hyphenation codes.
-.TP
-4
-lines can be broken after the character
-(initially characters
-.B \-\e(hy\e(em
-have this property);
-a line will not be broken at a character with this property
-unless the characters on each side both have non-zero
-hyphenation codes.
-.TP
-8
-the character overlaps horizontally
-(initially characters
-.B \e(ul\e(rn\e(ru
-have this property);
-.TP
-16
-the character overlaps vertically
-(initially character
-.B \e(br
-has this property);
-.TP
-32
-an end of sentence character followed by any number of characters
-with this property will be treated
-as the end of a sentence if followed by a newline or two spaces;
-in other words
-the character is transparent for the purposes of end of sentence
-recognition;
-this is the same as having a zero space factor in \*(tx
-(initially characters
-.B \(ts')]*\e(dg\e(rq
-have this property).
-.RE
-.TP
-.BI .char\ c\ string
-Define character
-.I c
-to be
-.IR string .
-Every time character
-.I c
-needs to be printed,
-.I string
-will be processed in a temporary environment and the result
-will be wrapped up into a single object.
-Compatibility mode will be turned off
-and the escape character will be set to
-.B \e
-while
-.I string
-is being processed.
-Any emboldening, constant spacing or track kerning will be applied
-to this object rather than to individual characters in
-.IR string .
-A character defined by this request can be used just like
-a normal character provided by the output device.
-In particular other characters can be translated to it
-with the
-.B tr
-request;
-it can be made the leader character by the
-.B lc
-request;
-repeated patterns can be drawn with the character using the
-.B \el
-and
-.B \eL
-escape sequences;
-words containing the character can be hyphenated
-correctly, if the
-.B hcode
-request is used to give the character a hyphenation code.
-There is a special anti-recursion feature:
-use of character within the character's definition
-will be handled like normal characters not defined with
-.BR char .
-A character definition can be removed with the
-.B rchar
-request.
-.TP
-.BI .chop\ xx
-Chop the last character off macro, string, or diversion
-.IR xx .
-This is useful for removing the newline from the end of diversions
-that are to be interpolated as strings.
-.TP
-.BI .close\ stream
-Close the stream named
-.IR stream ;
-.I stream
-will no longer be an acceptable argument to the
-.B write
-request.
-See the
-.B open
-request.
-.TP
-.B .continue
-Finish the current iteration of a while loop.
-See also the
-.B while
-and
-.B break
-requests.
-.TP
-.BI .cp\ n
-If
-.I n
-is non-zero or missing, enable compatibility mode, otherwise
-disable it.
-In compatibility mode, long names are not recognised, and the
-incompatibilities caused by long names do not arise.
-.TP
-.BI .dei\ xx\ yy
-Define macro indirectly.
-The following example
-.RS
-.IP
-.ne 2v+\n(.Vu
-.ft B
-.nf
-\&.ds xx aa
-\&.ds yy bb
-\&.dei xx yy
-.fi
-.RE
-.IP
-is equivalent to
-.RS
-.IP
-.B
-\&.de aa bb
-.RE
-.TP
-.BI .de1\ xx\ yy
-Similar to
-.BR .de ,
-but compatibility mode is switched off during execution.
-On entry, the current compatibility mode is saved and restored at exit.
-.TP
-.BI .do\ xxx
-Interpret
-.I .xxx
-with compatibility mode disabled.
-For example,
-.RS
-.IP
-.B
-\&.do fam T
-.LP
-would have the same effect as
-.IP
-.B
-\&.fam T
-.LP
-except that it would work even if compatibility mode had been enabled.
-Note that the previous compatibility mode is restored before any files
-sourced by
-.I xxx
-are interpreted.
-.RE
-.TP
-.B .ecs
-Save current escape character.
-.TP
-.B .ecr
-Restore escape character saved with
-.BR ecs .
-Without a previous call to
-.BR ecs ,
-.RB ` \e '
-will be the new escape character.
-.TP
-.BI .evc\ xx
-Copy the contents of environment
-.I xx
-to the current environment.
-No pushing or popping of environents will be done.
-.TP
-.BI .fam\ xx
-Set the current font family to
-.IR xx .
-The current font family is part of the current environment.
-If
-.I xx
-is missing, switch back to previous font family.
-See the description of the
-.B sty
-request for more information on font families.
-.TP
-.BI .fspecial\ f\ s1\ s2\|.\|.\|.
-When the current font is
-.IR f ,
-fonts
-.IR s1 ,
-.IR s2 ,\|.\|.\|.
-will be special, that is, they will searched for characters not in
-the current font.
-Any fonts specified in the
-.B special
-request will be searched after fonts specified in the
-.B fspecial
-request.
-.TP
-.BI .ftr\ f\ g
-Translate font
-.I f
-to
-.IR g .
-Whenever a font named
-.I f
-is referred to in
-.B \ef
-escape sequence,
-or in the
-.BR ft ,
-.BR ul ,
-.BR bd ,
-.BR cs ,
-.BR tkf ,
-.BR special ,
-.BR fspecial ,
-.BR fp ,
-or
-.BR sty
-requests,
-font
-.I g
-will be used.
-If
-.I g
-is missing,
-or equal to
-.I f
-then font
-.I f
-will not be translated.
-.TP
-.BI .hcode \ c1\ code1\ c2\ code2\|.\|.\|.
-Set the hyphenation code of character
-.I c1
-to
-.I code1
-and that of
-.I c2
-to
-.IR code2 .
-A hyphenation code must be a single input
-character (not a special character) other than a digit or a space.
-Initially each lower-case letter has a hyphenation code, which
-is itself, and each upper-case letter has a hyphenation code
-which is the lower case version of itself.
-See also the
-.B hpf
-request.
-.TP
-.BI .hla\ lang
-Set the current hyphenation language to
-.IR lang .
-Hyphenation exceptions specified with the
-.B hw
-request and hyphenation patterns specified with the
-.B hpf
-request are both associated with the current hyphenation language.
-The
-.B hla
-request is usually invoked by the
-.B troffrc
-file.
-.TP
-.BI .hlm\ n
-Set the maximum number of consecutive hyphenated lines to
-.IR n .
-If
-.I n
-is negative, there is no maximum.
-The default value is \-1.
-This value is associated with the current environment.
-Only lines output from an environment count towards the maximum associated
-with that environment.
-Hyphens resulting from
-.B \e%
-are counted; explicit hyphens are not.
-.TP
-.BI .hpf\ file
-Read hyphenation patterns from
-.IR file ;
-this will be searched for in the same way that
-.IB name .tmac
-is searched for when the
-.BI \-m name
-option is specified.
-It should have the same format as the argument to
-the \epatterns primitive in \*(tx;
-the letters appearing in this file are interpreted as hyphenation
-codes.
-A
-.B %
-character in the patterns file introduces a comment that continues
-to the end of the line.
-The set of hyphenation patterns is associated with the current language
-set by the
-.B hla
-request.
-The
-.B hpf
-request
-is usually invoked by the
-.B troffrc
-file.
-.TP
-.BI .hym\ n
-Set the
-.I hyphenation margin
-to
-.IR n :
-when the current adjustment mode is not
-.BR b ,
-the line will not be hyphenated if the line is no more than
-.I n
-short.
-The default hyphenation margin is 0.
-The default scaling indicator for this request is
-.IR m .
-The hyphenation margin is associated with the current environment.
-The current hyphenation margin is available in the
-.B \en[.hym]
-register.
-.TP
-.BI .hys\ n
-Set the
-.I hyphenation space
-to
-.IR n :
-when the current adjustment mode is
-.B b
-don't hyphenate the line if the line can be justified by adding no more than
-.I n
-extra space to each word space.
-The default hyphenation space is 0.
-The default scaling indicator for this request is
-.BR m .
-The hyphenation space is associated with the current environment.
-The current hyphenation space is available in the
-.B \en[.hys]
-register.
-.TP
-.BI .kern\ n
-If
-.I n
-is non-zero or missing, enable pairwise kerning, otherwise disable it.
-.TP
-.BI .length\ xx\ string
-Compute the length of
-.I string
-and return it in the number register
-.I xx
-(which is not necessarily defined before).
-.TP
-.BI .linetabs\ n
-If
-.I n
-is non-zero or missing, enable line-tabs mode, otherwise disable it (which
-is the default).
-In line-tabs mode, tab distances are computed relative to the (current)
-output line.
-Otherwise they are taken relative to the input line.
-For example, the following
-.RS
-.IP
-.ne 6v+\n(.Vu
-.ft B
-.nf
-\&.ds x a\et\ec
-\&.ds y b\et\ec
-\&.ds z c
-\&.ta 1i 3i
-\e*x
-\e*y
-\e*z
-.fi
-.RE
-.IP
-yields
-.RS
-.IP
-a b c
-.RE
-.IP
-In line-tabs mode, the same code gives
-.RS
-.IP
-a b c
-.RE
-.IP
-Line-tabs mode is associated with the current environment; the read-only
-number register
-.B \\en[.linetabs]
-is set to\~1 if in line-tabs mode, and 0 otherwise.
-.TP
-.BI .mso\ file
-The same as the
-.B so
-request except that
-.I file
-is searched for in the same directories as macro files for the
-the
-.B \-m
-command line option.
-If the file name to be included
-has the form
-.IB name .tmac
-and it isn't found,
-.B mso
-tries to include
-.BI tmac. name
-instead and vice versa.
-.TP
-.BI .nop \ anything
-Execute
-.IR anything .
-This is similar to `.if\ 1'.
-.TP
-.B .nroff
-Make the
-.B n
-built-in condition true
-and the
-.B t
-built-in condition false.
-This can be reversed using the
-.B troff
-request.
-.TP
-.BI .open\ stream\ filename
-Open
-.I filename
-for writing and associate the stream named
-.I stream
-with it.
-See also the
-.B close
-and
-.B write
-requests.
-.TP
-.BI .opena\ stream\ filename
-Like
-.BR open ,
-but if
-.I filename
-exists, append to it instead of truncating it.
-.TP
-.B .pnr
-Print the names and contents of all currently defined number registers
-on stderr.
-.TP
-.BI .psbb \ filename
-Get the bounding box of a PostScript image
-.IR filename .
-This file must conform to Adobe's Document Structuring Conventions; the
-command looks for a
-.B %%BoundingBox
-comment to extract the bounding box values.
-After a successful call, the coordinates (in PostScript units) of the lower
-left and upper right corner can be found in the registers
-.BR \en[llx] ,
-.BR \en[lly] ,
-.BR \en[urx] ,
-and
-.BR \en[ury] ,
-respectively.
-If some error has occurred, the four registers are set to zero.
-.TP
-.BI .pso \ command
-This behaves like the
-.B so
-request except that input comes from the standard output of
-.IR command .
-.TP
-.B .ptr
-Print the names and positions of all traps (not including input line
-traps and diversion traps) on stderr. Empty slots in the page trap
-list are printed as well, because they can affect the priority of
-subsequently planted traps.
-.TP
-.BI .rchar\ c1\ c2\|.\|.\|.
-Remove the definitions of characters
-.IR c1 ,
-.IR c2 ,\|.\|.\|.
-This undoes the effect of a
-.B char
-request.
-.TP
-.B .return
-Within a macro, return immediately.
-No effect otherwise.
-.TP
-.B .rj
-.TQ
-.BI .rj\ n
-Right justify the next
-.I n
-input lines.
-Without an argument right justify the next input line.
-The number of lines to be right justified is available in the
-.B \en[.rj]
-register.
-This implicitly does
-.BR .ce\ 0 .
-The
-.B ce
-request implicitly does
-.BR .rj\ 0 .
-.TP
-.BI .rnn \ xx\ yy
-Rename number register
-.I xx
-to
-.IR yy .
-.TP
-.BI .shc\ c
-Set the soft hyphen character to
-.IR c .
-If
-.I c
-is omitted,
-the soft hyphen character will be set to the default
-.BR \e(hy .
-The soft hyphen character is the character which will be inserted
-when a word is hyphenated at a line break.
-If the soft hyphen character does not exist in the font of the character
-immediately preceding a potential break point,
-then the line will not be broken at that point.
-Neither definitions (specified with the
-.B char
-request)
-nor translations (specified with the
-.B tr
-request)
-are considered when finding the soft hyphen character.
-.TP
-.BI .shift\ n
-In a macro, shift the arguments by
-.I n
-positions:
-argument
-.I i
-becomes argument
-.IR i \- n ;
-arguments 1 to
-.I n
-will no longer be available.
-If
-.I n
-is missing,
-arguments will be shifted by 1.
-Shifting by negative amounts is currently undefined.
-.TP
-.BI .special\ s1\ s2\|.\|.\|.
-Fonts
-.IR s1 ,
-.IR s2 ,
-are special and will be searched for characters not in the
-current font.
-.TP
-.BI .sty\ n\ f
-Associate style
-.I f
-with font position
-.IR n .
-A font position can be associated either with a font or
-with a style.
-The current font is the index of a font position and so is also
-either a font or a style.
-When it is a style, the font that is actually used is the font the
-name of which is the concatenation of the name of the current family
-and the name of the current style.
-For example, if the current font is 1 and font position 1 is
-associated with style
-.B R
-and the current
-font family is
-.BR T ,
-then font
-.BR TR
-will be used.
-If the current font is not a style, then the current family is ignored.
-When the requests
-.BR cs ,
-.BR bd ,
-.BR tkf ,
-.BR uf ,
-or
-.B fspecial
-are applied to a style,
-then they will instead be applied to the member of the
-current family corresponding to that style.
-The default family can be set with the
-.B \-f
-option.
-The styles command in the
-.SM DESC
-file controls which font positions
-(if any) are initially associated with styles rather than fonts.
-.TP
-.BI .substring\ xx\ n1\ [ n2 ]
-Replace the string in register
-.I xx
-with the substring defined by the indices
-.I n1
-and
-.IR n2 .
-The first character in the string has index one.
-If
-.I n2
-is omitted, it is taken to be equal to the string's length. If the
-index value
-.I n1
-or
-.I n2
-is negative or zero, it will be counted from the end of the string,
-going backwards: The last character has index 0, the character before
-the last character has index -1, etc.
-.TP
-.BI .tkf\ f\ s1\ n1\ s2\ n2
-Enable track kerning for font
-.IR f .
-When the current font is
-.I f
-the width of every character will be increased by an amount
-between
-.I n1
-and
-.IR n2 ;
-when the current point size is less than or equal to
-.I s1
-the width will be increased by
-.IR n1 ;
-when it is greater than or equal to
-.I s2
-the width will be increased by
-.IR n2 ;
-when the point size is greater than or equal to
-.I s1
-and less than or equal to
-.I s2
-the increase in width is a linear function of the point size.
-.TP
-.BI .tm1\ string
-Similar to the
-.B tm
-request,
-.I string
-is read in copy mode and written on the standard error, but an initial
-double quote in
-.I string
-is stripped off to allow initial blanks.
-.TP
-.BI .tmc\ string
-Similar to
-.BR tm1
-but without writing a final newline.
-.TP
-.BI .trf\ filename
-Transparently output the contents of file
-.IR filename .
-Each line is output as it would be were it preceded by
-.BR \e! ;
-however, the lines are not subject to copy-mode interpretation.
-If the file does not end with a newline, then a newline will
-be added.
-For example, you can define a macro
-.I x
-containing the contents of file
-.IR f ,
-using
-.RS
-.IP
-.BI .di\ x
-.br
-.BI .trf\ f
-.br
-.B .di
-.LP
-Unlike with the
-.B cf
-request,
-the file cannot contain characters such as
-.SM NUL
-that are not legal troff input characters.
-.RE
-.TP
-.B .trnt abcd
-This is the same as the
-.B tr
-request except that the translations do not apply to text that is
-transparently throughput into a diversion with
-.BR \e! .
-For example,
-.RS
-.IP
-.nf
-.ft B
-\&.tr ab
-\&.di x
-\e!.tm a
-\&.di
-\&.x
-.fi
-.ft
-.LP
-will print
-.BR b ;
-if
-.B trnt
-is used instead of
-.B tr
-it will print
-.BR a .
-.RE
-.TP
-.B .troff
-Make the
-.B n
-built-in condition false,
-and the
-.B t
-built-in condition true.
-This undoes the effect of the
-.B nroff
-request.
-.TP
-.BI .unformat\ xx
-This request `unformats' the diversion
-.IR xx .
-Contrary to the
-.B .asciify
-request, which tries to convert formatted elements of the diversion back
-to input tokens as much as possible,
-.B .unformat
-will only handle tabs and spaces between words (usually caused by spaces
-or newlines in the input) specially.
-The former are treated as if they were input tokens, and the latter are
-stretchable again.
-Note that the vertical size of lines is not preserved.
-Glyph information (font, font size, space width, etc.) is retained.
-Useful in conjunction with the
-.B .box
-and
-.B .boxa
-requests.
-.TP
-.BI .vpt\ n
-Enable vertical position traps if
-.I n
-is non-zero, disable them otherwise.
-Vertical position traps are traps set by the
-.B wh
-or
-.B dt
-requests.
-Traps set by the
-.B it
-request are not vertical position traps.
-The parameter that controls whether vertical position traps are enabled
-is global.
-Initially vertical position traps are enabled.
-.TP
-.BI .warn\ n
-Control warnings.
-.I n
-is the sum of the numbers associated with each warning that is to be enabled;
-all other warnings will be disabled.
-The number associated with each warning is listed in the `Warnings' section.
-For example,
-.B .warn 0
-will disable all warnings, and
-.B .warn 1
-will disable all warnings except that about missing characters.
-If
-.I n
-is not given,
-all warnings will be enabled.
-.TP
-.BI .while \ c\ anything
-While condition
-.I c
-is true, accept
-.I anything
-as input;
-.I c
-can be any condition acceptable to an
-.B if
-request;
-.I anything
-can comprise multiple lines if the first line starts with
-.B \e{
-and the last line ends with
-.BR \e} .
-See also the
-.B break
-and
-.B continue
-requests.
-.TP
-.BI .write\ stream\ anything
-Write
-.I anything
-to the stream named
-.IR stream .
-.I stream
-must previously have been the subject of an
-.B open
-request.
-.I anything
-is read in copy mode;
-a leading
-.B \(ts
-will be stripped.
-.TP
-.BI .writem\ stream\ xx
-Write the contents of the macro or string
-.I xx
-to the stream named
-.IR stream .
-.I stream
-must previously have been the subject of an
-.B open
-request.
-.I xx
-is read in copy mode.
+.BI \-w name
+Enable warning
+.IR name .
+Available warnings are described in the section
+.I WARNINGS
+below.
.
-.SS Extended requests
+For example, to enable all warnings, use
+.B \-w
+.BR all .
+Multiple
+.B \-w
+options are allowed.
.
.TP
-.BI .cf\ filename
-When used in a diversion, this will embed in the diversion an object which,
-when reread, will cause the contents of
-.I filename
-to be transparently copied through to the output.
-In UNIX troff, the
-contents of
-.I filename
-is immediately copied through to the output regardless of whether
-there is a current diversion; this behaviour is so anomalous that it
-must be considered a bug.
-.TP
-.BI .ev\ xx
-If
-.I xx
-is not a number, this will switch to a named environment called
-.IR xx .
-The environment should be popped with a matching
-.B ev
-request without any arguments, just as for numbered environments.
-There is no limit on the number of named environments; they will be
-created the first time that they are referenced.
-.TP
-.BI .fp\ n\ f1\ f2
-The
-.B fp
-request has an optional third argument.
-This argument gives the external name of the font,
-which is used for finding the font description file.
-The second argument gives the internal name of the font
-which is used to refer to the font in troff after it has been mounted.
-If there is no third argument then the internal name will be used
-as the external name.
-This feature allows you to use fonts with long names in compatibility mode.
-.TP
-.BI .ss\ m\ n
-When two arguments are given to the
-.B ss
-request, the second argument gives the
-.IR "sentence space size" .
-If the second argument is not given, the sentence space size
-will be the same as the word space size.
-Like the word space size, the sentence space is in units of
-one twelfth of the spacewidth parameter for the current font.
-Initially both the word space size and the sentence
-space size are 12.
-Contrary to UNIX troff, GNU troff handles this request in nroff mode
-also; a given value is then rounded down to the nearest multiple of\~12.
-The sentence space size is used in two circumstances:
-if the end of a sentence occurs at the end of a line in fill mode, then
-both an inter-word space and a sentence space will be added;
-if two spaces follow the end of a sentence in the middle of a line,
-then the second space will be a sentence space.
-Note that the behaviour of UNIX troff will be exactly
-that exhibited by GNU troff if a second argument is never given to the
-.B ss
-request.
-In GNU troff, as in UNIX troff, you should always
-follow a sentence with either a newline or two spaces.
-.TP
-.BI .ta\ n1\ n2\|.\|.\|.nn \ T\ r1\ r2\|.\|.\|.\|rn
-Set tabs at positions
-.IR n1 ,
-.IR n2 ,\|.\|.\|.\|,
-.I nn
-and then set tabs at
-.IR nn + r1 ,
-.IR nn + r2 ,\|.\|.\|.\|.\|,
-.IR nn + rn
-and then at
-.IR nn + rn + r1 ,
-.IR nn + rn + r2 ,\|.\|.\|.\|,
-.IR nn + rn + rn ,
-and so on.
-For example,
-.RS
-.IP
-.B
-\&.ta T .5i
-.LP
-will set tabs every half an inch.
-.RE
-.
-.SS New number registers
+.BI \-W name
+Inhibit warning
+.IR name .
+Multiple
+.B \-W
+options are allowed.
.
-The following read-only registers are available:
-.TP
-.B \en[.C]
-1 if compatibility mode is in effect, 0 otherwise.
-.TP
-.B \en[.cdp]
-The depth of the last character added to the current environment.
-It is positive if the character extends below the baseline.
-.TP
-.B \en[.ce]
-The number of lines remaining to be centered, as set by the
-.B ce
-request.
-.TP
-.B \en[.cht]
-The height of the last character added to the current environment.
-It is positive if the character extends above the baseline.
-.TP
-.B \en[.csk]
-The skew of the last character added to the current environment.
-The
-.I skew
-of a character is how far to the right of the center of a character
-the center of an accent over that character should be placed.
-.TP
-.B \en[.ev]
-The name or number of the current environment.
-This is a string-valued register.
-.TP
-.B \en[.fam]
-The current font family.
-This is a string-valued register.
-.TP
-.B \en[.fp]
-The number of the next free font position.
-.TP
-.B \en[.g]
-Always 1.
-Macros should use this to determine whether they are running
-under GNU troff.
-.TP
-.B \en[.hla]
-The current hyphenation language as set by the
-.B hla
-request.
-.TP
-.B \en[.hlc]
-The number of immediately preceding consecutive hyphenated lines.
-.TP
-.B \en[.hlm]
-The maximum allowed number of consecutive hyphenated lines, as set by the
-.B hlm
-request.
-.TP
-.B \en[.hy]
-The current hyphenation flags (as set by the
-.B hy
-request).
-.TP
-.B \en[.hym]
-The current hyphenation margin (as set by the
-.B hym
-request).
-.TP
-.B \en[.hys]
-The current hyphenation space (as set by the
-.B hys
-request).
-.TP
-.B \en[.in]
-The indent that applies to the current output line.
-.TP
-.B \en[.int]
-Set to a positive value if last output line is interrupted (i.e., if it
-contains
-.IR \ec ).
-.TP
-.B \en[.kern]
-.B 1
-if pairwise kerning is enabled,
-.B 0
-otherwise.
-.TP
-.B \en[.lg]
-The current ligature mode (as set by the
-.B lg
-request).
-.TP
-.B \en[.linetabs]
-The current line-tabs mode (as set by the
-.B linetabs
-request).
-.TP
-.B \en[.ll]
-The line length that applies to the current output line.
-.TP
-.B \en[.lt]
-The title length as set by the
-.B lt
-request.
-.TP
-.B \en[.ne]
-The amount of space that was needed in the last
-.B ne
-request that caused a trap to be sprung.
-Useful in conjunction with the
-.B \en[.trunc]
-register.
-.TP
-.B \en[.ns]
-.B 1
-if no-space mode is active,
-.B 0
-otherwise.
-.TP
-.B \en[.pn]
-The number of the next page:
-either the value set by a
-.B pn
-request, or the number of the current page plus 1.
-.TP
-.B \en[.ps]
-The current pointsize in scaled points.
-.TP
-.B \en[.psr]
-The last-requested pointsize in scaled points.
-.TP
-.B \en[.rj]
-The number of lines to be right-justified as set by the
-.B rj
-request.
-.TP
-.B \en[.sr]
-The last requested pointsize in points as a decimal fraction.
-This is a string-valued register.
-.TP
-.B \en[.tabs]
-A string representation of the current tab settings suitable for use as
-an argument to the
-.B ta
-request.
-.TP
-.B \en[.trunc]
-The amount of vertical space truncated by the most recently sprung
-vertical position trap, or,
-if the trap was sprung by a
-.B ne
-request,
-minus the amount of vertical motion produced by the
-.B ne
-request.
-In other words, at the point a trap is sprung, it represents the difference
-of what the vertical position would have been but for the trap,
-and what the vertical position actually is.
-Useful in conjunction with the
-.B \en[.ne]
-register.
-.TP
-.B \en[.ss]
-.TQ
-.B \en[.sss]
-These give the values of the parameters set by the
-first and second arguments of the
-.B ss
-request.
-.TP
-.B \en[.vpt]
-1 if vertical position traps are enabled, 0 otherwise.
-.TP
-.B \en[.warn]
-The sum of the numbers associated with each of the currently enabled
-warnings.
-The number associated with each warning is listed in the `Warnings'
-subsection.
-.TP
-.B \en[.x]
-The major version number.
-For example, if the version number is
-.B 1.03
-then
-.B \en[.x]
-will contain
-.BR 1 .
-.TP
-.B \en[.y]
-The minor version number.
-For example, if the version number is
-.B 1.03
-then
-.B \en[.y]
-will contain
-.BR 03 .
-.TP
-.B \en[.Y]
-The revision number of groff.
-.TP
-.B \en[llx]
-.TQ
-.B \en[lly]
-.TQ
-.B \en[urx]
-.TQ
-.B \en[ury]
-These four registers are set by the
-.B \&.psbb
-request and contain the bounding box values (in PostScript units) of a given
-PostScript image.
-.LP
-The following read/write registers are set by the
-.B \ew
-escape sequence:
-.TP
-.B \en[rst]
-.TQ
-.B \en[rsb]
-Like the
-.B st
-and
-.B sb
-registers, but takes account of the heights and depths of characters.
-.TP
-.B \en[ssc]
-The amount of horizontal space (possibly negative) that should
-be added to the last character before a subscript.
-.TP
-.B \en[skw]
-How far to right of the center of the last character
-in the
-.B \ew
-argument,
-the center of an accent from a roman font should be placed over that character.
-.LP
-Other available read/write number registers are:
-.TP
-.B \en[c.]
-The current input line number.
-.B \en[.c]
-is a read-only alias to this register.
.TP
-.B \en[hp]
-The current horizontal position at input line.
-.TP
-.B \en[systat]
-The return value of the system() function executed by the last
-.B sy
-request.
-.TP
-.B \en[slimit]
-If greater than 0, the maximum number of objects on the input stack.
-If less than or equal to 0, there is no limit on the number of objects
-on the input stack. With no limit, recursion can continue until
-virtual memory is exhausted.
-.TP
-.B \en[year]
-The current year.
-Note that the traditional
-.B troff
-number register
-.B \en[yr]
-is the current year minus 1900.
-.
-.SS Miscellaneous
+.B \-z
+Suppress formatted output.
.
-.B @g@troff
-predefines a single (read/write) string-based register,
-.BR \e*(.T ,
-which contains the argument given to the
-.B -T
-command line option, namely the current output device (for example,
-.I latin1
-or
-.IR ascii ).
-Note that this is not the same as the (read-only) number register
-.B \en[.T]
-which is defined to be\ 1 if
-.B troff
-is called with the
-.B -T
-command line option, and zero otherwise. This behaviour is different to
-UNIX troff.
-.LP
-Fonts not listed in the
-.SM DESC
-file are automatically mounted on the next available font position
-when they are referenced.
-If a font is to be mounted explicitly with the
-.B fp
-request on an unused font position,
-it should be mounted on the first unused font position,
-which can be found in the
-.B \en[.fp]
-register;
-although
-.B troff
-does not enforce this strictly,
-it will not allow a font to be mounted at a position whose number is much
-greater than that of any currently used position.
-.LP
-Interpolating a string does not hide existing macro arguments.
-Thus in a macro, a more efficient way of doing
-.IP
-.BI . xx\ \e\e$@
-.LP
-is
-.IP
-.BI \e\e*[ xx ]\e\e
-.LP
-If the font description file contains pairwise kerning information,
-characters from that font will be kerned.
-Kerning between two characters can be inhibited by placing a
-.B \e&
-between them.
-.LP
-In a string comparison in a condition,
-characters that appear at different input levels
-to the first delimiter character will not be recognised
-as the second or third delimiters.
-This applies also to the
-.B tl
-request.
-In a
-.B \ew
-escape sequence,
-a character that appears at a different input level to
-the starting delimiter character will not be recognised
-as the closing delimiter character.
-When decoding a macro argument that is delimited
-by double quotes, a character that appears at a different
-input level to the starting delimiter character will not
-be recognised as the closing delimiter character.
-The implementation of
-.B \e$@
-ensures that the double quotes surrounding an argument
-will appear the same input level, which will be different
-to the input level of the argument itself.
-In a long escape name
-.B ]
-will not be recognized as a closing delimiter except
-when it occurs at the same input level as the opening
-.BR ] .
-In compatibility mode, no attention is paid to the input-level.
-.LP
-There are some new types of condition:
-.TP
-.BI .if\ r xxx
-True if there is a number register named
-.IR xxx .
-.TP
-.BI .if\ d xxx
-True if there is a string, macro, diversion, or request named
-.IR xxx .
-.TP
-.BI .if\ c ch
-True if there is a character
-.IR ch
-available;
-.I ch
-is either an
-.SM ASCII
-character
-or a special character
-.BI \e( xx
-or
-.BI \e[ xxx ]\fR;
-the condition will also be true if
-.I ch
-has been defined by the
-.B char
-request.
-.LP
-The
-.B tr
-request can now map characters onto
-.BR \e~ .
.
-.SS Warnings
+.\" --------------------------------------------------------------------
+.SH WARNINGS
+.\" --------------------------------------------------------------------
.
The warnings that can be given by
-.B troff
+.B @g@troff
are divided into the following categories.
+.
The name associated with each warning is used by the
.B \-w
and
.B \-W
-options;
-the number is used by the
+options; the number is used by the
.B warn
request, and by the
.B .warn
-register.
-.nr x \w'\fBright-brace'+1n+\w'0000'u
+register; it is always a power of 2 to allow bitwise composition.
+.
+.P
+.TS
+tab(@), center, box;
+c c c | c c c
+r rI lB | r rI lB.
+Bit@Code@Warning@Bit@Code@Warning
+_
+0@1@char@10@1024@reg
+1@2@number@11@2048@tab
+2@4@break@12@4096@right-brace
+3@8@delim@13@8192@missing
+4@16@el@14@16384@input
+5@32@scale@15@32768@escape
+6@64@range@16@65536@space
+7@128@syntax@17@131072@font
+8@256@di@18@262144@ig
+9@512@mac@19@524288@color
+.TE
+.
+.P
+.nr x \w'\fBright-brace'+1n+\w'00000'u
.ta \nxuR
+.
.TP \nxu+3n
-.BR char \t1
-Non-existent characters.
+.BR break "\t4"
+In fill mode, lines which could not be broken so that their length was
+less than the line length.
+.
This is enabled by default.
+.
.TP
-.BR number \t2
-Invalid numeric expressions.
+.BR char "\t1"
+Non-existent characters.
+.
This is enabled by default.
+.
.TP
-.BR break \t4
-In fill mode, lines which could not be broken so that their length was
-less than the line length.
-This is enabled by default.
+.BR color "\t524288"
+Color related warnings.
+.
.TP
-.BR delim \t8
+.BR delim "\t8"
Missing or mismatched closing delimiters.
+.
+.TP
+.BR di "\t256"
+Use of
+.B di
+or
+.B da
+without an argument when there is no current diversion.
+.
.TP
-.BR el \t16
+.BR el "\t16"
Use of the
.B el
request with no matching
.B ie
request.
+.
.TP
-.BR scale \t32
-Meaningless scaling indicators.
+.BR escape "\t32768"
+Unrecognized escape sequences.
+.
+When an unrecognized escape sequence is encountered, the escape
+character is ignored.
+.
.TP
-.BR range \t64
-Out of range arguments.
+.BR font "\t131072"
+Non-existent fonts.
+.
+This is enabled by default.
+.
.TP
-.BR syntax \t128
-Dubious syntax in numeric expressions.
+.BR ig "\t262144"
+Invalid escapes in text ignored with the
+.B ig
+request.
+.
+These are conditions that are errors when they do not occur in ignored
+text.
+.
.TP
-.BR di \t256
-Use of
-.B di
-or
-.B da
-without an argument when there is no current diversion.
+.BR input "\t16384"
+Invalid input characters.
+.
.TP
-.BR mac \t512
+.BR mac "\t512"
Use of undefined strings, macros and diversions.
-When an undefined string, macro or diversion is used,
-that string is automatically defined as empty.
-So, in most cases, at most one warning will be given for
-each name.
+.
+When an undefined string, macro or diversion is used, that string is
+automatically defined as empty.
+.
+So, in most cases, at most one warning will be given for each name.
+.
.TP
-.BR reg \t1024
-Use of undefined number registers.
-When an undefined number register is used,
-that register is automatically defined to have a value of 0.
-a definition is automatically made with a value of 0.
-So, in most cases, at most one warning will be given for
-use of a particular name.
+.BR missing "\t8192"
+Requests that are missing non-optional arguments.
+.
.TP
-.BR tab \t2048
-Inappropriate use of a tab character.
-Either use of a tab character where a number was expected,
-or use of tab character in an unquoted macro argument.
+.BR number "\t2"
+Invalid numeric expressions.
+.
+This is enabled by default.
+.
.TP
-.BR right-brace \t4096
-Use of
-.B \e}
-where a number was expected.
+.BR range "\t64"
+Out of range arguments.
+.
.TP
-.BR missing \t8192
-Requests that are missing non-optional arguments.
+.BR reg "\t1024"
+Use of undefined number registers.
+.
+When an undefined number register is used, that register is
+automatically defined to have a value of\~0.
+.
+So, in most cases, at most one warning will be given for use of a
+particular name.
+.
.TP
-.BR input \t16384
-Illegal input characters.
+.BR right-brace "\t4096"
+Use of
+.B \[rs]}
+where a number was expected.
+.
.TP
-.BR escape \t32768
-Unrecognized escape sequences.
-When an unrecognized escape sequence is encountered,
-the escape character is ignored.
+.BR scale "\t32"
+Meaningless scaling indicators.
+.
.TP
-.BR space \t65536
+.BR space "\t65536"
Missing space between a request or macro and its argument.
-This warning will be given
-when an undefined name longer than two characters is encountered,
-and the first two characters of the name make a defined name.
+.
+This warning will be given when an undefined name longer than two
+characters is encountered, and the first two characters of the name
+make a defined name.
+.
The request or macro will not be invoked.
+.
When this warning is given, no macro is automatically defined.
+.
This is enabled by default.
+.
This warning will never occur in compatibility mode.
+.
.TP
-.BR font \t131072
-Non-existent fonts.
-This is enabled by default.
+.BR syntax "\t128"
+Dubious syntax in numeric expressions.
+.
.TP
-.BR ig \t262144
-Illegal escapes in text ignored with the
-.B ig
-request.
-These are conditions that are errors when they do not occur
-in ignored text.
-.LP
+.BR tab "\t2048"
+Inappropriate use of a tab character.
+Either use of a tab character where a number was expected, or use of tab
+character in an unquoted macro argument.
+.
+.P
There are also names that can be used to refer to groups of warnings:
+.
.TP
.B all
All warnings except
.BR di ,
-.B mac
+.BR mac ,
and
.BR reg .
-It is intended that this covers all warnings
-that are useful with traditional macro packages.
+It is intended that this covers all warnings that are useful with
+traditional macro packages.
+.
.TP
.B w
All warnings.
.
-.SS Incompatibilities
-.
-.LP
-Long names cause some incompatibilities.
-UNIX troff will interpret
-.IP
-.B
-\&.dsabcd
-.LP
-as defining a string
-.B ab
-with contents
-.BR cd .
-Normally, GNU troff will interpret this as a call of a macro named
-.BR dsabcd .
-Also UNIX troff will interpret
-.B \e*[
-or
-.B \en[
-as references to a string or number register called
-.BR [ .
-In GNU troff, however, this will normally be interpreted as the start
-of a long name.
-In
-.I compatibility mode
-GNU troff will interpret these things in the traditional way.
-In compatibility mode, however, long names are not recognised.
-Compatibility mode can be turned on with the
-.B \-C
-command line option, and turned on or off with the
-.B cp
-request.
-The number register
-.B \en[.C]
-is 1 if compatibility mode is on, 0 otherwise.
-.LP
-GNU troff
-does not allow the use of the escape sequences
-.BR \\e\e|\e^\e&\e}\e{\e (space) \e'\e`\e-\e_\e!\e%\ec
-in names of strings, macros, diversions, number registers,
-fonts or environments; UNIX troff does.
-The
-.B \eA
-escape sequence may be helpful in avoiding use of these
-escape sequences in names.
-.LP
-Fractional pointsizes cause one noteworthy incompatibility.
-In UNIX troff the
-.B ps
-request ignores scale indicators and so
-.IP
-.B .ps\ 10u
-.LP
-will set the pointsize to 10 points, whereas in
-GNU troff it will set the pointsize to 10 scaled points.
-.LP
-In GNU troff there is a fundamental difference between unformatted,
-input characters, and formatted, output characters.
-Everything that affects how an output character
-will be output is stored with the character; once an output
-character has been constructed it is unaffected by any subsequent
-requests that are executed, including
-.BR bd ,
-.BR cs ,
-.BR tkf ,
-.BR tr ,
-or
-.B fp
-requests.
-Normally output characters are constructed from input
-characters at the moment immediately before the character
-is added to the current output line.
-Macros, diversions and strings are all, in fact, the same type
-of object; they contain lists of input characters and output
-characters in any combination.
-An output character does not behave like an input character
-for the purposes of macro processing; it does not inherit any
-of the special properties that the input character from which it
-was constructed might have had.
-For example,
-.IP
-.nf
-.ft B
-\&.di x
-\e\e\e\e
-\&.br
-\&.di
-\&.x
-.ft
-.fi
-.LP
-will print
-.B \e\e
-in GNU troff;
-each pair of input
-.BR \e s
-is turned into one output
-.B \e
-and the resulting output
-.BR \e s
-are not interpreted as escape characters when they are reread.
-UNIX troff would interpret them as escape characters
-when they were reread and would end up printing one
-.BR \e .
-The correct way to obtain a printable
-.B \e
-is to use the
-.B \ee
-escape sequence: this will always print a single instance of the
-current escape character, regardless of whether or not it is used in a
-diversion; it will also work in both GNU troff and UNIX troff.
-If you wish for some reason to store in a diversion an escape
-sequence that will be interpreted when the diversion is reread,
-you can either use the traditional
-.B \e!\&
-transparent output facility, or, if this is unsuitable, the new
-.B \e?\&
-escape sequence.
-.
.
+.\" --------------------------------------------------------------------
.SH ENVIRONMENT
-.
+.\" --------------------------------------------------------------------
.
.TP
.SM
.B GROFF_TMAC_PATH
A colon separated list of directories in which to search for
macro files.
-.B troff
-will scan directories given in
-the
+.B @g@troff
+will scan directories given in the
.B \-M
-option before these, and in standard directories (current directory if in
-unsafe mode, home directory,
-.BR @LOCALMACRODIR@ ,
+option before these, and in standard directories (current directory if
+in unsafe mode, home directory,
.BR @SYSTEMMACRODIR@ ,
+.BR @LOCALMACRODIR@ ,
.BR @MACRODIR@ )
after these.
+.
.TP
.SM
.B GROFF_TYPESETTER
Default device.
+.
.TP
.SM
.B GROFF_FONT_PATH
A colon separated list of directories in which to search for the
.BI dev name
directory.
-.B troff
+.B @g@troff
will scan directories given in the
.B \-F
option before these, and in standard directories
-.RB ( @FONTPATH@ )
+.RB ( @LOCALFONTDIR@ ,
+.BR @FONTDIR@ ,
+.BR @LEGACYFONTDIR@ )
after these.
.
.
+.\" --------------------------------------------------------------------
.SH FILES
-.
+.\" --------------------------------------------------------------------
.
.Tp \w'@FONTDIR@/devname/DESC'u+3n
.B @MACRODIR@/troffrc
Initialization file (called before any other macro package).
+.
.TP
.B @MACRODIR@/troffrc-end
Initialization file (called after any other macro package).
+.
.TP
.BI @MACRODIR@/ name .tmac
.TQ
.BI @MACRODIR@/tmac. name
Macro files
+.
.TP
.BI @FONTDIR@/dev name /DESC
Device description file for device
.IR name .
+.
.TP
.BI @FONTDIR@/dev name / F
Font file for font
.I F
of device
.IR name .
-.LP
+.P
Note that
.B troffrc
and
.B troffrc-end
-are neither searched in the current nor in the home directory by default for
-security reasons (even if the
+are neither searched in the current nor in the home directory by
+default for security reasons (even if the
.B \-U
option is given).
+.
Use the
.B \-M
command line option or the
@@ -2463,28 +600,86 @@ environment variable to add these directories to the search path if
necessary.
.
.
+.\" --------------------------------------------------------------------
+.SH AUTHOR
+.\" --------------------------------------------------------------------
+.
+Copyright (C) 1989, 2001, 2002 Free Software Foundation, Inc.
+.
+.P
+This document is distributed under the terms of the FDL (GNU Free
+Documentation License) version 1.1 or later.
+.
+You should have received a copy of the FDL on your system, it is also
+available on-line at the
+.URL http://www.gnu.org/copyleft/fdl.html "GNU copyleft site" .
+This document was written by James Clark, with modifications from
+.MTO wl@gnu.org "Werner Lemberg"
+and
+.MTO bwarken@mayn.de "Bernd Warken"
+.
+.P
+This document is part of
+.IR groff ,
+the GNU roff distribution.
+.
+.
+.\" --------------------------------------------------------------------
.SH "SEE ALSO"
+.\" --------------------------------------------------------------------
.
+.TP
+.BR groff (@MAN1EXT@)
+The main program of the
+.I groff
+system, a wrapper around
+.IR @g@troff .
.
+.TP
.BR groff (@MAN7EXT@)
--- This is a short but complete reference of all requests, registers, and
-escapes.
-.PP
-.BR groff (@MAN1EXT@),
-.BR @g@tbl (@MAN1EXT@),
-.BR @g@pic (@MAN1EXT@),
-.BR @g@eqn (@MAN1EXT@),
-.BR @g@refer (@MAN1EXT@),
-.BR @g@soelim (@MAN1EXT@),
-.BR @g@grn (@MAN1EXT@),
-.BR grops (@MAN1EXT@),
-.BR grodvi (@MAN1EXT@),
-.BR grotty (@MAN1EXT@),
-.BR grohtml (@MAN1EXT@),
-.BR grolj4 (@MAN1EXT@),
-.BR groff_font (@MAN5EXT@),
-.BR groff_out (@MAN5EXT@),
-.BR groff_char (@MAN7EXT@)
+A description of the
+.I groff
+language, including a short but complete reference of all predefined
+requests, registers, and escapes of plain
+.IR groff .
+From the command line, this is called by
+.RS
+.IP
+.B man 7 groff
+.RE
+.
+.TP
+.BR \%groff_diff (@MAN7EXT@)
+The differences of the
+.I groff
+language and the
+.I classical troff
+language.
+.
+Currently, this is the most actual document of the
+.I groff
+system.
+.
+.TP
+.BR roff (@MAN7EXT@)
+An overview over
+.I groff
+and other
+.I roff
+systems, including pointers to further related documentation.
+.
+.P
+The
+.I groff info
+.IR file ,
+cf.\&
+.BR info (@MAN1EXT@),
+presents all groff documentation within a single document.
+.
+.
+.\" --------------------------------------------------------------------
+.\" Emacs variables
+.\" --------------------------------------------------------------------
.
.\" Local Variables:
.\" mode: nroff
diff --git a/contrib/groff/src/utils/addftinfo/Makefile.sub b/contrib/groff/src/utils/addftinfo/Makefile.sub
index 23848d5..af5bf70 100644
--- a/contrib/groff/src/utils/addftinfo/Makefile.sub
+++ b/contrib/groff/src/utils/addftinfo/Makefile.sub
@@ -1,9 +1,9 @@
-PROG=addftinfo
+PROG=addftinfo$(EXEEXT)
MAN1=addftinfo.n
XLIBS=$(LIBGROFF)
OBJS=\
- addftinfo.o \
- guess.o
+ addftinfo.$(OBJEXT) \
+ guess.$(OBJEXT)
CCSRCS=\
$(srcdir)/addftinfo.cc \
$(srcdir)/guess.cc
diff --git a/contrib/groff/src/utils/addftinfo/addftinfo.cc b/contrib/groff/src/utils/addftinfo/addftinfo.cc
index eb222d9..931d836 100644
--- a/contrib/groff/src/utils/addftinfo/addftinfo.cc
+++ b/contrib/groff/src/utils/addftinfo/addftinfo.cc
@@ -18,13 +18,12 @@ 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 <stdio.h>
+#include "lib.h"
+
#include <ctype.h>
-#include <string.h>
#include <assert.h>
#include <stdlib.h>
#include <errno.h>
-#include "lib.h"
#include "errarg.h"
#include "error.h"
#include "stringclass.h"
diff --git a/contrib/groff/src/utils/afmtodit/afmtodit.man b/contrib/groff/src/utils/afmtodit/afmtodit.man
index 585c229..2d4c866 100644
--- a/contrib/groff/src/utils/afmtodit/afmtodit.man
+++ b/contrib/groff/src/utils/afmtodit/afmtodit.man
@@ -1,5 +1,5 @@
.ig
-Copyright (C) 1989-2000, 2001 Free Software Foundation, Inc.
+Copyright (C) 1989-2000, 2001, 2002 Free Software Foundation, Inc.
Permission is granted to make and distribute verbatim copies of
this manual provided the copyright notice and this permission notice
@@ -16,15 +16,23 @@ versions, except that this permission notice may be included in
translations approved by the Free Software Foundation instead of in
the original English.
..
+.
+.
.\" Like TP, but if specified indent is more than half
.\" the current line-length - indent, use the default indent.
.de Tp
.ie \\n(.$=0:((0\\$1)*2u>(\\n(.lu-\\n(.iu)) .TP
.el .TP "\\$1"
..
+.
+.
.TH AFMTODIT @MAN1EXT@ "@MDATE@" "Groff Version @VERSION@"
+.
+.
.SH NAME
afmtodit \- create font files for use with groff \-Tps
+.
+.
.SH SYNOPSIS
.nr a \n(.j
.ad l
@@ -36,6 +44,7 @@ afmtodit \- create font files for use with groff \-Tps
.ie \\n(.$-1 .RI "[\ \fB\\$1\fP" "\\$2" "\ ]"
.el .RB "[\ " "\\$1" "\ ]"
..
+.
.OP \-nsv
.OP \-d desc_file
.OP \-e enc_file
@@ -46,16 +55,21 @@ afmtodit \- create font files for use with groff \-Tps
.I font
.br
.ad \na
+.
+.
.SH DESCRIPTION
.B afmtodit
creates a font file for use with groff and
.BR grops .
+.
.B afmtodit
is written in perl;
-you must have perl version 3 installed in order to run
+you must have perl version 3 or newer installed in order to run
.BR afmtodit .
+.
.I afm_file
is the AFM (Adobe Font Metric) file for the font.
+.
.I map_file
is a file that says which groff character names map onto
each PostScript character name;
@@ -69,15 +83,22 @@ where
is the PostScript name of the character
and
.I groff_char
-is the groff name of the character (as used in the groff font file.)
+is the groff name of the character (as used in the groff font file).
+.
The same
.I ps_char
can occur multiple times in the file;
each
.I groff_char
must occur at most once.
+.
+Lines starting with
+.B #
+and blank lines are ignored.
+.
.I font
is the groff name of the font.
+.
If a PostScript character is in the encoding to be used for the font
but is not mentioned in
.I map_file
@@ -88,14 +109,17 @@ which can be accessed by the
.B \eN
escape sequence in
.BR troff .
+.
The groff font file will be output to a file called
.IR font .
+.
.LP
If there is a downloadable font file for the font, it may be listed in
the file
.BR @FONTDIR@/devps/download ;
see
.BR grops (@MAN1EXT@).
+.
.LP
If the
.B \-i
@@ -123,53 +147,67 @@ is the PostScript name of the character,
and
.I n
is the desired value of the corresponding parameter in thousandths of an em.
+.
These parameters are normally needed only for italic (or oblique) fonts.
+.
+.
.SH OPTIONS
.TP
.B \-v
Print version.
+.
.TP
.B \-n
Don't output a
.B ligatures
command for this font.
+.
Use this with constant-width fonts.
+.
.TP
.B \-s
The font is special.
+.
The effect of this option is to add the
.B special
command to the font file.
+.
.TP
.BI \-d desc_file
The device description file is
.I desc_file
rather than the default
.BR DESC .
+.
.TP
.BI \-e enc_file
The PostScript font should be reencoded to use the encoding described
in enc_file.
+.
The format of
.I enc_file
is described in
.BR grops (@MAN1EXT@).
+.
.TP
.BI \-a n
Use
.I n
as the slant parameter in the font file;
this is used by groff in the positioning of accents.
+.
By default
.B afmtodit
uses the negative of the ItalicAngle specified in the afm file;
with true italic fonts it is sometimes desirable to use
a slant that is less than this.
+.
If you find that characters from an italic font have accents
placed too far to the right over them,
then use the
.B \-a
option to give the font a smaller slant.
+.
.TP
.BI \-i n
Generate an italic correction for each character so that
@@ -179,15 +217,19 @@ is equal to
thousandths of an em
plus the amount by which the right edge of the character's bounding
is to the right of the character's origin.
+.
If this would result in a negative italic correction, use a zero
italic correction instead.
+.
.IP
Also generate a subscript correction equal to the
product of the tangent of the slant of the font and
four fifths of the x-height of the font.
+.
If this would result in a subscript correction greater than the italic
correction, use a subscript correction equal to the italic correction
instead.
+.
.IP
Also generate a left italic correction for each character
equal to
@@ -195,29 +237,40 @@ equal to
thousandths of an em
plus the amount by which the left edge of the character's bounding box
is to the left of the character's origin.
+.
The left italic correction may be negative.
+.
.IP
This option is normally needed only with italic (or oblique) fonts.
+.
The font files distributed with groff were created using an option of
.B \-i50
for italic fonts.
+.
+.
.SH FILES
.Tp \w'\fB@FONTDIR@/devps/download'u+2n
.B @FONTDIR@/devps/DESC
Device description file.
+.
.TP
.BI @FONTDIR@/devps/ F
Font description file for font
.IR F .
+.
.TP
.B @FONTDIR@/devps/download
List of downloadable fonts.
+.
.TP
.B @FONTDIR@/devps/text.enc
Encoding used for text fonts.
+.
.TP
.B @FONTDIR@/devps/generate/textmap
Standard mapping.
+.
+.
.SH "SEE ALSO"
.BR groff (@MAN1EXT@),
.BR grops (@MAN1EXT@),
diff --git a/contrib/groff/src/utils/afmtodit/afmtodit.pl b/contrib/groff/src/utils/afmtodit/afmtodit.pl
index bfc058a..67c0f682 100644
--- a/contrib/groff/src/utils/afmtodit/afmtodit.pl
+++ b/contrib/groff/src/utils/afmtodit/afmtodit.pl
@@ -1,6 +1,6 @@
-#! /usr/bin/perl -P-
+#! /usr/bin/perl
# -*- Perl -*-
-# Copyright (C) 1989-2000 Free Software Foundation, Inc.
+# Copyright (C) 1989-2000, 2001, 2002 Free Software Foundation, Inc.
# Written by James Clark (jjc@jclark.com)
#
# This file is part of groff.
@@ -145,6 +145,7 @@ if ($opt_e) {
open(ENCODING, $opt_e) || die "$prog: can't open \`$opt_e': $!\n";
while (<ENCODING>) {
+ next if /^#/;
chop;
@field = split(' ');
if ($#field == 1) {
diff --git a/contrib/groff/src/utils/hpftodit/Makefile.sub b/contrib/groff/src/utils/hpftodit/Makefile.sub
index f5ff13e..7a16531 100644
--- a/contrib/groff/src/utils/hpftodit/Makefile.sub
+++ b/contrib/groff/src/utils/hpftodit/Makefile.sub
@@ -1,6 +1,6 @@
-PROG=hpftodit
+PROG=hpftodit$(EXEEXT)
MAN1=hpftodit.n
XLIBS=$(LIBGROFF)
MLIB=$(LIBM)
-OBJS=hpftodit.o
+OBJS=hpftodit.$(OBJEXT)
CCSRCS=$(srcdir)/hpftodit.cc
diff --git a/contrib/groff/src/utils/hpftodit/hpftodit.cc b/contrib/groff/src/utils/hpftodit/hpftodit.cc
index 15f6f7f..ecbc8a8 100644
--- a/contrib/groff/src/utils/hpftodit/hpftodit.cc
+++ b/contrib/groff/src/utils/hpftodit/hpftodit.cc
@@ -28,13 +28,12 @@ make it work with TrueType fonts
put filename in error messages (or fix lib)
*/
-#include <stdio.h>
+#include "lib.h"
+
#include <stdlib.h>
#include <math.h>
-#include <string.h>
#include <errno.h>
#include "assert.h"
-#include "lib.h"
#include "posix.h"
#include "errarg.h"
#include "error.h"
@@ -309,24 +308,6 @@ File::File(const char *s)
fatal("read unexpected number of bytes");
ptr_ = buf_;
end_ = buf_ + sb.st_size;
- // These are actually text files, so we must get rid of the `\r'
- // characters. This is also enabled for Posix systems, in case the
- // input came from Windows...
- unsigned char *p = buf_, *q = buf_;
- while (q < end_)
- {
- if (*q == '\r')
- {
- if (*++q != '\n')
- *p++ = '\r';
- }
-#if defined(__MSDOS__) || defined(_MSC_VER)
- if (*q == '\032') // ^Z means ``software EOF''
- break;
-#endif
- *p++ = *q++;
- }
- end_ = p;
}
void File::skip(int n)
diff --git a/contrib/groff/src/utils/indxbib/Makefile.sub b/contrib/groff/src/utils/indxbib/Makefile.sub
index f45a7a7..01e43b2 100644
--- a/contrib/groff/src/utils/indxbib/Makefile.sub
+++ b/contrib/groff/src/utils/indxbib/Makefile.sub
@@ -1,10 +1,10 @@
-PROG=indxbib
+PROG=indxbib$(EXEEXT)
MAN1=indxbib.n
XLIBS=$(LIBBIB) $(LIBGROFF)
MLIB=$(LIBM)
OBJS=\
- indxbib.o \
- signal.o
+ indxbib.$(OBJEXT) \
+ signal.$(OBJEXT)
CCSRCS=\
$(srcdir)/indxbib.cc
CSRCS=\
diff --git a/contrib/groff/src/utils/indxbib/indxbib.cc b/contrib/groff/src/utils/indxbib/indxbib.cc
index 4b2477f..9fced93 100644
--- a/contrib/groff/src/utils/indxbib/indxbib.cc
+++ b/contrib/groff/src/utils/indxbib/indxbib.cc
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 1989-1992, 2000, 2001 Free Software Foundation, Inc.
+/* Copyright (C) 1989-1992, 2000, 2001, 2002 Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
This file is part of groff.
@@ -18,14 +18,13 @@ 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 <stdio.h>
+#include "lib.h"
+
#include <stdlib.h>
-#include <string.h>
#include <assert.h>
#include <errno.h>
#include "posix.h"
-#include "lib.h"
#include "errarg.h"
#include "error.h"
#include "stringclass.h"
@@ -39,12 +38,6 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
extern "C" const char *Version_string;
-#ifndef HAVE_MKSTEMP_PROTO
-extern "C" {
- extern int mkstemp(char *);
-}
-#endif
-
#define DEFAULT_HASH_TABLE_SIZE 997
#define TEMP_INDEX_TEMPLATE "indxbibXXXXXX"
@@ -229,7 +222,7 @@ int main(int argc, char **argv)
name_max = file_name_max(".");
const char *filename = p ? p + 1 : basename;
if (name_max >= 0 &&
- long(strlen(filename) + sizeof(INDEX_SUFFIX) - 1) > name_max)
+ (strlen(filename) + sizeof(INDEX_SUFFIX) - 1) > name_max)
fatal("`%1.%2' is too long for a filename", filename, INDEX_SUFFIX);
if (p) {
p++;
@@ -240,16 +233,8 @@ int main(int argc, char **argv)
else {
temp_index_file = strsave(TEMP_INDEX_TEMPLATE);
}
-#ifndef HAVE_MKSTEMP
- if (!mktemp(temp_index_file) || !temp_index_file[0])
- fatal("cannot create file name for temporary file");
-#endif
catch_fatal_signals();
-#ifdef HAVE_MKSTEMP
int fd = mkstemp(temp_index_file);
-#else
- int fd = creat(temp_index_file, S_IRUSR|S_IRGRP|S_IROTH);
-#endif
if (fd < 0)
fatal("can't create temporary index file: %1", strerror(errno));
indxfp = fdopen(fd, FOPEN_WB);
@@ -300,6 +285,9 @@ int main(int argc, char **argv)
strcpy(index_file, basename);
strcat(index_file, INDEX_SUFFIX);
#ifdef HAVE_RENAME
+#ifdef __EMX__
+ unline(index_file);
+#endif /* __EMX__ */
if (rename(temp_index_file, index_file) < 0) {
#ifdef __MSDOS__
// RENAME could fail on plain MSDOS filesystems because
diff --git a/contrib/groff/src/utils/indxbib/signal.c b/contrib/groff/src/utils/indxbib/signal.c
index 8078472..fccd289 100644
--- a/contrib/groff/src/utils/indxbib/signal.c
+++ b/contrib/groff/src/utils/indxbib/signal.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1992 Free Software Foundation, Inc.
+/* Copyright (C) 1992, 2001 Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
This file is part of groff.
@@ -20,6 +20,10 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* Unfortunately vendors seem to have problems writing a <signal.h>
that is correct for C++, so we implement all signal handling in C. */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
#include <sys/types.h>
#include <signal.h>
#ifdef HAVE_UNISTD_H
diff --git a/contrib/groff/src/utils/lkbib/Makefile.sub b/contrib/groff/src/utils/lkbib/Makefile.sub
index 8f31e10..899236a 100644
--- a/contrib/groff/src/utils/lkbib/Makefile.sub
+++ b/contrib/groff/src/utils/lkbib/Makefile.sub
@@ -1,6 +1,6 @@
-PROG=lkbib
+PROG=lkbib$(EXEEXT)
MAN1=lkbib.n
XLIBS=$(LIBBIB) $(LIBGROFF)
MLIB=$(LIBM)
-OBJS=lkbib.o
+OBJS=lkbib.$(OBJEXT)
CCSRCS=$(srcdir)/lkbib.cc
diff --git a/contrib/groff/src/utils/lkbib/lkbib.cc b/contrib/groff/src/utils/lkbib/lkbib.cc
index 50e4e9b..42156ea 100644
--- a/contrib/groff/src/utils/lkbib/lkbib.cc
+++ b/contrib/groff/src/utils/lkbib/lkbib.cc
@@ -18,13 +18,12 @@ 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 <stdio.h>
+#include "lib.h"
+
#include <stdlib.h>
#include <errno.h>
-#include <string.h>
#include <assert.h>
-#include "lib.h"
#include "errarg.h"
#include "error.h"
diff --git a/contrib/groff/src/utils/lookbib/Makefile.sub b/contrib/groff/src/utils/lookbib/Makefile.sub
index 91b1404..7a08f0a 100644
--- a/contrib/groff/src/utils/lookbib/Makefile.sub
+++ b/contrib/groff/src/utils/lookbib/Makefile.sub
@@ -1,7 +1,7 @@
-PROG=lookbib
+PROG=lookbib$(EXEEXT)
MAN1=lookbib.n
XLIBS=$(LIBBIB) $(LIBGROFF)
MLIB=$(LIBM)
-OBJS=lookbib.o
+OBJS=lookbib.$(OBJEXT)
CCSRCS=$(srcdir)/lookbib.cc
NAMEPREFIX=$(g)
diff --git a/contrib/groff/src/utils/lookbib/lookbib.cc b/contrib/groff/src/utils/lookbib/lookbib.cc
index b742a4b..65e89bc 100644
--- a/contrib/groff/src/utils/lookbib/lookbib.cc
+++ b/contrib/groff/src/utils/lookbib/lookbib.cc
@@ -18,22 +18,23 @@ 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 <stdio.h>
+#include "lib.h"
+
#include <stdlib.h>
-#include <string.h>
#include <assert.h>
#include <errno.h>
#include "errarg.h"
#include "error.h"
-#include "lib.h"
#include "cset.h"
#include "refid.h"
#include "search.h"
+/* for isatty() */
+#include "posix.h"
+
extern "C" {
- int isatty(int);
const char *Version_string;
}
diff --git a/contrib/groff/src/utils/pfbtops/Makefile.sub b/contrib/groff/src/utils/pfbtops/Makefile.sub
index f731ff5..a8ed92a 100644
--- a/contrib/groff/src/utils/pfbtops/Makefile.sub
+++ b/contrib/groff/src/utils/pfbtops/Makefile.sub
@@ -1,6 +1,6 @@
-PROG=pfbtops
+PROG=pfbtops$(EXEEXT)
MAN1=pfbtops.n
-OBJS=pfbtops.o
+OBJS=pfbtops.$(OBJEXT)
CSRCS=$(srcdir)/pfbtops.c
XLIBS=$(LIBGROFF)
MLIB=$(LIBM)
diff --git a/contrib/groff/src/utils/pfbtops/pfbtops.c b/contrib/groff/src/utils/pfbtops/pfbtops.c
index 0964ede..3417dcb 100644
--- a/contrib/groff/src/utils/pfbtops/pfbtops.c
+++ b/contrib/groff/src/utils/pfbtops/pfbtops.c
@@ -19,7 +19,12 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* This translates ps fonts in .pfb format to ASCII ps files. */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
#include <stdio.h>
+#include <stdlib.h>
#include <getopt.h>
#include <limits.h>
diff --git a/contrib/groff/src/utils/tfmtodit/Makefile.sub b/contrib/groff/src/utils/tfmtodit/Makefile.sub
index 057bb3e..ee56ce6 100644
--- a/contrib/groff/src/utils/tfmtodit/Makefile.sub
+++ b/contrib/groff/src/utils/tfmtodit/Makefile.sub
@@ -1,6 +1,6 @@
-PROG=tfmtodit
+PROG=tfmtodit$(EXEEXT)
MAN1=tfmtodit.n
XLIBS=$(LIBGROFF)
MLIB=$(LIBM)
-OBJS=tfmtodit.o
+OBJS=tfmtodit.$(OBJEXT)
CCSRCS=$(srcdir)/tfmtodit.cc
diff --git a/contrib/groff/src/utils/tfmtodit/tfmtodit.cc b/contrib/groff/src/utils/tfmtodit/tfmtodit.cc
index 06b5d18..9fbbe25 100644
--- a/contrib/groff/src/utils/tfmtodit/tfmtodit.cc
+++ b/contrib/groff/src/utils/tfmtodit/tfmtodit.cc
@@ -47,12 +47,11 @@ This need only be done for a font for which math_fitting is false;
When it's true, the left_correction and subscript_correction should
both be zero. */
-#include <stdio.h>
+#include "lib.h"
+
#include <stdlib.h>
#include <math.h>
-#include <string.h>
#include <errno.h>
-#include "lib.h"
#include "errarg.h"
#include "error.h"
#include "assert.h"
diff --git a/contrib/groff/src/utils/tfmtodit/tfmtodit.man b/contrib/groff/src/utils/tfmtodit/tfmtodit.man
index b141c77..51f806d 100644
--- a/contrib/groff/src/utils/tfmtodit/tfmtodit.man
+++ b/contrib/groff/src/utils/tfmtodit/tfmtodit.man
@@ -1,5 +1,5 @@
.ig
-Copyright (C) 1989-2000, 2001 Free Software Foundation, Inc.
+Copyright (C) 1989-2000, 2001, 2002 Free Software Foundation, Inc.
Permission is granted to make and distribute verbatim copies of
this manual provided the copyright notice and this permission notice
@@ -121,8 +121,26 @@ def ignore_math_fit(expr left_adjustment,right_adjustment) =
.fi
.ft R
.LP
+For the EC font family, load the following definition after
+.B exbase
+(it is probably easiest to patch
+.B exbase.mf
+locally):
+.IP
+.nf
+.ft B
+def ignore_math_fit(expr left_adjustment,right_adjustment) =
+ ori_special "adjustment";
+ ori_numspecial left_adjustment*16/designsize;
+ ori_numspecial right_adjustment*16/designsize;
+ enddef;
+.fi
+.ft R
+.LP
The gf file created using this modified
.B cm.base
+or
+.B exbase
should be specified with the
.B \-g
option.
diff --git a/contrib/groff/src/xditview/ChangeLog b/contrib/groff/src/xditview/ChangeLog
index 977a90c..9db7cde 100644
--- a/contrib/groff/src/xditview/ChangeLog
+++ b/contrib/groff/src/xditview/ChangeLog
@@ -1,7 +1,57 @@
+2002-09-16 Werner LEMBERG <wl@gnu.org>
+
+ * Imakefile.in (GROFF_LOCALFONTDIR): New variable.
+ (GROFF_FONTPATH): Use it.
+ Remove /usr/local/lib/font.
+
+Version 1.18.0 released
+=======================
+
+2002-06-22 Werner LEMBERG <wl@gnu.org>
+
+ * gxditview.c (main): Handle `-help' and `--help' correctly.
+
+2002-06-17 Colin Watson <cjwatson@debian.org>
+
+ * Imakefile.in: s/@top_builddir@/@groff_top_builddir@/.
+
+2002-04-06 Werner LEMBERG <wl@gnu.org>
+
+ * DviChar.c (ISO_8859_1_map, Adobe_Symbol_map): Remove all
+ characters > 0x80.
+ * parse.c (ParseInput): Ignore `m' command.
+ (ParseDrawFunction): Don't move for unknown drawing functions.
+ Don't move for `f' drawing function.
+
+2002-03-25 Werner LEMBERG <wl@gnu.org>
+
+ * DviChar.c (ISO_8859_1_map): Use `t+-', `tmu', and `tdi' symbols
+ instead of `+-', `mu', and `di', respectively.
+
+2002-02-23 Werner LEMBERG <wl@gnu.org>
+
+ * DviChar.c (ISO_8859_1_map): Add `mc' symbol.
+
+2001-09-22 Werner LEMBERG <wl@gnu.org>
+
+ * Imakefile.in: Redefine `ProgramTargetHelper' as
+ `ProgramTargetHelperNoMan' and add a call to `InstallManPageLong'
+ to make the `install.man' target work if the build directory isn't
+ $srcdir.
+
+Version 1.17.2 released
+=======================
+
+Version 1.17.1 released
+=======================
+
2001-04-21 Albert Chin-A-Young <china@thewrittenword.com>
* Imakefile.in: Add support for recent HP architectures.
+Version 1.17 released
+=====================
+
2001-01-04 Rob Daasch <daasch@ece.pdx.edu>
* parse.c (ParseInput): Added 'F' to command switch to swallow
diff --git a/contrib/groff/src/xditview/DviChar.c b/contrib/groff/src/xditview/DviChar.c
index 2aaba45..608fb9e 100644
--- a/contrib/groff/src/xditview/DviChar.c
+++ b/contrib/groff/src/xditview/DviChar.c
@@ -132,526 +132,524 @@ static DviCharNameMap ISO8859_1_map = {
"iso8859-1",
0,
{
-{ 0, /* 0 */},
-{ 0, /* 1 */},
-{ 0, /* 2 */},
-{ 0, /* 3 */},
-{ 0, /* 4 */},
-{ 0, /* 5 */},
-{ 0, /* 6 */},
-{ 0, /* 7 */},
-{ 0, /* 8 */},
-{ 0, /* 9 */},
-{ 0, /* 10 */},
-{ 0, /* 11 */},
-{ 0, /* 12 */},
-{ 0, /* 13 */},
-{ 0, /* 14 */},
-{ 0, /* 15 */},
-{ 0, /* 16 */},
-{ 0, /* 17 */},
-{ 0, /* 18 */},
-{ 0, /* 19 */},
-{ 0, /* 20 */},
-{ 0, /* 21 */},
-{ 0, /* 22 */},
-{ 0, /* 23 */},
-{ 0, /* 24 */},
-{ 0, /* 25 */},
-{ 0, /* 26 */},
-{ 0, /* 27 */},
-{ 0, /* 28 */},
-{ 0, /* 29 */},
-{ 0, /* 30 */},
-{ 0, /* 31 */},
-{ 0, /* 32 */},
-{ "!", /* 33 */},
-{ "\"","dq", /* 34 */},
-{ "#","sh", /* 35 */},
-{ "$","Do", /* 36 */},
-{ "%", /* 37 */},
-{ "&", /* 38 */},
-{ "'","cq", /* 39 */},
-{ "(", /* 40 */},
-{ ")", /* 41 */},
-{ "*", /* 42 */},
-{ "+", /* 43 */},
-{ ",", /* 44 */},
-{ "\\-", /* 45 */},
-{ ".", /* 46 */},
-{ "/","sl", /* 47 */},
-{ "0", /* 48 */},
-{ "1", /* 49 */},
-{ "2", /* 50 */},
-{ "3", /* 51 */},
-{ "4", /* 52 */},
-{ "5", /* 53 */},
-{ "6", /* 54 */},
-{ "7", /* 55 */},
-{ "8", /* 56 */},
-{ "9", /* 57 */},
-{ ":", /* 58 */},
-{ ";", /* 59 */},
-{ "<", /* 60 */},
-{ "=","eq", /* 61 */},
-{ ">", /* 62 */},
-{ "?", /* 63 */},
-{ "@","at", /* 64 */},
-{ "A", /* 65 */},
-{ "B", /* 66 */},
-{ "C", /* 67 */},
-{ "D", /* 68 */},
-{ "E", /* 69 */},
-{ "F", /* 70 */},
-{ "G", /* 71 */},
-{ "H", /* 72 */},
-{ "I", /* 73 */},
-{ "J", /* 74 */},
-{ "K", /* 75 */},
-{ "L", /* 76 */},
-{ "M", /* 77 */},
-{ "N", /* 78 */},
-{ "O", /* 79 */},
-{ "P", /* 80 */},
-{ "Q", /* 81 */},
-{ "R", /* 82 */},
-{ "S", /* 83 */},
-{ "T", /* 84 */},
-{ "U", /* 85 */},
-{ "V", /* 86 */},
-{ "W", /* 87 */},
-{ "X", /* 88 */},
-{ "Y", /* 89 */},
-{ "Z", /* 90 */},
-{ "[","lB", /* 91 */},
-{ "\\","rs", /* 92 */},
-{ "]","rB", /* 93 */},
-{ "^","a^","ha" /* 94 */},
-{ "_", /* 95 */},
-{ "`","oq", /* 96 */},
-{ "a", /* 97 */},
-{ "b", /* 98 */},
-{ "c", /* 99 */},
-{ "d", /* 100 */},
-{ "e", /* 101 */},
-{ "f", /* 102 */},
-{ "g", /* 103 */},
-{ "h", /* 104 */},
-{ "i", /* 105 */},
-{ "j", /* 106 */},
-{ "k", /* 107 */},
-{ "l", /* 108 */},
-{ "m", /* 109 */},
-{ "n", /* 110 */},
-{ "o", /* 111 */},
-{ "p", /* 112 */},
-{ "q", /* 113 */},
-{ "r", /* 114 */},
-{ "s", /* 115 */},
-{ "t", /* 116 */},
-{ "u", /* 117 */},
-{ "v", /* 118 */},
-{ "w", /* 119 */},
-{ "x", /* 120 */},
-{ "y", /* 121 */},
-{ "z", /* 122 */},
-{ "{","lC", /* 123 */},
-{ "|","or","ba" /* 124 */},
-{ "}","rC", /* 125 */},
-{ "~","a~","ap","ti" /* 126 */},
-{ 0, /* 127 */},
-{ 0, /* 128 */},
-{ 0, /* 129 */},
-{ 0, /* 130 */},
-{ 0, /* 131 */},
-{ 0, /* 132 */},
-{ 0, /* 133 */},
-{ 0, /* 134 */},
-{ 0, /* 135 */},
-{ 0, /* 136 */},
-{ 0, /* 137 */},
-{ 0, /* 138 */},
-{ 0, /* 139 */},
-{ 0, /* 140 */},
-{ 0, /* 141 */},
-{ 0, /* 142 */},
-{ 0, /* 143 */},
-{ 0, /* 144 */},
-{ 0, /* 145 */},
-{ 0, /* 146 */},
-{ 0, /* 147 */},
-{ 0, /* 148 */},
-{ 0, /* 149 */},
-{ 0, /* 150 */},
-{ 0, /* 151 */},
-{ 0, /* 152 */},
-{ 0, /* 153 */},
-{ 0, /* 154 */},
-{ 0, /* 155 */},
-{ 0, /* 156 */},
-{ 0, /* 157 */},
-{ 0, /* 158 */},
-{ 0, /* 159 */},
-{ 0, /* 160 */},
-{ "r!", "\241", /* 161 */},
-{ "ct", "\242", /* 162 */},
-{ "Po", "\243", /* 163 */},
-{ "Cs", "\244", /* 164 */},
-{ "Ye", "\245", /* 165 */},
-{ "bb", "\246", /* 166 */},
-{ "sc", "\247", /* 167 */},
-{ "ad", "\250", /* 168 */},
-{ "co", "\251", /* 169 */},
-{ "Of", "\252", /* 170 */},
-{ "Fo", "\253", /* 171 */},
-{ "no", "\254", /* 172 */},
-{ "-", "hy", "\255" /* 173 */},
-{ "rg", "\256", /* 174 */},
-{ "a-", "\257", /* 175 */},
-{ "de", "\260", /* 176 */},
-{ "+-", "\261", /* 177 */},
-{ "S2", "\262", /* 178 */},
-{ "S3", "\263", /* 179 */},
-{ "aa", "\264", /* 180 */},
-/* Omit *m here; we want *m to match the other greek letters in the
- symbol font. */
-{ "\265", /* 181 */},
-{ "ps", "\266", /* 182 */},
-{ "pc", "\267", /* 183 */},
-{ "ac", "\270", /* 184 */},
-{ "S1", "\271", /* 185 */},
-{ "Om", "\272", /* 186 */},
-{ "Fc", "\273", /* 187 */},
-{ "14", "\274", /* 188 */},
-{ "12", "\275", /* 189 */},
-{ "34", "\276", /* 190 */},
-{ "r?", "\277", /* 191 */},
-{ "`A", "\300", /* 192 */},
-{ "'A", "\301", /* 193 */},
-{ "^A", "\302", /* 194 */},
-{ "~A", "\303", /* 195 */},
-{ ":A", "\304", /* 196 */},
-{ "oA", "\305", /* 197 */},
-{ "AE", "\306", /* 198 */},
-{ ",C", "\307", /* 199 */},
-{ "`E", "\310", /* 200 */},
-{ "'E", "\311", /* 201 */},
-{ "^E", "\312", /* 202 */},
-{ ":E", "\313", /* 203 */},
-{ "`I", "\314", /* 204 */},
-{ "'I", "\315", /* 205 */},
-{ "^I", "\316", /* 206 */},
-{ ":I", "\317", /* 207 */},
-{ "-D", "\320", /* 208 */},
-{ "~N", "\321", /* 209 */},
-{ "`O", "\322", /* 210 */},
-{ "'O", "\323", /* 211 */},
-{ "^O", "\324", /* 212 */},
-{ "~O", "\325", /* 213 */},
-{ ":O", "\326", /* 214 */},
-{ "mu", "\327", /* 215 */},
-{ "/O", "\330", /* 216 */},
-{ "`U", "\331", /* 217 */},
-{ "'U", "\332", /* 218 */},
-{ "^U", "\333", /* 219 */},
-{ ":U", "\334", /* 220 */},
-{ "'Y", "\335", /* 221 */},
-{ "TP", "\336", /* 222 */},
-{ "ss", "\337", /* 223 */},
-{ "`a", "\340", /* 224 */},
-{ "'a", "\341", /* 225 */},
-{ "^a", "\342", /* 226 */},
-{ "~a", "\343", /* 227 */},
-{ ":a", "\344", /* 228 */},
-{ "oa", "\345", /* 229 */},
-{ "ae", "\346", /* 230 */},
-{ ",c", "\347", /* 231 */},
-{ "`e", "\350", /* 232 */},
-{ "'e", "\351", /* 233 */},
-{ "^e", "\352", /* 234 */},
-{ ":e", "\353", /* 235 */},
-{ "`i", "\354", /* 236 */},
-{ "'i", "\355", /* 237 */},
-{ "^i", "\356", /* 238 */},
-{ ":i", "\357", /* 239 */},
-{ "Sd", "\360", /* 240 */},
-{ "~n", "\361", /* 241 */},
-{ "`o", "\362", /* 242 */},
-{ "'o", "\363", /* 243 */},
-{ "^o", "\364", /* 244 */},
-{ "~o", "\365", /* 245 */},
-{ ":o", "\366", /* 246 */},
-{ "di", "\367", /* 247 */},
-{ "/o", "\370", /* 248 */},
-{ "`u", "\371", /* 249 */},
-{ "'u", "\372", /* 250 */},
-{ "^u", "\373", /* 251 */},
-{ ":u", "\374", /* 252 */},
-{ "'y", "\375", /* 253 */},
-{ "Tp", "\376", /* 254 */},
-{ ":y", "\377", /* 255 */},
+{ 0, /* 0 */},
+{ 0, /* 1 */},
+{ 0, /* 2 */},
+{ 0, /* 3 */},
+{ 0, /* 4 */},
+{ 0, /* 5 */},
+{ 0, /* 6 */},
+{ 0, /* 7 */},
+{ 0, /* 8 */},
+{ 0, /* 9 */},
+{ 0, /* 10 */},
+{ 0, /* 11 */},
+{ 0, /* 12 */},
+{ 0, /* 13 */},
+{ 0, /* 14 */},
+{ 0, /* 15 */},
+{ 0, /* 16 */},
+{ 0, /* 17 */},
+{ 0, /* 18 */},
+{ 0, /* 19 */},
+{ 0, /* 20 */},
+{ 0, /* 21 */},
+{ 0, /* 22 */},
+{ 0, /* 23 */},
+{ 0, /* 24 */},
+{ 0, /* 25 */},
+{ 0, /* 26 */},
+{ 0, /* 27 */},
+{ 0, /* 28 */},
+{ 0, /* 29 */},
+{ 0, /* 30 */},
+{ 0, /* 31 */},
+{ 0, /* 32 */},
+{ "!", /* 33 */},
+{ "\"", "dq", /* 34 */},
+{ "#", "sh", /* 35 */},
+{ "$", "Do", /* 36 */},
+{ "%", /* 37 */},
+{ "&", /* 38 */},
+{ "'", "cq", /* 39 */},
+{ "(", /* 40 */},
+{ ")", /* 41 */},
+{ "*", /* 42 */},
+{ "+", /* 43 */},
+{ ",", /* 44 */},
+{ "\\-", /* 45 */},
+{ ".", /* 46 */},
+{ "/", "sl", /* 47 */},
+{ "0", /* 48 */},
+{ "1", /* 49 */},
+{ "2", /* 50 */},
+{ "3", /* 51 */},
+{ "4", /* 52 */},
+{ "5", /* 53 */},
+{ "6", /* 54 */},
+{ "7", /* 55 */},
+{ "8", /* 56 */},
+{ "9", /* 57 */},
+{ ":", /* 58 */},
+{ ";", /* 59 */},
+{ "<", /* 60 */},
+{ "=", "eq", /* 61 */},
+{ ">", /* 62 */},
+{ "?", /* 63 */},
+{ "@", "at", /* 64 */},
+{ "A", /* 65 */},
+{ "B", /* 66 */},
+{ "C", /* 67 */},
+{ "D", /* 68 */},
+{ "E", /* 69 */},
+{ "F", /* 70 */},
+{ "G", /* 71 */},
+{ "H", /* 72 */},
+{ "I", /* 73 */},
+{ "J", /* 74 */},
+{ "K", /* 75 */},
+{ "L", /* 76 */},
+{ "M", /* 77 */},
+{ "N", /* 78 */},
+{ "O", /* 79 */},
+{ "P", /* 80 */},
+{ "Q", /* 81 */},
+{ "R", /* 82 */},
+{ "S", /* 83 */},
+{ "T", /* 84 */},
+{ "U", /* 85 */},
+{ "V", /* 86 */},
+{ "W", /* 87 */},
+{ "X", /* 88 */},
+{ "Y", /* 89 */},
+{ "Z", /* 90 */},
+{ "[", "lB", /* 91 */},
+{ "\\", "rs", /* 92 */},
+{ "]", "rB", /* 93 */},
+{ "^", "a^", "ha" /* 94 */},
+{ "_", /* 95 */},
+{ "`", "oq", /* 96 */},
+{ "a", /* 97 */},
+{ "b", /* 98 */},
+{ "c", /* 99 */},
+{ "d", /* 100 */},
+{ "e", /* 101 */},
+{ "f", /* 102 */},
+{ "g", /* 103 */},
+{ "h", /* 104 */},
+{ "i", /* 105 */},
+{ "j", /* 106 */},
+{ "k", /* 107 */},
+{ "l", /* 108 */},
+{ "m", /* 109 */},
+{ "n", /* 110 */},
+{ "o", /* 111 */},
+{ "p", /* 112 */},
+{ "q", /* 113 */},
+{ "r", /* 114 */},
+{ "s", /* 115 */},
+{ "t", /* 116 */},
+{ "u", /* 117 */},
+{ "v", /* 118 */},
+{ "w", /* 119 */},
+{ "x", /* 120 */},
+{ "y", /* 121 */},
+{ "z", /* 122 */},
+{ "{", "lC", /* 123 */},
+{ "|", "or", "ba" /* 124 */},
+{ "}", "rC", /* 125 */},
+{ "~", "a~", "ap", "ti" /* 126 */},
+{ 0, /* 127 */},
+{ 0, /* 128 */},
+{ 0, /* 129 */},
+{ 0, /* 130 */},
+{ 0, /* 131 */},
+{ 0, /* 132 */},
+{ 0, /* 133 */},
+{ 0, /* 134 */},
+{ 0, /* 135 */},
+{ 0, /* 136 */},
+{ 0, /* 137 */},
+{ 0, /* 138 */},
+{ 0, /* 139 */},
+{ 0, /* 140 */},
+{ 0, /* 141 */},
+{ 0, /* 142 */},
+{ 0, /* 143 */},
+{ 0, /* 144 */},
+{ 0, /* 145 */},
+{ 0, /* 146 */},
+{ 0, /* 147 */},
+{ 0, /* 148 */},
+{ 0, /* 149 */},
+{ 0, /* 150 */},
+{ 0, /* 151 */},
+{ 0, /* 152 */},
+{ 0, /* 153 */},
+{ 0, /* 154 */},
+{ 0, /* 155 */},
+{ 0, /* 156 */},
+{ 0, /* 157 */},
+{ 0, /* 158 */},
+{ 0, /* 159 */},
+{ 0, /* 160 */},
+{ "r!", /* 161 */},
+{ "ct", /* 162 */},
+{ "Po", /* 163 */},
+{ "Cs", /* 164 */},
+{ "Ye", /* 165 */},
+{ "bb", /* 166 */},
+{ "sc", /* 167 */},
+{ "ad", /* 168 */},
+{ "co", /* 169 */},
+{ "Of", /* 170 */},
+{ "Fo", /* 171 */},
+{ "no", /* 172 */},
+{ "-", "hy", /* 173 */},
+{ "rg", /* 174 */},
+{ "a-", /* 175 */},
+{ "de", /* 176 */},
+{ "t+-", /* 177 */},
+{ "S2", /* 178 */},
+{ "S3", /* 179 */},
+{ "aa", /* 180 */},
+{ "mc", /* 181 */},
+{ "ps", /* 182 */},
+{ "pc", /* 183 */},
+{ "ac", /* 184 */},
+{ "S1", /* 185 */},
+{ "Om", /* 186 */},
+{ "Fc", /* 187 */},
+{ "14", /* 188 */},
+{ "12", /* 189 */},
+{ "34", /* 190 */},
+{ "r?", /* 191 */},
+{ "`A", /* 192 */},
+{ "'A", /* 193 */},
+{ "^A", /* 194 */},
+{ "~A", /* 195 */},
+{ ":A", /* 196 */},
+{ "oA", /* 197 */},
+{ "AE", /* 198 */},
+{ ",C", /* 199 */},
+{ "`E", /* 200 */},
+{ "'E", /* 201 */},
+{ "^E", /* 202 */},
+{ ":E", /* 203 */},
+{ "`I", /* 204 */},
+{ "'I", /* 205 */},
+{ "^I", /* 206 */},
+{ ":I", /* 207 */},
+{ "-D", /* 208 */},
+{ "~N", /* 209 */},
+{ "`O", /* 210 */},
+{ "'O", /* 211 */},
+{ "^O", /* 212 */},
+{ "~O", /* 213 */},
+{ ":O", /* 214 */},
+{ "tmu", /* 215 */},
+{ "/O", /* 216 */},
+{ "`U", /* 217 */},
+{ "'U", /* 218 */},
+{ "^U", /* 219 */},
+{ ":U", /* 220 */},
+{ "'Y", /* 221 */},
+{ "TP", /* 222 */},
+{ "ss", /* 223 */},
+{ "`a", /* 224 */},
+{ "'a", /* 225 */},
+{ "^a", /* 226 */},
+{ "~a", /* 227 */},
+{ ":a", /* 228 */},
+{ "oa", /* 229 */},
+{ "ae", /* 230 */},
+{ ",c", /* 231 */},
+{ "`e", /* 232 */},
+{ "'e", /* 233 */},
+{ "^e", /* 234 */},
+{ ":e", /* 235 */},
+{ "`i", /* 236 */},
+{ "'i", /* 237 */},
+{ "^i", /* 238 */},
+{ ":i", /* 239 */},
+{ "Sd", /* 240 */},
+{ "~n", /* 241 */},
+{ "`o", /* 242 */},
+{ "'o", /* 243 */},
+{ "^o", /* 244 */},
+{ "~o", /* 245 */},
+{ ":o", /* 246 */},
+{ "tdi", /* 247 */},
+{ "/o", /* 248 */},
+{ "`u", /* 249 */},
+{ "'u", /* 250 */},
+{ "^u", /* 251 */},
+{ ":u", /* 252 */},
+{ "'y", /* 253 */},
+{ "Tp", /* 254 */},
+{ ":y", /* 255 */},
}};
static DviCharNameMap Adobe_Symbol_map = {
"adobe-fontspecific",
1,
{
-{ 0, /* 0 */},
-{ 0, /* 1 */},
-{ 0, /* 2 */},
-{ 0, /* 3 */},
-{ 0, /* 4 */},
-{ 0, /* 5 */},
-{ 0, /* 6 */},
-{ 0, /* 7 */},
-{ 0, /* 8 */},
-{ 0, /* 9 */},
-{ 0, /* 10 */},
-{ 0, /* 11 */},
-{ 0, /* 12 */},
-{ 0, /* 13 */},
-{ 0, /* 14 */},
-{ 0, /* 15 */},
-{ 0, /* 16 */},
-{ 0, /* 17 */},
-{ 0, /* 18 */},
-{ 0, /* 19 */},
-{ 0, /* 20 */},
-{ 0, /* 21 */},
-{ 0, /* 22 */},
-{ 0, /* 23 */},
-{ 0, /* 24 */},
-{ 0, /* 25 */},
-{ 0, /* 26 */},
-{ 0, /* 27 */},
-{ 0, /* 28 */},
-{ 0, /* 29 */},
-{ 0, /* 30 */},
-{ 0, /* 31 */},
-{ 0, /* 32 */},
-{ "!", /* 33 */},
-{ "fa", /* 34 */},
-{ "#", "sh", /* 35 */},
-{ "te", /* 36 */},
-{ "%", /* 37 */},
-{ "&", /* 38 */},
-{ "st", /* 39 */},
-{ "(", /* 40 */},
-{ ")", /* 41 */},
-{ "**", /* 42 */},
-{ "+", "pl", /* 43 */},
-{ ",", /* 44 */},
-{ "\\-", "mi", /* 45 */},
-{ ".", /* 46 */},
-{ "/", "sl", /* 47 */},
-{ "0", /* 48 */},
-{ "1", /* 49 */},
-{ "2", /* 50 */},
-{ "3", /* 51 */},
-{ "4", /* 52 */},
-{ "5", /* 53 */},
-{ "6", /* 54 */},
-{ "7", /* 55 */},
-{ "8", /* 56 */},
-{ "9", /* 57 */},
-{ ":", /* 58 */},
-{ ";", /* 59 */},
-{ "<", /* 60 */},
-{ "=", "eq", /* 61 */},
-{ ">", /* 62 */},
-{ "?", /* 63 */},
-{ "=~", /* 64 */},
-{ "*A", /* 65 */},
-{ "*B", /* 66 */},
-{ "*X", /* 67 */},
-{ "*D", /* 68 */},
-{ "*E", /* 69 */},
-{ "*F", /* 70 */},
-{ "*G", /* 71 */},
-{ "*Y", /* 72 */},
-{ "*I", /* 73 */},
-{ "+h", /* 74 */},
-{ "*K", /* 75 */},
-{ "*L", /* 76 */},
-{ "*M", /* 77 */},
-{ "*N", /* 78 */},
-{ "*O", /* 79 */},
-{ "*P", /* 80 */},
-{ "*H", /* 81 */},
-{ "*R", /* 82 */},
-{ "*S", /* 83 */},
-{ "*T", /* 84 */},
-{ 0, /* 85 */},
-{ "ts", /* 86 */},
-{ "*W", /* 87 */},
-{ "*C", /* 88 */},
-{ "*Q", /* 89 */},
-{ "*Z", /* 90 */},
-{ "[", "lB", /* 91 */},
-{ "tf", "3d", /* 92 */},
-{ "]", "rB", /* 93 */},
-{ "pp", /* 94 */},
-{ "_", /* 95 */},
-{ "radicalex", /* 96 */},
-{ "*a", /* 97 */},
-{ "*b", /* 98 */},
-{ "*x", /* 99 */},
-{ "*d", /* 100 */},
-{ "*e", /* 101 */},
-{ "*f", /* 102 */},
-{ "*g", /* 103 */},
-{ "*y", /* 104 */},
-{ "*i", /* 105 */},
-{ "+f", /* 106 */},
-{ "*k", /* 107 */},
-{ "*l", /* 108 */},
-{ "*m", "\265", /* 109 */},
-{ "*n", /* 110 */},
-{ "*o", /* 111 */},
-{ "*p", /* 112 */},
-{ "*h", /* 113 */},
-{ "*r", /* 114 */},
-{ "*s", /* 115 */},
-{ "*t", /* 116 */},
-{ "*u", /* 117 */},
-{ "+p", /* 118 */},
-{ "*w", /* 119 */},
-{ "*c", /* 120 */},
-{ "*q", /* 121 */},
-{ "*z", /* 122 */},
-{ "lC", "{", /* 123 */},
-{ "ba", "or", "|", /* 124 */},
-{ "rC", "}", /* 125 */},
-{ "ap", /* 126 */},
-{ 0, /* 127 */},
-{ 0, /* 128 */},
-{ 0, /* 129 */},
-{ 0, /* 130 */},
-{ 0, /* 131 */},
-{ 0, /* 132 */},
-{ 0, /* 133 */},
-{ 0, /* 134 */},
-{ 0, /* 135 */},
-{ 0, /* 136 */},
-{ 0, /* 137 */},
-{ 0, /* 138 */},
-{ 0, /* 139 */},
-{ 0, /* 140 */},
-{ 0, /* 141 */},
-{ 0, /* 142 */},
-{ 0, /* 143 */},
-{ 0, /* 144 */},
-{ 0, /* 145 */},
-{ 0, /* 146 */},
-{ 0, /* 147 */},
-{ 0, /* 148 */},
-{ 0, /* 149 */},
-{ 0, /* 150 */},
-{ 0, /* 151 */},
-{ 0, /* 152 */},
-{ 0, /* 153 */},
-{ 0, /* 154 */},
-{ 0, /* 155 */},
-{ 0, /* 156 */},
-{ 0, /* 157 */},
-{ 0, /* 158 */},
-{ 0, /* 159 */},
-{ 0, /* 160 */},
-{ "*U", /* 161 */},
-{ "fm", /* 162 */},
-{ "<=", /* 163 */},
-{ "f/", /* 164 */},
-{ "if", /* 165 */},
-{ "Fn", /* 166 */},
-{ "CL", /* 167 */},
-{ "DI", /* 168 */},
-{ "HE", /* 169 */},
-{ "SP", /* 170 */},
-{ "<>", /* 171 */},
-{ "<-", /* 172 */},
-{ "ua", "arrowverttp" /* 173 */},
-{ "->", /* 174 */},
-{ "da", "arrowvertbt" /* 175 */},
-{ "de", "\260", /* 176 */},
-{ "+-", "\261", /* 177 */},
-{ "sd", /* 178 */},
-{ ">=", /* 179 */},
-{ "mu", "\327", /* 180 */},
-{ "pt", /* 181 */},
-{ "pd", /* 182 */},
-{ "bu", /* 183 */},
-{ "di", "\367", /* 184 */},
-{ "!=", /* 185 */},
-{ "==", /* 186 */},
-{ "~=", "~~", /* 187 */},
-{ 0, /* 188 */},
-{ "arrowvertex", /* 189 */},
-{ "an", /* 190 */},
-{ "CR", /* 191 */},
-{ "Ah", /* 192 */},
-{ "Im", /* 193 */},
-{ "Re", /* 194 */},
-{ "wp", /* 195 */},
-{ "c*", /* 196 */},
-{ "c+", /* 197 */},
-{ "es", /* 198 */},
-{ "ca", /* 199 */},
-{ "cu", /* 200 */},
-{ "sp", /* 201 */},
-{ "ip", /* 202 */},
-{ "nb", /* 203 */},
-{ "sb", /* 204 */},
-{ "ib", /* 205 */},
-{ "mo", /* 206 */},
-{ "nm", /* 207 */},
-{ "/_", /* 208 */},
-{ "gr", /* 209 */},
-{ "rg", /* 210 */},
-{ "co", /* 211 */},
-{ "tm", /* 212 */},
-{ 0, /* 213 */},
-{ "sr", /* 214 */},
-{ "md", /* 215 */},
-{ "no", "\254", /* 216 */},
-{ "AN", /* 217 */},
-{ "OR", /* 218 */},
-{ "hA", /* 219 */},
-{ "lA", /* 220 */},
-{ "uA", /* 221 */},
-{ "rA", /* 222 */},
-{ "dA", /* 223 */},
-{ "lz", /* 224 */},
-{ "la", /* 225 */},
-{ 0, /* 226 */},
-{ 0, /* 227 */},
-{ 0, /* 228 */},
-{ 0, /* 229 */},
-{ "parenlefttp", /* 230 */},
-{ "parenleftex", /* 231 */},
-{ "parenleftbt", /* 232 */},
-{ "bracketlefttp", "lc", /* 233 */},
-{ "bracketleftex", /* 234 */},
-{ "bracketleftbt", "lf", /* 235 */},
-{ "bracelefttp", "lt", /* 236 */},
-{ "braceleftmid", "lk", /* 237 */},
-{ "braceleftbt", "lb", /* 238 */},
+{ 0, /* 0 */},
+{ 0, /* 1 */},
+{ 0, /* 2 */},
+{ 0, /* 3 */},
+{ 0, /* 4 */},
+{ 0, /* 5 */},
+{ 0, /* 6 */},
+{ 0, /* 7 */},
+{ 0, /* 8 */},
+{ 0, /* 9 */},
+{ 0, /* 10 */},
+{ 0, /* 11 */},
+{ 0, /* 12 */},
+{ 0, /* 13 */},
+{ 0, /* 14 */},
+{ 0, /* 15 */},
+{ 0, /* 16 */},
+{ 0, /* 17 */},
+{ 0, /* 18 */},
+{ 0, /* 19 */},
+{ 0, /* 20 */},
+{ 0, /* 21 */},
+{ 0, /* 22 */},
+{ 0, /* 23 */},
+{ 0, /* 24 */},
+{ 0, /* 25 */},
+{ 0, /* 26 */},
+{ 0, /* 27 */},
+{ 0, /* 28 */},
+{ 0, /* 29 */},
+{ 0, /* 30 */},
+{ 0, /* 31 */},
+{ 0, /* 32 */},
+{ "!", /* 33 */},
+{ "fa", /* 34 */},
+{ "#", "sh", /* 35 */},
+{ "te", /* 36 */},
+{ "%", /* 37 */},
+{ "&", /* 38 */},
+{ "st", /* 39 */},
+{ "(", /* 40 */},
+{ ")", /* 41 */},
+{ "**", /* 42 */},
+{ "+", "pl", /* 43 */},
+{ ",", /* 44 */},
+{ "\\-", "mi", /* 45 */},
+{ ".", /* 46 */},
+{ "/", "sl", /* 47 */},
+{ "0", /* 48 */},
+{ "1", /* 49 */},
+{ "2", /* 50 */},
+{ "3", /* 51 */},
+{ "4", /* 52 */},
+{ "5", /* 53 */},
+{ "6", /* 54 */},
+{ "7", /* 55 */},
+{ "8", /* 56 */},
+{ "9", /* 57 */},
+{ ":", /* 58 */},
+{ ";", /* 59 */},
+{ "<", /* 60 */},
+{ "=", "eq", /* 61 */},
+{ ">", /* 62 */},
+{ "?", /* 63 */},
+{ "=~", /* 64 */},
+{ "*A", /* 65 */},
+{ "*B", /* 66 */},
+{ "*X", /* 67 */},
+{ "*D", /* 68 */},
+{ "*E", /* 69 */},
+{ "*F", /* 70 */},
+{ "*G", /* 71 */},
+{ "*Y", /* 72 */},
+{ "*I", /* 73 */},
+{ "+h", /* 74 */},
+{ "*K", /* 75 */},
+{ "*L", /* 76 */},
+{ "*M", /* 77 */},
+{ "*N", /* 78 */},
+{ "*O", /* 79 */},
+{ "*P", /* 80 */},
+{ "*H", /* 81 */},
+{ "*R", /* 82 */},
+{ "*S", /* 83 */},
+{ "*T", /* 84 */},
+{ 0, /* 85 */},
+{ "ts", /* 86 */},
+{ "*W", /* 87 */},
+{ "*C", /* 88 */},
+{ "*Q", /* 89 */},
+{ "*Z", /* 90 */},
+{ "[", "lB", /* 91 */},
+{ "tf", "3d", /* 92 */},
+{ "]", "rB", /* 93 */},
+{ "pp", /* 94 */},
+{ "_", /* 95 */},
+{ "radicalex", /* 96 */},
+{ "*a", /* 97 */},
+{ "*b", /* 98 */},
+{ "*x", /* 99 */},
+{ "*d", /* 100 */},
+{ "*e", /* 101 */},
+{ "*f", /* 102 */},
+{ "*g", /* 103 */},
+{ "*y", /* 104 */},
+{ "*i", /* 105 */},
+{ "+f", /* 106 */},
+{ "*k", /* 107 */},
+{ "*l", /* 108 */},
+{ "*m", /* 109 */},
+{ "*n", /* 110 */},
+{ "*o", /* 111 */},
+{ "*p", /* 112 */},
+{ "*h", /* 113 */},
+{ "*r", /* 114 */},
+{ "*s", /* 115 */},
+{ "*t", /* 116 */},
+{ "*u", /* 117 */},
+{ "+p", /* 118 */},
+{ "*w", /* 119 */},
+{ "*c", /* 120 */},
+{ "*q", /* 121 */},
+{ "*z", /* 122 */},
+{ "lC", "{", /* 123 */},
+{ "ba", "or", "|", /* 124 */},
+{ "rC", "}", /* 125 */},
+{ "ap", /* 126 */},
+{ 0, /* 127 */},
+{ 0, /* 128 */},
+{ 0, /* 129 */},
+{ 0, /* 130 */},
+{ 0, /* 131 */},
+{ 0, /* 132 */},
+{ 0, /* 133 */},
+{ 0, /* 134 */},
+{ 0, /* 135 */},
+{ 0, /* 136 */},
+{ 0, /* 137 */},
+{ 0, /* 138 */},
+{ 0, /* 139 */},
+{ 0, /* 140 */},
+{ 0, /* 141 */},
+{ 0, /* 142 */},
+{ 0, /* 143 */},
+{ 0, /* 144 */},
+{ 0, /* 145 */},
+{ 0, /* 146 */},
+{ 0, /* 147 */},
+{ 0, /* 148 */},
+{ 0, /* 149 */},
+{ 0, /* 150 */},
+{ 0, /* 151 */},
+{ 0, /* 152 */},
+{ 0, /* 153 */},
+{ 0, /* 154 */},
+{ 0, /* 155 */},
+{ 0, /* 156 */},
+{ 0, /* 157 */},
+{ 0, /* 158 */},
+{ 0, /* 159 */},
+{ 0, /* 160 */},
+{ "*U", /* 161 */},
+{ "fm", /* 162 */},
+{ "<=", /* 163 */},
+{ "f/", /* 164 */},
+{ "if", /* 165 */},
+{ "Fn", /* 166 */},
+{ "CL", /* 167 */},
+{ "DI", /* 168 */},
+{ "HE", /* 169 */},
+{ "SP", /* 170 */},
+{ "<>", /* 171 */},
+{ "<-", /* 172 */},
+{ "ua", "arrowverttp", /* 173 */},
+{ "->", /* 174 */},
+{ "da", "arrowvertbt", /* 175 */},
+{ "de", /* 176 */},
+{ "+-", /* 177 */},
+{ "sd", /* 178 */},
+{ ">=", /* 179 */},
+{ "mu", /* 180 */},
+{ "pt", /* 181 */},
+{ "pd", /* 182 */},
+{ "bu", /* 183 */},
+{ "di", /* 184 */},
+{ "!=", /* 185 */},
+{ "==", /* 186 */},
+{ "~=", "~~", /* 187 */},
+{ 0, /* 188 */},
+{ "arrowvertex", /* 189 */},
+{ "an", /* 190 */},
+{ "CR", /* 191 */},
+{ "Ah", /* 192 */},
+{ "Im", /* 193 */},
+{ "Re", /* 194 */},
+{ "wp", /* 195 */},
+{ "c*", /* 196 */},
+{ "c+", /* 197 */},
+{ "es", /* 198 */},
+{ "ca", /* 199 */},
+{ "cu", /* 200 */},
+{ "sp", /* 201 */},
+{ "ip", /* 202 */},
+{ "nb", /* 203 */},
+{ "sb", /* 204 */},
+{ "ib", /* 205 */},
+{ "mo", /* 206 */},
+{ "nm", /* 207 */},
+{ "/_", /* 208 */},
+{ "gr", /* 209 */},
+{ "rg", /* 210 */},
+{ "co", /* 211 */},
+{ "tm", /* 212 */},
+{ 0, /* 213 */},
+{ "sr", /* 214 */},
+{ "md", /* 215 */},
+{ "no", /* 216 */},
+{ "AN", /* 217 */},
+{ "OR", /* 218 */},
+{ "hA", /* 219 */},
+{ "lA", /* 220 */},
+{ "uA", /* 221 */},
+{ "rA", /* 222 */},
+{ "dA", /* 223 */},
+{ "lz", /* 224 */},
+{ "la", /* 225 */},
+{ 0, /* 226 */},
+{ 0, /* 227 */},
+{ 0, /* 228 */},
+{ 0, /* 229 */},
+{ "parenlefttp", /* 230 */},
+{ "parenleftex", /* 231 */},
+{ "parenleftbt", /* 232 */},
+{ "bracketlefttp", "lc", /* 233 */},
+{ "bracketleftex", /* 234 */},
+{ "bracketleftbt", "lf", /* 235 */},
+{ "bracelefttp", "lt", /* 236 */},
+{ "braceleftmid", "lk", /* 237 */},
+{ "braceleftbt", "lb", /* 238 */},
{ "bracerightex", "braceleftex", "bv", /* 239 */},
-{ 0, /* 240 */},
-{ "ra", /* 241 */},
-{ "is", /* 242 */},
-{ 0, /* 243 */},
-{ 0, /* 244 */},
-{ 0, /* 245 */},
-{ "parenrighttp", /* 246 */},
-{ "parenrightex", /* 247 */},
-{ "parenrightbt", /* 248 */},
-{ "bracketrighttp", "rc", /* 249 */},
-{ "bracketrightex", /* 250 */},
-{ "bracketrightbt", "rf", /* 251 */},
-{ "bracerighttp", "rt" /* 252 */},
-{ "bracerightmid", "rk" /* 253 */},
-{ "bracerightbt", "rb" /* 254 */},
-{ 0, /* 255 */},
+{ 0, /* 240 */},
+{ "ra", /* 241 */},
+{ "is", /* 242 */},
+{ 0, /* 243 */},
+{ 0, /* 244 */},
+{ 0, /* 245 */},
+{ "parenrighttp", /* 246 */},
+{ "parenrightex", /* 247 */},
+{ "parenrightbt", /* 248 */},
+{ "bracketrighttp", "rc", /* 249 */},
+{ "bracketrightex", /* 250 */},
+{ "bracketrightbt", "rf", /* 251 */},
+{ "bracerighttp", "rt", /* 252 */},
+{ "bracerightmid", "rk", /* 253 */},
+{ "bracerightbt", "rb", /* 254 */},
+{ 0, /* 255 */},
}};
diff --git a/contrib/groff/src/xditview/Imakefile.in b/contrib/groff/src/xditview/Imakefile.in
index 01fab4f..32b3505 100644
--- a/contrib/groff/src/xditview/Imakefile.in
+++ b/contrib/groff/src/xditview/Imakefile.in
@@ -1,7 +1,7 @@
srcdir=@srcdir@
top_srcdir=@top_srcdir@
VPATH=@srcdir@
-top_builddir=@top_builddir@
+top_builddir=@groff_top_builddir@
version=`cat $(top_srcdir)/VERSION`
# No additional number if revision is zero
@@ -12,7 +12,8 @@ GROFF_DATADIR = $(GROFF_PREFIX)/share
GROFF_DATAPROGRAMDIR = $(GROFF_DATADIR)/groff
GROFF_DATASUBDIR = $(GROFF_DATAPROGRAMDIR)/$(version)$(revision)
GROFF_FONTDIR = $(GROFF_DATASUBDIR)/font
-GROFF_FONTPATH = $(GROFF_FONTDIR):/usr/local/lib/font:/usr/lib/font
+GROFF_LOCALFONTDIR = $(GROFF_DATAPROGRAMDIR)/site-font
+GROFF_FONTPATH = $(GROFF_FONTDIR):$(GROFF_LOCALFONTDIR):/usr/lib/font
DPIS = 75 100
PROGRAMS = \
@@ -72,7 +73,10 @@ DEFINES = \
DEVDIR = $(top_builddir)/font
MKINSTALLDIRS = $(top_srcdir)/mkinstalldirs
+#undef ProgramTargetHelper
+#define ProgramTargetHelper ProgramTargetHelperNoMan
ComplexProgramTarget_1(gxditview,$(LOCAL_LIBRARIES),$(MATHLIB))
+InstallManPageLong($(srcdir)/gxditview,$(MANDIR),gxditview)
NormalProgramTarget(xtotroff,$(OBJS2),$(DEPXLIB),$(XLIB), /**/)
InstallAppDefaults(GXditview)
diff --git a/contrib/groff/src/xditview/parse.c b/contrib/groff/src/xditview/parse.c
index e1df8c9..d763268 100644
--- a/contrib/groff/src/xditview/parse.c
+++ b/contrib/groff/src/xditview/parse.c
@@ -141,6 +141,7 @@ ParseInput(dw)
break;
case 'F': /* input files */
case '+': /* continuation of X device control */
+ case 'm': /* color */
case '#': /* comment */
GetLine(dw, NULL, 0);
break;
@@ -205,7 +206,7 @@ DviWidget dw;
char *buf;
{
int v[DRAW_ARGS_MAX];
- int i;
+ int i, no_move = 0;
char *ptr;
v[0] = v[1] = v[2] = v[3] = 0;
@@ -257,24 +258,28 @@ char *buf;
case 'f':
if (i > 0 && v[0] >= 0 && v[0] <= DVI_FILL_MAX)
dw->dvi.fill = v[0];
+ no_move = 1;
break;
default:
#if 0
warning("unknown drawing function %s", buf);
#endif
+ no_move = 1;
break;
}
- if (buf[0] == 'e') {
- if (i > 0)
- dw->dvi.state->x += v[0];
- }
- else {
- while (--i >= 0) {
- if (i & 1)
- dw->dvi.state->y += v[i];
- else
- dw->dvi.state->x += v[i];
+ if (!no_move) {
+ if (buf[0] == 'e') {
+ if (i > 0)
+ dw->dvi.state->x += v[0];
+ }
+ else {
+ while (--i >= 0) {
+ if (i & 1)
+ dw->dvi.state->y += v[i];
+ else
+ dw->dvi.state->x += v[i];
+ }
}
}
}
diff --git a/contrib/groff/src/xditview/xditview.c b/contrib/groff/src/xditview/xditview.c
index e836cf5..75b7fd1 100644
--- a/contrib/groff/src/xditview/xditview.c
+++ b/contrib/groff/src/xditview/xditview.c
@@ -179,7 +179,9 @@ int main(argc, argv)
toplevel = XtAppInitialize(&xtcontext, "GXditview",
options, XtNumber (options),
&argc, argv, fallback_resources, NULL, 0);
- if (argc > 2)
+ if (argc > 2
+ || (argc == 2 && (!strcmp(argv[1], "-help")
+ || !strcmp(argv[1], "--help"))))
Syntax(argv[0]);
XtGetApplicationResources(toplevel, (XtPointer)&app_resources,
OpenPOWER on IntegriCloud