summaryrefslogtreecommitdiffstats
path: root/contrib/groff/src/devices
diff options
context:
space:
mode:
authorru <ru@FreeBSD.org>2005-10-20 10:45:19 +0000
committerru <ru@FreeBSD.org>2005-10-20 10:45:19 +0000
commit353ac0b339df3493d1950b6527988b77b76bd197 (patch)
tree8a188846a3f5bd2f2b8cb869cba64e3c470a2b26 /contrib/groff/src/devices
parentc40093b1f1b43dc237b9d272697cdd0842ec64ec (diff)
downloadFreeBSD-src-353ac0b339df3493d1950b6527988b77b76bd197.zip
FreeBSD-src-353ac0b339df3493d1950b6527988b77b76bd197.tar.gz
Virgin import of FSF groff v1.19.2
Diffstat (limited to 'contrib/groff/src/devices')
-rw-r--r--contrib/groff/src/devices/grodvi/dvi.cpp59
-rw-r--r--contrib/groff/src/devices/grodvi/grodvi.man8
-rw-r--r--contrib/groff/src/devices/grohtml/grohtml.man169
-rw-r--r--contrib/groff/src/devices/grohtml/html-table.cpp117
-rw-r--r--contrib/groff/src/devices/grohtml/html-table.h10
-rw-r--r--contrib/groff/src/devices/grohtml/html-text.cpp242
-rw-r--r--contrib/groff/src/devices/grohtml/html-text.h20
-rw-r--r--contrib/groff/src/devices/grohtml/html.h5
-rw-r--r--contrib/groff/src/devices/grohtml/output.cpp27
-rw-r--r--contrib/groff/src/devices/grohtml/post-html.cpp1965
-rw-r--r--contrib/groff/src/devices/grolbp/lbp.cpp40
-rw-r--r--contrib/groff/src/devices/grolbp/lbp.h309
-rw-r--r--contrib/groff/src/devices/grolj4/Makefile.sub1
-rw-r--r--contrib/groff/src/devices/grolj4/grolj4.man3
-rw-r--r--contrib/groff/src/devices/grolj4/lj4.cpp24
-rw-r--r--contrib/groff/src/devices/grolj4/lj4_font.man167
-rw-r--r--contrib/groff/src/devices/grops/grops.man72
-rw-r--r--contrib/groff/src/devices/grops/ps.cpp30
-rw-r--r--contrib/groff/src/devices/grops/ps.h6
-rw-r--r--contrib/groff/src/devices/grops/psrm.cpp8
-rw-r--r--contrib/groff/src/devices/grotty/grotty.man6
-rw-r--r--contrib/groff/src/devices/grotty/tty.cpp242
-rw-r--r--contrib/groff/src/devices/xditview/ChangeLog542
-rw-r--r--contrib/groff/src/devices/xditview/DESC.in9
-rw-r--r--contrib/groff/src/devices/xditview/Dvi.c611
-rw-r--r--contrib/groff/src/devices/xditview/Dvi.h46
-rw-r--r--contrib/groff/src/devices/xditview/DviP.h233
-rw-r--r--contrib/groff/src/devices/xditview/FontMap17
-rw-r--r--contrib/groff/src/devices/xditview/GXditview.ad57
-rw-r--r--contrib/groff/src/devices/xditview/Makefile.sub47
-rw-r--r--contrib/groff/src/devices/xditview/Menu.h46
-rw-r--r--contrib/groff/src/devices/xditview/README13
-rw-r--r--contrib/groff/src/devices/xditview/TODO17
-rw-r--r--contrib/groff/src/devices/xditview/ad2c64
-rw-r--r--contrib/groff/src/devices/xditview/device.c565
-rw-r--r--contrib/groff/src/devices/xditview/device.h21
-rw-r--r--contrib/groff/src/devices/xditview/draw.c699
-rw-r--r--contrib/groff/src/devices/xditview/font.c442
-rw-r--r--contrib/groff/src/devices/xditview/gray1.bm4
-rw-r--r--contrib/groff/src/devices/xditview/gray2.bm4
-rw-r--r--contrib/groff/src/devices/xditview/gray3.bm4
-rw-r--r--contrib/groff/src/devices/xditview/gray4.bm4
-rw-r--r--contrib/groff/src/devices/xditview/gray5.bm4
-rw-r--r--contrib/groff/src/devices/xditview/gray6.bm4
-rw-r--r--contrib/groff/src/devices/xditview/gray7.bm4
-rw-r--r--contrib/groff/src/devices/xditview/gray8.bm4
-rw-r--r--contrib/groff/src/devices/xditview/gxditview.man410
-rw-r--r--contrib/groff/src/devices/xditview/lex.c96
-rw-r--r--contrib/groff/src/devices/xditview/page.c82
-rw-r--r--contrib/groff/src/devices/xditview/parse.c366
-rw-r--r--contrib/groff/src/devices/xditview/xdit.bm14
-rw-r--r--contrib/groff/src/devices/xditview/xdit_mask.bm14
-rw-r--r--contrib/groff/src/devices/xditview/xditview.c657
53 files changed, 7786 insertions, 844 deletions
diff --git a/contrib/groff/src/devices/grodvi/dvi.cpp b/contrib/groff/src/devices/grodvi/dvi.cpp
index df16939..201eb1c 100644
--- a/contrib/groff/src/devices/grodvi/dvi.cpp
+++ b/contrib/groff/src/devices/grodvi/dvi.cpp
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001, 2002, 2003
+/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001, 2002, 2003, 2004
Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
@@ -17,7 +17,7 @@ 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. */
+Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */
#include "driver.h"
#include "nonposix.h"
@@ -340,12 +340,12 @@ void dvi_printer::set_color(color *col)
do_special(buf);
}
-void dvi_printer::set_char(int index, font *f, const environment *env,
+void dvi_printer::set_char(int idx, font *f, const environment *env,
int w, const char *)
{
if (*env->col != cur_color)
set_color(env->col);
- int code = f->get_code(index);
+ int code = f->get_code(idx);
if (env->size != cur_point_size || f != cur_font) {
cur_font = f;
cur_point_size = env->size;
@@ -384,7 +384,7 @@ void dvi_printer::set_char(int index, font *f, const environment *env,
}
possibly_begin_line();
end_h = env->hpos + w;
- cur_h += scale(f->get_width(index, UNITWIDTH)/MULTIPLIER,
+ cur_h += scale(f->get_width(idx, UNITWIDTH)/MULTIPLIER,
cur_point_size*RES_7227);
if (cur_h > max_h)
max_h = cur_h;
@@ -709,24 +709,26 @@ void draw_dvi_printer::draw(int code, int *p, int np, const environment *env)
fill_flag = 1;
// fall through
case 'c':
- // troff adds an extra argument to C
- if (np != 1 && !(code == 'C' && np == 2)) {
- error("1 argument required for circle");
+ {
+ // troff adds an extra argument to C
+ if (np != 1 && !(code == 'C' && np == 2)) {
+ error("1 argument required for circle");
+ break;
+ }
+ moveto(env->hpos+p[0]/2, env->vpos);
+ if (fill_flag)
+ fill_next(env);
+ else
+ set_line_thickness(env);
+ int rad;
+ rad = milliinches(p[0]/2);
+ sprintf(buf, "%s 0 0 %d %d 0 6.28319",
+ (fill_flag ? "ia" : "ar"),
+ rad,
+ rad);
+ do_special(buf);
break;
}
- moveto(env->hpos+p[0]/2, env->vpos);
- if (fill_flag)
- fill_next(env);
- else
- set_line_thickness(env);
- int rad;
- rad = milliinches(p[0]/2);
- sprintf(buf, "%s 0 0 %d %d 0 6.28319",
- (fill_flag ? "ia" : "ar"),
- rad,
- rad);
- do_special(buf);
- break;
case 'l':
if (np != 2) {
error("2 arguments required for line");
@@ -820,11 +822,11 @@ void draw_dvi_printer::draw(int code, int *p, int np, const environment *env)
if (adjust_arc_center(p, c)) {
int rad = milliinches(int(sqrt(c[0]*c[0] + c[1]*c[1]) + .5));
moveto(env->hpos + int(c[0]), env->vpos + int(c[1]));
- sprintf(buf, "ar 0 0 %d %d %f %f",
- rad,
- rad,
- atan2(p[1] + p[3] - c[1], p[0] + p[2] - c[0]),
- atan2(-c[1], -c[0]));
+ double start = atan2(p[1] + p[3] - c[1], p[0] + p[2] - c[0]);
+ double end = atan2(-c[1], -c[0]);
+ if (end - start < 0)
+ start -= 2 * 3.14159265358;
+ sprintf(buf, "ar 0 0 %d %d %f %f", rad, rad, start, end);
do_special(buf);
}
else {
@@ -915,7 +917,7 @@ int main(int argc, char **argv)
{ "version", no_argument, 0, 'v' },
{ NULL, 0, 0, 0 }
};
- while ((c = getopt_long(argc, argv, "dF:lp:vw:", long_options, NULL))
+ while ((c = getopt_long(argc, argv, "dF:I:lp:vw:", long_options, NULL))
!= EOF)
switch(c) {
case 'd':
@@ -927,6 +929,9 @@ int main(int argc, char **argv)
case 'F':
font::command_line_font_dir(optarg);
break;
+ case 'I':
+ // ignore include search path
+ break;
case 'p':
if (!font::scan_papersize(optarg, 0,
&user_paper_length, &user_paper_width))
diff --git a/contrib/groff/src/devices/grodvi/grodvi.man b/contrib/groff/src/devices/grodvi/grodvi.man
index 793bfe2..7c74c32 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, 2002, 2003 Free Software Foundation, Inc.
+Copyright (C) 1989-2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
Permission is granted to make and distribute verbatim copies of
this manual provided the copyright notice and this permission notice
@@ -17,6 +17,8 @@ translations approved by the Free Software Foundation instead of in
the original English.
..
.
+.do nr grodvi_C \n[.C]
+.cp 0
.
.ie t .ds tx T\h'-.1667m'\v'.224m'E\v'-.224m'\h'-.125m'X
.el .ds tx TeX
@@ -117,7 +119,7 @@ may not contain a newline.
.
.LP
For inclusion of EPS image files,
-.B grodvi
+.B \-Tdvi
loads
.B pspic.tmac
automatically, providing the
@@ -425,6 +427,8 @@ and widths of rules be rounded.
.BR groff_char (@MAN7EXT@),
.BR groff_tmac (@MAN5EXT@)
.
+.cp \n[grodvi_C]
+.
.\" Local Variables:
.\" mode: nroff
.\" End:
diff --git a/contrib/groff/src/devices/grohtml/grohtml.man b/contrib/groff/src/devices/grohtml/grohtml.man
index 976990a..ec82beb 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, 2002 Free Software Foundation, Inc.
+Copyright (C) 1999-2000, 2001, 2002, 2003, 2004 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
@@ -16,17 +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"
+. ie \\n(.$=0:((0\\$1)*2u>(\\n(.lu-\\n(.iu)) .TP
+. 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
@@ -34,22 +40,28 @@ grohtml \- html driver for groff
.in +\w'\fBgrohtml 'u
.ti \niu
.B grohtml
+.
.de OP
-.ie \\n(.$-1 .RI "[\ \fB\\$1\fP" "\\$2" "\ ]"
-.el .RB "[\ " "\\$1" "\ ]"
+. ie \\n(.$-1 .RI "[\ \fB\\$1\fP" "\\$2" "\ ]"
+. el .RB "[\ " "\\$1" "\ ]"
..
-.OP \-vhlrn
+.
+.OP \-bhlnprv
+.OP \-a \%aa-text-bits
.OP \-D dir
.OP \-F dir
-.OP \-i resolution
+.OP \-g \%aa-graphic-bits
+.OP \-i \%resolution
.OP \-I \%image-stem
+.OP \-j \%filename
.OP \-o \%image-vertical-offset
-.OP \-a \%aa-text-bits
-.OP \-a \%aa-graphic-bits
+.OP \-s size
+.OP \-S level
.RI "[\ " files\|.\|.\|. "\ ]"
.br
.ad \na
.
+.
.SH DESCRIPTION
The
.B grohtml
@@ -84,13 +96,15 @@ using
.BR groff 's
.B \-P
option.
+.
+.
.SH OPTIONS
.TP
.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.
+The default is\~4 but valid values are 0, 1, 2, and\~4.
Note your version of
.B gs
needs to support the
@@ -102,12 +116,33 @@ A value of\~0 stops
.B grohtml
from issuing antialiasing commands to
.BR gs .
+.
+.TP
+.B \-b
+Initialize the background color to white.
+.
+.TP
+.BI \-D dir
+Inform
+.B grohtml
+to place all image files into directory
+.IR dir .
+.
+.TP
+.BI \-F dir
+Prepend directory
+.IB dir /dev name
+to the search path for font and device description files;
+.I name
+is the name of the device, usually
+.BR html .
+.
.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.
+The default is\~4 but valid values are 0, 1, 2, and\~4.
Note your version of
.B gs
needs to support the
@@ -119,69 +154,93 @@ 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 -h
-Generates section and number headings by using
+.B \-h
+Generate 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.
-.TP
-.B -r
-Turns off the automatic header and footer line (html rule).
-.TP
-.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 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
-to the search path for font and device description files;
-.I name
-is the name of the device, usually
-.BR html .
+.
.TP
.BI \-i resolution
Select the resolution for all images.
By default this is 100 pixels per inch.
-Example: -i200 indicates 200 pixels per inch.
+Example:
+.B \-i200
+indicates 200 pixels per inch.
+.
.TP
.BI \-I stem
Determine the image stem name.
If omitted grohtml uses
-.BI grohtml- XXX
+.BI \%grohtml- XXX
.RI ( XXX
is the process ID).
+.
+.TP
+.BI \-j filename
+Inform
+.B grohtml
+to split the html output into multiple files.
+The
+.I filename
+is the stem and specified section headings
+(default is level one) start a new file, named
+.IR filename-n.html .
+.
+.TP
+.B \-l
+Turn off the production of automatic section links at the top of the
+document.
+.
+.TP
+.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 older versions of
+some browsers (Netscape).
+This flag is automatically turned on if a heading contains an image.
+.
.TP
.BI \-o vertical-offset
Specify the vertical offset of images in points.
+.
.TP
-.BI \-D dir
-Inform
+.B \-p
+Display page rendering progress to stderr.
.B grohtml
-to place all image files into directory
-.IR dir .
+only displays a page number when an image is required.
+.
+.TP
+.B \-r
+Turn off the automatic header and footer line (html rule).
+.
+.TP
+.B \-s size
+Set the base point size of the source file.
+Thereafter when this point size is used in the source it will correspond
+to the html base size.
+Every increase of two points in the source will yield a
+.B <big>
+tag, and conversely when a decrease of two points is seen a
+.B <small>
+tag is emitted.
+.
+.TP
+.BI \-S level
+When splitting html output,
+split at the heading level (or higher) defined by
+.IR level .
+.
.TP
.B \-v
Print the version number.
.
+.
.SH USAGE
There are styles called
.BR R ,
@@ -189,11 +248,15 @@ There are styles called
.BR B ,
and
.B BI
-mounted at font positions 1 to 4.
+mounted at font positions 1 to\~4.
+.
+.
.SH DEPENDENCIES
.B grohtml
is dependent upon the png utilities
-.RB ( \&\%pnmcut ,\ \%pnmcrop ,\ \%pnmtopng )
+.RB ( \%pnmcut ,
+.BR \%pnmcrop ,
+.BR \%pnmtopng )
and GhostScript
.RB ( gs ).
.B \%pnmtopng
@@ -208,10 +271,14 @@ from the
package.
Images are generated whenever a table, picture, equation or line is
encountered.
+.
+.
.SH BUGS
.B Grohtml
has been completely redesigned and rewritten.
-It is still alpha code.
+It is still beta code.
+.
+.
.SH "SEE ALSO"
.BR afmtodit (@MAN1EXT@),
.BR groff (@MAN1EXT@),
diff --git a/contrib/groff/src/devices/grohtml/html-table.cpp b/contrib/groff/src/devices/grohtml/html-table.cpp
index 3585cd3..7e5b2dc 100644
--- a/contrib/groff/src/devices/grohtml/html-table.cpp
+++ b/contrib/groff/src/devices/grohtml/html-table.cpp
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
*
* Gaius Mulley (gaius@glam.ac.uk) wrote html-table.cpp
*
@@ -24,7 +24,7 @@ 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. */
+Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */
#include "driver.h"
#include "stringclass.h"
@@ -32,6 +32,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "html-table.h"
#include "ctype.h"
#include "html.h"
+#include "html-text.h"
#if !defined(TRUE)
# define TRUE (1==1)
@@ -62,7 +63,7 @@ void tabs::delete_list (void)
while (p != NULL) {
q = p;
p = p->next;
- free(q);
+ delete q;
}
tab = NULL;
}
@@ -104,7 +105,7 @@ int tabs::compatible (const char *s)
while ((*s != (char)0) && isspace(*s))
s++;
// collect tab position
- total += atoi(s);
+ total = atoi(s);
// move over tab position
while ((*s != (char)0) && !isspace(*s))
s++;
@@ -149,10 +150,10 @@ void tabs::init (const char *s)
while ((*s != (char)0) && !isspace(*s))
s++;
if (last == NULL) {
- tab = (tab_position *)malloc(sizeof(tab_position));
+ tab = new tab_position;
last = tab;
} else {
- last->next = (tab_position *)malloc(sizeof(tab_position));
+ last->next = new tab_position;
last = last->next;
}
last->alignment = align;
@@ -162,6 +163,16 @@ void tabs::init (const char *s)
}
/*
+ * check_init - define tab stops using, s, providing none already exist.
+ */
+
+void tabs::check_init (const char *s)
+{
+ if (tab == NULL)
+ init(s);
+}
+
+/*
* find_tab - returns the tab number corresponding to the position, pos.
*/
@@ -228,7 +239,7 @@ void tabs::dump_tabs (void)
*/
html_table::html_table (simple_output *op, int linelen)
- : columns(NULL), out(op), linelength(linelen), last_col(NULL), start_space(FALSE)
+ : out(op), columns(NULL), linelength(linelen), last_col(NULL), start_space(FALSE)
{
tab_stops = new tabs();
}
@@ -242,7 +253,7 @@ html_table::~html_table ()
c = columns;
while (columns != NULL) {
columns = columns->next;
- free(c);
+ delete c;
c = columns;
}
}
@@ -258,7 +269,7 @@ void html_table::remove_cols (cols *c)
while (c != NULL) {
p = c;
c = c->next;
- free(p);
+ delete p;
}
}
@@ -322,15 +333,21 @@ void html_table::emit_table_header (int space)
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();
+
+ out->put_string("<table width=\"100%\"")
+ .put_string(" border=0 rules=\"none\" frame=\"void\"\n")
+ .put_string(" cellspacing=\"0\" cellpadding=\"0\"");
+ out->put_string(">")
+ .nl();
+ out->put_string("<tr valign=\"top\" align=\"left\"");
+ if (space) {
+ out->put_string(" style=\"margin-top: ");
+ out->put_string(STYLE_VERTICAL_SPACE);
+ out->put_string("\"");
+ }
+ out->put_string(">").nl();
}
}
@@ -348,6 +365,16 @@ int html_table::get_right (cols *c)
}
/*
+ * set_space - assigns start_space. Used to determine the
+ * vertical alignment when generating the next table row.
+ */
+
+void html_table::set_space (int space)
+{
+ start_space = space;
+}
+
+/*
* emit_col - moves onto column, n.
*/
@@ -461,18 +488,22 @@ void html_table::finish_row (void)
void html_table::emit_new_row (void)
{
finish_row();
- out->put_string("<tr valign=\"top\" align=\"left\">").nl();
+
+ out->put_string("<tr valign=\"top\" align=\"left\"");
+ if (start_space) {
+ out->put_string(" style=\"margin-top: ");
+ out->put_string(STYLE_VERTICAL_SPACE);
+ out->put_string("\"");
+ }
+ out->put_string(">").nl();
+ start_space = FALSE;
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();
}
/*
@@ -516,13 +547,23 @@ cols *html_table::get_column (int coln)
int html_table::insert_column (int coln, int hstart, int hend, char align)
{
cols *c = columns;
- cols *l = NULL;
+ cols *l = columns;
cols *n = NULL;
while (c != NULL && c->no < coln) {
l = c;
c = c->next;
}
+ if (l != NULL && l->no>coln && hend > l->left)
+ return FALSE; // new column bumps into previous one
+
+ l = NULL;
+ c = columns;
+ 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
@@ -530,7 +571,7 @@ int html_table::insert_column (int coln, int hstart, int hend, char align)
(l->next->left < hend))
return FALSE; // new column bumps into next one
- n = (cols *)malloc(sizeof(cols));
+ n = new cols;
if (l == NULL) {
n->next = columns;
columns = n;
@@ -691,7 +732,6 @@ html_indent::html_indent (simple_output *op, int ind, int pageoffset, int linele
in = ind;
pg = pageoffset;
ll = linelength;
- is_used = FALSE;
}
html_indent::~html_indent (void)
@@ -702,18 +742,33 @@ html_indent::~html_indent (void)
void html_indent::begin (int space)
{
- if (! is_used) {
- table->emit_table_header(space);
- table->emit_col(1);
- is_used = TRUE;
+ if (in + pg == 0) {
+ if (space) {
+ table->out->put_string(" style=\"margin-top: ");
+ table->out->put_string(STYLE_VERTICAL_SPACE);
+ table->out->put_string("\"");
+ }
+ }
+ else {
+ //
+ // we use exactly the same mechanism for calculating
+ // indentation as html_table::emit_col
+ //
+ table->out->put_string(" style=\"margin-left:")
+ .put_number(((in + pg) * 100 + ll/2) / ll -
+ (ll/2)/ll)
+ .put_string("%;");
+
+ if (space) {
+ table->out->put_string(" margin-top: ");
+ table->out->put_string(STYLE_VERTICAL_SPACE);
+ }
+ table->out->put_string("\"");
}
}
void html_indent::end (void)
{
- if (is_used)
- table->emit_finish_table();
- is_used = FALSE;
}
/*
diff --git a/contrib/groff/src/devices/grohtml/html-table.h b/contrib/groff/src/devices/grohtml/html-table.h
index c26eb6d..dc6cebe 100644
--- a/contrib/groff/src/devices/grohtml/html-table.h
+++ b/contrib/groff/src/devices/grohtml/html-table.h
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
*
* Gaius Mulley (gaius@glam.ac.uk) wrote html-table.h
*
@@ -24,7 +24,7 @@ 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. */
+Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */
#include "html.h"
@@ -45,6 +45,7 @@ public:
void clear (void);
int compatible (const char *s);
void init (const char *s);
+ void check_init (const char *s);
int find_tab (int pos);
int get_tab_pos (int n);
char get_tab_align (int n);
@@ -91,14 +92,15 @@ public:
void add_indent (int indent);
void finish_row (void);
int get_effective_linelength (void);
+ void set_space (int space);
tabs *tab_stops; /* tab stop positions */
+ simple_output *out;
private:
cols *columns; /* column entries */
- simple_output *out;
int linelength;
cols *last_col; /* last column started */
- int start_space; /* encapsulate with <p> </p> */
+ int start_space; /* have we seen a `.sp' tag? */
void remove_cols (cols *c);
};
diff --git a/contrib/groff/src/devices/grohtml/html-text.cpp b/contrib/groff/src/devices/grohtml/html-text.cpp
index 21a79eb..b58d5e4 100644
--- a/contrib/groff/src/devices/grohtml/html-text.cpp
+++ b/contrib/groff/src/devices/grohtml/html-text.cpp
@@ -1,5 +1,6 @@
// -*- C++ -*-
-/* Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005
+ * Free Software Foundation, Inc.
*
* Gaius Mulley (gaius@glam.ac.uk) wrote html-text.cpp
*
@@ -24,7 +25,7 @@ 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. */
+Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */
#include "driver.h"
#include "stringclass.h"
@@ -40,6 +41,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "html-text.h"
+#undef DEBUGGING
// #define DEBUGGING
html_text::html_text (simple_output *op) :
@@ -145,18 +147,24 @@ 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>");
- if (t->indent != NULL) {
+ case P_TAG: if (t->indent == NULL) {
+ out->put_string("</p>");
+ } else {
delete t->indent;
t->indent = NULL;
+ out->put_string("</p>");
}
- out->nl(); out->enable_newlines(FALSE);
+ out->enable_newlines(FALSE);
blank_para = TRUE; break;
case SUB_TAG: out->put_string("</sub>"); break;
case SUP_TAG: out->put_string("</sup>"); break;
case TT_TAG: out->put_string("</tt>"); break;
- case PRE_TAG: out->put_string("</pre>"); out->nl(); out->enable_newlines(TRUE);
- blank_para = TRUE; break;
+ case PRE_TAG: out->put_string("</pre>"); out->enable_newlines(TRUE);
+ blank_para = TRUE;
+ if (t->indent != NULL)
+ delete t->indent;
+ t->indent = NULL;
+ break;
case SMALL_TAG: out->put_string("</small>"); break;
case BIG_TAG: out->put_string("</big>"); break;
case COLOR_TAG: out->put_string("</font>"); break;
@@ -168,19 +176,29 @@ void html_text::end_tag (tag_definition *t)
/*
* issue_tag - writes out an html tag with argument.
+ * space == 0 if no space is requested
+ * space == 1 if a space is requested
+ * space == 2 if tag should not have a space style
*/
-void html_text::issue_tag (const char *tagname, const char *arg)
+void html_text::issue_tag (const char *tagname, const char *arg,
+ int space)
{
- if ((arg == 0) || (strlen(arg) == 0)) {
+ if ((arg == 0) || (strlen(arg) == 0))
out->put_string(tagname);
- out->put_string(">");
- } else {
+ else {
out->put_string(tagname);
out->put_string(" ");
out->put_string(arg);
- out->put_string(">");
}
+ if (space == TRUE) {
+ out->put_string(" style=\"margin-top: ");
+ out->put_string(STYLE_VERTICAL_SPACE);
+ out->put_string("\"");
+ }
+ if (space == TRUE || space == FALSE)
+ out->put_string(" valign=\"top\"");
+ out->put_string(">");
}
/*
@@ -214,29 +232,31 @@ void html_text::start_tag (tag_definition *t)
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) {
+ case P_TAG: if (t->indent != NULL) {
out->nl();
- issue_tag("\n<p", (char *)t->arg1);
- } else {
- out->nl();
+#if defined(DEBUGGING)
out->simple_comment("INDENTATION");
- t->indent->begin(FALSE);
- start_space = FALSE;
- issue_tag("<p", (char *)t->arg1);
+#endif
+ out->put_string("\n<p");
+ t->indent->begin(start_space);
+ issue_tag("", (char *)t->arg1);
+ } else {
+ out->nl();
+ issue_tag("\n<p", (char *)t->arg1, start_space);
}
out->enable_newlines(TRUE); break;
case SUB_TAG: issue_tag("<sub", (char *)t->arg1); break;
case SUP_TAG: issue_tag("<sup", (char *)t->arg1); break;
case TT_TAG: issue_tag("<tt", (char *)t->arg1); break;
- case PRE_TAG: if (t->indent != NULL) {
- out->nl();
- out->simple_comment("INDENTATION");
- t->indent->begin(FALSE);
- start_space = FALSE;
- }
- out->enable_newlines(TRUE);
- out->nl(); issue_tag("<pre", (char *)t->arg1);
+ case PRE_TAG: out->enable_newlines(TRUE);
+ out->nl(); out->put_string("<pre");
+ if (t->indent == NULL)
+ issue_tag("", (char *)t->arg1, start_space);
+ else {
+ t->indent->begin(start_space);
+ issue_tag("", (char *)t->arg1);
+ }
out->enable_newlines(FALSE); break;
case SMALL_TAG: issue_tag("<small", (char *)t->arg1); break;
case BIG_TAG: issue_tag("<big", (char *)t->arg1); break;
@@ -264,7 +284,7 @@ void html_text::flush_text (void)
}
p = stackptr;
stackptr = stackptr->next;
- free(p);
+ delete p;
}
lastptr = NULL;
}
@@ -285,6 +305,23 @@ int html_text::is_present (HTML_TAG t)
return FALSE;
}
+/*
+ * uses_indent - returns TRUE if the current paragraph is using a
+ * html table to effect an indent.
+ */
+
+int html_text::uses_indent (void)
+{
+ tag_definition *p = stackptr;
+
+ while (p != NULL) {
+ if (p->indent != NULL)
+ return TRUE;
+ p = p->next;
+ }
+ return FALSE;
+}
+
extern void stop();
/*
@@ -337,7 +374,7 @@ void html_text::do_push (tag_definition *p)
void html_text::push_para (HTML_TAG t, void *arg, html_indent *in)
{
- tag_definition *p=(tag_definition *)malloc(sizeof(tag_definition));
+ tag_definition *p= new tag_definition;
p->type = t;
p->arg1 = arg;
@@ -357,7 +394,7 @@ void html_text::push_para (HTML_TAG t)
void html_text::push_para (color *c)
{
- tag_definition *p=(tag_definition *)malloc(sizeof(tag_definition));
+ tag_definition *p = new tag_definition;
p->type = COLOR_TAG;
p->arg1 = NULL;
@@ -407,9 +444,11 @@ void html_text::do_pre (void)
done_tt();
if (is_present(P_TAG)) {
html_indent *i = remove_indent(P_TAG);
+ int space = retrieve_para_space();
(void)done_para();
if (! is_present(PRE_TAG))
push_para(PRE_TAG, NULL, i);
+ start_space = space;
} else if (! is_present(PRE_TAG))
push_para(PRE_TAG, NULL, NULL);
dump_stack();
@@ -475,8 +514,8 @@ char *html_text::shutdown (HTML_TAG t)
/*
* push tag onto temp stack
*/
- p->next = temp;
- temp = p;
+ p->next = temp;
+ temp = p;
}
/*
@@ -495,7 +534,7 @@ char *html_text::shutdown (HTML_TAG t)
lastptr = NULL;
if (p->indent != NULL)
delete p->indent;
- free(p);
+ delete p;
}
/*
@@ -508,7 +547,7 @@ char *html_text::shutdown (HTML_TAG t)
push_para(temp->type, temp->arg1, temp->indent);
p = temp;
temp = temp->next;
- free(p);
+ delete p;
}
}
return arg;
@@ -607,7 +646,7 @@ void html_text::check_emit_text (tag_definition *t)
void html_text::do_emittext (const char *s, int length)
{
if ((! is_present(P_TAG)) && (! is_present(PRE_TAG)))
- do_para("");
+ do_para("", FALSE);
if (is_present(BREAK_TAG)) {
int text = remove_break();
@@ -615,13 +654,12 @@ void html_text::do_emittext (const char *s, int length)
if (text) {
if (is_present(PRE_TAG)) {
out->nl();
- } else {
+ } else
out->put_string("<br>").nl();
- }
}
- } else {
+ } else
check_emit_text(stackptr);
- }
+
out->put_string(s, length);
space_emitted = FALSE;
blank_para = FALSE;
@@ -631,38 +669,40 @@ void html_text::do_emittext (const char *s, int length)
* do_para - starts a new paragraph
*/
-void html_text::do_para (const char *arg, html_indent *in)
+void html_text::do_para (const char *arg, html_indent *in, int space)
{
if (! is_present(P_TAG)) {
if (is_present(PRE_TAG)) {
html_indent *i = remove_indent(PRE_TAG);
done_pre();
- if (i == in || in == NULL)
+ if ((arg == NULL || (strcmp(arg, "") == 0)) &&
+ (i == in || in == NULL))
in = i;
else
delete i;
}
remove_sub_sup();
push_para(P_TAG, (void *)arg, in);
- space_emitted = TRUE;
+ start_space = space;
}
}
-void html_text::do_para (const char *arg)
+void html_text::do_para (const char *arg, int space)
{
- do_para(arg, NULL);
+ do_para(arg, NULL, space);
}
void html_text::do_para (simple_output *op, const char *arg1,
- int indentation, int pageoffset, int linelength)
+ int indentation_value, int page_offset,
+ int line_length, int space)
{
- html_indent *indent;
+ html_indent *ind;
- if (indentation == 0)
- indent = NULL;
+ if (indentation_value == 0)
+ ind = NULL;
else
- indent = new html_indent(op, indentation, pageoffset, linelength);
- do_para(arg1, indent);
+ ind = new html_indent(op, indentation_value, page_offset, line_length);
+ do_para(arg1, ind, space);
}
/*
@@ -671,8 +711,11 @@ void html_text::do_para (simple_output *op, const char *arg1,
char *html_text::done_para (void)
{
+ char *result;
space_emitted = TRUE;
- return shutdown(P_TAG);
+ result = shutdown(P_TAG);
+ start_space = FALSE;
+ return result;
}
/*
@@ -696,25 +739,30 @@ html_indent *html_text::remove_indent (HTML_TAG tag)
}
/*
+ * remove_para_space - removes the leading space to a paragraph
+ * (effectively this trims off a leading `.sp' tag).
+ */
+
+void html_text::remove_para_space (void)
+{
+ start_space = FALSE;
+}
+
+/*
* do_space - issues an end of paragraph
*/
void html_text::do_space (void)
{
if (is_in_pre()) {
- if (blank_para)
- start_space = TRUE;
- else {
- do_emittext("", 0);
- out->nl();
- space_emitted = TRUE;
- }
+ do_emittext("", 0);
+ out->force_nl();
+ space_emitted = TRUE;
} else {
html_indent *i = remove_indent(P_TAG);
- do_para(done_para(), i);
+ do_para(done_para(), i, TRUE);
space_emitted = TRUE;
- start_space = TRUE;
}
}
@@ -724,13 +772,11 @@ void html_text::do_space (void)
void html_text::do_break (void)
{
- if (! is_present(PRE_TAG)) {
- if (emitted_text()) {
- if (! is_present(BREAK_TAG)) {
+ if (! is_present(PRE_TAG))
+ if (emitted_text())
+ if (! is_present(BREAK_TAG))
push_para(BREAK_TAG);
- }
- }
- }
+
space_emitted = TRUE;
}
@@ -756,7 +802,8 @@ int html_text::emitted_text (void)
}
/*
- * ever_emitted_text - returns TRUE if we have ever emitted text in this paragraph.
+ * ever_emitted_text - returns TRUE if we have ever emitted text in this
+ * paragraph.
*/
int html_text::ever_emitted_text (void)
@@ -765,7 +812,7 @@ int html_text::ever_emitted_text (void)
}
/*
- * starts_with_space - returns TRUE if we have start this paragraph with a .sp
+ * starts_with_space - returns TRUE if we started this paragraph with a .sp
*/
int html_text::starts_with_space (void)
@@ -774,19 +821,34 @@ int html_text::starts_with_space (void)
}
/*
+ * retrieve_para_space - returns TRUE, if the paragraph starts with
+ * a space and text has not yet been emitted.
+ * If TRUE is returned, then the, start_space,
+ * variable is set to FALSE.
+ */
+
+int html_text::retrieve_para_space (void)
+{
+ if (start_space && blank_para) {
+ start_space = FALSE;
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+/*
* emit_space - writes a space providing that text was written beforehand.
*/
void html_text::emit_space (void)
{
- if (space_emitted) {
- if (is_present(PRE_TAG)) {
- do_emittext(" ", 1);
- }
- } else {
+ if (is_present(PRE_TAG))
+ do_emittext(" ", 1);
+ else
out->space_or_newline();
- space_emitted = TRUE;
- }
+
+ space_emitted = TRUE;
}
/*
@@ -817,7 +879,7 @@ void html_text::remove_def (tag_definition *t)
if (l->next == NULL)
lastptr = l;
}
- free(p);
+ delete p;
}
}
@@ -837,7 +899,8 @@ void html_text::remove_tag (HTML_TAG tag)
}
/*
- * remove_sub_sup - removes a sub or sup tag, should either exist on the stack.
+ * remove_sub_sup - removes a sub or sup tag, should either exist
+ * on the stack.
*/
void html_text::remove_sub_sup (void)
@@ -882,7 +945,7 @@ int html_text::remove_break (void)
if (l->next == NULL)
lastptr = l;
}
- free(p);
+ delete p;
}
/*
* now determine whether text was issued before <br>
@@ -910,8 +973,9 @@ void html_text::remove_para_align (void)
while (p != NULL) {
if (p->type == P_TAG && p->arg1 != NULL) {
html_indent *i = remove_indent(P_TAG);
+ int space = retrieve_para_space();
done_para();
- do_para("", i);
+ do_para("", i, space);
return;
}
p = p->next;
@@ -920,6 +984,25 @@ void html_text::remove_para_align (void)
}
/*
+ * get_alignment - returns the alignment for the paragraph.
+ * If no alignment was given then we return "".
+ */
+
+char *html_text::get_alignment (void)
+{
+ if (is_present(P_TAG)) {
+ tag_definition *p=stackptr;
+
+ while (p != NULL) {
+ if (p->type == P_TAG && p->arg1 != NULL)
+ return (char *)p->arg1;
+ p = p->next;
+ }
+ }
+ return (char *)"";
+}
+
+/*
* do_small - potentially inserts a <small> tag into the html stream.
* However we check for a <big> tag, if present then we terminate it.
* Otherwise a <small> tag is inserted.
@@ -962,4 +1045,3 @@ void html_text::do_sub (void)
{
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 aa4dd80..e0e3cc7 100644
--- a/contrib/groff/src/devices/grohtml/html-text.h
+++ b/contrib/groff/src/devices/grohtml/html-text.h
@@ -1,5 +1,6 @@
// -*- C++ -*-
-/* Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005
+ * Free Software Foundation, Inc.
*
* Gaius Mulley (gaius@glam.ac.uk) wrote html-text.h
*
@@ -23,11 +24,13 @@ 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. */
+Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */
#include "html.h"
#include "html-table.h"
+#define STYLE_VERTICAL_SPACE "1em"
+
/*
* html tags
*/
@@ -64,9 +67,10 @@ public:
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 (const char *arg, int space); // used for no indentation
void do_para (simple_output *op, const char *arg1,
- int indentation, int pageoffset, int linelength);
+ int indentation, int pageoffset, int linelength,
+ int space);
void do_sup (void);
void do_sub (void);
void do_space (void);
@@ -87,11 +91,15 @@ public:
int emitted_text (void);
int ever_emitted_text (void);
int starts_with_space (void);
+ int retrieve_para_space (void);
void emit_space (void);
int is_in_pre (void);
+ int uses_indent (void);
void remove_tag (HTML_TAG tag);
void remove_sub_sup (void);
void remove_para_align (void);
+ void remove_para_space (void);
+ char *get_alignment (void);
private:
tag_definition *stackptr; /* the current paragraph state */
@@ -108,7 +116,7 @@ private:
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 do_para (const char *arg, html_indent *in, int space);
void push_para (HTML_TAG t);
void push_para (HTML_TAG t, void *arg, html_indent *in);
void push_para (color *c);
@@ -116,7 +124,7 @@ private:
char *shutdown (HTML_TAG t);
void check_emit_text (tag_definition *t);
int remove_break (void);
- void issue_tag (const char *tagname, const char *arg);
+ void issue_tag (const char *tagname, const char *arg, int space=2);
void issue_color_begin (color *c);
void remove_def (tag_definition *t);
html_indent *remove_indent (HTML_TAG tag);
diff --git a/contrib/groff/src/devices/grohtml/html.h b/contrib/groff/src/devices/grohtml/html.h
index 431647c..b14fb2c 100644
--- a/contrib/groff/src/devices/grohtml/html.h
+++ b/contrib/groff/src/devices/grohtml/html.h
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+/* Copyright (C) 2000, 2001, 2002, 2004 Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
This file is part of groff.
@@ -16,7 +16,7 @@ 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. */
+Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */
#if !defined(HTML_H)
# define HTML_H
@@ -72,6 +72,7 @@ public:
simple_output &enable_newlines(int);
simple_output &check_newline(int n);
simple_output &nl(void);
+ simple_output &force_nl(void);
simple_output &space_or_newline (void);
simple_output &begin_tag (void);
FILE *get_file();
diff --git a/contrib/groff/src/devices/grohtml/output.cpp b/contrib/groff/src/devices/grohtml/output.cpp
index 2705b9e..f253127 100644
--- a/contrib/groff/src/devices/grohtml/output.cpp
+++ b/contrib/groff/src/devices/grohtml/output.cpp
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 2000, 2001, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2000, 2001, 2003, 2004, 2005 Free Software Foundation, Inc.
*
* Gaius Mulley (gaius@glam.ac.uk) wrote output.cpp
* but it owes a huge amount of ideas and raw code from
@@ -25,7 +25,7 @@ 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. */
+Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */
#include "driver.h"
#include "stringclass.h"
@@ -67,7 +67,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
word::word (const char *w, int n)
: next(0)
{
- s = (char *)malloc(n+1);
+ s = new char[n+1];
strncpy(s, w, n);
s[n] = (char)0;
}
@@ -78,7 +78,7 @@ word::word (const char *w, int n)
word::~word ()
{
- free(s);
+ a_delete s;
}
/*
@@ -253,6 +253,19 @@ simple_output &simple_output::space_or_newline (void)
}
/*
+ * force_nl - forces a newline.
+ */
+
+simple_output &simple_output::force_nl (void)
+{
+ space_or_newline();
+ col += last_word.flush(fp);
+ FPUTC('\n', fp);
+ col = 0;
+ return *this ;
+}
+
+/*
* nl - writes a newline providing that we
* are not in the first column.
*/
@@ -261,10 +274,8 @@ simple_output &simple_output::nl (void)
{
space_or_newline();
col += last_word.flush(fp);
- if (col != 0) {
- FPUTC('\n', fp);
- col = 0;
- }
+ FPUTC('\n', fp);
+ col = 0;
return *this ;
}
diff --git a/contrib/groff/src/devices/grohtml/post-html.cpp b/contrib/groff/src/devices/grohtml/post-html.cpp
index 7c96deb..1283e06 100644
--- a/contrib/groff/src/devices/grohtml/post-html.cpp
+++ b/contrib/groff/src/devices/grohtml/post-html.cpp
@@ -1,5 +1,6 @@
// -*- C++ -*-
-/* Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005
+ * Free Software Foundation, Inc.
*
* Gaius Mulley (gaius@glam.ac.uk) wrote post-html.cpp
* but it owes a huge amount of ideas and raw code from
@@ -21,7 +22,7 @@ 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. */
+Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */
#include "driver.h"
#include "stringclass.h"
@@ -38,6 +39,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include <stdio.h>
#include <fcntl.h>
+#include <string.h>
extern "C" const char *Version_string;
@@ -50,8 +52,7 @@ extern "C" const char *Version_string;
#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 CENTER_TOLERANCE 2 /* how many pixels off center do we allow */
#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 */
@@ -60,7 +61,7 @@ typedef enum {CENTERED, LEFT, RIGHT, INLINE} TAG_ALIGNMENT;
typedef enum {col_tag, tab_tag, tab0_tag, none} colType;
#undef DEBUG_TABLES
-
+// #define DEBUG_TABLES
/*
* prototypes
@@ -78,6 +79,16 @@ static int simple_anchors = FALSE; /* default to anchors with
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? */
+static string job_name; /* if set then the output is split into */
+ /* multiple files with `job_name'-%d.html */
+static int multiple_files = FALSE; /* must we the output be divided into */
+ /* multiple html files, one for each */
+ /* heading? */
+static int base_point_size = 0; /* which troff font size maps onto html */
+ /* size 3? */
+static int split_level = 2; /* what heading level to split at? */
+static string head_info; /* user supplied information to be placed */
+ /* into <head> </head> */
/*
@@ -109,7 +120,7 @@ static int max (int a, int b)
static int is_intersection (int a1, int a2, int b1, int b2)
{
// easier to prove NOT outside limits
- return( ! ((a1 > b2) || (a2 < b1)) );
+ return ! ((a1 > b2) || (a2 < b1));
}
/*
@@ -118,7 +129,7 @@ static int is_intersection (int a1, int a2, int b1, int b2)
static int is_digit (char ch)
{
- return( (ch >= '0') && (ch <= '9') );
+ return (ch >= '0') && (ch <= '9');
}
/*
@@ -128,6 +139,9 @@ static int is_digit (char ch)
struct file {
FILE *fp;
file *next;
+ int new_output_file;
+ int require_links;
+ string output_file_name;
file (FILE *f);
};
@@ -137,21 +151,28 @@ struct file {
*/
file::file (FILE *f)
- : fp(f), next(0)
+ : fp(f), next(NULL), new_output_file(FALSE),
+ require_links(FALSE), output_file_name("")
{
}
class files {
public:
- files ();
- FILE *get_file (void);
- void start_of_list (void);
- void move_next (void);
- void add_new_file (FILE *f);
+ files ();
+ FILE *get_file (void);
+ void start_of_list (void);
+ void move_next (void);
+ void add_new_file (FILE *f);
+ void set_file_name (string name);
+ void set_links_required (void);
+ int are_links_required (void);
+ int is_new_output_file (void);
+ string file_name (void);
+ string next_file_name (void);
private:
- file *head;
- file *tail;
- file *ptr;
+ file *head;
+ file *tail;
+ file *ptr;
};
/*
@@ -159,7 +180,7 @@ private:
*/
files::files ()
- : head(0), tail(0), ptr(0)
+ : head(NULL), tail(NULL), ptr(NULL)
{
}
@@ -169,11 +190,10 @@ files::files ()
FILE *files::get_file (void)
{
- if (ptr) {
- return( ptr->fp );
- } else {
- return( 0 );
- }
+ if (ptr)
+ return ptr->fp;
+ else
+ return NULL;
}
/*
@@ -191,7 +211,7 @@ void files::start_of_list (void)
void files::move_next (void)
{
- if (ptr != 0)
+ if (ptr != NULL)
ptr = ptr->next;
}
@@ -201,7 +221,7 @@ void files::move_next (void)
void files::add_new_file (FILE *f)
{
- if (head == 0) {
+ if (head == NULL) {
head = new file(f);
tail = head;
} else {
@@ -212,6 +232,76 @@ void files::add_new_file (FILE *f)
}
/*
+ * set_file_name - sets the final file name to contain the html
+ * data to name.
+ */
+
+void files::set_file_name (string name)
+{
+ if (ptr != NULL) {
+ ptr->output_file_name = name;
+ ptr->new_output_file = TRUE;
+ }
+}
+
+/*
+ * set_links_required - issue links when processing this component
+ * of the file.
+ */
+
+void files::set_links_required (void)
+{
+ if (ptr != NULL)
+ ptr->require_links = TRUE;
+}
+
+/*
+ * are_links_required - returns TRUE if this section of the file
+ * requires that links should be issued.
+ */
+
+int files::are_links_required (void)
+{
+ if (ptr != NULL)
+ return ptr->require_links;
+ return FALSE;
+}
+
+/*
+ * is_new_output_file - returns TRUE if this component of the file
+ * is the start of a new output file.
+ */
+
+int files::is_new_output_file (void)
+{
+ if (ptr != NULL)
+ return ptr->new_output_file;
+ return FALSE;
+}
+
+/*
+ * file_name - returns the name of the file.
+ */
+
+string files::file_name (void)
+{
+ if (ptr != NULL)
+ return ptr->output_file_name;
+ return string("");
+}
+
+/*
+ * next_file_name - returns the name of the next file.
+ */
+
+string files::next_file_name (void)
+{
+ if (ptr != NULL && ptr->next != NULL)
+ return ptr->next->output_file_name;
+ return string("");
+}
+
+/*
* the class and methods for styles
*/
@@ -229,7 +319,7 @@ struct style {
};
style::style()
- : f(0)
+ : f(NULL)
{
}
@@ -265,14 +355,14 @@ struct char_block {
};
char_block::char_block()
-: buffer(NULL), used(0), next(0)
+: buffer(NULL), used(0), next(NULL)
{
}
char_block::char_block(int length)
-: used(0), next(0)
+: used(0), next(NULL)
{
- buffer = (char *)malloc(max(length, char_block::SIZE));
+ buffer = new char[max(length, char_block::SIZE)];
if (buffer == NULL)
fatal("out of memory error");
}
@@ -280,7 +370,7 @@ char_block::char_block(int length)
char_block::~char_block()
{
if (buffer != NULL)
- free(buffer);
+ a_delete buffer;
}
class char_buffer {
@@ -295,13 +385,13 @@ private:
};
char_buffer::char_buffer()
-: head(0), tail(0)
+: head(NULL), tail(NULL)
{
}
char_buffer::~char_buffer()
{
- while (head != 0) {
+ while (head != NULL) {
char_block *temp = head;
head = head->next;
delete temp;
@@ -316,7 +406,7 @@ char *char_buffer::add_string (const char *s, unsigned int length)
if (s == NULL || length == 0)
return NULL;
- if (tail == 0) {
+ if (tail == NULL) {
tail = new char_block(length+1);
head = tail;
} else {
@@ -341,7 +431,7 @@ char *char_buffer::add_string (const char *s, unsigned int length)
// and return start of new string
- return( &tail->buffer[old_used] );
+ return &tail->buffer[old_used];
}
char *char_buffer::add_string (const string &s)
@@ -382,7 +472,10 @@ public:
int is_in (void);
int is_po (void);
int is_ti (void);
+ int is_ll (void);
int is_ce (void);
+ int is_tl (void);
+ int is_eo_tl (void);
int is_eol_ce (void);
int is_col (void);
int is_tab (void);
@@ -392,6 +485,7 @@ public:
int is_tab_te (void);
int is_nf (void);
int is_fi (void);
+ int is_eo_h (void);
int get_arg (void);
int get_tab_args (char *align);
@@ -423,16 +517,16 @@ text_glob::text_glob (style *s, const char *str, int length,
int max_vertical, int max_horizontal,
bool is_troff_command,
bool is_auto_image, bool is_special_command,
- bool is_a_line, int line_thickness)
+ bool is_a_line_flag, int line_thickness)
: text_style(*s), text_string(str), text_length(length),
minv(min_vertical), minh(min_horizontal), maxv(max_vertical), maxh(max_horizontal),
is_tag(is_troff_command), is_img_auto(is_auto_image), is_special(is_special_command),
- is_line(is_a_line), thickness(line_thickness), tab(NULL)
+ is_line(is_a_line_flag), thickness(line_thickness), tab(NULL)
{
}
text_glob::text_glob ()
- : text_string(0), text_length(0), minv(-1), minh(-1), maxv(-1), maxh(-1),
+ : text_string(NULL), text_length(0), minv(-1), minh(-1), maxv(-1), maxh(-1),
is_tag(FALSE), is_special(FALSE), is_line(FALSE), thickness(0), tab(NULL)
{
}
@@ -483,11 +577,11 @@ void text_glob::text_glob_special (style *s, char *str, int length,
void text_glob::text_glob_line (style *s,
int min_vertical , int min_horizontal,
int max_vertical , int max_horizontal,
- int thickness)
+ int thickness_value)
{
text_glob *g = new text_glob(s, "", 0,
min_vertical, min_horizontal, max_vertical, max_horizontal,
- FALSE, FALSE, FALSE, TRUE, thickness);
+ FALSE, FALSE, FALSE, TRUE, thickness_value);
*this = *g;
delete g;
}
@@ -565,7 +659,7 @@ int text_glob::is_a_tag (void)
int text_glob::is_eol (void)
{
- return( is_tag && (strcmp(text_string, "html-tag:eol") == 0) );
+ return is_tag && (strcmp(text_string, "devtag:.eol") == 0);
}
/*
@@ -574,26 +668,56 @@ int text_glob::is_eol (void)
int text_glob::is_eol_ce (void)
{
- return( is_tag && (strcmp(text_string, "html-tag:eol.ce") == 0) );
+ return is_tag && (strcmp(text_string, "devtag:eol.ce") == 0);
}
+/*
+ * is_tl - returns TRUE if glob contains the tag .tl
+ */
+
+int text_glob::is_tl (void)
+{
+ return is_tag && (strcmp(text_string, "devtag:.tl") == 0);
+}
/*
- * is_nf - returns TRUE if glob contains the tag .nf
+ * is_eo_tl - returns TRUE if glob contains the tag eo.tl
+ */
+
+int text_glob::is_eo_tl (void)
+{
+ return is_tag && (strcmp(text_string, "devtag:.eo.tl") == 0);
+}
+
+/*
+ * is_nf - returns TRUE if glob contains the tag .fi 0
*/
int text_glob::is_nf (void)
{
- return( is_tag && (strcmp(text_string, "html-tag:.nf") == 0) );
+ return is_tag && (strncmp(text_string, "devtag:.fi",
+ strlen("devtag:.fi")) == 0) &&
+ (get_arg() == 0);
}
/*
- * is_fi - returns TRUE if glob contains the tag .fi
+ * is_fi - returns TRUE if glob contains the tag .fi 1
*/
int text_glob::is_fi (void)
{
- return( is_tag && (strcmp(text_string, "html-tag:.fi") == 0) );
+ return( is_tag && (strncmp(text_string, "devtag:.fi",
+ strlen("devtag:.fi")) == 0) &&
+ (get_arg() == 1) );
+}
+
+/*
+ * is_eo_h - returns TRUE if glob contains the tag .eo.h
+ */
+
+int text_glob::is_eo_h (void)
+{
+ return is_tag && (strcmp(text_string, "devtag:.eo.h") == 0);
}
/*
@@ -602,7 +726,8 @@ int text_glob::is_fi (void)
int text_glob::is_ce (void)
{
- return( is_tag && (strcmp(text_string, "html-tag:.ce") == 0) );
+ return is_tag && (strncmp(text_string, "devtag:.ce",
+ strlen("devtag:.ce")) == 0);
}
/*
@@ -611,7 +736,8 @@ int text_glob::is_ce (void)
int text_glob::is_in (void)
{
- return( is_tag && (strncmp(text_string, "html-tag:.in ", strlen("html-tag:.in ")) == 0) );
+ return is_tag && (strncmp(text_string, "devtag:.in ",
+ strlen("devtag:.in ")) == 0);
}
/*
@@ -620,7 +746,8 @@ int text_glob::is_in (void)
int text_glob::is_po (void)
{
- return( is_tag && (strncmp(text_string, "html-tag:.po ", strlen("html-tag:.po ")) == 0) );
+ return is_tag && (strncmp(text_string, "devtag:.po ",
+ strlen("devtag:.po ")) == 0);
}
/*
@@ -629,7 +756,18 @@ int text_glob::is_po (void)
int text_glob::is_ti (void)
{
- return( is_tag && (strncmp(text_string, "html-tag:.ti ", strlen("html-tag:.ti ")) == 0) );
+ return is_tag && (strncmp(text_string, "devtag:.ti ",
+ strlen("devtag:.ti ")) == 0);
+}
+
+/*
+ * is_ll - returns TRUE if glob contains the tag .ll
+ */
+
+int text_glob::is_ll (void)
+{
+ return is_tag && (strncmp(text_string, "devtag:.ll ",
+ strlen("devtag:.ll ")) == 0);
}
/*
@@ -638,7 +776,8 @@ int text_glob::is_ti (void)
int text_glob::is_col (void)
{
- return( is_tag && (strncmp(text_string, "html-tag:.col", strlen("html-tag:.col")) == 0) );
+ return is_tag && (strncmp(text_string, "devtag:.col",
+ strlen("devtag:.col")) == 0);
}
/*
@@ -647,7 +786,7 @@ int text_glob::is_col (void)
int text_glob::is_tab_ts (void)
{
- return( is_tag && (strcmp(text_string, "html-tag:.tab-ts") == 0) );
+ return is_tag && (strcmp(text_string, "devtag:.tab-ts") == 0);
}
/*
@@ -656,7 +795,7 @@ int text_glob::is_tab_ts (void)
int text_glob::is_tab_te (void)
{
- return( is_tag && (strcmp(text_string, "html-tag:.tab-te") == 0) );
+ return is_tag && (strcmp(text_string, "devtag:.tab-te") == 0);
}
/*
@@ -665,7 +804,8 @@ int text_glob::is_tab_te (void)
int text_glob::is_ta (void)
{
- return( is_tag && (strncmp(text_string, "html-tag:.ta ", strlen("html-tag:.ta ")) == 0) );
+ return is_tag && (strncmp(text_string, "devtag:.ta ",
+ strlen("devtag:.ta ")) == 0);
}
/*
@@ -674,7 +814,8 @@ int text_glob::is_ta (void)
int text_glob::is_tab (void)
{
- return( is_tag && (strncmp(text_string, "html-tag:tab ", strlen("html-tag:tab ")) == 0) );
+ return is_tag && (strncmp(text_string, "devtag:tab ",
+ strlen("devtag:tab ")) == 0);
}
/*
@@ -683,7 +824,8 @@ int text_glob::is_tab (void)
int text_glob::is_tab0 (void)
{
- return( is_tag && (strncmp(text_string, "html-tag:tab0", strlen("html-tag:tab0")) == 0) );
+ return is_tag && (strncmp(text_string, "devtag:tab0",
+ strlen("devtag:tab0")) == 0);
}
/*
@@ -705,14 +847,14 @@ int text_glob::is_auto_img (void)
int text_glob::is_br (void)
{
- return( is_a_tag() && ((strcmp ("html-tag:.br", text_string) == 0) ||
- (strncmp("html-tag:.sp", text_string, 11) == 0) ||
- (strcmp ("html-tag:.ce", text_string) == 0)) );
+ return is_a_tag() && ((strcmp ("devtag:.br", text_string) == 0) ||
+ (strncmp("devtag:.sp", text_string,
+ strlen("devtag:.sp")) == 0));
}
int text_glob::get_arg (void)
{
- if (strncmp("html-tag:", text_string, strlen("html-tag:")) == 0) {
+ if (strncmp("devtag:", text_string, strlen("devtag:")) == 0) {
const char *p = text_string;
while ((*p != (char)0) && (!isspace(*p)))
@@ -732,7 +874,7 @@ int text_glob::get_arg (void)
int text_glob::get_tab_args (char *align)
{
- if (strncmp("html-tag:", text_string, strlen("html-tag:")) == 0) {
+ if (strncmp("devtag:", text_string, strlen("devtag:")) == 0) {
const char *p = text_string;
// firstly the alignment C|R|L
@@ -774,10 +916,11 @@ html_table *text_glob::get_table (void)
}
/*
- * the class and methods used to construct ordered double linked lists.
- * In a previous implementation we used templates via #include "ordered-list.h",
- * but this does assume that all C++ compilers can handle this feature. Pragmatically
- * it is safer to assume this is not the case.
+ * the class and methods used to construct ordered double linked
+ * lists. In a previous implementation we used templates via
+ * #include "ordered-list.h", but this does assume that all C++
+ * compilers can handle this feature. Pragmatically it is safer to
+ * assume this is not the case.
*/
struct element_list {
@@ -893,7 +1036,8 @@ int list::is_less (element_list *a, element_list *b)
}
/*
- * add - adds a datum to the list in the order specified by the region position.
+ * add - adds a datum to the list in the order specified by the
+ * region position.
*/
void list::add (text_glob *in, int line_number, int min_vertical, int min_horizontal, int max_vertical, int max_horizontal)
@@ -902,7 +1046,13 @@ void list::add (text_glob *in, int line_number, int min_vertical, int min_horizo
element_list *t = new element_list(in, line_number, min_vertical, min_horizontal, max_vertical, max_horizontal);
element_list *last;
- if (head == 0) {
+#if 0
+ fprintf(stderr, "[%s %d,%d,%d,%d] ",
+ in->text_string, min_vertical, min_horizontal, max_vertical, max_horizontal);
+ fflush(stderr);
+#endif
+
+ if (head == NULL) {
head = t;
tail = t;
ptr = t;
@@ -911,9 +1061,8 @@ void list::add (text_glob *in, int line_number, int min_vertical, int min_horizo
} else {
last = tail;
- while ((last != head) && (is_less(t, last))) {
+ while ((last != head) && (is_less(t, last)))
last = last->left;
- }
if (is_less(t, last)) {
t->right = last;
@@ -921,9 +1070,8 @@ void list::add (text_glob *in, int line_number, int min_vertical, int min_horizo
t->left = last->left;
last->left = t;
// now check for a new head
- if (last == head) {
+ if (last == head)
head = t;
- }
} else {
// add t beyond last
t->right = last->right;
@@ -931,9 +1079,8 @@ void list::add (text_glob *in, int line_number, int min_vertical, int min_horizo
last->right->left = t;
last->right = t;
// now check for a new tail
- if (last == tail) {
+ if (last == tail)
tail = t;
- }
}
}
}
@@ -948,22 +1095,20 @@ void list::sub_move_right (void)
element_list *t=ptr->right;
if (head == tail) {
- head = 0;
- if (tail != 0) {
+ head = NULL;
+ if (tail != NULL)
delete tail;
- }
- tail = 0;
- ptr = 0;
+
+ tail = NULL;
+ ptr = NULL;
} else {
- if (head == ptr) {
+ if (head == ptr)
head = head->right;
- }
- if (tail == ptr) {
+ if (tail == ptr)
tail = tail->left;
- }
ptr->left->right = ptr->right;
ptr->right->left = ptr->left;
- ptr=t;
+ ptr = t;
}
}
@@ -991,7 +1136,7 @@ void list::start_from_tail (void)
int list::is_empty (void)
{
- return( head == 0 );
+ return head == NULL;
}
/*
@@ -1000,7 +1145,7 @@ int list::is_empty (void)
int list::is_equal_to_tail (void)
{
- return( ptr == tail );
+ return ptr == tail;
}
/*
@@ -1009,7 +1154,7 @@ int list::is_equal_to_tail (void)
int list::is_equal_to_head (void)
{
- return( ptr == head );
+ return ptr == head;
}
/*
@@ -1036,7 +1181,7 @@ void list::move_right (void)
text_glob* list::get_data (void)
{
- return( ptr->datum );
+ return ptr->datum;
}
/*
@@ -1047,11 +1192,10 @@ text_glob* list::get_data (void)
text_glob* list::move_right_get_data (void)
{
ptr = ptr->right;
- if (ptr == head) {
- return( 0 );
- } else {
- return( ptr->datum );
- }
+ if (ptr == head)
+ return NULL;
+ else
+ return ptr->datum;
}
/*
@@ -1062,11 +1206,10 @@ text_glob* list::move_right_get_data (void)
text_glob* list::move_left_get_data (void)
{
ptr = ptr->left;
- if (ptr == tail) {
- return( 0 );
- } else {
- return( ptr->datum );
- }
+ if (ptr == tail)
+ return NULL;
+ else
+ return ptr->datum;
}
/*
@@ -1078,7 +1221,7 @@ void list::insert (text_glob *in)
if (is_empty())
fatal("list must not be empty if we are inserting data");
else {
- if (ptr == 0)
+ if (ptr == NULL)
ptr = head;
element_list *t = new element_list(in, ptr->lineno, ptr->minv, ptr->minh, ptr->maxv, ptr->maxh);
@@ -1121,7 +1264,8 @@ public:
void add_and_encode (style *s, const string &str,
int line_number,
int min_vertical, int min_horizontal,
- int max_vertical, int max_horizontal);
+ int max_vertical, int max_horizontal,
+ int is_tag);
void add_line (style *s,
int line_number,
int x1, int y1, int x2, int y2,
@@ -1183,7 +1327,8 @@ void page::add_tag (style *s, const string &str,
if (str.length() > 0) {
text_glob *g;
- if (strncmp((str+'\0').contents(), "html-tag:.auto-image", 20) == 0) {
+ if (strncmp((str+'\0').contents(), "devtag:.auto-image",
+ strlen("devtag:.auto-image")) == 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);
@@ -1202,15 +1347,18 @@ void page::add_tag (style *s, const string &str,
void page::add_line (style *s,
int line_number,
- int x1, int y1, int x2, int y2,
+ int x_1, int y_1, int x_2, int y_2,
int thickness)
{
- if (y1 == y2) {
+ if (y_1 == y_2) {
text_glob *g = new text_glob();
g->text_glob_line(s,
- min(y1, y2), min(x1, y2), max(y1, y2), max(x1, x2),
+ min(y_1, y_2), min(x_1, x_2),
+ max(y_1, y_2), max(x_1, x_2),
thickness);
- glyphs.add(g, line_number, min(y1, y2), min(x1, y2), max(y1, y2), max(x1, x2));
+ glyphs.add(g, line_number,
+ min(y_1, y_2), min(x_1, x_2),
+ max(y_1, y_2), max(x_1, x_2));
}
}
@@ -1240,7 +1388,8 @@ static char *to_unicode (unsigned int ch)
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)
+ int max_vertical, int max_horizontal,
+ int is_tag)
{
string html_string;
char *html_glyph;
@@ -1267,10 +1416,10 @@ void page::add_and_encode (style *s, const string &str,
if (html_glyph)
html_string += html_glyph;
else {
- int index=s->f->name_to_index((troff_charname + '\0').contents());
+ int idx=s->f->name_to_index((troff_charname + '\0').contents());
- if (s->f->contains(index) && (index != 0))
- html_string += s->f->get_code(index);
+ if (s->f->contains(idx) && (idx != 0))
+ html_string += s->f->get_code(idx);
}
}
} else
@@ -1279,9 +1428,18 @@ void page::add_and_encode (style *s, const string &str,
}
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);
+ if (is_tag)
+ g->text_glob_tag(s, buffer.add_string(html_string),
+ html_string.length(),
+ min_vertical, min_horizontal,
+ max_vertical, max_horizontal);
+ else
+ 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);
}
}
@@ -1380,18 +1538,21 @@ public:
header_desc ();
~header_desc ();
- int no_of_headings; // how many headings have we found?
- char_buffer headings; // all the headings used in the document
- list headers; // list of headers built from .NH and .SH
- int header_level; // current header level
- int written_header; // have we written the header yet?
- string header_buffer; // current header text
+ int no_of_level_one_headings; // how many .SH or .NH 1 have we found?
+ int no_of_headings; // how many headings have we found?
+ char_buffer headings; // all the headings used in the document
+ list headers; // list of headers built from .NH and .SH
+ list header_filename; // in which file is this header?
+ int header_level; // current header level
+ int written_header; // have we written the header yet?
+ string header_buffer; // current header text
void write_headings (FILE *f, int force);
};
header_desc::header_desc ()
- : no_of_headings(0), header_level(2), written_header(0)
+ : no_of_level_one_headings(0), no_of_headings(0),
+ header_level(2), written_header(0)
{
}
@@ -1412,9 +1573,15 @@ void header_desc::write_headings (FILE *f, int force)
int h=1;
headers.start_from_head();
+ header_filename.start_from_head();
do {
g = headers.get_data();
- fputs("<a href=\"#", f);
+ fputs("<a href=\"", f);
+ if (multiple_files && (! header_filename.is_empty())) {
+ text_glob *fn = header_filename.get_data();
+ fputs(fn->text_string, f);
+ }
+ fputs("#", f);
if (simple_anchors) {
string buffer(ANCHOR_TEMPLATE);
@@ -1428,12 +1595,345 @@ void header_desc::write_headings (FILE *f, int force)
fputs(g->text_string, f);
fputs("</a><br>\n", f);
headers.move_right();
+ if (multiple_files && (! header_filename.is_empty()))
+ header_filename.move_right();
} while (! headers.is_equal_to_head());
fputs("\n", f);
}
}
}
+struct assert_pos {
+ assert_pos *next;
+ const char *val;
+ const char *id;
+};
+
+class assert_state {
+public:
+ assert_state ();
+ ~assert_state ();
+
+ void addx (const char *c, const char *i, const char *v,
+ const char *f, const char *l);
+ void addy (const char *c, const char *i, const char *v,
+ const char *f, const char *l);
+ void build(const char *c, const char *v,
+ const char *f, const char *l);
+ void check_br (int br);
+ void check_ce (int ce);
+ void check_fi (int fi);
+ void check_sp (int sp);
+ void reset (void);
+
+private:
+ int check_br_flag;
+ int check_ce_flag;
+ int check_fi_flag;
+ int check_sp_flag;
+ const char *val_br;
+ const char *val_ce;
+ const char *val_fi;
+ const char *val_sp;
+ const char *file_br;
+ const char *file_ce;
+ const char *file_fi;
+ const char *file_sp;
+ const char *line_br;
+ const char *line_ce;
+ const char *line_fi;
+ const char *line_sp;
+
+ assert_pos *xhead;
+ assert_pos *yhead;
+
+ void add (assert_pos **h,
+ const char *c, const char *i, const char *v,
+ const char *f, const char *l);
+ void compare(assert_pos *t,
+ const char *v, const char *f, const char *l);
+ void close (const char *c);
+ void set (const char *c, const char *v,
+ const char *f, const char *l);
+ void check_value (const char *s, int v, const char *name,
+ const char *f, const char *l, int *flag);
+ int check_value_error (int c, int v, const char *s,
+ const char *name,
+ const char *f, const char *l, int flag);
+};
+
+assert_state::assert_state ()
+{
+ reset();
+ val_br = NULL;
+ val_ce = NULL;
+ val_fi = NULL;
+ val_sp = NULL;
+ file_br = NULL;
+ file_ce = NULL;
+ file_fi = NULL;
+ file_sp = NULL;
+ line_br = NULL;
+ line_ce = NULL;
+ line_fi = NULL;
+ line_sp = NULL;
+ xhead = NULL;
+ yhead = NULL;
+}
+
+assert_state::~assert_state ()
+{
+ assert_pos *t;
+
+ while (xhead != NULL) {
+ t = xhead;
+ xhead = xhead->next;
+ a_delete (char *)t->val;
+ a_delete (char *)t->id;
+ delete t;
+ }
+ while (yhead != NULL) {
+ t = yhead;
+ yhead = yhead->next;
+ a_delete (char *)t->val;
+ a_delete (char *)t->id;
+ delete t;
+ }
+}
+
+void assert_state::reset (void)
+{
+ check_br_flag = 0;
+ check_ce_flag = 0;
+ check_fi_flag = 0;
+ check_sp_flag = 0;
+}
+
+void assert_state::add (assert_pos **h,
+ const char *c, const char *i, const char *v,
+ const char *f, const char *l)
+{
+ assert_pos *t = *h;
+
+ while (t != NULL) {
+ if (strcmp(t->id, i) == 0)
+ break;
+ t = t->next;
+ }
+ if (t != NULL && v != NULL && (v[0] != '='))
+ compare(t, v, f, l);
+ else {
+ if (t == NULL) {
+ t = new assert_pos;
+ t->next = *h;
+ (*h) = t;
+ }
+ if (v == NULL || v[0] != '=') {
+ if (f == NULL)
+ f = "stdin";
+ if (l == NULL)
+ l = "<none>";
+ if (v == NULL)
+ v = "no value at all";
+ fprintf(stderr, "%s:%s:error in assert format of id=%s expecting value to be prefixed with an `=' got %s\n",
+ f, l, i, v);
+ }
+ t->id = i;
+ t->val = v;
+ a_delete (char *)c;
+ a_delete (char *)f;
+ a_delete (char *)l;
+ }
+}
+
+void assert_state::addx (const char *c, const char *i, const char *v,
+ const char *f, const char *l)
+{
+ add(&xhead, c, i, v, f, l);
+}
+
+void assert_state::addy (const char *c, const char *i, const char *v,
+ const char *f, const char *l)
+{
+ add(&yhead, c, i, v, f, l);
+}
+
+void assert_state::compare(assert_pos *t,
+ const char *v, const char *f, const char *l)
+{
+ const char *s=t->val;
+
+ while ((*v) == '=')
+ v++;
+ while ((*s) == '=')
+ s++;
+
+ if (strcmp(v, s) != 0) {
+ if (f == NULL)
+ f = "stdin";
+ if (l == NULL)
+ l = "<none>";
+ fprintf(stderr, "%s:%s: grohtml assertion failed at id%s expecting %s and was given %s\n",
+ f, l, t->id, s, v);
+ }
+}
+
+void assert_state::close (const char *c)
+{
+ if (strcmp(c, "sp") == 0)
+ check_sp_flag = 0;
+ else if (strcmp(c, "br") == 0)
+ check_br_flag = 0;
+ else if (strcmp(c, "fi") == 0)
+ check_fi_flag = 0;
+ else if (strcmp(c, "nf") == 0)
+ check_fi_flag = 0;
+ else if (strcmp(c, "ce") == 0)
+ check_ce_flag = 0;
+ else
+ fprintf(stderr, "internal error: unrecognised tag in grohtml (%s)\n", c);
+}
+
+const char *replace_negate_str (const char *before, char *after)
+{
+ if (before != NULL)
+ a_delete (char *)before;
+
+ if (strlen(after) > 0) {
+ int d = atoi(after);
+
+ if (d < 0 || d > 1) {
+ fprintf(stderr, "expecting nf/fi value to be 0 or 1 not %d\n", d);
+ d = 0;
+ }
+ if (d == 0)
+ after[0] = '1';
+ else
+ after[0] = '0';
+ after[1] = (char)0;
+ }
+ return after;
+}
+
+const char *replace_str (const char *before, const char *after)
+{
+ if (before != NULL)
+ a_delete (char *)before;
+ return after;
+}
+
+void assert_state::set (const char *c, const char *v,
+ const char *f, const char *l)
+{
+ if (l == NULL)
+ l = "<none>";
+ if (f == NULL)
+ f = "stdin";
+
+ // fprintf(stderr, "%s:%s:setting %s to %s\n", f, l, c, v);
+ if (strcmp(c, "sp") == 0) {
+ check_sp_flag = 1;
+ val_sp = replace_str(val_sp, strsave(v));
+ file_sp = replace_str(file_sp, strsave(f));
+ line_sp = replace_str(line_sp, strsave(l));
+ } else if (strcmp(c, "br") == 0) {
+ check_br_flag = 1;
+ val_br = replace_str(val_br, strsave(v));
+ file_br = replace_str(file_br, strsave(f));
+ line_br = replace_str(line_br, strsave(l));
+ } else if (strcmp(c, "fi") == 0) {
+ check_fi_flag = 1;
+ val_fi = replace_str(val_fi, strsave(v));
+ file_fi = replace_str(file_fi, strsave(f));
+ line_fi = replace_str(line_fi, strsave(l));
+ } else if (strcmp(c, "nf") == 0) {
+ check_fi_flag = 1;
+ val_fi = replace_negate_str(val_fi, strsave(v));
+ file_fi = replace_str(file_fi, strsave(f));
+ line_fi = replace_str(line_fi, strsave(l));
+ } else if (strcmp(c, "ce") == 0) {
+ check_ce_flag = 1;
+ val_ce = replace_str(val_ce, strsave(v));
+ file_ce = replace_str(file_ce, strsave(f));
+ line_ce = replace_str(line_ce, strsave(l));
+ }
+}
+
+/*
+ * build - builds the troff state assertion.
+ * see tmac/www.tmac for cmd examples.
+ */
+
+void assert_state::build (const char *c, const char *v,
+ const char *f, const char *l)
+{
+ if (c[0] == '{')
+ set(&c[1], v, f, l);
+ if (c[0] == '}')
+ close(&c[1]);
+}
+
+int assert_state::check_value_error (int c, int v, const char *s,
+ const char *name,
+ const char *f, const char *l, int flag)
+{
+ if (! c) {
+ if (f == NULL)
+ f = "stdin";
+ if (l == NULL)
+ l = "<none>";
+ fprintf(stderr, "%s:%s:grohtml (troff state) assertion failed, expected %s to be %s but found it to contain %d\n",
+ f, l, name, s, v);
+ return 0;
+ }
+ return flag;
+}
+
+void assert_state::check_value (const char *s, int v, const char *name,
+ const char *f, const char *l, int *flag)
+{
+ if (strncmp(s, "<=", 2) == 0)
+ *flag = check_value_error(v <= atoi(&s[2]), v, s, name, f, l, *flag);
+ else if (strncmp(s, ">=", 2) == 0)
+ *flag = check_value_error(v >= atoi(&s[2]), v, s, name, f, l, *flag);
+ else if (strncmp(s, "==", 2) == 0)
+ *flag = check_value_error(v == atoi(&s[2]), v, s, name, f, l, *flag);
+ else if (strncmp(s, "!=", 2) == 0)
+ *flag = check_value_error(v != atoi(&s[2]), v, s, name, f, l, *flag);
+ else if (strncmp(s, "<", 1) == 0)
+ *flag = check_value_error(v < atoi(&s[2]), v, s, name, f, l, *flag);
+ else if (strncmp(s, ">", 1) == 0)
+ *flag = check_value_error(v > atoi(&s[2]), v, s, name, f, l, *flag);
+ else if (strncmp(s, "=", 1) == 0)
+ *flag = check_value_error(v == atoi(&s[1]), v, s, name, f, l, *flag);
+ else
+ *flag = check_value_error(v == atoi(s), v, s, name, f, l, *flag);
+}
+
+void assert_state::check_sp (int sp)
+{
+ if (check_sp_flag)
+ check_value(val_sp, sp, "sp", file_sp, line_sp, &check_sp_flag);
+}
+
+void assert_state::check_fi (int fi)
+{
+ if (check_fi_flag)
+ check_value(val_fi, fi, "fi", file_fi, line_fi, &check_fi_flag);
+}
+
+void assert_state::check_br (int br)
+{
+ if (check_br_flag)
+ check_value(val_br, br, "br", file_br, line_br, &check_br_flag);
+}
+
+void assert_state::check_ce (int ce)
+{
+ if (check_ce_flag)
+ check_value(val_ce, ce, "ce", file_ce, line_ce, &check_ce_flag);
+}
+
class html_printer : public printer {
files file_list;
simple_output html;
@@ -1477,12 +1977,26 @@ class html_printer : public printer {
int max_linelength;
int linelength;
int pageoffset;
- int indentation;
- int prev_indent;
+ int troff_indent;
+ int device_indent;
+ int temp_indent;
int pointsize;
int vertical_spacing;
int line_number;
color *background;
+ int seen_indent;
+ int next_indent;
+ int seen_pageoffset;
+ int next_pageoffset;
+ int seen_linelength;
+ int next_linelength;
+ int seen_center;
+ int next_center;
+ int seen_space;
+ int seen_break;
+ int current_column;
+ int row_space;
+ assert_state as;
void flush_sbuf ();
void set_style (const style &);
@@ -1508,15 +2022,18 @@ class html_printer : public printer {
void start_font (const char *name);
void end_font (const char *name);
int is_font_courier (font *f);
+ int is_line_start (int nf);
int is_courier_until_eol (void);
void start_size (int from, int to);
void do_font (text_glob *g);
void do_center (char *arg);
+ void do_check_center (void);
void do_break (void);
+ void do_space (char *arg);
void do_eol (void);
void do_eol_ce (void);
void do_title (void);
- void do_fill (int on);
+ void do_fill (char *arg);
void do_heading (char *arg);
void write_header (void);
void determine_header_level (int level);
@@ -1533,6 +2050,9 @@ class html_printer : public printer {
void do_auto_image (text_glob *g, const char *filename);
void do_links (void);
void do_flush (void);
+ void do_job_name (char *name);
+ void do_head (char *name);
+ void insert_split_file (void);
int is_in_middle (int left, int right);
void do_sup_or_sub (text_glob *g);
int start_subscript (text_glob *g);
@@ -1563,6 +2083,18 @@ class html_printer : public printer {
void remove_courier_tabs (void);
void update_min_max (colType type_of_col, int *minimum, int *maximum, text_glob *g);
void add_table_end (const char *);
+ void do_file_components (void);
+ void write_navigation (const string &top, const string &prev,
+ const string &next, const string &current);
+ void emit_link (const string &to, const char *name);
+ int get_troff_indent (void);
+ void restore_troff_indent (void);
+ void handle_assertion (int minv, int minh, int maxv, int maxh, const char *s);
+ void handle_state_assertion (text_glob *g);
+ void do_end_para (text_glob *g);
+ int round_width (int x);
+ void handle_tag_within_title (text_glob *g);
+ void writeHeadMetaStyle (void);
// ADD HERE
public:
@@ -1570,10 +2102,13 @@ public:
~html_printer ();
void set_char (int i, font *f, const environment *env, int w, const char *name);
void set_numbered_char(int num, const environment *env, int *widthp);
+ int set_char_and_width(const char *nm, const environment *env,
+ int *widthp, font **f);
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);
+ void devtag (char *arg, const environment *env, char type);
font *make_font (const char *);
void end_of_line ();
};
@@ -1640,6 +2175,24 @@ void html_printer::emit_line (text_glob *)
}
/*
+ * restore_troff_indent - is called when we have temporarily shutdown
+ * indentation (typically done when we have
+ * centered an image).
+ */
+
+void html_printer::restore_troff_indent (void)
+{
+ troff_indent = next_indent;
+ if (troff_indent > 0) {
+ /*
+ * force device indentation
+ */
+ device_indent = 0;
+ do_indent(get_troff_indent(), pageoffset, linelength);
+ }
+}
+
+/*
* emit_raw - writes the raw html information directly to the device.
*/
@@ -1650,17 +2203,20 @@ void html_printer::emit_raw (text_glob *g)
determine_space(g);
current_paragraph->do_emittext(g->text_string, g->text_length);
} else {
+ int space = current_paragraph->retrieve_para_space() || seen_space;
+
current_paragraph->done_para();
+ shutdown_table();
switch (next_tag) {
case CENTERED:
- current_paragraph->do_para("align=center");
+ current_paragraph->do_para("align=center", space);
break;
case LEFT:
- current_paragraph->do_para(&html, "align=left", indentation, pageoffset, linelength);
+ current_paragraph->do_para(&html, "align=left", get_troff_indent(), pageoffset, linelength, space);
break;
case RIGHT:
- current_paragraph->do_para(&html, "align=right", indentation, pageoffset, linelength);
+ current_paragraph->do_para(&html, "align=right", get_troff_indent(), pageoffset, linelength, space);
break;
default:
fatal("unknown enumeration");
@@ -1669,39 +2225,37 @@ void html_printer::emit_raw (text_glob *g)
current_paragraph->done_para();
next_tag = INLINE;
supress_sub_sup = TRUE;
- if (indentation > 0) {
- /*
- * restore indentation
- */
- int newin = indentation;
- indentation = 0;
- do_indent(newin, pageoffset, linelength);
- }
+ seen_space = FALSE;
+ restore_troff_indent();
}
}
/*
+ * handle_tag_within_title - handle a limited number of tags within
+ * the context of a table. Those tags which
+ * set values rather than generate spaces
+ * and paragraphs.
+ */
+
+void html_printer::handle_tag_within_title (text_glob *g)
+{
+ if (g->is_in() || g->is_ti() || g->is_po() || g->is_ce() || g->is_ll()
+ || g->is_fi() || g->is_nf())
+ troff_tag(g);
+}
+
+/*
* do_center - handle the .ce commands from troff.
*/
void html_printer::do_center (char *arg)
{
- int n = atoi(arg);
- current_paragraph->do_break();
-
- if (n > 0) {
- current_paragraph->done_para();
- supress_sub_sup = TRUE;
- current_paragraph->do_para("align=center");
- end_center += n;
- } else {
- end_center = 0;
- current_paragraph->remove_para_align();
- }
+ next_center = atoi(arg);
+ seen_center = TRUE;
}
/*
- * do_centered_image - set a flag such that the next html-tag is
+ * do_centered_image - set a flag such that the next devtag is
* placed inside a centered paragraph.
*/
@@ -1711,7 +2265,7 @@ void html_printer::do_centered_image (void)
}
/*
- * do_right_image - set a flag such that the next html-tag is
+ * do_right_image - set a flag such that the next devtag is
* placed inside a right aligned paragraph.
*/
@@ -1721,7 +2275,7 @@ void html_printer::do_right_image (void)
}
/*
- * do_left_image - set a flag such that the next html-tag is
+ * do_left_image - set a flag such that the next devtag is
* placed inside a left aligned paragraph.
*/
@@ -1759,7 +2313,8 @@ static string &generate_img_src (const char *filename)
filename++;
}
if (exists(filename))
- *s += string("<img src=\"") + filename + "\">";
+ *s += string("<img src=\"") + filename + "\" "
+ + "alt=\"Image " + filename + "\">";
return *s;
}
@@ -1808,7 +2363,6 @@ void html_printer::do_title (void)
{
text_glob *t;
int removed_from_head;
- int eol_ce = 0;
if (page_number == 1) {
int found_title_start = FALSE;
@@ -1830,24 +2384,16 @@ void html_printer::do_title (void)
page_contents->glyphs.sub_move_right(); /* move onto next word */
removed_from_head = ((!page_contents->glyphs.is_empty()) &&
(page_contents->glyphs.is_equal_to_head()));
- } else if (t->is_eol_ce()) {
- /* process the eol associated with .ce
- */
- eol_ce++;
- page_contents->glyphs.sub_move_right(); /* move onto next word */
- } else if (t->is_eol()) {
+ } else if (t->is_eo_tl()) {
/* 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;
+ handle_tag_within_title(t);
+ 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 (found_title_start) {
title.text += " " + string(t->text_string, t->text_length);
page_contents->glyphs.sub_move_right(); /* move onto next word */
@@ -1861,15 +2407,17 @@ void html_printer::do_title (void)
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));
+ } while ((! page_contents->glyphs.is_equal_to_head()) ||
+ (removed_from_head));
}
- outstanding_eol(eol_ce);
}
}
void html_printer::write_header (void)
{
if (! header.header_buffer.empty()) {
+ int space = current_paragraph->retrieve_para_space() || seen_space;
+
if (header.header_level > 7) {
header.header_level = 7;
}
@@ -1897,7 +2445,7 @@ void html_printer::write_header (void)
// lastly we generate a tag
- html.nl().put_string("<a name=\"");
+ html.nl().nl().put_string("<a name=\"");
if (simple_anchors) {
string buffer(ANCHOR_TEMPLATE);
@@ -1937,7 +2485,23 @@ void html_printer::write_header (void)
html.put_string(">").nl();
}
- current_paragraph->do_para(&html, "", indentation, pageoffset, linelength);
+ /* and now we save the file name in which this header will occur */
+
+ style st; // fake style to enable us to use the list data structure
+
+ text_glob *h=new text_glob();
+ h->text_glob_html(&st,
+ header.headings.add_string(file_list.file_name()),
+ file_list.file_name().length(),
+ header.no_of_headings, header.header_level,
+ header.no_of_headings, header.header_level);
+
+ header.header_filename.add(h,
+ header.no_of_headings,
+ header.no_of_headings, header.no_of_headings,
+ header.no_of_headings, header.no_of_headings);
+
+ current_paragraph->do_para(&html, "", get_troff_indent(), pageoffset, linelength, space);
}
}
@@ -1955,6 +2519,10 @@ void html_printer::determine_header_level (int level)
}
}
header.header_level = level+1;
+ if (header.header_level >= 2 && header.header_level <= split_level) {
+ header.no_of_level_one_headings++;
+ insert_split_file();
+ }
}
/*
@@ -1964,39 +2532,46 @@ void html_printer::determine_header_level (int level)
void html_printer::do_heading (char *arg)
{
text_glob *g;
- text_glob *l = 0;
int level=atoi(arg);
+ int horiz;
header.header_buffer.clear();
page_contents->glyphs.move_right();
if (! page_contents->glyphs.is_equal_to_head()) {
g = page_contents->glyphs.get_data();
+ horiz = g->minh;
do {
if (g->is_auto_img()) {
string img=generate_img_src((char *)(g->text_string + 20));
if (! img.empty()) {
simple_anchors = TRUE; // we cannot use full heading anchors with images
- if (l != 0)
+ if (horiz < g->minh)
header.header_buffer += " ";
- l = g;
header.header_buffer += img;
}
- } else if (! (g->is_a_line() || g->is_a_tag())) {
+ }
+ else if (g->is_in() || g->is_ti() || g->is_po() || g->is_ce() || g->is_ll())
+ troff_tag(g);
+ else if (g->is_fi())
+ fill_on = 1;
+ else if (g->is_nf())
+ fill_on = 0;
+ else if (! (g->is_a_line() || g->is_a_tag())) {
/*
- * we ignore tags commands when constructing a heading
+ * we ignore the other tag commands when constructing a heading
*/
- if (l != 0)
+ if (horiz < g->minh)
header.header_buffer += " ";
- l = g;
+ horiz = g->maxh;
header.header_buffer += string(g->text_string, g->text_length);
}
page_contents->glyphs.move_right();
g = page_contents->glyphs.get_data();
} while ((! page_contents->glyphs.is_equal_to_head()) &&
- (! g->is_br()));
+ (! g->is_eo_h()));
}
determine_header_level(level);
@@ -2046,8 +2621,8 @@ void html_printer::do_linelength (char *arg)
if (max_linelength == -1)
max_linelength = atoi(arg);
- if (fill_on)
- do_indent(indentation, pageoffset, atoi(arg));
+ next_linelength = atoi(arg);
+ seen_linelength = TRUE;
}
/*
@@ -2056,8 +2631,20 @@ void html_printer::do_linelength (char *arg)
void html_printer::do_pageoffset (char *arg)
{
- if (fill_on)
- do_indent(indentation, atoi(arg), linelength);
+ next_pageoffset = atoi(arg);
+ seen_pageoffset = TRUE;
+}
+
+/*
+ * get_troff_indent - returns the indent value.
+ */
+
+int html_printer::get_troff_indent (void)
+{
+ if (end_tempindent > 0)
+ return temp_indent;
+ else
+ return troff_indent;
}
/*
@@ -2066,8 +2653,8 @@ void html_printer::do_pageoffset (char *arg)
void html_printer::do_indentation (char *arg)
{
- if (fill_on)
- do_indent(atoi(arg), pageoffset, linelength);
+ next_indent = atoi(arg);
+ seen_indent = TRUE;
}
/*
@@ -2077,9 +2664,12 @@ void html_printer::do_indentation (char *arg)
void html_printer::do_tempindent (char *arg)
{
if (fill_on) {
- end_tempindent = 1;
- prev_indent = indentation;
- do_indent(atoi(arg), pageoffset, linelength);
+ /*
+ * we set the end_tempindent to 2 as the first .br
+ * activates the .ti and the second terminates it.
+ */
+ end_tempindent = 2;
+ temp_indent = atoi(arg);
}
}
@@ -2105,17 +2695,19 @@ void html_printer::shutdown_table (void)
void html_printer::do_indent (int in, int pageoff, int linelen)
{
- if ((indentation != -1) &&
- (pageoffset+indentation != in+pageoff)) {
-
+ if ((device_indent != -1) &&
+ (pageoffset+device_indent != in+pageoff)) {
+
+ int space = current_paragraph->retrieve_para_space() || seen_space;
current_paragraph->done_para();
- indentation = in;
+ device_indent = in;
pageoffset = pageoff;
if (linelen <= max_linelength)
linelength = linelen;
- current_paragraph->do_para(&html, "", indentation, pageoffset, max_linelength);
+ current_paragraph->do_para(&html, "", device_indent,
+ pageoffset, max_linelength, space);
}
}
@@ -2134,24 +2726,56 @@ void html_printer::do_verticalspacing (char *arg)
void html_printer::do_pointsize (char *arg)
{
- pointsize = atoi(arg);
+ /*
+ * firstly check to see whether this point size is really associated with a .tl tag
+ */
+
+ if (! page_contents->glyphs.is_empty()) {
+ text_glob *g = page_contents->glyphs.get_data();
+ text_glob *t = page_contents->glyphs.get_data();
+
+ while (t->is_a_tag() && (! page_contents->glyphs.is_equal_to_head())) {
+ if (t->is_tl()) {
+ /*
+ * found title therefore ignore this .ps tag
+ */
+ while (t != g) {
+ page_contents->glyphs.move_left();
+ t = page_contents->glyphs.get_data();
+ }
+ return;
+ }
+ page_contents->glyphs.move_right();
+ t = page_contents->glyphs.get_data();
+ }
+ /*
+ * move back to original position
+ */
+ while (t != g) {
+ page_contents->glyphs.move_left();
+ t = page_contents->glyphs.get_data();
+ }
+ /*
+ * collect legal pointsize
+ */
+ pointsize = atoi(arg);
+ }
}
/*
* do_fill - records whether troff has requested that text be filled.
*/
-void html_printer::do_fill (int on)
+void html_printer::do_fill (char *arg)
{
- current_paragraph->do_break();
- output_hpos = indentation+pageoffset;
+ int on = atoi(arg);
+
+ output_hpos = get_troff_indent()+pageoffset;
supress_sub_sup = TRUE;
if (fill_on != on) {
if (on)
- current_paragraph->do_para("");
- else
- current_paragraph->do_pre();
+ current_paragraph->do_para("", seen_space);
fill_on = on;
}
}
@@ -2168,7 +2792,53 @@ void html_printer::do_eol (void)
current_paragraph->do_break();
}
}
- output_hpos = indentation+pageoffset;
+ output_hpos = get_troff_indent()+pageoffset;
+}
+
+/*
+ * do_check_center - checks to see whether we have seen a `.ce' tag
+ * during the previous line.
+ */
+
+void html_printer::do_check_center(void)
+{
+ if (seen_center) {
+ seen_center = FALSE;
+ if (next_center > 0) {
+ if (end_center == 0) {
+ int space = current_paragraph->retrieve_para_space() || seen_space;
+ current_paragraph->done_para();
+ supress_sub_sup = TRUE;
+ current_paragraph->do_para("align=center", space);
+ } else
+ if (strcmp("align=center",
+ current_paragraph->get_alignment()) != 0) {
+ /*
+ * different alignment, so shutdown paragraph and open
+ * a new one.
+ */
+ int space = current_paragraph->retrieve_para_space() || seen_space;
+ current_paragraph->done_para();
+ supress_sub_sup = TRUE;
+ current_paragraph->do_para("align=center", space);
+ } else
+ /*
+ * same alignment, if we have emitted text then issue a break.
+ */
+ if (current_paragraph->emitted_text())
+ current_paragraph->do_break();
+ } else
+ /*
+ * next_center == 0
+ */
+ if (end_center > 0) {
+ seen_space = seen_space || current_paragraph->retrieve_para_space();
+ current_paragraph->done_para();
+ supress_sub_sup = TRUE;
+ current_paragraph->do_para("", seen_space);
+ }
+ end_center = next_center;
+ }
}
/*
@@ -2205,26 +2875,110 @@ void html_printer::do_flush (void)
void html_printer::do_links (void)
{
- current_paragraph->done_para();
+ html.end_line(); // flush line
auto_links = FALSE; /* from now on only emit under user request */
file_list.add_new_file(xtmpfile());
+ file_list.set_links_required();
html.set_file(file_list.get_file());
}
/*
+ * insert_split_file -
+ */
+
+void html_printer::insert_split_file (void)
+{
+ if (multiple_files) {
+ current_paragraph->done_para(); // flush paragraph
+ html.end_line(); // flush line
+ html.set_file(file_list.get_file()); // flush current file
+ file_list.add_new_file(xtmpfile());
+ string split_file = job_name;
+
+ split_file += string("-");
+ split_file += as_string(header.no_of_level_one_headings);
+ split_file += string(".html");
+ split_file += '\0';
+
+ file_list.set_file_name(split_file);
+ html.set_file(file_list.get_file());
+ }
+}
+
+/*
+ * do_job_name - assigns the job_name to name.
+ */
+
+void html_printer::do_job_name (char *name)
+{
+ if (! multiple_files) {
+ multiple_files = TRUE;
+ while (name != NULL && (*name != (char)0) && (*name == ' '))
+ name++;
+ job_name = name;
+ }
+}
+
+/*
+ * do_head - adds a string to head_info which is to be included into
+ * the <head> </head> section of the html document.
+ */
+
+void html_printer::do_head (char *name)
+{
+ head_info += string(name);
+ head_info += '\n';
+}
+
+/*
* do_break - handles the ".br" request and also
- * undoes an outstanding ".ti" command.
+ * undoes an outstanding ".ti" command
+ * and calls indent if the indentation
+ * related registers have changed.
*/
void html_printer::do_break (void)
{
+ int seen_temp_indent = FALSE;
+
current_paragraph->do_break();
if (end_tempindent > 0) {
end_tempindent--;
- if (end_tempindent == 0)
- do_indent(prev_indent, pageoffset, linelength);
+ if (end_tempindent > 0)
+ seen_temp_indent = TRUE;
+ }
+ if (seen_indent || seen_pageoffset || seen_linelength || seen_temp_indent) {
+ if (seen_indent && (! seen_temp_indent))
+ troff_indent = next_indent;
+ if (! seen_pageoffset)
+ next_pageoffset = pageoffset;
+ if (! seen_linelength)
+ next_linelength = linelength;
+ do_indent(get_troff_indent(), next_pageoffset, next_linelength);
+ }
+ seen_indent = seen_temp_indent;
+ seen_linelength = FALSE;
+ seen_pageoffset = FALSE;
+ do_check_center();
+ output_hpos = get_troff_indent()+pageoffset;
+ supress_sub_sup = TRUE;
+}
+
+void html_printer::do_space (char *arg)
+{
+ int n = atoi(arg);
+
+ seen_space = atoi(arg);
+ as.check_sp(seen_space);
+#if 0
+ if (n>0 && table)
+ table->set_space(TRUE);
+#endif
+
+ while (n>0) {
+ current_paragraph->do_space();
+ n--;
}
- output_hpos = indentation+pageoffset;
supress_sub_sup = TRUE;
}
@@ -2237,14 +2991,24 @@ void html_printer::do_tab_ts (text_glob *g)
html_table *t = g->get_table();
if (t != NULL) {
+ current_column = 0;
current_paragraph->done_pre();
current_paragraph->done_para();
+ current_paragraph->remove_para_space();
+#if defined(DEBUG_TABLES)
html.simple_comment("TABS");
+#endif
t->set_linelength(max_linelength);
t->add_indent(pageoffset);
+#if 0
+ t->emit_table_header(seen_space);
+#else
t->emit_table_header(FALSE);
+ row_space = current_paragraph->retrieve_para_space() || seen_space;
+ seen_space = FALSE;
+#endif
}
table = t;
@@ -2258,23 +3022,16 @@ void html_printer::do_tab_te (void)
{
if (table) {
current_paragraph->done_para();
+ current_paragraph->remove_para_space();
table->emit_finish_table();
}
table = NULL;
-
- if (indentation > 0) {
- /*
- * restore indentation
- */
- int newin = indentation;
- indentation = 0;
- do_indent(newin, pageoffset, linelength);
- }
+ restore_troff_indent();
}
/*
- * do_tab - handle the "html-tag:tab" tag
+ * do_tab - handle the "devtag:tab" tag
*/
void html_printer::do_tab (char *s)
@@ -2283,7 +3040,7 @@ void html_printer::do_tab (char *s)
while (isspace(*s))
s++;
s++;
- int col = table->find_column(atoi(s) + pageoffset + indentation);
+ int col = table->find_column(atoi(s) + pageoffset + get_troff_indent());
if (col > 0) {
current_paragraph->done_para();
table->emit_col(col);
@@ -2292,13 +3049,13 @@ void html_printer::do_tab (char *s)
}
/*
- * do_tab0 - handle the "html-tag:tab0" tag
+ * do_tab0 - handle the "devtag:tab0" tag
*/
void html_printer::do_tab0 (void)
{
if (table) {
- int col = table->find_column(pageoffset+indentation);
+ int col = table->find_column(pageoffset+get_troff_indent());
if (col > 0) {
current_paragraph->done_para();
table->emit_col(col);
@@ -2313,33 +3070,40 @@ void html_printer::do_tab0 (void)
void html_printer::do_col (char *s)
{
if (table) {
+ if (atoi(s) < current_column)
+ row_space = seen_space;
+
+ current_column = atoi(s);
current_paragraph->done_para();
- table->emit_col(atoi(s));
+ table->emit_col(current_column);
+ current_paragraph->do_para("", row_space);
}
}
/*
- * troff_tag - processes the troff tag and manipulates the troff state machine.
+ * troff_tag - processes the troff tag and manipulates the troff
+ * state machine.
*/
void html_printer::troff_tag (text_glob *g)
{
/*
- * firstly skip over html-tag:
+ * firstly skip over devtag:
*/
- char *t=(char *)g->text_string+9;
+ char *t=(char *)g->text_string+strlen("devtag:");
- if (g->is_eol()) {
+ if (strncmp(g->text_string, "html</p>:", strlen("html</p>:")) == 0) {
+ do_end_para(g);
+ } else if (g->is_eol()) {
do_eol();
} else if (g->is_eol_ce()) {
do_eol_ce();
} else if (strncmp(t, ".sp", 3) == 0) {
- if (g->get_arg() > 0)
- current_paragraph->do_space();
- else
- current_paragraph->do_break();
- supress_sub_sup = TRUE;
+ char *a = (char *)t+3;
+ do_space(a);
} else if (strncmp(t, ".br", 3) == 0) {
+ seen_break = 1;
+ as.check_br(1);
do_break();
} else if (strcmp(t, ".centered-image") == 0) {
do_centered_image();
@@ -2354,7 +3118,7 @@ void html_printer::troff_tag (text_glob *g)
char *a = (char *)t+3;
supress_sub_sup = TRUE;
do_center(a);
- } else if (strncmp(t, ".tl", 3) == 0) {
+ } else if (g->is_tl()) {
supress_sub_sup = TRUE;
title.with_h1 = TRUE;
do_title();
@@ -2363,9 +3127,8 @@ void html_printer::troff_tag (text_glob *g)
title.with_h1 = FALSE;
do_title();
} else if (strncmp(t, ".fi", 3) == 0) {
- do_fill(TRUE);
- } else if (strncmp(t, ".nf", 3) == 0) {
- do_fill(FALSE);
+ char *a = (char *)t+3;
+ do_fill(a);
} else if ((strncmp(t, ".SH", 3) == 0) || (strncmp(t, ".NH", 3) == 0)) {
char *a = (char *)t+3;
do_heading(a);
@@ -2389,6 +3152,12 @@ void html_printer::troff_tag (text_glob *g)
do_pointsize(a);
} else if (strcmp(t, ".links") == 0) {
do_links();
+ } else if (strncmp(t, ".job-name", 9) == 0) {
+ char *a = (char *)t+9;
+ do_job_name(a);
+ } else if (strncmp(t, ".head", 5) == 0) {
+ char *a = (char *)t+5;
+ do_head(a);
} else if (strcmp(t, ".no-auto-rule") == 0) {
auto_rule = FALSE;
} else if (strcmp(t, ".tab-ts") == 0) {
@@ -2412,7 +3181,8 @@ void html_printer::troff_tag (text_glob *g)
int html_printer::is_in_middle (int left, int right)
{
- return( abs(abs(left-pageoffset) - abs(pageoffset+linelength-right)) <= CENTER_TOLERANCE );
+ return( abs(abs(left-pageoffset) - abs(pageoffset+linelength-right))
+ <= CENTER_TOLERANCE );
}
/*
@@ -2427,17 +3197,31 @@ void html_printer::flush_globs (void)
page_contents->glyphs.start_from_head();
do {
g = page_contents->glyphs.get_data();
+#if 0
+ fprintf(stderr, "[%s:%d:%d:%d:%d]",
+ g->text_string, g->minv, g->minh, g->maxv, g->maxh) ;
+ fflush(stderr);
+#endif
+
+ handle_state_assertion(g);
if (strcmp(g->text_string, "XXXXXXX") == 0)
stop();
- if (g->is_a_tag()) {
+ if (g->is_a_tag())
troff_tag(g);
- } else if (g->is_a_line()) {
+ else if (g->is_a_line())
emit_line(g);
- } else {
+ else {
+ as.check_sp(seen_space);
+ as.check_br(seen_break);
+ seen_break = 0;
+ seen_space = 0;
emit_html(g);
}
+
+ as.check_fi(fill_on);
+ as.check_ce(end_center);
/*
* after processing the title (and removing it) the glyph list might be empty
*/
@@ -2456,11 +3240,16 @@ void html_printer::flush_globs (void)
int html_printer::calc_nf (text_glob *g, int nf)
{
if (g != NULL) {
- if (g->is_fi())
+ if (g->is_fi()) {
+ as.check_fi(TRUE);
return FALSE;
- if (g->is_nf())
+ }
+ if (g->is_nf()) {
+ as.check_fi(FALSE);
return TRUE;
+ }
}
+ as.check_fi(! nf);
return nf;
}
@@ -2471,16 +3260,15 @@ int html_printer::calc_nf (text_glob *g, int nf)
void html_printer::calc_po_in (text_glob *g, int nf)
{
if (g->is_in())
- indentation = g->get_arg();
+ troff_indent = 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;
+ temp_indent = g->get_arg();
+ end_tempindent = 2;
+ } else if (g->is_br() || (nf && g->is_eol())) {
+ if (end_tempindent > 0)
+ end_tempindent--;
}
}
@@ -2491,13 +3279,15 @@ void html_printer::calc_po_in (text_glob *g, int nf)
int html_printer::next_horiz_pos (text_glob *g, int nf)
{
- int next = -1;
+ 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)
+ if (g == NULL) {
page_contents->glyphs.start_from_head();
+ as.reset();
+ }
else {
next = g->minh;
page_contents->glyphs.move_left();
@@ -2517,7 +3307,7 @@ text_glob *html_printer::insert_tab_ts (text_glob *where)
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->insert_tag(string("devtag:.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);
@@ -2537,7 +3327,7 @@ void html_printer::insert_tab_te (void)
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
+ page_contents->insert_tag(string("devtag:.tab-te")); // tab table end
while (g != page_contents->glyphs.get_data())
page_contents->glyphs.move_right();
page_contents->dump_page();
@@ -2553,7 +3343,7 @@ void html_printer::insert_tab_0 (text_glob *where)
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->insert_tag(string("devtag:tab0")); // tab0 start of line
page_contents->glyphs.move_right();
page_contents->glyphs.move_to(old_pos);
}
@@ -2595,10 +3385,11 @@ void html_printer::remove_courier_tabs (void)
if (! page_contents->glyphs.is_empty()) {
page_contents->glyphs.start_from_head();
+ as.reset();
line_start = TRUE;
do {
g = page_contents->glyphs.get_data();
-
+ handle_state_assertion(g);
nf = calc_nf(g, nf);
if (line_start) {
@@ -2608,7 +3399,8 @@ void html_printer::remove_courier_tabs (void)
}
}
- line_start = g->is_br() || g->is_nf() || g->is_fi() || (nf && g->is_eol());
+ // line_start = g->is_br() || g->is_nf() || g->is_fi() || (nf && g->is_eol());
+ line_start = g->is_br() || (nf && g->is_eol());
page_contents->glyphs.move_right();
} while (! page_contents->glyphs.is_equal_to_head());
}
@@ -2624,10 +3416,11 @@ void html_printer::insert_tab0_foreach_tab (void)
if (! page_contents->glyphs.is_empty()) {
page_contents->glyphs.start_from_head();
+ as.reset();
start_of_line = page_contents->glyphs.get_data();
do {
g = page_contents->glyphs.get_data();
-
+ handle_state_assertion(g);
nf = calc_nf(g, nf);
if (g->is_tab())
@@ -2640,6 +3433,7 @@ void html_printer::insert_tab0_foreach_tab (void)
do {
page_contents->glyphs.move_right();
g = page_contents->glyphs.get_data();
+ handle_state_assertion(g);
nf = calc_nf(g, nf);
if (page_contents->glyphs.is_equal_to_head()) {
if (seen_tab && !seen_col)
@@ -2707,7 +3501,8 @@ void html_printer::add_table_end (const char *
}
/*
- * lookahead_for_tables - checks for .col tags and inserts table start/end tags
+ * lookahead_for_tables - checks for .col tags and inserts table
+ * start/end tags
*/
void html_printer::lookahead_for_tables (void)
@@ -2721,9 +3516,9 @@ void html_printer::lookahead_for_tables (void)
int found_col = FALSE;
int seen_text = FALSE;
int ncol = 0;
- int colmin;
- int colmax;
- html_table *table = new html_table(&html, -1);
+ int colmin = 0; // pacify compiler
+ int colmax = 0; // pacify compiler
+ html_table *tbl = new html_table(&html, -1);
const char *tab_defs = NULL;
char align = 'L';
int nf = FALSE;
@@ -2735,7 +3530,28 @@ void html_printer::lookahead_for_tables (void)
page_contents->dump_page();
if (! page_contents->glyphs.is_empty()) {
page_contents->glyphs.start_from_head();
+ as.reset();
g = page_contents->glyphs.get_data();
+ if (g->is_br()) {
+ g = page_contents->glyphs.move_right_get_data();
+ handle_state_assertion(g);
+ if (page_contents->glyphs.is_equal_to_head()) {
+ if (tbl != NULL) {
+ delete tbl;
+ tbl = NULL;
+ }
+ return;
+ }
+
+ start_of_line = g;
+ seen_text = FALSE;
+ ncol = 0;
+ left = next_horiz_pos(g, nf);
+ if (found_col)
+ last = g;
+ found_col = FALSE;
+ }
+
do {
#if defined(DEBUG_TABLES)
fprintf(stderr, " [") ;
@@ -2752,11 +3568,11 @@ void html_printer::lookahead_for_tables (void)
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);
+ start_of_table->remember_table(tbl);
+ tbl = new html_table(&html, -1);
page_contents->insert_tag(string("*** TAB -> COL ***"));
if (tab_defs != NULL)
- table->tab_stops->init(tab_defs);
+ tbl->tab_stops->init(tab_defs);
start_of_table = NULL;
last = NULL;
}
@@ -2770,28 +3586,28 @@ void html_printer::lookahead_for_tables (void)
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);
+ ncol = tbl->find_tab_column(colmin);
+ colmin += pageoffset + get_troff_indent();
+ colmax = tbl->get_tab_pos(ncol+1);
if (colmax > 0)
- colmax += pageoffset + indentation;
+ colmax += pageoffset + get_troff_indent();
} 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);
+ start_of_table->remember_table(tbl);
+ tbl = 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);
+ tbl->tab_stops->init(tab_defs);
type_of_col = tab0_tag;
ncol = 1;
colmin = 0;
- colmax = table->get_tab_pos(2) + pageoffset + indentation;
+ colmax = tbl->get_tab_pos(2) + pageoffset + get_troff_indent();
} else if (! g->is_a_tag())
update_min_max(type_of_col, &colmin, &colmax, g);
@@ -2805,34 +3621,39 @@ void html_printer::lookahead_for_tables (void)
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->remember_table(tbl);
+ tbl = new html_table(&html, -1);
start_of_table = NULL;
last = NULL;
} else if (g->is_ta()) {
tab_defs = g->text_string;
- if (!table->tab_stops->compatible(tab_defs)) {
+
+ if (type_of_col == col_tag)
+ tbl->tab_stops->check_init(tab_defs);
+
+ if (!tbl->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->remember_table(tbl);
+ tbl = new html_table(&html, -1);
start_of_table = NULL;
type_of_col = none;
last = NULL;
}
- table->tab_stops->init(tab_defs);
+ tbl->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) || (! tbl->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->remember_table(tbl);
+ tbl = new html_table(&html, -1);
start_of_table = NULL;
type_of_col = none;
last = NULL;
@@ -2843,16 +3664,19 @@ void html_printer::lookahead_for_tables (void)
* move onto next glob, check whether we are starting a new line
*/
g = page_contents->glyphs.move_right_get_data();
+ handle_state_assertion(g);
if (g == NULL) {
if (found_col) {
page_contents->glyphs.start_from_head();
+ as.reset();
last = g;
found_col = FALSE;
}
} else if (g->is_br() || (nf && g->is_eol())) {
do {
g = page_contents->glyphs.move_right_get_data();
+ handle_state_assertion(g);
nf = calc_nf(g, nf);
} while ((g != NULL) && (g->is_br() || (nf && g->is_eol())));
start_of_line = g;
@@ -2876,18 +3700,20 @@ void html_printer::lookahead_for_tables (void)
page_contents->glyphs.move_left();
insert_tab_te();
- start_of_table->remember_table(table);
- table = NULL;
+ start_of_table->remember_table(tbl);
+ tbl = NULL;
page_contents->insert_tag(string("*** LAST ***"));
}
}
- if (table != NULL)
- delete table;
+ if (tbl != NULL) {
+ delete tbl;
+ tbl = NULL;
+ }
// and reset the registers
pageoffset = old_pageoffset;
- indentation = 0;
- prev_indent = 0;
+ troff_indent = 0;
+ temp_indent = 0;
end_tempindent = 0;
}
@@ -2935,6 +3761,37 @@ void html_printer::determine_space (text_glob *g)
}
/*
+ * is_line_start - returns TRUE if we are at the start of a line.
+ */
+
+int html_printer::is_line_start (int nf)
+{
+ int line_start = FALSE;
+ int result = TRUE;
+ text_glob *orig = page_contents->glyphs.get_data();
+ text_glob *g;
+
+ if (! page_contents->glyphs.is_equal_to_head()) {
+ do {
+ page_contents->glyphs.move_left();
+ g = page_contents->glyphs.get_data();
+ result = g->is_a_tag();
+ if (g->is_fi())
+ nf = FALSE;
+ else if (g->is_nf())
+ nf = TRUE;
+ line_start = g->is_col() || g->is_br() || (nf && g->is_eol());
+ } while ((!line_start) && (result));
+ /*
+ * now restore our previous position.
+ */
+ while (page_contents->glyphs.get_data() != orig)
+ page_contents->glyphs.move_right();
+ }
+ return result;
+}
+
+/*
* is_font_courier - returns TRUE if the font, f, is courier.
*/
@@ -2945,7 +3802,7 @@ int html_printer::is_font_courier (font *f)
return( (fontname != 0) && (fontname[0] == 'C') );
}
- return( FALSE );
+ return FALSE;
}
/*
@@ -2994,24 +3851,28 @@ void html_printer::start_font (const char *fontname)
current_paragraph->do_bold();
current_paragraph->do_italic();
} else if (strcmp(fontname, "CR") == 0) {
- if ((! fill_on) && (is_courier_until_eol())) {
+ if ((! fill_on) && (is_courier_until_eol()) &&
+ is_line_start(! fill_on)) {
current_paragraph->do_pre();
}
current_paragraph->do_tt();
} else if (strcmp(fontname, "CI") == 0) {
- if ((! fill_on) && (is_courier_until_eol())) {
+ if ((! fill_on) && (is_courier_until_eol()) &&
+ is_line_start(! fill_on)) {
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())) {
+ if ((! fill_on) && (is_courier_until_eol()) &&
+ is_line_start(! fill_on)) {
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())) {
+ if ((! fill_on) && (is_courier_until_eol()) &&
+ is_line_start(! fill_on)) {
current_paragraph->do_pre();
}
current_paragraph->do_tt();
@@ -3164,6 +4025,23 @@ void html_printer::do_sup_or_sub (text_glob *g)
}
/*
+ * do_end_para - writes out the html text after shutting down the
+ * current paragraph.
+ */
+
+void html_printer::do_end_para (text_glob *g)
+{
+ do_font(g);
+ current_paragraph->done_para();
+ current_paragraph->remove_para_space();
+ html.put_string(g->text_string+9);
+ output_vpos = g->minv;
+ output_hpos = g->maxh;
+ output_vpos_max = g->maxv;
+ supress_sub_sup = FALSE;
+}
+
+/*
* emit_html - write out the html text
*/
@@ -3187,6 +4065,7 @@ void html_printer::flush_sbuf()
if (sbuf.length() > 0) {
int r=font::res; // resolution of the device
set_style(sbuf_style);
+
if (overstrike_detected && (! is_bold(sbuf_style.f))) {
font *bold_font = make_bold(sbuf_style.f);
if (bold_font != NULL)
@@ -3297,11 +4176,24 @@ html_printer::html_printer()
max_linelength(-1),
linelength(0),
pageoffset(0),
- indentation(0),
- prev_indent(0),
- pointsize(0),
+ troff_indent(0),
+ device_indent(0),
+ temp_indent(0),
+ pointsize(base_point_size),
line_number(0),
- background(default_background)
+ background(default_background),
+ seen_indent(FALSE),
+ next_indent(0),
+ seen_pageoffset(FALSE),
+ next_pageoffset(0),
+ seen_linelength(FALSE),
+ next_linelength(0),
+ seen_center(FALSE),
+ next_center(0),
+ seen_space(0),
+ seen_break(0),
+ current_column(0),
+ row_space(FALSE)
{
file_list.add_new_file(xtmpfile());
html.set_file(file_list.get_file());
@@ -3336,17 +4228,17 @@ html_printer::html_printer()
* add_to_sbuf - adds character code or name to the sbuf.
*/
-void html_printer::add_to_sbuf (int index, const string &s)
+void html_printer::add_to_sbuf (int idx, const string &s)
{
if (sbuf_style.f == NULL)
return;
char *html_glyph = NULL;
- unsigned int code = sbuf_style.f->get_code(index);
+ unsigned int code = sbuf_style.f->get_code(idx);
if (s.empty()) {
- if (sbuf_style.f->contains(index))
- html_glyph = (char *)sbuf_style.f->get_special_device_encoding(index);
+ if (sbuf_style.f->contains(idx))
+ html_glyph = (char *)sbuf_style.f->get_special_device_encoding(idx);
else
html_glyph = NULL;
@@ -3362,7 +4254,7 @@ void html_printer::add_to_sbuf (int index, const string &s)
sbuf += html_glyph;
}
-int html_printer::sbuf_continuation (int index, const char *name,
+int html_printer::sbuf_continuation (int idx, const char *name,
const environment *env, int w)
{
/*
@@ -3372,7 +4264,7 @@ int html_printer::sbuf_continuation (int index, const char *name,
|| ((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);
+ add_to_sbuf(idx, name);
sbuf_prev_hpos = sbuf_end_hpos;
sbuf_end_hpos += w + sbuf_kern;
return TRUE;
@@ -3384,7 +4276,7 @@ int html_printer::sbuf_continuation (int index, const char *name,
*/
if (env->hpos-sbuf_end_hpos < space_width) {
- add_to_sbuf(index, name);
+ add_to_sbuf(idx, name);
sbuf_prev_hpos = sbuf_end_hpos;
sbuf_end_hpos = env->hpos + w;
return TRUE;
@@ -3401,18 +4293,18 @@ int html_printer::sbuf_continuation (int index, const char *name,
char *get_html_translation (font *f, const string &name)
{
- int index;
+ int idx;
if ((f == 0) || name.empty())
return NULL;
else {
- index = f->name_to_index((char *)(name + '\0').contents());
- if (index == 0) {
+ idx = f->name_to_index((char *)(name + '\0').contents());
+ if (idx == 0) {
error("character `%s' not found", (name + '\0').contents());
return NULL;
} else
- if (f->contains(index))
- return (char *)f->get_special_device_encoding(index);
+ if (f->contains(idx))
+ return (char *)f->get_special_device_encoding(idx);
else
return NULL;
}
@@ -3425,7 +4317,7 @@ char *get_html_translation (font *f, const string &name)
* is flushed.
*/
-int html_printer::overstrike(int index, const char *name, const environment *env, int w)
+int html_printer::overstrike(int idx, const char *name, const environment *env, int w)
{
if ((env->hpos < sbuf_end_hpos)
|| ((sbuf_kern != 0) && (sbuf_end_hpos - sbuf_kern < env->hpos))) {
@@ -3435,7 +4327,7 @@ int html_printer::overstrike(int index, const char *name, const environment *env
if (overstrike_detected) {
/* already detected, remove previous glyph and use this glyph */
sbuf.set_length(last_sbuf_length);
- add_to_sbuf(index, name);
+ add_to_sbuf(idx, name);
sbuf_end_hpos = env->hpos + w;
return TRUE;
} else {
@@ -3444,7 +4336,7 @@ int html_printer::overstrike(int index, const char *name, const environment *env
if (! is_bold(sbuf_style.f))
flush_sbuf();
overstrike_detected = TRUE;
- add_to_sbuf(index, name);
+ add_to_sbuf(idx, name);
sbuf_end_hpos = env->hpos + w;
return TRUE;
}
@@ -3453,11 +4345,13 @@ int html_printer::overstrike(int index, const char *name, const environment *env
}
/*
- * set_char - adds a character into the sbuf if it is a continuation with the previous
- * word otherwise flush the current sbuf and add character anew.
+ * set_char - adds a character into the sbuf if it is a continuation
+ * with the previous word otherwise flush the current sbuf
+ * and add character anew.
*/
-void html_printer::set_char(int i, font *f, const environment *env, int w, const char *name)
+void html_printer::set_char(int i, font *f, const environment *env,
+ int w, const char *name)
{
style sty(f, env->size, env->height, env->slant, env->fontno, *env->col);
if (sty.slant != 0) {
@@ -3471,6 +4365,8 @@ void html_printer::set_char(int i, font *f, const environment *env, int w, const
return;
flush_sbuf();
+ if (sbuf_style.f == NULL)
+ sbuf_style = sty;
add_to_sbuf(i, name);
sbuf_end_hpos = env->hpos + w;
sbuf_start_hpos = env->hpos;
@@ -3516,11 +4412,44 @@ void html_printer::set_numbered_char(int num, const environment *env,
w = nbsp_width;
else
w = f->get_width(i, env->size);
+ w = round_width(w);
if (widthp)
*widthp = w;
set_char(i, f, env, w, 0);
}
+int html_printer::set_char_and_width(const char *nm, const environment *env,
+ int *widthp, font **f)
+{
+ int i = font::name_to_index(nm);
+ int fn = env->fontno;
+ if (fn < 0 || fn >= nfonts) {
+ error("bad font position `%1'", fn);
+ return -1;
+ }
+ *f = font_table[fn];
+ if (*f == 0) {
+ error("no font mounted at `%1'", fn);
+ return -1;
+ }
+ if (!(*f)->contains(i)) {
+ if (nm[0] != '\0' && nm[1] == '\0')
+ error("font `%1' does not contain ascii character `%2'",
+ (*f)->get_name(),
+ nm[0]);
+ else
+ error("font `%1' does not contain special character `%2'",
+ (*f)->get_name(),
+ nm);
+ return -1;
+ }
+ int w = (*f)->get_width(i, env->size);
+ w = round_width(w);
+ if (widthp)
+ *widthp = w;
+ return i;
+}
+
/*
* write_title - writes the title to this document
*/
@@ -3573,8 +4502,8 @@ void html_printer::begin_page(int n)
output_vpos = -1;
output_vpos_max = -1;
current_paragraph = new html_text(&html);
- do_indent(indentation, pageoffset, linelength);
- current_paragraph->do_para("");
+ do_indent(get_troff_indent(), pageoffset, linelength);
+ current_paragraph->do_para("", FALSE);
}
void html_printer::end_page(int)
@@ -3606,6 +4535,133 @@ void html_printer::do_body (void)
}
}
+/*
+ * emit_link - generates: <a href="to">name</a>
+ */
+
+void html_printer::emit_link (const string &to, const char *name)
+{
+ fputs("<a href=\"", stdout);
+ fputs(to.contents(), stdout);
+ fputs("\">", stdout);
+ fputs(name, stdout);
+ fputs("</a>", stdout);
+}
+
+/*
+ * write_navigation - writes out the links which navigate between
+ * file fragments.
+ */
+
+void html_printer::write_navigation (const string &top, const string &prev,
+ const string &next, const string &current)
+{
+ int need_bar = FALSE;
+
+ if (multiple_files) {
+ write_rule();
+ fputs("[ ", stdout);
+ if ((strcmp(prev.contents(), "") != 0) && prev != top && prev != current) {
+ emit_link(prev, "prev");
+ need_bar = TRUE;
+ }
+ if ((strcmp(next.contents(), "") != 0) && next != top && next != current) {
+ if (need_bar)
+ fputs(" | ", stdout);
+ emit_link(next, "next");
+ need_bar = TRUE;
+ }
+ if (top != "<standard input>" && (strcmp(top.contents(), "") != 0) && top != current) {
+ if (need_bar)
+ fputs(" | ", stdout);
+ emit_link(top, "top");
+ }
+ fputs(" ]\n", stdout);
+ write_rule();
+ }
+}
+
+/*
+ * do_file_components - scan the file list copying each temporary
+ * file in turn. This is used twofold:
+ *
+ * firstly to emit section heading links,
+ * between file fragments if required and
+ * secondly to generate jobname file fragments
+ * if required.
+ */
+
+void html_printer::do_file_components (void)
+{
+ int fragment_no = 1;
+ string top;
+ string prev;
+ string next;
+ string current;
+
+ file_list.start_of_list();
+ top = string(job_name);
+ top += string(".html");
+ top += '\0';
+ next = file_list.next_file_name();
+ next += '\0';
+ current = next;
+ while (file_list.get_file() != 0) {
+ if (fseek(file_list.get_file(), 0L, 0) < 0)
+ fatal("fseek on temporary file failed");
+ html.copy_file(file_list.get_file());
+ fclose(file_list.get_file());
+
+ file_list.move_next();
+ if (file_list.is_new_output_file()) {
+ if (fragment_no > 1)
+ write_navigation(top, prev, next, current);
+ prev = current;
+ current = next;
+ next = file_list.next_file_name();
+ next += '\0';
+ string split_file = file_list.file_name();
+ split_file += '\0';
+ fflush(stdout);
+ freopen(split_file.contents(), "w", stdout);
+ fragment_no++;
+ writeHeadMetaStyle();
+ write_navigation(top, prev, next, current);
+ }
+ if (file_list.are_links_required())
+ header.write_headings(stdout, TRUE);
+ }
+ if (fragment_no > 1)
+ write_navigation(top, prev, next, current);
+ else
+ write_rule();
+}
+
+/*
+ * writeHeadMetaStyle - emits the <head> <meta> and <style> tags and
+ * related information.
+ */
+
+void html_printer::writeHeadMetaStyle (void)
+{
+ fputs("<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\n", stdout);
+ fputs("\"http://www.w3.org/TR/html4/loose.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 http-equiv=\"Content-Type\" "
+ "content=\"text/html; charset=US-ASCII\">\n", stdout);
+ fputs("<meta name=\"Content-Style\" content=\"text/css\">\n", stdout);
+
+ fputs("<style type=\"text/css\">\n", stdout);
+ fputs(" p { margin-top: 0; margin-bottom: 0; }\n", stdout);
+ fputs(" pre { margin-top: 0; margin-bottom: 0; }\n", stdout);
+ fputs(" table { margin-top: 0; margin-bottom: 0; }\n", stdout);
+ fputs("</style>\n", stdout);
+}
+
html_printer::~html_printer()
{
#ifdef LONG_FOR_TIME_T
@@ -3628,17 +4684,11 @@ html_printer::~html_printer()
.put_string(ctime(&t), strlen(ctime(&t))-1)
.end_comment();
- fputs("<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\n", stdout);
- fputs("\"http://www.w3.org/TR/html4/loose.dtd\">\n", stdout);
+ writeHeadMetaStyle();
- fputs("<html>\n", stdout);
- fputs("<head>\n", stdout);
- fputs("<meta name=\"generator\" "
- "content=\"groff -Thtml, see www.gnu.org\">\n", stdout);
- fputs("<meta http-equiv=\"Content-Type\" "
- "content=\"text/html; charset=US-ASCII\">\n", stdout);
- fputs("<meta name=\"Content-Style\" content=\"text/css\">\n", stdout);
write_title(TRUE);
+ head_info += '\0';
+ fputs(head_info.contents(), stdout);
fputs("</head>\n", stdout);
do_body();
@@ -3650,28 +4700,131 @@ html_printer::~html_printer()
#endif
html.end_line();
html.end_line();
- /*
- * now run through the file list copying each temporary file in turn and emitting the links.
- */
- file_list.start_of_list();
- while (file_list.get_file() != 0) {
- if (fseek(file_list.get_file(), 0L, 0) < 0)
- fatal("fseek on temporary file failed");
- html.copy_file(file_list.get_file());
- fclose(file_list.get_file());
- file_list.move_next();
- if (file_list.get_file() != 0)
- header.write_headings(stdout, TRUE);
+
+ if (multiple_files) {
+ fputs("</body>\n", stdout);
+ fputs("</html>\n", stdout);
+ do_file_components();
+ } else {
+ do_file_components();
+ fputs("</body>\n", stdout);
+ fputs("</html>\n", stdout);
}
- write_rule();
- fputs("</body>\n", stdout);
- fputs("</html>\n", stdout);
}
/*
- * special - handle all x X requests from troff. For post-html they allow users
- * to pass raw html commands, turn auto linked headings off/on and
- * also allow troff to emit tags to indicate when a: .br, .sp etc occurs.
+ * get_str - returns a dupicate of string, s. The duplicate
+ * string is terminated at the next ',' or ']'.
+ */
+
+static char *get_str (const char *s, char **n)
+{
+ int i=0;
+ char *v;
+
+ while ((s[i] != (char)0) && (s[i] != ',') && (s[i] != ']'))
+ i++;
+ if (i>0) {
+ v = new char[i+1];
+ memcpy(v, s, i+1);
+ v[i] = (char)0;
+ if (s[i] == ',')
+ (*n) = (char *)&s[i+1];
+ else
+ (*n) = (char *)&s[i];
+ return v;
+ }
+ if (s[i] == ',')
+ (*n) = (char *)&s[1];
+ else
+ (*n) = (char *)s;
+ return NULL;
+}
+
+/*
+ * make_val - creates a string from if s is NULL.
+ */
+
+char *make_val (char *s, int v, char *id, char *f, char *l)
+{
+ if (s == NULL) {
+ char buf[30];
+
+ sprintf(buf, "%d", v);
+ return strsave(buf);
+ }
+ else {
+ /*
+ * check that value, s, is the same as, v.
+ */
+ char *t = s;
+
+ while (*t == '=')
+ t++;
+ if (atoi(t) != v) {
+ if (f == NULL)
+ f = (char *)"stdin";
+ if (l == NULL)
+ l = (char *)"<none>";
+ fprintf(stderr, "%s:%s: grohtml assertion failed at id%s expecting %d and was given %s\n",
+ f, l, id, v, s);
+ }
+ return s;
+ }
+}
+
+/*
+ * handle_assertion - handles the assertions created via .www:ASSERT
+ * in www.tmac. See www.tmac for examples.
+ * This method should be called as we are
+ * parsing the ditroff input. It checks the x, y
+ * position assertions. It does _not_ check the
+ * troff state assertions as these are unknown at this
+ * point.
+ */
+
+void html_printer::handle_assertion (int minv, int minh, int maxv, int maxh, const char *s)
+{
+ char *n;
+ char *cmd = get_str(s, &n);
+ char *id = get_str(n, &n);
+ char *val = get_str(n, &n);
+ char *file= get_str(n, &n);
+ char *line= get_str(n, &n);
+
+ if (strcmp(cmd, "assertion:[x") == 0)
+ as.addx(cmd, id, make_val(val, minh, id, file, line), file, line);
+ else if (strcmp(cmd, "assertion:[y") == 0)
+ as.addy(cmd, id, make_val(val, minv, id, file, line), file, line);
+ else
+ if (strncmp(cmd, "assertion:[", strlen("assertion:[")) == 0)
+ page_contents->add_tag(&sbuf_style, string(s),
+ line_number, minv, minh, maxv, maxh);
+}
+
+/*
+ * build_state_assertion - builds the troff state assertions.
+ */
+
+void html_printer::handle_state_assertion (text_glob *g)
+{
+ if (g != NULL && g->is_a_tag() &&
+ (strncmp(g->text_string, "assertion:[", 11) == 0)) {
+ char *n = (char *)&g->text_string[11];
+ char *cmd = get_str(n, &n);
+ char *val = get_str(n, &n);
+ (void)get_str(n, &n); // unused
+ char *file= get_str(n, &n);
+ char *line= get_str(n, &n);
+
+ as.build(cmd, val, file, line);
+ }
+}
+
+/*
+ * special - handle all x X requests from troff. For post-html they
+ * allow users to pass raw html commands, turn auto linked
+ * headings off/on etc.
*/
void html_printer::special(char *s, const environment *env, char type)
@@ -3702,16 +4855,73 @@ void html_printer::special(char *s, const environment *env, char type)
page_contents->add_and_encode(&sbuf_style, string(&s[5]),
line_number,
env->vpos-env->size*r/72, env->hpos,
- env->vpos , env->hpos);
+ env->vpos , env->hpos,
+ FALSE);
/*
- * assume that the html command has no width, if it does then hopefully troff
- * will have fudged this in a macro by requesting that the formatting move right by
- * the appropriate amount.
+ * assume that the html command has no width, if it does then
+ * hopefully troff will have fudged this in a macro by
+ * requesting that the formatting move right by the appropriate
+ * amount.
+ */
+ } else if (strncmp(s, "html</p>:", 9) == 0) {
+ int r=font::res; /* resolution of the device */
+ font *f=sbuf_style.f;
+
+ if (f == NULL) {
+ int found=FALSE;
+
+ f = font::load_font("TR", &found);
+ }
+
+ /*
+ * need to pass all of string through to html output during flush
+ */
+ page_contents->add_and_encode(&sbuf_style, string(s),
+ line_number,
+ env->vpos-env->size*r/72, env->hpos,
+ env->vpos , env->hpos,
+ TRUE);
+
+ /*
+ * assume that the html command has no width, if it does then
+ * hopefully troff will have fudged this in a macro by
+ * requesting that the formatting move right by the appropriate
+ * amount.
*/
} else if (strncmp(s, "index:", 6) == 0) {
cutoff_heading = atoi(&s[6]);
- } else if (strncmp(s, "html-tag:", 9) == 0) {
+ } else if (strncmp(s, "assertion:[", 11) == 0) {
+ int r=font::res; /* resolution of the device */
+
+ handle_assertion(env->vpos-env->size*r/72, env->hpos,
+ env->vpos, env->hpos, s);
+ }
+ }
+}
+
+/*
+ * devtag - handles device troff tags sent from the `troff'.
+ * These include the troff state machine tags:
+ * .br, .sp, .in, .tl, .ll etc
+ *
+ * (see man 5 grohtml_tags).
+ */
+
+void html_printer::devtag (char *s, const environment *env, char type)
+{
+ if (type != 'p')
+ return;
+
+ if (s != 0) {
+ flush_sbuf();
+ if (env->fontno >= 0) {
+ style sty(get_font_from_index(env->fontno), env->size, env->height,
+ env->slant, env->fontno, *env->col);
+ sbuf_style = sty;
+ }
+
+ if (strncmp(s, "devtag:", strlen("devtag:")) == 0) {
int r=font::res; /* resolution of the device */
page_contents->add_tag(&sbuf_style, string(s),
@@ -3722,6 +4932,26 @@ void html_printer::special(char *s, const environment *env, char type)
}
}
+
+/*
+ * taken from number.cpp in src/roff/troff, [hunits::hunits(units x)]
+ */
+
+int html_printer::round_width(int x)
+{
+ int r = font::hor;
+ int n;
+
+ // don't depend on the rounding direction for division of negative integers
+ if (r == 1)
+ n = x;
+ else
+ n = (x < 0
+ ? -((-x + r/2 - 1)/r)
+ : (x + r/2 - 1)/r);
+ return n * r;
+}
+
int main(int argc, char **argv)
{
program_name = argv[0];
@@ -3733,58 +4963,69 @@ int main(int argc, char **argv)
{ "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))
+ while ((c = getopt_long(argc, argv, "a:bdD:F:g:hi:I:j:lno:prs:S:v",
+ long_options, NULL))
!= EOF)
switch(c) {
- case 'v':
- printf("GNU post-grohtml (groff) version %s\n", Version_string);
- exit(0);
- break;
case 'a':
/* text antialiasing bits - handled by pre-html */
break;
- case 'g':
- /* graphic antialiasing bits - handled by pre-html */
- break;
case 'b':
// set background color to white
default_background = new color;
default_background->set_gray(color::MAX_COLOR_VAL);
break;
- case 'F':
- font::command_line_font_dir(optarg);
+ case 'd':
+ /* handled by pre-html */
break;
- case 'l':
- auto_links = FALSE;
+ case 'D':
+ /* handled by pre-html */
break;
- case 'r':
- auto_rule = FALSE;
+ case 'F':
+ font::command_line_font_dir(optarg);
break;
- case 'd':
- /* handled by pre-html */
+ case 'g':
+ /* graphic antialiasing bits - handled by pre-html */
break;
case 'h':
/* do not use the Hn headings of html, but manufacture our own */
manufacture_headings = TRUE;
break;
- case 'o':
- /* handled by pre-html */
- break;
- case 'p':
- /* handled by pre-html */
- break;
case 'i':
/* handled by pre-html */
break;
case 'I':
/* handled by pre-html */
break;
- case 'D':
- /* handled by pre-html */
+ case 'j':
+ multiple_files = TRUE;
+ job_name = optarg;
+ break;
+ case 'l':
+ auto_links = FALSE;
break;
case 'n':
simple_anchors = TRUE;
break;
+ case 'o':
+ /* handled by pre-html */
+ break;
+ case 'p':
+ /* handled by pre-html */
+ break;
+ case 'r':
+ auto_rule = FALSE;
+ break;
+ case 's':
+ base_point_size = atoi(optarg);
+ break;
+ case 'S':
+ split_level = atoi(optarg) + 1;
+ break;
+ case 'v':
+ printf("GNU post-grohtml (groff) version %s\n", Version_string);
+ exit(0);
+ break;
case CHAR_MAX + 1: // --help
usage(stdout);
exit(0);
diff --git a/contrib/groff/src/devices/grolbp/lbp.cpp b/contrib/groff/src/devices/grolbp/lbp.cpp
index b34a1e0..081ab99 100644
--- a/contrib/groff/src/devices/grolbp/lbp.cpp
+++ b/contrib/groff/src/devices/grolbp/lbp.cpp
@@ -1,5 +1,6 @@
// -*- C++ -*-
-/* Copyright (C) 1994, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 1994, 2000, 2001, 2002, 2003, 2004, 2005
+ Free Software Foundation, Inc.
Written by Francisco Andrés Verdú <pandres@dragonet.es> with many ideas
taken from the other groff drivers.
@@ -18,16 +19,13 @@ 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. */
+Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */
/*
TODO
- Add X command to include bitmaps
*/
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#endif
#include "driver.h"
#include "lbp.h"
@@ -93,21 +91,6 @@ private:
int paperwidth;
};
-// Compatibility section.
-//
-// Here we define some functions not present in some of the targets
-// platforms
-#ifndef HAVE_STRSEP
-// Solaris 8 doesn't have the strsep function
-static char *strsep(char **pcadena, const char *delim)
-{
- char *p;
- p = strtok(*pcadena, delim);
- *pcadena = strtok(NULL, delim);
- return p;
-}
-#endif
-
lbp_font::lbp_font(const char *nm)
: font(nm)
{
@@ -231,7 +214,7 @@ inline void lbp_printer::set_line_thickness(int size,const environment *env)
/* fprintf(stderr, "thickness: %d == %d, size %d, %d \n",
size, line_thickness, env->size,req_linethickness); */
return;
-}; // lbp_printer::set_line_thickness
+} // lbp_printer::set_line_thickness
void lbp_printer::begin_page(int)
{
@@ -294,10 +277,10 @@ char *lbp_printer::font_name(const lbp_font *f, const int siz)
return bfont_name;
}
-void lbp_printer::set_char(int index, font *f, const environment *env,
+void lbp_printer::set_char(int idx, font *f, const environment *env,
int w, const char *)
{
- int code = f->get_code(index);
+ int code = f->get_code(idx);
unsigned char ch = code & 0xff;
unsigned short symbol_set = code >> 8;
if (f != cur_font) {
@@ -441,9 +424,9 @@ void lbp_printer::draw(int code, int *p, int np, const environment *env)
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) {
@@ -663,12 +646,15 @@ int main(int argc, char **argv)
int c = 0;
int option_index = 0;
while (c >= 0) {
- c = getopt_long (argc, argv, "F:p:lvo:c:hw:",
+ c = getopt_long (argc, argv, "c:F:hI:lo:p:vw:",
long_options, &option_index);
switch (c) {
case 'F':
font::command_line_font_dir(optarg);
break;
+ case 'I':
+ // ignore include path arguments
+ break;
case 'p':
{
const char *s;
@@ -694,7 +680,7 @@ int main(int argc, char **argv)
orientation = 1;
else
error("unknown orientation '%1'", optarg);
- };
+ }
break;
case 'c':
{
diff --git a/contrib/groff/src/devices/grolbp/lbp.h b/contrib/groff/src/devices/grolbp/lbp.h
index e669ff2..b3171cf 100644
--- a/contrib/groff/src/devices/grolbp/lbp.h
+++ b/contrib/groff/src/devices/grolbp/lbp.h
@@ -1,5 +1,6 @@
// -*- C -*-
-/* Copyright (C) 1994, 2000, 2001, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 1994, 2000, 2001, 2003, 2004, 2005
+ 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
@@ -14,7 +15,7 @@ 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. */
+Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */
/* This file contains a set of utility functions to use canon CAPSL printers
* (lbp-4 and lbp-8 series printers) */
@@ -28,14 +29,15 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
static FILE *lbpoutput = NULL;
static FILE *vdmoutput = NULL;
+
static inline void
lbpinit(FILE *outfile)
{
lbpoutput = outfile;
-};
+}
-static inline void
+static void
lbpprintf(const char *format, ... )
{ /* Taken from cjet */
va_list stuff;
@@ -43,68 +45,78 @@ lbpprintf(const char *format, ... )
va_start(stuff, format);
vfprintf(lbpoutput, format, stuff);
va_end(stuff);
-};
+}
+
static inline void
lbpputs(const char *data)
{
fputs(data,lbpoutput);
-};
+}
+
static inline void
lbpputc(unsigned char c)
{
fputc(c,lbpoutput);
-};
+}
static inline void
-lbpsavestatus(int index )
+lbpsavestatus(int idx )
{
- fprintf(lbpoutput,"\033[%d%%y",index);
-};
+ fprintf(lbpoutput,"\033[%d%%y",idx);
+}
+
static inline void
-lbprestorestatus(int index )
+lbprestorestatus(int idx )
{
- fprintf(lbpoutput,"\033[%d%cz",index ,'%');
-};
+ fprintf(lbpoutput,"\033[%d%cz",idx ,'%');
+}
+
static inline void
-lbpsavepos(int index)
+lbpsavepos(int idx)
{
- fprintf(lbpoutput,"\033[1;%d;0x",index);
-};
+ fprintf(lbpoutput,"\033[1;%d;0x",idx);
+}
+
static inline void
-lbprestorepos(int index)
+lbprestorepos(int idx)
{
- fprintf(lbpoutput,"\033[0;%d;0x",index);
-};
+ fprintf(lbpoutput,"\033[0;%d;0x",idx);
+}
+
static inline void
-lbprestoreposx(int index)
+lbprestoreposx(int idx)
{
- fprintf(lbpoutput,"\033[0;%d;1x",index);
-};
+ fprintf(lbpoutput,"\033[0;%d;1x",idx);
+}
+
static inline void
lbpmoverel(int despl, char direction)
{
fprintf(lbpoutput,"\033[%d%c",despl,direction);
-};
+}
+
static inline void
lbplinerel(int width,int despl,char direction )
{
fprintf(lbpoutput,"\033[%d;0;9{\033[%d%c\033[9}",width,despl,direction);
-};
+}
+
static inline void
lbpmoveabs(int x, int y)
{
fprintf(lbpoutput,"\033[%d;%df",y,x);
-};
+}
+
static inline void
lbplineto(int x,int y, int width )
@@ -112,7 +124,8 @@ lbplineto(int x,int y, int width )
fprintf(lbpoutput,"\033[%d;0;9{",width);
lbpmoveabs(x,y);
fprintf(lbpoutput,"\033[9}\n");
-};
+}
+
static inline void
lbpruleabs(int x, int y, int hsize, int vsize)
@@ -121,9 +134,11 @@ lbpruleabs(int x, int y, int hsize, int vsize)
fprintf(lbpoutput,"\033[0;9;000s");
lbpmoveabs(x+hsize,y+vsize);
fprintf(lbpoutput,"\033[9r");
-};
+}
+
+
+static void vdmprintf(const char *format, ... );
-static inline void vdmprintf(const char *format, ... );
static inline char *
vdmnum(int num,char *result)
@@ -147,7 +162,8 @@ vdmnum(int num,char *result)
*p++ = b3;
*p = 0x00; /* End of the resulting string */
return result;
-};
+}
+
static inline void
vdmorigin(int newx, int newy)
@@ -155,7 +171,7 @@ vdmorigin(int newx, int newy)
char nx[4],ny[4];
vdmprintf("}\"%s%s\x1e",vdmnum(newx,nx),vdmnum(newy,ny));
-}; /* vdmorigin */
+}
static inline FILE *
@@ -170,15 +186,17 @@ vdminit(FILE *vdmfile)
vdmnum(-3,scale),vdmnum(1,size),vdmnum(1,lineend));
return vdmoutput;
-};
+}
+
static inline void
vdmend()
{
vdmprintf("}p\x1e");
-};
+}
-static inline void
+
+static void
vdmprintf(const char *format, ... )
{ /* Taken from cjet */
va_list stuff;
@@ -187,7 +205,8 @@ vdmprintf(const char *format, ... )
va_start(stuff, format);
vfprintf(vdmoutput, format, stuff);
va_end(stuff);
-};
+}
+
static inline void
vdmsetfillmode(int pattern,int perimeter, int inverted)
@@ -200,7 +219,8 @@ vdmsetfillmode(int pattern,int perimeter, int inverted)
vdmprintf("I%s%s%s%s%s\x1e",vdmnum(pattern,patt),\
vdmnum(perimeter,perim),vdmnum(0,rot),
vdmnum(0,espejo),vdmnum(inverted,inv));
-};
+}
+
static inline void
vdmcircle(int centerx, int centery, int radius)
@@ -209,7 +229,8 @@ vdmcircle(int centerx, int centery, int radius)
vdmprintf("5%s%s%s\x1e",vdmnum(centerx,x),vdmnum(centery,y),\
vdmnum(radius,rad));
-};
+}
+
static inline void
vdmaarc(int centerx, int centery, int radius,int startangle,int angle,int style,int arcopen)
@@ -220,7 +241,8 @@ vdmaarc(int centerx, int centery, int radius,int startangle,int angle,int style,
vdmnum(centerx,x),vdmnum(centery,y),\
vdmnum(radius,rad),vdmnum(startangle,stx),vdmnum(angle,sty),\
vdmnum(style,styl));
-};
+}
+
static inline void
vdmvarc(int centerx, int centery,int radius, int startx, int starty, int endx, int endy,\
@@ -228,11 +250,12 @@ vdmvarc(int centerx, int centery,int radius, int startx, int starty, int endx, i
{
char x[4],y[4],rad[4],stx[4],sty[4],enx[4],eny[4],styl[4],op[4];
- vdmprintf("}6%s%s%s%s%s%s%s%s\x1e",vdmnum(arcopen,op),\
+ vdmprintf("}6%s%s%s%s%s%s%s%s%s\x1e",vdmnum(arcopen,op),\
vdmnum(centerx,x),vdmnum(centery,y),\
vdmnum(radius,rad),vdmnum(startx,stx),vdmnum(starty,sty),\
vdmnum(endx,enx),vdmnum(endy,eny),vdmnum(style,styl));
-};
+}
+
static inline void
vdmellipse(int centerx, int centery, int radiusx, int radiusy,int rotation)
@@ -242,7 +265,8 @@ vdmellipse(int centerx, int centery, int radiusx, int radiusy,int rotation)
vdmprintf("}7%s%s%s%s%s\x1e\n",vdmnum(centerx,x),vdmnum(centery,y),\
vdmnum(radiusx,radx),vdmnum(radiusy,rady),\
vdmnum(rotation,rotat));
-};
+}
+
static inline void
vdmsetlinetype(int lintype)
@@ -251,7 +275,8 @@ vdmsetlinetype(int lintype)
vdmprintf("E1%s%s\x1e",vdmnum(lintype,ltyp),vdmnum(1,expfact));
-};
+}
+
static inline void
vdmsetlinestyle(int lintype, int pattern,int unionstyle)
@@ -265,7 +290,8 @@ vdmsetlinestyle(int lintype, int pattern,int unionstyle)
vdmnum(pattern,patt),vdmnum(0,rot),
vdmnum(0,espejo),vdmnum(0,in));
vdmprintf("}F%s",vdmnum(unionstyle,rot));
-};
+}
+
static inline void
vdmlinewidth(int width)
@@ -273,7 +299,8 @@ vdmlinewidth(int width)
char wh[4];
vdmprintf("F1%s\x1e",vdmnum(width,wh));
-};
+}
+
static inline void
vdmrectangle(int origx, int origy,int dstx, int dsty)
@@ -282,7 +309,8 @@ vdmrectangle(int origx, int origy,int dstx, int dsty)
vdmprintf("}:%s%s%s%s\x1e\n",vdmnum(origx,xcoord),vdmnum(dstx,sdstx),\
vdmnum(origy,ycoord),vdmnum(dsty,sdsty));
-}; /* polyline */
+}
+
static inline void
vdmpolyline(int numpoints, int *points)
@@ -296,10 +324,11 @@ vdmpolyline(int numpoints, int *points)
for (i = 1; i < numpoints ; i++) {
vdmprintf("%s%s",vdmnum(*p,xcoord),vdmnum(*(p+1),ycoord));
p += 2;
- }; /* for */
+ } /* for */
vdmprintf("\x1e\n");
-}; /* polyline */
+}
+
static inline void
vdmpolygon(int numpoints, int *points)
{
@@ -312,10 +341,10 @@ vdmpolygon(int numpoints, int *points)
for (i = 1; i < numpoints ; i++) {
vdmprintf("%s%s",vdmnum(*p,xcoord),vdmnum(*(p+1),ycoord));
p += 2;
- }; /* for */
+ } /* for */
vdmprintf("\x1e\n");
-}; /* vdmpolygon */
+}
/************************************************************************
@@ -325,7 +354,7 @@ static inline int
vdminited()
{
return (vdmoutput != NULL);
-}; /* vdminited */
+}
static inline void
@@ -340,7 +369,8 @@ vdmline(int startx, int starty, int sizex, int sizey)
vdmpolyline(2,points);
-};
+}
+
/*#define THRESHOLD .05 */ /* inch */
#define THRESHOLD 1 /* points (1/300 inch) */
@@ -348,13 +378,13 @@ static inline void
splinerel(double px,double py,int flush)
{
static int lx = 0 ,ly = 0;
- static float pend = 0.0;
+ static double pend = 0.0;
static int dy = 0, despx = 0, despy = 0, sigpend = 0;
- int dxnew ,dynew, sg;
+ int dxnew = 0, dynew = 0, sg;
char xcoord[4],ycoord[4];
- float npend ;
+ double npend ;
- if (flush == -1) {lx = (int)px; ly = (int)py; return;};
+ if (flush == -1) {lx = (int)px; ly = (int)py; return;}
if (flush == 0) {
dxnew = (int)px -lx;
@@ -366,7 +396,7 @@ splinerel(double px,double py,int flush)
despx = dxnew;
if ((sg == sigpend) && (dy == 0)){
return;
- };
+ }
dy = 0;
}
else {
@@ -377,9 +407,9 @@ splinerel(double px,double py,int flush)
else
{ sigpend = sg;
pend = npend;
- }; /* else (( npend == pend) && ... */
- }; /* else (if (dynew == 0)) */
- }; /* if (!flush ) */
+ } /* else (( npend == pend) && ... */
+ } /* else (if (dynew == 0)) */
+ } /* if (!flush ) */
/* if we've changed direction we must draw the line */
/* fprintf(stderr," (%d) %.2f,%.2f\n",flush,(float)px,(float)py);*/
@@ -390,7 +420,7 @@ splinerel(double px,double py,int flush)
if (flush) {
dxnew = dy = despx = despy = 0;
return;
- }; /* if (flush) */
+ } /* if (flush) */
dxnew -= despx;
dynew -= despy;
if ((dxnew != 0) || (dynew != 0)) vdmprintf("%s%s",vdmnum(dxnew,xcoord),\
@@ -401,111 +431,116 @@ splinerel(double px,double py,int flush)
lx = (int)px; ly = (int)py;
dxnew = dy = despx = despy = 0;
-}; /* splinerel */
+}
+
/**********************************************************************
* The following code to draw splines is adapted from the transfig package
*/
static void
-quadratic_spline(double a1,double b1, double a2, double b2, \
- double a3, double b3, double a4, double b4)
-{
- double x1, y1, x4, y4;
- double xmid, ymid;
-
- x1 = a1; y1 = b1;
- x4 = a4; y4 = b4;
- xmid = (a2 + a3)/2.0;
- ymid = (b2 + b3)/2.0;
- if ((fabs(x1 - xmid) < THRESHOLD) && (fabs(y1 - ymid) < THRESHOLD)) {
- splinerel(xmid,ymid,0);
-/* fprintf(tfp, "PA%.4f,%.4f;\n", xmid, ymid);*/
+quadratic_spline(double a_1, double b_1, double a_2, double b_2, \
+ double a_3, double b_3, double a_4, double b_4)
+{
+ double x_1, y_1, x_4, y_4;
+ double x_mid, y_mid;
+
+ x_1 = a_1; y_1 = b_1;
+ x_4 = a_4; y_4 = b_4;
+ x_mid = (a_2 + a_3)/2.0;
+ y_mid = (b_2 + b_3)/2.0;
+ if ((fabs(x_1 - x_mid) < THRESHOLD)
+ && (fabs(y_1 - y_mid) < THRESHOLD)) {
+ splinerel(x_mid, y_mid, 0);
+/* fprintf(tfp, "PA%.4f,%.4f;\n", x_mid, y_mid);*/
}
else {
- quadratic_spline(x1, y1, ((x1+a2)/2.0), ((y1+b2)/2.0),
- ((3.0*a2+a3)/4.0), ((3.0*b2+b3)/4.0), xmid, ymid);
- }
+ quadratic_spline(x_1, y_1, ((x_1+a_2)/2.0), ((y_1+b_2)/2.0),
+ ((3.0*a_2+a_3)/4.0), ((3.0*b_2+b_3)/4.0), x_mid, y_mid);
+ }
- if ((fabs(xmid - x4) < THRESHOLD) && (fabs(ymid - y4) < THRESHOLD)) {
- splinerel(x4,y4,0);
-/* fprintf(tfp, "PA%.4f,%.4f;\n", x4, y4);*/
+ if ((fabs(x_mid - x_4) < THRESHOLD)
+ && (fabs(y_mid - y_4) < THRESHOLD)) {
+ splinerel(x_4, y_4, 0);
+/* fprintf(tfp, "PA%.4f,%.4f;\n", x_4, y_4);*/
}
else {
- quadratic_spline(xmid, ymid, ((a2+3.0*a3)/4.0), ((b2+3.0*b3)/4.0),
- ((a3+x4)/2.0), ((b3+y4)/2.0), x4, y4);
- };
-}; /* quadratic_spline */
+ quadratic_spline(x_mid, y_mid,
+ ((a_2+3.0*a_3)/4.0), ((b_2+3.0*b_3)/4.0),
+ ((a_3+x_4)/2.0), ((b_3+y_4)/2.0), x_4, y_4);
+ }
+}
+
#define XCOORD(i) numbers[(2*i)]
#define YCOORD(i) numbers[(2*i)+1]
static void
-vdmspline(int numpoints, int ox,int oy, int *numbers)
+vdmspline(int numpoints, int o_x, int o_y, int *numbers)
{
- double cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4;
- double x1, y1, x2, y2;
+ double cx_1, cy_1, cx_2, cy_2, cx_3, cy_3, cx_4, cy_4;
+ double x_1, y_1, x_2, y_2;
char xcoord[4],ycoord[4];
int i;
/*p = s->points;
- x1 = p->x/ppi;*/
- x1 = ox;
- y1 = oy;
+ x_1 = p->x/ppi;*/
+ x_1 = o_x;
+ y_1 = o_y;
/* p = p->next;
- x2 = p->x/ppi;
- y2 = p->y/ppi;*/
- x2 = ox + XCOORD(0);
- y2 = oy + YCOORD(0);
- cx1 = (x1 + x2)/2.0;
- cy1 = (y1 + y2)/2.0;
- cx2 = (x1 + 3.0*x2)/4.0;
- cy2 = (y1 + 3.0*y2)/4.0;
-
-/* fprintf(stderr,"Spline %d (%d,%d)\n",numpoints,(int)x1,(int)y1);*/
- vdmprintf("1%s%s",vdmnum((int)x1,xcoord),vdmnum((int)y1,ycoord));
- splinerel(x1,y1,-1);
- splinerel(cx1,cy1,0);
+ x_2 = p->x/ppi;
+ y_2 = p->y/ppi;*/
+ x_2 = o_x + XCOORD(0);
+ y_2 = o_y + YCOORD(0);
+ cx_1 = (x_1 + x_2)/2.0;
+ cy_1 = (y_1 + y_2)/2.0;
+ cx_2 = (x_1 + 3.0*x_2)/4.0;
+ cy_2 = (y_1 + 3.0*y_2)/4.0;
+
+/* fprintf(stderr,"Spline %d (%d,%d)\n",numpoints,(int)x_1,(int)y_1);*/
+ vdmprintf("1%s%s",vdmnum((int)x_1,xcoord),vdmnum((int)y_1,ycoord));
+ splinerel(x_1,y_1,-1);
+ splinerel(cx_1,cy_1,0);
/* fprintf(tfp, "PA%.4f,%.4f;PD%.4f,%.4f;\n",
- x1, y1, cx1, cy1);*/
+ x_1, y_1, cx_1, cy_1);*/
/*for (p = p->next; p != NULL; p = p->next) {*/
for (i = 1; i < (numpoints); i++) {
- x1 = x2;
- y1 = y2;
-/* x2 = p->x/ppi;
- y2 = p->y/ppi;*/
- x2 = x1 + XCOORD(i);
- y2 = y1 + YCOORD(i);
- cx3 = (3.0*x1 + x2)/4.0;
- cy3 = (3.0*y1 + y2)/4.0;
- cx4 = (x1 + x2)/2.0;
- cy4 = (y1 + y2)/2.0;
- /* fprintf(stderr,"Point (%d,%d) - (%d,%d)\n",(int)x1,(int)(y1),(int)x2,(int)y2);*/
- quadratic_spline(cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4);
- cx1 = cx4;
- cy1 = cy4;
- cx2 = (x1 + 3.0*x2)/4.0;
- cy2 = (y1 + 3.0*y2)/4.0;
- }
- x1 = x2;
- y1 = y2;
-/* p = s->points->next;
- x2 = p->x/ppi;
- y2 = p->y/ppi;*/
- x2 = ox + XCOORD(0);
- y2 = oy + YCOORD(0);
- cx3 = (3.0*x1 + x2)/4.0;
- cy3 = (3.0*y1 + y2)/4.0;
- cx4 = (x1 + x2)/2.0;
- cy4 = (y1 + y2)/2.0;
- splinerel(x1,y1,0);
- splinerel(x1,y1,1);
- /*vdmprintf("%s%s",vdmnum((int)(x1-lx),xcoord),\
- vdmnum((int)(y1-ly),ycoord));*/
+ x_1 = x_2;
+ y_1 = y_2;
+/* x_2 = p->x/ppi;
+ y_2 = p->y/ppi;*/
+ x_2 = x_1 + XCOORD(i);
+ y_2 = y_1 + YCOORD(i);
+ cx_3 = (3.0*x_1 + x_2)/4.0;
+ cy_3 = (3.0*y_1 + y_2)/4.0;
+ cx_4 = (x_1 + x_2)/2.0;
+ cy_4 = (y_1 + y_2)/2.0;
+ /* fprintf(stderr,"Point (%d,%d) - (%d,%d)\n",(int)x_1,(int)(y_1),(int)x_2,(int)y_2);*/
+ quadratic_spline(cx_1, cy_1, cx_2, cy_2, cx_3, cy_3, cx_4, cy_4);
+ cx_1 = cx_4;
+ cy_1 = cy_4;
+ cx_2 = (x_1 + 3.0*x_2)/4.0;
+ cy_2 = (y_1 + 3.0*y_2)/4.0;
+ }
+ x_1 = x_2;
+ y_1 = y_2;
+/* p = s->points->next;
+ x_2 = p->x/ppi;
+ y_2 = p->y/ppi;*/
+ x_2 = o_x + XCOORD(0);
+ y_2 = o_y + YCOORD(0);
+ cx_3 = (3.0*x_1 + x_2)/4.0;
+ cy_3 = (3.0*y_1 + y_2)/4.0;
+ cx_4 = (x_1 + x_2)/2.0;
+ cy_4 = (y_1 + y_2)/2.0;
+ splinerel(x_1, y_1, 0);
+ splinerel(x_1, y_1, 1);
+ /*vdmprintf("%s%s",vdmnum((int)(x_1-lx),xcoord),\
+ vdmnum((int)(y_1-ly),ycoord));*/
vdmprintf("\x1e\n");
-/* fprintf(tfp, "PA%.4f,%.4f;PU;\n", x1, y1);*/
+/* fprintf(tfp, "PA%.4f,%.4f;PU;\n", x_1, y_1);*/
-}; /* vdmspline */
+}
#endif
diff --git a/contrib/groff/src/devices/grolj4/Makefile.sub b/contrib/groff/src/devices/grolj4/Makefile.sub
index 9899b7a..1216a49 100644
--- a/contrib/groff/src/devices/grolj4/Makefile.sub
+++ b/contrib/groff/src/devices/grolj4/Makefile.sub
@@ -1,5 +1,6 @@
PROG=grolj4$(EXEEXT)
MAN1=grolj4.n
+MAN5=lj4_font.n
XLIBS=$(LIBDRIVER) $(LIBGROFF)
MLIB=$(LIBM)
OBJS=lj4.$(OBJEXT)
diff --git a/contrib/groff/src/devices/grolj4/grolj4.man b/contrib/groff/src/devices/grolj4/grolj4.man
index 267c621..260a619 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, 2002 Free Software Foundation, Inc.
+Copyright (C) 1994-2000, 2001, 2002, 2004 Free Software Foundation, Inc.
Permission is granted to make and distribute verbatim copies of
this manual provided the copyright notice and this permission notice
@@ -140,6 +140,7 @@ Macros for use with
.SH BUGS
Small dots.
.SH "SEE ALSO"
+.BR lj4_font (@MAN5EXT@),
.BR groff (@MAN1EXT@),
.BR @g@troff (@MAN1EXT@),
.BR groff_out (@MAN5EXT@),
diff --git a/contrib/groff/src/devices/grolj4/lj4.cpp b/contrib/groff/src/devices/grolj4/lj4.cpp
index 1332e19..1284954 100644
--- a/contrib/groff/src/devices/grolj4/lj4.cpp
+++ b/contrib/groff/src/devices/grolj4/lj4.cpp
@@ -1,5 +1,6 @@
// -*- C++ -*-
-/* Copyright (C) 1994, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 1994, 2000, 2001, 2002, 2003, 2004
+ Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
This file is part of groff.
@@ -16,7 +17,7 @@ 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. */
+Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */
/*
TODO
@@ -277,10 +278,10 @@ 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,
+void lj4_printer::set_char(int idx, font *f, const environment *env,
int w, const char *)
{
- int code = f->get_code(index);
+ int code = f->get_code(idx);
unsigned char ch = code & 0xff;
unsigned short symbol_set = code >> 8;
@@ -611,18 +612,21 @@ int main(int argc, char **argv)
{ "version", no_argument, 0, 'v' },
{ NULL, 0, 0, 0 }
};
- while ((c = getopt_long(argc, argv, ":F:p:d:lvw:c:", long_options, NULL))
+ while ((c = getopt_long(argc, argv, "c:d:F:I:lp:vw:", long_options, NULL))
!= EOF)
switch(c) {
case 'l':
landscape_flag = 1;
break;
+ case 'I':
+ // ignore include search path
+ break;
case ':':
if (optopt == 'd') {
fprintf(stderr, "duplex assumed to be long-side\n");
duplex_flag = 1;
} else
- fprintf(stderr, "option -%c requires an operand\n", optopt);
+ fprintf(stderr, "option -%c requires an argument\n", optopt);
fflush(stderr);
break;
case 'd':
@@ -644,11 +648,9 @@ int main(int argc, char **argv)
break;
}
case 'v':
- {
- printf("GNU grolj4 (groff) version %s\n", Version_string);
- exit(0);
- break;
- }
+ printf("GNU grolj4 (groff) version %s\n", Version_string);
+ exit(0);
+ break;
case 'F':
font::command_line_font_dir(optarg);
break;
diff --git a/contrib/groff/src/devices/grolj4/lj4_font.man b/contrib/groff/src/devices/grolj4/lj4_font.man
new file mode 100644
index 0000000..e82edff
--- /dev/null
+++ b/contrib/groff/src/devices/grolj4/lj4_font.man
@@ -0,0 +1,167 @@
+.tr ~
+.ig
+Copyright (C) 2004 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 preserved on all copies.
+
+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.
+
+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.
+..
+.\" 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"
+..
+.tr ~
+.TH LJ4_FONT @MAN5EXT@ "@MDATE@" "Groff Version @VERSION@"
+.\" --------------------------------------------------------------------------
+.SH NAME
+.\" --------------------------------------------------------------------------
+lj4_font \- groff fonts for use with devlj4
+.\" --------------------------------------------------------------------------
+.SH DESCRIPTION
+.\" --------------------------------------------------------------------------
+Nominally, all Hewlett-Packard LaserJet~4\(enseries and newer printers
+have the same internal fonts: 45 scalable fonts and one bitmapped
+Lineprinter font.
+The scalable fonts are available in sizes between 0.25 point and 999.75
+points, in 0.25-point increments; the Lineprinter font is available only
+in 8.5-point size.
+.LP
+The LaserJet font files included with
+.B groff
+assume that all printers since the LaserJet~4 are identical.
+There are some differences between fonts in the earlier and more recent
+printers, however.
+The LaserJet~4 printer used Agfa Intellifont technology for 35 of the
+internal scalable fonts; the remaining 10 scalable fonts were TrueType.
+Beginning with the LaserJet~4000\(enseries printers introduced in 1997,
+all scalable internal fonts have been TrueType.
+The number of printable glyphs differs slightly between Intellifont and
+TrueType fonts (generally, the TrueType fonts include more glyphs), and
+there are some minor differences in glyph metrics.
+Differences among printer models are described in the
+.I "PCL~5 Comparison Guide"
+and the
+.I "PCL~5 Comparison Guide Addendum"
+(for printers introduced since approximately 2001).
+.LP
+LaserJet printers reference a glyph by a combination of a 256-glyph
+symbol set and an index within that symbol set.
+Many glyphs appear in more than one symbol set; all combinations of
+symbol set and index that reference the same glyph are equivalent.
+For each glyph,
+.BR hpftodit (@MAN1EXT@)
+searches a list of symbol sets, and selects the first set that contains
+the glyph.
+The printing code generated by
+.BR hpftodit (@MAN1EXT@)
+is an integer that encodes a numerical value for the symbol set in the
+high byte(s), and the index in the low byte.
+See
+.BR groff_font (@MAN5EXT@)
+for a complete description of the font file format; symbol sets are
+described in greater detail in the
+.IR "PCL~5 Printer Language Technical Reference Manual" .
+.LP
+Two of the scalable fonts, Symbol and Wingdings, are bound to
+256-glyph symbol sets; the remaining scalable fonts, as well as the
+Lineprinter font, support numerous symbol sets, sufficient to enable
+printing of more than 600 glyphs.
+.LP
+The metrics generated by
+.BR hpftodit (@MAN1EXT@)
+assume that the DESC file contains values of 1200 for res and 6350 for
+unitwidth (or any combination (e.g., 2400 and 3175) for which
+res~\(mu~unitwidth~=~7\|620\|000).
+Although HP PCL~5 LaserJet printers support an internal resolution of
+7200 units per inch, they use a 16-bit signed integer for cursor
+positioning; if
+.B devlj4
+is to support U.S. ledger paper (11\(sd~\(mu~17\(sd), the maximum usable
+resolution is 32\|767~/~17, or 1927, units per inch, which rounds down to
+1200 units per inch.
+If the largest required paper size is less (e.g., 8.5\(sd~\(mu~11\(sd or
+A5), a greater resolution (and lesser unitwidth) can be specified.
+.\" --------------------------------------------------------------------------
+.SH LIMITATIONS
+.\" --------------------------------------------------------------------------
+Font metrics for Intellifont fonts were provided by Tagged Font Metric
+(TFM) files originally developed by Agfa/Compugraphic.
+The TFM files provided for these fonts supported 600+ glyphs and
+contained extensive lists of kern pairs.
+.LP
+To accommodate developers who had become accustomed to TFM files, HP also
+provided TFM files for the 10 TrueType fonts included in the LaserJet~4.
+The TFM files for TrueType fonts generally included less information
+than the Intellifont TFMs, supporting fewer glyphs, and in most cases,
+providing no kerning information.
+By the time the LaserJet~4000 printer was introduced, most
+developers had migrated to other means of obtaining font metrics,
+and support for new TFM files was very limited.
+The TFM files provided for the TrueType fonts in the LaserJet~4000
+support only the Latin 2 (ISO 8859-2) symbol set, and include no kerning
+information; consequently, they are of little value for any but the most
+rudimentary documents.
+.LP
+Because the Intellifont TFM files contain considerably more information,
+they generally are preferable to the TrueType TFM files even for use
+with the TrueType fonts in the newer printers.
+The metrics for the TrueType fonts are very close, though not identical,
+to those for the earlier Intellifont fonts of the same names.
+Although most output using the Intellifont metrics with the newer
+printers is quite acceptable, a few glyphs may fail to print as
+expected.
+The differences in glyph metrics may be particularly noticeable with
+composite parentheses, brackets, and braces used by
+.BR eqn (@MAN1EXT@) .
+A script, located in
+.BR @FONTDIR@/devlj4/generate ,
+can be used to adjust the metrics for these glyphs in the special font S
+for use with printers that have all TrueType fonts.
+.LP
+At the time HP last supported TFM files, only Version 1 of the Unicode
+standard was available.
+Consequently, many glyphs lacking assigned code points were assigned by
+HP to the Private Use Area (PUA).
+Later versions of the Unicode standard included code points outside the
+PUA for many of these glyphs.
+The HP-supplied TrueType TFM files use the PUA assignments;
+TFM files generated from more recent TrueType font files require the
+later Unicode values to access the same glyphs.
+Consequently, two different mapping files may be required: one for the
+HP-supplied TFM files, and one for more recent TFM files.
+.\" --------------------------------------------------------------------------
+.SH FILES
+.\" --------------------------------------------------------------------------
+.Tp \w'\fB@FONTDIR@/devlj4/DESC'u+2n
+.B @FONTDIR@/devlj4/DESC
+Device description file.
+.TP
+.BI @FONTDIR@/devlj4/ F
+Font description file for font
+.IR F .
+.\" --------------------------------------------------------------------------
+.SH "SEE ALSO"
+.\" --------------------------------------------------------------------------
+.ad 0
+.BR groff (@MAN1EXT@),
+.BR groff_diff (@MAN1EXT@),
+.BR hpftodit (@MAN1EXT@),
+.BR grolj4 (@MAN1EXT@),
+.BR groff_font (@MAN5EXT@)
+.
+.\" Local Variables:
+.\" mode: nroff
+.\" End:
diff --git a/contrib/groff/src/devices/grops/grops.man b/contrib/groff/src/devices/grops/grops.man
index e9f8f02..0ff2579 100644
--- a/contrib/groff/src/devices/grops/grops.man
+++ b/contrib/groff/src/devices/grops/grops.man
@@ -1,5 +1,6 @@
.ig
-Copyright (C) 1989-2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+Copyright (C) 1989-2000, 2001, 2002, 2003, 2004, 2005
+ Free Software Foundation, Inc.
Permission is granted to make and distribute verbatim copies of
this manual provided the copyright notice and this permission notice
@@ -17,6 +18,9 @@ translations approved by the Free Software Foundation instead of in
the original English.
..
.
+.do nr grops_C \n[.C]
+.cp 0
+.
.mso www.tmac
.
.
@@ -62,6 +66,7 @@ grops \- PostScript driver for groff
.OP \-b n
.OP \-c n
.OP \-F dir
+.OP \-I dir
.OP \-p papersize
.OP \-P prologue
.OP \-w n
@@ -112,6 +117,15 @@ using the
.B \-P
option.
.
+.PP
+Note that
+.B grops
+doesn't produce a valid document structure (conforming to the Document
+Structuring Convention) if called with multiple file arguments.
+.
+To print such concatenated output it is necessary to deactivate DSC
+handling in the printing program or previewer.
+.
.
.SH OPTIONS
.TP
@@ -184,6 +198,9 @@ PostScript command).
This was the behaviour of groff version 1.18.1 and earlier; it is needed
for older printers which don't understand PostScript LanguageLevel\~2.
.
+It is also necessary if the output is further processed to get an
+encapsulated PS (EPS) file -- see below.
+.
.IP
The default value can be specified by a
.
@@ -225,6 +242,19 @@ 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
+.BI \-I dir
+This option may be used to specify a directory to search for
+files on the command line and files named in
+.B \eX'ps: import'
+and
+.B \eX'ps: file'
+escapes.
+The current directory is always searched first.
+This option may be specified more than once;
+the directories will be searched in the order specified.
+No directory search is performed for files specified using an absolute path.
+.
+.TP
.B \-l
Print the document in landscape format.
.
@@ -754,7 +784,7 @@ commands.
.RS
.LP
For example,
-.B gxditview
+.B \%gxditview
is not able to display a proper
.B \[rs](em
character because the standard X11 fonts do not provide it;
@@ -772,7 +802,7 @@ request
.
.LP
In this case,
-.B gxditview
+.B \%gxditview
will be unable to display the
.B \[rs](em
character and will draw the line,
@@ -783,10 +813,10 @@ will print the
character
and ignore the line (this code is already in file
.B Xps.tmac
-which will be loaded if a documented intended for
+which will be loaded if a document intended for
.B grops
is previewed with
-.BR gxditview ).
+.BR \%gxditview ).
.RE
.
.LP
@@ -1002,6 +1032,32 @@ comments)
should be used.
.
.
+.SS Encapsulated PostScript
+.B grops
+itself doesn't emit bounding box information.
+.
+With the help of GhostScript the following commands will produce an
+encapsulated PS file
+.B foo.eps
+from input file
+.BR foo :
+.
+.IP
+.B
+groff -P-b16 foo > foo.ps
+.br
+.B
+gs -dNOPAUSE -sDEVICE=bbox -- foo.ps 2> foo.bbox
+.br
+.B
+cat foo.ps | sed \-e '/%%Orientation/rfoo.bbx' > foo.eps
+.br
+.B
+rm foo.bbx
+.br
+.
+.
+.
.SS TrueType fonts
TrueType fonts can be used with
.B grops
@@ -1103,6 +1159,12 @@ Temporary file.
.BR groff_char (@MAN7EXT@),
.BR groff_tmac (@MAN5EXT@)
.
+.PP
+.URL "http://\:partners.adobe.com/\:public/\:developer/\:en/\:ps/\:5001.DSC_Spec.pdf" \
+ "PostScript Language Document Structuring Conventions Specification"
+.
+.cp \n[grops_C]
+.
.\" Local Variables:
.\" mode: nroff
.\" End:
diff --git a/contrib/groff/src/devices/grops/ps.cpp b/contrib/groff/src/devices/grops/ps.cpp
index f1c094b..b6a5403 100644
--- a/contrib/groff/src/devices/grops/ps.cpp
+++ b/contrib/groff/src/devices/grops/ps.cpp
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001, 2002, 2003
+/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001, 2002, 2003, 2004
Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
@@ -17,7 +17,7 @@ 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. */
+Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */
/*
* PostScript documentation:
@@ -42,6 +42,9 @@ extern "C" {
extern "C" const char *Version_string;
+// search path defaults to the current directory
+search_path include_search_path(0, 0, 0, 1);
+
static int landscape_flag = 0;
static int manual_feed_flag = 0;
static int ncopies = 1;
@@ -326,9 +329,14 @@ ps_output &ps_output::put_fix_number(int i)
ps_output &ps_output::put_float(double d)
{
char buf[128];
- sprintf(buf, "%.3g", d);
- int len = strlen(buf);
- if (col > 0 && col + len + need_space > max_line_length) {
+ sprintf(buf, "%.4f", d);
+ int last = strlen(buf) - 1;
+ while (buf[last] == '0')
+ last--;
+ if (buf[last] == '.')
+ last--;
+ buf[++last] = '\0';
+ if (col > 0 && col + last + need_space > max_line_length) {
putc('\n', fp);
col = 0;
need_space = 0;
@@ -338,7 +346,7 @@ ps_output &ps_output::put_float(double d)
col++;
}
fputs(buf, fp);
- col += len;
+ col += last;
need_space = 1;
return *this;
}
@@ -789,7 +797,7 @@ void ps_printer::define_encoding(const char *encoding, int encoding_index)
p++;
if (*p != '#' && *p != '\0' && (p = strtok(buf, WS)) != 0) {
char *q = strtok(0, WS);
- int n;
+ int n = 0; // pacify compiler
if (q == 0 || sscanf(q, "%d", &n) != 1 || n < 0 || n >= 256)
fatal_with_file_and_line(path, lineno, "bad second field");
vec[n] = new char[strlen(p) + 1];
@@ -1790,7 +1798,7 @@ int main(int argc, char **argv)
{ "version", no_argument, 0, 'v' },
{ NULL, 0, 0, 0 }
};
- while ((c = getopt_long(argc, argv, "b:c:F:glmp:P:vw:", long_options, NULL))
+ while ((c = getopt_long(argc, argv, "b:c:F:gI:lmp:P:vw:", long_options, NULL))
!= EOF)
switch(c) {
case 'b':
@@ -1810,6 +1818,9 @@ int main(int argc, char **argv)
case 'g':
guess_flag = 1;
break;
+ case 'I':
+ include_search_path.command_line_dir(optarg);
+ break;
case 'l':
landscape_flag = 1;
break;
@@ -1864,6 +1875,7 @@ int main(int argc, char **argv)
static void usage(FILE *stream)
{
fprintf(stream,
- "usage: %s [-glmv] [-b n] [-c n] [-w n] [-P prologue] [-F dir] [files ...]\n",
+"usage: %s [-glmv] [-b n] [-c n] [-w n] [-I dir] [-P prologue]\n"
+" [-F dir] [files ...]\n",
program_name);
}
diff --git a/contrib/groff/src/devices/grops/ps.h b/contrib/groff/src/devices/grops/ps.h
index a4b4169..fabf47d 100644
--- a/contrib/groff/src/devices/grops/ps.h
+++ b/contrib/groff/src/devices/grops/ps.h
@@ -17,7 +17,7 @@ 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. */
+Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */
class ps_output {
public:
@@ -123,3 +123,7 @@ enum {
USE_PS_ADOBE_2_0 = 010,
NO_PAPERSIZE = 020
};
+
+#include "searchpath.h"
+
+extern search_path include_search_path;
diff --git a/contrib/groff/src/devices/grops/psrm.cpp b/contrib/groff/src/devices/grops/psrm.cpp
index ab94ffe..f1894f5 100644
--- a/contrib/groff/src/devices/grops/psrm.cpp
+++ b/contrib/groff/src/devices/grops/psrm.cpp
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001, 2002, 2003
+/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001, 2002, 2003, 2004
Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
@@ -17,7 +17,7 @@ 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. */
+Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */
#include "driver.h"
#include "stringclass.h"
@@ -347,7 +347,7 @@ void resource_manager::supply_resource(resource *r, int rank, FILE *outfp,
r->flags |= resource::BUSY;
if (rank > r->rank)
r->rank = rank;
- char *path;
+ char *path = 0; // pacify compiler
FILE *fp = 0;
if (r->filename != 0) {
if (r->type == RESOURCE_FONT) {
@@ -360,7 +360,7 @@ void resource_manager::supply_resource(resource *r, int rank, FILE *outfp,
}
else {
errno = 0;
- fp = fopen(r->filename, "r");
+ fp = include_search_path.open_file_cautious(r->filename);
if (!fp) {
error("can't open `%1': %2", r->filename, strerror(errno));
a_delete r->filename;
diff --git a/contrib/groff/src/devices/grotty/grotty.man b/contrib/groff/src/devices/grotty/grotty.man
index 198ca47..6c56457 100644
--- a/contrib/groff/src/devices/grotty/grotty.man
+++ b/contrib/groff/src/devices/grotty/grotty.man
@@ -1,5 +1,5 @@
.ig
-Copyright (C) 1989-2000, 2001, 2002 Free Software Foundation, Inc.
+Copyright (C) 1989-2000, 2001, 2002, 2003 Free Software Foundation, Inc.
Permission is granted to make and distribute verbatim copies of
this manual provided the copyright notice and this permission notice
@@ -17,6 +17,8 @@ translations approved by the Free Software Foundation instead of in
the original English.
..
.
+.do nr grotty_C \n[.C]
+.cp 0
.
.TH GROTTY @MAN1EXT@ "@MDATE@" "Groff Version @VERSION@"
.SH NAME
@@ -414,6 +416,8 @@ cell, affecting all subsequent operations.
.BR man (1),
.BR less (1)
.
+.cp \n[grotty_C]
+.
.\" Local Variables:
.\" mode: nroff
.\" End:
diff --git a/contrib/groff/src/devices/grotty/tty.cpp b/contrib/groff/src/devices/grotty/tty.cpp
index 812ebf8..a959461 100644
--- a/contrib/groff/src/devices/grotty/tty.cpp
+++ b/contrib/groff/src/devices/grotty/tty.cpp
@@ -1,5 +1,6 @@
// -*- C++ -*-
-/* Copyright (C) 1989-2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 1989-2000, 2001, 2002, 2003, 2004, 2005
+ Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
This file is part of groff.
@@ -16,14 +17,16 @@ 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. */
+Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */
#include "driver.h"
#include "device.h"
#include "ptable.h"
-declare_ptable(char)
-implement_ptable(char)
+typedef signed char schar;
+
+declare_ptable(schar)
+implement_ptable(schar)
extern "C" const char *Version_string;
@@ -41,25 +44,38 @@ extern "C" const char *Version_string;
static int horizontal_tab_flag = 0;
static int form_feed_flag = 0;
-static int bold_flag = 1;
-static int underline_flag = 1;
+static int bold_flag_option = 1;
+static int bold_flag;
+static int underline_flag_option = 1;
+static int underline_flag;
static int overstrike_flag = 1;
static int draw_flag = 1;
-static int italic_flag = 0;
-static int reverse_flag = 0;
+static int italic_flag_option = 0;
+static int italic_flag;
+static int reverse_flag_option = 0;
+static int reverse_flag;
static int old_drawing_scheme = 0;
+static void update_options();
+static void usage(FILE *stream);
+
+static int hline_char = '-';
+static int vline_char = '|';
+
enum {
UNDERLINE_MODE = 0x01,
BOLD_MODE = 0x02,
VDRAW_MODE = 0x04,
HDRAW_MODE = 0x08,
CU_MODE = 0x10,
- COLOR_CHANGE = 0x20
+ COLOR_CHANGE = 0x20,
+ START_LINE = 0x40,
+ END_LINE = 0x80
};
// Mode to use for bold-underlining.
-static unsigned char bold_underline_mode = BOLD_MODE|UNDERLINE_MODE;
+static unsigned char bold_underline_mode_option = BOLD_MODE|UNDERLINE_MODE;
+static unsigned char bold_underline_mode;
#ifndef IS_EBCDIC_HOST
#define CSI "\033["
@@ -77,7 +93,7 @@ static unsigned char bold_underline_mode = BOLD_MODE|UNDERLINE_MODE;
#define SGR_REVERSE CSI "7m"
#define SGR_NO_REVERSE CSI "27m"
// many terminals can't handle `CSI 39 m' and `CSI 49 m' to reset
-// the foreground and bachground color, respectively; thus we use
+// the foreground and background color, respectively; we thus use
// `CSI 0 m' exclusively
#define SGR_DEFAULT CSI "0m"
@@ -105,13 +121,14 @@ tty_font *tty_font::load_tty_font(const char *s)
const char *num = f->get_internal_name();
long n;
if (num != 0 && (n = strtol(num, 0, 0)) != 0)
- f->mode = int(n & (BOLD_MODE|UNDERLINE_MODE));
+ f->mode = (unsigned char)(n & (BOLD_MODE|UNDERLINE_MODE));
if (!underline_flag)
f->mode &= ~UNDERLINE_MODE;
if (!bold_flag)
f->mode &= ~BOLD_MODE;
if ((f->mode & (BOLD_MODE|UNDERLINE_MODE)) == (BOLD_MODE|UNDERLINE_MODE))
- f->mode = (f->mode & ~(BOLD_MODE|UNDERLINE_MODE)) | bold_underline_mode;
+ f->mode = (unsigned char)((f->mode & ~(BOLD_MODE|UNDERLINE_MODE))
+ | bold_underline_mode);
return f;
}
@@ -138,11 +155,12 @@ class glyph {
static glyph *free_list;
public:
glyph *next;
- short hpos;
+ int w;
+ int hpos;
unsigned int code;
unsigned char mode;
- char back_color_idx;
- char fore_color_idx;
+ schar back_color_idx;
+ schar fore_color_idx;
void *operator new(size_t);
void operator delete(void *);
inline int draw_mode() { return mode & (VDRAW_MODE|HDRAW_MODE); }
@@ -181,19 +199,19 @@ class tty_printer : public printer {
int nlines;
int cached_v;
int cached_vpos;
- char curr_fore_idx;
- char curr_back_idx;
+ schar curr_fore_idx;
+ schar curr_back_idx;
int is_underline;
int is_bold;
int cu_flag;
- PTABLE(char) tty_colors;
- void make_underline();
- void make_bold(unsigned int);
- char color_to_idx(color *col);
- void add_char(unsigned int, int, int, color *, color *, unsigned char);
+ PTABLE(schar) tty_colors;
+ void make_underline(int);
+ void make_bold(unsigned int, int);
+ schar color_to_idx(color *col);
+ void add_char(unsigned int, int, int, int, color *, color *, unsigned char);
char *make_rgb_string(unsigned int, unsigned int, unsigned int);
- int tty_color(unsigned int, unsigned int, unsigned int, char *,
- char = DEFAULT_COLOR_IDX);
+ int tty_color(unsigned int, unsigned int, unsigned int, schar *,
+ schar = DEFAULT_COLOR_IDX);
public:
tty_printer(const char *device);
~tty_printer();
@@ -203,7 +221,7 @@ public:
void change_color(const environment * const env);
void change_fill_color(const environment * const env);
void put_char(unsigned int);
- void put_color(char, int);
+ void put_color(schar, int);
void begin_page(int) { }
void end_page(int page_length);
font *make_font(const char *);
@@ -233,14 +251,14 @@ char *tty_printer::make_rgb_string(unsigned int r,
int tty_printer::tty_color(unsigned int r,
unsigned int g,
- unsigned int b, char *idx, char value)
+ unsigned int b, schar *idx, schar value)
{
int unknown_color = 0;
char *s = make_rgb_string(r, g, b);
- char *i = tty_colors.lookup(s);
+ schar *i = tty_colors.lookup(s);
if (!i) {
unknown_color = 1;
- i = new char[1];
+ i = new schar[1];
*i = value;
tty_colors.define(s, i);
}
@@ -249,10 +267,14 @@ int tty_printer::tty_color(unsigned int r,
return unknown_color;
}
-tty_printer::tty_printer(const char *device) : cached_v(0)
+tty_printer::tty_printer(const char *dev) : cached_v(0)
{
- is_utf8 = !strcmp(device, "utf8");
- char dummy;
+ is_utf8 = !strcmp(dev, "utf8");
+ if (is_utf8) {
+ hline_char = 0x2500;
+ vline_char = 0x2502;
+ }
+ schar dummy;
// black, white
(void)tty_color(0, 0, 0, &dummy, 0);
(void)tty_color(color::MAX_COLOR_VAL,
@@ -278,11 +300,18 @@ tty_printer::~tty_printer()
a_delete lines;
}
-void tty_printer::make_underline()
+void tty_printer::make_underline(int w)
{
if (old_drawing_scheme) {
- putchar('_');
- putchar('\b');
+ if (!w)
+ warning("can't underline zero-width character");
+ else {
+ int n = w / font::hor;
+ for (int i = 0; i < n; i++)
+ putchar('_');
+ for (int j = 0; j < n; j++)
+ putchar('\b');
+ }
}
else {
if (!is_underline) {
@@ -297,11 +326,17 @@ void tty_printer::make_underline()
}
}
-void tty_printer::make_bold(unsigned int c)
+void tty_printer::make_bold(unsigned int c, int w)
{
if (old_drawing_scheme) {
- put_char(c);
- putchar('\b');
+ if (!w)
+ warning("can't print zero-width character in bold");
+ else {
+ int n = w / font::hor;
+ put_char(c);
+ for (int i = 0; i < n; i++)
+ putchar('\b');
+ }
}
else {
if (!is_bold)
@@ -310,13 +345,13 @@ void tty_printer::make_bold(unsigned int c)
}
}
-char tty_printer::color_to_idx(color *col)
+schar tty_printer::color_to_idx(color *col)
{
if (col->is_default())
return DEFAULT_COLOR_IDX;
unsigned int r, g, b;
col->get_rgb(&r, &g, &b);
- char idx;
+ schar idx;
if (tty_color(r, g, b, &idx)) {
char *s = col->print_color();
error("Unknown color (%1) mapped to default", s);
@@ -328,15 +363,15 @@ char tty_printer::color_to_idx(color *col)
void tty_printer::set_char(int i, font *f, const environment *env,
int w, const char *)
{
- if (w != font::hor)
- fatal("width of character not equal to horizontal resolution");
- add_char(f->get_code(i),
+ if (w % font::hor != 0)
+ fatal("width of character not a multiple of horizontal resolution");
+ add_char(f->get_code(i), w,
env->hpos, env->vpos,
env->col, env->fill,
((tty_font *)f)->get_mode());
}
-void tty_printer::add_char(unsigned int c,
+void tty_printer::add_char(unsigned int c, int w,
int h, int v,
color *fore, color *back,
unsigned char mode)
@@ -377,6 +412,7 @@ void tty_printer::add_char(unsigned int c,
cached_vpos = vpos;
}
glyph *g = new glyph;
+ g->w = w;
g->hpos = hpos;
g->code = c;
g->fore_color_idx = color_to_idx(fore);
@@ -400,7 +436,8 @@ void tty_printer::add_char(unsigned int c,
void tty_printer::special(char *arg, const environment *env, char type)
{
if (type == 'u') {
- add_char(*arg - '0', env->hpos, env->vpos, env->col, env->fill, CU_MODE);
+ add_char(*arg - '0', 0, env->hpos, env->vpos, env->col, env->fill,
+ CU_MODE);
return;
}
if (type != 'p')
@@ -433,17 +470,18 @@ void tty_printer::special(char *arg, const environment *env, char type)
old_drawing_scheme = 1;
else
old_drawing_scheme = 0;
+ update_options();
}
}
void tty_printer::change_color(const environment * const env)
{
- add_char(0, env->hpos, env->vpos, env->col, env->fill, COLOR_CHANGE);
+ add_char(0, 0, env->hpos, env->vpos, env->col, env->fill, COLOR_CHANGE);
}
void tty_printer::change_fill_color(const environment * const env)
{
- add_char(0, env->hpos, env->vpos, env->col, env->fill, COLOR_CHANGE);
+ add_char(0, 0, env->hpos, env->vpos, env->col, env->fill, COLOR_CHANGE);
}
void tty_printer::draw(int code, int *p, int np, const environment *env)
@@ -462,10 +500,22 @@ void tty_printer::draw(int code, int *p, int np, const environment *env)
v += len;
len = -len;
}
- while (len >= 0) {
- add_char('|', env->hpos, v, env->col, env->fill, VDRAW_MODE);
+ if (len >= 0 && len <= font::vert)
+ add_char(vline_char, font::hor, env->hpos, v, env->col, env->fill,
+ VDRAW_MODE|START_LINE|END_LINE);
+ else {
+ add_char(vline_char, font::hor, env->hpos, v, env->col, env->fill,
+ VDRAW_MODE|START_LINE);
len -= font::vert;
v += font::vert;
+ while (len > 0) {
+ add_char(vline_char, font::hor, env->hpos, v, env->col, env->fill,
+ VDRAW_MODE|START_LINE|END_LINE);
+ len -= font::vert;
+ v += font::vert;
+ }
+ add_char(vline_char, font::hor, env->hpos, v, env->col, env->fill,
+ VDRAW_MODE|END_LINE);
}
}
if (p[1] == 0) {
@@ -476,10 +526,22 @@ void tty_printer::draw(int code, int *p, int np, const environment *env)
h += len;
len = -len;
}
- while (len >= 0) {
- add_char('-', h, env->vpos, env->col, env->fill, HDRAW_MODE);
+ if (len >= 0 && len <= font::hor)
+ add_char(hline_char, font::hor, h, env->vpos, env->col, env->fill,
+ HDRAW_MODE|START_LINE|END_LINE);
+ else {
+ add_char(hline_char, font::hor, h, env->vpos, env->col, env->fill,
+ HDRAW_MODE|START_LINE);
len -= font::hor;
h += font::hor;
+ while (len > 0) {
+ add_char(hline_char, font::hor, h, env->vpos, env->col, env->fill,
+ HDRAW_MODE|START_LINE|END_LINE);
+ len -= font::hor;
+ h += font::hor;
+ }
+ add_char(hline_char, font::hor, h, env->vpos, env->col, env->fill,
+ HDRAW_MODE|END_LINE);
}
}
}
@@ -511,7 +573,7 @@ void tty_printer::put_char(unsigned int wc)
putchar(wc);
}
-void tty_printer::put_color(char color_index, int back)
+void tty_printer::put_color(schar color_index, int back)
{
if (color_index == DEFAULT_COLOR_IDX) {
putstring(SGR_DEFAULT);
@@ -541,6 +603,20 @@ void tty_printer::put_color(char color_index, int back)
}
}
+// The possible Unicode combinations for crossing characters.
+//
+// ` ' = 0, ` -' = 4, `- ' = 8, `--' = 12,
+//
+// ` ' = 0, ` ' = 1, `|' = 2, `|' = 3
+// | |
+
+static int crossings[4*4] = {
+ 0x0000, 0x2577, 0x2575, 0x2502,
+ 0x2576, 0x250C, 0x2514, 0x251C,
+ 0x2574, 0x2510, 0x2518, 0x2524,
+ 0x2500, 0x252C, 0x2534, 0x253C
+};
+
void tty_printer::end_page(int page_length)
{
if (page_length % font::vert != 0)
@@ -588,7 +664,12 @@ void tty_printer::end_page(int page_length)
if (nextp && p->hpos == nextp->hpos) {
if (p->draw_mode() == HDRAW_MODE &&
nextp->draw_mode() == VDRAW_MODE) {
- nextp->code = '+';
+ if (is_utf8)
+ nextp->code =
+ crossings[((p->mode & (START_LINE|END_LINE)) >> 4)
+ + ((nextp->mode & (START_LINE|END_LINE)) >> 6)];
+ else
+ nextp->code = '+';
continue;
}
if (p->draw_mode() != 0 && p->draw_mode() == nextp->draw_mode()) {
@@ -611,7 +692,7 @@ void tty_printer::end_page(int page_length)
if (next_tab_pos > p->hpos)
break;
if (cu_flag)
- make_underline();
+ make_underline(p->w);
else if (!old_drawing_scheme && is_underline) {
if (italic_flag)
putstring(SGR_NO_ITALIC);
@@ -627,7 +708,7 @@ void tty_printer::end_page(int page_length)
}
for (; hpos < p->hpos; hpos++) {
if (cu_flag)
- make_underline();
+ make_underline(p->w);
else if (!old_drawing_scheme && is_underline) {
if (italic_flag)
putstring(SGR_NO_ITALIC);
@@ -655,7 +736,7 @@ void tty_printer::end_page(int page_length)
continue;
}
if (p->mode & UNDERLINE_MODE)
- make_underline();
+ make_underline(p->w);
else if (!old_drawing_scheme && is_underline) {
if (italic_flag)
putstring(SGR_NO_ITALIC);
@@ -666,7 +747,7 @@ void tty_printer::end_page(int page_length)
is_underline = 0;
}
if (p->mode & BOLD_MODE)
- make_bold(p->code);
+ make_bold(p->code, p->w);
else if (!old_drawing_scheme && is_bold) {
putstring(SGR_NO_BOLD);
is_bold = 0;
@@ -682,7 +763,7 @@ void tty_printer::end_page(int page_length)
}
}
put_char(p->code);
- hpos++;
+ hpos += p->w / font::hor;
}
if (!old_drawing_scheme
&& (is_bold || is_underline
@@ -711,7 +792,23 @@ printer *make_printer()
return new tty_printer(device);
}
-static void usage(FILE *stream);
+static void update_options()
+{
+ if (old_drawing_scheme) {
+ italic_flag = 0;
+ reverse_flag = 0;
+ bold_underline_mode = bold_underline_mode_option;
+ bold_flag = bold_flag_option;
+ underline_flag = underline_flag_option;
+ }
+ else {
+ italic_flag = italic_flag_option;
+ reverse_flag = reverse_flag_option;
+ bold_underline_mode = BOLD_MODE|UNDERLINE_MODE;
+ bold_flag = 1;
+ underline_flag = 1;
+ }
+}
int main(int argc, char **argv)
{
@@ -726,7 +823,7 @@ int main(int argc, char **argv)
{ "version", no_argument, 0, 'v' },
{ NULL, 0, 0, 0 }
};
- while ((c = getopt_long(argc, argv, "bBcdfF:hioruUv", long_options, NULL))
+ while ((c = getopt_long(argc, argv, "bBcdfF:hiI:oruUv", long_options, NULL))
!= EOF)
switch(c) {
case 'v':
@@ -735,11 +832,14 @@ int main(int argc, char **argv)
break;
case 'i':
// Use italic font instead of underlining.
- italic_flag = 1;
+ italic_flag_option = 1;
+ break;
+ case 'I':
+ // ignore include search path
break;
case 'b':
// Do not embolden by overstriking.
- bold_flag = 0;
+ bold_flag_option = 0;
break;
case 'c':
// Use old scheme for emboldening and underline.
@@ -747,7 +847,7 @@ int main(int argc, char **argv)
break;
case 'u':
// Do not underline.
- underline_flag = 0;
+ underline_flag_option = 0;
break;
case 'o':
// Do not overstrike (other than emboldening and underlining).
@@ -755,15 +855,15 @@ int main(int argc, char **argv)
break;
case 'r':
// Use reverse mode instead of underlining.
- reverse_flag = 1;
+ reverse_flag_option = 1;
break;
case 'B':
// Do bold-underlining as bold.
- bold_underline_mode = BOLD_MODE;
+ bold_underline_mode_option = BOLD_MODE;
break;
case 'U':
// Do bold-underlining as underlining.
- bold_underline_mode = UNDERLINE_MODE;
+ bold_underline_mode_option = UNDERLINE_MODE;
break;
case 'h':
// Use horizontal tabs.
@@ -790,15 +890,7 @@ int main(int argc, char **argv)
default:
assert(0);
}
- if (old_drawing_scheme) {
- italic_flag = 0;
- reverse_flag = 0;
- }
- else {
- bold_underline_mode = BOLD_MODE|UNDERLINE_MODE;
- bold_flag = 1;
- underline_flag = 1;
- }
+ update_options();
if (optind >= argc)
do_file("-");
else {
diff --git a/contrib/groff/src/devices/xditview/ChangeLog b/contrib/groff/src/devices/xditview/ChangeLog
new file mode 100644
index 0000000..41ea31c
--- /dev/null
+++ b/contrib/groff/src/devices/xditview/ChangeLog
@@ -0,0 +1,542 @@
+2004-05-29 Werner LEMBERG <wl@gnu.org>
+
+ gxditview and xtotroff have been integrated into the normal groff
+ directory structure; future changes are logged in the main
+ ChangeLog file.
+
+2004-05-13 Werner LEMBERG <wl@gnu.org>
+
+Version 1.19.1 released
+=======================
+
+2004-04-17 Werner LEMBERG <wl@gnu.org>
+
+ * device.c (scale_round): Round correctly for negative values
+ (this is the same function as in src/libs/libgroff/font.c).
+ Found by Paul Eggert.
+
+2003-11-10 Werner LEMBERG <wl@gnu.org>
+
+ * Imakefile.in: s/@top_srcdir@/@abs_top_srcdir@/,
+ s/@groff_top_builddir@/@abs_top_builddir@/.
+
+Version 1.19 released
+=====================
+
+2003-03-03 Werner LEMBERG <wl@gnu.org>
+
+ * Imakefile.in (extraclean): Added gxditview._man.
+
+2003-01-28 Werner LEMBERG <wl@gnu.org>
+
+ * Imakefile.in (SEP): New variable; set to @PATH_SEPARATOR@.
+ (GROFF_FONTPATH): Use it.
+
+2003-01-07 Werner LEMBERG <wl@gnu.org>
+
+ * DviChar.c (Adobe_Symbol_map): Add `sqrt'.
+
+2003-01-06 Werner LEMBERG <wl@gnu.org>
+
+ * DviChar.c (Adobe_Symbol_map): Add `integral'.
+
+2002-12-29 Werner LEMBERG <wl@gnu.org>
+
+ * DviChar.c (ISO_8859_1_map): Remove `ap' and `eq'.
+
+2002-12-20 Werner LEMBERG <wl@gnu.org>
+
+ * DviChar.c (Adobe_Symbol_map): Don't include `or'.
+ * draw.c (AdjustCharDeltas): Apply correction only if nadj > 1.
+ (DoCharacter): Call FlushCharCache if font size and font number
+ differ.
+ Reset `dw->dvi.cache.adjustable' properly.
+
+2002-12-09 Werner LEMBERG <wl@gnu.org>
+
+ * DviChar.c (ISO_8859_1_map): Use `tno' symbol instead of `no'.
+
+2002-12-01 Werner LEMBERG <wl@gnu.org>
+
+ * Imakefile.in: Use `InstallAppDefaultsLong' instead of
+ `InstallAppDefaults' to make it work if build directory isn't
+ $srcdir.
+
+2002-11-24 Werner LEMBERG <wl@gnu.org>
+
+ * DviChar.c (Adobe_Symbol_map): Add glyph `braceex'.
+
+2002-11-14 Werner LEMBERG <wl@gnu.org>
+
+ * DviChar.c (ISO_8859_1_map): Don't include `or'.
+
+Version 1.18.1 released
+=======================
+
+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
+ filename strings as ignored comments.
+
+2000-12-02 Werner LEMBERG <wl@gnu.org>
+
+ * device.c (find_file): Remove home directory in search path.
+
+2000-11-14 Werner LEMBERG <wl@gnu.org>
+
+ * device.c (open_device_file): Remove `path' parameter.
+ (find_file): Construct font path similar to groff: First the contents
+ of GROFF_FONT_PATH, then the home directory, and finally the default
+ font path.
+ * Imakefile.in: Fix GROFF_DATAPROGRAMDIR and GROFF_FONTPATH.
+
+2000-10-23 Werner LEMBERG <wl@gnu.org>
+
+ Change installation structure for data files from .../groff/... to
+ .../groff/<version><revision>/... to be conform with other GNU
+ programs.
+
+ * Imakefile.in: Implement it.
+
+Version 1.16.1 released
+=======================
+
+Version 1.16 released
+=====================
+
+2000-05-18 Werner LEMBERG <wl@gnu.org>
+
+ * DviChar.c: Adding `cq' as an alias for "'" in latin-1 map.
+
+2000-05-03 Werner LEMBERG <wl@gnu.org>
+
+ * DviChar.c: Adding `dq' as an alias for `"' in latin-1 map.
+
+2000-04-28 Werner LEMBERG <wl@gnu.org>
+
+ * DviChar.c: Replacing `md' glyph name with `pc' in latin-1 map to
+ make it distinct from the `md' glyph in the symbol font.
+
+2000-03-03 Werner LEMBERG <wl@gnu.org>
+
+ * Imakefile replaced with Imakefile.in which will be configured by
+ the main configure script of groff. This will set the correct font
+ path, and it will make it possible to build xditview in a directory
+ different from $srcdir.
+
+2000-03-01 Colin Phipps <crp22@cam.ac.uk>
+
+ * Dvi.c (OpenFile): Use tmpdir() for security reasons.
+ * xtotroff.c (MapFont): Avoid race while opening file.
+
+2000-02-06 Werner LEMBERG <wl@gnu.org>
+
+ * Imakefile: Adapted to new directory structure.
+
+ * README: Updated.
+
+Version 1.15 released
+=====================
+
+1999-12-21 Werner LEMBERG <wl@gnu.org>
+
+ * README: Fixed ftp GNU address.
+
+1999-12-13 Werner LEMBERG <wl@gnu.org>
+
+ * device.c: Use extern declarations of strtok(), strchr(), and
+ getenv() only if not defined as macros.
+
+1999-11-18 Larry Jones <larry.jones@sdrc.com>
+
+ * xditview.c: Add fallback_resources to allow running without
+ access to the app-defaults file.
+
+ * Imakefile: Added rule to create app-defaults to a C header file.
+
+ * GXditview-ad.h: New file containing fallback default resources.
+
+ * ad2c: New file to do the app-defaults -> C header file
+ conversion.
+
+1999-10-27 Larry Jones <larry.jones@sdrc.com>
+
+ * font.c (DisposeFontSizes): If there's a problem loading a font,
+ xditview will fall-back and use the default font, but it hasn't
+ checked before unloading fonts which could result in unloading the
+ default font (possibly multiple times) and then X errors.
+
+1999-09-13 Werner LEMBERG <wl@gnu.org>
+
+ * Imakefile (extraclean): Added Makefile.
+
+ * xditview.c (main, MakePrompt): Fixing compilation warnings.
+
+ * TODO: Imakefile should be replaced with a configure script.
+
+1999-09-13 Werner LEMBERG <wl@gnu.org>
+
+ * Makefile: Removed.
+
+1999-09-12 Werner LEMBERG <wl@gnu.org>
+
+ * Imakefile (GROFF_FONTPATH): Another addition.
+
+ * device.c (FONTPATH): Update to match current groff version.
+
+1999-09-11 Larry Jones <larry.jones@sdrc.com>
+
+ * Imakefile (GROFF_LIBDIR, GROFF_FONTPATH): Update to match
+ current groff version.
+
+ * Dvi.c (Realize, Destroy), DviP.h, draw.c (setFillGC), gray*.bm:
+ Allow 8 levels of gray rather than just 1.
+
+ * draw.c (DrawFilledCircle, DrawFilledEllipse, DrawFilledPolygon):
+ Draw outlines to prevent gaps between abutting figures.
+
+1999-05-27 Werner LEMBERG <wl@gnu.org>
+
+ * xtotroff.c (usage): Fixed typo.
+
+Mon Sep 11 10:40:33 1995 James Clark <jjc@jclark.com>
+
+ * device.c (INT_MIN, INT_MAX): Don't define if already defined.
+
+Mon Aug 8 11:14:11 1994 James Clark (jjc@jclark.com)
+
+ * DviChar.c (Adobe_Symbol_map): Use \(nb for notsubset.
+
+Tue Apr 19 04:41:16 1994 James Clark (jjc@jclark.com)
+
+ * Dvi.c (resources): Change default for background and foreground
+ to "XtDefaultBackground" and "XtDefaultForeground".
+
+Sat Feb 12 10:38:47 1994 James Clark (jjc@jclark.com)
+
+ * DviChar.c (Adobe_Symbol_map): Rename radicalex to rn.
+
+Thu May 27 20:30:12 1993 James Clark (jjc@jclark.com)
+
+ * device.c (isascii): Define if necessary.
+ (canonicalize_name): Cast argument to isdigit() to unsigned char.
+
+Thu Apr 29 18:36:57 1993 James Clark (jjc at jclark.com)
+
+ * xditview.c: Include <X11/Xos.h>.
+ (NewFile): Don't declare rindex(). Use strrchr() rather than
+ rindex().
+
+Tue Mar 30 15:12:09 1993 James Clark (jjc at jclark)
+
+ * draw.c (charExists): Check that fi->per_char is not NULL.
+
+Sat Dec 12 17:42:40 1992 James Clark (jjc at jclark)
+
+ * Dvi.c (SetGeometry): Cast XtMakeGeometryRequest arguments.
+
+ * draw.c (DrawPolygon, DrawFilledPolygon): Cast Xtfree argument.
+
+ * font.c (DisposeFontSizes): Add declaration.
+
+ * draw.c (FakeCharacter): Add declaration.
+
+Wed Oct 28 13:24:00 1992 James Clark (jjc at jclark)
+
+ * Imakefile (install.dev): Deleted.
+ (fonts): New target.
+
+Mon Oct 12 10:50:44 1992 James Clark (jjc at jclark)
+
+ * Imakefile (install.dev): Say when we're installing devX*-12.
+
+ * Imakefile (install.dev): Depends on DESC and FontMap.
+
+Thu Oct 1 20:03:45 1992 James Clark (jjc at jclark)
+
+ * xditview.c (Syntax): Mention -filename option.
+
+Sat Aug 15 12:56:39 1992 James Clark (jjc at jclark)
+
+ * GXditview.ad: Bind space and return to NextPage. Bind backspace
+ and delete to previous page.
+
+ * DviChar.c (Adobe_Symbol_map): Add `an'.
+
+ * DviChar.c (Adobe_Symbol_map): Add arrowvertex, arrowverttp, and
+ arrowvertbt.
+
+Mon Aug 10 11:54:27 1992 James Clark (jjc at jclark)
+
+ * FontMap: Add m/p fields to the fonts names.
+
+Sat Aug 8 12:00:28 1992 James Clark (jjc at jclark)
+
+ * DESC: Leave font positions 5-9 blank.
+
+Tue Jul 28 11:37:05 1992 James Clark (jjc at jclark)
+
+ * Imakefile: Don't use gendef. Pass definition of FONTPATH using
+ DEFINES.
+ (path.h): Deleted.
+ (device.c): Don't include path.h. Provide default definition of
+ FONTPATH.
+
+Mon Jul 6 14:06:53 1992 James Clark (jjc at jclark)
+
+ * Imakefile: Don't install tmac.X and tmac.Xps.
+ * tmac.X, tmac.Xps: Moved to ../macros.
+
+ * Imakefile: Don't install eqnchar.
+ * eqnchar: Deleted.
+
+Sun Jun 14 12:55:02 1992 James Clark (jjc@jclark)
+
+ * tmac.Xps: Handle OE, oe, lq, rq.
+ * draw.c (FakeCharacter): Don't handle these.
+
+ * draw.c (FakeCharacter): Don't handle f/.
+
+Mon Jun 8 11:46:37 1992 James Clark (jjc@jclark)
+
+ * tmac.X: Translate char160 to space.
+
+Sun Jun 7 14:39:53 1992 James Clark (jjc@jclark)
+
+ * tmac.X: Do `mso tmac.psic' before restoring compatibility mode.
+
+ * tmac.X: Add \(OE, \(oe, \(ah, \(ao, \(ho.
+
+ * tmac.Xps: Make it work in compatibility mode.
+ Redo existing character definitions with .Xps-char.
+ Add more character definitions.
+ (Xps-char): New macro.
+
+Sat Jun 6 21:46:03 1992 James Clark (jjc@jclark)
+
+ * DviChar.c (Adobe_Symbol_map): Add +h, +f, +p, Fn, lz.
+ * tmac.X: Add \(bq, \(Bq, \(aq.
+ * tmac.Xps: Handle \(aq, \(bq, \(Bq, \(Fn.
+
+Wed Jun 3 11:11:15 1992 James Clark (jjc@jclark)
+
+ * DviChar.c (Adobe_Symbol_map): Add wp.
+
+Tue Apr 21 09:21:59 1992 James Clark (jjc at jclark)
+
+ * GXditview.ad: Bind n, p, q keys to NextPage, PreviousPage and
+ Quit actions.
+
+ * xditview.c (RerasterizeAction): New function.
+ (xditview_actions): Add RerasterizeAction.
+ * GXditview.ad: Bind r key to Rerasterize action.
+
+Fri Apr 17 08:25:36 1992 James Clark (jjc at jclark)
+
+ * xditview.c: Add -filename option.
+ (main): Copy any -filename argument into current_file_name.
+
+Mon Mar 16 10:21:58 1992 James Clark (jjc at jclark)
+
+ * tmac.X: Load tmac.pspic.
+
+Sun Mar 8 11:27:19 1992 James Clark (jjc at jclark)
+
+ * Lex.c (GetLine, GetWord, GetNumber): Rewrite.
+
+Sat Oct 12 22:58:52 1991 James Clark (jjc at jclark)
+
+ * Dvi.c (SetDevice): If the size change request is refused but a
+ larger geometry is offered, request that.
+
+Wed Oct 9 12:27:48 1991 James Clark (jjc at jclark)
+
+ * font.c (InstallFontSizes): Ignore FontNameAverageWidth component.
+
+ * Dvi.c (default_font_map): Add `adobe' to font names to avoid
+ ambiguity.
+
+ * FontMap: New file.
+ * FontMap.X100, FontMap.X75: Deleted.
+ * xtotroff.c (main, usage): Add -s and -r options.
+ (MapFont): Change the font pattern to have the selected resolution and
+ size.
+ * Imakefile (install.dev): Use FontMap and supply appropriate -s
+ and -r options.
+
+ * xtotroff.c (MapFont): Check for ambiguity by comparing canonicalized
+ font names.
+
+ * DviP.h (DviFontList): Add initialized and scalable members.
+ (font.c): Add support for scalable fonts based on R5 xditview.
+
+ * DviChar.c: Use xmalloc rather than malloc.
+ * xditview.c (xmalloc): New function.
+ * xtotroff.c (xmalloc): New function.
+ * other files: Use XtMalloc and XtFree instead of malloc and free.
+
+Thu Aug 29 20:15:31 1991 James Clark (jjc at jclark)
+
+ * draw.c (setGC): Do multiplication in floating point to avoid
+ overflow.
+
+Tue Aug 13 12:04:41 1991 James Clark (jjc at jclark)
+
+ * draw.c (FakeCharacter): Remove casts in defintion of pack2.
+
+Tue Jul 30 11:42:39 1991 James Clark (jjc at jclark)
+
+ * tmac.Xps: New file.
+ * Imakefile (install): Install tmac.Xps.
+
+Tue Jul 2 09:31:37 1991 James Clark (jjc at jclark)
+
+ * xtotroff.c (main): Pass argv[0] to usage().
+
+Sun Jun 30 12:34:06 1991 James Clark (jjc at jclark)
+
+ * xtotroff.c (MapFont): Handle the case where XLoadQueryFont
+ returns NULL.
+
+Sat Jun 29 12:32:52 1991 James Clark (jjc at jclark)
+
+ * Imakefile: Use ../gendef to generate path.h.
+
+Sun Jun 16 13:26:34 1991 James Clark (jjc at jclark)
+
+ * Imakefile (depend.o): Change to device.o.
+
+Sun Jun 2 12:17:56 1991 James Clark (jjc at jclark)
+
+ * Imakefile: Remove spaces from the beginning of variable
+ assignment lines.
+
+Sun May 26 14:14:01 1991 James Clark (jjc at jclark)
+
+ * xditview.c (Syntax): Update.
+
+ * Dvi.c (DviSaveToFile, SaveToFile): New functions.
+ (FindPage): Check that we're not readingTmp before checking for
+ end of file of normal input file.
+ (ClassPartInitialize): New function.
+ * Dvi.h: Add declaration of DviSaveToFile.
+ * DviP.h: Add save method to DviClassPart. Declare
+ InheritSaveToFile.
+ * xditview.c (DoPrint, Print, PrintAction): New functions.
+ * xditview.c: Add print menu entry.
+ * xditview.c: Provide printCommand application resource.
+ * lex.c: Don't output EOF to temporary file.
+
+ * Dvi.c (QueryGeometry): Check request->request_mode.
+
+ * Dvi.c (SetDevice): New function.
+ (SetDeviceResolution): Deleted.
+
+ * Dvi.c: Add resolution resource.
+ * DviP.h: Add definitions of XtNResolution and XtCResolution.
+ * xditview.c: Add -resolution argument.
+ * GXditview.ad: Add default for GXditview.height.
+ * Dvi.c (Initialize, SetDevice): Use default_resolution.
+
+ * Dvi.c: Make MY_HEIGHT and MY_WIDTH use the paperlength and
+ paperwidth commands in the DESC file.
+
+ * Dvi.c: Add SS font to default font map.
+
+ * draw.c: Rewritten so as not to assume device and display
+ resolution is the same.
+ * DviP.h: Include device.h. Add device_font member to DviFontList.
+ Add adjustable array to DviCharCache. Add text_x_width,
+ text_device_width, word_flag, device_font, device_font_number,
+ device, native, device_resolution, display_resolution,
+ paperlength, paperwidth, scale_factor, sizescale members.
+ * Dvi.c (Initialize): Initialize new variable used by draw.c.
+ (Destroy): Call device_destroy.
+ * font.c (MaxFontPosition): New function.
+ (LookupFontSizeBySize): Handle sizescale.
+ (InstallFont): Load the device font.
+ (ForgetFonts): New function.
+ (QueryDeviceFont): New function.
+ * parse.c (ParseInput): Handle t and u commands. Split off
+ character output into draw.c.
+ (ParseDeviceControl): Ignore res command. Use the device argument
+ to the T command.
+
+ * font.c (MapXNameToDviName): Ifdefed out.
+
+ * path.h: New file.
+ * device.c, device.h: New files.
+
+ * DviChar.c: Add entries for lB, rB, oq, lC, rC, md.
+
+ * INSTALL: New file.
+
+ * libxdvi: Merged into main directory.
+ * xtotroff.c, xditview.c: Change includes accordingly.
+
+ * devX75, devX100: Merged into main directory.
+ * xditview.man: Renamed to gxditview.man.
+
+ * Xditview.ad: Renamed to GXditview.ad.
+ * xditview.c (main): Use class of GXditview rather than xditview.
+
+ * Imakefile: New file.
+ * Makefile: Deleted.
+
+ * xtotroff.c (MapFont): Unlink output file before opening it.
+
+ * Started separate ChangeLog.
diff --git a/contrib/groff/src/devices/xditview/DESC.in b/contrib/groff/src/devices/xditview/DESC.in
new file mode 100644
index 0000000..172170c
--- /dev/null
+++ b/contrib/groff/src/devices/xditview/DESC.in
@@ -0,0 +1,9 @@
+styles R I B BI
+fonts 6 0 0 0 0 0 S
+sizes 8 10 12 14 18 24 0
+res 75
+X11
+hor 1
+vert 1
+unitwidth 10
+postpro gxditview
diff --git a/contrib/groff/src/devices/xditview/Dvi.c b/contrib/groff/src/devices/xditview/Dvi.c
new file mode 100644
index 0000000..f849fb1
--- /dev/null
+++ b/contrib/groff/src/devices/xditview/Dvi.c
@@ -0,0 +1,611 @@
+#ifndef SABER
+#ifndef lint
+static char Xrcsid[] = "$XConsortium: Dvi.c,v 1.9 89/12/10 16:12:25 rws Exp $";
+#endif /* lint */
+#endif /* SABER */
+
+/*
+ * Dvi.c - Dvi display widget
+ *
+ */
+
+#define XtStrlen(s) ((s) ? strlen(s) : 0)
+
+ /* The following are defined for the reader's convenience. Any
+ Xt..Field macro in this code just refers to some field in
+ one of the substructures of the WidgetRec. */
+
+#include <X11/IntrinsicP.h>
+#include <X11/StringDefs.h>
+#include <X11/Xmu/Converters.h>
+#include <stdio.h>
+#include <ctype.h>
+#include "DviP.h"
+
+/****************************************************************
+ *
+ * Full class record constant
+ *
+ ****************************************************************/
+
+/* Private Data */
+
+static char default_font_map_1[] = "\
+TR -adobe-times-medium-r-normal--*-100-*-*-*-*-iso8859-1\n\
+TI -adobe-times-medium-i-normal--*-100-*-*-*-*-iso8859-1\n\
+TB -adobe-times-bold-r-normal--*-100-*-*-*-*-iso8859-1\n\
+TBI -adobe-times-bold-i-normal--*-100-*-*-*-*-iso8859-1\n\
+CR -adobe-courier-medium-r-normal--*-100-*-*-*-*-iso8859-1\n\
+CI -adobe-courier-medium-o-normal--*-100-*-*-*-*-iso8859-1\n\
+CB -adobe-courier-bold-r-normal--*-100-*-*-*-*-iso8859-1\n\
+CBI -adobe-courier-bold-o-normal--*-100-*-*-*-*-iso8859-1\n\
+";
+static char default_font_map_2[] = "\
+HR -adobe-helvetica-medium-r-normal--*-100-*-*-*-*-iso8859-1\n\
+HI -adobe-helvetica-medium-o-normal--*-100-*-*-*-*-iso8859-1\n\
+HB -adobe-helvetica-bold-r-normal--*-100-*-*-*-*-iso8859-1\n\
+HBI -adobe-helvetica-bold-o-normal--*-100-*-*-*-*-iso8859-1\n\
+";
+static char default_font_map_3[] = "\
+NR -adobe-new century schoolbook-medium-r-normal--*-100-*-*-*-*-iso8859-1\n\
+NI -adobe-new century schoolbook-medium-i-normal--*-100-*-*-*-*-iso8859-1\n\
+NB -adobe-new century schoolbook-bold-r-normal--*-100-*-*-*-*-iso8859-1\n\
+NBI -adobe-new century schoolbook-bold-i-normal--*-100-*-*-*-*-iso8859-1\n\
+S -adobe-symbol-medium-r-normal--*-100-*-*-*-*-adobe-fontspecific\n\
+SS -adobe-symbol-medium-r-normal--*-100-*-*-*-*-adobe-fontspecific\n\
+";
+
+#define offset(field) XtOffset(DviWidget, field)
+
+#define MY_WIDTH(dw) ((int)(dw->dvi.paperwidth * dw->dvi.scale_factor + .5))
+#define MY_HEIGHT(dw) ((int)(dw->dvi.paperlength * dw->dvi.scale_factor + .5))
+
+static XtResource resources[] = {
+ {(String)XtNfontMap, (String)XtCFontMap, (String)XtRString,
+ sizeof (char *), offset(dvi.font_map_string),
+ (String)XtRString, NULL /* set in code */},
+ {(String)XtNforeground, (String)XtCForeground, (String)XtRPixel,
+ sizeof (unsigned long), offset(dvi.foreground),
+ (String)XtRString, (XtPointer)"XtDefaultForeground"},
+ {(String)XtNbackground, (String)XtCBackground, (String)XtRPixel,
+ sizeof (unsigned long), offset(dvi.background),
+ (String)XtRString, (XtPointer)"XtDefaultBackground"},
+ {(String)XtNpageNumber, (String)XtCPageNumber, (String)XtRInt,
+ sizeof (int), offset(dvi.requested_page),
+ (String)XtRString, (XtPointer)"1"},
+ {(String)XtNlastPageNumber, (String)XtCLastPageNumber, (String)XtRInt,
+ sizeof (int), offset (dvi.last_page),
+ (String)XtRString, (XtPointer)"0"},
+ {(String)XtNfile, (String)XtCFile, (String)XtRFile,
+ sizeof (FILE *), offset (dvi.file),
+ (String)XtRFile, (XtPointer)0},
+ {(String)XtNseek, (String)XtCSeek, (String)XtRBoolean,
+ sizeof (Boolean), offset(dvi.seek),
+ (String)XtRString, (XtPointer)"false"},
+ {(String)XtNfont, (String)XtCFont, (String)XtRFontStruct,
+ sizeof (XFontStruct *), offset(dvi.default_font),
+ (String)XtRString, (XtPointer)"xtdefaultfont"},
+ {(String)XtNbackingStore, (String)XtCBackingStore, (String)XtRBackingStore,
+ sizeof (int), offset(dvi.backing_store),
+ (String)XtRString, (XtPointer)"default"},
+ {(String)XtNnoPolyText, (String)XtCNoPolyText, (String)XtRBoolean,
+ sizeof (Boolean), offset(dvi.noPolyText),
+ (String)XtRString, (XtPointer)"false"},
+ {(String)XtNresolution, (String)XtCResolution, (String)XtRInt,
+ sizeof(int), offset(dvi.default_resolution),
+ (String)XtRString, (XtPointer)"75"},
+};
+
+#undef offset
+
+static void ClassInitialize (void);
+static void ClassPartInitialize(WidgetClass);
+static void Initialize(Widget, Widget, ArgList, Cardinal *);
+static void Realize (Widget, XtValueMask *, XSetWindowAttributes *);
+static void Destroy (Widget);
+static void Redisplay (Widget, XEvent *, Region);
+static Boolean SetValues (Widget, Widget, Widget,
+ ArgList, Cardinal *);
+static Boolean SetValuesHook (Widget, ArgList, Cardinal *);
+static XtGeometryResult QueryGeometry (Widget, XtWidgetGeometry *,
+ XtWidgetGeometry *);
+static void ShowDvi (DviWidget);
+static void CloseFile (DviWidget);
+static void OpenFile (DviWidget);
+static void FindPage (DviWidget);
+
+static void SaveToFile (Widget, FILE *);
+
+/* font.c */
+extern void ParseFontMap(DviWidget);
+extern void DestroyFontMap(DviFontMap *);
+extern void ForgetFonts(DviWidget);
+
+/* page.c */
+extern void DestroyFileMap(DviFileMap *);
+extern long SearchPagePosition(DviWidget, int);
+extern void FileSeek(DviWidget, long);
+extern void ForgetPagePositions(DviWidget);
+
+/* parse.c */
+extern int ParseInput(register DviWidget);
+
+DviClassRec dviClassRec = {
+{
+ &widgetClassRec, /* superclass */
+ (String)"Dvi", /* class_name */
+ sizeof(DviRec), /* size */
+ ClassInitialize, /* class_initialize */
+ ClassPartInitialize, /* class_part_initialize */
+ FALSE, /* class_inited */
+ Initialize, /* initialize */
+ NULL, /* initialize_hook */
+ Realize, /* realize */
+ NULL, /* actions */
+ 0, /* num_actions */
+ resources, /* resources */
+ XtNumber(resources), /* resource_count */
+ NULLQUARK, /* xrm_class */
+ FALSE, /* compress_motion */
+ TRUE, /* compress_exposure */
+ TRUE, /* compress_enterleave */
+ FALSE, /* visible_interest */
+ Destroy, /* destroy */
+ NULL, /* resize */
+ Redisplay, /* expose */
+ SetValues, /* set_values */
+ SetValuesHook, /* set_values_hook */
+ NULL, /* set_values_almost */
+ NULL, /* get_values_hook */
+ NULL, /* accept_focus */
+ XtVersion, /* version */
+ NULL, /* callback_private */
+ 0, /* tm_table */
+ QueryGeometry, /* query_geometry */
+ NULL, /* display_accelerator */
+ NULL /* extension */
+},{
+ SaveToFile, /* save */
+},
+};
+
+WidgetClass dviWidgetClass = (WidgetClass) &dviClassRec;
+
+static void ClassInitialize (void)
+{
+ int len1 = strlen(default_font_map_1);
+ int len2 = strlen(default_font_map_2);
+ int len3 = strlen(default_font_map_3);
+ char *dfm = XtMalloc(len1 + len2 + len3 + 1);
+ char *ptr = dfm;
+ strcpy(ptr, default_font_map_1); ptr += len1;
+ strcpy(ptr, default_font_map_2); ptr += len2;
+ strcpy(ptr, default_font_map_3);
+ resources[0].default_addr = dfm;
+
+ XtAddConverter( XtRString, XtRBackingStore, XmuCvtStringToBackingStore,
+ NULL, 0 );
+}
+
+/****************************************************************
+ *
+ * Private Procedures
+ *
+ ****************************************************************/
+
+/* ARGSUSED */
+static void Initialize(Widget request, Widget new_wd,
+ ArgList args, Cardinal *num_args)
+{
+ DviWidget dw = (DviWidget) new_wd;
+
+ dw->dvi.current_page = 0;
+ dw->dvi.font_map = 0;
+ dw->dvi.cache.index = 0;
+ dw->dvi.text_x_width = 0;
+ dw->dvi.text_device_width = 0;
+ dw->dvi.word_flag = 0;
+ dw->dvi.file = 0;
+ dw->dvi.tmpFile = 0;
+ dw->dvi.state = 0;
+ dw->dvi.readingTmp = 0;
+ dw->dvi.cache.char_index = 0;
+ dw->dvi.cache.font_size = -1;
+ dw->dvi.cache.font_number = -1;
+ dw->dvi.cache.adjustable[0] = 0;
+ dw->dvi.file_map = 0;
+ dw->dvi.fonts = 0;
+ dw->dvi.seek = False;
+ dw->dvi.device_resolution = dw->dvi.default_resolution;
+ dw->dvi.display_resolution = dw->dvi.default_resolution;
+ dw->dvi.paperlength = dw->dvi.default_resolution*11;
+ dw->dvi.paperwidth = (dw->dvi.default_resolution*8
+ + dw->dvi.default_resolution/2);
+ dw->dvi.scale_factor = 1.0;
+ dw->dvi.sizescale = 1;
+ dw->dvi.line_thickness = -1;
+ dw->dvi.line_width = 1;
+ dw->dvi.fill = DVI_FILL_MAX;
+ dw->dvi.device_font = 0;
+ dw->dvi.device_font_number = -1;
+ dw->dvi.device = 0;
+ dw->dvi.native = 0;
+
+ request = request; /* unused; suppress compiler warning */
+ args = args;
+ num_args = num_args;
+}
+
+#include "gray1.bm"
+#include "gray2.bm"
+#include "gray3.bm"
+#include "gray4.bm"
+#include "gray5.bm"
+#include "gray6.bm"
+#include "gray7.bm"
+#include "gray8.bm"
+
+static void
+Realize (Widget w, XtValueMask *valueMask, XSetWindowAttributes *attrs)
+{
+ DviWidget dw = (DviWidget) w;
+ XGCValues values;
+
+ if (dw->dvi.backing_store != Always + WhenMapped + NotUseful) {
+ attrs->backing_store = dw->dvi.backing_store;
+ *valueMask |= CWBackingStore;
+ }
+ XtCreateWindow (w, (unsigned)InputOutput, (Visual *) CopyFromParent,
+ *valueMask, attrs);
+ values.foreground = dw->dvi.foreground;
+ values.cap_style = CapRound;
+ values.join_style = JoinRound;
+ values.line_width = dw->dvi.line_width;
+ dw->dvi.normal_GC = XCreateGC (XtDisplay (w), XtWindow (w),
+ GCForeground|GCCapStyle|GCJoinStyle
+ |GCLineWidth,
+ &values);
+ dw->dvi.gray[0] = XCreateBitmapFromData(XtDisplay (w), XtWindow (w),
+ gray1_bits,
+ gray1_width, gray1_height);
+ dw->dvi.gray[1] = XCreateBitmapFromData(XtDisplay (w), XtWindow (w),
+ gray2_bits,
+ gray2_width, gray2_height);
+ dw->dvi.gray[2] = XCreateBitmapFromData(XtDisplay (w), XtWindow (w),
+ gray3_bits,
+ gray3_width, gray3_height);
+ dw->dvi.gray[3] = XCreateBitmapFromData(XtDisplay (w), XtWindow (w),
+ gray4_bits,
+ gray4_width, gray4_height);
+ dw->dvi.gray[4] = XCreateBitmapFromData(XtDisplay (w), XtWindow (w),
+ gray5_bits,
+ gray5_width, gray5_height);
+ dw->dvi.gray[5] = XCreateBitmapFromData(XtDisplay (w), XtWindow (w),
+ gray6_bits,
+ gray6_width, gray6_height);
+ dw->dvi.gray[6] = XCreateBitmapFromData(XtDisplay (w), XtWindow (w),
+ gray7_bits,
+ gray7_width, gray7_height);
+ dw->dvi.gray[7] = XCreateBitmapFromData(XtDisplay (w), XtWindow (w),
+ gray8_bits,
+ gray8_width, gray8_height);
+ values.background = dw->dvi.background;
+ values.stipple = dw->dvi.gray[5];
+ dw->dvi.fill_GC = XCreateGC (XtDisplay (w), XtWindow (w),
+ GCForeground|GCBackground|GCStipple,
+ &values);
+
+ dw->dvi.fill_type = 9;
+
+ if (dw->dvi.file)
+ OpenFile (dw);
+ ParseFontMap (dw);
+}
+
+static void
+Destroy(Widget w)
+{
+ DviWidget dw = (DviWidget) w;
+
+ XFreeGC (XtDisplay (w), dw->dvi.normal_GC);
+ XFreeGC (XtDisplay (w), dw->dvi.fill_GC);
+ XFreePixmap (XtDisplay (w), dw->dvi.gray[0]);
+ XFreePixmap (XtDisplay (w), dw->dvi.gray[1]);
+ XFreePixmap (XtDisplay (w), dw->dvi.gray[2]);
+ XFreePixmap (XtDisplay (w), dw->dvi.gray[3]);
+ XFreePixmap (XtDisplay (w), dw->dvi.gray[4]);
+ XFreePixmap (XtDisplay (w), dw->dvi.gray[5]);
+ XFreePixmap (XtDisplay (w), dw->dvi.gray[6]);
+ XFreePixmap (XtDisplay (w), dw->dvi.gray[7]);
+ DestroyFontMap (dw->dvi.font_map);
+ DestroyFileMap (dw->dvi.file_map);
+ device_destroy (dw->dvi.device);
+}
+
+/*
+ * Repaint the widget window
+ */
+
+/* ARGSUSED */
+static void
+Redisplay(Widget w, XEvent *event, Region region)
+{
+ DviWidget dw = (DviWidget) w;
+ XRectangle extents;
+
+ XClipBox (region, &extents);
+ dw->dvi.extents.x1 = extents.x;
+ dw->dvi.extents.y1 = extents.y;
+ dw->dvi.extents.x2 = extents.x + extents.width;
+ dw->dvi.extents.y2 = extents.y + extents.height;
+ ShowDvi (dw);
+
+ event = event; /* unused; suppress compiler warning */
+}
+
+/*
+ * Set specified arguments into widget
+ */
+/* ARGSUSED */
+static Boolean
+SetValues (Widget wcurrent, Widget wrequest, Widget wnew,
+ ArgList args, Cardinal *num_args)
+{
+ Boolean redisplay = FALSE;
+ char *new_map;
+ int cur, req;
+ DviWidget current = (DviWidget)wcurrent;
+ DviWidget request = (DviWidget)wrequest;
+ DviWidget new_wd = (DviWidget)wnew;
+
+ if (current->dvi.font_map_string != request->dvi.font_map_string) {
+ new_map = XtMalloc (strlen (request->dvi.font_map_string) + 1);
+ if (new_map) {
+ redisplay = TRUE;
+ strcpy (new_map, request->dvi.font_map_string);
+ new_wd->dvi.font_map_string = new_map;
+ if (current->dvi.font_map_string)
+ XtFree (current->dvi.font_map_string);
+ current->dvi.font_map_string = 0;
+ ParseFontMap (new_wd);
+ }
+ }
+
+ req = request->dvi.requested_page;
+ cur = current->dvi.requested_page;
+ if (cur != req) {
+ if (!request->dvi.file)
+ req = 0;
+ else {
+ if (req < 1)
+ req = 1;
+ if (current->dvi.last_page != 0 &&
+ req > current->dvi.last_page)
+ req = current->dvi.last_page;
+ }
+ if (cur != req)
+ redisplay = TRUE;
+ new_wd->dvi.requested_page = req;
+ if (current->dvi.last_page == 0 && req > cur)
+ FindPage (new_wd);
+ }
+
+ args = args; /* unused; suppress compiler warning */
+ num_args = num_args;
+
+ return redisplay;
+}
+
+/*
+ * use the set_values_hook entry to check when
+ * the file is set
+ */
+
+static Boolean
+SetValuesHook (Widget wdw, ArgList args, Cardinal *num_argsp)
+{
+ Cardinal i;
+ DviWidget dw = (DviWidget)wdw;
+
+ for (i = 0; i < *num_argsp; i++) {
+ if (!strcmp (args[i].name, XtNfile)) {
+ CloseFile (dw);
+ OpenFile (dw);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+static void CloseFile (DviWidget dw)
+{
+ if (dw->dvi.tmpFile)
+ fclose (dw->dvi.tmpFile);
+ ForgetPagePositions (dw);
+}
+
+static void OpenFile (DviWidget dw)
+{
+ dw->dvi.tmpFile = 0;
+ if (!dw->dvi.seek)
+ dw->dvi.tmpFile = tmpfile();
+ dw->dvi.requested_page = 1;
+ dw->dvi.last_page = 0;
+}
+
+static XtGeometryResult
+QueryGeometry (Widget w, XtWidgetGeometry *request,
+ XtWidgetGeometry *geometry_return)
+{
+ XtGeometryResult ret;
+ DviWidget dw = (DviWidget) w;
+
+ ret = XtGeometryYes;
+ if (((request->request_mode & CWWidth)
+ && request->width < MY_WIDTH(dw))
+ || ((request->request_mode & CWHeight)
+ && request->height < MY_HEIGHT(dw)))
+ ret = XtGeometryAlmost;
+ geometry_return->width = MY_WIDTH(dw);
+ geometry_return->height = MY_HEIGHT(dw);
+ geometry_return->request_mode = CWWidth|CWHeight;
+ return ret;
+}
+
+void
+SetDevice (DviWidget dw, const char *name)
+{
+ XtWidgetGeometry request, reply;
+ XtGeometryResult ret;
+
+ ForgetFonts (dw);
+ dw->dvi.device = device_load (name);
+ if (!dw->dvi.device)
+ return;
+ dw->dvi.sizescale = dw->dvi.device->sizescale;
+ dw->dvi.device_resolution = dw->dvi.device->res;
+ dw->dvi.native = dw->dvi.device->X11;
+ dw->dvi.paperlength = dw->dvi.device->paperlength;
+ dw->dvi.paperwidth = dw->dvi.device->paperwidth;
+ if (dw->dvi.native) {
+ dw->dvi.display_resolution = dw->dvi.device_resolution;
+ dw->dvi.scale_factor = 1.0;
+ }
+ else {
+ dw->dvi.display_resolution = dw->dvi.default_resolution;
+ dw->dvi.scale_factor = ((double)dw->dvi.display_resolution
+ / dw->dvi.device_resolution);
+ }
+ request.request_mode = CWWidth|CWHeight;
+ request.width = MY_WIDTH(dw);
+ request.height = MY_HEIGHT(dw);
+ ret = XtMakeGeometryRequest ((Widget)dw, &request, &reply);
+ if (ret == XtGeometryAlmost
+ && reply.height >= request.height
+ && reply.width >= request.width) {
+ request.width = reply.width;
+ request.height = reply.height;
+ XtMakeGeometryRequest ((Widget)dw, &request, &reply);
+ }
+}
+
+static void
+ShowDvi (DviWidget dw)
+{
+ if (!dw->dvi.file) {
+ static char Error[] = "No file selected";
+
+ XSetFont (XtDisplay(dw), dw->dvi.normal_GC,
+ dw->dvi.default_font->fid);
+ XDrawString (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC,
+ 20, 20, Error, strlen (Error));
+ return;
+ }
+
+ FindPage (dw);
+
+ dw->dvi.display_enable = 1;
+ ParseInput (dw);
+ if (dw->dvi.last_page && dw->dvi.requested_page > dw->dvi.last_page)
+ dw->dvi.requested_page = dw->dvi.last_page;
+}
+
+static void
+FindPage (DviWidget dw)
+{
+ int i;
+ long file_position;
+
+ if (dw->dvi.requested_page < 1)
+ dw->dvi.requested_page = 1;
+
+ if (dw->dvi.last_page != 0 && dw->dvi.requested_page > dw->dvi.last_page)
+ dw->dvi.requested_page = dw->dvi.last_page;
+
+ file_position = SearchPagePosition (dw, dw->dvi.requested_page);
+ if (file_position != -1) {
+ FileSeek(dw, file_position);
+ dw->dvi.current_page = dw->dvi.requested_page;
+ } else {
+ for (i=dw->dvi.requested_page; i > 0; i--) {
+ file_position = SearchPagePosition (dw, i);
+ if (file_position != -1)
+ break;
+ }
+ if (file_position == -1)
+ file_position = 0;
+ FileSeek (dw, file_position);
+
+ dw->dvi.current_page = i;
+
+ dw->dvi.display_enable = 0;
+ while (dw->dvi.current_page != dw->dvi.requested_page) {
+ dw->dvi.current_page = ParseInput (dw);
+ /*
+ * at EOF, seek back to the beginning of this page.
+ */
+ if (!dw->dvi.readingTmp && feof (dw->dvi.file)) {
+ file_position = SearchPagePosition (dw,
+ dw->dvi.current_page);
+ if (file_position != -1)
+ FileSeek (dw, file_position);
+ dw->dvi.requested_page = dw->dvi.current_page;
+ break;
+ }
+ }
+ }
+}
+
+void DviSaveToFile(Widget w, FILE *fp)
+{
+ XtCheckSubclass(w, dviWidgetClass, NULL);
+ (*((DviWidgetClass) XtClass(w))->command_class.save)(w, fp);
+}
+
+static
+void SaveToFile(Widget w, FILE *fp)
+{
+ DviWidget dw = (DviWidget)w;
+ long pos;
+ int c;
+
+ if (dw->dvi.tmpFile) {
+ pos = ftell(dw->dvi.tmpFile);
+ if (dw->dvi.ungot) {
+ pos--;
+ dw->dvi.ungot = 0;
+ /* The ungot character is in the tmpFile, so we don't
+ want to read it from file. */
+ (void)getc(dw->dvi.file);
+ }
+ }
+ else
+ pos = ftell(dw->dvi.file);
+ FileSeek(dw, 0L);
+ while (DviGetC(dw, &c) != EOF)
+ if (putc(c, fp) == EOF) {
+ /* XXX print error message */
+ break;
+ }
+ FileSeek(dw, pos);
+}
+
+static
+void ClassPartInitialize(WidgetClass widget_class)
+{
+ DviWidgetClass wc = (DviWidgetClass)widget_class;
+ DviWidgetClass super = (DviWidgetClass) wc->core_class.superclass;
+ if (wc->command_class.save == InheritSaveToFile)
+ wc->command_class.save = super->command_class.save;
+}
+
+/*
+Local Variables:
+c-indent-level: 8
+c-continued-statement-offset: 8
+c-brace-offset: -8
+c-argdecl-indent: 8
+c-label-offset: -8
+c-tab-always-indent: nil
+End:
+*/
diff --git a/contrib/groff/src/devices/xditview/Dvi.h b/contrib/groff/src/devices/xditview/Dvi.h
new file mode 100644
index 0000000..bf97374
--- /dev/null
+++ b/contrib/groff/src/devices/xditview/Dvi.h
@@ -0,0 +1,46 @@
+/*
+* $XConsortium: Dvi.h,v 1.4 89/07/21 14:22:06 jim Exp $
+*/
+
+#ifndef _XtDvi_h
+#define _XtDvi_h
+
+/***********************************************************************
+ *
+ * Dvi Widget
+ *
+ ***********************************************************************/
+
+/* Parameters:
+
+ Name Class RepType Default Value
+ ---- ----- ------- -------------
+ background Background pixel White
+ foreground Foreground Pixel Black
+ fontMap FontMap char * ...
+ pageNumber PageNumber int 1
+*/
+
+#define XtNfontMap (String)"fontMap"
+#define XtNpageNumber (String)"pageNumber"
+#define XtNlastPageNumber (String)"lastPageNumber"
+#define XtNnoPolyText (String)"noPolyText"
+#define XtNseek (String)"seek"
+#define XtNresolution (String)"resolution"
+
+#define XtCFontMap (String)"FontMap"
+#define XtCPageNumber (String)"PageNumber"
+#define XtCLastPageNumber (String)"LastPageNumber"
+#define XtCNoPolyText (String)"NoPolyText"
+#define XtCSeek (String)"Seek"
+#define XtCResolution (String)"Resolution"
+
+typedef struct _DviRec *DviWidget; /* completely defined in DviP.h */
+typedef struct _DviClassRec *DviWidgetClass; /* completely defined in DviP.h */
+
+extern WidgetClass dviWidgetClass;
+
+void DviSaveToFile(Widget, FILE *);
+
+#endif /* _XtDvi_h */
+/* DON'T ADD STUFF AFTER THIS #endif */
diff --git a/contrib/groff/src/devices/xditview/DviP.h b/contrib/groff/src/devices/xditview/DviP.h
new file mode 100644
index 0000000..00f32c8
--- /dev/null
+++ b/contrib/groff/src/devices/xditview/DviP.h
@@ -0,0 +1,233 @@
+/*
+ * $XConsortium: DviP.h,v 1.5 89/07/22 19:44:08 keith Exp $
+ */
+
+/*
+ * DviP.h - Private definitions for Dvi widget
+ */
+
+#ifndef _XtDviP_h
+#define _XtDviP_h
+
+#include "Dvi.h"
+#include "DviChar.h"
+#include "device.h"
+
+/***********************************************************************
+ *
+ * Dvi Widget Private Data
+ *
+ ***********************************************************************/
+
+/************************************
+ *
+ * Class structure
+ *
+ ***********************************/
+
+/* Type for save method. */
+
+typedef void (*DviSaveProc)(Widget, FILE *);
+
+/*
+ * New fields for the Dvi widget class record
+ */
+
+
+typedef struct _DviClass {
+ DviSaveProc save;
+} DviClassPart;
+
+/*
+ * Full class record declaration
+ */
+
+typedef struct _DviClassRec {
+ CoreClassPart core_class;
+ DviClassPart command_class;
+} DviClassRec;
+
+extern DviClassRec dviClassRec;
+
+/***************************************
+ *
+ * Instance (widget) structure
+ *
+ **************************************/
+
+/*
+ * a list of fonts we've used for this widget
+ */
+
+typedef struct _dviFontSizeList {
+ struct _dviFontSizeList *next;
+ int size;
+ char *x_name;
+ XFontStruct *font;
+ int doesnt_exist;
+} DviFontSizeList;
+
+typedef struct _dviFontList {
+ struct _dviFontList *next;
+ char *dvi_name;
+ char *x_name;
+ int dvi_number;
+ Boolean initialized;
+ Boolean scalable;
+ DviFontSizeList *sizes;
+ DviCharNameMap *char_map;
+ DeviceFont *device_font;
+} DviFontList;
+
+typedef struct _dviFontMap {
+ struct _dviFontMap *next;
+ char *dvi_name;
+ char *x_name;
+} DviFontMap;
+
+#define DVI_TEXT_CACHE_SIZE 256
+#define DVI_CHAR_CACHE_SIZE 1024
+
+typedef struct _dviCharCache {
+ XTextItem cache[DVI_TEXT_CACHE_SIZE];
+ char adjustable[DVI_TEXT_CACHE_SIZE];
+ char char_cache[DVI_CHAR_CACHE_SIZE];
+ int index;
+ int max;
+ int char_index;
+ int font_size;
+ int font_number;
+ XFontStruct *font;
+ int start_x, start_y;
+ int x, y;
+} DviCharCache;
+
+typedef struct _dviState {
+ struct _dviState *next;
+ int font_size;
+ int font_number;
+ int x;
+ int y;
+} DviState;
+
+typedef struct _dviFileMap {
+ struct _dviFileMap *next;
+ long position;
+ int page_number;
+} DviFileMap;
+
+/*
+ * New fields for the Dvi widget record
+ */
+
+typedef struct {
+ /*
+ * resource specifiable items
+ */
+ char *font_map_string;
+ unsigned long foreground;
+ unsigned long background;
+ int requested_page;
+ int last_page;
+ XFontStruct *default_font;
+ FILE *file;
+ Boolean noPolyText;
+ Boolean seek; /* file is "seekable" */
+ int default_resolution;
+ /*
+ * private state
+ */
+ FILE *tmpFile; /* used when reading stdin */
+ char readingTmp; /* reading now from tmp */
+ char ungot; /* have ungetc'd a char */
+ GC normal_GC;
+ GC fill_GC;
+ DviFileMap *file_map;
+ DviFontList *fonts;
+ DviFontMap *font_map;
+ int current_page;
+ int font_size;
+ int font_number;
+ DeviceFont *device_font;
+ int device_font_number;
+ Device *device;
+ int native;
+ int device_resolution;
+ int display_resolution;
+ int paperlength;
+ int paperwidth;
+ double scale_factor; /* display res / device res */
+ int sizescale;
+ int line_thickness;
+ int line_width;
+
+#define DVI_FILL_MAX 1000
+
+ int fill;
+#define DVI_FILL_WHITE 0
+#define DVI_FILL_GRAY 1
+#define DVI_FILL_BLACK 2
+ int fill_type;
+ Pixmap gray[8];
+ int backing_store;
+ XFontStruct *font;
+ int display_enable;
+ struct ExposedExtents {
+ int x1, y1, x2, y2;
+ } extents;
+ DviState *state;
+ DviCharCache cache;
+ int text_x_width;
+ int text_device_width;
+ int word_flag;
+} DviPart;
+
+int DviGetAndPut(DviWidget, int *);
+#define DviGetIn(dw,cp)\
+ (dw->dvi.tmpFile ? (\
+ DviGetAndPut (dw, cp) \
+ ) :\
+ (*cp = getc (dw->dvi.file))\
+)
+
+#define DviGetC(dw, cp)\
+ (dw->dvi.readingTmp ? (\
+ ((*cp = getc (dw->dvi.tmpFile)) == EOF) ? (\
+ fseek (dw->dvi.tmpFile, 0l, 2),\
+ (dw->dvi.readingTmp = 0),\
+ DviGetIn (dw,cp)\
+ ) : (\
+ *cp\
+ )\
+ ) : (\
+ DviGetIn(dw,cp)\
+ )\
+)
+
+#define DviUngetC(dw, c)\
+ (dw->dvi.readingTmp ? (\
+ ungetc (c, dw->dvi.tmpFile)\
+ ) : ( \
+ (dw->dvi.ungot = 1),\
+ ungetc (c, dw->dvi.file)))
+
+/*
+ * Full widget declaration
+ */
+
+typedef struct _DviRec {
+ CorePart core;
+ DviPart dvi;
+} DviRec;
+
+#define InheritSaveToFile ((DviSaveProc)_XtInherit)
+
+XFontStruct *QueryFont (DviWidget, int, int);
+
+DviCharNameMap *QueryFontMap (DviWidget, int);
+
+DeviceFont *QueryDeviceFont (DviWidget, int);
+
+char *GetWord(DviWidget, char *, int);
+char *GetLine(DviWidget, char *, int);
+#endif /* _XtDviP_h */
diff --git a/contrib/groff/src/devices/xditview/FontMap b/contrib/groff/src/devices/xditview/FontMap
new file mode 100644
index 0000000..90911f0
--- /dev/null
+++ b/contrib/groff/src/devices/xditview/FontMap
@@ -0,0 +1,17 @@
+TR -adobe-times-medium-r-normal--*-*-*-*-p-*-iso8859-1
+TI -adobe-times-medium-i-normal--*-*-*-*-p-*-iso8859-1
+TB -adobe-times-bold-r-normal--*-*-*-*-p-*-iso8859-1
+TBI -adobe-times-bold-i-normal--*-*-*-*-p-*-iso8859-1
+CR -adobe-courier-medium-r-normal--*-*-*-*-m-*-iso8859-1
+CI -adobe-courier-medium-o-normal--*-*-*-*-m-*-iso8859-1
+CB -adobe-courier-bold-r-normal--*-*-*-*-m-*-iso8859-1
+CBI -adobe-courier-bold-o-normal--*-*-*-*-m-*-iso8859-1
+HR -adobe-helvetica-medium-r-normal--*-*-*-*-p-*-iso8859-1
+HI -adobe-helvetica-medium-o-normal--*-*-*-*-p-*-iso8859-1
+HB -adobe-helvetica-bold-r-normal--*-*-*-*-p-*-iso8859-1
+HBI -adobe-helvetica-bold-o-normal--*-*-*-*-p-*-iso8859-1
+NR -adobe-new century schoolbook-medium-r-normal--*-*-*-*-p-*-iso8859-1
+NI -adobe-new century schoolbook-medium-i-normal--*-*-*-*-p-*-iso8859-1
+NB -adobe-new century schoolbook-bold-r-normal--*-*-*-*-p-*-iso8859-1
+NBI -adobe-new century schoolbook-bold-i-normal--*-*-*-*-p-*-iso8859-1
+S -adobe-symbol-medium-r-normal--*-*-*-*-p-*-adobe-fontspecific
diff --git a/contrib/groff/src/devices/xditview/GXditview.ad b/contrib/groff/src/devices/xditview/GXditview.ad
new file mode 100644
index 0000000..e99ff5e
--- /dev/null
+++ b/contrib/groff/src/devices/xditview/GXditview.ad
@@ -0,0 +1,57 @@
+GXditview.height: 840
+
+GXditview.paned.allowResize: true
+GXditview.paned.viewport.allowVert: true
+GXditview.paned.viewport.allowHoriz: true
+GXditview.paned.viewport.skipAdjust: false
+GXditview.paned.viewport.width: 600
+GXditview.paned.viewport.height: 800
+GXditview.paned.viewport.showGrip: false
+GXditview.paned.label.skipAdjust: true
+
+GXditview.paned.viewport.dvi.translations: #augment \
+ <Btn1Down>: XawPositionSimpleMenu(menu) MenuPopup(menu)\n\
+ <Key>Next: NextPage()\n\
+ <Key>n: NextPage()\n\
+ <Key>space: NextPage()\n\
+ <Key>Return: NextPage()\n\
+ <Key>Prior: PreviousPage()\n\
+ <Key>p: PreviousPage()\n\
+ <Key>BackSpace: PreviousPage()\n\
+ <Key>Delete: PreviousPage()\n\
+ <Key>Select: SelectPage()\n\
+ <Key>Find: OpenFile()\n\
+ <Key>r: Rerasterize()\n\
+ <Key>q: Quit()
+GXditview.paned.label.translations: #augment \
+ <Btn1Down>: XawPositionSimpleMenu(menu) MenuPopup(menu)\n\
+ <Key>Next: NextPage()\n\
+ <Key>n: NextPage()\n\
+ <Key>space: NextPage()\n\
+ <Key>Return: NextPage()\n\
+ <Key>Prior: PreviousPage()\n\
+ <Key>p: PreviousPage()\n\
+ <Key>BackSpace: PreviousPage()\n\
+ <Key>Delete: PreviousPage()\n\
+ <Key>Select: SelectPage()\n\
+ <Key>Find: OpenFile()\n\
+ <Key>r: Rerasterize()\n\
+ <Key>q: Quit()
+GXditview.menu.nextPage.label: Next Page
+GXditview.menu.previousPage.label: Previous Page
+GXditview.menu.selectPage.label: Select Page
+GXditview.menu.print.label: Print
+GXditview.menu.openFile.label: Open
+GXditview.menu.quit.label: Quit
+
+GXditview.promptShell.allowShellResize: true
+GXditview.promptShell.promptDialog.value.translations: #override \
+ <Key>Return: Accept()
+
+GXditview.promptShell.promptDialog.accept.label: Accept
+GXditview.promptShell.promptDialog.accept.translations: #override \
+ <BtnUp>: Accept() unset()
+
+GXditview.promptShell.promptDialog.cancel.label: Cancel
+GXditview.promptShell.promptDialog.cancel.translations: #override \
+ <BtnUp>: Cancel() unset()
diff --git a/contrib/groff/src/devices/xditview/Makefile.sub b/contrib/groff/src/devices/xditview/Makefile.sub
new file mode 100644
index 0000000..f403020
--- /dev/null
+++ b/contrib/groff/src/devices/xditview/Makefile.sub
@@ -0,0 +1,47 @@
+PROG=gxditview$(EXEEXT)
+MAN1=gxditview.n
+MLIB=$(LIBM)
+XLIBS=$(LIBXUTIL)
+EXTRA_CFLAGS=$(X_CFLAGS)
+EXTRA_LDFLAGS=$(X_LIBS) $(X_PRE_LIBS) -lXaw -lXmu -lXt -lX11 $(X_EXTRA_LIBS)
+OBJS=\
+ device.$(OBJEXT) \
+ draw.$(OBJEXT) \
+ Dvi.$(OBJEXT) \
+ font.$(OBJEXT) \
+ lex.$(OBJEXT) \
+ page.$(OBJEXT) \
+ parse.$(OBJEXT) \
+ xditview.$(OBJEXT)
+CSRCS=\
+ $(srcdir)/device.c \
+ $(srcdir)/draw.c \
+ $(srcdir)/Dvi.c \
+ $(srcdir)/font.c \
+ $(srcdir)/lex.c \
+ $(srcdir)/page.c \
+ $(srcdir)/parse.c \
+ $(srcdir)/xditview.c
+HDRS=\
+ $(srcdir)/device.h \
+ $(srcdir)/Dvi.h \
+ $(srcdir)/DviP.h \
+ $(srcdir)/Menu.h
+GENHDRS=GXditview-ad.h
+
+all depend: $(GENHDRS)
+
+GXditview-ad.h: $(srcdir)/GXditview.ad
+ @echo Making $@
+ @-rm -f $@
+ $(SHELL) $(srcdir)/ad2c $(srcdir)/GXditview.ad >GXditview-ad.h
+
+install_data: $(srcdir)/GXditview.ad
+ -test -d $(appresdir) || $(mkinstalldirs) $(appresdir)
+ if test -f $(appresdir)/GXditview; then \
+ mv $(appresdir)/GXditview $(appresdir)/GXditview.old; \
+ fi
+ $(INSTALL_DATA) $(srcdir)/GXditview.ad $(appresdir)/GXditview
+
+uninstall_sub:
+ -rm -f $(appresdir)/GXditview
diff --git a/contrib/groff/src/devices/xditview/Menu.h b/contrib/groff/src/devices/xditview/Menu.h
new file mode 100644
index 0000000..c306b27
--- /dev/null
+++ b/contrib/groff/src/devices/xditview/Menu.h
@@ -0,0 +1,46 @@
+/*
+ * $XConsortium: Menu.h,v 1.2 89/07/21 14:22:10 jim Exp $
+ */
+
+#ifndef _XtMenu_h
+#define _XtMenu_h
+
+/***********************************************************************
+ *
+ * Menu Widget
+ *
+ ***********************************************************************/
+
+/* Parameters:
+
+ Name Class RepType Default Value
+ ---- ----- ------- -------------
+ background Background pixel White
+ border BorderColor pixel Black
+ borderWidth BorderWidth int 1
+ height Height int 120
+ mappedWhenManaged MappedWhenManaged Boolean True
+ reverseVideo ReverseVideo Boolean False
+ width Width int 120
+ x Position int 0
+ y Position int 0
+
+*/
+
+#define XtNmenuEntries "menuEntries"
+#define XtNhorizontalPadding "horizontalPadding"
+#define XtNverticalPadding "verticalPadding"
+#define XtNselection "Selection"
+
+#define XtCMenuEntries "MenuEntries"
+#define XtCPadding "Padding"
+#define XtCSelection "Selection"
+
+typedef struct _MenuRec *MenuWidget; /* completely defined in MenuPrivate.h */
+typedef struct _MenuClassRec *MenuWidgetClass; /* completely defined in MenuPrivate.h */
+
+extern WidgetClass menuWidgetClass;
+
+extern Widget XawMenuCreate ();
+#endif /* _XtMenu_h */
+/* DON'T ADD STUFF AFTER THIS #endif */
diff --git a/contrib/groff/src/devices/xditview/README b/contrib/groff/src/devices/xditview/README
new file mode 100644
index 0000000..1461b5a
--- /dev/null
+++ b/contrib/groff/src/devices/xditview/README
@@ -0,0 +1,13 @@
+This is gxditview, an X11 previewer for groff based on MIT's xditview.
+This version can be used with the output of gtroff -Tps as well as
+with -TX75 and -TX100. You will need X11R5 or newer to install it (it
+might work on X11R4, but I haven't tested it.)
+
+Previously, gxditview was installed in the usual place for X binaries
+(e.g., /usr/bin/X11); you have to remove it manually.
+
+xditview is copyrighted by MIT under the usual X terms (see
+gxditview.man); the changes to that which come along with the groff package
+are in the public domain.
+
+Please report bugs to bug-groff@gnu.org.
diff --git a/contrib/groff/src/devices/xditview/TODO b/contrib/groff/src/devices/xditview/TODO
new file mode 100644
index 0000000..161a7cf
--- /dev/null
+++ b/contrib/groff/src/devices/xditview/TODO
@@ -0,0 +1,17 @@
+Replace Imakefile with a configure script.
+
+Better error handling.
+
+Resource and command-line option to specify font path.
+
+Resource to specify name of environment variable from which to get the
+font path.
+
+Have character substitutions (currently done in draw.c:FakeCharacter)
+specified in a resource (similar format to FontMap).
+
+The initial width of the dialog box should expand to accommodate the
+default value.
+
+Option in Print dialog to specify that only the current page should be
+printed.
diff --git a/contrib/groff/src/devices/xditview/ad2c b/contrib/groff/src/devices/xditview/ad2c
new file mode 100644
index 0000000..ad5d121
--- /dev/null
+++ b/contrib/groff/src/devices/xditview/ad2c
@@ -0,0 +1,64 @@
+#! /bin/sh
+#
+# ad2c : Convert app-defaults file to C strings decls.
+#
+# George Ferguson, ferguson@cs.rcohester.edu, 12 Nov 1990.
+# 19 Mar 1991: gf
+# Made it self-contained.
+# 6 Jan 1992: mycroft@gnu.ai.mit.edu (Charles Hannum)
+# Removed use of "-n" and ":read" label since Gnu and
+# IBM sed print pattern space on "n" command. Still works
+# with Sun sed, of course.
+# 7 Jan 1992: matthew@sunpix.East.Sun.COM (Matthew Stier)
+# Escape quotes after escaping backslashes.
+# 8 Jul 1992: Version 1.6
+# Manpage fixes.
+# 19 Apr 1993: Version 1.7
+# Remove comments that were inside the sed command since
+# some versions of sed don't like them. The comments are
+# now given here in the header.
+# 31 May 2004: Werner Lemberg <wl@gnu.org>
+# Force casts to `String'.
+#
+# Comments on the script by line:
+# /^!/d Remove comments
+# /^$/d Remove blanks
+# s/\\/\\\\/g Escape backslashes...
+# s/\\$//g ...except the line continuation ones
+# s/"/\\"/g Escape quotes
+# s/^/"/ Add leading quote and cast
+# : test Establish label for later branch
+# /\\$/b slash Branch to label "slash" if line ends in backslash
+# s/$/",/ Otherwise add closing quote and comma...
+# p ...output the line...
+# d ...and clear the pattern space so it's not printed again
+# : slash Branch comes here if line ends in backslash
+# n Read next line, append to pattern space
+# [...] The "d" and "s" commands that follow just delete
+# comments and blank lines and escape control sequences
+# b test Branch up to see if the line ends in backslash or not
+#
+
+sed '
+/^!/d
+/^$/d
+s/\\/\\\\/g
+s/\\$//g
+s/"/\\"/g
+s/^/(String)"/
+: test
+/\\$/b slash
+s/$/",/
+p
+d
+: slash
+n
+/^!/d
+/^$/d
+s/"/\\"/g
+s/\\\\/\\/g
+s/\\n/\\\\n/g
+s/\\t/\\\\t/g
+s/\\f/\\\\f/g
+s/\\b/\\\\b/g
+b test' "$@"
diff --git a/contrib/groff/src/devices/xditview/device.c b/contrib/groff/src/devices/xditview/device.c
new file mode 100644
index 0000000..2cb2219
--- /dev/null
+++ b/contrib/groff/src/devices/xditview/device.c
@@ -0,0 +1,565 @@
+/* device.c */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <X11/Xos.h>
+#include <X11/Intrinsic.h>
+
+#include "device.h"
+#include "defs.h"
+
+#ifndef isascii
+#define isascii(c) (1)
+#endif
+
+/* Name of environment variable containing path to be used for
+searching for device and font description files. */
+#define FONTPATH_ENV_VAR "GROFF_FONT_PATH"
+
+#define WS " \t\r\n"
+
+#ifndef INT_MIN
+/* Minimum and maximum values a `signed int' can hold. */
+#define INT_MIN (-INT_MAX-1)
+#define INT_MAX 2147483647
+#endif
+
+#define CHAR_TABLE_SIZE 307
+
+struct _DeviceFont {
+ char *name;
+ int special;
+ DeviceFont *next;
+ Device *dev;
+ struct charinfo *char_table[CHAR_TABLE_SIZE];
+ struct charinfo *code_table[256];
+};
+
+struct charinfo {
+ int width;
+ int code;
+ struct charinfo *next;
+ struct charinfo *code_next;
+ char name[1];
+};
+
+static char *current_filename = 0;
+static int current_lineno = -1;
+
+static void error(const char *s);
+static FILE *open_device_file(const char *, const char *, char **);
+static DeviceFont *load_font(Device *, const char *);
+static Device *new_device(const char *);
+static DeviceFont *new_font(const char *, Device *);
+static void delete_font(DeviceFont *);
+static unsigned hash_name(const char *);
+static struct charinfo *add_char(DeviceFont *, const char *, int, int);
+static int read_charset_section(DeviceFont *, FILE *);
+static char *canonicalize_name(const char *);
+static int scale_round(int, int, int);
+
+static
+Device *new_device(const char *name)
+{
+ Device *dev;
+
+ dev = XtNew(Device);
+ dev->sizescale = 1;
+ dev->res = 0;
+ dev->unitwidth = 0;
+ dev->fonts = 0;
+ dev->X11 = 0;
+ dev->paperlength = 0;
+ dev->paperwidth = 0;
+ dev->name = XtNewString(name);
+ return dev;
+}
+
+void device_destroy(Device *dev)
+{
+ DeviceFont *f;
+
+ if (!dev)
+ return;
+ f = dev->fonts;
+ while (f) {
+ DeviceFont *tem = f;
+ f = f->next;
+ delete_font(tem);
+ }
+
+ XtFree(dev->name);
+ XtFree((char *)dev);
+}
+
+Device *device_load(const char *name)
+{
+ Device *dev;
+ FILE *fp;
+ int err = 0;
+ char buf[256];
+
+ fp = open_device_file(name, "DESC", &current_filename);
+ if (!fp)
+ return 0;
+ dev = new_device(name);
+ current_lineno = 0;
+ while (fgets(buf, sizeof(buf), fp)) {
+ char *p;
+ current_lineno++;
+ p = strtok(buf, WS);
+ if (p) {
+ int *np = 0;
+ char *q;
+
+ if (strcmp(p, "charset") == 0)
+ break;
+ if (strcmp(p, "X11") == 0)
+ dev->X11 = 1;
+ else if (strcmp(p, "sizescale") == 0)
+ np = &dev->sizescale;
+ else if (strcmp(p, "res") == 0)
+ np = &dev->res;
+ else if (strcmp(p, "unitwidth") == 0)
+ np = &dev->unitwidth;
+ else if (strcmp(p, "paperwidth") == 0)
+ np = &dev->paperwidth;
+ else if (strcmp(p, "paperlength") == 0)
+ np = &dev->paperlength;
+
+ if (np) {
+ q = strtok((char *)0, WS);
+ if (!q || sscanf(q, "%d", np) != 1 || *np <= 0) {
+ error("bad argument");
+ err = 1;
+ break;
+ }
+ }
+ }
+ }
+ fclose(fp);
+ current_lineno = -1;
+ if (!err) {
+ if (dev->res == 0) {
+ error("missing res line");
+ err = 1;
+ }
+ else if (dev->unitwidth == 0) {
+ error("missing unitwidth line");
+ err = 1;
+ }
+ }
+ if (dev->paperlength == 0)
+ dev->paperlength = dev->res*11;
+ if (dev->paperwidth == 0)
+ dev->paperwidth = dev->res*8 + dev->res/2;
+ if (err) {
+ device_destroy(dev);
+ dev = 0;
+ }
+ XtFree(current_filename);
+ current_filename = 0;
+ return dev;
+}
+
+
+DeviceFont *device_find_font(Device *dev, const char *name)
+{
+ DeviceFont *f;
+
+ if (!dev)
+ return 0;
+ for (f = dev->fonts; f; f = f->next)
+ if (strcmp(f->name, name) == 0)
+ return f;
+ return load_font(dev, name);
+}
+
+static
+DeviceFont *load_font(Device *dev, const char *name)
+{
+ FILE *fp;
+ char buf[256];
+ DeviceFont *f;
+ int special = 0;
+
+ fp = open_device_file(dev->name, name, &current_filename);
+ if (!fp)
+ return 0;
+ current_lineno = 0;
+ for (;;) {
+ char *p;
+
+ if (!fgets(buf, sizeof(buf), fp)) {
+ error("no charset line");
+ return 0;
+ }
+ current_lineno++;
+ p = strtok(buf, WS);
+ /* charset must be on a line by itself */
+ if (p && strcmp(p, "charset") == 0 && strtok((char *)0, WS) == 0)
+ break;
+ if (p && strcmp(p, "special") == 0)
+ special = 1;
+ }
+ f = new_font(name, dev);
+ f->special = special;
+ if (!read_charset_section(f, fp)) {
+ delete_font(f);
+ f = 0;
+ }
+ else {
+ f->next = dev->fonts;
+ dev->fonts = f;
+ }
+ fclose(fp);
+ XtFree(current_filename);
+ current_filename = 0;
+ return f;
+}
+
+static
+DeviceFont *new_font(const char *name, Device *dev)
+{
+ int i;
+ DeviceFont *f;
+
+ f = XtNew(DeviceFont);
+ f->name = XtNewString(name);
+ f->dev = dev;
+ f->special = 0;
+ f->next = 0;
+ for (i = 0; i < CHAR_TABLE_SIZE; i++)
+ f->char_table[i] = 0;
+ for (i = 0; i < 256; i++)
+ f->code_table[i] = 0;
+ return f;
+}
+
+static
+void delete_font(DeviceFont *f)
+{
+ int i;
+
+ if (!f)
+ return;
+ XtFree(f->name);
+ for (i = 0; i < CHAR_TABLE_SIZE; i++) {
+ struct charinfo *ptr = f->char_table[i];
+ while (ptr) {
+ struct charinfo *tem = ptr;
+ ptr = ptr->next;
+ XtFree((char *)tem);
+ }
+ }
+ XtFree((char *)f);
+}
+
+
+static
+unsigned hash_name(const char *name)
+{
+ unsigned n = 0;
+ /* XXX do better than this */
+ while (*name)
+ n = (n << 1) ^ *name++;
+
+ return n;
+}
+
+static
+int scale_round(int n, int x, int y)
+{
+ int y2;
+
+ if (x == 0)
+ return 0;
+ y2 = y/2;
+ if (n >= 0) {
+ if (n <= (INT_MAX - y2)/x)
+ return (n*x + y2)/y;
+ return (int)(n*(double)x/(double)y + .5);
+ }
+ else {
+ if (-(unsigned)n <= (-(unsigned)INT_MIN - y2)/x)
+ return (n*x - y2)/y;
+ return (int)(n*(double)x/(double)y + .5);
+ }
+}
+
+static
+char *canonicalize_name(const char *s)
+{
+ static char ch[2];
+ if (s[0] == 'c' && s[1] == 'h' && s[2] == 'a' && s[3] == 'r') {
+ const char *p;
+ int n;
+
+ for (p = s + 4; *p; p++)
+ if (!isascii(*p) || !isdigit((unsigned char)*p))
+ return (char *)s;
+ n = atoi(s + 4);
+ if (n >= 0 && n <= 0xff) {
+ ch[0] = (char)n;
+ return ch;
+ }
+ }
+ return (char *)s;
+}
+
+/* Return 1 if the character is present in the font; widthp gets the
+width if non-null. */
+
+int device_char_width(DeviceFont *f, int ps, const char *name, int *widthp)
+{
+ struct charinfo *p;
+
+ name = canonicalize_name(name);
+ for (p = f->char_table[hash_name(name) % CHAR_TABLE_SIZE];; p = p->next) {
+ if (!p)
+ return 0;
+ if (strcmp(p->name, name) == 0)
+ break;
+ }
+ *widthp = scale_round(p->width, ps, f->dev->unitwidth);
+ return 1;
+}
+
+int device_code_width(DeviceFont *f, int ps, int code, int *widthp)
+{
+ struct charinfo *p;
+
+ for (p = f->code_table[code & 0xff];; p = p->code_next) {
+ if (!p)
+ return 0;
+ if (p->code == code)
+ break;
+ }
+ *widthp = scale_round(p->width, ps, f->dev->unitwidth);
+ return 1;
+}
+
+char *device_name_for_code(DeviceFont *f, int code)
+{
+ static struct charinfo *state = 0;
+ if (f)
+ state = f->code_table[code & 0xff];
+ for (; state; state = state->code_next)
+ if (state->code == code && state->name[0] != '\0') {
+ char *name = state->name;
+ state = state->code_next;
+ return name;
+ }
+ return 0;
+}
+
+int device_font_special(DeviceFont *f)
+{
+ return f->special;
+}
+
+static
+struct charinfo *add_char(DeviceFont *f, const char *name, int width, int code)
+{
+ struct charinfo **pp;
+ struct charinfo *ci;
+
+ name = canonicalize_name(name);
+ if (strcmp(name, "---") == 0)
+ name = "";
+
+ ci = (struct charinfo *)XtMalloc(XtOffsetOf(struct charinfo, name[0])
+ + strlen(name) + 1);
+
+ strcpy(ci->name, name);
+ ci->width = width;
+ ci->code = code;
+
+ if (*name != '\0') {
+ pp = &f->char_table[hash_name(name) % CHAR_TABLE_SIZE];
+ ci->next = *pp;
+ *pp = ci;
+ }
+ pp = &f->code_table[code & 0xff];
+ ci->code_next = *pp;
+ *pp = ci;
+ return ci;
+}
+
+/* Return non-zero for success. */
+
+static
+int read_charset_section(DeviceFont *f, FILE *fp)
+{
+ struct charinfo *last_charinfo = 0;
+ char buf[256];
+
+ while (fgets(buf, sizeof(buf), fp)) {
+ char *name;
+ int width;
+ int code;
+ char *p;
+
+ current_lineno++;
+ name = strtok(buf, WS);
+ if (!name)
+ continue; /* ignore blank lines */
+ p = strtok((char *)0, WS);
+ if (!p) /* end of charset section */
+ break;
+ if (strcmp(p, "\"") == 0) {
+ if (!last_charinfo) {
+ error("first line of charset section cannot use `\"'");
+ return 0;
+ }
+ else
+ (void)add_char(f, name,
+ last_charinfo->width, last_charinfo->code);
+ }
+ else {
+ char *q;
+ if (sscanf(p, "%d", &width) != 1) {
+ error("bad width field");
+ return 0;
+ }
+ p = strtok((char *)0, WS);
+ if (!p) {
+ error("missing type field");
+ return 0;
+ }
+ p = strtok((char *)0, WS);
+ if (!p) {
+ error("missing code field");
+ return 0;
+ }
+ code = (int)strtol(p, &q, 0);
+ if (q == p) {
+ error("bad code field");
+ return 0;
+ }
+ last_charinfo = add_char(f, name, width, code);
+ }
+ }
+ return 1;
+}
+
+static
+FILE *find_file(const char *file, char **result)
+{
+ char *buf = NULL;
+ int bufsiz = 0;
+ int flen;
+ FILE *fp;
+ char *path;
+ char *env;
+
+ env = getenv(FONTPATH_ENV_VAR);
+ path = XtMalloc(((env && *env) ? strlen(env) + 1 : 0)
+ + strlen(FONTPATH) + 1);
+ *path = '\0';
+ if (env && *env) {
+ strcat(path, env);
+ strcat(path, ":");
+ }
+ strcat(path, FONTPATH);
+
+ *result = NULL;
+
+ if (file == NULL)
+ return NULL;
+ if (*file == '\0')
+ return NULL;
+
+ if (*file == '/') {
+ fp = fopen(file, "r");
+ if (fp)
+ *result = XtNewString(file);
+ return fp;
+ }
+
+ flen = strlen(file);
+
+ while (*path) {
+ int len;
+ char *start, *end;
+
+ start = path;
+ end = strchr(path, ':');
+ if (end)
+ path = end + 1;
+ else
+ path = end = strchr(path, '\0');
+ if (start >= end)
+ continue;
+ if (end[-1] == '/')
+ --end;
+ len = (end - start) + 1 + flen + 1;
+ if (len > bufsiz) {
+ if (buf)
+ buf = XtRealloc(buf, len);
+ else
+ buf = XtMalloc(len);
+ bufsiz = len;
+ }
+ memcpy(buf, start, end - start);
+ buf[end - start] = '/';
+ strcpy(buf + (end - start) + 1, file);
+ fp = fopen(buf, "r");
+ if (fp) {
+ *result = buf;
+ return fp;
+ }
+ }
+ XtFree(buf);
+ return NULL;
+}
+
+static
+FILE *open_device_file(const char *device_name, const char *file_name,
+ char **result)
+{
+ char *buf;
+ FILE *fp;
+
+ buf = XtMalloc(3 + strlen(device_name) + 1 + strlen(file_name) + 1);
+ sprintf(buf, "dev%s/%s", device_name, file_name);
+ fp = find_file(buf, result);
+ if (!fp) {
+ fprintf(stderr, "can't find device file `%s'\n", file_name);
+ fflush(stderr);
+ }
+ XtFree(buf);
+ return fp;
+}
+
+static
+void error(const char *s)
+{
+ if (current_filename) {
+ fprintf(stderr, "%s:", current_filename);
+ if (current_lineno > 0)
+ fprintf(stderr, "%d:", current_lineno);
+ putc(' ', stderr);
+ }
+ fputs(s, stderr);
+ putc('\n', stderr);
+ fflush(stderr);
+}
+
+/*
+Local Variables:
+c-indent-level: 4
+c-continued-statement-offset: 4
+c-brace-offset: -4
+c-argdecl-indent: 4
+c-label-offset: -4
+c-tab-always-indent: nil
+End:
+*/
diff --git a/contrib/groff/src/devices/xditview/device.h b/contrib/groff/src/devices/xditview/device.h
new file mode 100644
index 0000000..6f2944b
--- /dev/null
+++ b/contrib/groff/src/devices/xditview/device.h
@@ -0,0 +1,21 @@
+
+typedef struct _DeviceFont DeviceFont;
+
+typedef struct _Device {
+ char *name;
+ int sizescale;
+ int res;
+ int unitwidth;
+ int paperlength;
+ int paperwidth;
+ int X11;
+ DeviceFont *fonts;
+} Device;
+
+void device_destroy(Device *);
+Device *device_load(const char *);
+DeviceFont *device_find_font(Device *, const char *);
+int device_char_width(DeviceFont *, int, const char *, int *);
+char *device_name_for_code(DeviceFont *, int);
+int device_code_width(DeviceFont *, int, int, int *);
+int device_font_special(DeviceFont *);
diff --git a/contrib/groff/src/devices/xditview/draw.c b/contrib/groff/src/devices/xditview/draw.c
new file mode 100644
index 0000000..a808aba
--- /dev/null
+++ b/contrib/groff/src/devices/xditview/draw.c
@@ -0,0 +1,699 @@
+/*
+ * draw.c
+ *
+ * accept dvi function calls and translate to X
+ */
+
+#include <X11/Xos.h>
+#include <X11/IntrinsicP.h>
+#include <X11/StringDefs.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <math.h>
+
+/* math.h on a Sequent doesn't define M_PI, apparently */
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+#include "DviP.h"
+
+#define DeviceToX(dw, n) ((int)((n) * (dw)->dvi.scale_factor + .5))
+#define XPos(dw) (DeviceToX((dw), (dw)->dvi.state->x - \
+ (dw)->dvi.text_device_width) + (dw)->dvi.text_x_width)
+#define YPos(dw) (DeviceToX((dw), (dw)->dvi.state->y))
+
+static int FakeCharacter(DviWidget, char *, int);
+
+/* font.c */
+extern int MaxFontPosition(DviWidget);
+
+void
+HorizontalMove(DviWidget dw, int delta)
+{
+ dw->dvi.state->x += delta;
+}
+
+void
+HorizontalGoto(DviWidget dw, int NewPosition)
+{
+ dw->dvi.state->x = NewPosition;
+}
+
+void
+VerticalMove(DviWidget dw, int delta)
+{
+ dw->dvi.state->y += delta;
+}
+
+void
+VerticalGoto(DviWidget dw, int NewPosition)
+{
+ dw->dvi.state->y = NewPosition;
+}
+
+void
+AdjustCacheDeltas (DviWidget dw)
+{
+ int extra;
+ int nadj;
+ int i;
+
+ nadj = 0;
+ extra = DeviceToX(dw, dw->dvi.text_device_width)
+ - dw->dvi.text_x_width;
+ if (extra == 0)
+ return;
+ for (i = 0; i <= dw->dvi.cache.index; i++)
+ if (dw->dvi.cache.adjustable[i])
+ ++nadj;
+ dw->dvi.text_x_width += extra;
+ if (nadj <= 1)
+ return;
+ for (i = 0; i <= dw->dvi.cache.index; i++)
+ if (dw->dvi.cache.adjustable[i]) {
+ int x;
+ int *deltap;
+
+ x = extra/nadj;
+ deltap = &dw->dvi.cache.cache[i].delta;
+#define MIN_DELTA 2
+ if (*deltap > 0 && x + *deltap < MIN_DELTA) {
+ x = MIN_DELTA - *deltap;
+ if (x <= 0)
+ *deltap = MIN_DELTA;
+ else
+ x = 0;
+ }
+ else
+ *deltap += x;
+ extra -= x;
+ --nadj;
+ dw->dvi.cache.adjustable[i] = 0;
+ }
+}
+
+void
+FlushCharCache (DviWidget dw)
+{
+ if (dw->dvi.cache.char_index != 0) {
+ AdjustCacheDeltas (dw);
+ XDrawText (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC,
+ dw->dvi.cache.start_x, dw->dvi.cache.start_y,
+ dw->dvi.cache.cache, dw->dvi.cache.index + 1);
+ }
+ dw->dvi.cache.index = 0;
+ dw->dvi.cache.max = DVI_TEXT_CACHE_SIZE;
+#if 0
+ if (dw->dvi.noPolyText)
+ dw->dvi.cache.max = 1;
+#endif
+ dw->dvi.cache.char_index = 0;
+ dw->dvi.cache.cache[0].nchars = 0;
+ dw->dvi.cache.start_x = dw->dvi.cache.x = XPos (dw);
+ dw->dvi.cache.start_y = dw->dvi.cache.y = YPos (dw);
+}
+
+void
+Newline (DviWidget dw)
+{
+ FlushCharCache (dw);
+ dw->dvi.text_x_width = dw->dvi.text_device_width = 0;
+ dw->dvi.word_flag = 0;
+}
+
+void
+Word (DviWidget dw)
+{
+ dw->dvi.word_flag = 1;
+}
+
+#define charWidth(fi,c) (\
+ (fi)->per_char ?\
+ (fi)->per_char[(c) - (fi)->min_char_or_byte2].width\
+ :\
+ (fi)->max_bounds.width\
+)
+
+
+static
+int charExists (XFontStruct *fi, int c)
+{
+ XCharStruct *p;
+
+ /* `c' is always >= 0 */
+ if (fi->per_char == NULL
+ || (unsigned int)c < fi->min_char_or_byte2
+ || (unsigned int)c > fi->max_char_or_byte2)
+ return 0;
+ p = fi->per_char + (c - fi->min_char_or_byte2);
+ return (p->lbearing != 0 || p->rbearing != 0 || p->width != 0
+ || p->ascent != 0 || p->descent != 0 || p->attributes != 0);
+}
+
+/* `wid' is in device units */
+static void
+DoCharacter (DviWidget dw, int c, int wid)
+{
+ register XFontStruct *font;
+ register XTextItem *text;
+ int x, y;
+
+ x = XPos(dw);
+ y = YPos(dw);
+
+ /*
+ * quick and dirty extents calculation:
+ */
+ if (!(y + 24 >= dw->dvi.extents.y1
+ && y - 24 <= dw->dvi.extents.y2
+#if 0
+ && x + 24 >= dw->dvi.extents.x1
+ && x - 24 <= dw->dvi.extents.x2
+#endif
+ ))
+ return;
+
+ if (y != dw->dvi.cache.y
+ || dw->dvi.cache.char_index >= DVI_CHAR_CACHE_SIZE) {
+ FlushCharCache (dw);
+ x = dw->dvi.cache.x;
+ dw->dvi.cache.adjustable[dw->dvi.cache.index] = 0;
+ }
+ /*
+ * load a new font, if the current block is not empty,
+ * step to the next.
+ */
+ if (dw->dvi.cache.font_size != dw->dvi.state->font_size ||
+ dw->dvi.cache.font_number != dw->dvi.state->font_number)
+ {
+ FlushCharCache (dw);
+ x = dw->dvi.cache.x;
+ dw->dvi.cache.font_size = dw->dvi.state->font_size;
+ dw->dvi.cache.font_number = dw->dvi.state->font_number;
+ dw->dvi.cache.font = QueryFont (dw,
+ dw->dvi.cache.font_number,
+ dw->dvi.cache.font_size);
+ if (dw->dvi.cache.cache[dw->dvi.cache.index].nchars != 0) {
+ ++dw->dvi.cache.index;
+ if (dw->dvi.cache.index >= dw->dvi.cache.max)
+ FlushCharCache (dw);
+ dw->dvi.cache.cache[dw->dvi.cache.index].nchars = 0;
+ dw->dvi.cache.adjustable[dw->dvi.cache.index] = 0;
+ }
+ }
+ if (x != dw->dvi.cache.x || dw->dvi.word_flag) {
+ if (dw->dvi.cache.cache[dw->dvi.cache.index].nchars != 0) {
+ ++dw->dvi.cache.index;
+ if (dw->dvi.cache.index >= dw->dvi.cache.max)
+ FlushCharCache (dw);
+ dw->dvi.cache.cache[dw->dvi.cache.index].nchars = 0;
+ dw->dvi.cache.adjustable[dw->dvi.cache.index] = 0;
+ }
+ dw->dvi.cache.adjustable[dw->dvi.cache.index]
+ = dw->dvi.word_flag;
+ dw->dvi.word_flag = 0;
+ }
+ font = dw->dvi.cache.font;
+ text = &dw->dvi.cache.cache[dw->dvi.cache.index];
+ if (text->nchars == 0) {
+ text->chars = &dw->dvi.cache.char_cache[dw->dvi.cache.char_index];
+ text->delta = x - dw->dvi.cache.x;
+ if (font != dw->dvi.font) {
+ text->font = font->fid;
+ dw->dvi.font = font;
+ } else
+ text->font = None;
+ dw->dvi.cache.x += text->delta;
+ }
+ if (charExists(font, c)) {
+ int w;
+ dw->dvi.cache.char_cache[dw->dvi.cache.char_index++] = (char) c;
+ ++text->nchars;
+ w = charWidth(font, c);
+ dw->dvi.cache.x += w;
+ if (wid != 0) {
+ dw->dvi.text_x_width += w;
+ dw->dvi.text_device_width += wid;
+ }
+ }
+}
+
+static
+int FindCharWidth (DviWidget dw, char *buf, int *widp)
+{
+ int maxpos;
+ int i;
+
+ if (dw->dvi.device_font == 0
+ || dw->dvi.state->font_number != dw->dvi.device_font_number) {
+ dw->dvi.device_font_number = dw->dvi.state->font_number;
+ dw->dvi.device_font
+ = QueryDeviceFont (dw, dw->dvi.device_font_number);
+ }
+ if (dw->dvi.device_font
+ && device_char_width (dw->dvi.device_font,
+ dw->dvi.state->font_size, buf, widp))
+ return 1;
+
+ maxpos = MaxFontPosition (dw);
+ for (i = 1; i <= maxpos; i++) {
+ DeviceFont *f = QueryDeviceFont (dw, i);
+ if (f && device_font_special (f)
+ && device_char_width (f, dw->dvi.state->font_size,
+ buf, widp)) {
+ dw->dvi.state->font_number = i;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/* Return the width of the character in device units. */
+
+int PutCharacter (DviWidget dw, char *buf)
+{
+ int prevFont;
+ int c = -1;
+ int wid = 0;
+ DviCharNameMap *map;
+
+ if (!dw->dvi.display_enable)
+ return 0; /* The width doesn't matter in this case. */
+ prevFont = dw->dvi.state->font_number;
+ if (!FindCharWidth (dw, buf, &wid))
+ return 0;
+ map = QueryFontMap (dw, dw->dvi.state->font_number);
+ if (map)
+ c = DviCharIndex (map, buf);
+ if (c >= 0)
+ DoCharacter (dw, c, wid);
+ else
+ (void) FakeCharacter (dw, buf, wid);
+ dw->dvi.state->font_number = prevFont;
+ return wid;
+}
+
+/* Return 1 if we can fake it; 0 otherwise. */
+
+static
+int FakeCharacter (DviWidget dw, char *buf, int wid)
+{
+ int oldx, oldw;
+ char ch[2];
+ const char *chars = 0;
+
+ if (buf[0] == '\0' || buf[1] == '\0' || buf[2] != '\0')
+ return 0;
+#define pack2(c1, c2) (((c1) << 8) | (c2))
+
+ switch (pack2(buf[0], buf[1])) {
+ case pack2('f', 'i'):
+ chars = "fi";
+ break;
+ case pack2('f', 'l'):
+ chars = "fl";
+ break;
+ case pack2('f', 'f'):
+ chars = "ff";
+ break;
+ case pack2('F', 'i'):
+ chars = "ffi";
+ break;
+ case pack2('F', 'l'):
+ chars = "ffl";
+ break;
+ }
+ if (!chars)
+ return 0;
+ oldx = dw->dvi.state->x;
+ oldw = dw->dvi.text_device_width;
+ ch[1] = '\0';
+ for (; *chars; chars++) {
+ ch[0] = *chars;
+ dw->dvi.state->x += PutCharacter (dw, ch);
+ }
+ dw->dvi.state->x = oldx;
+ dw->dvi.text_device_width = oldw + wid;
+ return 1;
+}
+
+void
+PutNumberedCharacter (DviWidget dw, int c)
+{
+ char *name;
+ int wid;
+ DviCharNameMap *map;
+
+ if (!dw->dvi.display_enable)
+ return;
+
+ if (dw->dvi.device_font == 0
+ || dw->dvi.state->font_number != dw->dvi.device_font_number) {
+ dw->dvi.device_font_number = dw->dvi.state->font_number;
+ dw->dvi.device_font
+ = QueryDeviceFont (dw, dw->dvi.device_font_number);
+ }
+
+ if (dw->dvi.device_font == 0
+ || !device_code_width (dw->dvi.device_font,
+ dw->dvi.state->font_size, c, &wid))
+ return;
+ if (dw->dvi.native) {
+ DoCharacter (dw, c, wid);
+ return;
+ }
+ map = QueryFontMap (dw, dw->dvi.state->font_number);
+ if (!map)
+ return;
+ for (name = device_name_for_code (dw->dvi.device_font, c);
+ name;
+ name = device_name_for_code ((DeviceFont *)0, c)) {
+ int code = DviCharIndex (map, name);
+ if (code >= 0) {
+ DoCharacter (dw, code, wid);
+ break;
+ }
+ if (FakeCharacter (dw, name, wid))
+ break;
+ }
+}
+
+void
+ClearPage (DviWidget dw)
+{
+ XClearWindow (XtDisplay (dw), XtWindow (dw));
+}
+
+static void
+setGC (DviWidget dw)
+{
+ int desired_line_width;
+
+ if (dw->dvi.line_thickness < 0)
+ desired_line_width = (int)(((double)dw->dvi.device_resolution
+ * dw->dvi.state->font_size)
+ / (10.0*72.0*dw->dvi.sizescale));
+ else
+ desired_line_width = dw->dvi.line_thickness;
+
+ if (desired_line_width != dw->dvi.line_width) {
+ XGCValues values;
+ values.line_width = DeviceToX(dw, desired_line_width);
+ if (values.line_width == 0)
+ values.line_width = 1;
+ XChangeGC(XtDisplay (dw), dw->dvi.normal_GC,
+ GCLineWidth, &values);
+ dw->dvi.line_width = desired_line_width;
+ }
+}
+
+static void
+setFillGC (DviWidget dw)
+{
+ int fill_type;
+ unsigned long mask = GCFillStyle | GCForeground;
+
+ fill_type = (dw->dvi.fill * 10) / (DVI_FILL_MAX + 1);
+ if (dw->dvi.fill_type != fill_type) {
+ XGCValues values;
+ if (fill_type <= 0) {
+ values.foreground = dw->dvi.background;
+ values.fill_style = FillSolid;
+ } else if (fill_type >= 9) {
+ values.foreground = dw->dvi.foreground;
+ values.fill_style = FillSolid;
+ } else {
+ values.foreground = dw->dvi.foreground;
+ values.fill_style = FillOpaqueStippled;
+ values.stipple = dw->dvi.gray[fill_type - 1];
+ mask |= GCStipple;
+ }
+ XChangeGC(XtDisplay (dw), dw->dvi.fill_GC, mask, &values);
+ dw->dvi.fill_type = fill_type;
+ }
+}
+
+void
+DrawLine (DviWidget dw, int x, int y)
+{
+ int xp, yp;
+
+ AdjustCacheDeltas (dw);
+ setGC (dw);
+ xp = XPos (dw);
+ yp = YPos (dw);
+ XDrawLine (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC,
+ xp, yp,
+ xp + DeviceToX (dw, x), yp + DeviceToX (dw, y));
+}
+
+void
+DrawCircle (DviWidget dw, int diam)
+{
+ int d;
+
+ AdjustCacheDeltas (dw);
+ setGC (dw);
+ d = DeviceToX (dw, diam);
+ XDrawArc (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC,
+ XPos (dw), YPos (dw) - d/2,
+ d, d, 0, 64*360);
+}
+
+void
+DrawFilledCircle (DviWidget dw, int diam)
+{
+ int d;
+
+ AdjustCacheDeltas (dw);
+ setFillGC (dw);
+ d = DeviceToX (dw, diam);
+ XFillArc (XtDisplay (dw), XtWindow (dw), dw->dvi.fill_GC,
+ XPos (dw), YPos (dw) - d/2,
+ d, d, 0, 64*360);
+ XDrawArc (XtDisplay (dw), XtWindow (dw), dw->dvi.fill_GC,
+ XPos (dw), YPos (dw) - d/2,
+ d, d, 0, 64*360);
+}
+
+void
+DrawEllipse (DviWidget dw, int a, int b)
+{
+ AdjustCacheDeltas (dw);
+ setGC (dw);
+ XDrawArc (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC,
+ XPos (dw), YPos (dw) - DeviceToX (dw, b/2),
+ DeviceToX (dw, a), DeviceToX (dw, b), 0, 64*360);
+}
+
+void
+DrawFilledEllipse (DviWidget dw, int a, int b)
+{
+ AdjustCacheDeltas (dw);
+ setFillGC (dw);
+ XFillArc (XtDisplay (dw), XtWindow (dw), dw->dvi.fill_GC,
+ XPos (dw), YPos (dw) - DeviceToX (dw, b/2),
+ DeviceToX (dw, a), DeviceToX (dw, b), 0, 64*360);
+ XDrawArc (XtDisplay (dw), XtWindow (dw), dw->dvi.fill_GC,
+ XPos (dw), YPos (dw) - DeviceToX (dw, b/2),
+ DeviceToX (dw, a), DeviceToX (dw, b), 0, 64*360);
+}
+
+void
+DrawArc (DviWidget dw, int x_0, int y_0, int x_1, int y_1)
+{
+ int angle1, angle2;
+ int rad = (int)((sqrt ((double)x_0*x_0 + (double)y_0*y_0)
+ + sqrt ((double)x_1*x_1 + (double)y_1*y_1)
+ + 1.0)/2.0);
+ if ((x_0 == 0 && y_0 == 0) || (x_1 == 0 && y_1 == 0))
+ return;
+ angle1 = (int)(atan2 ((double)y_0, (double)-x_0)*180.0*64.0/M_PI);
+ angle2 = (int)(atan2 ((double)-y_1, (double)x_1)*180.0*64.0/M_PI);
+
+ angle2 -= angle1;
+ if (angle2 < 0)
+ angle2 += 64*360;
+
+ AdjustCacheDeltas (dw);
+ setGC (dw);
+
+ rad = DeviceToX (dw, rad);
+ XDrawArc (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC,
+ XPos (dw) + DeviceToX (dw, x_0) - rad,
+ YPos (dw) + DeviceToX (dw, y_0) - rad,
+ rad*2, rad*2, angle1, angle2);
+}
+
+void
+DrawPolygon (DviWidget dw, int *v, int n)
+{
+ XPoint *p;
+ int i;
+ int dx, dy;
+
+ n /= 2;
+
+ AdjustCacheDeltas (dw);
+ setGC (dw);
+ p = (XPoint *)XtMalloc((n + 2)*sizeof(XPoint));
+ p[0].x = XPos (dw);
+ p[0].y = YPos (dw);
+ dx = 0;
+ dy = 0;
+ for (i = 0; i < n; i++) {
+ dx += v[2*i];
+ p[i + 1].x = DeviceToX (dw, dx) + p[0].x;
+ dy += v[2*i + 1];
+ p[i + 1].y = DeviceToX (dw, dy) + p[0].y;
+ }
+ p[n+1].x = p[0].x;
+ p[n+1].y = p[0].y;
+ XDrawLines (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC,
+ p, n + 2, CoordModeOrigin);
+ XtFree((char *)p);
+}
+
+void
+DrawFilledPolygon (DviWidget dw, int *v, int n)
+{
+ XPoint *p;
+ int i;
+ int dx, dy;
+
+ n /= 2;
+ if (n < 2)
+ return;
+
+ AdjustCacheDeltas (dw);
+ setFillGC (dw);
+ p = (XPoint *)XtMalloc((n + 2)*sizeof(XPoint));
+ p[0].x = p[n+1].x = XPos (dw);
+ p[0].y = p[n+1].y = YPos (dw);
+ dx = 0;
+ dy = 0;
+ for (i = 0; i < n; i++) {
+ dx += v[2*i];
+ p[i + 1].x = DeviceToX (dw, dx) + p[0].x;
+ dy += v[2*i + 1];
+ p[i + 1].y = DeviceToX (dw, dy) + p[0].y;
+ }
+ XFillPolygon (XtDisplay (dw), XtWindow (dw), dw->dvi.fill_GC,
+ p, n + 1, Complex, CoordModeOrigin);
+ XDrawLines (XtDisplay (dw), XtWindow (dw), dw->dvi.fill_GC,
+ p, n + 2, CoordModeOrigin);
+ XtFree((char *)p);
+}
+
+#define POINTS_MAX 10000
+
+static void
+appendPoint(XPoint *points, int *pointi, int x, int y)
+{
+ if (*pointi < POINTS_MAX) {
+ points[*pointi].x = x;
+ points[*pointi].y = y;
+ *pointi += 1;
+ }
+}
+
+#define FLATNESS 1
+
+static void
+flattenCurve(XPoint *points, int *pointi,
+ int x_2, int y_2, int x_3, int y_3, int x_4, int y_4)
+{
+ int x_1, y_1, dx, dy, n1, n2, n;
+
+ x_1 = points[*pointi - 1].x;
+ y_1 = points[*pointi - 1].y;
+
+ dx = x_4 - x_1;
+ dy = y_4 - y_1;
+
+ n1 = dy*(x_2 - x_1) - dx*(y_2 - y_1);
+ n2 = dy*(x_3 - x_1) - dx*(y_3 - y_1);
+ if (n1 < 0)
+ n1 = -n1;
+ if (n2 < 0)
+ n2 = -n2;
+ n = n1 > n2 ? n1 : n2;
+
+ if (n*n / (dy*dy + dx*dx) <= FLATNESS*FLATNESS)
+ appendPoint (points, pointi, x_4, y_4);
+ else {
+ flattenCurve (points, pointi,
+ (x_1 + x_2)/2,
+ (y_1 + y_2)/2,
+ (x_1 + x_2*2 + x_3)/4,
+ (y_1 + y_2*2 + y_3)/4,
+ (x_1 + 3*x_2 + 3*x_3 + x_4)/8,
+ (y_1 + 3*y_2 + 3*y_3 + y_4)/8);
+ flattenCurve (points, pointi,
+ (x_2 + x_3*2 + x_4)/4,
+ (y_2 + y_3*2 + y_4)/4,
+ (x_3 + x_4)/2,
+ (y_3 + y_4)/2,
+ x_4,
+ y_4);
+ }
+}
+
+void
+DrawSpline (DviWidget dw, int *v, int n)
+{
+ int sx, sy, tx, ty;
+ int ox, oy, dx, dy;
+ int i;
+ int pointi;
+ XPoint points[POINTS_MAX];
+
+ if (n == 0 || (n & 1) != 0)
+ return;
+ AdjustCacheDeltas (dw);
+ setGC (dw);
+ ox = XPos (dw);
+ oy = YPos (dw);
+ dx = v[0];
+ dy = v[1];
+ sx = ox;
+ sy = oy;
+ tx = sx + DeviceToX (dw, dx);
+ ty = sy + DeviceToX (dw, dy);
+
+ pointi = 0;
+
+ appendPoint (points, &pointi, sx, sy);
+ appendPoint (points, &pointi, (sx + tx)/2, (sy + ty)/2);
+
+ for (i = 2; i < n; i += 2) {
+ int ux = ox + DeviceToX (dw, dx += v[i]);
+ int uy = oy + DeviceToX (dw, dy += v[i+1]);
+ flattenCurve (points, &pointi,
+ (sx + tx*5)/6, (sy + ty*5)/6,
+ (tx*5 + ux)/6, (ty*5 + uy)/6,
+ (tx + ux)/2, (ty + uy)/2);
+ sx = tx;
+ sy = ty;
+ tx = ux;
+ ty = uy;
+ }
+
+ appendPoint (points, &pointi, tx, ty);
+
+ XDrawLines (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC,
+ points, pointi, CoordModeOrigin);
+}
+
+
+/*
+Local Variables:
+c-indent-level: 8
+c-continued-statement-offset: 8
+c-brace-offset: -8
+c-argdecl-indent: 8
+c-label-offset: -8
+c-tab-always-indent: nil
+End:
+*/
diff --git a/contrib/groff/src/devices/xditview/font.c b/contrib/groff/src/devices/xditview/font.c
new file mode 100644
index 0000000..c111a7b
--- /dev/null
+++ b/contrib/groff/src/devices/xditview/font.c
@@ -0,0 +1,442 @@
+/*
+ * font.c
+ *
+ * map dvi fonts to X fonts
+ */
+
+#include <X11/Xos.h>
+#include <X11/IntrinsicP.h>
+#include <X11/StringDefs.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include "DviP.h"
+#include "XFontName.h"
+
+static void DisposeFontSizes(DviWidget, DviFontSizeList *);
+void DestroyFontMap(DviFontMap *);
+
+static char *
+savestr (const char *s)
+{
+ char *n;
+
+ if (!s)
+ return 0;
+ n = XtMalloc (strlen (s) + 1);
+ if (n)
+ strcpy (n, s);
+ return n;
+}
+
+static DviFontList *
+LookupFontByPosition (DviWidget dw, int position)
+{
+ DviFontList *f;
+
+ for (f = dw->dvi.fonts; f; f = f->next)
+ if (f->dvi_number == position)
+ break;
+ return f;
+}
+
+int
+MaxFontPosition (DviWidget dw)
+{
+ DviFontList *f;
+ int n = -1;
+
+ for (f = dw->dvi.fonts; f; f = f->next)
+ if (f->dvi_number > n)
+ n = f->dvi_number;
+ return n;
+}
+
+static DviFontSizeList *
+LookupFontSizeBySize (DviWidget dw, DviFontList *f, int size)
+{
+ DviFontSizeList *fs, *best = 0, *smallest = 0;
+ int bestsize = 0;
+ XFontName fontName;
+ unsigned int fontNameAttributes;
+ char fontNameString[2048];
+ int decipointsize;
+
+ if (f->scalable) {
+ decipointsize = (10*size)/dw->dvi.sizescale;
+ for (best = f->sizes; best; best = best->next)
+ if (best->size == decipointsize)
+ return best;
+ best = (DviFontSizeList *) XtMalloc(sizeof *best);
+ best->next = f->sizes;
+ best->size = decipointsize;
+ f->sizes = best;
+ XParseFontName (f->x_name, &fontName, &fontNameAttributes);
+ fontNameAttributes &= ~(FontNamePixelSize|FontNameAverageWidth);
+ fontNameAttributes |= FontNameResolutionX;
+ fontNameAttributes |= FontNameResolutionY;
+ fontNameAttributes |= FontNamePointSize;
+ fontName.ResolutionX = dw->dvi.display_resolution;
+ fontName.ResolutionY = dw->dvi.display_resolution;
+ fontName.PointSize = decipointsize;
+ XFormatFontName (&fontName, fontNameAttributes, fontNameString);
+ best->x_name = savestr (fontNameString);
+ best->doesnt_exist = 0;
+ best->font = 0;
+ return best;
+ }
+ for (fs = f->sizes; fs; fs=fs->next) {
+ if (dw->dvi.sizescale*fs->size <= 10*size
+ && fs->size >= bestsize) {
+ best = fs;
+ bestsize = fs->size;
+ }
+ if (smallest == 0 || fs->size < smallest->size)
+ smallest = fs;
+ }
+ return best ? best : smallest;
+}
+
+static char *
+SkipFontNameElement (char *n)
+{
+ while (*n != '-')
+ if (!*++n)
+ return 0;
+ return n+1;
+}
+
+# define SizePosition 8
+# define EncodingPosition 13
+
+static int
+ConvertFontNameToSize (char *n)
+{
+ int i, size;
+
+ for (i = 0; i < SizePosition; i++) {
+ n = SkipFontNameElement (n);
+ if (!n)
+ return -1;
+ }
+ size = atoi (n);
+ return size;
+}
+
+static char *
+ConvertFontNameToEncoding (char *n)
+{
+ int i;
+ for (i = 0; i < EncodingPosition; i++) {
+ n = SkipFontNameElement (n);
+ if (!n)
+ return 0;
+ }
+ return n;
+}
+
+DviFontSizeList *
+InstallFontSizes (DviWidget dw, const char *x_name, Boolean *scalablep)
+{
+ char fontNameString[2048];
+ char **fonts;
+ int i, count;
+ int size;
+ DviFontSizeList *sizes, *new_size;
+ XFontName fontName;
+ unsigned int fontNameAttributes;
+
+ *scalablep = FALSE;
+ if (!XParseFontName ((XFontNameString)x_name, &fontName,
+ &fontNameAttributes))
+ return 0;
+ fontNameAttributes &= ~(FontNamePixelSize|FontNamePointSize
+ |FontNameAverageWidth);
+ fontNameAttributes |= FontNameResolutionX;
+ fontNameAttributes |= FontNameResolutionY;
+ fontName.ResolutionX = dw->dvi.display_resolution;
+ fontName.ResolutionY = dw->dvi.display_resolution;
+ XFormatFontName (&fontName, fontNameAttributes, fontNameString);
+ fonts = XListFonts (XtDisplay (dw), fontNameString, 10000000, &count);
+ sizes = 0;
+ for (i = 0; i < count; i++) {
+ size = ConvertFontNameToSize (fonts[i]);
+ if (size == 0) {
+ DisposeFontSizes (dw, sizes);
+ sizes = 0;
+ *scalablep = TRUE;
+ break;
+ }
+ if (size != -1) {
+ new_size = (DviFontSizeList *) XtMalloc (sizeof *new_size);
+ new_size->next = sizes;
+ new_size->size = size;
+ new_size->x_name = savestr (fonts[i]);
+ new_size->doesnt_exist = 0;
+ new_size->font = 0;
+ sizes = new_size;
+ }
+ }
+ XFreeFontNames (fonts);
+ return sizes;
+}
+
+static void
+DisposeFontSizes (DviWidget dw, DviFontSizeList *fs)
+{
+ DviFontSizeList *next;
+
+ for (; fs; fs=next) {
+ next = fs->next;
+ if (fs->x_name)
+ XtFree (fs->x_name);
+ if (fs->font && fs->font != dw->dvi.default_font) {
+ XUnloadFont (XtDisplay (dw), fs->font->fid);
+ XFree ((char *)fs->font);
+ }
+ XtFree ((char *) fs);
+ }
+}
+
+static DviFontList *
+InstallFont (DviWidget dw, int position,
+ const char *dvi_name, const char *x_name)
+{
+ DviFontList *f;
+ char *encoding;
+
+ if ((f = LookupFontByPosition (dw, position)) != NULL) {
+ /*
+ * ignore gratuitous font loading
+ */
+ if (!strcmp (f->dvi_name, dvi_name) &&
+ !strcmp (f->x_name, x_name))
+ return f;
+
+ DisposeFontSizes (dw, f->sizes);
+ if (f->dvi_name)
+ XtFree (f->dvi_name);
+ if (f->x_name)
+ XtFree (f->x_name);
+ f->device_font = 0;
+ } else {
+ f = (DviFontList *) XtMalloc (sizeof (*f));
+ f->next = dw->dvi.fonts;
+ dw->dvi.fonts = f;
+ }
+ f->initialized = FALSE;
+ f->dvi_name = savestr (dvi_name);
+ f->device_font = device_find_font (dw->dvi.device, dvi_name);
+ f->x_name = savestr (x_name);
+ f->dvi_number = position;
+ f->sizes = 0;
+ f->scalable = FALSE;
+ if (f->x_name) {
+ encoding = ConvertFontNameToEncoding (f->x_name);
+ f->char_map = DviFindMap (encoding);
+ } else
+ f->char_map = 0;
+ /*
+ * force requery of fonts
+ */
+ dw->dvi.font = 0;
+ dw->dvi.font_number = -1;
+ dw->dvi.cache.font = 0;
+ dw->dvi.cache.font_number = -1;
+ dw->dvi.device_font = 0;
+ dw->dvi.device_font_number = -1;
+ return f;
+}
+
+void
+ForgetFonts (DviWidget dw)
+{
+ DviFontList *f = dw->dvi.fonts;
+
+ while (f) {
+ DviFontList *tem = f;
+
+ if (f->sizes)
+ DisposeFontSizes (dw, f->sizes);
+ if (f->dvi_name)
+ XtFree (f->dvi_name);
+ if (f->x_name)
+ XtFree (f->x_name);
+ f = f->next;
+ XtFree ((char *) tem);
+ }
+
+ /*
+ * force requery of fonts
+ */
+ dw->dvi.font = 0;
+ dw->dvi.font_number = -1;
+ dw->dvi.cache.font = 0;
+ dw->dvi.cache.font_number = -1;
+ dw->dvi.device_font = 0;
+ dw->dvi.device_font_number = -1;
+ dw->dvi.fonts = 0;
+}
+
+
+static char *
+MapDviNameToXName (DviWidget dw, const char *dvi_name)
+{
+ DviFontMap *fm;
+
+ for (fm = dw->dvi.font_map; fm; fm=fm->next)
+ if (!strcmp (fm->dvi_name, dvi_name))
+ return fm->x_name;
+ return 0;
+}
+
+#if 0
+static char *
+MapXNameToDviName (DviWidget dw, const char *x_name)
+{
+ DviFontMap *fm;
+
+ for (fm = dw->dvi.font_map; fm; fm=fm->next)
+ if (!strcmp (fm->x_name, x_name))
+ return fm->dvi_name;
+ return 0;
+}
+#endif
+
+void
+ParseFontMap (DviWidget dw)
+{
+ char dvi_name[1024];
+ char x_name[2048];
+ char *m, *s;
+ DviFontMap *fm, *new_map;
+
+ if (dw->dvi.font_map)
+ DestroyFontMap (dw->dvi.font_map);
+ fm = 0;
+ m = dw->dvi.font_map_string;
+ while (*m) {
+ s = m;
+ while (*m && !isspace (*m))
+ ++m;
+ strncpy (dvi_name, s, m-s);
+ dvi_name[m-s] = '\0';
+ while (isspace (*m))
+ ++m;
+ s = m;
+ while (*m && *m != '\n')
+ ++m;
+ strncpy (x_name, s, m-s);
+ x_name[m-s] = '\0';
+ new_map = (DviFontMap *) XtMalloc (sizeof *new_map);
+ new_map->x_name = savestr (x_name);
+ new_map->dvi_name = savestr (dvi_name);
+ new_map->next = fm;
+ fm = new_map;
+ ++m;
+ }
+ dw->dvi.font_map = fm;
+}
+
+void
+DestroyFontMap (DviFontMap *font_map)
+{
+ DviFontMap *next;
+
+ for (; font_map; font_map = next) {
+ next = font_map->next;
+ if (font_map->x_name)
+ XtFree (font_map->x_name);
+ if (font_map->dvi_name)
+ XtFree (font_map->dvi_name);
+ XtFree ((char *) font_map);
+ }
+}
+
+/* ARGSUSED */
+
+void
+SetFontPosition (DviWidget dw, int position,
+ const char *dvi_name, const char *extra)
+{
+ char *x_name;
+
+ x_name = MapDviNameToXName (dw, dvi_name);
+ if (x_name)
+ (void) InstallFont (dw, position, dvi_name, x_name);
+
+ extra = extra; /* unused; suppress compiler warning */
+}
+
+XFontStruct *
+QueryFont (DviWidget dw, int position, int size)
+{
+ DviFontList *f;
+ DviFontSizeList *fs;
+
+ f = LookupFontByPosition (dw, position);
+ if (!f)
+ return dw->dvi.default_font;
+ if (!f->initialized) {
+ f->sizes = InstallFontSizes (dw, f->x_name, &f->scalable);
+ f->initialized = TRUE;
+ }
+ fs = LookupFontSizeBySize (dw, f, size);
+ if (!fs)
+ return dw->dvi.default_font;
+ if (!fs->font) {
+ if (fs->x_name)
+ fs->font = XLoadQueryFont (XtDisplay (dw), fs->x_name);
+ if (!fs->font)
+ fs->font = dw->dvi.default_font;
+ }
+ return fs->font;
+}
+
+DeviceFont *
+QueryDeviceFont (DviWidget dw, int position)
+{
+ DviFontList *f;
+
+ f = LookupFontByPosition (dw, position);
+ if (!f)
+ return 0;
+ return f->device_font;
+}
+
+DviCharNameMap *
+QueryFontMap (DviWidget dw, int position)
+{
+ DviFontList *f;
+
+ f = LookupFontByPosition (dw, position);
+ if (f)
+ return f->char_map;
+ else
+ return 0;
+}
+
+#if 0
+LoadFont (DviWidget dw, int position, int size)
+{
+ XFontStruct *font;
+
+ font = QueryFont (dw, position, size);
+ dw->dvi.font_number = position;
+ dw->dvi.font_size = size;
+ dw->dvi.font = font;
+ XSetFont (XtDisplay (dw), dw->dvi.normal_GC, font->fid);
+ return;
+}
+#endif
+
+/*
+Local Variables:
+c-indent-level: 8
+c-continued-statement-offset: 8
+c-brace-offset: -8
+c-argdecl-indent: 8
+c-label-offset: -8
+c-tab-always-indent: nil
+End:
+*/
diff --git a/contrib/groff/src/devices/xditview/gray1.bm b/contrib/groff/src/devices/xditview/gray1.bm
new file mode 100644
index 0000000..c40a95e
--- /dev/null
+++ b/contrib/groff/src/devices/xditview/gray1.bm
@@ -0,0 +1,4 @@
+#define gray1_width 3
+#define gray1_height 3
+static char gray1_bits[] = {
+ 0x00, 0x02, 0x00};
diff --git a/contrib/groff/src/devices/xditview/gray2.bm b/contrib/groff/src/devices/xditview/gray2.bm
new file mode 100644
index 0000000..e87a1bc
--- /dev/null
+++ b/contrib/groff/src/devices/xditview/gray2.bm
@@ -0,0 +1,4 @@
+#define gray2_width 3
+#define gray2_height 3
+static char gray2_bits[] = {
+ 0x00, 0x03, 0x00};
diff --git a/contrib/groff/src/devices/xditview/gray3.bm b/contrib/groff/src/devices/xditview/gray3.bm
new file mode 100644
index 0000000..d9313eb
--- /dev/null
+++ b/contrib/groff/src/devices/xditview/gray3.bm
@@ -0,0 +1,4 @@
+#define gray3_width 3
+#define gray3_height 3
+static char gray3_bits[] = {
+ 0x00, 0x03, 0x02};
diff --git a/contrib/groff/src/devices/xditview/gray4.bm b/contrib/groff/src/devices/xditview/gray4.bm
new file mode 100644
index 0000000..dad142a
--- /dev/null
+++ b/contrib/groff/src/devices/xditview/gray4.bm
@@ -0,0 +1,4 @@
+#define gray4_width 3
+#define gray4_height 3
+static char gray4_bits[] = {
+ 0x00, 0x07, 0x02};
diff --git a/contrib/groff/src/devices/xditview/gray5.bm b/contrib/groff/src/devices/xditview/gray5.bm
new file mode 100644
index 0000000..5f57618
--- /dev/null
+++ b/contrib/groff/src/devices/xditview/gray5.bm
@@ -0,0 +1,4 @@
+#define gray5_width 3
+#define gray5_height 3
+static char gray5_bits[] = {
+ 0x04, 0x07, 0x02};
diff --git a/contrib/groff/src/devices/xditview/gray6.bm b/contrib/groff/src/devices/xditview/gray6.bm
new file mode 100644
index 0000000..b76701d
--- /dev/null
+++ b/contrib/groff/src/devices/xditview/gray6.bm
@@ -0,0 +1,4 @@
+#define gray6_width 3
+#define gray6_height 3
+static char gray6_bits[] = {
+ 0x04, 0x07, 0x03};
diff --git a/contrib/groff/src/devices/xditview/gray7.bm b/contrib/groff/src/devices/xditview/gray7.bm
new file mode 100644
index 0000000..ef47bc6
--- /dev/null
+++ b/contrib/groff/src/devices/xditview/gray7.bm
@@ -0,0 +1,4 @@
+#define gray7_width 3
+#define gray7_height 3
+static char gray7_bits[] = {
+ 0x05, 0x07, 0x03};
diff --git a/contrib/groff/src/devices/xditview/gray8.bm b/contrib/groff/src/devices/xditview/gray8.bm
new file mode 100644
index 0000000..12de7cb
--- /dev/null
+++ b/contrib/groff/src/devices/xditview/gray8.bm
@@ -0,0 +1,4 @@
+#define gray8_width 3
+#define gray8_height 3
+static char gray8_bits[] = {
+ 0x05, 0x07, 0x07};
diff --git a/contrib/groff/src/devices/xditview/gxditview.man b/contrib/groff/src/devices/xditview/gxditview.man
new file mode 100644
index 0000000..2c1302b
--- /dev/null
+++ b/contrib/groff/src/devices/xditview/gxditview.man
@@ -0,0 +1,410 @@
+.TH GXDITVIEW @MAN1EXT@ "@MDATE@" "Groff Version @VERSION@"
+.
+.
+.SH NAME
+gxditview \- display groff intermediate output files
+.
+.
+.SH SYNOPSIS
+.B \%gxditview
+.RI [\fB\- toolkitoption\ .\|.\|.\|]
+.RI [\fB\- option\ .\|.\|.\|]
+.RI [ filename ]
+.
+.
+.SH DESCRIPTION
+The
+.B \%gxditview
+program displays the
+.I groff intermediate
+.IR output ,
+see
+.BR groff_out (@MAN5EXT@),
+on an X\~display.
+.
+It uses the standard X11 fonts, so it does not require access to the
+server machine for font loading.
+.
+There are several ways to use
+.BR \%gxditview .
+.
+.
+.PP
+The
+.I groff intermediate output
+can be generated by
+.BR groff\~\-Z .
+This can be viewed by explicity calling
+.B \%gxditview
+.IR \%filename .
+If
+.I filename
+is
+.BR \- ,
+.B \%gxditview
+will read the standard input;
+.I \%filename
+cannot be omitted.
+.
+The
+.I groff intermediate output
+is different for all devices.
+.
+.B \%gxditview
+can view it for all devices, but the quality is not always good.
+.
+.
+.PP
+The best result is achieved with the
+.BR X *
+devices for
+.BR groff 's
+option
+.BR \-T .
+.
+There are four
+.BR X *
+devices:
+.BR \%\-TX75 ,
+.BR \%\-TX75\-12 ,
+.BR \%\-TX100 ,
+.BR \%\-TX100\-12 .
+They differ by the X\~resolution (75dpi or 100dpi) and the used base font
+size (10pt or 12pt).
+.
+They are especially built for
+.BR \%gxditview .
+When using one of them
+.B groff
+generates the
+.I intermediate output
+for this device and calls
+.B \%gxditview
+automatically for viewing.
+.
+.
+.PP
+.BR groff 's
+option
+.B \-X
+should be considered obsolete today; it produces
+.I intermediate output
+for
+.I Postscript
+and uses
+.B \%gxditview
+as a viewer for it, but with a bad quality.
+.
+Simply don't use it.
+.
+.
+.PP
+During the run of
+.BR \%gxditview ,
+the left mouse button brings up a menu with the following entries:
+.
+.TP 8
+.B "Next Page"
+Display the next page.
+.
+.TP
+.B "Previous Page"
+Display the previous page.
+.
+.TP
+.B "Select Page"
+Select a particular numbered page specified by a dialog box.
+.
+.TP
+.B Print
+Print the
+.I groff intermediate output
+using a command specified by a dialog box.
+.
+The default command initially displayed is controlled by the
+.B printCommand
+application resource, and by the
+.B \-printCommand
+option.
+.
+.TP
+.B Open
+Open for display a new file specified by a dialog box.
+.
+The file should contain some
+.I groff intermediate
+.IR output .
+If the filename starts with
+.B |
+it will be taken to be a command to read from.
+.
+.TP
+.B Quit
+Exit from
+.BR \%gxditview .
+.
+.
+.PP
+The
+.IR n ,
+.I Space
+and
+.I Return
+keys are bound to the
+.B Next\ Page
+action.
+.
+The
+.IR p ,
+.I BackSpace
+and
+.I Delete
+keys are bound to the
+.B Previous\ Page
+action.
+.
+The
+.I q
+key is bound to the
+.B Quit
+action.
+.
+The
+.I r
+key is bound to the
+.B Rerasterize
+action which rereads the current file, and redisplays the current
+page; if the current file is a command, the command will be
+reexecuted.
+.
+.
+.PP
+The
+.B paperlength
+and
+.B paperwidth
+commands in the DESC file specify the length and width in machine units
+of the virtual page displayed by
+.BR \%gxditview .
+.
+.
+.SH OPTIONS
+The
+.B \%gxditview
+program accepts all of the standard X\~Toolkit command line options
+along with the additional options listed below:
+.
+.TP 8
+.B \-help
+This option indicates that a brief summary of the allowed options should be
+printed.
+.
+.TP
+.B \-page
+This option specifies the page number of the document to be displayed.
+.
+.TP
+.BI \-backingStore\ backing-store-type
+Redisplay of the
+.I groff intermediate output
+window can take up to a second or so, this option causes the server to
+save the window contents so that when it is scrolled around the
+viewport, the window is painted from contents saved in backing store.
+.I backing-store-type
+can be one of
+.BR Always ,
+.B WhenMapped
+or
+.BR NotUseful .
+.
+.TP
+.BI \-printCommand\ command
+The default command displayed in the dialog box for the
+.B Print
+menu entry will be
+.IR command .
+.
+.TP
+.BI \-resolution\ res
+The
+.I groff intermediate output
+file will be displayed at a resolution of
+.I res
+dpi, unless the DESC file contains the
+.B X11
+command, in which case the device resolution will be used.
+.
+This corresponds to the
+.I Dvi
+widget's
+.B resolution
+resource.
+.
+The default is 75.
+.
+.TP
+.BI \-filename\ string
+The default filename displayed in the dialog box for the
+.B Open
+menu entry will be
+.IR string .
+This can be either a filename, or a command starting with
+.BR | .
+.
+.
+.PP
+The following standard X\~Toolkit command line arguments are commonly used
+with
+.BR \%gxditview :
+.
+.TP 8
+.BI \-bg\ color
+This option specifies the color to use for the background of the window.
+.
+The default is \fIwhite\fP.
+.
+.TP
+.BI \-bd\ color
+This option specifies the color to use for the border of the window.
+.
+The default is \fIblack\fP.
+.
+.TP
+.BI \-bw\ number
+This option specifies the width in pixels of the border surrounding the
+window.
+.
+.TP
+.BI \-fg\ color
+This option specifies the color to use for displaying text.
+.
+The default is
+\fIblack\fP.
+.
+.TP
+.BI \-fn\ font
+This option specifies the font to be used for displaying widget text.
+.
+The default is \fIfixed\fP.
+.
+.TP
+.B \-rv
+This option indicates that reverse video should be simulated by swapping
+the foreground and background colors.
+.
+.TP
+.BI \-geometry\ geometry
+This option specifies the preferred size and position of the window.
+.
+.TP
+.BI \-display\ host : display
+This option specifies the X\~server to contact.
+.
+.TP
+.BI \-xrm\ resourcestring
+This option specifies a resource string to be used.
+.
+.
+.SH X DEFAULTS
+This program uses the
+.I Dvi
+widget in the X\~Toolkit.
+.
+It understands all of the core resource names and classes as well as:
+.
+.TP 8
+.BR width\ (class\ Width )
+Specifies the width of the window.
+.
+.TP
+.BR height\ (class\ Height )
+Specifies the height of the window.
+.
+.TP
+.BR foreground\ (class\ Foreground )
+Specifies the default foreground color.
+.
+.TP
+.BR font\ (class\ Font )
+Specifies the font to be used for error messages.
+.
+.TP
+.BR fontMap\ (class\ FontMap )
+Specifies the mapping from
+.I groff
+font names to X\~font names.
+.
+This must be a string containing a sequence of lines.
+.
+Each line contains two whitespace separated fields: first the
+.I groff
+font name, and secondly the X\~font name.
+.
+The default is
+.nf
+"\e
+TR -adobe-times-medium-r-normal--*-100-*-*-*-*-iso8859-1\en\e
+TI -adobe-times-medium-i-normal--*-100-*-*-*-*-iso8859-1\en\e
+TB -adobe-times-bold-r-normal--*-100-*-*-*-*-iso8859-1\en\e
+TBI -adobe-times-bold-i-normal--*-100-*-*-*-*-iso8859-1\en\e
+CR -adobe-courier-medium-r-normal--*-100-*-*-*-*-iso8859-1\en\e
+CI -adobe-courier-medium-o-normal--*-100-*-*-*-*-iso8859-1\en\e
+CB -adobe-courier-bold-r-normal--*-100-*-*-*-*-iso8859-1\en\e
+CBI -adobe-courier-bold-o-normal--*-100-*-*-*-*-iso8859-1\en\e
+HR -adobe-helvetica-medium-r-normal--*-100-*-*-*-*-iso8859-1\en\e
+HI -adobe-helvetica-medium-o-normal--*-100-*-*-*-*-iso8859-1\en\e
+HB -adobe-helvetica-bold-r-normal--*-100-*-*-*-*-iso8859-1\en\e
+HBI -adobe-helvetica-bold-o-normal--*-100-*-*-*-*-iso8859-1\en\e
+NR -adobe-new century schoolbook-medium-r-normal--*-100-*-*-*-*-iso8859-1\en\e
+NI -adobe-new century schoolbook-medium-i-normal--*-100-*-*-*-*-iso8859-1\en\e
+NB -adobe-new century schoolbook-bold-r-normal--*-100-*-*-*-*-iso8859-1\en\e
+NBI -adobe-new century schoolbook-bold-i-normal--*-100-*-*-*-*-iso8859-1\en\e
+S -adobe-symbol-medium-r-normal--*-100-*-*-*-*-adobe-fontspecific\en\e
+SS -adobe-symbol-medium-r-normal--*-100-*-*-*-*-adobe-fontspecific\en\e
+"
+.fi
+.
+.
+.SH "SEE ALSO"
+.BR X (1),
+.BR xrdb (1),
+.BR xditview (1),
+.BR groff (@MAN1EXT@),
+.BR groff_out (@MAN5EXT@)
+.
+.
+.SH ORIGIN
+This program is derived from
+.BR \%xditview ;
+portions of
+.B \%xditview
+originated in
+.B \%xtroff
+which was derived from
+.BR \%suntroff .
+.
+.
+.SH COPYRIGHT
+Copyright 1989, Massachusetts Institute of Technology.
+.br
+See
+.BR X (1)
+for a full statement of rights and permissions.
+.
+.
+.SH AUTHORS
+Keith Packard (MIT X Consortium)
+.br
+Richard L. Hyde (Purdue)
+.br
+David Slattengren (Berkeley)
+.br
+Malcolm Slaney (Schlumberger Palo Alto Research)
+.br
+Mark Moraes (University of Toronto)
+.br
+James Clark
+.
+.\" Local Variables:
+.\" mode: nroff
+.\" End:
diff --git a/contrib/groff/src/devices/xditview/lex.c b/contrib/groff/src/devices/xditview/lex.c
new file mode 100644
index 0000000..dfe1e0d
--- /dev/null
+++ b/contrib/groff/src/devices/xditview/lex.c
@@ -0,0 +1,96 @@
+#include <X11/Xos.h>
+#include <X11/IntrinsicP.h>
+#include <X11/StringDefs.h>
+#include <stdio.h>
+#include "DviP.h"
+
+int
+DviGetAndPut(DviWidget dw, int *cp)
+{
+ if (dw->dvi.ungot) {
+ dw->dvi.ungot = 0;
+ *cp = getc (dw->dvi.file);
+ }
+ else {
+ *cp = getc (dw->dvi.file);
+ if (*cp != EOF)
+ putc (*cp, dw->dvi.tmpFile);
+ }
+ return *cp;
+}
+
+char *
+GetLine(DviWidget dw, char *Buffer, int Length)
+{
+ int i = 0, c;
+
+ Length--; /* Save room for final '\0' */
+
+ while (DviGetC (dw, &c) != EOF) {
+ if (Buffer && i < Length)
+ Buffer[i++] = c;
+ if (c == '\n') {
+ DviUngetC(dw, c);
+ break;
+ }
+ }
+ if (Buffer)
+ Buffer[i] = '\0';
+ return Buffer;
+}
+
+char *
+GetWord(DviWidget dw, char *Buffer, int Length)
+{
+ int i = 0, c;
+
+ Length--; /* Save room for final '\0' */
+ while (DviGetC(dw, &c) == ' ' || c == '\n')
+ ;
+ while (c != EOF) {
+ if (Buffer && i < Length)
+ Buffer[i++] = c;
+ if (DviGetC(dw, &c) == ' ' || c == '\n') {
+ DviUngetC(dw, c);
+ break;
+ }
+ }
+ if (Buffer)
+ Buffer[i] = '\0';
+ return Buffer;
+}
+
+int
+GetNumber(DviWidget dw)
+{
+ int i = 0, c;
+ int negative = 0;
+
+ while (DviGetC(dw, &c) == ' ' || c == '\n')
+ ;
+ if (c == '-') {
+ negative = 1;
+ DviGetC(dw, &c);
+ }
+
+ for (; c >= '0' && c <= '9'; DviGetC(dw, &c)) {
+ if (negative)
+ i = i*10 - (c - '0');
+ else
+ i = i*10 + c - '0';
+ }
+ if (c != EOF)
+ DviUngetC(dw, c);
+ return i;
+}
+
+/*
+Local Variables:
+c-indent-level: 8
+c-continued-statement-offset: 8
+c-brace-offset: -8
+c-argdecl-indent: 8
+c-label-offset: -8
+c-tab-always-indent: nil
+End:
+*/
diff --git a/contrib/groff/src/devices/xditview/page.c b/contrib/groff/src/devices/xditview/page.c
new file mode 100644
index 0000000..d1c5c9f
--- /dev/null
+++ b/contrib/groff/src/devices/xditview/page.c
@@ -0,0 +1,82 @@
+/*
+ * page.c
+ *
+ * map page numbers to file position
+ */
+
+#include <X11/Xos.h>
+#include <X11/IntrinsicP.h>
+#include <X11/StringDefs.h>
+#include <stdio.h>
+#include <ctype.h>
+#include "DviP.h"
+
+#ifdef X_NOT_STDC_ENV
+extern long ftell();
+#endif
+
+static DviFileMap *
+MapPageNumberToFileMap (DviWidget dw, int number)
+{
+ DviFileMap *m;
+
+ for (m = dw->dvi.file_map; m; m=m->next)
+ if (m->page_number == number)
+ break;
+ return m;
+}
+
+void
+DestroyFileMap (DviFileMap *m)
+{
+ DviFileMap *next;
+
+ for (; m; m = next) {
+ next = m->next;
+ XtFree ((char *) m);
+ }
+}
+
+void
+ForgetPagePositions (DviWidget dw)
+{
+ DestroyFileMap (dw->dvi.file_map);
+ dw->dvi.file_map = 0;
+}
+
+void
+RememberPagePosition(DviWidget dw, int number)
+{
+ DviFileMap *m;
+
+ if (!(m = MapPageNumberToFileMap (dw, number))) {
+ m = (DviFileMap *) XtMalloc (sizeof *m);
+ m->page_number = number;
+ m->next = dw->dvi.file_map;
+ dw->dvi.file_map = m;
+ }
+ if (dw->dvi.tmpFile)
+ m->position = ftell (dw->dvi.tmpFile);
+ else
+ m->position = ftell (dw->dvi.file);
+}
+
+long
+SearchPagePosition (DviWidget dw, int number)
+{
+ DviFileMap *m;
+
+ if (!(m = MapPageNumberToFileMap (dw, number)))
+ return -1;
+ return m->position;
+}
+
+void
+FileSeek(DviWidget dw, long position)
+{
+ if (dw->dvi.tmpFile) {
+ dw->dvi.readingTmp = 1;
+ fseek (dw->dvi.tmpFile, position, 0);
+ } else
+ fseek (dw->dvi.file, position, 0);
+}
diff --git a/contrib/groff/src/devices/xditview/parse.c b/contrib/groff/src/devices/xditview/parse.c
new file mode 100644
index 0000000..de7d6ba
--- /dev/null
+++ b/contrib/groff/src/devices/xditview/parse.c
@@ -0,0 +1,366 @@
+/*
+ * parse.c
+ *
+ * parse dvi input
+ */
+
+#include <X11/Xos.h>
+#include <X11/IntrinsicP.h>
+#include <X11/StringDefs.h>
+#include <stdio.h>
+#include <ctype.h>
+#include "DviP.h"
+
+static int StopSeen = 0;
+static void ParseDrawFunction(DviWidget, char *);
+static void ParseDeviceControl(DviWidget);
+static void push_env(DviWidget);
+static void pop_env(DviWidget);
+
+/* draw.c */
+extern int PutCharacter(DviWidget, char *);
+extern int PutNumberedCharacter(DviWidget, int);
+extern void HorizontalGoto(DviWidget, int);
+extern void Word(DviWidget);
+extern void VerticalGoto(DviWidget, int);
+extern void VerticalMove(DviWidget, int);
+extern void FlushCharCache(DviWidget);
+extern void Newline(DviWidget);
+extern void DrawLine(DviWidget, int, int);
+extern void DrawCircle(DviWidget, int);
+extern void DrawFilledCircle(DviWidget, int);
+extern void DrawEllipse(DviWidget, int, int);
+extern void DrawFilledEllipse(DviWidget, int, int);
+extern void DrawArc(DviWidget, int, int, int, int);
+extern void DrawPolygon(DviWidget, int *, int);
+extern void DrawFilledPolygon(DviWidget, int *, int);
+extern void DrawSpline(DviWidget, int *, int);
+
+/* Dvi.c */
+extern void SetDevice(DviWidget, const char *);
+
+/* page.c */
+extern void RememberPagePosition(DviWidget, int);
+
+/* font.c */
+extern void SetFontPosition(DviWidget, int, const char *, const char *);
+
+/* lex.c */
+extern int GetNumber(DviWidget);
+
+#define HorizontalMove(dw, delta) ((dw)->dvi.state->x += (delta))
+
+
+int
+ParseInput(register DviWidget dw)
+{
+ int n, k;
+ int c;
+ char Buffer[BUFSIZ];
+ int NextPage;
+ int otherc;
+
+ StopSeen = 0;
+
+ /*
+ * make sure some state exists
+ */
+
+ if (!dw->dvi.state)
+ push_env (dw);
+ for (;;) {
+ switch (DviGetC(dw, &c)) {
+ case '\n':
+ break;
+ case ' ': /* when input is text */
+ case 0: /* occasional noise creeps in */
+ break;
+ case '{': /* push down current environment */
+ push_env(dw);
+ break;
+ case '}':
+ pop_env(dw);
+ break;
+ /*
+ * two motion digits plus a character
+ */
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ HorizontalMove(dw, (c-'0')*10 +
+ DviGetC(dw,&otherc)-'0');
+ /* fall through */
+ case 'c': /* single ascii character */
+ DviGetC(dw,&c);
+ if (c == ' ')
+ break;
+ Buffer[0] = c;
+ Buffer[1] = '\0';
+ (void) PutCharacter (dw, Buffer);
+ break;
+ case 'C':
+ GetWord (dw, Buffer, BUFSIZ);
+ (void) PutCharacter (dw, Buffer);
+ break;
+ case 't':
+ Buffer[1] = '\0';
+ while (DviGetC (dw, &c) != EOF
+ && c != ' ' && c != '\n') {
+ Buffer[0] = c;
+ HorizontalMove (dw, PutCharacter (dw, Buffer));
+ }
+ break;
+ case 'u':
+ n = GetNumber(dw);
+ Buffer[1] = '\0';
+ while (DviGetC (dw, &c) == ' ')
+ ;
+ while (c != EOF && c != ' ' && c != '\n') {
+ Buffer[0] = c;
+ HorizontalMove (dw,
+ PutCharacter (dw, Buffer) + n);
+ DviGetC (dw, &c);
+ }
+ break;
+
+ case 'D': /* draw function */
+ (void) GetLine(dw, Buffer, BUFSIZ);
+ if (dw->dvi.display_enable)
+ ParseDrawFunction(dw, Buffer);
+ break;
+ case 's': /* ignore fractional sizes */
+ n = GetNumber(dw);
+ dw->dvi.state->font_size = n;
+ break;
+ case 'f':
+ n = GetNumber(dw);
+ dw->dvi.state->font_number = n;
+ break;
+ case 'H': /* absolute horizontal motion */
+ k = GetNumber(dw);
+ HorizontalGoto(dw, k);
+ break;
+ case 'h': /* relative horizontal motion */
+ k = GetNumber(dw);
+ HorizontalMove(dw, k);
+ break;
+ case 'w': /* word space */
+ Word (dw);
+ break;
+ case 'V':
+ n = GetNumber(dw);
+ VerticalGoto(dw, n);
+ break;
+ case 'v':
+ n = GetNumber(dw);
+ VerticalMove(dw, n);
+ break;
+ case 'P': /* new spread */
+ break;
+ case 'p': /* new page */
+ (void) GetNumber(dw);
+ NextPage = dw->dvi.current_page + 1;
+ RememberPagePosition(dw, NextPage);
+ FlushCharCache (dw);
+ return(NextPage);
+ case 'N':
+ n = GetNumber(dw);
+ PutNumberedCharacter (dw, n);
+ break;
+ case 'n': /* end of line */
+ GetNumber(dw);
+ GetNumber(dw);
+ Newline (dw);
+ HorizontalGoto(dw, 0);
+ break;
+ case 'F': /* input files */
+ case '+': /* continuation of X device control */
+ case 'm': /* color */
+ case '#': /* comment */
+ GetLine(dw, NULL, 0);
+ break;
+ case 'x': /* device control */
+ ParseDeviceControl(dw);
+ break;
+ case EOF:
+ dw->dvi.last_page = dw->dvi.current_page;
+ FlushCharCache (dw);
+ return dw->dvi.current_page;
+ default:
+ break;
+ }
+ }
+}
+
+static void
+push_env(DviWidget dw)
+{
+ DviState *new_state;
+
+ new_state = (DviState *) XtMalloc (sizeof (*new_state));
+ if (dw->dvi.state)
+ *new_state = *(dw->dvi.state);
+ else {
+ new_state->font_size = 10;
+ new_state->font_number = 1;
+ new_state->x = 0;
+ new_state->y = 0;
+ }
+ new_state->next = dw->dvi.state;
+ dw->dvi.state = new_state;
+}
+
+static void
+pop_env(DviWidget dw)
+{
+ DviState *old;
+
+ old = dw->dvi.state;
+ dw->dvi.state = old->next;
+ XtFree ((char *) old);
+}
+
+static void
+InitTypesetter (DviWidget dw)
+{
+ while (dw->dvi.state)
+ pop_env (dw);
+ push_env (dw);
+ FlushCharCache (dw);
+}
+
+#define DRAW_ARGS_MAX 128
+
+static void
+ParseDrawFunction(DviWidget dw, char *buf)
+{
+ int v[DRAW_ARGS_MAX];
+ int i, no_move = 0;
+ char *ptr;
+
+ v[0] = v[1] = v[2] = v[3] = 0;
+
+ if (buf[0] == '\0')
+ return;
+ ptr = buf+1;
+
+ for (i = 0; i < DRAW_ARGS_MAX; i++) {
+ if (sscanf(ptr, "%d", v + i) != 1)
+ break;
+ while (*ptr == ' ')
+ ptr++;
+ while (*ptr != '\0' && *ptr != ' ')
+ ptr++;
+ }
+
+ switch (buf[0]) {
+ case 'l': /* draw a line */
+ DrawLine(dw, v[0], v[1]);
+ break;
+ case 'c': /* circle */
+ DrawCircle(dw, v[0]);
+ break;
+ case 'C':
+ DrawFilledCircle(dw, v[0]);
+ break;
+ case 'e': /* ellipse */
+ DrawEllipse(dw, v[0], v[1]);
+ break;
+ case 'E':
+ DrawFilledEllipse(dw, v[0], v[1]);
+ break;
+ case 'a': /* arc */
+ DrawArc(dw, v[0], v[1], v[2], v[3]);
+ break;
+ case 'p':
+ DrawPolygon(dw, v, i);
+ break;
+ case 'P':
+ DrawFilledPolygon(dw, v, i);
+ break;
+ case '~': /* wiggly line */
+ DrawSpline(dw, v, i);
+ break;
+ case 't':
+ dw->dvi.line_thickness = v[0];
+ break;
+ 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 (!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];
+ }
+ }
+ }
+}
+
+static void
+ParseDeviceControl(DviWidget dw) /* Parse the x commands */
+{
+ char str[20], str1[50];
+ int c, n;
+
+ GetWord (dw, str, 20);
+ switch (str[0]) { /* crude for now */
+ case 'T': /* output device */
+ GetWord (dw, str, 20);
+ SetDevice (dw, str);
+ break;
+ case 'i': /* initialize */
+ InitTypesetter (dw);
+ break;
+ case 't': /* trailer */
+ break;
+ case 'p': /* pause -- can restart */
+ break;
+ case 's': /* stop */
+ StopSeen = 1;
+ return;
+ case 'r': /* resolution when prepared */
+ break;
+ case 'f': /* font used */
+ n = GetNumber (dw);
+ GetWord (dw, str, 20);
+ GetLine (dw, str1, 50);
+ SetFontPosition (dw, n, str, str1);
+ break;
+ case 'H': /* char height */
+ break;
+ case 'S': /* slant */
+ break;
+ }
+ while (DviGetC (dw, &c) != '\n') /* skip rest of input line */
+ if (c == EOF)
+ return;
+ return;
+}
+
+
+/*
+Local Variables:
+c-indent-level: 8
+c-continued-statement-offset: 8
+c-brace-offset: -8
+c-argdecl-indent: 8
+c-label-offset: -8
+c-tab-always-indent: nil
+End:
+*/
diff --git a/contrib/groff/src/devices/xditview/xdit.bm b/contrib/groff/src/devices/xditview/xdit.bm
new file mode 100644
index 0000000..0c7aa8c
--- /dev/null
+++ b/contrib/groff/src/devices/xditview/xdit.bm
@@ -0,0 +1,14 @@
+#define xdit_width 32
+#define xdit_height 32
+static unsigned char xdit_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0x03, 0x02, 0x00, 0x00, 0x02,
+ 0x8a, 0xa2, 0xfc, 0x03, 0x52, 0x14, 0x03, 0x04, 0x02, 0x80, 0x00, 0x08,
+ 0x52, 0x54, 0x00, 0x10, 0x8a, 0x22, 0x8f, 0x23, 0x02, 0x20, 0x06, 0x21,
+ 0x8a, 0x12, 0x8c, 0x40, 0x52, 0x14, 0x8c, 0x40, 0x02, 0x10, 0x58, 0x40,
+ 0x52, 0x14, 0x30, 0x40, 0x8a, 0x12, 0x30, 0x40, 0x02, 0x10, 0x70, 0x40,
+ 0x8a, 0x12, 0xc8, 0x40, 0x52, 0x24, 0xc4, 0xe0, 0x02, 0x20, 0x84, 0xe1,
+ 0x52, 0x54, 0xce, 0xf3, 0x8a, 0xa2, 0x00, 0xf8, 0x02, 0x00, 0x03, 0xfc,
+ 0x8a, 0x22, 0xfc, 0xf3, 0x52, 0x14, 0x00, 0xc2, 0x02, 0x00, 0x00, 0x02,
+ 0x52, 0x14, 0x45, 0x02, 0x8a, 0xa2, 0x28, 0x02, 0x02, 0x00, 0x00, 0x02,
+ 0x02, 0x00, 0x00, 0x02, 0xfe, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/contrib/groff/src/devices/xditview/xdit_mask.bm b/contrib/groff/src/devices/xditview/xdit_mask.bm
new file mode 100644
index 0000000..a584629
--- /dev/null
+++ b/contrib/groff/src/devices/xditview/xdit_mask.bm
@@ -0,0 +1,14 @@
+#define xdit_mask_width 32
+#define xdit_mask_height 32
+static unsigned char xdit_mask_bits[] = {
+ 0xff, 0xff, 0xff, 0x07, 0xff, 0xff, 0xff, 0x07, 0xff, 0xff, 0xff, 0x07,
+ 0xff, 0xff, 0xff, 0x07, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x1f,
+ 0xff, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xc7,
+ 0xff, 0xff, 0xff, 0x07, 0xff, 0xff, 0xff, 0x07, 0xff, 0xff, 0xff, 0x07,
+ 0xff, 0xff, 0xff, 0x07, 0xff, 0xff, 0xff, 0x07, 0xff, 0xff, 0xff, 0x07,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/contrib/groff/src/devices/xditview/xditview.c b/contrib/groff/src/devices/xditview/xditview.c
new file mode 100644
index 0000000..7afdb47
--- /dev/null
+++ b/contrib/groff/src/devices/xditview/xditview.c
@@ -0,0 +1,657 @@
+/*
+ * Copyright 1991 Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of M.I.T. not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. M.I.T. makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T.
+ * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+/*
+ * xditview --
+ *
+ * Display ditroff output in an X window
+ */
+
+#ifndef SABER
+#ifndef lint
+static char rcsid[] = "$XConsortium: xditview.c,v 1.17 89/12/10 17:05:08 rws Exp $";
+#endif /* lint */
+#endif /* SABER */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <X11/Xatom.h>
+#include <X11/Xlib.h>
+#include <X11/Xos.h>
+#include <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+#include <X11/Shell.h>
+#include <X11/Xaw/Paned.h>
+#include <X11/Xaw/Viewport.h>
+#include <X11/Xaw/Box.h>
+#include <X11/Xaw/Command.h>
+#include <X11/Xaw/Dialog.h>
+#include <X11/Xaw/Label.h>
+#include <X11/Xaw/SimpleMenu.h>
+#include <X11/Xaw/SmeBSB.h>
+
+#include <stdlib.h>
+#include <signal.h>
+#include <stdio.h>
+
+#include "Dvi.h"
+
+#include "xdit.bm"
+#include "xdit_mask.bm"
+
+#ifdef NEED_DECLARATION_POPEN
+FILE *popen(const char *, const char *);
+#endif /* NEED_DECLARATION_POPEN */
+
+#ifdef NEED_DECLARATION_PCLOSE
+int pclose (FILE *);
+#endif /* NEED_DECLARATION_PCLOSE */
+
+typedef void (*MakePromptFunc)(const char *);
+
+static String fallback_resources[] = {
+#include "GXditview-ad.h"
+ NULL
+};
+
+static struct app_resources {
+ char *print_command;
+ char *filename;
+} app_resources;
+
+#define offset(field) XtOffset(struct app_resources *, field)
+
+/* Application resources. */
+
+static XtResource resources[] = {
+ {(String)"printCommand", (String)"PrintCommand", (String)XtRString,
+ sizeof(char*), offset(print_command), (String)XtRString, NULL},
+ {(String)"filename", (String)"Filename", (String)XtRString,
+ sizeof(char*), offset(filename), (String)XtRString, NULL},
+};
+
+#undef offset
+
+/* Command line options table. Only resources are entered here...there is a
+ pass over the remaining options after XtParseCommand is let loose. */
+
+static XrmOptionDescRec options[] = {
+{(char *)"-page", (char *)"*dvi.pageNumber",
+ XrmoptionSepArg, NULL},
+{(char *)"-backingStore", (char *)"*dvi.backingStore",
+ XrmoptionSepArg, NULL},
+{(char *)"-resolution", (char *)"*dvi.resolution",
+ XrmoptionSepArg, NULL},
+{(char *)"-printCommand", (char *)".printCommand",
+ XrmoptionSepArg, NULL},
+{(char *)"-filename", (char *)".filename",
+ XrmoptionSepArg, NULL},
+{(char *)"-noPolyText", (char *)"*dvi.noPolyText",
+ XrmoptionNoArg, (XPointer)"TRUE"},
+};
+
+static char current_print_command[1024];
+
+static char current_file_name[1024];
+static FILE *current_file;
+
+/*
+ * Report the syntax for calling xditview.
+ */
+
+static void
+Syntax(const char *call)
+{
+ (void) printf ("Usage: %s [-fg <color>] [-bg <color>]\n", call);
+ (void) printf (" [-bd <color>] [-bw <pixels>] [-help]\n");
+ (void) printf (" [-display displayname] [-geometry geom]\n");
+ (void) printf (" [-page <page-number>] [-backing <backing-store>]\n");
+ (void) printf (" [-resolution <res>] [-print <command>]\n");
+ (void) printf (" [-filename <file>] [filename]\n\n");
+ exit(1);
+}
+
+static void NewFile (const char *);
+static void SetPageNumber (int);
+static Widget toplevel, paned, viewport, dvi;
+static Widget page;
+static Widget simpleMenu;
+
+static void NextPage(Widget, XtPointer, XtPointer);
+static void PreviousPage(Widget, XtPointer, XtPointer);
+static void SelectPage(Widget, XtPointer, XtPointer);
+static void OpenFile(Widget, XtPointer, XtPointer);
+static void Quit(Widget, XtPointer, XtPointer);
+static void Print(Widget, XtPointer, XtPointer);
+
+static struct menuEntry {
+ const char *name;
+ XtCallbackProc function;
+} menuEntries[] = {
+ {"nextPage", NextPage},
+ {"previousPage", PreviousPage},
+ {"selectPage", SelectPage},
+ {"print", Print},
+ {"openFile", OpenFile},
+ {"quit", Quit},
+};
+
+static void NextPageAction(Widget, XEvent *, String *, Cardinal *);
+static void PreviousPageAction(Widget, XEvent *, String *, Cardinal *);
+static void SelectPageAction(Widget, XEvent *, String *, Cardinal *);
+static void OpenFileAction(Widget, XEvent *, String *, Cardinal *);
+static void QuitAction(Widget, XEvent *, String *, Cardinal *);
+static void AcceptAction(Widget, XEvent *, String *, Cardinal *);
+static void CancelAction(Widget, XEvent *, String *, Cardinal *);
+static void PrintAction(Widget, XEvent *, String *, Cardinal *);
+static void RerasterizeAction(Widget, XEvent *, String *, Cardinal *);
+
+static void MakePrompt(Widget, const char *, MakePromptFunc, const char *);
+
+XtActionsRec xditview_actions[] = {
+ {(String)"NextPage", NextPageAction},
+ {(String)"PreviousPage", PreviousPageAction},
+ {(String)"SelectPage", SelectPageAction},
+ {(String)"Print", PrintAction},
+ {(String)"OpenFile", OpenFileAction},
+ {(String)"Rerasterize", RerasterizeAction},
+ {(String)"Quit", QuitAction},
+ {(String)"Accept", AcceptAction},
+ {(String)"Cancel", CancelAction},
+};
+
+#define MenuNextPage 0
+#define MenuPreviousPage 1
+#define MenuSelectPage 2
+#define MenuPrint 3
+#define MenuOpenFile 4
+#define MenuQuit 5
+
+static char pageLabel[256] = "Page <none>";
+
+int main(int argc, char **argv)
+{
+ char *file_name = 0;
+ Cardinal i;
+ static Arg labelArgs[] = {
+ {XtNlabel, (XtArgVal) pageLabel},
+ };
+ XtAppContext xtcontext;
+ Arg topLevelArgs[2];
+ Widget entry;
+ Arg pageNumberArgs[1];
+ int page_number;
+
+ toplevel = XtAppInitialize(&xtcontext, "GXditview",
+ options, XtNumber (options),
+ &argc, argv, fallback_resources, NULL, 0);
+ if (argc > 2
+ || (argc == 2 && (!strcmp(argv[1], "-help")
+ || !strcmp(argv[1], "--help"))))
+ Syntax(argv[0]);
+
+ XtGetApplicationResources(toplevel, (XtPointer)&app_resources,
+ resources, XtNumber(resources),
+ NULL, (Cardinal) 0);
+ if (app_resources.print_command)
+ strcpy(current_print_command, app_resources.print_command);
+
+ XtAppAddActions(xtcontext, xditview_actions, XtNumber (xditview_actions));
+
+ XtSetArg (topLevelArgs[0], XtNiconPixmap,
+ XCreateBitmapFromData (XtDisplay (toplevel),
+ XtScreen(toplevel)->root,
+ (char *)xdit_bits,
+ xdit_width, xdit_height));
+
+ XtSetArg (topLevelArgs[1], XtNiconMask,
+ XCreateBitmapFromData (XtDisplay (toplevel),
+ XtScreen(toplevel)->root,
+ (char *)xdit_mask_bits,
+ xdit_mask_width, xdit_mask_height));
+ XtSetValues (toplevel, topLevelArgs, 2);
+ if (argc > 1)
+ file_name = argv[1];
+
+ /*
+ * create the menu and insert the entries
+ */
+ simpleMenu = XtCreatePopupShell ("menu", simpleMenuWidgetClass, toplevel,
+ NULL, 0);
+ for (i = 0; i < XtNumber (menuEntries); i++) {
+ entry = XtCreateManagedWidget(menuEntries[i].name,
+ smeBSBObjectClass, simpleMenu,
+ NULL, (Cardinal) 0);
+ XtAddCallback(entry, XtNcallback, menuEntries[i].function, NULL);
+ }
+
+ paned = XtCreateManagedWidget("paned", panedWidgetClass, toplevel,
+ NULL, (Cardinal) 0);
+ viewport = XtCreateManagedWidget("viewport", viewportWidgetClass, paned,
+ NULL, (Cardinal) 0);
+ dvi = XtCreateManagedWidget ("dvi", dviWidgetClass, viewport, NULL, 0);
+ page = XtCreateManagedWidget ("label", labelWidgetClass, paned,
+ labelArgs, XtNumber (labelArgs));
+ XtSetArg (pageNumberArgs[0], XtNpageNumber, &page_number);
+ XtGetValues (dvi, pageNumberArgs, 1);
+ if (file_name)
+ NewFile (file_name);
+ /* NewFile modifies current_file_name, so do this here. */
+ if (app_resources.filename)
+ strcpy(current_file_name, app_resources.filename);
+ XtRealizeWidget (toplevel);
+ if (file_name)
+ SetPageNumber (page_number);
+ XtAppMainLoop(xtcontext);
+ return 0;
+}
+
+static void
+SetPageNumber (int number)
+{
+ Arg arg[2];
+ int actual_number, last_page;
+
+ XtSetArg (arg[0], XtNpageNumber, number);
+ XtSetValues (dvi, arg, 1);
+ XtSetArg (arg[0], XtNpageNumber, &actual_number);
+ XtSetArg (arg[1], XtNlastPageNumber, &last_page);
+ XtGetValues (dvi, arg, 2);
+ if (actual_number == 0)
+ sprintf (pageLabel, "Page <none>");
+ else if (last_page > 0)
+ sprintf (pageLabel, "Page %d of %d", actual_number, last_page);
+ else
+ sprintf (pageLabel, "Page %d", actual_number);
+ XtSetArg (arg[0], XtNlabel, pageLabel);
+ XtSetValues (page, arg, 1);
+}
+
+static void
+SelectPageNumber (const char *number_string)
+{
+ SetPageNumber (atoi(number_string));
+}
+
+static int hadFile = 0;
+
+static void
+NewFile (const char *name)
+{
+ Arg arg[2];
+ char *n;
+ FILE *new_file;
+ Boolean seek = 0;
+
+ if (current_file) {
+ if (!strcmp (current_file_name, "-"))
+ ;
+ else if (current_file_name[0] == '|')
+ pclose (current_file);
+ else
+ fclose (current_file);
+ }
+ if (!strcmp (name, "-"))
+ new_file = stdin;
+ else if (name[0] == '|')
+ new_file = popen (name+1, "r");
+ else {
+ new_file = fopen (name, "r");
+ seek = 1;
+ }
+ if (!new_file) {
+ /* XXX display error message */
+ return;
+ }
+ XtSetArg (arg[0], XtNfile, new_file);
+ XtSetArg (arg[1], XtNseek, seek);
+ XtSetValues (dvi, arg, 2);
+ if (hadFile || name[0] != '-' || name[1] != '\0') {
+ XtSetArg (arg[0], XtNtitle, name);
+ if (name[0] != '/' && (n = strrchr (name, '/')))
+ n = n + 1;
+ else
+ n = (char *)name;
+ XtSetArg (arg[1], XtNiconName, n);
+ XtSetValues (toplevel, arg, 2);
+ }
+ hadFile = 1;
+ SelectPageNumber ("1");
+ strcpy (current_file_name, name);
+ current_file = new_file;
+}
+
+static char fileBuf[1024];
+
+static void
+ResetMenuEntry (Widget entry)
+{
+ Arg arg[1];
+
+ XtSetArg (arg[0], (String)XtNpopupOnEntry, entry);
+ XtSetValues (XtParent(entry) , arg, (Cardinal) 1);
+}
+
+/*ARGSUSED*/
+
+static void
+NextPage (Widget entry, XtPointer name, XtPointer data)
+{
+ name = name; /* unused; suppress compiler warning */
+ data = data;
+
+ NextPageAction((Widget)NULL, (XEvent *) 0, (String *) 0, (Cardinal *) 0);
+ ResetMenuEntry (entry);
+}
+
+static void
+NextPageAction (Widget widget, XEvent *event,
+ String *params, Cardinal *num_params)
+{
+ Arg args[1];
+ int number;
+
+ XtSetArg (args[0], XtNpageNumber, &number);
+ XtGetValues (dvi, args, 1);
+ SetPageNumber (number+1);
+
+ widget = widget; /* unused; suppress compiler warning */
+ event = event;
+ params = params;
+ num_params = num_params;
+}
+
+/*ARGSUSED*/
+
+static void
+PreviousPage (Widget entry, XtPointer name, XtPointer data)
+{
+ name = name; /* unused; suppress compiler warning */
+ data = data;
+
+ PreviousPageAction ((Widget)NULL, (XEvent *) 0, (String *) 0,
+ (Cardinal *) 0);
+ ResetMenuEntry (entry);
+}
+
+static void
+PreviousPageAction (Widget widget, XEvent *event,
+ String *params, Cardinal *num_params)
+{
+ Arg args[1];
+ int number;
+
+ XtSetArg (args[0], XtNpageNumber, &number);
+ XtGetValues (dvi, args, 1);
+ SetPageNumber (number-1);
+
+ widget = widget; /* unused; suppress compiler warning */
+ event = event;
+ params = params;
+ num_params = num_params;
+}
+
+/* ARGSUSED */
+
+static void
+SelectPage (Widget entry, XtPointer name, XtPointer data)
+{
+ name = name; /* unused; suppress compiler warning */
+ data = data;
+
+ SelectPageAction ((Widget)NULL, (XEvent *) 0, (String *) 0,
+ (Cardinal *) 0);
+ ResetMenuEntry (entry);
+}
+
+static void
+SelectPageAction (Widget widget, XEvent *event,
+ String *params, Cardinal *num_params)
+{
+ widget = widget; /* unused; suppress compiler warning */
+ event = event;
+ params = params;
+ num_params = num_params;
+
+ MakePrompt (toplevel, "Page number", SelectPageNumber, "");
+}
+
+
+static void
+DoPrint (const char *name)
+{
+ FILE *print_file;
+ RETSIGTYPE (*handler)(int);
+
+ /* Avoid dieing because of an invalid command. */
+ handler = signal(SIGPIPE, SIG_IGN);
+
+ print_file = popen(name, "w");
+ if (!print_file)
+ /* XXX print error message */
+ return;
+ DviSaveToFile(dvi, print_file);
+ pclose(print_file);
+ signal(SIGPIPE, handler);
+ strcpy(current_print_command, name);
+}
+
+static void
+RerasterizeAction (Widget widget, XEvent *event,
+ String *params, Cardinal *num_params)
+{
+ Arg args[1];
+ int number;
+
+ if (current_file_name[0] == 0) {
+ /* XXX display an error message */
+ return;
+ }
+ XtSetArg (args[0], XtNpageNumber, &number);
+ XtGetValues (dvi, args, 1);
+ NewFile(current_file_name);
+ SetPageNumber (number);
+
+ widget = widget; /* unused; suppress compiler warning */
+ event = event;
+ params = params;
+ num_params = num_params;
+}
+
+/* ARGSUSED */
+
+static void
+Print (Widget entry, XtPointer name, XtPointer data)
+{
+ name = name; /* unused; suppress compiler warning */
+ data = data;
+
+ PrintAction ((Widget)NULL, (XEvent *) 0, (String *) 0, (Cardinal *) 0);
+ ResetMenuEntry (entry);
+}
+
+static void
+PrintAction (Widget widget, XEvent *event,
+ String *params, Cardinal *num_params)
+{
+ widget = widget; /* unused; suppress compiler warning */
+ event = event;
+ params = params;
+ num_params = num_params;
+
+ if (current_print_command[0])
+ strcpy (fileBuf, current_print_command);
+ else
+ fileBuf[0] = '\0';
+ MakePrompt (toplevel, "Print command:", DoPrint, fileBuf);
+}
+
+
+/* ARGSUSED */
+
+static void
+OpenFile (Widget entry, XtPointer name, XtPointer data)
+{
+ name = name; /* unused; suppress compiler warning */
+ data = data;
+
+ OpenFileAction ((Widget)NULL, (XEvent *) 0, (String *) 0, (Cardinal *) 0);
+ ResetMenuEntry (entry);
+}
+
+static void
+OpenFileAction (Widget widget, XEvent *event,
+ String *params, Cardinal *num_params)
+{
+ widget = widget; /* unused; suppress compiler warning */
+ event = event;
+ params = params;
+ num_params = num_params;
+
+ if (current_file_name[0])
+ strcpy (fileBuf, current_file_name);
+ else
+ fileBuf[0] = '\0';
+ MakePrompt (toplevel, "File to open:", NewFile, fileBuf);
+}
+
+/* ARGSUSED */
+
+static void
+Quit (Widget entry, XtPointer closure, XtPointer data)
+{
+ entry = entry; /* unused; suppress compiler warning */
+ closure = closure;
+ data = data;
+
+ QuitAction ((Widget)NULL, (XEvent *) 0, (String *) 0, (Cardinal *) 0);
+}
+
+static void
+QuitAction (Widget widget, XEvent *event,
+ String *params, Cardinal *num_params)
+{
+ widget = widget; /* unused; suppress compiler warning */
+ event = event;
+ params = params;
+ num_params = num_params;
+
+ exit (0);
+}
+
+Widget promptShell, promptDialog;
+MakePromptFunc promptfunction;
+
+/* ARGSUSED */
+static
+void CancelAction (Widget widget, XEvent *event,
+ String *params, Cardinal *num_params)
+{
+ widget = widget; /* unused; suppress compiler warning */
+ event = event;
+ params = params;
+ num_params = num_params;
+
+ if (promptShell) {
+ XtSetKeyboardFocus(toplevel, (Widget) None);
+ XtDestroyWidget(promptShell);
+ promptShell = (Widget) 0;
+ }
+}
+
+static
+void AcceptAction (Widget widget, XEvent *event,
+ String *params, Cardinal *num_params)
+{
+ (*promptfunction)(XawDialogGetValueString(promptDialog));
+ CancelAction (widget, event, params, num_params);
+}
+
+static void
+MakePrompt(Widget centerw, const char *prompt,
+ MakePromptFunc func, const char *def)
+{
+ static Arg dialogArgs[] = {
+ {XtNlabel, 0},
+ {XtNvalue, 0},
+ };
+ Arg valueArgs[1];
+ Arg centerArgs[2];
+ Position source_x, source_y;
+ Position dest_x, dest_y;
+ Dimension center_width, center_height;
+ Dimension prompt_width, prompt_height;
+ Widget valueWidget;
+
+ CancelAction ((Widget)NULL, (XEvent *) 0, (String *) 0, (Cardinal *) 0);
+ promptShell = XtCreatePopupShell ("promptShell", transientShellWidgetClass,
+ toplevel, NULL, (Cardinal) 0);
+ dialogArgs[0].value = (XtArgVal)prompt;
+ dialogArgs[1].value = (XtArgVal)def;
+ promptDialog = XtCreateManagedWidget( "promptDialog", dialogWidgetClass,
+ promptShell, dialogArgs, XtNumber (dialogArgs));
+ XawDialogAddButton(promptDialog, "accept", NULL, (XtPointer) 0);
+ XawDialogAddButton(promptDialog, "cancel", NULL, (XtPointer) 0);
+ valueWidget = XtNameToWidget (promptDialog, "value");
+ if (valueWidget) {
+ XtSetArg (valueArgs[0], (String)XtNresizable, TRUE);
+ XtSetValues (valueWidget, valueArgs, 1);
+ /*
+ * as resizable isn't set until just above, the
+ * default value will be displayed incorrectly.
+ * rectify the situation by resetting the values
+ */
+ XtSetValues (promptDialog, dialogArgs, XtNumber (dialogArgs));
+ }
+ XtSetKeyboardFocus (promptDialog, valueWidget);
+ XtSetKeyboardFocus (toplevel, valueWidget);
+ XtRealizeWidget (promptShell);
+ /*
+ * place the widget in the center of the "parent"
+ */
+ XtSetArg (centerArgs[0], XtNwidth, &center_width);
+ XtSetArg (centerArgs[1], XtNheight, &center_height);
+ XtGetValues (centerw, centerArgs, 2);
+ XtSetArg (centerArgs[0], XtNwidth, &prompt_width);
+ XtSetArg (centerArgs[1], XtNheight, &prompt_height);
+ XtGetValues (promptShell, centerArgs, 2);
+ source_x = (center_width - prompt_width) / 2;
+ source_y = (center_height - prompt_height) / 3;
+ XtTranslateCoords (centerw, source_x, source_y, &dest_x, &dest_y);
+ XtSetArg (centerArgs[0], XtNx, dest_x);
+ XtSetArg (centerArgs[1], XtNy, dest_y);
+ XtSetValues (promptShell, centerArgs, 2);
+ XtMapWidget(promptShell);
+ promptfunction = func;
+}
+
+/*
+Local Variables:
+c-indent-level: 4
+c-continued-statement-offset: 4
+c-brace-offset: -4
+c-argdecl-indent: 4
+c-label-offset: -4
+c-tab-always-indent: nil
+End:
+*/
OpenPOWER on IntegriCloud