summaryrefslogtreecommitdiff
path: root/dviware/umddvi
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /dviware/umddvi
Initial commit
Diffstat (limited to 'dviware/umddvi')
-rw-r--r--dviware/umddvi/dev/conf.sh113
-rw-r--r--dviware/umddvi/dev/config3
-rw-r--r--dviware/umddvi/dev/dmd-sp.c568
-rw-r--r--dviware/umddvi/dev/dmd.c920
-rw-r--r--dviware/umddvi/dev/dmdcodes.h39
-rw-r--r--dviware/umddvi/dev/dmdhost.c236
-rw-r--r--dviware/umddvi/dev/dmdslave.c1176
-rw-r--r--dviware/umddvi/dev/dvipr.sh71
-rw-r--r--dviware/umddvi/dev/fontdesc1
-rw-r--r--dviware/umddvi/dev/imagen1-special.c718
-rw-r--r--dviware/umddvi/dev/imagen1.c867
-rw-r--r--dviware/umddvi/dev/interpress.h29
-rw-r--r--dviware/umddvi/dev/ip.c696
-rw-r--r--dviware/umddvi/dev/iptex.sh61
-rw-r--r--dviware/umddvi/dev/makefile143
-rw-r--r--dviware/umddvi/dev/makefile.3b149
-rw-r--r--dviware/umddvi/dev/makefile.local143
-rw-r--r--dviware/umddvi/dev/readme7
-rw-r--r--dviware/umddvi/dev/verser1.c1047
-rw-r--r--dviware/umddvi/dev/verser2.c758
-rw-r--r--dviware/umddvi/doc/box.tex30
-rw-r--r--dviware/umddvi/doc/doc.tex82
-rw-r--r--dviware/umddvi/doc/dow.tex32
-rw-r--r--dviware/umddvi/doc/dvitodev.tex9
-rw-r--r--dviware/umddvi/doc/dvitodvi.tex5
-rw-r--r--dviware/umddvi/doc/figures.tex19
-rw-r--r--dviware/umddvi/doc/install.tex99
-rw-r--r--dviware/umddvi/doc/intro.tex20
-rw-r--r--dviware/umddvi/doc/makefile36
-rw-r--r--dviware/umddvi/doc/section.tex105
-rw-r--r--dviware/umddvi/doc/texx.tex226
-rw-r--r--dviware/umddvi/doc/verb.tex36
-rw-r--r--dviware/umddvi/dvi/dviselect.c974
-rw-r--r--dviware/umddvi/dvi/makefile61
-rw-r--r--dviware/umddvi/dvi/readme2
-rw-r--r--dviware/umddvi/h/arith.h56
-rw-r--r--dviware/umddvi/h/binding.h194
-rw-r--r--dviware/umddvi/h/box.h395
-rw-r--r--dviware/umddvi/h/conv.h82
-rw-r--r--dviware/umddvi/h/dmddev.h19
-rw-r--r--dviware/umddvi/h/dvi.h33
-rw-r--r--dviware/umddvi/h/dviclass.h70
-rw-r--r--dviware/umddvi/h/dvicodes.h72
-rw-r--r--dviware/umddvi/h/error.h28
-rw-r--r--dviware/umddvi/h/fio.h48
-rw-r--r--dviware/umddvi/h/font.h223
-rw-r--r--dviware/umddvi/h/gfclass.h57
-rw-r--r--dviware/umddvi/h/gfcodes.h43
-rw-r--r--dviware/umddvi/h/imagen.h24
-rw-r--r--dviware/umddvi/h/impcodes.h41
-rw-r--r--dviware/umddvi/h/io.h84
-rw-r--r--dviware/umddvi/h/num.h38
-rw-r--r--dviware/umddvi/h/postamble.h45
-rw-r--r--dviware/umddvi/h/readme1
-rw-r--r--dviware/umddvi/h/search.h31
-rw-r--r--dviware/umddvi/h/str.h34
-rw-r--r--dviware/umddvi/h/tfm.h83
-rw-r--r--dviware/umddvi/h/types.h43
-rw-r--r--dviware/umddvi/h/verser.h68
-rw-r--r--dviware/umddvi/installation1
-rw-r--r--dviware/umddvi/lib/bcopy.s29
-rw-r--r--dviware/umddvi/lib/bzero.s27
-rw-r--r--dviware/umddvi/lib/conv.c49
-rw-r--r--dviware/umddvi/lib/dviclass.c96
-rw-r--r--dviware/umddvi/lib/error.c94
-rw-r--r--dviware/umddvi/lib/findpost.c90
-rw-r--r--dviware/umddvi/lib/fio.c41
-rw-r--r--dviware/umddvi/lib/font.c417
-rw-r--r--dviware/umddvi/lib/font_subr.c238
-rw-r--r--dviware/umddvi/lib/getopt.c68
-rw-r--r--dviware/umddvi/lib/gfclass.c80
-rw-r--r--dviware/umddvi/lib/gffont.c920
-rw-r--r--dviware/umddvi/lib/gripes.c177
-rw-r--r--dviware/umddvi/lib/llib-lib65
-rw-r--r--dviware/umddvi/lib/magfactor.c39
-rw-r--r--dviware/umddvi/lib/makefile140
-rw-r--r--dviware/umddvi/lib/makefile.3b132
-rw-r--r--dviware/umddvi/lib/man/all.tex5
-rw-r--r--dviware/umddvi/lib/man/base.tex67
-rw-r--r--dviware/umddvi/lib/man/bstring.tex23
-rw-r--r--dviware/umddvi/lib/man/dviclass.tex169
-rw-r--r--dviware/umddvi/lib/man/magfactor.tex12
-rw-r--r--dviware/umddvi/lib/man/makefile21
-rw-r--r--dviware/umddvi/lib/man/xx7
-rw-r--r--dviware/umddvi/lib/note16
-rw-r--r--dviware/umddvi/lib/pkfont.c767
-rw-r--r--dviware/umddvi/lib/pxlfont.c301
-rw-r--r--dviware/umddvi/lib/readme248
-rw-r--r--dviware/umddvi/lib/rotate.c150
-rw-r--r--dviware/umddvi/lib/scaletfm.c111
-rw-r--r--dviware/umddvi/lib/scanpost.c98
-rw-r--r--dviware/umddvi/lib/search.c178
-rw-r--r--dviware/umddvi/lib/seek.c134
-rw-r--r--dviware/umddvi/lib/split.c219
-rw-r--r--dviware/umddvi/lib/strsave.c25
-rw-r--r--dviware/umddvi/lib/tfm.c119
-rw-r--r--dviware/umddvi/lib/tfmfont.c247
-rw-r--r--dviware/umddvi/libcompat/bcmp.c6
-rw-r--r--dviware/umddvi/libcompat/bcopy.c6
-rw-r--r--dviware/umddvi/libcompat/bzero.c6
-rw-r--r--dviware/umddvi/libcompat/closedir.c18
-rw-r--r--dviware/umddvi/libcompat/dir.h33
-rw-r--r--dviware/umddvi/libcompat/dup2.c7
-rw-r--r--dviware/umddvi/libcompat/errs8
-rw-r--r--dviware/umddvi/libcompat/index.c9
-rw-r--r--dviware/umddvi/libcompat/makefile11
-rw-r--r--dviware/umddvi/libcompat/opendir.c43
-rw-r--r--dviware/umddvi/libcompat/read_me8
-rw-r--r--dviware/umddvi/libcompat/readdir.c59
-rw-r--r--dviware/umddvi/libcompat/regex.c401
-rw-r--r--dviware/umddvi/libcompat/rename.c14
-rw-r--r--dviware/umddvi/libcompat/rindex.c9
-rw-r--r--dviware/umddvi/libcompat/seekdir.c33
-rw-r--r--dviware/umddvi/libcompat/telldir.c17
-rw-r--r--dviware/umddvi/makefile54
-rw-r--r--dviware/umddvi/makefile.3b54
-rw-r--r--dviware/umddvi/man/dvidmd.1186
-rw-r--r--dviware/umddvi/man/dvipr.196
-rw-r--r--dviware/umddvi/man/dviselect.1110
-rw-r--r--dviware/umddvi/man/iptex.1126
-rw-r--r--dviware/umddvi/misc/bcopy.c17
-rw-r--r--dviware/umddvi/misc/bzero.c17
-rw-r--r--dviware/umddvi/misc/check.sh21
-rw-r--r--dviware/umddvi/misc/checkw.150
-rw-r--r--dviware/umddvi/misc/checkw.c342
-rw-r--r--dviware/umddvi/misc/fixfix.c68
-rw-r--r--dviware/umddvi/misc/fontdesc21
-rw-r--r--dviware/umddvi/misc/getdep.sh34
-rw-r--r--dviware/umddvi/misc/makefile44
-rw-r--r--dviware/umddvi/misc/makesubdir.sh30
-rw-r--r--dviware/umddvi/misc/makesunfont.c183
-rw-r--r--dviware/umddvi/misc/rot.alg44
-rw-r--r--dviware/umddvi/misc/showfont.c173
-rw-r--r--dviware/umddvi/misc/showtfmwidth.c165
-rw-r--r--dviware/umddvi/misc/unmakesubdir.sh22
-rw-r--r--dviware/umddvi/previewers/dvistuff.c978
-rw-r--r--dviware/umddvi/previewers/dvistuff.h83
-rw-r--r--dviware/umddvi/previewers/makefile54
-rw-r--r--dviware/umddvi/previewers/texsun.136
-rw-r--r--dviware/umddvi/previewers/texsun.c1576
-rw-r--r--dviware/umddvi/previewers/texx.136
-rw-r--r--dviware/umddvi/previewers/texx.c1382
-rw-r--r--dviware/umddvi/previewers/texx2/00readme.tex62
-rw-r--r--dviware/umddvi/previewers/texx2/buildfonts17
-rw-r--r--dviware/umddvi/previewers/texx2/changelog123
-rw-r--r--dviware/umddvi/previewers/texx2/description64
-rw-r--r--dviware/umddvi/previewers/texx2/dvi-simple.c508
-rw-r--r--dviware/umddvi/previewers/texx2/dvi-simple.h75
-rw-r--r--dviware/umddvi/previewers/texx2/dvipage.c915
-rw-r--r--dviware/umddvi/previewers/texx2/dvipage.h64
-rw-r--r--dviware/umddvi/previewers/texx2/dvipage2.c522
-rw-r--r--dviware/umddvi/previewers/texx2/dvipagep.h106
-rw-r--r--dviware/umddvi/previewers/texx2/fonts9
-rw-r--r--dviware/umddvi/previewers/texx2/fonts.distrib9
-rw-r--r--dviware/umddvi/previewers/texx2/imakefile23
-rw-r--r--dviware/umddvi/previewers/texx2/makefile26
-rw-r--r--dviware/umddvi/previewers/texx2/manifest33
-rw-r--r--dviware/umddvi/previewers/texx2/mftobdf.c600
-rw-r--r--dviware/umddvi/previewers/texx2/mio.h64
-rw-r--r--dviware/umddvi/previewers/texx2/readme57
-rw-r--r--dviware/umddvi/previewers/texx2/texx2-defs.h4
-rw-r--r--dviware/umddvi/previewers/texx2/texx2-error.c224
-rw-r--r--dviware/umddvi/previewers/texx2/texx2-file.c383
-rw-r--r--dviware/umddvi/previewers/texx2/texx2-font.c127
-rw-r--r--dviware/umddvi/previewers/texx2/texx2-font.h8
-rw-r--r--dviware/umddvi/previewers/texx2/texx2-mark.c163
-rw-r--r--dviware/umddvi/previewers/texx2/texx2-mark.h24
-rw-r--r--dviware/umddvi/previewers/texx2/texx2-page.c833
-rw-r--r--dviware/umddvi/previewers/texx2/texx2-page.h63
-rw-r--r--dviware/umddvi/previewers/texx2/texx2-widgets.c174
-rw-r--r--dviware/umddvi/previewers/texx2/texx2-widgets.h40
-rw-r--r--dviware/umddvi/previewers/texx2/texx2.c104
-rw-r--r--dviware/umddvi/previewers/texx2/texx2.h58
-rw-r--r--dviware/umddvi/readme35
-rw-r--r--dviware/umddvi/readme.nyu8
175 files changed, 29128 insertions, 0 deletions
diff --git a/dviware/umddvi/dev/conf.sh b/dviware/umddvi/dev/conf.sh
new file mode 100644
index 0000000000..d10d74e484
--- /dev/null
+++ b/dviware/umddvi/dev/conf.sh
@@ -0,0 +1,113 @@
+#! /bin/sh
+#
+# conf - dynamically configure a makefile
+#
+# uses lines of the form "# conf" ... "# endconf" to figure out what
+# to do.
+#
+# This script uses the file `Makefile' as a base and creates a
+# new `Makefile.local'. It is assumed that the first thing the
+# original makefile does is run make on the local Makefile.
+
+PATH=/bin:/usr/bin:/usr/ucb:"$PATH"; export PATH
+
+# saved configuration file
+conf=Config
+
+# temp files
+t1=/tmp/conf1.$$
+t2=/tmp/conf2.$$
+
+# clean up if interrupted
+trap "rm -f $t1 $t2; exit 1" 1 2 3 15
+
+# Step 1: find the "# conf" lines, gripe if none. (But if $1 is
+# "update", we will just read the saved configuration.)
+case $1 in
+update)
+ if [ ! -f $conf ]; then
+ echo "Your saved configuration file \`$conf' is gone!"
+ echo "(Try \`make conf' again.)"
+ exit 1
+ fi;;
+*)
+ grep "^#[ ][ ]*conf[ ][ ]*" Makefile |
+ sort | uniq >$t1
+ case $? in
+ 0) ;;
+ *) echo "Something is seriously wrong with \`Makefile': there are
+no \`# conf' lines in it. You'll have to fix it by hand (sorry)."
+ rm -f $t1; exit 1;;
+ esac;;
+esac
+
+# Step 2: collect list of entries, and remember for later.
+# If $1 is "update", take the remembered entries; if "all", take all entries.
+case "$1" in
+update)
+ # N.B.: The following depends on the fact that the first two
+ # lines of $conf are comments, the third the configuration.
+ list="`awk 'NR==3 {print}' $conf`";;
+all)
+ list=`awk '{if ($3 != "none") printf ("%s ", $3)}' <$t1`
+ echo "# This file contains the default \`all' configuration.
+# Do not edit it yourself: use \`make conf' instead.
+$list" >$conf;;
+*)
+ list=
+ for i in `awk '{if ($3 != "none") printf ("%s ", $3)}' <$t1`; do
+ echo -n "Do you have a(n) $i? "
+ read answer
+ case "$answer" in
+ y|Y|yes|Yes|YES) list="$list $i";;
+ esac;
+ done
+ echo "# This file contains your configuration.
+# Do not edit it yourself: use \`make conf' instead.
+$list" >$conf;;
+esac
+
+# Step 3: edit the Makefile so that the things that are configured
+# in are on, and those that are not are commented out. Put the result
+# in Makefile.local.
+# This `if' is for 4.3beta machines, where `mv -f' is botched
+if [ -f Makefile.local ]; then
+ mv -f Makefile.local Makefile.l.bak
+fi
+awk "
+BEGIN {
+ want = 0; # 0 => normal
+ # 1 => uncomment, -1 => comment
+ split(\"$list\", list);
+}
+/^#[ ][ ]*conf[ ][ ]*/ { # a conf item
+ want = -1; # assume we do not want it
+ for (i in list)
+ if (list[i] == \$3)
+ want = 1; # we do want it after all
+ print; # in any case, echo it
+ next;
+}
+/^#[ ][ ]*endconf/ { # end of conf item
+ want = 0; # back to normal
+}
+/^# / { # something that was commented out
+ if (want <= 0) { # do not really want it
+ print;
+ next;
+ }
+ for (i = 2; i < NF; i++) # want it: uncomment
+ printf(\"%s \", \$i);
+ print \$NF;
+ next;
+}
+{ # anything else
+ if (want >= 0) # take it as is
+ print;
+ else # comment it out
+ printf(\"# %s\n\", \$0);
+}" <Makefile >$t2
+(trap '' 1 2 3 15; mv -f $t2 Makefile.local)
+
+# Clean up and exit
+rm -f $t1 $t2; exit 0
diff --git a/dviware/umddvi/dev/config b/dviware/umddvi/dev/config
new file mode 100644
index 0000000000..64650ecd58
--- /dev/null
+++ b/dviware/umddvi/dev/config
@@ -0,0 +1,3 @@
+# This file contains the default `all' configuration.
+# Do not edit it yourself: use `make conf' instead.
+imagen versatec
diff --git a/dviware/umddvi/dev/dmd-sp.c b/dviware/umddvi/dev/dmd-sp.c
new file mode 100644
index 0000000000..40bf02424b
--- /dev/null
+++ b/dviware/umddvi/dev/dmd-sp.c
@@ -0,0 +1,568 @@
+/*
+ * Support drawing routines for Chris Torek's DVI->ImPress program.
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+#include "types.h"
+#include "dmdcodes.h"
+
+/* Put a two-byte (word) value to the Imagen */
+#define putword(w) (putchar((w) >> 8), putchar(w))
+
+extern char *malloc();
+
+
+#define TRUE 1
+#define FALSE 0
+
+#define PI 3.14157926536
+#define TWOPI (PI*2.0)
+#define MAXPOINTS 300 /* Most number of points in a path */
+
+
+/* Graphics operations */
+#define WHITE 0
+#define SHADE 3
+#define OR 7
+#define BLACK 15
+
+extern double cos(), sin(), sqrt();
+extern int DPI; /* Resolution of device */
+#define PixPerInX DPI
+#define PixPerInY DPI
+
+extern int UserMag;
+#define fconv(x, f)\
+ (((double)(x)/1000.0) * ((double)(f)) * ((double)UserMag/1000.0))
+#define conv(x, f)\
+ ((int) ((((double)(x)/1000.0) * ((double)(f)) * ((double)UserMag/1000.0)) + 0.5))
+#define xconv(x) conv(x, PixPerInX)
+#define yconv(y) conv(y, PixPerInY)
+
+extern int ImHH; /* Imagen horizontal position */
+extern int ImVV; /* Imagen vertical position */
+extern int hh; /* current horizontal position, in DEVs */
+extern int vv; /* current vertical position, in DEVs */
+
+
+static int xx[MAXPOINTS], yy[MAXPOINTS], pathlen,
+ pensize = 1; /* Size we want Imagen to draw at, default 2 pixels */
+
+#define MAXPENSIZE 20 /* Imagen restriction */
+
+static int
+ family_defined = FALSE, /* Have we chosen family yet? */
+ texture_defined = FALSE,/* Have we done a set_texture yet? */
+ whiten_next = FALSE, /* Should next object be whitened? */
+ blacken_next = FALSE, /* Should next object be blackened? */
+ shade_next = FALSE; /* Should next object be shaded? */
+
+/* Predefined shading (texture) glyph */
+/* First, define size of glyph */
+#define THEIGHT 32 /* bits high */
+#define TWIDTH 4 /* bytes wide */
+/* Next, declare the bit map for the glyph */
+static char stexture[THEIGHT][TWIDTH]={
+ {0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00},
+ {0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00},
+ {0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00},
+ {0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00},
+ {0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00},
+ {0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00},
+ {0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00},
+ {0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00}};
+
+/*
+ * Copy a default texture into the stexture array
+ */
+static void glyph_init()
+{
+ static char btexture[THEIGHT][TWIDTH]={
+ {0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00},
+ {0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00},
+ {0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00},
+ {0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00},
+ {0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00},
+ {0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00},
+ {0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00},
+ {0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00}};
+
+ int i;
+ for (i=0; i<THEIGHT; i++)
+ bcopy(btexture[i],stexture[i],TWIDTH);
+
+}
+
+#define push_location()
+#define pop_location()
+
+#ifdef notdef
+/*
+ * Push the state of the Imagen and set up a new virtual coord system
+ */
+static void push_location()
+{
+ putchar(imP_Push);
+ putchar(imP_SetHVSystem);
+ putchar(0140);
+}
+
+
+/*
+ * Create the pushed virtual page, and pop the state of the printer
+ */
+static void pop_location()
+{
+ putchar(imP_Pop);
+}
+#endif
+
+
+/*
+ * Set the pen size
+ * Called as \special{pn size}
+ * eg: \special{pn 8}
+ * The size is the number of milli-inches for the diameter of the pen.
+ * This routine converts that value to device-dependent pixels, and makes
+ * sure that the resulting value is within legal bounds.
+ */
+static void im_pensize(cp)
+char *cp;
+{
+ int size;
+
+ if (sscanf(cp, " %d ", &size) != 1) return;
+ pensize = yconv(size);
+ if (pensize < 1) pensize = 1;
+ else if (pensize > MAXPENSIZE) pensize = MAXPENSIZE;
+}
+
+
+/*
+ * Make sure the pen size is set. Since we push and pop the state,
+ * this has to be sent for each different object (I think).
+ */
+static void set_pen_size()
+{
+ putchar(DMD_PENSIZE);
+ putchar(pensize);
+}
+
+
+/*
+ * Actually apply the attributes (shade, whiten, or blacken) to the currently
+ * defined path/figure.
+ */
+static void do_attributes()
+{
+ static int family; /* Family of downloaded texture glyph */
+ static int member; /* Member of family */
+ int i,j; /* Loop through glyph array */
+
+ if (shade_next) {
+ shade_next = FALSE;
+#ifdef notdef
+ if (!family_defined) {
+ family_defined = TRUE;
+ family = fnum++;
+ member = -1;
+ }
+ if (!texture_defined) {
+ texture_defined = TRUE;
+ member++;
+ putchar(imP_DefGlyph);
+ putchar((family & 0x7e) >> 1);
+ putchar((family & 0x01) << 7 | (member & 0x7f));
+ /*putword(0); */ /* Advance width */
+ putword(32);
+ putword(TWIDTH*8); /* pixel width (8 x number of bytes) */
+ /*putword(0); */ /* left offset */
+ putword(32);
+ putword(THEIGHT); /* and height of glyph */
+ /*putword(0); */ /* top offset */
+ putword(32);
+ for (i=0; i<THEIGHT; i++)/* Do rows */
+ for (j=0; j<TWIDTH; j++) putchar(stexture[i][j]);
+ }
+ putchar(imP_SetTexture);
+ putchar((family & 0x7e) >> 1);
+ putchar((family & 0x01) << 7 | (member & 0x7f));
+#endif
+ putchar(DMD_FILLPATH);
+ putchar(SHADE);
+ glyph_init(); /* reinitialize the array */
+ }
+ else if (whiten_next) {
+ whiten_next = FALSE;
+ putchar(DMD_FILLPATH);
+ putchar(WHITE);
+ }
+ else if (blacken_next) {
+ blacken_next = FALSE;
+ putchar(DMD_FILLPATH);
+ putchar(BLACK);
+ }
+}
+
+
+/*
+ * Flush the path that we've built up with im_drawto()
+ * Called as \special{fp}
+ */
+static void im_flushpath()
+{
+ register int i;
+
+ push_location();
+ if (pathlen <= 0) return;
+ set_pen_size();
+ putchar(DMD_SEGMENT);
+ putword(pathlen);
+ for (i=1; i<=pathlen; i++) {
+ putword(xx[i]);
+ putword(yy[i]);
+ }
+ pathlen = 0;
+ putchar(DMD_DRAWPATH);
+ putchar(BLACK);
+ do_attributes();
+ pop_location();
+}
+
+
+/* Helper routine for dashed_line() */
+static void connect(x0, y0, x1, y1)
+int x0, y0, x1, y1;
+{
+ set_pen_size();
+ putchar(DMD_SEGMENT);
+ putword(2); /* Path length */
+ putword(x0); putword(y0);/* The path */
+ putword(x1); putword(y1);
+ putchar(DMD_DRAWPATH);
+ putchar(BLACK);
+}
+
+
+/* Another helper. Draw a dot at the indicated point */
+static void dot_at(x, y)
+int x,y;
+{
+ set_pen_size();
+ putchar(DMD_SEGMENT);
+ putword(1); /* Path length */
+ putword(x); putword(y); /* The path */
+ putchar(DMD_DRAWPATH);
+ putchar(BLACK);
+}
+
+
+/*
+ * Draw a dashed or dotted line between the first pair of points in the array
+ * Called as \special{da <inchesperdash>} (dashed line)
+ * or \special{dt <inchesperdot>} (dotted line)
+ * eg: \special{da 0.05}
+ */
+static void dashed_line(cp, dotted)
+char *cp;
+int dotted; /* boolean */
+{
+ int i, numdots, x0, y0, x1, y1;
+ double cx0, cy0, cx1, cy1;
+ double d, spacesize, a, b, dx, dy, pixperdash;
+ float inchesperdash;
+
+ if (sscanf(cp, " %f ", &inchesperdash) != 1) return;
+ if (pathlen <= 1) return;
+ pixperdash = inchesperdash * ((float) PixPerInY);
+ if (pixperdash < 2.)
+ pixperdash = 2.;
+ x0 = xx[1]; x1 = xx[2];
+ y0 = yy[1]; y1 = yy[2];
+ dx = x1 - x0;
+ dy = y1 - y0;
+ push_location();
+ if (dotted) {
+ numdots = sqrt(dx*dx + dy*dy) / pixperdash + 0.5;
+ if (numdots > 0)
+ for (i = 0; i <= numdots; i++) {
+ a = (float) i / (float) numdots;
+ cx0 = ((float) x0) + (a*dx) + 0.5;
+ cy0 = ((float) y0) + (a*dy) + 0.5;
+ dot_at((int) cx0, (int) cy0);
+ }
+ }
+ else {
+ d = sqrt(dx*dx + dy*dy);
+ if (d <= 2 * pixperdash) {
+ connect(x0, y0, x1, y1);
+ pathlen = 0;
+ pop_location();
+ return;
+ }
+ numdots = d / (2 * pixperdash) + 1;
+ spacesize = (d - numdots * pixperdash) / (numdots - 1);
+ for (i=0; i<numdots-1; i++) {
+ a = i * (pixperdash + spacesize) / d;
+ b = a + pixperdash / d;
+ cx0 = ((float) x0) + (a*dx) + 0.5;
+ cy0 = ((float) y0) + (a*dy) + 0.5;
+ cx1 = ((float) x0) + (b*dx) + 0.5;
+ cy1 = ((float) y0) + (b*dy) + 0.5;
+ connect((int) cx0, (int) cy0, (int) cx1, (int) cy1);
+ b += spacesize / d;
+ }
+ cx0 = ((float) x0) + (b*dx) + 0.5;
+ cy0 = ((float) y0) + (b*dy) + 0.5;
+ connect((int) cx0, (int) cy0, x1, y1);
+ }
+ pathlen = 0;
+ pop_location();
+}
+
+
+/*
+ * Virtually draw to a given x,y position on the virtual page.
+ * X and Y are expressed in thousandths of an inch, and this
+ * routine converts them to pixels.
+ *
+ * Called as \special{pa <x> <y>}
+ * eg: \special{pa 0 1200}
+ */
+static void im_drawto(cp)
+char *cp;
+{
+ int x,y;
+
+ if (sscanf(cp, " %d %d ", &x, &y) != 2) return;
+
+ if (++pathlen >= MAXPOINTS)
+ error(1, 0, "Too many points specified");
+ xx[pathlen] = xconv(x) + ImHH;
+ yy[pathlen] = yconv(y) + ImVV;
+}
+
+/* Same routine as above, but it uses the special graphics primitives */
+static void im_arc(cp)
+char *cp;
+{
+ int xc, yc, xrad, yrad;
+ float start_angle, end_angle, fxrad, fyrad;
+ int xp, yp;
+
+ if (sscanf(cp, " %d %d %d %d %f %f ", &xc, &yc, &xrad, &yrad, &start_angle,
+ &end_angle) != 6) return;
+ push_location();
+ set_pen_size();
+ xc = xconv(xc) + ImHH;
+ yc = yconv(yc) + ImVV;
+ {
+ double temp;
+ temp = start_angle;
+ start_angle = end_angle;
+ end_angle = temp;
+ }
+ if (xrad >= yrad-1 && xrad <= yrad+1) { /* Circle or arc */
+ putchar(DMD_CIRCLE);
+ putword(xc); putword(yc);
+ /* starting point */
+ fyrad = fconv(yrad, PixPerInY);
+ xp = fyrad * cos(start_angle) + xc + .5;
+ yp = fyrad * sin(start_angle) + yc + .5;
+ putword(xp); putword(yp);
+ /* finishing point */
+ xp = fyrad * cos(end_angle) + xc + .5;
+ yp = fyrad * sin(end_angle) + yc + .5;
+ putword(xp); putword(yp);
+ }
+ else { /* Ellipse */
+ putchar(DMD_ELLIPSE);
+ putword(xc); putword(yc);
+ /* starting point */
+ fxrad = fconv(xrad, PixPerInX);
+ fyrad = fconv(yrad, PixPerInY);
+ xp = fxrad * cos(start_angle) + xc + .5;
+ yp = fyrad * sin(start_angle) + yc + .5;
+ putword(xp); putword(yp);
+ /* finishing point */
+ xp = fxrad * cos(end_angle) + xc + .5;
+ yp = fyrad * sin(end_angle) + yc + .5;
+ putword(xp); putword(yp);
+ putword(xconv(xrad));
+ putword(yconv(yrad));
+ }
+ putchar(DMD_DRAWPATH);
+ putchar(BLACK);
+ do_attributes();
+ pop_location();
+}
+
+
+/*
+ * Create a spline through the points in the array.
+ * Called like flush path (fp) command, after points
+ * have been defined via pa command(s).
+ *
+ * eg: \special{sp}
+ */
+static void flush_spline()
+{
+ register int i;
+
+ push_location();
+ if (pathlen <= 0) return;
+ set_pen_size();
+ putchar(DMD_SPLINE);
+ putword(pathlen);
+ for (i=1; i<=pathlen; i++) {
+ putword(xx[i]);
+ putword(yy[i]);
+ }
+ pathlen = 0;
+ putchar(DMD_DRAWPATH);
+ putchar(BLACK);
+ do_attributes();
+ pop_location();
+}
+
+
+/*
+ * Whiten the interior of the next figure (path). Command is:
+ * \special{wh}
+ */
+static void im_whiten()
+{
+ whiten_next = TRUE;
+}
+
+
+/*
+ * Blacken the interior of the next figure (path). Command is:
+ * \special{bk}
+ */
+static void im_blacken()
+{
+ blacken_next = TRUE;
+}
+
+
+/*
+ * Shade the interior of the next figure (path) with the predefined
+ * texture. Command is:
+ * \special{sh}
+ */
+static void im_shade()
+{
+ shade_next = TRUE;
+}
+
+
+/*
+ * Define the texture array. Command is:
+ * \special{tx 32bits 32bits ....}
+ */
+static void im_texture(pcount,bitpattern)
+int pcount, bitpattern[32];
+{
+ int i,j,k;
+ unsigned long ul_one;
+
+#ifdef notdef
+#ifdef DEBUG
+ if (sizeof ul_one != TWIDTH)
+ error(1, 0, "pointer/size mismatch");
+#endif
+ j = 0;
+ for (k=0; k < THEIGHT/pcount; k++) {
+ for (i=0; i<pcount; i++) {
+ ul_one = htonl((unsigned long) bitpattern[i]);
+ bcopy((char *) &ul_one, stexture[j++], TWIDTH);
+ }
+ }
+ texture_defined = FALSE;
+#endif
+}
+
+
+/*
+ * This routine takes the string argument for a tx command and
+ * parses out the separate bitpatterns to call im_texture with.
+ * Written by Tinh Tang
+ */
+static void do_texture(t)
+char *t;
+{
+ int bitpattern[32];
+ int pcount = 0;
+
+ while (isspace (*t)) t++;
+ while (*t) {
+ if (sscanf(t, "%x", &bitpattern[pcount++]) != 1) {
+ error(0, 0, "malformed tx command");
+ return;
+ }
+ while (*t && !isspace(*t)) t++;/* Skip to space */
+ while (*t && isspace(*t)) t++;/* Skip to nonspace */
+ }
+ if (pcount != 4 && pcount != 8 && pcount != 16 && pcount != 32) {
+ error(0, 0, "malformed tx command");
+ return;
+ }
+ im_texture(pcount, bitpattern);
+}
+
+
+#define COMLEN 3 /* Length of a tpic command plus one */
+
+DoSpecial(k)
+ i32 k;
+{
+ char *spstring, *cp, command[COMLEN];
+ register int len;
+
+ spstring = malloc((unsigned) (k+1));
+ if (spstring == NULL) error(2, 0, "Out of memory");
+ len = 0;
+ while (k--) spstring[len++] = GetByte(stdin);
+ spstring[len] = '\0';
+ cp = spstring;
+ while (isspace(*cp)) ++cp;
+ len = 0;
+ while (!isspace(*cp) && *cp && len < COMLEN-1) command[len++] = *cp++;
+ command[len] = '\0';
+
+ if (ImHH != hh || ImVV != vv)
+ ImSetPosition(hh, vv);
+
+ if (strcmp(command, "pn") == 0) im_pensize(cp);
+ else if (strcmp(command, "fp") == 0) im_flushpath();
+ else if (strcmp(command, "da") == 0) dashed_line(cp, 0);
+ else if (strcmp(command, "dt") == 0) dashed_line(cp, 1);
+ else if (strcmp(command, "pa") == 0) im_drawto(cp);
+ else if (strcmp(command, "ar") == 0) im_arc(cp);
+ else if (strcmp(command, "sp") == 0) flush_spline();
+ else if (strcmp(command, "sh") == 0) im_shade();
+ else if (strcmp(command, "wh") == 0) im_whiten();
+ else if (strcmp(command, "bk") == 0) im_blacken();
+ else if (strcmp(command, "tx") == 0) im_texture(cp);
+ else error(0, 0, "warning: ignoring \\special");
+
+ free(spstring);
+}
diff --git a/dviware/umddvi/dev/dmd.c b/dviware/umddvi/dev/dmd.c
new file mode 100644
index 0000000000..bc194b989e
--- /dev/null
+++ b/dviware/umddvi/dev/dmd.c
@@ -0,0 +1,920 @@
+#ifndef lint
+static char rcsid[] = "$Header: imagen1.c,v 2.4 86/11/18 02:26:18 chris Exp $";
+#endif
+
+/*
+ * DVI to Imagen driver
+ *
+ * Reads DVI version 2 files and converts to imPRESS commands for spooling to
+ * the Imagen (via ipr).
+ *
+ * TODO:
+ * think about fonts with characters outside [0..127]
+ */
+
+#include <stdio.h>
+#include "types.h"
+#include "conv.h"
+#include "dvi.h"
+#include "dviclass.h"
+#include "dvicodes.h"
+#include "fio.h"
+#include "font.h"
+#include "postamble.h"
+#include "search.h"
+#include "dmddev.h"
+#include "dmdcodes.h"
+
+char *ProgName;
+extern int errno;
+extern char *optarg;
+extern int optind;
+
+/* Globals */
+char serrbuf[BUFSIZ]; /* buffer for stderr */
+
+/*
+ * DVI style arithmetic: when moving horizontally by a DVI distance >=
+ * `space', we are to recompute horizontal position from DVI units;
+ * otherwise, we are to use device resolution units to keep track of
+ * horizontal position. A similar scheme must be used for vertical
+ * positioning.
+ */
+struct fontinfo {
+ struct font *f; /* the font */
+ i32 pspace; /* boundary between `small' & `large' spaces
+ (for positive horizontal motion) */
+ i32 nspace; /* -4 * pspace, for negative motion */
+ i32 vspace; /* 5 * pspace, for vertical motion */
+ int family; /* DMD family number (we get one) */
+#ifdef notyet
+ int UseTime; /* cache info: flush fonts on LRU basis */
+#endif
+};
+
+/*
+ * We use one of the per-glyph user flags to keep track of whether a
+ * glyph has been loaded into the Imagen.
+ */
+#define GF_LOADED GF_USR0
+
+/*
+ * The exception that proves the rule is that hh and fromSP(dvi_h) are not
+ * allowed to get more than MaxDrift units apart.
+ */
+int MaxDrift; /* the maximum allowable difference between
+ hh and fromSP(dvi_h) */
+
+struct fontinfo *CurrentFont; /* the current font */
+
+int ExpectBOP; /* true => BOP ok */
+int ExpectEOP; /* true => EOP ok */
+
+int DPI; /* -d => device resolution (dots/inch) */
+int PFlag = 1; /* -p => no page reversal */
+int LFlag; /* -l => landscape mode (eventually...) */
+int SFlag = 1; /* -s => silent (no page numbers) */
+int Exflag; /* -x => exit emulator */
+int Debug; /* -D => debug flag */
+
+int XOffset;
+int YOffset; /* offsets for margins */
+
+int hh; /* current horizontal position, in DEVs */
+int vv; /* current vertical position, in DEVs */
+
+/*
+ * Similar to dvi_stack, but includes `hh' and `vv', which are usually
+ * but not always the same as fromSP(h) and fromSP(v):
+ */
+struct localstack {
+ int stack_hh;
+ int stack_vv;
+ struct dvi_stack stack_dvi;
+};
+
+struct localstack *dvi_stack; /* base of stack */
+struct localstack *dvi_stackp; /* current place in stack */
+
+int HHMargin; /* horizontal margin (in DEVs) */
+int VVMargin; /* vertical margin (in DEVs) */
+
+long CurrentPagePointer; /* current page we are processing */
+long PrevPagePointer; /* The previous page pointer from the DVI
+ file. This allows us to read the file
+ backwards, which obviates the need for
+ page reversal (reversal is unsupported
+ on the 8/300). */
+
+int Numerator; /* numerator from DVI file */
+int Denominator; /* denominator from DVI file */
+int DVIMag; /* magnification from DVI file */
+int UserMag; /* user-specified magnification */
+
+int ImHH; /* Imagen horizontal position */
+int ImVV; /* Imagen vertical position */
+int ImFamily; /* Imagen current-font number */
+
+char *PrintEngine; /* e.g., canon, ricoh */
+struct search *FontFinder; /* maps from DVI index to internal fontinfo */
+int FontErrors; /* true => error(s) occurred during font
+ definitions from DVI postamble */
+
+struct fontinfo NoFont; /* a fake font to help get things started */
+
+char *getenv(), *malloc();
+
+/* Absolute value */
+#define ABS(n) ((n) >= 0 ? (n) : -(n))
+
+/* Put a two-byte (word) value to the Imagen */
+#define putword(w) (putchar((w) >> 8), putchar(w))
+
+/*
+ * Correct devpos (the actual device position) to be within MaxDrift pixels
+ * of dvipos (the virtual DVI position).
+ */
+#define FIXDRIFT(devpos, dvipos) \
+ if ((devpos) < (dvipos)) \
+ if ((dvipos) - (devpos) <= MaxDrift) \
+ /* void */; \
+ else \
+ (devpos) = (dvipos) - MaxDrift; \
+ else \
+ if ((devpos) - (dvipos) <= MaxDrift) \
+ /* void */; \
+ else \
+ (devpos) = (dvipos) + MaxDrift
+
+SelectFont(n)
+ i32 n;
+{
+ int x = S_LOOKUP;
+
+ if ((CurrentFont = (struct fontinfo *)SSearch(FontFinder, n, &x)) == 0)
+ GripeNoSuchFont(n);
+}
+
+/*
+ * Start a page (process a DVI_BOP).
+ */
+BeginPage()
+{
+ register int *i;
+ static int count[10]; /* the 10 counters */
+ static int beenhere;
+
+ if (!ExpectBOP)
+ GripeUnexpectedOp("BOP");
+ if (beenhere) {
+ if (!SFlag)
+ putc(' ', stderr);
+ } else
+ beenhere++;
+ CurrentPagePointer = ftell(stdin) - 1;
+
+ dvi_stackp = dvi_stack;
+
+ ExpectBOP = 0;
+ ExpectEOP++; /* set the new "expect" state */
+
+ for (i = count; i < &count[sizeof count / sizeof *count]; i++)
+ fGetLong(stdin, *i);
+ fGetLong(stdin, PrevPagePointer);
+
+ if (!SFlag) {
+ (void) fprintf(stderr, "[%d", count[0]);
+ (void) fflush(stderr);
+ }
+ putchar(DMD_PAGE);
+ ImHH = 0;
+ ImVV = 0;
+
+ hh = HHMargin;
+ vv = VVMargin;
+ dvi_h = toSP(hh);
+ dvi_v = toSP(vv);
+ dvi_w = 0;
+ dvi_x = 0;
+ dvi_y = 0;
+ dvi_z = 0;
+}
+
+/*
+ * End a page (process a DVI_EOP)
+ */
+EndPage()
+{
+ int newpage;
+
+ if (!ExpectEOP)
+ GripeUnexpectedOp("EOP");
+
+ if (!SFlag) {
+ putc(']', stderr);
+ (void) fflush(stderr);
+ }
+ ExpectEOP = 0;
+ ExpectBOP++;
+
+again:
+ putchar(DMD_ENDPAGE);
+ newpage = pagecmd();
+ switch (newpage) {
+ case -1:
+ if (PrevPagePointer != -1)
+ fseek(stdin, PrevPagePointer, 0);
+ else
+ goto again;
+ break;
+ case 0:
+ fseek(stdin, CurrentPagePointer, 0);
+ break;
+ case 1:
+ default:
+ break;
+ }
+}
+
+/*
+ * Store the relevant information from the DVI postamble, and set up
+ * various internal things.
+ */
+PostAmbleHeader(p)
+ register struct PostAmbleInfo *p;
+{
+ register int n;
+
+ PrevPagePointer = p->pai_PrevPagePointer;
+ Numerator = p->pai_Numerator;
+ Denominator = p->pai_Denominator;
+ DVIMag = p->pai_DVIMag;
+
+ /*
+ * Set the conversion factor. This must be done before using
+ * any fonts.
+ */
+ SetConversion(DPI, UserMag, Numerator, Denominator, DVIMag);
+
+ n = p->pai_DVIStackSize * sizeof *dvi_stack;
+ dvi_stack = (struct localstack *) malloc((unsigned) n);
+ if ((dvi_stackp = dvi_stack) == NULL)
+ GripeOutOfMemory(n, "DVI stack");
+}
+
+/* Handle one of the font definitions from the DVI postamble. */
+PostAmbleFontDef(p)
+ register struct PostAmbleFont *p;
+{
+ register int i;
+ register struct glyph *g;
+ register struct fontinfo *fi;
+ register struct font *f;
+ register char *s;
+ char *fname;
+ int def = S_CREATE | S_EXCL;
+ char loaded[16];
+ char *rindex(), *strsave();
+
+ fi = (struct fontinfo *) SSearch(FontFinder, p->paf_DVIFontIndex,
+ &def);
+ if (fi == NULL) {
+ if (def & S_COLL)
+ GripeFontAlreadyDefined(p->paf_DVIFontIndex);
+ else
+ error(1, 0, "can't stash font %ld (out of memory?)",
+ p->paf_DVIFontIndex);
+ /*NOTREACHED*/
+ }
+ f = GetFont(p->paf_name, p->paf_DVIMag, p->paf_DVIDesignSize,
+ PrintEngine, &fname);
+ if ((fi->f = f) == NULL) {
+ GripeCannotGetFont(p->paf_name, p->paf_DVIMag,
+ p->paf_DVIDesignSize, PrintEngine, fname);
+ FontErrors++;
+ return;
+ }
+ if (Debug) {
+ (void) fprintf(stderr, "[%s -> %s]\n",
+ Font_TeXName(f), fname);
+ (void) fflush(stderr);
+ }
+ /* match checksums, if not zero */
+ if (p->paf_DVIChecksum && f->f_checksum &&
+ p->paf_DVIChecksum != f->f_checksum)
+ GripeDifferentChecksums(fname, p->paf_DVIChecksum,
+ f->f_checksum);
+
+ fi->pspace = p->paf_DVIMag / 6; /* a three-unit "thin space" */
+ fi->nspace = -4 * fi->pspace;
+ fi->vspace = 5 * fi->pspace;
+ putchar(DMD_MKFONT);
+ if (s = rindex(fname, '/'))
+ s++;
+ else
+ s = fname;
+ while (*s)
+ putchar(*s++);
+ putchar(0);
+ fi->family = inkbd();
+ if (fi->family == 255)
+ error(1, 0, "out of space in remote dmd");
+ s = loaded;
+ for (i = 0; i < sizeof loaded; i++)
+ *s++ = inkbd();
+#define bitset(a, i) (a[i>>3] & (1 << ((~i) & 07)))
+ for (i = 0; i < 128; i++) {
+ if (bitset(loaded, i)) {
+ g = GLYPH(f, i);
+ g->g_pixwidth = fromSP(g->g_tfmwidth);
+ g->g_flags |= GF_LOADED;
+ }
+ }
+}
+
+/* Read the postamble. */
+ReadPostAmble()
+{
+
+ if ((FontFinder = SCreate(sizeof(struct fontinfo))) == 0)
+ error(1, 0, "can't create FontFinder (out of memory?)");
+ ScanPostAmble(stdin, PostAmbleHeader, PostAmbleFontDef);
+ if (FontErrors)
+ GripeMissingFontsPreventOutput(FontErrors);
+}
+
+/* Read the preamble and do a few sanity checks */
+ReadPreAmble()
+{
+ register int n;
+
+ rewind(stdin);
+ if (GetByte(stdin) != Sign8(DVI_PRE))
+ GripeMissingOp("PRE");
+ if (GetByte(stdin) != Sign8(DVI_VERSION))
+ GripeMismatchedValue("version numbers");
+ if (GetLong(stdin) != Numerator)
+ GripeMismatchedValue("numerator");
+ if (GetLong(stdin) != Denominator)
+ GripeMismatchedValue("denominator");
+ if (GetLong(stdin) != DVIMag)
+ GripeMismatchedValue("\\magfactor");
+ n = UnSign8(GetByte(stdin));
+ while (--n >= 0)
+ (void) GetByte(stdin);
+}
+
+main(argc, argv)
+ int argc;
+ register char **argv;
+{
+ register int c;
+ char *inname;
+
+ setbuf(stderr, serrbuf);
+
+ ProgName = *argv;
+ UserMag = 1000;
+ MaxDrift = DefaultMaxDrift;
+ DPI = DefaultDPI;
+ inname = "stdin";
+ PrintEngine = "dmd";
+
+ while ((c = getopt(argc, argv, "d:e:lm:pr:sxDX:Y:")) != EOF) {
+ switch (c) {
+
+ case 'd': /* max drift value */
+ MaxDrift = atoi(optarg);
+ break;
+
+ case 'e': /* engine */
+ PrintEngine = optarg;
+ break;
+
+ case 'l': /* landscape mode */
+ LFlag++;
+ break;
+
+ case 'm': /* magnification */
+ UserMag = atoi(optarg);
+ break;
+
+ case 'p': /* no page reversal */
+ PFlag++;
+ break;
+
+ case 'r': /* resolution */
+ DPI = atoi(optarg);
+ break;
+
+ case 's': /* silent */
+ SFlag++;
+ break;
+
+ case 'x': /* Exit */
+ Exflag++;
+ break;
+
+ case 'D':
+ Debug++;
+ break;
+
+ case 'X': /* x offset, in 1/10 inch increments */
+ XOffset = atoi(optarg);
+ break;
+
+ case 'Y': /* y offset */
+ YOffset = atoi(optarg);
+ break;
+
+ case '?':
+ (void) fprintf(stderr, "\
+Usage: %s [-d drift] [-m mag] [-x] [more options, see manual] [file]\n",
+ ProgName);
+ (void) fflush(stderr);
+ exit(1);
+ }
+ }
+ if (optind < argc)
+ if (freopen(inname = argv[optind], "r", stdin) == NULL)
+ error(1, errno, "can't open %s", inname);
+
+ dmdstart();
+ if (isatty(fileno(stdin))) {
+ putchar(Exflag ? DMD_EXIT : DMD_TERM);
+ exit(0);
+ }
+
+
+/* fontinit((char *) NULL); */
+
+ ReadPostAmble();
+
+ /* Margins -- needs work! */
+ HHMargin = DefaultLeftMargin + XOffset * DPI / 10;
+ VVMargin = DefaultTopMargin + YOffset * DPI / 10;
+
+ ReadPreAmble();
+ ExpectBOP++;
+ if (!PFlag)
+ (void) fseek(stdin, PrevPagePointer, 0);
+
+ /* All set! */
+
+ /*
+ * If the first command in the DVI file involves motion, we will need
+ * to compare it to the current font `space' parameter; so start with
+ * a fake current font of all zeros.
+ */
+ CurrentFont = &NoFont;
+ ReadDVIFile();
+ if (!SFlag) {
+ (void) fprintf(stderr, "\n");
+ (void) fflush(stderr);
+ }
+ putchar(DMD_TERM);
+ exit(0);
+}
+
+/*
+ * Skip a font definition (since we are using those from the postamble)
+ */
+/*ARGSUSED*/
+SkipFontDef(font)
+ i32 font;
+{
+ register int i;
+
+ (void) GetLong(stdin);
+ (void) GetLong(stdin);
+ (void) GetLong(stdin);
+ i = UnSign8(GetByte(stdin)) + UnSign8(GetByte(stdin));
+ while (--i >= 0)
+ (void) GetByte(stdin);
+}
+
+/*
+ * Draw a rule at the current (hh,vv) position. There are two 4 byte
+ * parameters. The first is the height of the rule, and the second is the
+ * width. (hh,vv) is the lower left corner of the rule.
+ */
+SetRule(advance)
+ int advance;
+{
+ register i32 h, w, rw;
+
+ fGetLong(stdin, h);
+ fGetLong(stdin, rw);
+
+ h = ConvRule(h);
+ w = ConvRule(rw);
+
+ /* put the rule out */
+ if (ImHH != hh || ImVV != vv)
+ ImSetPosition(hh, vv);
+ putchar(DMD_RULE);
+ putword(w);
+ putword(h);
+ if (advance) {
+ hh += w;
+ dvi_h += rw;
+ w = fromSP(dvi_h);
+ FIXDRIFT(hh, w);
+ }
+}
+
+/* if anyone ever uses character codes > 127, this driver will need work */
+char chartoobig[] = "Warning: character code %d too big for Imagen!";
+
+/*
+ * This rather large routine reads the DVI file and calls on other routines
+ * to do anything moderately difficult (except put characters: there is
+ * some ugly code with `goto's which makes things faster).
+ */
+
+ReadDVIFile()
+{
+ register int c;
+ register struct glyph *g;
+ register struct font *f;
+ register i32 p;
+ int advance;
+
+ ImFamily = -1; /* force DMD_SETFONT command */
+
+ /*
+ * Only way out is via "return" statement. I had a `for (;;)' here,
+ * but everything crawled off the right.
+ */
+loop:
+ /*
+ * Get the DVI byte, and switch on its parameter length and type.
+ * Note that getchar() returns unsigned values.
+ */
+ c = getchar();
+
+ /*
+ * Handling characters (the most common case) early makes the
+ * program run a bit faster.
+ */
+ if (DVI_IsChar(c)) {
+ advance = 1;
+do_char:
+ f = CurrentFont->f;
+ g = GLYPH(f, c);
+ if (!GVALID(g)) {
+ error(0, 0, "there is no character %d in %s",
+ c, f->f_path);
+ goto loop;
+ }
+ if ((g->g_flags & GF_LOADED) == 0)
+ DownLoadGlyph(c, g);
+ if (HASRASTER(g)) { /* workaround for Imagen bug */
+
+ /* BEGIN INLINE EXPANSION OF ImSetPosition */
+ register int delta;
+
+ if (ImHH != hh) {
+ delta = hh - ImHH;
+ if (delta == 1)
+ putchar(DMD_FORW);
+ else if (delta == -1)
+ putchar(DMD_BACK);
+ else if (-128 <= delta && delta <= 127) {
+ putchar(DMD_HREL);
+ putchar(delta);
+ } else {
+ putchar(DMD_HABS);
+ putword(hh);
+ }
+ ImHH = hh;
+ }
+ if (ImVV != vv) {
+ delta = vv - ImVV;
+ if (-128 <= delta && delta <= 127) {
+ putchar(DMD_VREL);
+ putchar(delta);
+ } else {
+ putchar(DMD_VABS);
+ putword(vv);
+ }
+ ImVV = vv;
+ }
+ /* END INLINE EXPANSION OF ImSetPosition */
+ if (ImFamily != CurrentFont->family) {
+ putchar(DMD_SETFONT);
+ putchar(CurrentFont->family);
+ ImFamily = CurrentFont->family;
+ }
+ putchar(c);
+ ImHH += g->g_pixwidth;
+ }
+ if (advance) {
+ hh += g->g_pixwidth;
+ dvi_h += g->g_tfmwidth;
+ p = fromSP(dvi_h);
+ FIXDRIFT(hh, p);
+ }
+ goto loop;
+ }
+
+ switch (DVI_OpLen(c)) {
+
+ case DPL_NONE:
+ break;
+
+ case DPL_SGN1:
+ p = getchar();
+ p = Sign8(p);
+ break;
+
+ case DPL_SGN2:
+ fGetWord(stdin, p);
+ p = Sign16(p);
+ break;
+
+ case DPL_SGN3:
+ fGet3Byte(stdin, p);
+ p = Sign24(p);
+ break;
+
+ case DPL_SGN4:
+ fGetLong(stdin, p);
+ break;
+
+ case DPL_UNS1:
+ p = UnSign8(getchar());
+ break;
+
+ case DPL_UNS2:
+ fGetWord(stdin, p);
+ p = UnSign16(p);
+ break;
+
+ case DPL_UNS3:
+ fGet3Byte(stdin, p);
+ p = UnSign24(p);
+ break;
+
+ default:
+ panic("DVI_OpLen(%d) = %d", c, DVI_OpLen(c));
+ /* NOTREACHED */
+ }
+
+ switch (DVI_DT(c)) {
+
+ case DT_SET:
+ advance = 1;
+ c = p;
+ if (c > 127)
+ error(0, 0, chartoobig, c);
+ goto do_char;
+
+ case DT_PUT:
+ advance = 0;
+ c = p;
+ if (c > 127)
+ error(0, 0, chartoobig, c);
+ goto do_char;
+
+ case DT_SETRULE:
+ SetRule(1);
+ break;
+
+ case DT_PUTRULE:
+ SetRule(0);
+ break;
+
+ case DT_NOP:
+ break;
+
+ case DT_BOP:
+ BeginPage();
+ break;
+
+ case DT_EOP:
+ EndPage();
+ break;
+
+ case DT_PUSH:
+ dvi_stackp->stack_hh = hh;
+ dvi_stackp->stack_vv = vv;
+ dvi_stackp->stack_dvi = dvi_current;
+ dvi_stackp++;
+ break;
+
+ case DT_POP:
+ dvi_stackp--;
+ hh = dvi_stackp->stack_hh;
+ vv = dvi_stackp->stack_vv;
+ dvi_current = dvi_stackp->stack_dvi;
+ break;
+
+ case DT_W0: /* there should be a way to make these pretty */
+ p = dvi_w;
+ goto move_right;
+
+ case DT_W:
+ dvi_w = p;
+ goto move_right;
+
+ case DT_X0:
+ p = dvi_x;
+ goto move_right;
+
+ case DT_X:
+ dvi_x = p;
+ goto move_right;
+
+ case DT_RIGHT:
+move_right:
+ dvi_h += p;
+ /*
+ * DVItype tells us that we must round motions in this way:
+ * `When the horizontal motion is small, like a kern, hh
+ * changes by rounding the kern; but when the motion is
+ * large, hh changes by rounding the true position so that
+ * accumulated rounding errors disappear.'
+ */
+ if (p >= CurrentFont->pspace || p <= CurrentFont->nspace)
+ hh = fromSP(dvi_h);
+ else {
+ hh += fromSP(p);
+ p = fromSP(dvi_h);
+ FIXDRIFT(hh, p);
+ }
+ break;
+
+ case DT_Y0:
+ p = dvi_y;
+ goto move_down;
+
+ case DT_Y:
+ dvi_y = p;
+ goto move_down;
+
+ case DT_Z0:
+ p = dvi_z;
+ goto move_down;
+
+ case DT_Z:
+ dvi_z = p;
+ goto move_down;
+
+ case DT_DOWN:
+move_down:
+ dvi_v += p;
+ /*
+ * `Vertical motion is done similarly, but with the threshold
+ * between ``small'' and ``large'' increased by a factor of
+ * 5. The idea is to make fractions like $1\over2$ round
+ * consistently, but to absorb accumulated rounding errors in
+ * the baseline-skip moves.'
+ */
+ if (ABS(p) >= CurrentFont->vspace)
+ vv = fromSP(dvi_v);
+ else {
+ vv += fromSP(p);
+ p = fromSP(dvi_v);
+ FIXDRIFT(vv, p);
+ }
+ break;
+
+ case DT_FNTNUM:
+ SelectFont((i32) (c - DVI_FNTNUM0));
+ break;
+
+ case DT_FNT:
+ SelectFont(p);
+ break;
+
+ case DT_XXX:
+ DoSpecial(p);
+ break;
+
+ case DT_FNTDEF:
+ SkipFontDef(p);
+ break;
+
+ case DT_PRE:
+ GripeUnexpectedOp("PRE");
+ /* NOTREACHED */
+
+ case DT_POST:
+ if (PFlag)
+ return;
+ GripeUnexpectedOp("POST");
+ /* NOTREACHED */
+
+ case DT_POSTPOST:
+ GripeUnexpectedOp("POSTPOST");
+ /* NOTREACHED */
+
+ case DT_UNDEF:
+ GripeUndefinedOp(c);
+ /* NOTREACHED */
+
+ default:
+ panic("DVI_DT(%d) = %d", c, DVI_DT(c));
+ /* NOTREACHED */
+ }
+ goto loop;
+}
+
+/*
+ * Download the character c/g in the current font.
+ */
+DownLoadGlyph(c, g)
+ int c;
+ register struct glyph *g;
+{
+ register char *p;
+ register int i, j, w;
+
+ g->g_pixwidth = fromSP(g->g_tfmwidth);
+ g->g_flags |= GF_LOADED;
+ if (!HASRASTER(g)) /* never load dull glyphs */
+ return;
+
+ if (!LFlag) {
+ w = 0;
+ p = RASTER(g, CurrentFont->f, ROT_NORM);
+ } else {
+ w = 1 << 14;
+ p = RASTER(g, CurrentFont->f, ROT_RIGHT);
+ }
+
+ w |= (CurrentFont->family << 7) | c;
+
+ /* Define the character */
+ if (-128 <= g->g_pixwidth && g->g_pixwidth <= 127 &&
+ g->g_width <= 255 && g->g_height <= 255 &&
+ -128 <= g->g_xorigin && g->g_xorigin <= 127 &&
+ -128 <= g->g_yorigin && g->g_yorigin <= 127) {
+ putchar(DMD_SGLYPH); /* a.k.a. SGLY */
+ putword(w); /* rotation, family, member */
+ putchar(g->g_pixwidth); /* advance */
+ putchar(g->g_width); /* width */
+ putchar(g->g_xorigin); /* left offset */
+ putchar(g->g_height); /* height */
+ putchar(g->g_yorigin); /* top-offset */
+ } else {
+ putchar(DMD_BGLYPH); /* a.k.a. BGLY */
+ putword(w); /* rotation, family, member */
+ putchar(g->g_pixwidth); /* advance */
+ putchar(g->g_width); /* width */
+ putchar(g->g_xorigin); /* left offset */
+ putchar(g->g_height); /* height */
+ putchar(g->g_yorigin); /* top-offset */
+ }
+
+ /*
+ * Now put out the bitmap.
+ */
+ w = (g->g_width + 7) >> 3;
+ for (i = g->g_height; --i >= 0;)
+ for (j = w; --j >= 0;)
+ (void) putchar(*p++);
+
+ if (g->g_raster) { /* XXX */
+ free(g->g_raster);
+ g->g_raster = NULL;
+ }
+
+}
+
+/*
+ * Set the Imagen's h & v positions. It is currently at ImHH, ImVV.
+ */
+ImSetPosition(h, v)
+ register int h, v;
+{
+
+ register int delta;
+ if (ImHH != h) {
+ delta = h - ImHH;
+ if (delta == 1)
+ putchar(DMD_FORW);
+ else if (delta == -1)
+ putchar(DMD_BACK);
+ else if (-128 <= delta && delta <= 127) {
+ putchar(DMD_HREL);
+ putchar(delta);
+ } else {
+ putchar(DMD_HABS);
+ putword(h);
+ }
+ ImHH = h;
+ }
+ if (ImVV != v) {
+ delta = v - ImVV;
+ if (-128 <= delta && delta <= 127) {
+ putchar(DMD_VREL);
+ putchar(delta);
+ } else {
+ putchar(DMD_VABS);
+ putword(v);
+ }
+ ImVV = v;
+ }
+}
diff --git a/dviware/umddvi/dev/dmdcodes.h b/dviware/umddvi/dev/dmdcodes.h
new file mode 100644
index 0000000000..78b134e37a
--- /dev/null
+++ b/dviware/umddvi/dev/dmdcodes.h
@@ -0,0 +1,39 @@
+/* DMD command codes */
+
+#define DMD_FORW 131 /* one pixel forward */
+#define DMD_BACK 132 /* one pixel backward */
+#define DMD_HABS 135 /* + short, set absolute H pos */
+#define DMD_HREL 136 /* + schar, set relative H pos */
+#define DMD_VABS 137 /* + short, set absolute V pos */
+#define DMD_VREL 138 /* + schar, set relative V pos */
+
+#define DMD_EXIT 140
+#define DMD_ASCII 141
+#define DMD_TERM 142
+#define DMD_CLEAR 143
+#define DMD_TYPESET 144
+#define DMD_ACK 145
+#define DMD_NAK 146
+#define DMD_WIND 147
+#define DMD_NEXT 149
+
+#define DMD_RULE 193 /* print a rule */
+
+#define DMD_SGLYPH 198 /* define a small glyph */
+#define DMD_BGLYPH 199 /* define a big glyph */
+
+#define DMD_MKFONT 205 /* create a downloaded font */
+#define DMD_SETFONT 206 /* specify font number */
+
+#define DMD_PAGE 218 /* start a new page */
+#define DMD_ENDPAGE 219 /* request next action */
+
+#define DMD_SEGMENT 221 /* define path with lines */
+#define DMD_SPLINE 222 /* define path with spline */
+#define DMD_CIRCLE 223 /* define circular path */
+#define DMD_ELLIPSE 224 /* define elliptical path */
+#define DMD_DRAWPATH 225 /* draw a path */
+#define DMD_FILLPATH 226 /* fill a path */
+#define DMD_PENSIZE 227 /* set pen size */
+
+#define imP_ForceDel 240 /* force glyph deletion */
diff --git a/dviware/umddvi/dev/dmdhost.c b/dviware/umddvi/dev/dmdhost.c
new file mode 100644
index 0000000000..344b5d02b1
--- /dev/null
+++ b/dviware/umddvi/dev/dmdhost.c
@@ -0,0 +1,236 @@
+
+#include <stdio.h>
+#ifdef sys5
+#include <sys/termio.h>
+#else
+#include <sgtty.h>
+#endif
+#include <signal.h>
+#include <sys/jioctl.h>
+#include <setjmp.h>
+#include "dmdcodes.h"
+
+static jmp_buf jenv;
+int jerq;
+static char prooftty[] = "/dev/tty";
+#ifdef sys5
+static struct termio sttybuf, sttysave;
+#else
+static struct sgttyb modes, savetty;
+#endif
+static int termraw;
+
+void
+sighup()
+{
+ putchar(DMD_EXIT);
+ exit(1);
+}
+
+dmdstart()
+{
+ char command[256];
+ int ismpx;
+
+ signal(SIGHUP, sighup);
+
+ if ((jerq = open(prooftty, 2)) < 0) {
+ error(1, 0, prooftty);
+ exit(1);
+ }
+ if (ioctl(jerq, JMPX, 0) == -1)
+ ismpx = 0;
+ else
+ ismpx = 1;
+
+#ifdef sys5
+ ioctl(jerq, TCGETA, &sttysave);
+ sttybuf.c_iflag = IGNBRK;
+ sttybuf.c_cflag = (sttysave.c_cflag & (CBAUD | CLOCAL)) | CS8 | CREAD;
+ sttybuf.c_cc[VMIN] = 1;
+ (void)ioctl(jerq, TCSETAW, &sttybuf);
+#else
+ ioctl(jerq, TIOCGETP, &modes);
+ savetty = modes;
+ modes.sg_flags |= RAW;
+ modes.sg_flags &= ~ECHO;
+ ioctl(jerq, TIOCSETP, &modes);
+#endif
+ termraw++;
+#define Proofm "/usr/local/lib/dvidmd.m"
+#define Proofj "/usr/local/lib/dvidmd.j"
+#define X32ld "32ld"
+ if (!isatty(1) || !verify()) {
+ sprintf(command, "%s %s < %s > %s", X32ld,
+ ismpx ? Proofm : Proofj, prooftty, prooftty);
+ if (system(command) != 0)
+ error(1, 0, "%s failed", X32ld);
+ if (!verify())
+ error(1, 0, "could not sync display");
+ }
+}
+
+void
+alarmcatch(sig)
+{
+ longjmp(jenv, 1);
+}
+
+verify()
+{
+ char c;
+
+ signal(SIGALRM, alarmcatch);
+ c = DMD_TYPESET;
+ write(jerq, &c, 1);
+ if (setjmp(jenv))
+ return(0);
+ alarm(2);
+ read(jerq, &c, 1);
+ alarm(0);
+ return (c == DMD_ACK);
+}
+
+pagecmd()
+{
+ int i, c;
+
+ switch (c = inkbd()) {
+ case DMD_EXIT:
+ exit(0);
+ case DMD_PAGE:
+ i = inkbd();
+ if (i > 127)
+ i -= 256;
+ return(i);
+ default:
+ error(1, 0, "bad pagecmd response 0%o", c);
+ }
+ /*NOTREACHED*/
+}
+
+inkbd()
+{
+ char c;
+ register i;
+
+ fflush(stdout);
+ if (read(jerq, &c, 1) != 1)
+ c = 4; /* ^D, looks like EOF */
+ i = c & 0377;
+ return(i);
+}
+
+exit(n)
+{
+ fflush(stdout);
+ fflush(stderr);
+ if (termraw) {
+#ifdef sys5
+ (void)ioctl(jerq, TCSETAW, &sttysave);
+#else
+ ioctl(jerq, TIOCSETP, &savetty);
+#endif
+ }
+ _exit(n);
+}
+
+#ifndef lint
+static char rcsid[] = "$Header: error.c,v 2.5 86/11/08 17:09:39 chris Exp $";
+#endif
+
+/*
+ * Print an error message with an optional system error number, and
+ * optionally quit.
+ *
+ * THIS CODE IS SYSTEM DEPENDENT UNLESS varargs WORKS WITH vprintf
+ * OR _doprnt. It should work properly under System V using vprintf.
+ * (If you have vprintf, define HAVE_VPRINTF.)
+ */
+
+#include <varargs.h>
+
+#ifdef lint
+
+/* VARARGS3 ARGSUSED */
+error(quit, e, fmt) int quit, e; char *fmt; {;}
+
+/* VARARGS1 ARGSUSED */
+panic(fmt) char *fmt; { exit(1); /* NOTREACHED */ }
+
+#else lint
+
+extern char *ProgName;
+extern int errno;
+extern char *sys_errlist[];
+extern int sys_nerr;
+
+/*
+ * We can be civlised by calling legitimate routines.
+ */
+error(va_alist)
+ va_dcl
+{
+ va_list l;
+ int quit, e;
+ char *fmt;
+
+ if (termraw)
+ putchar(DMD_ASCII);
+ (void) fflush(stdout); /* sync error messages */
+ (void) fprintf(stderr, "%s: ", ProgName);
+ va_start(l);
+ /* pick up the constant arguments: quit, errno, printf format */
+ quit = va_arg(l, int);
+ e = va_arg(l, int);
+ if (e < 0)
+ e = errno;
+ fmt = va_arg(l, char *);
+#if defined(sys5) || defined(HAVE_VPRINTF)
+ (void) vfprintf(stderr, fmt, l);
+#else
+ _doprnt(fmt, l, stderr);
+#endif
+ va_end(l);
+ if (e) {
+ if (e < sys_nerr)
+ (void) fprintf(stderr, ": %s", sys_errlist[e]);
+ else
+ (void) fprintf(stderr, ": Unknown error code %d", e);
+ }
+ (void) putc('\n', stderr);
+ (void) fflush(stderr); /* just in case */
+ if (termraw)
+ putchar(0);
+ if (quit) {
+ if (termraw)
+ putchar(DMD_TERM);
+ exit(quit);
+ }
+}
+
+panic(va_alist)
+ va_dcl
+{
+ va_list l;
+ char *fmt;
+
+ if (termraw)
+ putchar(DMD_TERM);
+ (void) fflush(stdout);
+ (void) fprintf(stderr, "%s: panic: ", ProgName);
+ va_start(l);
+ /* pick up the constant argument: printf format */
+ fmt = va_arg(l, char *);
+#if defined(sys5) || defined(HAVE_VPRINTF)
+ (void) vfprintf(stderr, fmt, l);
+#else
+ _doprnt(fmt, l, stderr);
+#endif
+ va_end(l);
+ (void) putc('\n', stderr);
+ (void) fflush(stderr);
+ abort();
+}
+
+#endif /* lint */
diff --git a/dviware/umddvi/dev/dmdslave.c b/dviware/umddvi/dev/dmdslave.c
new file mode 100644
index 0000000000..ac1988379c
--- /dev/null
+++ b/dviware/umddvi/dev/dmdslave.c
@@ -0,0 +1,1176 @@
+/*
+ * Typesetter/Terminal Emulator for the DMD 5620
+ *
+ * Lou Salkind
+ * New York University
+ * Thu Apr 2 01:21:09 EST 1987
+ *
+ * This program was inspired by the DMD proof program
+ * and the Impress typesetting language. It is used by
+ * the TeX DVIDMD driver.
+ */
+
+#include <jerq.h>
+#include "layer.h"
+#include "font.h"
+#include "dmdcodes.h"
+
+#define MAXFAMILY 128 /* number of different fonts */
+#define MAXFONTNAME 16 /* maximum font string */
+#define PAGECHAR 8192 /* buffered characters to save */
+#define MAXPAGE 127
+
+#define SCROLLSIZE 20 /* scrolling border */
+#define PAGEPIXELS 1010 /* XXX - length of page (should be an argument) */
+#define NEWLINESIZE 16
+#define CURSOR '\01' /* cursor char in font */
+#define LINEBUFSIZE 100
+
+#define MOVED 256
+
+#ifdef PAGECHAR
+/* treatment of input characters */
+#define CHAR_DISCARD 0
+#define CHAR_STORE 1
+#define CHAR_FETCH 2
+
+int savechars;
+char savebuf[PAGECHAR];
+char *saveptr;
+#endif
+
+#define RoundUp(a, b) (((a) + (b) - 1) & ~((b) - 1))
+
+#ifdef MPX
+#undef cursinhibit
+#undef cursallow
+#define cursinhibit() {}
+#define cursallow() {}
+#endif
+
+static Texture16 prompt = {
+ 0x0000, 0x0000, 0x0000, 0x322E, 0x4B69, 0x4369, 0x42A9, 0x42A9,
+ 0x42A9, 0x4229, 0x4229, 0x4229, 0x322E, 0x0000, 0x0000, 0x0000
+};
+
+Point fudge = {5, 3}; /* DAG - offsets from corners */
+
+int dotypeset; /* 1==typesetter, 0==terminal */
+int cursvis; /* is cursor visible */
+Point org; /* current origin */
+Point typeorg; /* current typesetter origin */
+Point curpt; /* current typesetter point relative to origin */
+Point curpos; /* current ascii terminal position */
+
+struct line {
+ char buf[LINEBUFSIZE];
+ char *bufp;
+};
+
+struct line line;
+
+struct glyph {
+ Bitmap g_bitmap;
+ short g_pxwidth;
+ short g_xoffset;
+ short g_yoffset;
+};
+
+struct fontinfo {
+ char f_name[MAXFONTNAME];
+ struct glyph f_glyph[128];
+};
+
+struct fontinfo *ftbl[MAXFAMILY];
+struct fontinfo *curfont;
+Point inpoint();
+
+
+main()
+{
+ register int c;
+
+ resetmode(DMD_TERM);
+#ifdef MPX
+ P->state |= RESHAPED; /* set window parameters */
+#else
+ Drect = inset(Drect, 2);
+#endif /* MPX */
+ windowupdate();
+ for(;;) {
+ c = inchar();
+ if (dotypeset)
+ typeset(c);
+ else {
+ if(cursvis)
+ term(CURSOR, 0); /* undraw cursor */
+ term(c, 1);
+ while (own()&RCV)
+ term(inchar(), 1);
+ term(CURSOR, 0); /* draw at new spot */
+ cursvis = 1;
+ }
+ }
+}
+
+/* terminal emulation */
+term(c, advance)
+ register int c;
+{
+ register struct line *linep = &line;
+ register Point *pp = &curpos;
+ register Fontchar *fp;
+ Rectangle r;
+ Point p;
+
+ if (c & 0x80) {
+ if (c == DMD_TYPESET) {
+ resetmode(DMD_TYPESET);
+ send(DMD_ACK);
+ return;
+ }
+ c &= 0x7F;
+ }
+ switch(c) {
+ default:
+ fp = defont.info+c;
+ if (fp->width+pp->x >= Drect.corner.x)
+ newline(linep, pp);
+ p = *pp;
+ r.origin.x = fp->x;
+ r.corner.x = (fp+1)->x;
+ if (advance) {
+ r.origin.y = 0;
+ r.corner.y = defont.height;
+ bitblt(defont.bits, r, &display, p, F_STORE);
+ pp->x += fp->width;
+ if (linep->bufp < linep->buf+LINEBUFSIZE)
+ *linep->bufp++ = c;
+ } else {
+ r.origin.y = fp->top;
+ r.corner.y = fp->bottom;
+ p.y += fp->top;
+ bitblt(defont.bits, r, &display, p, F_XOR);
+ }
+ break;
+ case '\n':
+ newline(linep, pp);
+ break;
+ case '\7':
+ ringbell(); /* DAG -- should work? */
+ case 0:
+ break;
+ case '\r':
+ pp->x=Drect.origin.x+fudge.x; /* DAG -- changed 5 to fudge.x */
+ linep->bufp = linep->buf;
+ break;
+ case '\013': /* ^K: reverse linefeed */
+ if(pp->y>Drect.origin.y+fudge.y+defont.height)
+ pp->y-=NEWLINESIZE;
+ break;
+ case '\b':
+ backspace(linep, pp);
+ break;
+ case '\014':
+ formfeed(linep, pp);
+ break;
+ case '\t':
+ pp->x=nexttab(pp->x);
+ if(pp->x>=Drect.corner.x)
+ newline(linep, pp);
+ if(linep->bufp<linep->buf+LINEBUFSIZE)
+ *linep->bufp++=c;
+ break;
+ }
+}
+
+/*int eightspaces=8*dispatch[' '].c_wid;*/
+int eightspaces=72;
+
+nexttab(x)
+{
+ register int xx = x-Drect.origin.x-fudge.x;
+
+ return(xx-(xx%eightspaces)+eightspaces+Drect.origin.x+fudge.x);
+}
+
+backspace(linep, pp)
+ register struct line *linep;
+ register Point *pp;
+{
+ register char *p;
+ register int x = Drect.origin.x+fudge.x;
+
+ if (linep->bufp>linep->buf) {
+ for (p=linep->buf; p<linep->bufp-1; p++)
+ if (*p=='\t')
+ x = nexttab(x);
+ else
+ x += defont.info[*p].width;
+ pp->x = x;
+ --linep->bufp;
+ if (*p!='\t')
+ term(*p, 0);
+ }
+}
+
+newline(linep, pp)
+ struct line *linep;
+ register Point *pp;
+{
+ register cursoff=0;
+
+ if (pp->y+2*NEWLINESIZE > Drect.corner.y-fudge.y+1) {
+ /* weirdness is because the tail of the arrow may be anywhere */
+ if (rectXrect(Rect(mouse.xy.x-16, mouse.xy.y-16, mouse.xy.x+16,
+ mouse.xy.y+16), Drect)){
+ cursinhibit();
+ cursoff++;
+ }
+ lscroll();
+ if(cursoff)
+ cursallow();
+ } else
+ pp->y += NEWLINESIZE;
+ pp->x = Drect.origin.x+fudge.x;
+ linep->bufp = linep->buf;
+}
+
+lscroll()
+{
+ Rectangle r;
+
+ r = Drect;
+ r.origin.y += NEWLINESIZE;
+ bitblt(&display, r, &display, Pt(r.origin.x, r.origin.y-NEWLINESIZE), F_STORE);
+ stipple(Rpt(Pt(Drect.origin.x, Drect.corner.y-NEWLINESIZE), Drect.corner));
+}
+
+formfeed(linep, pp)
+ struct line *linep;
+ Point *pp;
+{
+ cursinhibit();
+ stipple(Drect);
+ cursallow();
+ *pp=add(Drect.origin, fudge);
+ linep->bufp=linep->buf;
+}
+
+stipple(r)
+ Rectangle r;
+{
+ cursinhibit();
+ rectf(&display, r, F_CLR);
+ cursallow();
+}
+
+/* routines to handle command input */
+
+inchar()
+{
+ register int c;
+
+#ifdef PAGECHAR
+ if (savechars == CHAR_FETCH)
+ return(*saveptr++ & 0377);
+#endif
+#ifdef MPX
+ wait(RCV);
+ if (P->state&(RESHAPED|MOVED))
+ windowupdate();
+ c = rcvchar();
+#else
+ for ( ; ; ) {
+ wait(RCV|KBD);
+ if (own() & RCV) {
+ c = rcvchar();
+ break;
+ }
+ if (!dotypeset)
+ send(kbdchar());
+ }
+#endif MPX
+#ifdef PAGECHAR
+ if (savechars == CHAR_STORE) {
+ if (saveptr < &savebuf[PAGECHAR])
+ *saveptr++ = c;
+ else
+ savechars = CHAR_DISCARD;
+ }
+#endif
+ return(c&0377);
+}
+
+insignchar()
+{
+ register int c;
+
+ c = inchar();
+ if (c > 127)
+ c -= 256;
+ return(c);
+}
+
+inshort()
+{
+ register short i;
+
+ i = inchar() << 8;
+ i |= inchar();
+ return(i);
+}
+
+Point
+inpoint()
+{
+ Point p;
+
+ p.x = inshort() + typeorg.x;
+ p.y = inshort() + typeorg.y;
+ return(p);
+}
+
+send(c)
+{
+ char cc = c;
+
+ sendnchars(1, &cc);
+}
+
+/* typesetter emulation */
+typeset(c)
+ register int c;
+{
+ register struct glyph *g;
+ register Bitmap *b;
+ Point pprime;
+ int old;
+
+ if (c <= 127) {
+ if (curfont == 0)
+ return;
+ g = &curfont->f_glyph[c];
+ b = &g->g_bitmap;
+ if (b->base == 0) {
+ curpt.x += g->g_pxwidth;
+ return;
+ }
+ pprime = add(curpt, typeorg);
+ pprime.x -= g->g_xoffset;
+ pprime.y -= g->g_yoffset;
+ bitblt(b, b->rect, &display, pprime, F_OR);
+ curpt.x += g->g_pxwidth;
+ return;
+ }
+
+ switch (c) {
+ case DMD_EXIT:
+ bye();
+ break;
+ case DMD_TERM:
+#ifdef PAGECHAR
+ savechars = CHAR_DISCARD;
+#endif
+ resetmode(DMD_TERM);
+ break;
+ case DMD_CLEAR:
+ stipple(Drect);
+ curpos = add(org, fudge);
+ break;
+ case DMD_TYPESET:
+ send(DMD_ACK);
+ break;
+ case DMD_ASCII:
+#ifdef PAGECHAR
+ if (savechars == CHAR_STORE)
+ saveptr--;
+ old = savechars;
+ savechars = CHAR_DISCARD;
+#endif
+ while (c = inchar())
+ term(c, 1);
+#ifdef PAGECHAR
+ savechars = old;
+#endif
+ break;
+ case DMD_RULE: {
+ short w, h;
+ Rectangle r;
+
+ w = inshort();
+ h = inshort();
+ pprime = add(curpt, typeorg);
+ pprime.y++;
+ r.origin = pprime;
+ r.origin.y = pprime.y - h;
+ r.corner = pprime;
+ r.corner.x = pprime.x + w;
+ rectf(&display, r, F_STORE);
+ break;
+ }
+ case DMD_FORW:
+ curpt.x++;
+ break;
+ case DMD_BACK:
+ curpt.x--;
+ break;
+ case DMD_HABS:
+ curpt.x = inshort();
+ break;
+ case DMD_HREL:
+ curpt.x += insignchar();
+ break;
+ case DMD_VABS:
+ curpt.y = inshort();
+ break;
+ case DMD_VREL:
+ curpt.y += insignchar();
+ break;
+ case DMD_PAGE:
+#ifdef PAGECHAR
+ saveptr = savebuf;
+ savechars = CHAR_STORE;
+#endif
+ stipple(Drect);
+ curpos = add(org, fudge);
+ curpt.x = curpt.y = 0;
+ break;
+ case DMD_ENDPAGE:
+ pagecmd();
+ break;
+ case DMD_SETFONT: {
+ int i;
+
+ i = inchar();
+ if (i < MAXFAMILY)
+ curfont = ftbl[i];
+ break;
+ }
+ case DMD_MKFONT:
+ case DMD_SGLYPH:
+ case DMD_BGLYPH:
+#ifdef PAGECHAR
+ if (savechars == CHAR_STORE)
+ saveptr--;
+ old = savechars;
+ savechars = CHAR_DISCARD;
+#endif
+ if (c == DMD_MKFONT)
+ ldfont();
+ else
+ ldglyph(c);
+#ifdef PAGECHAR
+ savechars = old;
+#endif
+ break;
+ case DMD_SEGMENT:
+ case DMD_SPLINE:
+ define_path(c);
+ break;
+ case DMD_CIRCLE:
+ define_circle();
+ break;
+ case DMD_ELLIPSE:
+ define_ellipse();
+ break;
+ case DMD_DRAWPATH:
+ draw_path();
+ break;
+ case DMD_FILLPATH:
+ fill_path();
+ break;
+ case DMD_PENSIZE:
+ set_pen();
+ break;
+ default:
+ break;
+ }
+}
+
+/* request an index number for a new font */
+ldfont()
+{
+ register struct fontinfo *f;
+ register int i, j;
+ register int x = -1;
+ char name[MAXFONTNAME];
+ register char *p;
+ char loaded[16];
+
+ p = name;
+ while (*p++ = inchar())
+ if (p >= &name[MAXFONTNAME]) {
+ while (inchar())
+ continue;
+ break;
+ }
+ for (i = 0; i < sizeof(loaded); i++)
+ loaded[i] = 0;
+ /* look for the font... */
+ for (i = 0; i < MAXFAMILY; i++) {
+ f = ftbl[i];
+ if (f && strncmp(f->f_name, name, sizeof(f->f_name)) == 0) {
+ for (j = 0; j < 128; j++) {
+ if (f->f_glyph[j].g_bitmap.base)
+ loaded[j>>3] |= 1 << (~j & 07);
+ }
+ send(i);
+ sendnchars(sizeof(loaded), loaded);
+ return;
+ }
+ if (x == -1 && f == 0)
+ x = i;
+ }
+ if (x == -1) {
+ send(-1);
+ return;
+ }
+ f = (struct fontinfo *)alloc(sizeof (struct fontinfo));
+ if (f == 0) {
+ send(-1);
+ return;
+ }
+ ftbl[x] = f;
+ strncpy(f->f_name, name, sizeof(f->f_name));
+ send(x);
+ sendnchars(sizeof(loaded), loaded);
+}
+
+/* download a particular character in a font */
+ldglyph(c)
+ int c;
+{
+ register struct glyph *g;
+ register int i, j;
+ register char *p;
+ short chr, fam, w;
+ int words;
+ int o;
+ short xs, ys;
+ int endb;
+ static struct glyph gdummy;
+
+ w = inshort();
+ fam = (w >> 7) & 0177;
+ chr = w & 0177;
+ if (ftbl[fam])
+ g = &(ftbl[fam]->f_glyph[chr]);
+ else {
+ ftbl[fam] = (struct fontinfo *)alloc(sizeof (struct fontinfo));
+ g = ftbl[fam] ? &(ftbl[fam]->f_glyph[chr]) : &gdummy;
+ }
+
+ if (c == DMD_SGLYPH) {
+ g->g_pxwidth = insignchar();
+ xs = inchar();
+ g->g_xoffset = insignchar();
+ ys = inchar();
+ g->g_yoffset = insignchar();
+ } else {
+ g->g_pxwidth = inshort();
+ xs = inshort();
+ g->g_xoffset = inshort();
+ ys = inshort();
+ g->g_yoffset = inshort();
+ }
+ words = RoundUp(xs, WORDSIZE) >> WORDSHIFT;
+ o = RoundUp(xs, 8) >> 3;
+ endb = words * sizeof(Word);
+ if (g->g_bitmap.base)
+ free(g->g_bitmap.base);
+ if (g == &gdummy || (p = alloc(ys * endb)) == 0) {
+ /* skip raster bytes */
+ j = o * ys;
+ for (i = 0; i < j; i++)
+ inchar();
+ } else {
+ /* read raster here */
+ g->g_bitmap.base = (Word *)p;
+ g->g_bitmap.width = words;
+ g->g_bitmap.rect.origin.x = 0;
+ g->g_bitmap.rect.origin.y = 0;
+ g->g_bitmap.rect.corner.x = xs;
+ g->g_bitmap.rect.corner.y = ys;
+ g->g_bitmap._null = 0;
+ p = (char *)g->g_bitmap.base;
+ for (j = 0; j < ys; j++) {
+ for (i = 0; i < o; i++)
+ *p++ = inchar();
+ for ( ; i < endb; i++)
+ *p++ = 0;
+ }
+ }
+}
+
+/* mouse and keyboard input routines at end of page */
+
+static char *b3m[] = {
+ "redraw",
+ "next",
+ "prev",
+ "quit",
+ "exit",
+ NULL
+};
+
+static Menu menu = { b3m };
+
+Texture16 ok = {
+ 0x1C44, 0x2248, 0x2250, 0x2270,
+ 0x2248, 0x1C44, 0x0000, 0x0380,
+ 0x0440, 0x0440, 0x0080, 0x0100,
+ 0x0100, 0x0100, 0x0000, 0x0100,
+};
+
+minkbd()
+{
+ Texture16 *t;
+ register int i;
+ int oscroll = 0;
+ register int inscroll = 0;
+ Point selpt;
+
+ while (i = wait(KBD|MOUSE|RCV)) {
+ if (i&KBD)
+ return(kbdchar());
+ else if (i&RCV)
+ return(rcvchar());
+ selpt = mouse.xy;
+ i = selpt.x - Drect.origin.x;
+ inscroll = 0;
+ if (i >= 0 && i < SCROLLSIZE)
+ inscroll += 1;
+ i = Drect.corner.y - selpt.y;
+ if (i >= 0 && i < SCROLLSIZE)
+ inscroll += 2;
+ if (inscroll != oscroll) {
+ cursswitch(inscroll ? &C_crosshair : &prompt);
+ oscroll = inscroll;
+ }
+ switch (inscroll) {
+ case 0:
+ if (!bttn3())
+ break;
+ switch (i = menuhit(&menu, 3)) {
+ case -1:
+ break;
+ case 4:
+ t = cursswitch(&ok);
+ while (!bttn123()) sleep(1);
+ i = bttn3();
+ while (bttn123()) sleep(1);
+ (void)cursswitch(t);
+ if (i)
+ return('x');
+ break;
+ default:
+ return("rnpq"[i]);
+ }
+ break;
+ case 1:
+ if (!bttn13())
+ break;
+ if (bttn1())
+ typeorg.y -= selpt.y - Drect.origin.y;
+ else
+ typeorg.y += selpt.y - Drect.origin.y;
+ /* primitive scroll for now */
+ while (bttn123());
+ return('s');
+ case 2:
+ if (!bttn13())
+ break;
+ if (bttn1())
+ typeorg.x -= selpt.x - Drect.origin.x;
+ else
+ typeorg.x += selpt.x - Drect.origin.x;
+ /* primitive scroll for now */
+ while (bttn123());
+ return('s');
+ case 3:
+ if (bttn1())
+ return('n');
+ else if (bttn2())
+ return('r');
+ else if (bttn3())
+ return('p');
+ break;
+ }
+ sleep(1);
+ }
+ /*NOT REACHED*/
+}
+
+pagecmd()
+{
+ register int i;
+ register Texture16 *t;
+ int cmd;
+ Point p1, p2;
+ int redraw;
+#ifdef PAGECHAR
+ int pagesaved;
+ char buf[40];
+
+ pagesaved = savechars != CHAR_DISCARD;
+#endif
+ t = cursswitch(&prompt);
+pgstart:
+ redraw = 0;
+ /*
+ * draw outlines of scroll bars. We will draw
+ * the whole lines when we can't write in the
+ * scroll area, but for now, do it this way.
+ */
+ p1 = Drect.origin;
+ p1.x += SCROLLSIZE;
+ p2.x = p1.x;
+ p2.y = p1.y + SCROLLSIZE;
+ segment(&display, p1, p2, F_STORE);
+ p1.y = Drect.corner.y - 2*SCROLLSIZE;
+ p2.y = Drect.corner.y;
+ segment(&display, p1, p2, F_STORE);
+ p1.y = Drect.corner.y - SCROLLSIZE;
+ p2.y = p1.y;
+ p1.x = Drect.origin.x;
+ p2.x = p1.x + 2*SCROLLSIZE;
+ segment(&display, p1, p2, F_STORE);
+ p1.x = Drect.corner.x - SCROLLSIZE;
+ p2.x = Drect.corner.x;
+ segment(&display, p1, p2, F_STORE);
+#ifdef PAGECHAR
+ savechars = CHAR_DISCARD;
+#ifdef DEBUG
+ sprintf(buf, "%d", saveptr-savebuf);
+ p1 = org;
+ p1.x += 20;
+ p1.y += 20;
+ string(&defont, buf, &display, p1, F_XOR);
+#endif
+#endif
+ switch (cmd = minkbd()) {
+ case 0177:
+ case 04:
+ case 'q':
+ send(DMD_EXIT);
+ resetmode(DMD_TERM);
+ t = 0;
+ break;
+ case 'x':
+ send(DMD_EXIT);
+ bye();
+ break;
+ case 'r':
+ case '\f':
+ typeorg = org;
+ /* fall into... */
+ case 's':
+ redraw = 1;
+ break;
+ case 'n':
+ case ' ':
+ typeorg.y -= Drect.corner.y - Drect.origin.y;
+ if (org.y - typeorg.y < PAGEPIXELS) {
+ redraw = 1;
+ break;
+ }
+ /* fall into... */
+ case '+':
+ case '\r':
+ case '\n':
+ typeorg = org;
+ send(DMD_PAGE);
+ send(1);
+ break;
+ case 'p':
+ typeorg.y += Drect.corner.y - Drect.origin.y;
+ if (org.y >= typeorg.y) {
+ redraw = 1;
+ break;
+ }
+ /* fall into... */
+ case '-':
+ typeorg = org;
+ send(DMD_PAGE);
+ send(-1);
+ break;
+ default:
+ /* ringbell(); */
+ goto pgstart;
+ }
+ if (redraw) {
+#ifdef PAGECHAR
+ if (pagesaved) {
+#ifdef MPX
+ if (P->state&(RESHAPED|MOVED))
+ windowupdate();
+#endif
+ typeset(DMD_PAGE);
+ saveptr = savebuf;
+ savechars = CHAR_FETCH;
+ while ((i = inchar()) != DMD_ENDPAGE)
+ typeset(i);
+ (void)cursswitch(&prompt);
+ goto pgstart;
+ }
+#endif
+ send(DMD_PAGE);
+ send(0);
+ }
+ (void)cursswitch(t);
+}
+
+inkbd()
+{
+ wait(RCV|KBD);
+ return((own()&KBD)? kbdchar():rcvchar());
+}
+
+bye()
+{
+ register int i;
+
+ for (i = 0; i < MAXFAMILY; i++) {
+ if (ftbl[i])
+ freefont(ftbl[i]);
+ }
+ exit();
+}
+
+freefont(f)
+ struct fontinfo *f;
+{
+ struct glyph *g;
+
+ for (g = f->f_glyph; g < &f->f_glyph[128]; g++)
+ if (g->g_bitmap.base)
+ free((char *)g->g_bitmap.base);
+ free((char *)f);
+}
+
+#ifdef notdef
+edit(s)
+ char *s;
+{
+ char buf[40];
+ Point p;
+ int c;
+ register i;
+
+ strcpy(buf, s);
+ p = mouse.xy;
+ disp(buf, p);
+ for(i = strlen(buf); (c = inkbd()) != '\r';)
+ {
+ disp(buf, p);
+ p = mouse.xy;
+ switch(c)
+ {
+ case '\b':
+ if((buf[i] != ' ') && (i > 0))
+ buf[--i] = 0;
+ break;
+ case '@':
+ while(buf[i] != ' ') i--;
+ buf[++i] = 0;
+ break;
+ default:
+ buf[i++] = c;
+ buf[i] = 0;
+ break;
+ }
+ disp(buf, p);
+ }
+ disp(buf, p);
+ strcpy(s, buf);
+}
+
+disp(s, p)
+ char *s;
+ Point p;
+{
+ string(&defont, "\001", &display,
+ string(&defont, s, &display, p, F_XOR), F_XOR);
+}
+#endif
+
+resetmode(c)
+ int c;
+{
+ if (c == DMD_TERM) {
+ cursvis = dotypeset = 0;
+#ifdef MPX
+ request(SEND|RCV);
+#else
+ request(SEND|RCV|KBD);
+#endif
+ curpos.x = org.x + fudge.x;
+ curpos.y = Drect.corner.y - fudge.y - defont.height;
+ } else {
+ dotypeset = 1;
+ request(SEND|RCV|KBD|MOUSE);
+ typeorg = org;
+ }
+}
+
+windowupdate()
+{
+#ifdef MPX
+ if (P->state&RESHAPED) {
+#endif
+ org = Drect.origin;
+ typeorg = org;
+ curpos = add(org, fudge);
+ line.bufp = line.buf;
+ if (cursvis) {
+ term(CURSOR, 0); /* flip state */
+ cursvis = 0;
+ }
+#ifdef MPX
+ } else {
+ curpos = add(sub(curpos, org), Drect.origin);
+ typeorg = add(sub(typeorg, org), Drect.origin);
+ org = Drect.origin;
+ }
+ P->state &= ~(MOVED|RESHAPED);
+#endif
+ artdeco();
+}
+
+static Texture16 vstripe = {
+ 0xf0f0, 0xf0f0, 0xf0f0, 0xf0f0,
+ 0xf0f0, 0xf0f0, 0xf0f0, 0xf0f0,
+ 0xf0f0, 0xf0f0, 0xf0f0, 0xf0f0,
+ 0xf0f0, 0xf0f0, 0xf0f0, 0xf0f0
+};
+
+static Texture16 hstripe = {
+ 0xffff, 0xffff, 0xffff, 0xffff,
+ 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xffff, 0xffff, 0xffff, 0xffff,
+ 0x0000, 0x0000, 0x0000, 0x0000,
+};
+
+artdeco()
+{
+ texture16(&display, Rect(display.rect.origin.x, display.rect.origin.y,
+ display.rect.corner.x, Drect.origin.y), &vstripe, F_XOR);
+ texture16(&display, Rect(display.rect.origin.x, Drect.origin.y,
+ Drect.origin.x, Drect.corner.y), &hstripe, F_XOR);
+ texture16(&display, Rect(Drect.corner.x, Drect.origin.y,
+ display.rect.corner.x, Drect.corner.y), &hstripe, F_XOR);
+ texture16(&display, Rect(display.rect.origin.x, Drect.corner.y,
+ display.rect.corner.x, display.rect.corner.y), &vstripe, F_XOR);
+}
+
+/* graphics support; for now there are some unimplemented operations */
+
+#define MAXPOINTS 60
+
+#define PATH_NONE -1
+#define PATH_SEGMENT 0
+#define PATH_SPLINE 1
+#define PATH_CIRCLE 2
+#define PATH_ELLIPSE 3
+
+int path_type = PATH_NONE;
+int pen_size = 1;
+
+struct {
+ Point c_center;
+ Point c_start;
+ Point c_finish;
+} path_circle;
+
+struct {
+ Point e_center;
+ Point e_start;
+ Point e_finish;
+ short e_xradius;
+ short e_yradius;
+} path_ellipse;
+
+Point path_pts[MAXPOINTS+2];
+int path_len;
+
+define_path(c)
+{
+ register int i, n;
+ register Point *pp;
+
+ path_type = (c==DMD_SEGMENT) ? PATH_SEGMENT : PATH_SPLINE;
+ n = inshort();
+ path_len = n;
+ if (path_len > MAXPOINTS) {
+ path_len = MAXPOINTS;
+ for (i = path_len; i < n; i++)
+ (void)inpoint();
+ }
+ pp = &path_pts[1];
+ for (i = 0; i < path_len; i++)
+ *pp++ = inpoint();
+}
+
+define_circle()
+{
+ path_circle.c_center = inpoint();
+ path_circle.c_start = inpoint();
+ path_circle.c_finish = inpoint();
+ path_type = PATH_CIRCLE;
+}
+
+define_ellipse()
+{
+ path_ellipse.e_center = inpoint();
+ path_ellipse.e_start = inpoint();
+ path_ellipse.e_finish = inpoint();
+ path_ellipse.e_xradius = inshort();
+ path_ellipse.e_yradius = inshort();
+ path_type = PATH_ELLIPSE;
+}
+
+draw_path()
+{
+ int rop;
+
+ rop = inchar(); /* ignore for now */
+ switch (path_type) {
+ case PATH_SEGMENT:
+ draw_segment(F_OR);
+ break;
+ case PATH_SPLINE:
+ draw_spline(F_OR);
+ break;
+ case PATH_CIRCLE:
+ draw_circle(F_OR);
+ break;
+ case PATH_ELLIPSE:
+ draw_ellipse(F_OR);
+ break;
+ }
+}
+
+fill_path()
+{
+ int rop;
+
+ rop = inchar(); /* ignore for now */
+}
+
+set_pen()
+{
+ int i = inchar();
+
+ if (i < 1)
+ i = 1;
+ pen_size = i;
+}
+
+/* draw a spline path */
+draw_spline(f)
+ int f;
+{
+ register Point *pp = path_pts;
+ register long w, t1, t2, t3, scale=1000;
+ register int i, j, steps=10;
+ int n = path_len + 1;
+ Point p, q;
+
+ pp[0] = pp[1];
+ pp[n] = pp[n-1];
+ p = pp[0];
+ for (i = 0; i < n-1; i++) {
+ for (j = 0; j < steps; j++) {
+ w = scale * j / steps;
+ t1 = w * w / (2 * scale);
+ w = w - scale/2;
+ t2 = 3*scale/4 - w * w / scale;
+ w = w - scale/2;
+ t3 = w * w / (2*scale);
+ q.x = (t1*pp[i+2].x + t2*pp[i+1].x +
+ t3*pp[i].x + scale/2) / scale;
+ q.y = (t1*pp[i+2].y + t2*pp[i+1].y +
+ t3*pp[i].y + scale/2) / scale;
+ line_btw(p, q, f);
+ p = q;
+ }
+ }
+}
+
+/* draw a segment path */
+draw_segment(f)
+ int f;
+{
+ register Point *pp;
+ register int i;
+
+ pp = &path_pts[1];
+ if (path_len == 1) {
+ if (pen_size > 1)
+ disc(&display, pp[0], pen_size, f);
+ else
+ point(&display, pp[0], f);
+ } else {
+ for (i = 1; i < path_len; i++) {
+ line_btw(pp[0], pp[1], f);
+ pp++;
+ }
+ }
+}
+
+draw_circle(f)
+ int f;
+{
+ /* ignore pen size for now */
+
+ if (path_circle.c_center.x == path_circle.c_finish.x &&
+ path_circle.c_center.y == path_circle.c_finish.y) {
+ circle(&display, path_circle.c_center, path_circle.c_start.x, f);
+ } else {
+ arc(&display, path_circle.c_center, path_circle.c_start,
+ path_circle.c_finish, f);
+ }
+}
+
+draw_ellipse(f)
+ int f;
+{
+ /* ignore pen size for now */
+
+ if (path_ellipse.e_center.x == path_ellipse.e_finish.x &&
+ path_ellipse.e_center.y == path_ellipse.e_finish.y) {
+ ellipse(&display, path_ellipse.e_center, path_ellipse.e_xradius,
+ path_ellipse.e_yradius, f);
+ } else {
+ elarc(&display, path_ellipse.e_center, path_ellipse.e_xradius,
+ path_ellipse.e_yradius, path_ellipse.e_start,
+ path_ellipse.e_finish, f);
+ }
+}
+
+/* Draw a line on the screen. */
+line_btw(p0, p1, rop)
+ Point p0, p1;
+{
+ register int i;
+ register int incx;
+
+ if (abs(p1.y-p0.y) > abs(p1.x-p0.x)) {
+ incx = 1;
+ p0.x -= pen_size/2;
+ p1.x -= pen_size/2;
+ } else {
+ incx = 0;
+ p0.y -= pen_size/2;
+ p1.y -= pen_size/2;
+ }
+ for (i = 0; i < pen_size; i++) {
+ segment(&display, p0, p1, rop);
+ if (incx) {
+ p0.x++; p1.x++;
+ } else {
+ p0.y++; p1.y++;
+ }
+ }
+}
diff --git a/dviware/umddvi/dev/dvipr.sh b/dviware/umddvi/dev/dvipr.sh
new file mode 100644
index 0000000000..65ada43730
--- /dev/null
+++ b/dviware/umddvi/dev/dvipr.sh
@@ -0,0 +1,71 @@
+#! /bin/sh
+#
+# print a dvi file on the versatec
+#
+# NOTE: sense of -h is inverted (-h => no horizontal printing)
+
+flags=
+hflag=-h
+q=
+v=
+title=
+
+# eat arguments
+
+while [ $# -gt 0 ]
+do
+ case "$1" in
+ -m)
+ shift
+ flags="$flags -m $1";;
+ -h)
+ hflag=;;
+ -q)
+ q=q;;
+ -v)
+ v=v;;
+ -t)
+ echo tape interface not yet implemented 2>&1;;
+ -T)
+ shift
+ title="$1";;
+ -T*)
+ title="$1";;
+ -*)
+ flags="$flags $1";;
+ *)
+ break
+ esac
+ shift
+done
+
+if [ $# != 1 ]; then
+ echo "Usage: $0 [-q] [-v] [-h] [-s] [-m mag] [-d drift] [-T title] filename" 2>&1
+ exit 1
+fi
+
+if [ x"$title" = x ]; then
+ title="$*"
+fi
+
+# pass 2 only?
+if [ x$v = xv ]; then
+ exec spool -d versatec -verser2 -t "$title" $*
+fi
+
+dvifile=$1
+
+if [ ! -r $dvifile ]; then
+ dvifile=$1.dvi
+ if [ ! -r $dvifile ]; then
+ echo "$0: cannot find $1 or $1.dvi" 2>&1
+ exit 1
+ fi
+fi
+
+# pass 1 only?
+if [ x$q = xq ]; then
+ exec verser1 $hflag $flags $dvifile
+fi
+
+verser1 $hflag $flags $dvifile | spool -d versatec -verser2 -t "$title"
diff --git a/dviware/umddvi/dev/fontdesc b/dviware/umddvi/dev/fontdesc
new file mode 100644
index 0000000000..3954e1d339
--- /dev/null
+++ b/dviware/umddvi/dev/fontdesc
@@ -0,0 +1 @@
+font pxl * 0 /usr/local/lib/tex/fonts/pxl/%n.%mpxl
diff --git a/dviware/umddvi/dev/imagen1-special.c b/dviware/umddvi/dev/imagen1-special.c
new file mode 100644
index 0000000000..628b26c483
--- /dev/null
+++ b/dviware/umddvi/dev/imagen1-special.c
@@ -0,0 +1,718 @@
+/*
+ * Support drawing routines for Chris Torek's DVI->ImPress program.
+ *
+ * Requires v1.7 or later ImPress to handle paths.
+ * Better if v1.9 or later for arc, circle, and ellipse primitives
+ * (define USEGRAPHICS).
+ *
+ * Tim Morgan, UC Irvine, 11/17/85
+ *
+ *
+ * At the time these routines are called, the position of the Imagen should
+ * have been updated to the upper left corner of the graph (the position
+ * the \special appears at in the dvi file). Then the coordinates in the
+ * graphics commands are in terms of a virtual page with axes oriented the
+ * same as the Imagen normally has:
+ *
+ * 0,0
+ * +-----------> +x
+ * |
+ * |
+ * |
+ * \ /
+ * +y
+ *
+ * Angles are measured in the conventional way, from +x towards +y.
+ * Unfortunately, that reverses the meaning of "counterclockwise" from
+ * what you see in the output.
+ *
+ * Unfortunately, some 8/300's don't have an aspect ratio which is 1:1.
+ * One of ours appears to be 295 dpi in the horizontal direction and 300dpi
+ * vertically. If ASPECT is defined, then dviimp/imagen1 and draw_imp/special
+ * use two different variables for the horizontal and vertical resolution, and
+ * otherwise, just one. Because the drawing routines which are defined
+ * in ImPress for circles, arcs, and ellipses in V1.9 and later assume that
+ * the output device is 1:1, they can't be used if ASPECT is defined, and
+ * because I don't want to hack up imagen1 to understand different horizontal
+ * and vertical resolutions, we're currently ignoring this problem, and not
+ * defining ASPECT.
+ */
+
+#define USEGRAPHICS /* Only if v1.9 or later imPRESS */
+#undef ASPECT
+
+#ifdef ASPECT /* Can't have both! */
+#undef USEGRAPHICS
+#endif
+
+#include <stdio.h>
+#include <ctype.h>
+#include "types.h"
+#include "imPcodes.h"
+
+/* Put a two-byte (word) value to the Imagen */
+#define putword(w) (putchar((w) >> 8), putchar(w))
+
+extern char *malloc();
+
+
+#define TRUE 1
+#define FALSE 0
+
+#define TWOPI (3.14157926536*2.0)
+#define MAXPOINTS 300 /* Most number of points in a path */
+#define SPLINEPOINTS 900 /* Most points in a spline */
+#define RADTOPXL 2607.435436 /* (16383 / (2pi)). This
+ converts from radians to the
+ angle units used by ImPress */
+
+/* Convert radian angles to 2**-14 angle units used by ImPress */
+#define RadToImpUnits(a) ((short) ((a)*RADTOPXL + 0.5))
+
+/* Graphics operations */
+#define WHITE 0
+#define SHADE 3
+#define OR 7
+#define BLACK 15
+
+extern double cos(), sin(), sqrt();
+#ifndef ASPECT
+extern int DPI; /* Resolution of device */
+#define PixPerInX DPI
+#define PixPerInY DPI
+#else
+extern int DPIx, DPIy; /* x,y resolution of device */
+#define PixPerInX DPIx
+#define PixPerInY DPIy
+#endif
+
+extern int UserMag;
+#define conv(x, f)\
+ ((int) ((((double)(x)/1000.0) * ((double)(f)) * ((double)UserMag/1000.0)) + 0.5))
+#define xconv(x) conv(x, PixPerInX)
+#define yconv(y) conv(y, PixPerInY)
+
+extern int ImHH; /* Imagen horizontal position */
+extern int ImVV; /* Imagen vertical position */
+extern int hh; /* current horizontal position, in DEVs */
+extern int vv; /* current vertical position, in DEVs */
+
+extern int NextFamilyNumber; /* Number of next ImPress family to use */
+#define fnum NextFamilyNumber
+
+static int xx[MAXPOINTS], yy[MAXPOINTS], pathlen,
+ pensize = 2; /* Size we want Imagen to draw at, default 2 pixels */
+
+#define MAXPENSIZE 20 /* Imagen restriction */
+
+static int
+ family_defined = FALSE, /* Have we chosen family yet? */
+ texture_defined = FALSE,/* Have we done a set_texture yet? */
+ whiten_next = FALSE, /* Should next object be whitened? */
+ blacken_next = FALSE, /* Should next object be blackened? */
+ shade_next = FALSE; /* Should next object be shaded? */
+
+/* Predefined shading (texture) glyph */
+/* First, define size of glyph */
+#define THEIGHT 32 /* bits high */
+#define TWIDTH 4 /* bytes wide */
+/* Next, declare the bit map for the glyph */
+static char stexture[THEIGHT][TWIDTH]={
+ {0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00},
+ {0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00},
+ {0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00},
+ {0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00},
+ {0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00},
+ {0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00},
+ {0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00},
+ {0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00}};
+
+/*
+ * Copy a default texture into the stexture array
+ */
+static void glyph_init()
+{
+ static char btexture[THEIGHT][TWIDTH]={
+ {0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00},
+ {0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00},
+ {0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00},
+ {0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00},
+ {0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00},
+ {0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00},
+ {0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00},
+ {0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00}};
+
+ int i;
+ for (i=0; i<THEIGHT; i++)
+ bcopy(btexture[i],stexture[i],TWIDTH);
+
+}
+
+
+/*
+ * Push the state of the Imagen and set up a new virtual coord system
+ */
+static void push_location()
+{
+ putchar(imP_Push);
+ putchar(imP_SetHVSystem);
+ putchar(0140);
+}
+
+
+/*
+ * Create the pushed virtual page, and pop the state of the printer
+ */
+static void pop_location()
+{
+ putchar(imP_Pop);
+}
+
+
+/*
+ * Set the pen size
+ * Called as \special{pn size}
+ * eg: \special{pn 8}
+ * The size is the number of milli-inches for the diameter of the pen.
+ * This routine converts that value to device-dependent pixels, and makes
+ * sure that the resulting value is within legal bounds.
+ */
+static void im_pensize(cp)
+char *cp;
+{
+ int size;
+
+ if (sscanf(cp, " %d ", &size) != 1) return;
+ pensize = yconv(size);
+ if (pensize < 1) pensize = 1;
+ else if (pensize > MAXPENSIZE) pensize = MAXPENSIZE;
+}
+
+
+/*
+ * Make sure the pen size is set. Since we push and pop the state,
+ * this has to be sent for each different object (I think).
+ */
+static void set_pen_size()
+{
+ putchar(imP_SetPen);
+ putchar(pensize);
+}
+
+
+/*
+ * Actually apply the attributes (shade, whiten, or blacken) to the currently
+ * defined path/figure.
+ */
+static void do_attributes()
+{
+ static int family; /* Family of downloaded texture glyph */
+ static int member; /* Member of family */
+ int i,j; /* Loop through glyph array */
+
+ if (shade_next) {
+ shade_next = FALSE;
+ if (!family_defined) {
+ family_defined = TRUE;
+ family = fnum++;
+ member = -1;
+ }
+ if (!texture_defined) {
+ texture_defined = TRUE;
+ member++;
+ putchar(imP_DefGlyph);
+ putchar((family & 0x7e) >> 1);
+ putchar((family & 0x01) << 7 | (member & 0x7f));
+ /*putword(0); */ /* Advance width */
+ putword(32);
+ putword(TWIDTH*8); /* pixel width (8 x number of bytes) */
+ /*putword(0); */ /* left offset */
+ putword(32);
+ putword(THEIGHT); /* and height of glyph */
+ /*putword(0); */ /* top offset */
+ putword(32);
+ for (i=0; i<THEIGHT; i++)/* Do rows */
+ for (j=0; j<TWIDTH; j++) putchar(stexture[i][j]);
+ }
+ putchar(imP_SetTexture);
+ putchar((family & 0x7e) >> 1);
+ putchar((family & 0x01) << 7 | (member & 0x7f));
+ putchar(imP_FillPath);
+ putchar(SHADE);
+ glyph_init(); /* reinitialize the array */
+ }
+ else if (whiten_next) {
+ whiten_next = FALSE;
+ putchar(imP_FillPath);
+ putchar(WHITE);
+ }
+ else if (blacken_next) {
+ blacken_next = FALSE;
+ putchar(imP_FillPath);
+ putchar(BLACK);
+ }
+}
+
+
+/*
+ * Flush the path that we've built up with im_drawto()
+ * Called as \special{fp}
+ */
+static void im_flushpath()
+{
+ register int i;
+
+ push_location();
+ if (pathlen <= 0) return;
+ set_pen_size();
+ putchar(imP_CreatePath);
+ putword(pathlen);
+ for (i=1; i<=pathlen; i++) {
+ putword(xx[i]);
+ putword(yy[i]);
+ }
+ pathlen = 0;
+ putchar(imP_DrawPath);
+ putchar(BLACK);
+ do_attributes();
+ pop_location();
+}
+
+
+/* Helper routine for dashed_line() */
+static void connect(x0, y0, x1, y1)
+int x0, y0, x1, y1;
+{
+ set_pen_size();
+ putchar(imP_CreatePath);
+ putword(2); /* Path length */
+ putword(x0); putword(y0);/* The path */
+ putword(x1); putword(y1);
+ putchar(imP_DrawPath);
+ putchar(BLACK);
+}
+
+
+/* Another helper. Draw a dot at the indicated point */
+static void dot_at(x, y)
+int x,y;
+{
+ set_pen_size();
+ putchar(imP_CreatePath);
+ putword(1); /* Path length */
+ putword(x); putword(y); /* The path */
+ putchar(imP_DrawPath);
+ putchar(BLACK);
+}
+
+
+/*
+ * Draw a dashed or dotted line between the first pair of points in the array
+ * Called as \special{da <inchesperdash>} (dashed line)
+ * or \special{dt <inchesperdot>} (dotted line)
+ * eg: \special{da 0.05}
+ */
+static void dashed_line(cp, dotted)
+char *cp;
+int dotted; /* boolean */
+{
+ int i, numdots, x0, y0, x1, y1;
+ double cx0, cy0, cx1, cy1;
+ double d, spacesize, a, b, dx, dy, pixperdash;
+ float inchesperdash;
+
+ if (sscanf(cp, " %f ", &inchesperdash) != 1) return;
+ if (pathlen <= 1) return;
+ pixperdash = inchesperdash * ((float) PixPerInY);
+ x0 = xx[1]; x1 = xx[2];
+ y0 = yy[1]; y1 = yy[2];
+ dx = x1 - x0;
+ dy = y1 - y0;
+ push_location();
+ if (dotted) {
+ numdots = sqrt(dx*dx + dy*dy) / pixperdash + 0.5;
+ if (numdots > 0)
+ for (i = 0; i <= numdots; i++) {
+ a = (float) i / (float) numdots;
+ cx0 = ((float) x0) + (a*dx) + 0.5;
+ cy0 = ((float) y0) + (a*dy) + 0.5;
+ dot_at((int) cx0, (int) cy0);
+ }
+ }
+ else {
+ d = sqrt(dx*dx + dy*dy);
+ if (d <= 2 * pixperdash) {
+ connect(x0, y0, x1, y1);
+ pathlen = 0;
+ pop_location();
+ return;
+ }
+ numdots = d / (2 * pixperdash) + 1;
+ spacesize = (d - numdots * pixperdash) / (numdots - 1);
+ for (i=0; i<numdots-1; i++) {
+ a = i * (pixperdash + spacesize) / d;
+ b = a + pixperdash / d;
+ cx0 = ((float) x0) + (a*dx) + 0.5;
+ cy0 = ((float) y0) + (a*dy) + 0.5;
+ cx1 = ((float) x0) + (b*dx) + 0.5;
+ cy1 = ((float) y0) + (b*dy) + 0.5;
+ connect((int) cx0, (int) cy0, (int) cx1, (int) cy1);
+ b += spacesize / d;
+ }
+ cx0 = ((float) x0) + (b*dx) + 0.5;
+ cy0 = ((float) y0) + (b*dy) + 0.5;
+ connect((int) cx0, (int) cy0, x1, y1);
+ }
+ pathlen = 0;
+ pop_location();
+}
+
+
+/*
+ * Virtually draw to a given x,y position on the virtual page.
+ * X and Y are expressed in thousandths of an inch, and this
+ * routine converts them to pixels.
+ *
+ * Called as \special{pa <x> <y>}
+ * eg: \special{pa 0 1200}
+ */
+static void im_drawto(cp)
+char *cp;
+{
+ int x,y;
+
+ if (sscanf(cp, " %d %d ", &x, &y) != 2) return;
+
+ if (++pathlen >= MAXPOINTS)
+ error(1, 0, "Too many points specified");
+ xx[pathlen] = xconv(x);
+ yy[pathlen] = yconv(y);
+}
+
+#ifndef USEGRAPHICS
+/*
+ * Helper routine for im_arc().
+ * Convert x and y to integers, then call im_drawto() normally.
+ */
+static void im_fdraw(x, y)
+float x, y;
+{
+ int ix,iy;
+
+ ix = (int) x + 0.5;
+ iy = (int) y + 0.5;
+ im_drawto(ix, iy);
+}
+
+
+/*
+ * Draw the indicated arc on the virtual page and flush it.
+ * The arc is always drawn counter clockwise from start_angle to end_angle on
+ * the virtual page. That is, clockwise in the real world (since +y is down).
+ * It is assumed that start_angle has been adjusted to be in the range
+ * 0.0 <= start_angle < 2*PI
+ * and that end_angle is the smallest suitable angle >= start_angle. Thus
+ * end_angle MAY be >= 2*PI.
+ *
+ * Called as \special{ar <xcenter> <ycenter> <xradius> <yradius>
+ * <startangle> <endangle>}
+ *
+ * <xcenter>,<ycenter>,<xradius>,<yradius> are in 1/1000's of an inch.
+ * <startangle> and <endangle> are in radians.
+ *
+ * eg: \special{ar 240 240 30 30 0.000 6.283}
+ */
+static void im_arc(cp)
+char *cp;
+{
+ int xc, yc, xrad, yrad;
+ float start_angle, end_angle;
+ double angle, theta, r, xcenter, ycenter, xradius, yradius;
+ int n;
+
+ if (sscanf(cp, " %d %d %d %d %f %f ", &xc, &yc, &xrad, &yrad, &start_angle,
+ &end_angle) != 6) return;
+ xcenter = xc; /* Convert to floating point */
+ ycenter = yc;
+ xradius = xrad;
+ yradius = yrad;
+ r = (xradius+yradius)/2.0;
+ theta = sqrt(1.0 / r);
+ n = TWOPI / theta + 0.5;
+ if (n<6) n = 6;
+ if (n>80) n = 80;
+ theta = TWOPI / n;
+
+ im_fdraw( xcenter + xradius*cos(start_angle),
+ ycenter + yradius*sin(start_angle) );
+ angle = start_angle + theta;
+ while (angle < end_angle) {
+ im_fdraw(xcenter + xradius*cos(angle),
+ ycenter + yradius*sin(angle) );
+ angle += theta;
+ }
+ im_fdraw( xcenter + xradius*cos(end_angle),
+ ycenter + yradius*sin(end_angle) );
+ im_flushpath();
+}
+
+#else USEGRAPHICS
+
+/* Same routine as above, but it uses the special graphics primitives */
+static void im_arc(cp)
+char *cp;
+{
+ int xc, yc, xrad, yrad;
+ float start_angle, end_angle;
+ short alpha0, alpha1;
+
+ if (sscanf(cp, " %d %d %d %d %f %f ", &xc, &yc, &xrad, &yrad, &start_angle,
+ &end_angle) != 6) return;
+ push_location();
+ set_pen_size();
+ putchar(imP_SetHAbs);
+ putword(xconv(xc));
+ putchar(imP_SetVAbs);
+ putword(yconv(yc));
+
+/*
+ * If end_angle > TWOPI, we can't simply use it, since it will be > 16383,
+ * and thus an illegal angle. Simply subtracting TWOPI will make it <
+ * start_angle, which will reverse the direction the arc is drawn, resulting
+ * in the wrong arc. So we also exchange start_angle and end_angle. But then
+ * start_angle < end_angle, so the arc goes back to its original direction!
+ * So we also subtract TWOPI from the original start_angle, foring end_angle
+ * to be negative (since 0<=start_angle<TWOPI originally), which will cause
+ * the Imagen to draw in a true CCW direction (opposite of normal).
+ */
+ if (end_angle > TWOPI) {
+ double temp;
+ temp = end_angle - TWOPI;
+ end_angle = start_angle - TWOPI;
+ start_angle = temp;
+ }
+ if (xrad >= yrad-1 && xrad <= yrad+1) { /* Circle or arc */
+ alpha0 = RadToImpUnits(start_angle);
+ alpha1 = RadToImpUnits(end_angle);
+ putchar(imP_CircleArc);
+ putword(xconv((double) xrad));
+ putword(alpha0);
+ putword(alpha1);
+ }
+ else { /* Ellipse */
+ putchar(imP_EllipseArc);
+ putword(xconv((double) xrad));
+ putword(yconv((double) yrad));
+ putword(0); /* alphaoff */
+ putword(0); /* zero start angle */
+ putword(16383); /* two pi end angle */
+ }
+ putchar(imP_DrawPath);
+ putchar(BLACK);
+ do_attributes();
+ pop_location();
+}
+#endif USEGRAPHICS
+
+
+/*
+ * Create a spline through the points in the array.
+ * Called like flush path (fp) command, after points
+ * have been defined via pa command(s).
+ *
+ * eg: \special{sp}
+ */
+static void flush_spline()
+{
+ int xp, yp, N;
+ float t1, t2, t3, w;
+ int i, j, steps;
+ int splinex[SPLINEPOINTS], spliney[SPLINEPOINTS], splinelen;
+
+ push_location();
+ set_pen_size();
+ putchar(imP_CreatePath);
+ splinelen = 0;
+ N = pathlen + 1;
+ xx[0] = xx[1];
+ yy[0] = yy[1];
+ xx[N] = xx[N-1];
+ yy[N] = yy[N-1];
+ for (i = 0; i < N-1; i++) { /* interval */
+ steps = (dist(xx[i],yy[i], xx[i+1],yy[i+1]) +
+ dist(xx[i+1],yy[i+1], xx[i+2],yy[i+2])) / 20;
+ for (j = 0; j < steps; j++) { /* points within */
+ w = ((float) j) / ((float) steps);
+ t1 = 0.5 * w * w;
+ w -= 0.5;
+ t2 = 0.75 - w * w;
+ w -= 0.5;
+ t3 = 0.5 * w * w;
+ xp = t1 * xx[i+2] + t2 * xx[i+1] + t3 * xx[i] + 0.5;
+ yp = t1 * yy[i+2] + t2 * yy[i+1] + t3 * yy[i] + 0.5;
+ if (splinelen >= SPLINEPOINTS)
+ error(1, 0, "Too many points in spline");
+ splinex[splinelen] = xp;
+ spliney[splinelen++] = yp;
+ }
+ }
+ putword(splinelen);
+ for (i=0; i<splinelen; i++) {
+ putword(splinex[i]);
+ putword(spliney[i]);
+ }
+
+ pathlen = 0;
+ putchar(imP_DrawPath);
+ putchar(BLACK);
+ pop_location();
+}
+
+
+static int dist(x1, y1, x2, y2) /* integer distance from x1,y1 to x2,y2 */
+{
+ float dx, dy;
+
+ dx = x2 - x1;
+ dy = y2 - y1;
+ return sqrt(dx*dx + dy*dy) + 0.5;
+}
+
+
+/*
+ * Whiten the interior of the next figure (path). Command is:
+ * \special{wh}
+ */
+static void im_whiten()
+{
+ whiten_next = TRUE;
+}
+
+
+/*
+ * Blacken the interior of the next figure (path). Command is:
+ * \special{bk}
+ */
+static void im_blacken()
+{
+ blacken_next = TRUE;
+}
+
+
+/*
+ * Shade the interior of the next figure (path) with the predefined
+ * texture. Command is:
+ * \special{sh}
+ */
+static void im_shade()
+{
+ shade_next = TRUE;
+}
+
+
+/*
+ * Define the texture array. Command is:
+ * \special{tx 32bits 32bits ....}
+ */
+static void im_texture(pcount,bitpattern)
+int pcount, bitpattern[32];
+{
+ int i,j,k;
+ unsigned long ul_one;
+
+#ifdef DEBUG
+ if (sizeof ul_one != TWIDTH)
+ error(1, 0, "pointer/size mismatch");
+#endif
+ j = 0;
+ for (k=0; k < THEIGHT/pcount; k++) {
+ for (i=0; i<pcount; i++) {
+ ul_one = htonl((unsigned long) bitpattern[i]);
+ bcopy((char *) &ul_one, stexture[j++], TWIDTH);
+ }
+ }
+ texture_defined = FALSE;
+}
+
+
+/*
+ * This routine takes the string argument for a tx command and
+ * parses out the separate bitpatterns to call im_texture with.
+ * Written by Tinh Tang
+ */
+static void do_texture(t)
+char *t;
+{
+ int bitpattern[32];
+ int pcount = 0;
+
+ while (isspace (*t)) t++;
+ while (*t) {
+ if (sscanf(t, "%x", &bitpattern[pcount++]) != 1) {
+ error(0, 0, "malformed tx command");
+ return;
+ }
+ while (*t && !isspace(*t)) t++;/* Skip to space */
+ while (*t && isspace(*t)) t++;/* Skip to nonspace */
+ }
+ if (pcount != 4 && pcount != 8 && pcount != 16 && pcount != 32) {
+ error(0, 0, "malformed tx command");
+ return;
+ }
+ im_texture(pcount, bitpattern);
+}
+
+
+#define COMLEN 3 /* Length of a tpic command plus one */
+
+DoSpecial(k)
+ i32 k;
+{
+ char *spstring, *cp, command[COMLEN];
+ register int len;
+
+ spstring = malloc((unsigned) (k+1));
+ if (spstring == NULL) error(2, 0, "Out of memory");
+ len = 0;
+ while (k--) spstring[len++] = GetByte(stdin);
+ spstring[len] = '\0';
+ cp = spstring;
+ while (isspace(*cp)) ++cp;
+ len = 0;
+ while (!isspace(*cp) && *cp && len < COMLEN-1) command[len++] = *cp++;
+ command[len] = '\0';
+
+ if (ImHH != hh || ImVV != vv)
+ ImSetPosition(hh, vv);
+
+ if (strcmp(command, "pn") == 0) im_pensize(cp);
+ else if (strcmp(command, "fp") == 0) im_flushpath();
+ else if (strcmp(command, "da") == 0) dashed_line(cp, 0);
+ else if (strcmp(command, "dt") == 0) dashed_line(cp, 1);
+ else if (strcmp(command, "pa") == 0) im_drawto(cp);
+ else if (strcmp(command, "ar") == 0) im_arc(cp);
+ else if (strcmp(command, "sp") == 0) flush_spline();
+ else if (strcmp(command, "sh") == 0) im_shade();
+ else if (strcmp(command, "wh") == 0) im_whiten();
+ else if (strcmp(command, "bk") == 0) im_blacken();
+ else if (strcmp(command, "tx") == 0) im_texture(cp);
+ else error(0, 0, "warning: ignoring \\special");
+
+ free(spstring);
+}
diff --git a/dviware/umddvi/dev/imagen1.c b/dviware/umddvi/dev/imagen1.c
new file mode 100644
index 0000000000..78b60a5a81
--- /dev/null
+++ b/dviware/umddvi/dev/imagen1.c
@@ -0,0 +1,867 @@
+/*
+ * Copyright (c) 1987 University of Maryland Department of Computer Science.
+ * All rights reserved. Permission to copy for any purpose is hereby granted
+ * so long as this copyright notice remains intact.
+ */
+
+#ifndef lint
+static char rcsid[] = "$Header: imagen1.c,v 2.6 87/06/16 17:14:18 chris Exp $";
+#endif
+
+/*
+ * DVI to Imagen driver
+ *
+ * Reads DVI version 2 files and converts to imPRESS commands for spooling to
+ * the Imagen (via ipr).
+ *
+ * TODO:
+ * think about fonts with characters outside [0..127]
+ */
+
+#include <stdio.h>
+#include "types.h"
+#include "conv.h"
+#include "dvi.h"
+#include "dviclass.h"
+#include "dvicodes.h"
+#include "fio.h"
+#include "font.h"
+#include "postamble.h"
+#include "search.h"
+#include "imagen.h"
+#include "imPcodes.h"
+
+char *ProgName;
+extern int errno;
+extern char *optarg;
+extern int optind;
+
+/* Globals */
+char serrbuf[BUFSIZ]; /* buffer for stderr */
+
+/*
+ * DVI style arithmetic: when moving horizontally by a DVI distance >=
+ * `space', we are to recompute horizontal position from DVI units;
+ * otherwise, we are to use device resolution units to keep track of
+ * horizontal position. A similar scheme must be used for vertical
+ * positioning.
+ */
+struct fontinfo {
+ struct font *f; /* the font */
+ i32 pspace; /* boundary between `small' & `large' spaces
+ (for positive horizontal motion) */
+ i32 nspace; /* -4 * pspace, for negative motion */
+ i32 vspace; /* 5 * pspace, for vertical motion */
+ int family; /* Imagen family number (we pick one) */
+#ifdef notyet
+ int UseTime; /* cache info: flush fonts on LRU basis */
+#endif
+};
+
+/*
+ * We use one of the per-glyph user flags to keep track of whether a
+ * glyph has been loaded into the Imagen.
+ */
+#define GF_LOADED GF_USR0
+
+/*
+ * The exception that proves the rule is that hh and fromSP(dvi_h) are not
+ * allowed to get more than MaxDrift units apart.
+ */
+int MaxDrift; /* the maximum allowable difference between
+ hh and fromSP(dvi_h) */
+
+struct fontinfo *CurrentFont; /* the current font */
+int NextFamilyNumber; /* next available Imagen glyph-family index */
+
+int ExpectBOP; /* true => BOP ok */
+int ExpectEOP; /* true => EOP ok */
+
+int DPI; /* -d => device resolution (dots/inch) */
+int PFlag; /* -p => no page reversal */
+int LFlag; /* -l => landscape mode (eventually...) */
+int SFlag; /* -s => silent (no page numbers) */
+int Debug; /* -D => debug flag */
+
+int XOffset;
+int YOffset; /* offsets for margins */
+
+int hh; /* current horizontal position, in DEVs */
+int vv; /* current vertical position, in DEVs */
+
+/*
+ * Similar to dvi_stack, but includes `hh' and `vv', which are usually
+ * but not always the same as fromSP(h) and fromSP(v):
+ */
+struct localstack {
+ int stack_hh;
+ int stack_vv;
+ struct dvi_stack stack_dvi;
+};
+
+struct localstack *dvi_stack; /* base of stack */
+struct localstack *dvi_stackp; /* current place in stack */
+
+int HHMargin; /* horizontal margin (in DEVs) */
+int VVMargin; /* vertical margin (in DEVs) */
+
+long PrevPagePointer; /* The previous page pointer from the DVI
+ file. This allows us to read the file
+ backwards, which obviates the need for
+ page reversal (reversal is unsupported
+ on the 8/300). */
+
+int Numerator; /* numerator from DVI file */
+int Denominator; /* denominator from DVI file */
+int DVIMag; /* magnification from DVI file */
+int UserMag; /* user-specified magnification */
+
+int ImHH; /* Imagen horizontal position */
+int ImVV; /* Imagen vertical position */
+int ImFamily; /* Imagen current-font number */
+
+char *PrintEngine; /* e.g., canon, ricoh */
+struct search *FontFinder; /* maps from DVI index to internal fontinfo */
+int FontErrors; /* true => error(s) occurred during font
+ definitions from DVI postamble */
+
+struct fontinfo NoFont; /* a fake font to help get things started */
+
+char *getenv(), *malloc();
+
+/* Absolute value */
+#define ABS(n) ((n) >= 0 ? (n) : -(n))
+
+/* Put a two-byte (word) value to the Imagen */
+#define putword(w) (putchar((w) >> 8), putchar(w))
+
+/*
+ * Correct devpos (the actual device position) to be within MaxDrift pixels
+ * of dvipos (the virtual DVI position).
+ */
+#define FIXDRIFT(devpos, dvipos) \
+ if ((devpos) < (dvipos)) \
+ if ((dvipos) - (devpos) <= MaxDrift) \
+ /* void */; \
+ else \
+ (devpos) = (dvipos) - MaxDrift; \
+ else \
+ if ((devpos) - (dvipos) <= MaxDrift) \
+ /* void */; \
+ else \
+ (devpos) = (dvipos) + MaxDrift
+
+SelectFont(n)
+ i32 n;
+{
+ int x = S_LOOKUP;
+
+ if ((CurrentFont = (struct fontinfo *)SSearch(FontFinder, n, &x)) == 0)
+ GripeNoSuchFont(n);
+}
+
+/*
+ * Start a page (process a DVI_BOP).
+ */
+BeginPage()
+{
+ register int *i;
+ static int count[10]; /* the 10 counters */
+ static int beenhere;
+
+ if (!ExpectBOP)
+ GripeUnexpectedOp("BOP");
+ if (beenhere) {
+ if (!SFlag)
+ putc(' ', stderr);
+ } else
+ beenhere++;
+
+ dvi_stackp = dvi_stack;
+
+ ExpectBOP = 0;
+ ExpectEOP++; /* set the new "expect" state */
+
+ for (i = count; i < &count[sizeof count / sizeof *count]; i++)
+ fGetLong(stdin, *i);
+ fGetLong(stdin, PrevPagePointer);
+
+ if (!SFlag) {
+ (void) fprintf(stderr, "[%d", count[0]);
+ (void) fflush(stderr);
+ }
+ putchar(imP_Page);
+ ImHH = 0;
+ ImVV = 0;
+
+ hh = HHMargin;
+ vv = VVMargin;
+ dvi_h = toSP(hh);
+ dvi_v = toSP(vv);
+ dvi_w = 0;
+ dvi_x = 0;
+ dvi_y = 0;
+ dvi_z = 0;
+}
+
+/*
+ * End a page (process a DVI_EOP)
+ */
+EndPage()
+{
+ if (!ExpectEOP)
+ GripeUnexpectedOp("EOP");
+
+ if (!SFlag) {
+ putc(']', stderr);
+ (void) fflush(stderr);
+ }
+ ExpectEOP = 0;
+ ExpectBOP++;
+
+ putchar(imP_EndPage);
+
+ if (!PFlag && PrevPagePointer != -1)
+ (void) fseek(stdin, PrevPagePointer, 0);
+}
+
+/*
+ * Store the relevant information from the DVI postamble, and set up
+ * various internal things.
+ */
+PostAmbleHeader(p)
+ register struct PostAmbleInfo *p;
+{
+ register int n;
+
+ PrevPagePointer = p->pai_PrevPagePointer;
+ Numerator = p->pai_Numerator;
+ Denominator = p->pai_Denominator;
+ DVIMag = p->pai_DVIMag;
+
+ /*
+ * Set the conversion factor. This must be done before using
+ * any fonts.
+ */
+ SetConversion(DPI, UserMag, Numerator, Denominator, DVIMag);
+
+ n = p->pai_DVIStackSize * sizeof *dvi_stack;
+ dvi_stack = (struct localstack *) malloc((unsigned) n);
+ if ((dvi_stackp = dvi_stack) == NULL)
+ GripeOutOfMemory(n, "DVI stack");
+}
+
+/* Handle one of the font definitions from the DVI postamble. */
+PostAmbleFontDef(p)
+ register struct PostAmbleFont *p;
+{
+ register struct fontinfo *fi;
+ register struct font *f;
+ register char *s;
+ char *fname;
+ int def = S_CREATE | S_EXCL;
+
+ fi = (struct fontinfo *) SSearch(FontFinder, p->paf_DVIFontIndex,
+ &def);
+ if (fi == NULL) {
+ if (def & S_COLL)
+ GripeFontAlreadyDefined(p->paf_DVIFontIndex);
+ else
+ error(1, 0, "can't stash font %ld (out of memory?)",
+ p->paf_DVIFontIndex);
+ /*NOTREACHED*/
+ }
+ if (NextFamilyNumber == MaxImFamily)
+ error(0, 0, "\
+WARNING: out of Imagen font family indicies;\n\
+\toutput will probably resemble freshly scrambled eggs.");
+ fi->family = NextFamilyNumber++;
+ f = GetFont(p->paf_name, p->paf_DVIMag, p->paf_DVIDesignSize,
+ PrintEngine, &fname);
+ if ((fi->f = f) == NULL) {
+ GripeCannotGetFont(p->paf_name, p->paf_DVIMag,
+ p->paf_DVIDesignSize, PrintEngine, fname);
+ FontErrors++;
+ return;
+ }
+ if (Debug) {
+ (void) fprintf(stderr, "[%s -> %s]\n",
+ Font_TeXName(f), fname);
+ (void) fflush(stderr);
+ }
+ /* match checksums, if not zero */
+ if (p->paf_DVIChecksum && f->f_checksum &&
+ p->paf_DVIChecksum != f->f_checksum)
+ GripeDifferentChecksums(fname, p->paf_DVIChecksum,
+ f->f_checksum);
+
+ fi->pspace = p->paf_DVIMag / 6; /* a three-unit "thin space" */
+ fi->nspace = -4 * fi->pspace;
+ fi->vspace = 5 * fi->pspace;
+}
+
+/* Read the postamble. */
+ReadPostAmble()
+{
+
+ if ((FontFinder = SCreate(sizeof(struct fontinfo))) == 0)
+ error(1, 0, "can't create FontFinder (out of memory?)");
+ ScanPostAmble(stdin, PostAmbleHeader, PostAmbleFontDef);
+ if (FontErrors)
+ GripeMissingFontsPreventOutput(FontErrors);
+}
+
+/* Read the preamble and do a few sanity checks */
+ReadPreAmble()
+{
+ register int n;
+
+ rewind(stdin);
+ if (GetByte(stdin) != Sign8(DVI_PRE))
+ GripeMissingOp("PRE");
+ if (GetByte(stdin) != Sign8(DVI_VERSION))
+ GripeMismatchedValue("version numbers");
+ if (GetLong(stdin) != Numerator)
+ GripeMismatchedValue("numerator");
+ if (GetLong(stdin) != Denominator)
+ GripeMismatchedValue("denominator");
+ if (GetLong(stdin) != DVIMag)
+ GripeMismatchedValue("\\magfactor");
+ n = UnSign8(GetByte(stdin));
+ while (--n >= 0)
+ (void) GetByte(stdin);
+}
+
+main(argc, argv)
+ int argc;
+ register char **argv;
+{
+ register int c;
+ char *inname;
+
+ setbuf(stderr, serrbuf);
+
+ ProgName = *argv;
+ UserMag = 1000;
+ MaxDrift = DefaultMaxDrift;
+ DPI = DefaultDPI;
+ inname = "stdin";
+ PrintEngine = "canon";
+
+ while ((c = getopt(argc, argv, "d:e:lm:pr:sDX:Y:")) != EOF) {
+ switch (c) {
+
+ case 'd': /* max drift value */
+ MaxDrift = atoi(optarg);
+ break;
+
+ case 'e': /* engine */
+ PrintEngine = optarg;
+ break;
+
+ case 'l': /* landscape mode */
+ LFlag++;
+ break;
+
+ case 'm': /* magnification */
+ UserMag = atoi(optarg);
+ break;
+
+ case 'p': /* no page reversal */
+ PFlag++;
+ break;
+
+ case 'r': /* resolution */
+ DPI = atoi(optarg);
+ break;
+
+ case 's': /* silent */
+ SFlag++;
+ break;
+
+ case 'D':
+ Debug++;
+ break;
+
+ case 'X': /* x offset, in 1/10 inch increments */
+ XOffset = atoi(optarg);
+ break;
+
+ case 'Y': /* y offset */
+ YOffset = atoi(optarg);
+ break;
+
+ case '?':
+ (void) fprintf(stderr, "\
+Usage: %s [-d drift] [-l] [-m mag] [-s] [more options, see manual] [file]\n",
+ ProgName);
+ (void) fflush(stderr);
+ exit(1);
+ }
+ }
+ if (optind < argc)
+ if (freopen(inname = argv[optind], "r", stdin) == NULL)
+ error(1, errno, "can't open %s", inname);
+
+ /* Ensure that stdin is seekable */
+ if (MakeSeekable(stdin))
+ error(1, 0,
+ "unable to copy input to temp file (see the manual)");
+
+/* fontinit((char *) NULL); */
+
+ ReadPostAmble();
+
+ /* Margins -- needs work! */
+ HHMargin = DefaultLeftMargin + XOffset * DPI / 10;
+ VVMargin = DefaultTopMargin + YOffset * DPI / 10;
+
+ ReadPreAmble();
+ ExpectBOP++;
+ if (!PFlag)
+ (void) fseek(stdin, PrevPagePointer, 0);
+
+ /* All set! */
+ printf("@document(language imPRESS, name \"%s\")", inname);
+ if (LFlag) {
+ putchar(imP_SetHVSystem);
+ putchar(0x55); /* origin=ulc, h:v=90, h:x=90 */
+ putchar(imP_SetAdvDirs);
+ putchar(0); /* main=0 (degrees), secondary=90 */
+ }
+
+ /*
+ * If the first command in the DVI file involves motion, we will need
+ * to compare it to the current font `space' parameter; so start with
+ * a fake current font of all zeros.
+ */
+ CurrentFont = &NoFont;
+ ReadDVIFile();
+ if (!SFlag) {
+ (void) fprintf(stderr, "\n");
+ (void) fflush(stderr);
+ }
+ putchar(imP_EOF);
+
+ exit(0);
+}
+
+/*
+ * Skip a font definition (since we are using those from the postamble)
+ */
+/*ARGSUSED*/
+SkipFontDef(font)
+ i32 font;
+{
+ register int i;
+
+ (void) GetLong(stdin);
+ (void) GetLong(stdin);
+ (void) GetLong(stdin);
+ i = UnSign8(GetByte(stdin)) + UnSign8(GetByte(stdin));
+ while (--i >= 0)
+ (void) GetByte(stdin);
+}
+
+/*
+ * Perform a \special - right now ignore all of them
+ */
+DoSpecial(len)
+ i32 len; /* length of the \special string */
+{
+
+ error(0, 0, "warning: ignoring \\special");
+ (void) fseek(stdin, (long) len, 1);
+}
+
+/*
+ * Draw a rule at the current (hh,vv) position. There are two 4 byte
+ * parameters. The first is the height of the rule, and the second is the
+ * width. (hh,vv) is the lower left corner of the rule.
+ */
+SetRule(advance)
+ int advance;
+{
+ register i32 h, w, rw;
+
+ fGetLong(stdin, h);
+ fGetLong(stdin, rw);
+
+ h = ConvRule(h);
+ w = ConvRule(rw);
+
+ /* put the rule out */
+ if (ImHH != hh || ImVV != vv)
+ ImSetPosition(hh, vv);
+ putchar(imP_Rule);
+ putword(w);
+ putword(h);
+ putword(-h + 1);
+ if (advance) {
+ hh += w;
+ dvi_h += rw;
+ w = fromSP(dvi_h);
+ FIXDRIFT(hh, w);
+ }
+}
+
+/* if anyone ever uses character codes > 127, this driver will need work */
+char chartoobig[] = "Warning: character code %d too big for Imagen!";
+
+/*
+ * This rather large routine reads the DVI file and calls on other routines
+ * to do anything moderately difficult (except put characters: there is
+ * some ugly code with `goto's which makes things faster).
+ */
+
+ReadDVIFile()
+{
+ register int c;
+ register struct glyph *g;
+ register struct font *f;
+ register i32 p;
+ int advance;
+
+ ImFamily = -1; /* force imP_SetFamily command */
+
+ /*
+ * Only way out is via "return" statement. I had a `for (;;)' here,
+ * but everything crawled off the right.
+ */
+loop:
+ /*
+ * Get the DVI byte, and switch on its parameter length and type.
+ * Note that getchar() returns unsigned values.
+ */
+ c = getchar();
+
+ /*
+ * Handling characters (the most common case) early makes the
+ * program run a bit faster.
+ */
+ if (DVI_IsChar(c)) {
+ advance = 1;
+do_char:
+ f = CurrentFont->f;
+ g = GLYPH(f, c);
+ if (!GVALID(g)) {
+ error(0, 0, "there is no character %d in %s",
+ c, f->f_path);
+ goto loop;
+ }
+ if ((g->g_flags & GF_LOADED) == 0)
+ DownLoadGlyph(c, g);
+ if (HASRASTER(g)) { /* workaround for Imagen bug */
+ /* BEGIN INLINE EXPANSION OF ImSetPosition */
+ if (ImHH != hh) {
+ if (ImHH == hh - 1)
+ putchar(imP_Forw);
+ else if (ImHH == hh + 1)
+ putchar(imP_Backw);
+ else {
+ putchar(imP_SetHAbs);
+ putword(hh);
+ }
+ ImHH = hh;
+ }
+ if (ImVV != vv) {
+ putchar(imP_SetVAbs);
+ putword(vv);
+ ImVV = vv;
+ }
+ /* END INLINE EXPANSION OF ImSetPosition */
+ if (ImFamily != CurrentFont->family) {
+ putchar(imP_SetFamily);
+ putchar(CurrentFont->family);
+ ImFamily = CurrentFont->family;
+ }
+ putchar(c);
+ ImHH += g->g_pixwidth;
+ }
+ if (advance) {
+ hh += g->g_pixwidth;
+ dvi_h += g->g_tfmwidth;
+ p = fromSP(dvi_h);
+ FIXDRIFT(hh, p);
+ }
+ goto loop;
+ }
+
+ switch (DVI_OpLen(c)) {
+
+ case DPL_NONE:
+ break;
+
+ case DPL_SGN1:
+ p = getchar();
+ p = Sign8(p);
+ break;
+
+ case DPL_SGN2:
+ fGetWord(stdin, p);
+ p = Sign16(p);
+ break;
+
+ case DPL_SGN3:
+ fGet3Byte(stdin, p);
+ p = Sign24(p);
+ break;
+
+ case DPL_SGN4:
+ fGetLong(stdin, p);
+ break;
+
+ case DPL_UNS1:
+ p = UnSign8(getchar());
+ break;
+
+ case DPL_UNS2:
+ fGetWord(stdin, p);
+ p = UnSign16(p);
+ break;
+
+ case DPL_UNS3:
+ fGet3Byte(stdin, p);
+ p = UnSign24(p);
+ break;
+
+ default:
+ panic("DVI_OpLen(%d) = %d", c, DVI_OpLen(c));
+ /* NOTREACHED */
+ }
+
+ switch (DVI_DT(c)) {
+
+ case DT_SET:
+ advance = 1;
+ c = p;
+ if (c > 127)
+ error(0, 0, chartoobig, c);
+ goto do_char;
+
+ case DT_PUT:
+ advance = 0;
+ c = p;
+ if (c > 127)
+ error(0, 0, chartoobig, c);
+ goto do_char;
+
+ case DT_SETRULE:
+ SetRule(1);
+ break;
+
+ case DT_PUTRULE:
+ SetRule(0);
+ break;
+
+ case DT_NOP:
+ break;
+
+ case DT_BOP:
+ BeginPage();
+ break;
+
+ case DT_EOP:
+ EndPage();
+ if (!PFlag && PrevPagePointer == -1)
+ return; /* was first page: done */
+ break;
+
+ case DT_PUSH:
+ dvi_stackp->stack_hh = hh;
+ dvi_stackp->stack_vv = vv;
+ dvi_stackp->stack_dvi = dvi_current;
+ dvi_stackp++;
+ break;
+
+ case DT_POP:
+ dvi_stackp--;
+ hh = dvi_stackp->stack_hh;
+ vv = dvi_stackp->stack_vv;
+ dvi_current = dvi_stackp->stack_dvi;
+ break;
+
+ case DT_W0: /* there should be a way to make these pretty */
+ p = dvi_w;
+ goto move_right;
+
+ case DT_W:
+ dvi_w = p;
+ goto move_right;
+
+ case DT_X0:
+ p = dvi_x;
+ goto move_right;
+
+ case DT_X:
+ dvi_x = p;
+ goto move_right;
+
+ case DT_RIGHT:
+move_right:
+ dvi_h += p;
+ /*
+ * DVItype tells us that we must round motions in this way:
+ * `When the horizontal motion is small, like a kern, hh
+ * changes by rounding the kern; but when the motion is
+ * large, hh changes by rounding the true position so that
+ * accumulated rounding errors disappear.'
+ */
+ if (p >= CurrentFont->pspace || p <= CurrentFont->nspace)
+ hh = fromSP(dvi_h);
+ else {
+ hh += fromSP(p);
+ p = fromSP(dvi_h);
+ FIXDRIFT(hh, p);
+ }
+ break;
+
+ case DT_Y0:
+ p = dvi_y;
+ goto move_down;
+
+ case DT_Y:
+ dvi_y = p;
+ goto move_down;
+
+ case DT_Z0:
+ p = dvi_z;
+ goto move_down;
+
+ case DT_Z:
+ dvi_z = p;
+ goto move_down;
+
+ case DT_DOWN:
+move_down:
+ dvi_v += p;
+ /*
+ * `Vertical motion is done similarly, but with the threshold
+ * between ``small'' and ``large'' increased by a factor of
+ * 5. The idea is to make fractions like $1\over2$ round
+ * consistently, but to absorb accumulated rounding errors in
+ * the baseline-skip moves.'
+ */
+ if (ABS(p) >= CurrentFont->vspace)
+ vv = fromSP(dvi_v);
+ else {
+ vv += fromSP(p);
+ p = fromSP(dvi_v);
+ FIXDRIFT(vv, p);
+ }
+ break;
+
+ case DT_FNTNUM:
+ SelectFont((i32) (c - DVI_FNTNUM0));
+ break;
+
+ case DT_FNT:
+ SelectFont(p);
+ break;
+
+ case DT_XXX:
+ DoSpecial(p);
+ break;
+
+ case DT_FNTDEF:
+ SkipFontDef(p);
+ break;
+
+ case DT_PRE:
+ GripeUnexpectedOp("PRE");
+ /* NOTREACHED */
+
+ case DT_POST:
+ if (PFlag)
+ return;
+ GripeUnexpectedOp("POST");
+ /* NOTREACHED */
+
+ case DT_POSTPOST:
+ GripeUnexpectedOp("POSTPOST");
+ /* NOTREACHED */
+
+ case DT_UNDEF:
+ GripeUndefinedOp(c);
+ /* NOTREACHED */
+
+ default:
+ panic("DVI_DT(%d) = %d", c, DVI_DT(c));
+ /* NOTREACHED */
+ }
+ goto loop;
+}
+
+/*
+ * Download the character c/g in the current font.
+ */
+DownLoadGlyph(c, g)
+ int c;
+ register struct glyph *g;
+{
+ register char *p;
+ register int i, j, w;
+
+ g->g_pixwidth = fromSP(g->g_tfmwidth);
+ g->g_flags |= GF_LOADED;
+ if (!HASRASTER(g)) /* never load dull glyphs */
+ return;
+
+ if (!LFlag) {
+ w = 0;
+ p = RASTER(g, CurrentFont->f, ROT_NORM);
+ } else {
+ w = 1 << 14;
+ p = RASTER(g, CurrentFont->f, ROT_RIGHT);
+ }
+
+ w |= (CurrentFont->family << 7) | c;
+
+ /* Define the character */
+ putchar(imP_DefGlyph); /* a.k.a. BGLY */
+ putword(w); /* rotation, family, member */
+ putword(g->g_pixwidth); /* advance */
+ putword(g->g_width); /* width */
+ putword(g->g_xorigin); /* left offset */
+ putword(g->g_height); /* height */
+ putword(g->g_yorigin); /* top-offset */
+
+ /*
+ * Now put out the bitmap.
+ */
+ w = (g->g_width + 7) >> 3;
+ for (i = g->g_height; --i >= 0;)
+ for (j = w; --j >= 0;)
+ (void) putchar(*p++);
+
+ if (g->g_raster) { /* XXX */
+ free(g->g_raster);
+ g->g_raster = NULL;
+ }
+
+}
+
+/*
+ * Set the Imagen's h & v positions. It is currently at ImHH, ImVV.
+ */
+ImSetPosition(h, v)
+ register int h, v;
+{
+
+ if (ImHH != h) {
+ if (ImHH == h - 1)
+ putchar(imP_Forw);
+ else if (ImHH == h + 1)
+ putchar(imP_Backw);
+ else {
+ putchar(imP_SetHAbs);
+ putword(h);
+ }
+ ImHH = h;
+ }
+ if (ImVV != v) {
+ putchar(imP_SetVAbs);
+ putword(v);
+ ImVV = v;
+ }
+}
diff --git a/dviware/umddvi/dev/interpress.h b/dviware/umddvi/dev/interpress.h
new file mode 100644
index 0000000000..e116267d88
--- /dev/null
+++ b/dviware/umddvi/dev/interpress.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 1987 University of Maryland Department of Computer Science.
+ * All rights reserved. Permission to copy for any purpose is hereby granted
+ * so long as this copyright notice remains intact.
+ */
+
+/* you are assumed to have read the Xerox Interpress documents... I am
+ not going to attempt to explain what these mean. */
+
+/* sequences */
+#define SeqString 1
+#define SeqInteger 2
+#define SeqRational 4
+#define SeqIdentifier 5
+#define SeqComment 6
+#define SeqContinued 7
+#define SeqLargeVec 8
+#define SeqPackedPixVec 9
+#define SeqComprPixVec 10
+#define SeqAdapPixVec 12
+
+/* operators */
+
+/* pseudo ops */
+#define IPBegin 102
+#define IPEnd 103
+#define IPPageInstr 105
+#define IPLB 106 /* { */
+#define IPRB 107 /* } */
diff --git a/dviware/umddvi/dev/ip.c b/dviware/umddvi/dev/ip.c
new file mode 100644
index 0000000000..a97ffbd7ad
--- /dev/null
+++ b/dviware/umddvi/dev/ip.c
@@ -0,0 +1,696 @@
+/*
+ * Copyright (c) 1987 University of Maryland Department of Computer Science.
+ * All rights reserved. Permission to copy for any purpose is hereby granted
+ * so long as this copyright notice remains intact.
+ */
+
+#ifndef lint
+static char rcsid[] = "$Header$";
+#endif
+
+/*
+ * DVI to Interpress driver
+ *
+ * Reads DVI version 2 files and converts to Xerox Interpress format.
+ */
+
+#include "types.h"
+#include "dvi.h"
+#include "dviclass.h"
+#include "dvicodes.h"
+#include "fio.h"
+#include "pxl.h"
+#include "search.h"
+#include "interpress.h"
+#include <stdio.h>
+
+char *ProgName;
+extern int errno;
+extern char *optarg;
+extern int optind;
+
+/* Globals */
+char serrbuf[BUFSIZ]; /* buffer for stderr */
+
+/* DVI style arithmetic: when moving horizontally by a DVI distance >=
+ ``space'', we are to recompute horizontal position from DVI units;
+ otherwise, we are to use device resolution units to keep track of
+ horizontal position. A similar scheme must be used for vertical
+ positioning. */
+struct fontinfo {
+ struct pxltail *px; /* pxl file info */
+ int ipfont; /* Interpress font index */
+ i32 pspace; /* boundary between ``small'' & ``large''
+ spaces (for positive horizontal motion) */
+ i32 nspace; /* -4 * pspace, for negative motion */
+ i32 vspace; /* 5 * pspace, for vertical motion */
+ int cwidth[128]; /* width (in DEVs) of each char */
+ char cload[128]; /* flag for ``char loaded into Imagen'' */
+};
+
+int MaxDrift; /* the maximum allowable difference between
+ hh and SPtoDEV(dvi_h), and vv and.... */
+
+struct search *FontFinder; /* search table for DVI index => fontinfo */
+struct fontinfo *CurrentFont; /* the current font (if any) */
+int NextIPFont; /* during font definition, the next ip font
+ index */
+int FontErrors; /* true => error(s) during font definition */
+
+char *TeXfonts; /* getenv("TEXFONTS") */
+
+int ExpectBOP; /* true => BOP ok */
+int ExpectEOP; /* true => EOP ok */
+
+int DPI; /* -d => device resolution (dots/inch) */
+/* int LFlag; /* -l => landscape mode (eventually...) */
+int SFlag; /* -s => silent (no page #s) */
+int XFlag; /* -x => debug (undocumented) */
+
+int hh; /* current horizontal position, in DEVs */
+int vv; /* current vertical position, in DEVs */
+
+/* Similar to dvi_stack, but includes ``hh'' and ``vv'', which are usually
+ but not always the same as SPtoDEV(h) and SPtoDEV(v): */
+struct localstack {
+ int stack_hh;
+ int stack_vv;
+ struct dvi_stack stack_dvi;
+};
+
+struct localstack *dvi_stack; /* base of stack */
+struct localstack *dvi_stackp; /* current place in stack */
+
+int HHMargin; /* horizontal margin (in DEVs) */
+int VVMargin; /* vertical margin (in DEVs) */
+
+int Numerator; /* numerator from DVI file */
+int Denominator; /* denominator from DVI file */
+int DVIMag; /* magnification from DVI file */
+
+double UserMag; /* user specified magnification */
+double GlobalMag; /* overall magnification (UserMag*DVIMag) */
+double conv; /* conversion factor for magnified DVI units */
+
+double OneHalf = 0.5; /* .5, so compiler can generate constant only
+ once */
+double Zero = 0.0; /* likewise */
+double _d_; /* Used to store intermediate results. The
+ compiler should do this for us, but it's
+ too stupid. */
+
+int IpHH; /* Interpress horizontal position */
+int IpVV; /* Interpress vertical position */
+int IpFont; /* Interpress current-font number */
+
+char *getenv (), *malloc ();
+
+/* Absolute value */
+#define ABS(n) ((n) >= 0 ? (n) : -(n))
+
+/* Round a floating point number to integer */
+#define ROUND(f) ((int) (_d_ = (f), \
+ _d_ < Zero ? _d_ - OneHalf : _d_ + OneHalf)
+
+/* Convert to floating point */
+#define FLOAT(i) ((double) (i))
+
+/* Convert a value in sp's to dev's, and vice versa */
+#define SPtoDEV(sp) (ROUND ((sp) * conv))
+#define DEVtoSP(dev) (ROUND ((dev) / conv))
+
+/* Put a two-byte (word) value */
+#define putword(w) (putchar ((w) >> 8), putchar (w))
+
+/* Correct devpos (the virtual device position) to be within MaxDrift pixels
+ of dvipos (the virtual DVI position). */
+#define FIXDRIFT(devpos, dvipos) \
+ if (ABS ((devpos) - (dvipos)) <= MaxDrift); \
+ else \
+ if ((devpos) < (dvipos)) \
+ (devpos) = (dvipos) - MaxDrift; \
+ else \
+ (devpos) = (dvipos) + MaxDrift
+
+/* Compute the DEV widths of the characters in the given font */
+ComputeCWidths (fi)
+struct fontinfo *fi;
+{
+ register int i;
+ register struct chinfo *ch;
+ register int *cw;
+
+ ch = fi -> px -> px_info;
+ cw = fi -> cwidth;
+ i = 128;
+ while (--i >= 0) {
+ *cw++ = SPtoDEV (ch -> ch_TFMwidth);
+ ch++;
+ }
+}
+
+SelectFont (n)
+int n;
+{
+ register struct fontinfo *f;
+
+ CurrentFont = f = FindFont ((i32) n, (struct fontinfo *) 0);
+ CurrentFontIndex = f - FontInfo;
+}
+
+/* Start a page (process a DVI_BOP) */
+/* NOTE: I'm depending on getting a BOP before any characters or rules on a
+ page! */
+BeginPage () {
+ register int *i;
+ static int count[10]; /* the 10 counters */
+ static int beenhere;
+
+ if (!ExpectBOP)
+ error (1, 0, "unexpected BOP");
+ if (beenhere) {
+ if (!SFlag)
+ putc (' ', stderr);
+ }
+ else
+ beenhere++;
+
+ dvi_stackp = dvi_stack;
+
+ ExpectBOP = 0;
+ ExpectEOP++; /* set the new "expect" state */
+
+ for (i = count; i < &count[sizeof count / sizeof *count]; i++)
+ fGetLong (stdin, *i);
+ fGetLong (stdin, i); /* previous page pointer */
+
+ if (!SFlag) {
+ fprintf (stderr, "[%d", count[0]);
+ (void) fflush (stderr);
+ }
+
+ putchar (imP_Page); /* XXX */
+ IpHH = 0;
+ IpVV = 0;
+
+ hh = HHMargin;
+ vv = VVMargin;
+ dvi_h = DEVtoSP (hh);
+ dvi_v = DEVtoSP (vv);
+ dvi_w = 0;
+ dvi_x = 0;
+ dvi_y = 0;
+ dvi_z = 0;
+}
+
+/* End a page (process a DVI_EOP) */
+EndPage () {
+ if (!ExpectEOP)
+ error (1, 0, "unexpected EOP");
+
+ if (!SFlag) {
+ putc (']', stderr);
+ (void) fflush (stderr);
+ }
+
+ ExpectEOP = 0;
+ ExpectBOP++;
+
+ putchar (imP_EndPage); /* XXX */
+}
+
+/* Begin XXX */
+/* Store the relevant information from the DVI postamble, and set up
+ various internal things. */
+PosotAmbleHeader (p)
+register struct PostAmbleInfo *p; {
+ register int n;
+
+ PrevPagePointer = p -> pai_PrevPagePointer;
+ Numerator = p -> pai_Numerator;
+ Denominator = p -> pai_Denominator;
+ DVIMag = p -> pai_DVIMag;
+
+ /* Here we sneakily correct for the actual device resolution, so that we can
+ pretend that it's 200 dots per inch. */
+ UserMag *= FLOAT (DPI) / 200.0;
+
+ GlobalMag = DMagFactor (DVIMag) * UserMag;
+
+ /* The conversion factor is figured as follows: there are exactly n/d DVI
+ units per decimicron, and 254000 decimicrons per inch, and 200 pixels per
+ inch. Then we have to adjust this by the stated magnification. */
+ conv = (Numerator / 254000.0) * (200.0 / Denominator) * GlobalMag;
+
+ n = p -> pai_DVIStackSize * sizeof *dvi_stack;
+ dvi_stack = (struct localstack *) malloc ((unsigned) n);
+ if ((dvi_stackp = dvi_stack) == 0)
+ error (1, errno, "can't allocate %d DVI stack bytes", n);
+ IntGlobalMag = ROUND (GlobalMag * 1000.0);
+}
+
+/* Handle one of the font definitions from the DVI postamble. */
+PostAmbleFontDef (p)
+register struct PostAmbleFont *p; {
+ register struct fontinfo *f;
+ register char *s;
+ int def = S_CREATE | S_EXCL;
+
+ f = (struct fontinfo *) SSearch (FontFinder, p -> paf_DVIFontIndex, &def);
+ if (f == 0)
+ if (def & S_COLL)
+ error (1, 0, "font %d already defined", p -> paf_DVIFontIndex);
+ else
+ error (1, 0, "can't stash font %d (out of memory?)",
+ p -> paf_DVIFontIndex);
+
+ f -> ipfont = NextIPFont++;
+ s = GenPXLFileName (p -> paf_name, p -> paf_DVIMag,
+ p -> paf_DVIDesignSize, IntGlobalMag, TeXfonts);
+ if ((f -> px = ReadPXLFile (s, 1)) == 0) {
+ error (0, errno, "can't find font \"%s\"", s);
+ FontErrors++;
+ return;
+ }
+ if (p -> paf_DVIChecksum != f -> px -> px_checksum)
+ error (0, 0, "\
+WARNING: width tables and raster tables have different\n\
+\tchecksums for font \"%s\"\n\
+\tPlease notify your TeX maintainer\n\
+\t(TFM checksum = 0%o, PXL checksum = 0%o)",
+ s, dvi_checksum, f -> px -> px_checksum);
+
+ ScaleTFMWidths (f -> px, dvi_mag);
+ ComputeCWidths (f);
+ f -> pspace = p -> paf_DVIMag / 6; /* a three-unit ``thin space'' */
+ f -> nspace = -4 * f -> pspace;
+ f -> vspace = 5 * f -> pspace;
+}
+
+/* Read the postamble. */
+ReadPostAmble () {
+ static char s[2] = { 's', 0 };
+
+ if ((FontFinder = SCreate (sizeof (struct fontinfo))) == 0)
+ error (1, 0, "can't create FontFinder (out of memory?)");
+ ScanPostAmble (stdin, PostAmbleHeader, PostAmbleFontDef);
+ if (FontErrors)
+ error (1, 0, "missing font%s prevent%s output (sorry)",
+ FontErrors > 1 ? s : &s[1], FontErrors == 1 ? s : &s[1]);
+}
+/* End XXX */
+
+/* Read the preamble and do a few sanity checks */
+ReadPreAmble () {
+ register int n;
+
+ rewind (stdin);
+ if (GetByte (stdin) != Sign8 (DVI_PRE))
+ error (1, 0, "missing PRE");
+ if (GetByte (stdin) != Sign8 (DVI_VERSION))
+ error (1, 0, "mismatched version numbers");
+ if (GetLong (stdin) != Numerator)
+ error (1, 0, "mismatched numerator");
+ if (GetLong (stdin) != Denominator)
+ error (1, 0, "mismatched denominator");
+ if (GetLong (stdin) != DVIMag)
+ error (1, 0, "mismatched \\magfactor");
+ n = UnSign8 (GetByte (stdin));
+ while (--n >= 0)
+ (void) GetByte (stdin);
+}
+
+main (argc, argv)
+int argc;
+register char **argv;
+{
+ register int c;
+ char *inname;
+
+ setbuf (stderr, serrbuf);
+
+ ProgName = *argv;
+ UserMag = 1.0;
+ MaxDrift = DefaultMaxDrift;
+ DPI = DefaultDPI;
+ inname = "stdin";
+
+ while ((c = getopt (argc, argv, "d:m:r:s")) != EOF) {
+ switch (c) {
+ case 'd': /* max drift value */
+ MaxDrift = atoi (optarg);
+ break;
+/* case 'l': /* landscape mode */
+/* LFlag++; */
+/* break; */
+ case 'm': /* magnification */
+ UserMag = DMagFactor (atoi (optarg));
+ break;
+ case 'r': /* resolution */
+ DPI = atoi (optarg);
+ break;
+ case 's': /* silent */
+ SFlag++;
+ break;
+ case 'x': /* enable debugging */
+ XFlag++;
+ break;
+ case '?':
+ fprintf (stderr, "\
+Usage: %s [-d drift] [-m mag] [-s] [-r resolution] [file]\n",
+ ProgName);
+ (void) fflush (stderr);
+ exit (1);
+ }
+ }
+ if (optind < argc)
+ if (freopen (inname = argv[optind], "r", stdin) == NULL)
+ error (1, errno, "can't open %s", inname);
+
+ /* ReadPostAmble does an fseek which, if performed on a tty, tends to make
+ the shell log one out, thus the following kludge: */
+ if (isatty (fileno (stdin)))
+ error (1, 0, "input from ttys is expressly forbidden!");
+
+ TeXfonts = getenv ("TEXFONTS");
+ if (TeXfonts == 0)
+ TeXfonts = "";
+
+ ReadPostAmble ();
+
+ /* Margins -- needs work! */
+ HHMargin = DefaultLeftMargin;/* XXX */
+ VVMargin = DefaultTopMargin;/* XXX */
+
+ ReadPreAmble ();
+ ExpectBOP++;
+ (void) fseek (stdin, PrevPagePointer, 0);
+
+ /* All set! */
+ printf ("Interpress/Xerox/2.1 ");
+ PutInstructionsBody (inname);
+ PutPreamble ();
+ ReadDVIFile ();
+ /* EOF is implicit (?) */
+
+ exit (0);
+}
+
+/* Skip a font definition (since we are using those from the postamble) */
+/* ARGSUSED */
+SkipFontDef (font)
+int font;
+{
+ register int i;
+
+ (void) GetLong (stdin);
+ (void) GetLong (stdin);
+ (void) GetLong (stdin);
+ i = UnSign8 (GetByte (stdin)) + UnSign8 (GetByte (stdin));
+ while (--i >= 0)
+ (void) GetByte (stdin);
+}
+
+/* Perform a \special - right now ignore all of them */
+DoSpecial (len)
+int len; /* length of the \special string */
+{
+ error (0, 0, "warning: ignoring \\special");
+ (void) fseek (stdin, (long) len, 1);
+}
+
+/* Draw a rule at the current (hh,vv) position. There are two 4 byte
+ parameters. The first is the height of the rule, and the second is the
+ width. (hh,vv) is the lower left corner of the rule. */
+SetRule (advance)
+int advance;
+{
+ i32 rwidth, /* rule width from DVI file */
+ rheight; /* rule height from DVI file */
+ register int h,
+ w;
+
+ fGetLong (stdin, rheight);
+ fGetLong (stdin, rwidth);
+
+ /* Rule sizes must be computed in this manner: */
+ h = conv * rheight;
+ if (FLOAT (h) < (conv * rheight))
+ h++;
+ w = conv * rwidth;
+ if (FLOAT (w) < (conv * rwidth))
+ w++;
+
+ /* put the rule out */
+ if (IpHH != hh || IpVV != vv)
+ SetPosition (hh, vv);
+ putchar (imP_Rule); /* XXX */
+ putword (w); /* XXX */
+ putword (h); /* XXX */
+ putword (-h + 1); /* XXX */
+ if (advance) {
+ hh += w;
+ dvi_h += rwidth;
+ if (ABS (hh - (w = SPtoDEV (dvi_h))) > MaxDrift)
+ hh = w + (hh < w ? -MaxDrift : MaxDrift);
+ }
+}
+
+/* FIXME (kerns, etc, etc) */
+/* resume XXX */
+/* This rather large routine reads the DVI file and calls on other routines
+ to do anything moderately difficult (except put characters: there is
+ a bunch of ugly code with ``goto''s which makes things much faster) */
+ReadDVIFile () {
+ register int c,
+ p;
+ int advance;
+
+ IpFamily = -1;
+
+ /* Only way out is via "return" statement */
+ for (;;) {
+ /* Get the DVI byte, and if it's a character, put it */
+/* c = UnSign8 (getchar ()); */
+ c = getchar (); /* getchar() returns unsigned values */
+
+ if (DVI_IsChar (c)) { /* I know, ugly, but ... no function call
+ overhead this way */
+ register struct chinfo *ch;
+ register struct fontinfo *cf;
+
+set:
+ advance = 1;
+put:
+ cf = CurrentFont;
+ ch = &cf -> px -> px_info[c];
+ if (ch -> ch_width == 0)
+ goto ignore; /* not a real character, just advance */
+ /* BEGIN INLINE EXPANSION OF IpSetPosition (the things we do in
+ the name of efficency! ;-) ) */
+ if (ImHH != hh) {
+ if (ImHH == hh - 1)
+ putchar (imP_Forw);
+ else if (ImHH == hh + 1)
+ putchar (imP_Backw);
+ else {
+ putchar (imP_SetHAbs);
+ putword (hh);
+ }
+ ImHH = hh;
+ }
+ if (ImVV != vv) {
+ putchar (imP_SetVAbs);
+ putword (vv);
+ ImVV = vv;
+ }
+ /* END INLINE EXPANSION OF ImSetPosition */
+ if (ImFamily != CurrentFontIndex) {
+ putchar (imP_SetFamily);
+ putchar (CurrentFontIndex);
+ ImFamily = CurrentFontIndex;
+ }
+ putchar (c);
+ ImHH += cf -> cwidth[c];
+ignore:
+ if (advance) {
+#ifdef DEBUG
+ if (XFlag) {
+ fprintf (stderr, "setchar%d h:=%d+%d=%d, hh:=%d\n",
+ c, dvi_h - DEVtoSP (HHMargin), ch->ch_TFMwidth,
+ dvi_h - DEVtoSP (HHMargin) + ch->ch_TFMwidth,
+ hh + CurrentFont->cwidth[c] - HHMargin);
+ fflush (stderr);
+ }
+#endif DEBUG
+ hh += cf -> cwidth[c];
+ dvi_h += ch -> ch_TFMwidth;
+ p = SPtoDEV (dvi_h);
+ FIXDRIFT (hh, p);
+ }
+ continue;
+ }
+ /* Wasn't a character, maybe a font? */
+ if (DVI_IsFont (c)) {
+ SelectFont ((i32) (c - DVI_FNTNUM0));
+ continue;
+ }
+ /* Wasn't a font, see if it's a generic one */
+ if (p = DVI_OpLen (c)) {
+ /* It's generic, get its parameter */
+ switch (p) {
+ case 1:
+ p = Sign8 (getchar ());
+ break;
+ case 2:
+ fGetWord (stdin, p);
+ p = Sign16 (p);
+ break;
+ case 3:
+ fGet3Byte (stdin, p);
+ p = Sign24 (p);
+ break;
+ case 4:
+ fGetLong (stdin, p);
+ break;
+ case 5:
+ p = UnSign8 (getchar ());
+ break;
+ case 6:
+ fGetWord (stdin, p);
+ p = UnSign16 (p);
+ break;
+ case 7:
+ fGet3Byte (stdin, p);
+ p = UnSign24 (p);
+ break;
+ }
+ /* Now that we have the parameter, perform the command */
+ switch (DVI_DT (c)) {
+ case DT_SET:
+ c = p;
+ goto set;
+ case DT_PUT:
+ c = p;
+ advance = 0;
+ goto put;
+ case DT_RIGHT:
+move_right:
+ dvi_h += p;
+ /* DVItype tells us that we must round motions in this way:
+ ``When the horizontal motion is small, like a kern, hh
+ changes by rounding the kern; but when the motion is
+ large, hh changes by rounding the true position so that
+ accumulated rounding errors disappear.'' */
+ if (p >= CurrentFont -> pspace ||
+ p <= CurrentFont -> nspace)
+ hh = SPtoDEV (dvi_h);
+ else {
+ hh += SPtoDEV (p);
+ p = SPtoDEV (dvi_h);
+ FIXDRIFT (hh, p);
+ }
+ break;
+ case DT_W:
+ dvi_w = p;
+ goto move_right;
+ case DT_X:
+ dvi_x = p;
+ goto move_right;
+ case DT_DOWN:
+move_down:
+ dvi_v += p;
+ /* ``Vertical motion is done similarly, but with the
+ threshold between ``small'' and ``large'' increased by a
+ factor of 5. The idea is to make fractions like $1\over2$
+ round consistently, but to absorb accumulated rounding
+ errors in the baeline-skip moves.'' */
+ if (ABS (p) >= CurrentFont -> vspace)
+ vv = SPtoDEV (dvi_v);
+ else {
+ vv += SPtoDEV (p);
+ p = SPtoDEV (dvi_v);
+ FIXDRIFT (vv, p);
+ }
+ break;
+ case DT_Y:
+ dvi_y = p;
+ goto move_down;
+ case DT_Z:
+ dvi_z = p;
+ goto move_down;
+ case DT_FNT:
+ SelectFont (p);
+ break;
+ case DT_XXX:
+ DoSpecial (p);
+ break;
+ case DT_FNTDEF:
+ SkipFontDef (p);
+ break;
+#ifdef PARANOID
+ default:
+ error (1, 0, "bad DVI_DT(%d): (%d)", c, DVI_DT (c));
+#endif PARANOID
+ }
+ continue;
+ }
+ /* Wasn't a char, wasn't a generic command, just pick it out from the
+ whole mess */
+ switch (c) {
+ case DVI_SETRULE:
+ SetRule (1);
+ break;
+ case DVI_PUTRULE:
+ SetRule (0);
+ break;
+ case DVI_NOP:
+ break;
+ case DVI_BOP:
+ BeginPage ();
+ break;
+ case DVI_EOP:
+ EndPage ();
+ if (PrevPagePointer == -1) {
+ if (!SFlag) {
+ fprintf (stderr, "\n");
+ (void) fflush (stderr);
+ }
+ return;
+ }
+ break;
+ case DVI_PUSH:
+ dvi_stackp -> stack_hh = hh;
+ dvi_stackp -> stack_vv = vv;
+ dvi_stackp -> stack_dvi = dvi_current;
+ dvi_stackp++;
+ break;
+ case DVI_POP:
+ dvi_stackp--;
+ hh = dvi_stackp -> stack_hh;
+ vv = dvi_stackp -> stack_vv;
+ dvi_current = dvi_stackp -> stack_dvi;
+ break;
+ case DVI_W0:
+ p = dvi_w;
+ goto move_right;
+ case DVI_X0:
+ p = dvi_x;
+ goto move_right;
+ case DVI_Y0:
+ p = dvi_y;
+ goto move_down;
+ case DVI_Z0:
+ p = dvi_z;
+ goto move_down;
+ case DVI_PRE:
+ error (1, 0, "unexpected PRE");
+ case DVI_POST: /* shouldn't get this, reading backwards */
+ error (1, 0, "unexpected POST");
+ case DVI_POSTPOST:
+ error (1, 0, "unexpected POSTPOST");
+ default:
+ error (1, 0, "undefined DVI opcode (%d)", c);
+ }
+ }
+}
diff --git a/dviware/umddvi/dev/iptex.sh b/dviware/umddvi/dev/iptex.sh
new file mode 100644
index 0000000000..919544ad2a
--- /dev/null
+++ b/dviware/umddvi/dev/iptex.sh
@@ -0,0 +1,61 @@
+#! /bin/sh
+#
+# print a dvi file on the imagen
+
+flags=
+cflag=-c
+# put default offset here: -X3 -Y-4 moves output .3in left, .4in up
+# from the usual 1" margin in both directions.
+offset=
+
+# eat arguments
+
+while [ $# -gt 0 ]
+do
+ case "$1" in
+ -c)
+ cflag=;;
+ -d|-m|-r|-X|-Y)
+ flags="$flags $1 $2"; shift;;
+ -)
+ break;;
+ -*)
+ flags="$flags $1";;
+ *)
+ break;;
+ esac
+ shift
+done
+
+if [ $# != 1 ]; then
+ echo "Usage: $0 [-c] [-l] [-s] [-m mag] [-d drift] [-r resol] filename" 2>&1
+ exit 1
+fi
+
+dvifile=$1
+if [ x$dvifile = x- ]; then
+ dvifile=
+else
+ # people insist that iptex should look for file.dvi first:
+ if [ -r $dvifile.dvi ]; then
+ dvifile=$dvifile.dvi
+ else
+ if [ ! -r $dvifile ]; then
+ echo "$0: cannot find $1 or $1.dvi" 1>&2
+ exit 1
+ fi
+ fi
+fi
+
+tmpfile=${TMPDIR-/tmp}/iptex$$
+if [ "$cflag" = -c ]; then
+ trap 'rm -f $tmpfile' 0 1 2 3 15
+ if imagen1 $offset $flags $dvifile > $tmpfile; then
+ ipr $tmpfile
+ else
+ echo "$0: output not spooled (use -c to force)" 1>&2
+ exit 1
+ fi
+else
+ imagen1 $offset $flags $dvifile | ipr
+fi
diff --git a/dviware/umddvi/dev/makefile b/dviware/umddvi/dev/makefile
new file mode 100644
index 0000000000..27202b1c59
--- /dev/null
+++ b/dviware/umddvi/dev/makefile
@@ -0,0 +1,143 @@
+#
+# Copyright (c) 1987 University of Maryland Department of Computer Science.
+# All rights reserved. Permission to copy for any purpose is hereby granted
+# so long as this copyright notice remains intact.
+#
+# $Header: Makefile,v 1.3 87/06/16 17:13:19 chris Exp $
+#
+# Makefile for device conversion programs
+#
+# You must run "make conf" to set up Makefile.local if you do not want
+# the default `all' configuration (see the file "conf.sh"). Remember to
+# use `make update'!
+DESTDIR=
+CFLAGS= -O -R -I../h
+MAKE= make
+
+# these are intended to be overridden by the definitions in ../Makefile
+# but just in case, they are here too
+BINDIR= ${DESTDIR}/usr/local/bin
+MANDIR= ${DESTDIR}/usr/local/man
+
+# Make options
+OPTS= BINDIR=${BINDIR} MANDIR=${MANDIR} DESTDIR=${DESTDIR} CC="${CC}" \
+ CFLAGS="${CFLAGS}" ${MFLAGS}
+
+SRCS= imagen1.c verser1.c verser2.c
+
+# First, the main entry used in the original Makefile.
+# It is also enabled by a `conf none'; this is just so that the
+# configurer will disable it in Makefile.local.
+# Whenever you run `make' afterward, this entry will run
+# make on your local Makefile.
+
+# conf none
+first:
+ @if [ -f Makefile.local ]; then :; else \
+ echo "You should run \`make conf' first!"; \
+ echo \
+"I will give you the default \`all' configuration for now."; \
+ sh conf.sh all; \
+ fi
+ @${MAKE} -f Makefile.local ${OPTS}
+# endconf none
+
+# In Makefile.local, this is the default (if you just say `make').
+# The `make' invocation will be commented out there.
+all:
+# conf none
+ @${MAKE} -f Makefile.local ${OPTS} $@
+# endconf none
+
+# Likewise, but for `make install'.
+install:
+# conf none
+ @${MAKE} -f Makefile.local ${OPTS} $@
+# endconf none
+
+# conf imagen
+# all: imagen1
+# install: inst-iptex inst-imagen1
+# endconf imagen
+
+# conf versatec
+# all: verser1 verser2
+# install: inst-dvipr inst-verser1 inst-verser2
+# endconf versatec
+
+# The rest of these are copied to Makefile.local, though many are
+# unused.
+conf:
+ @sh conf.sh
+ @echo "Remember to use \`make update' if you change the Makefile!"
+
+clean:
+ rm -f core *.o verser1 verser2 imagen1
+
+depend: ${SRCS}
+ cc -M ${CFLAGS} ${SRCS} |\
+ awk '{ if ($$1 != prev) { if (rec != "") print rec;\
+ rec = $$0; prev = $$1; }\
+ else { if (length(rec $$2) > 78) { print rec; rec = $$0; }\
+ else rec = rec " " $$2 } }\
+ END { print rec }' >makedep
+ echo '/^# DO NOT DELETE THIS LINE/+2,$$d' >eddep
+ echo '$$r makedep' >>eddep
+ echo 'w' >>eddep
+ cp Makefile Makefile.bak
+ ed - Makefile <eddep
+ rm eddep makedep
+ echo '# DEPENDENCIES MUST END AT END OF FILE' >>Makefile
+ echo '# IF YOU PUT STUFF HERE IT WILL GO AWAY' >>Makefile
+ echo '# see make depend above' >>Makefile
+ sh conf.sh update
+
+update:
+ @sh conf.sh update
+
+inst-dvipr:
+ install -c dvipr.sh ${BINDIR}/dvipr
+ install -c -m 444 ../man/dvipr.1 ${MANDIR}/man1/dvipr.1
+inst-verser1: verser1
+ install -s verser1 ${BINDIR}/verser1
+inst-verser2: verser2
+ install -s verser2 ${BINDIR}/verser2
+
+inst-iptex:
+ install -c iptex.sh ${BINDIR}/iptex
+ install -c -m 444 ../man/iptex.1 ${MANDIR}/man1/iptex.1
+inst-imagen1: imagen1
+ install -s imagen1 ${BINDIR}/imagen1
+
+lint: ${SRCS}
+ lint -hbxuL ../lib/llib-lib imagen1.c
+ lint -hbxuL ../lib/llib-lib verser1.c
+ lint -hbxuL ../lib/llib-lib verser2.c
+
+dist:
+ rm -f Makefile.bak Makefile.local Makefile.l.bak
+ sh conf.sh all
+
+imagen1: imagen1.o
+verser1: verser1.o
+verser2: verser2.o
+
+imagen1 verser1 verser2: ../lib/lib.a
+ ${CC} ${CFLAGS} -o $@ $@.o ../lib/lib.a
+
+# DO NOT DELETE THIS LINE -- make depend uses it
+
+imagen1.o: imagen1.c /usr/include/stdio.h ../h/types.h ../h/conv.h ../h/dvi.h
+imagen1.o: ../h/dviclass.h ../h/dvicodes.h ../h/fio.h ../h/font.h
+imagen1.o: ../h/postamble.h ../h/search.h ../h/imagen.h ../h/imPcodes.h
+verser1.o: verser1.c /usr/include/stdio.h ../h/types.h ../h/conv.h ../h/dvi.h
+verser1.o: ../h/dviclass.h ../h/dvicodes.h ../h/fio.h ../h/font.h
+verser1.o: ../h/postamble.h ../h/search.h ../h/verser.h
+verser2.o: verser2.c /usr/include/errno.h /usr/include/setjmp.h
+verser2.o: /usr/include/stdio.h /usr/include/sys/vcmd.h
+verser2.o: /usr/include/sys/ioctl.h /usr/include/sys/ttychars.h
+verser2.o: /usr/include/sys/ttydev.h ../h/types.h ../h/conv.h ../h/fio.h
+verser2.o: ../h/font.h ../h/verser.h
+# DEPENDENCIES MUST END AT END OF FILE
+# IF YOU PUT STUFF HERE IT WILL GO AWAY
+# see make depend above
diff --git a/dviware/umddvi/dev/makefile.3b b/dviware/umddvi/dev/makefile.3b
new file mode 100644
index 0000000000..487370252d
--- /dev/null
+++ b/dviware/umddvi/dev/makefile.3b
@@ -0,0 +1,149 @@
+# Makefile for device conversion programs
+#
+# You must run "make conf" to set up Makefile.local if you do not want
+# the default `all' configuration (see the file "conf.sh").
+DESTDIR=
+CFLAGS= -g -I../h -Dsys5
+MAKE= make
+MCC=dmdcc
+MCFLAGS= -g
+
+# these are intended to be overridden by the definitions in ../Makefile
+# but just in case, they are here too
+BINDIR= ${DESTDIR}/usr/local/bin
+MANDIR= ${DESTDIR}/usr/local/man
+
+# Make options
+OPTS= BINDIR=${BINDIR} MANDIR=${MANDIR} DESTDIR=${DESTDIR} CC="${CC}" \
+ CFLAGS="${CFLAGS}" ${MFLAGS}
+
+SRCS= imagen1.c imagen1-sp.c verser1.c verser2.c dmd.c dmdhost.c dmd-sp.c
+
+# First, the main entry used in the original Makefile.
+# It is also enabled by a `conf none'; this is just so that the
+# configurer will disable it in Makefile.local.
+# Whenever you run `make' afterward, this entry will run
+# make on your local Makefile.
+
+# conf none
+# first:
+# @if [ -f Makefile.local ]; then :; else \
+# echo "You should run \`make conf' first!"; \
+# echo \
+# "I will give you the default \`all' configuration for now."; \
+# sh conf.sh all; \
+# fi
+# @${MAKE} -f Makefile.local ${OPTS}
+# endconf none
+
+# In Makefile.local, this is the default (if you just say `make').
+# The `make' invocation will be commented out there.
+all:
+# conf none
+# @${MAKE} -f Makefile.local ${OPTS} $@
+# endconf none
+
+# Likewise, but for `make install'.
+install:
+# conf none
+# @${MAKE} -f Makefile.local ${OPTS} $@
+# endconf none
+
+# conf imagen
+all: imagen1 dvidmd dvidmd.j dvidmd.m
+install: inst-iptex inst-imagen1
+# endconf imagen
+
+# conf versatec
+# all: verser1 verser2
+# install: inst-dvipr inst-verser1 inst-verser2
+# endconf versatec
+
+# The rest of these are copied to Makefile.local, though many are
+# unused.
+conf:
+ @sh conf.sh
+ @echo "Remember to use \`make update' if you change the Makefile!"
+
+clean:
+ rm -f core *.o verser1 verser2 imagen1 dvidmd dvidmd.[jm]
+
+depend: ${SRCS}
+ cc -M ${CFLAGS} ${SRCS} |\
+ awk '{ if ($$1 != prev) { if (rec != "") print rec;\
+ rec = $$0; prev = $$1; }\
+ else { if (length(rec $$2) > 78) { print rec; rec = $$0; }\
+ else rec = rec " " $$2 } }\
+ END { print rec }' >makedep
+ echo '/^# DO NOT DELETE THIS LINE/+2,$$d' >eddep
+ echo '$$r makedep' >>eddep
+ echo 'w' >>eddep
+ cp Makefile Makefile.bak
+ ed - Makefile <eddep
+ rm eddep makedep
+ echo '# DEPENDENCIES MUST END AT END OF FILE' >>Makefile
+ echo '# IF YOU PUT STUFF HERE IT WILL GO AWAY' >>Makefile
+ echo '# see make depend above' >>Makefile
+ sh conf.sh update
+
+update:
+ @sh conf.sh update
+
+inst-dvipr:
+ install -c dvipr.sh ${BINDIR}/dvipr
+ install -c -m 444 ../man/dvipr.1 ${MANDIR}/man1/dvipr.1
+inst-verser1: verser1
+ install -s verser1 ${BINDIR}/verser1
+inst-verser2: verser2
+ install -s verser2 ${BINDIR}/verser2
+
+inst-iptex:
+ install -c iptex.sh ${BINDIR}/iptex
+ install -c -m 444 ../man/iptex.1 ${MANDIR}/man1/iptex.1
+inst-imagen1: imagen1
+ install -s imagen1 ${BINDIR}/imagen1
+
+lint: ${SRCS}
+ lint -hbxuL ../lib/llib-lib imagen1.c
+ lint -hbxuL ../lib/llib-lib verser1.c
+ lint -hbxuL ../lib/llib-lib verser2.c
+
+dist:
+ rm -f Makefile.bak Makefile.local Makefile.l.bak
+ sh conf.sh all
+
+dvidmd: dmd.o dmdhost.o dmd-sp.o
+ ${CC} ${CFLAGS} -o dvidmd dmd.o dmdhost.o dmd-sp.o ../lib/lib.a /usr/local/lib/libcompat.a -lm
+
+dvidmd.m: dmdslave.c
+ $(MCC) $(MCFLAGS) -o dvidmd.m dmdslave.c
+
+dvidmd.j: dmdslave.c
+ $(MCC) -J $(MCFLAGS) -o dvidmd.j dmdslave.c
+
+imagen1: imagen1.o imagen1-sp.o
+verser1: verser1.o
+verser2: verser2.o
+
+imagen1: ../lib/lib.a
+ ${CC} ${CFLAGS} -o imagen1 imagen1.o imagen1-sp.o ../lib/lib.a /usr/local/lib/libcompat.a -lm
+
+imagen1 verser1 verser2: ../lib/lib.a
+ ${CC} ${CFLAGS} -o $@ $@.o ../lib/lib.a /usr/local/lib/libcompat.a
+
+# DO NOT DELETE THIS LINE -- make depend uses it
+
+imagen1.o: imagen1.c /usr/include/stdio.h ../h/types.h ../h/conv.h ../h/dvi.h
+imagen1.o: ../h/dviclass.h ../h/dvicodes.h ../h/fio.h ../h/font.h
+imagen1.o: ../h/postamble.h ../h/search.h ../h/imagen.h ../h/imPcodes.h
+verser1.o: verser1.c /usr/include/stdio.h ../h/types.h ../h/conv.h ../h/dvi.h
+verser1.o: ../h/dviclass.h ../h/dvicodes.h ../h/fio.h ../h/font.h
+verser1.o: ../h/postamble.h ../h/search.h ../h/verser.h
+verser2.o: verser2.c /usr/include/errno.h /usr/include/setjmp.h
+verser2.o: /usr/include/stdio.h /usr/include/sys/vcmd.h
+verser2.o: /usr/include/sys/ioctl.h /usr/include/sys/ttychars.h
+verser2.o: /usr/include/sys/ttydev.h ../h/types.h ../h/conv.h ../h/fio.h
+verser2.o: ../h/font.h ../h/verser.h
+# DEPENDENCIES MUST END AT END OF FILE
+# IF YOU PUT STUFF HERE IT WILL GO AWAY
+# see make depend above
diff --git a/dviware/umddvi/dev/makefile.local b/dviware/umddvi/dev/makefile.local
new file mode 100644
index 0000000000..e23d533f08
--- /dev/null
+++ b/dviware/umddvi/dev/makefile.local
@@ -0,0 +1,143 @@
+#
+# Copyright (c) 1987 University of Maryland Department of Computer Science.
+# All rights reserved. Permission to copy for any purpose is hereby granted
+# so long as this copyright notice remains intact.
+#
+# $Header: Makefile,v 1.3 87/06/16 17:13:19 chris Exp $
+#
+# Makefile for device conversion programs
+#
+# You must run "make conf" to set up Makefile.local if you do not want
+# the default `all' configuration (see the file "conf.sh"). Remember to
+# use `make update'!
+DESTDIR=
+CFLAGS= -O -R -I../h
+MAKE= make
+
+# these are intended to be overridden by the definitions in ../Makefile
+# but just in case, they are here too
+BINDIR= ${DESTDIR}/usr/local/bin
+MANDIR= ${DESTDIR}/usr/local/man
+
+# Make options
+OPTS= BINDIR=${BINDIR} MANDIR=${MANDIR} DESTDIR=${DESTDIR} CC="${CC}" \
+ CFLAGS="${CFLAGS}" ${MFLAGS}
+
+SRCS= imagen1.c verser1.c verser2.c
+
+# First, the main entry used in the original Makefile.
+# It is also enabled by a `conf none'; this is just so that the
+# configurer will disable it in Makefile.local.
+# Whenever you run `make' afterward, this entry will run
+# make on your local Makefile.
+
+# conf none
+# first:
+# @if [ -f Makefile.local ]; then :; else \
+# echo "You should run \`make conf' first!"; \
+# echo \
+# "I will give you the default \`all' configuration for now."; \
+# sh conf.sh all; \
+# fi
+# @${MAKE} -f Makefile.local ${OPTS}
+# endconf none
+
+# In Makefile.local, this is the default (if you just say `make').
+# The `make' invocation will be commented out there.
+all:
+# conf none
+# @${MAKE} -f Makefile.local ${OPTS} $@
+# endconf none
+
+# Likewise, but for `make install'.
+install:
+# conf none
+# @${MAKE} -f Makefile.local ${OPTS} $@
+# endconf none
+
+# conf imagen
+all: imagen1
+install: inst-iptex inst-imagen1
+# endconf imagen
+
+# conf versatec
+all: verser1 verser2
+install: inst-dvipr inst-verser1 inst-verser2
+# endconf versatec
+
+# The rest of these are copied to Makefile.local, though many are
+# unused.
+conf:
+ @sh conf.sh
+ @echo "Remember to use \`make update' if you change the Makefile!"
+
+clean:
+ rm -f core *.o verser1 verser2 imagen1
+
+depend: ${SRCS}
+ cc -M ${CFLAGS} ${SRCS} |\
+ awk '{ if ($$1 != prev) { if (rec != "") print rec;\
+ rec = $$0; prev = $$1; }\
+ else { if (length(rec $$2) > 78) { print rec; rec = $$0; }\
+ else rec = rec " " $$2 } }\
+ END { print rec }' >makedep
+ echo '/^# DO NOT DELETE THIS LINE/+2,$$d' >eddep
+ echo '$$r makedep' >>eddep
+ echo 'w' >>eddep
+ cp Makefile Makefile.bak
+ ed - Makefile <eddep
+ rm eddep makedep
+ echo '# DEPENDENCIES MUST END AT END OF FILE' >>Makefile
+ echo '# IF YOU PUT STUFF HERE IT WILL GO AWAY' >>Makefile
+ echo '# see make depend above' >>Makefile
+ sh conf.sh update
+
+update:
+ @sh conf.sh update
+
+inst-dvipr:
+ install -c dvipr.sh ${BINDIR}/dvipr
+ install -c -m 444 ../man/dvipr.1 ${MANDIR}/man1/dvipr.1
+inst-verser1: verser1
+ install -s verser1 ${BINDIR}/verser1
+inst-verser2: verser2
+ install -s verser2 ${BINDIR}/verser2
+
+inst-iptex:
+ install -c iptex.sh ${BINDIR}/iptex
+ install -c -m 444 ../man/iptex.1 ${MANDIR}/man1/iptex.1
+inst-imagen1: imagen1
+ install -s imagen1 ${BINDIR}/imagen1
+
+lint: ${SRCS}
+ lint -hbxuL ../lib/llib-lib imagen1.c
+ lint -hbxuL ../lib/llib-lib verser1.c
+ lint -hbxuL ../lib/llib-lib verser2.c
+
+dist:
+ rm -f Makefile.bak Makefile.local Makefile.l.bak
+ sh conf.sh all
+
+imagen1: imagen1.o
+verser1: verser1.o
+verser2: verser2.o
+
+imagen1 verser1 verser2: ../lib/lib.a
+ ${CC} ${CFLAGS} -o $@ $@.o ../lib/lib.a
+
+# DO NOT DELETE THIS LINE -- make depend uses it
+
+imagen1.o: imagen1.c /usr/include/stdio.h ../h/types.h ../h/conv.h ../h/dvi.h
+imagen1.o: ../h/dviclass.h ../h/dvicodes.h ../h/fio.h ../h/font.h
+imagen1.o: ../h/postamble.h ../h/search.h ../h/imagen.h ../h/imPcodes.h
+verser1.o: verser1.c /usr/include/stdio.h ../h/types.h ../h/conv.h ../h/dvi.h
+verser1.o: ../h/dviclass.h ../h/dvicodes.h ../h/fio.h ../h/font.h
+verser1.o: ../h/postamble.h ../h/search.h ../h/verser.h
+verser2.o: verser2.c /usr/include/errno.h /usr/include/setjmp.h
+verser2.o: /usr/include/stdio.h /usr/include/sys/vcmd.h
+verser2.o: /usr/include/sys/ioctl.h /usr/include/sys/ttychars.h
+verser2.o: /usr/include/sys/ttydev.h ../h/types.h ../h/conv.h ../h/fio.h
+verser2.o: ../h/font.h ../h/verser.h
+# DEPENDENCIES MUST END AT END OF FILE
+# IF YOU PUT STUFF HERE IT WILL GO AWAY
+# see make depend above
diff --git a/dviware/umddvi/dev/readme b/dviware/umddvi/dev/readme
new file mode 100644
index 0000000000..0dd6cc1744
--- /dev/null
+++ b/dviware/umddvi/dev/readme
@@ -0,0 +1,7 @@
+This directory is for DVI to device conversion programs (including
+shell scripts to drive them).
+
+N.B.: verser2.c is probably vax-dependent.
+
+You should run "make conf" before trying to make or install any of
+these, else you will get all drivers.
diff --git a/dviware/umddvi/dev/verser1.c b/dviware/umddvi/dev/verser1.c
new file mode 100644
index 0000000000..9c8faf0bf6
--- /dev/null
+++ b/dviware/umddvi/dev/verser1.c
@@ -0,0 +1,1047 @@
+/*
+ * Copyright (c) 1987 University of Maryland Department of Computer Science.
+ * All rights reserved. Permission to copy for any purpose is hereby granted
+ * so long as this copyright notice remains intact.
+ */
+
+#ifndef lint
+static char rcsid[] = "$Header: verser1.c,v 2.4 87/06/16 17:14:51 chris Exp $";
+#endif
+
+/*
+ * Verser1 -- First half of DVI to Versatec driver
+ *
+ * Reads DVI version 2 files and converts to an intermediate form that
+ * is read by verser2. Most of the work consists of converting DVI units
+ * to Versatec units, sorting pages, and rotating positions if the -h
+ * flag is given.
+ *
+ * TODO:
+ * think about fonts with characters outside [0..127]
+ */
+
+#include <stdio.h>
+#include "types.h"
+#include "conv.h"
+#include "dvi.h"
+#include "dviclass.h"
+#include "dvicodes.h"
+#include "fio.h"
+#include "font.h"
+#include "postamble.h"
+#include "search.h"
+#include "verser.h"
+
+char *ProgName;
+extern char *optarg;
+extern int optind;
+
+/* Globals */
+char serrbuf[BUFSIZ]; /* buffer for stderr */
+
+/*
+ * According to DVItype, we have to plot characters using two simultaneous
+ * pieces of information: the character's TFM width modified by the scale
+ * factor from the DVI file (this is the width in scaled points), and the
+ * character's width in pixels (converted from scaled points). The former
+ * is obtained by the glyph routines; the latter we put in the g_pixwidth
+ * field of each glyph.
+ *
+ * Whenever we move horizontally by a DVI distance >= `space', we
+ * are to recompute horizontal position from DVI units; otherwise, we are to
+ * use device resolution units to keep track of horizontal position. A
+ * similar scheme must be followed for vertical positioning.
+ */
+struct fontinfo {
+ struct font *f; /* the font */
+ int index; /* our index number */
+ i32 pspace; /* boundary between `small' & `large' spaces
+ (for positive horizontal motion) */
+ i32 nspace; /* -4 * pspace, for negative motion */
+ i32 vspace; /* 5 * pspace, for vertical motion */
+};
+
+/*
+ * However, there's an exception to the rule (natch!): certain fonts
+ * tend to produce a constant "drift" away from the "correct" position
+ * which eventually builds up to an intolerable amount. So, if hh and
+ * fromSP(dvi_h) become more than MaxDrift units apart, hh must be adjusted
+ * by the smallest amount that will preserve the invariant. (The same
+ * applies to vv and dvi_v.)
+ */
+int MaxDrift; /* the maximum allowable difference between
+ hh and fromSP(dvi_h) */
+
+struct fontinfo *CurrentFont; /* the current font (if any) */
+int NextFont; /* during font definition, we assign
+ sequential indicies; verser2 knows this */
+
+struct fontinfo NoFont; /* a fake font, to help get things started */
+
+char *TeXFontDesc; /* getenv(CONFENV) */
+
+/* arrays containing page info */
+int Chars; /* number of chars {left,} on page */
+int MaxChars; /* total space for chars */
+int *yx; /* contains (y<<16|x) for each char */
+int *fcp; /* contains (font<<14|char<<7|part) */
+int *nextyx; /* pointer to next yx area */
+int *nextfcp; /* pointer to next fcp area */
+
+/*
+ * A few experiments showed that the typical job uses less than 3200
+ * characters per page. This is an extensible array, so the initial value
+ * affects only efficiency.
+ */
+#ifndef InitialChars
+#define InitialChars 4000 /* initial number of chars to allocate */
+#endif
+
+int ExpectBOP; /* true => BOP ok */
+int ExpectEOP; /* true => EOP ok */
+
+/*
+ * If there are lots of characters and rules that don't fit on a page,
+ * these flags help reduce error output.
+ */
+int TopEMsg; /* true => gave error message about top */
+int BottomEMsg; /* true => gave error message about bottom */
+int LeftEMsg; /* true => gave error message about left */
+int RightEMsg; /* true => gave error message about right */
+int RuleEMsg; /* true => gave error message about rule */
+
+int CFlag; /* -c => center output */
+int HFlag; /* -h => horizontal (sideways) output */
+int SFlag; /* -s => silent (no page #s) */
+int Debug; /* -D => debug flag */
+
+int hh; /* current horizontal position, in DEVs */
+int vv; /* current vertical position, in DEVs */
+
+/*
+ * Similar to dvi_stack, but includes `hh' and `vv', which are usually
+ * but not always the same as fromSP(h) and fromSP(v):
+ */
+struct localstack {
+ int stack_hh;
+ int stack_vv;
+ struct dvi_stack stack_dvi;
+};
+
+struct localstack *dvi_stack; /* base of stack */
+struct localstack *dvi_stackp; /* current place in stack */
+
+int BottomMargin; /* bottom margin (in DEVs) */
+int TopMargin; /* top margin (in DEVs) */
+int WidestPageWidth; /* width of widest page (in DEVs) */
+int TallestPageHeight; /* height of tallest page (in DEVs) */
+int HHMargin; /* horizontal margin (in DEVs) */
+int VVMargin; /* vertical margin (in DEVs) */
+
+i32 Numerator; /* numerator from DVI file */
+i32 Denominator; /* denominator from DVI file */
+i32 DVIMag; /* magnification from the DVI file */
+int UserMag; /* user specified magnification */
+
+struct search *FontFinder; /* maps from DVI index to internal info */
+int FontErrors; /* true => error(s) occurred during font
+ definitions from DVI postamble */
+
+char *malloc(), *realloc(), *getenv();
+
+/* Absolute value */
+#define ABS(n) ((n) >= 0 ? (n) : -(n))
+
+/* Correct devpos (the actual device position) to be within MaxDrift pixels
+ of dvipos (the virtual DVI position). */
+#define FIXDRIFT(devpos, dvipos) \
+ if (ABS((devpos) - (dvipos)) <= MaxDrift) \
+ /* void */; \
+ else \
+ if ((devpos) < (dvipos)) \
+ (devpos) = (dvipos) - MaxDrift; \
+ else \
+ (devpos) = (dvipos) + MaxDrift
+
+/*
+ * Compute the DEV widths of the characters in the given font.
+ */
+ComputeCWidths(fi)
+ struct fontinfo *fi;
+{
+ register struct font *f;
+ register struct glyph *g;
+ register int i;
+
+ f = fi->f;
+ for (i = 0; i < 128; i++) {
+ g = GLYPH(f, i);
+ if (GVALID(g))
+ g->g_pixwidth = fromSP(g->g_tfmwidth);
+ }
+}
+
+SelectFont(n)
+ i32 n;
+{
+ int x = S_LOOKUP;
+
+ if ((CurrentFont = (struct fontinfo *)SSearch(FontFinder, n, &x)) == 0)
+ error(1, 0, "font %d not in finder table", n);
+}
+
+/*
+ * Have run out of room in the current yx and fcp arrays, so expand them.
+ */
+ExpandArrays()
+{
+ register unsigned newsize;
+
+ MaxChars <<= 1;
+ newsize = MaxChars * sizeof *yx;
+ if ((yx = (int *) realloc((char *) yx, newsize)) == NULL)
+ GripeOutOfMemory(newsize, "yx array");
+ if ((fcp = (int *) realloc((char *) fcp, newsize)) == NULL)
+ GripeOutOfMemory(newsize, "fcp array");
+ Chars = MaxChars >> 1;
+ nextyx = &yx[Chars];
+ nextfcp = &fcp[Chars];
+ --Chars; /* because we're about to use one */
+}
+
+/*
+ * Sort the page arrays so that the values in yx are in ascending order. We
+ * use a Shell sort.
+ */
+SortPage()
+{
+ register int i, j, k, delta, *y, *f;
+
+ /*
+ * Chars is currently the number of chars on the page, not the number
+ * of chars left in the array.
+ */
+ y = yx;
+ f = fcp;
+ delta = 1;
+ while (9 * delta + 4 < Chars)
+ delta = 3 * delta + 1;
+ while (delta > 0) {
+ for (i = delta; i < Chars; i++) {
+ if (y[j = i - delta] > y[i]) {
+ register int t1 = y[i];
+ register int t2 = f[i];
+
+ k = i;
+ do {
+ y[k] = y[j];
+ f[k] = f[j];
+ k = j;
+ j -= delta;
+ } while (j >= 0 && y[j] > t1);
+ y[k] = t1;
+ f[k] = t2;
+ }
+ }
+ delta /= 3;
+ }
+}
+
+/*
+ * Start a page (process a DVI_BOP).
+ * NOTE: I'm depending on getting a BOP before any characters or rules on a
+ * page!
+ */
+BeginPage()
+{
+ register int *i;
+ static int count[11]; /* the 10 counters, plus the previous page
+ pointer (which we ignore anyway) */
+
+ if (!ExpectBOP)
+ GripeUnexpectedOp("BOP");
+
+ if (nextyx && !SFlag)
+ putc(' ', stderr);
+
+ /* Chars now becomes "number of characters left" */
+ Chars = MaxChars; /* empty the arrays */
+ nextyx = yx;
+ nextfcp = fcp;
+
+ dvi_stackp = dvi_stack;
+
+ ExpectBOP = 0;
+ ExpectEOP++; /* set the new "expect" state */
+
+ TopEMsg = 0;
+ BottomEMsg = 0;
+ LeftEMsg = 0;
+ RightEMsg = 0;
+ RuleEMsg = 0;
+
+ for (i = count; i < &count[sizeof count / sizeof *count]; i++)
+ fGetLong(stdin, *i);
+
+ if (!SFlag) {
+ (void) fprintf(stderr, "[%d", count[0]);
+ (void) fflush(stderr);
+ }
+ hh = HHMargin;
+ vv = VVMargin;
+ dvi_h = toSP(hh); /* `0' */
+ dvi_v = toSP(vv); /* `0' */
+ dvi_w = 0;
+ dvi_x = 0;
+ dvi_y = 0;
+ dvi_z = 0;
+}
+
+/*
+ * End a page (process a DVI_EOP).
+ */
+EndPage()
+{
+ register int i, *y, *f, t, v, oldv;
+
+ if (!ExpectEOP)
+ GripeUnexpectedOp("EOP");
+
+ /* Chars now becomes "number of characters on page" */
+ i = Chars = MaxChars - Chars;
+
+ ExpectBOP++;
+ ExpectEOP = 0; /* set the new "expect" state */
+
+ SortPage();
+
+ if (!SFlag) {
+ putc(']', stderr);
+ (void) fflush(stderr);
+ }
+ y = yx;
+ f = fcp;
+ oldv = 0;
+ while (--i >= 0) {
+ v = *y >> 16;
+ t = v - oldv;
+ if (*f >= 0) { /* setting a character */
+ t = (t << 16) | (*y++ & 0xffff);
+ PutLong(stdout, t);
+ t = *f++;
+ PutLong(stdout, t); /* move down & place char */
+ } else { /* setting a rule */
+ y++;
+ if (t > 0) { /* need to move down first */
+ t = -t;
+ PutLong(stdout, -1);
+ PutLong(stdout, t);
+ }
+ t = *f++ & 0x7fffffff;
+ PutLong(stdout, -1);
+ PutLong(stdout, t); /* place rule */
+ }
+ oldv = v;
+ }
+
+ /* Make all pages the same length */
+ if (HFlag)
+ t = -WidestPageWidth;
+ else
+ t = -TallestPageHeight;
+ t -= BottomMargin + TopMargin;
+ if (t) {
+ PutLong(stdout, -1); /* move down */
+ PutLong(stdout, t);
+ }
+ PutLong(stdout, -1);
+ PutLong(stdout, 0); /* end of page */
+}
+
+/*
+ * Store the relevant information from the DVI postamble, copying some of it
+ * to stdout for verser2, and set up variables.
+ */
+PostAmbleHeader(p)
+ register struct PostAmbleInfo *p;
+{
+ register int n;
+
+ Numerator = p->pai_Numerator;
+ Denominator = p->pai_Denominator;
+ DVIMag = p->pai_DVIMag;
+
+ /*
+ * Set the conversion factor.
+ */
+ SetConversion(200, UserMag, Numerator, Denominator, DVIMag);
+
+ TallestPageHeight = fromSP(p->pai_TallestPageHeight);
+ WidestPageWidth = fromSP(p->pai_WidestPageWidth);
+
+ n = p->pai_DVIStackSize * sizeof *dvi_stack;
+ dvi_stack = (struct localstack *) malloc((unsigned) n);
+ if ((dvi_stackp = dvi_stack) == 0)
+ GripeOutOfMemory(n, "DVI stack");
+
+ /* verser2 needs to set the conversion factor too */
+ PutLong(stdout, 200); /* keep raster density knowledge all here */
+ PutLong(stdout, UserMag);
+ PutLong(stdout, Numerator);
+ PutLong(stdout, Denominator);
+ PutLong(stdout, DVIMag);
+}
+
+/*
+ * Handle one of the font definitions from the DVI postamble.
+ */
+PostAmbleFontDef(p)
+ register struct PostAmbleFont *p;
+{
+ register struct fontinfo *fi;
+ register struct font *f;
+ register char *s;
+ register int n;
+ char *fname;
+ int def = S_CREATE | S_EXCL;
+
+ if (NextFont >= NFONTS) /* fix this later */
+ error(1, 0, "too many fonts (%d) used", NextFont);
+
+ fi = (struct fontinfo *) SSearch(FontFinder, p->paf_DVIFontIndex,
+ &def);
+ if (fi == NULL) {
+ if (def & S_COLL)
+ GripeFontAlreadyDefined(p->paf_DVIFontIndex);
+ else
+ error(1, 0, "can't stash font %ld (out of memory?)",
+ p->paf_DVIFontIndex);
+ /* NOTREACHED */
+ }
+ f = GetRasterlessFont(p->paf_name, p->paf_DVIMag,
+ p->paf_DVIDesignSize, "versatec", &fname);
+ if ((fi->f = f) == NULL) {
+ GripeCannotGetFont(p->paf_name, p->paf_DVIMag,
+ p->paf_DVIDesignSize, "versatec", fname);
+ FontErrors++;
+ return;
+ }
+ if (Debug) {
+ (void) fprintf(stderr, "[%s -> %s]\n",
+ Font_TeXName(f), fname);
+ (void) fflush(stderr);
+ }
+ /* match checksums, if not zero */
+ if (p->paf_DVIChecksum && f->f_checksum &&
+ p->paf_DVIChecksum != f->f_checksum)
+ GripeDifferentChecksums(fname, p->paf_DVIChecksum,
+ f->f_checksum);
+
+ putchar(1); /* signal another font */
+ PutLong(stdout, p->paf_DVIChecksum);
+ PutLong(stdout, p->paf_DVIMag);
+ PutLong(stdout, p->paf_DVIDesignSize);
+ n = p->paf_n1 + p->paf_n2;
+ PutLong(stdout, n);
+ fputs(p->paf_name, stdout);
+
+ ComputeCWidths(fi);
+
+ fi->index = NextFont++;
+ fi->pspace = p->paf_DVIMag / 6; /* a three-unit "thin space" */
+ fi->nspace = -4 * fi->pspace;
+ fi->vspace = 5 * fi->pspace;
+}
+
+/*
+ * Read the postamble.
+ */
+ReadPostAmble()
+{
+
+ if ((FontFinder = SCreate(sizeof(struct fontinfo))) == 0)
+ error(1, 0, "can't create FontFinder (out of memory?)");
+ ScanPostAmble(stdin, PostAmbleHeader, PostAmbleFontDef);
+ if (FontErrors)
+ GripeMissingFontsPreventOutput(FontErrors);
+ putchar(0); /* mark end of fonts */
+}
+
+/*
+ * Read the preamble and do a few sanity checks.
+ */
+ReadPreAmble()
+{
+ register int n;
+
+ rewind(stdin);
+ if (GetByte(stdin) != Sign8(DVI_PRE))
+ GripeMissingOp("PRE");
+ if (GetByte(stdin) != Sign8(DVI_VERSION))
+ GripeMismatchedValue("version numbers");
+ if (GetLong(stdin) != Numerator)
+ GripeMismatchedValue("numerator");
+ if (GetLong(stdin) != Denominator)
+ GripeMismatchedValue("denominator");
+ if (GetLong(stdin) != DVIMag)
+ GripeMismatchedValue("\\magfactor");
+ n = UnSign8(GetByte(stdin));
+ while (--n >= 0)
+ (void) GetByte(stdin);
+}
+
+main(argc, argv)
+ int argc;
+ register char **argv;
+{
+ register int c;
+ register char *s;
+ int lmargin;
+
+ setbuf(stderr, serrbuf);
+
+ ProgName = *argv;
+ UserMag = 1000;
+ MaxDrift = DefaultMaxDrift;
+
+ while ((c = getopt(argc, argv, "cd:hm:sD")) != EOF) {
+ switch (c) {
+
+ case 'c':
+ CFlag++;/* centered output */
+ break;
+
+ case 'd': /* max drift value */
+ MaxDrift = atoi(optarg);
+ break;
+
+ case 'h': /* horizontal output */
+ HFlag++;
+ break;
+
+ case 'm': /* magnification */
+ UserMag = atoi(optarg);
+ break;
+
+ case 's': /* silent */
+ SFlag++;
+ break;
+
+ case 'D':
+ Debug++;
+ break;
+
+ case '?':
+ (void) fprintf(stderr, "\
+Usage: %s [-c] [-h] [-m mag] [-s] [file]\n",
+ ProgName);
+ (void) fflush(stderr);
+ exit(1);
+ }
+ }
+ if (optind < argc)
+ if (freopen(argv[optind], "r", stdin) == NULL)
+ error(1, -1, "can't open %s", argv[optind]);
+
+ if (MakeSeekable(stdin))
+ error(1, 0,
+ "unable to copy input to temp file (see the manual)");
+
+ if ((TeXFontDesc = getenv(CONFENV)) == NULL)
+ TeXFontDesc = "";
+
+ c = (VERSION << 1) + (HFlag ? 1 : 0);
+ putchar(c);
+ c = strlen(s = TeXFontDesc);
+ PutLong(stdout, c);
+ while (--c >= 0)
+ putchar(*s++);
+
+ ReadPostAmble();
+
+ /*
+ * The character plotter must check each character to ensure it
+ * is on the page, because the widest and tallest page values from
+ * the DVI file are not always accurate; so these tests do little
+ * save to keep one from finding the offending object. Accordingly,
+ * I have disabled them. 20 May 1984 ACT.
+ */
+#ifdef notdef
+ if (HFlag) {
+ if (MaxPageWidth - MinimumLeftMargin < TallestPageHeight)
+ error(1, 0, "text object too high!");
+ if (MaxPageHeight - MinimumTopMargin < WidestPageWidth)
+ error(1, 0, "text object too wide!");
+ } else { /* page height can be safely ignored */
+ if (MaxPageWidth - MinimumLeftMargin < WidestPageWidth)
+ error(1, 0, "text object too wide!");
+ }
+#endif
+
+ /* Determine margins */
+ /* THIS CODE NEEDS WORK */
+ if (CFlag) {
+ lmargin = HFlag ? TallestPageHeight : WidestPageWidth;
+ lmargin = (MaxPageWidth - lmargin) >> 1;
+ if (lmargin < MinimumLeftMargin) {
+ lmargin = MinimumLeftMargin;
+ error(0, 0, "\
+cannot center (page too wide); flush left instead");
+ }
+ } else
+ lmargin = HFlag ? DefaultTopMargin : DefaultLeftMargin;
+
+ if (HFlag) {
+ TopMargin = (MaxPageHeight - WidestPageWidth) >> 1;
+ if (TopMargin < 0)
+ TopMargin = 0;
+ BottomMargin = MaxPageHeight - TopMargin - WidestPageWidth;
+ if (BottomMargin < 0)
+ BottomMargin = 0;
+ } else {
+ TopMargin = DefaultTopMargin;
+ BottomMargin = DefaultBottomMargin;
+ }
+
+ HHMargin = lmargin;
+ VVMargin = TopMargin;
+
+ ReadPreAmble();
+ ExpectBOP++;
+
+ /* Allocate arrays */
+ MaxChars = InitialChars;
+ if ((yx = (int *) malloc(InitialChars * sizeof *yx)) == NULL)
+ GripeOutOfMemory(InitialChars * sizeof *yx, "yx array");
+ if ((fcp = (int *) malloc(InitialChars * sizeof *fcp)) == NULL)
+ GripeOutOfMemory(InitialChars * sizeof *fcp, "fcp array");
+
+ /*
+ * If the first command in the DVI file involves motion, we will need
+ * to compare it to the current font `space' parameter; so start with
+ * a fake current font of all zeros.
+ */
+ CurrentFont = &NoFont;
+ ReadDVIFile();
+
+ exit(0);
+}
+
+/*
+ * Skip a font definition (since we are using those from the postamble).
+ */
+/*ARGSUSED*/
+SkipFontDef(font)
+ i32 font;
+{
+ register int i;
+
+ (void) GetLong(stdin);
+ (void) GetLong(stdin);
+ (void) GetLong(stdin);
+ i = UnSign8(GetByte(stdin)) + UnSign8(GetByte(stdin));
+ while (--i >= 0)
+ (void) GetByte(stdin);
+}
+
+/*
+ * Perform a \special - right now ignore all of them.
+ */
+DoSpecial(len)
+ i32 len; /* length of the \special string */
+{
+
+ error(0, 0, "warning: ignoring \\special");
+ (void) fseek (stdin, (long) len, 1);
+}
+
+#ifndef lint
+#define maxysize min(MaxCharHeight, 255)
+#else
+#define maxysize 255
+#endif
+
+/*
+ * Draw a rule at the current (hh,vv) position. There are two 4 byte
+ * parameters. The first is the height of the rule, and the second is
+ * the width. (hh,vv) is the lower left corner of the rule.
+ */
+SetRule(advance)
+ int advance;
+{
+ i32 rwidth; /* rule width from DVI file */
+ i32 rheight; /* rule height from DVI file */
+ register int y; /* temporary y value */
+ register int x; /* temporary x value */
+ register int h, w; /* temporaries */
+ register int ymax; /* bottommost (versatec-wise) y coord */
+ register int xmax; /* rightmost (versatec-wise) x coord */
+ register int ymin; /* topmost y coord */
+ register int xmin; /* leftmost x coord */
+ int anybad = 0;
+
+ fGetLong(stdin, rheight);
+ fGetLong(stdin, rwidth);
+
+ h = ConvRule(rheight);
+ w = ConvRule(rwidth);
+
+ if (!HFlag) {
+ xmin = hh;
+ ymax = vv;
+ ymin = ymax - h;
+ xmax = xmin + w;
+ } else {
+ ymin = hh - FFMargin;
+ xmin = MaxPageWidth - vv - 1; /* ???DO I NEED -1 ANYMORE?? */
+ xmax = xmin + h;
+ ymax = ymin + w;
+ if (ymax > MaxPageHeight - FFMargin)
+ ymax = MaxPageHeight - FFMargin, anybad++;
+ }
+ if (ymin < 0)
+ ymin = 0, anybad++;
+ if (xmin < 0)
+ xmin = 0, anybad++;
+ if (xmax > MaxPageWidth)
+ xmax = MaxPageWidth, anybad++;
+ if (anybad && !RuleEMsg) {
+ error(0, 0, "WARNING: rule(s) off page edge; clipped to fit");
+ RuleEMsg++;
+ }
+ if (advance) {
+ hh += w;
+ dvi_h += rwidth;
+ x = fromSP(dvi_h);
+ FIXDRIFT(hh, x);
+ }
+ for (y = ymin; y < ymax; y += h) {
+ for (x = xmin; x < xmax; x += w) {
+ h = ymax - y;
+ h = min(h, maxysize);
+ w = xmax - x;
+ w = min(w, 255);
+ if (--Chars < 0)
+ ExpandArrays();
+ *nextyx++ = (y << 16) | x;
+ *nextfcp++ = (1 << 31) | (x << 16) | (h << 8) | w;
+ }
+ }
+}
+
+/* this driver needs work for codes > 127 */
+char chartoobig[] = "Character code %d is too big; ignored";
+
+/*
+ * Used inside the dump-char code to ensure chars are within page limits:
+ */
+#define CHECK(cond, msg, flag) \
+ if (cond) { \
+ if (!flag) { \
+ error(0, 0, warn, msg); \
+ flag++; \
+ } \
+ goto ignore; \
+ }
+
+/*
+ * This rather large routine reads the DVI file and calls on other routines
+ * to do anything moderately difficult (except put characters: there is
+ * a bunch of ugly code with `goto's which makes things much faster).
+ */
+ReadDVIFile()
+{
+ register int c;
+ register struct glyph *g;
+ register i32 p;
+ int advance;
+ static char warn[] = "\
+WARNING: text object(s) run off %s of page; ignored";
+
+ /*
+ * Only way out is via "return" statement. I had a `for (;;)' here,
+ * but everything crawled off the right.
+ */
+loop:
+ /*
+ * Get the DVI byte, and switch on its parameter length and type.
+ * Note that getchar() returns unsigned values.
+ */
+ c = getchar();
+
+ /*
+ * Handling characters (the most common case) early makes hte
+ * program run a bit faster.
+ */
+ if (DVI_IsChar(c)) {
+ advance = 1;
+do_char:
+ {
+ register struct font *f = CurrentFont->f;
+
+ g = GLYPH(f, c);
+ if (!GVALID(g)) {
+ error(0, 0, "there is no character %d in %s",
+ c, f->f_path);
+ goto loop;
+ }
+ }
+ {
+ register int ulcx, ulcy, height;
+
+ if (!HFlag) {
+ ulcy = vv - g->g_yorigin;
+ ulcx = hh - g->g_xorigin;
+ height = g->g_height;
+ CHECK(ulcy < 0, "top", TopEMsg);
+ CHECK(ulcx < 0, "left", LeftEMsg);
+ CHECK(ulcx + g->g_width >= MaxPageWidth,
+ "right", RightEMsg);
+ } else {/* rotate & translate */
+ ulcy = hh - g->g_xorigin - FFMargin;
+ ulcx = MaxPageWidth -
+ (vv + g->g_height - g->g_yorigin);
+ height = g->g_width;
+ CHECK(ulcy < 0, "left", LeftEMsg);
+ CHECK(ulcy+height >= MaxPageHeight-FFMargin,
+ "right", RightEMsg);
+ CHECK(ulcx < 0, "bottom", BottomEMsg);
+ CHECK(ulcx + g->g_height >= MaxPageWidth,
+ "top", TopEMsg);
+ }
+ p = 0;
+ while (height > 0) {
+ if (--Chars < 0)
+ ExpandArrays();
+ *nextyx++ = (ulcy << 16) | ulcx;
+ *nextfcp++ = (CurrentFont->index<<FONTSHIFT) |
+ ((c & CHARMASK) << CHARSHIFT) | p;
+ height -= MaxCharHeight;
+ ulcy += MaxCharHeight;
+ p++;
+ }
+ }
+ignore:
+ if (advance) {
+ hh += g->g_pixwidth;
+ dvi_h += g->g_tfmwidth;
+ p = fromSP(dvi_h);
+ FIXDRIFT(hh, p);
+ }
+ goto loop;
+ }
+
+ switch (DVI_OpLen(c)) {
+
+ case DPL_NONE:
+ break;
+
+ case DPL_SGN1:
+ p = getchar();
+ p = Sign8(p);
+ break;
+
+ case DPL_SGN2:
+ fGetWord(stdin, p);
+ p = Sign16(p);
+ break;
+
+ case DPL_SGN3:
+ fGet3Byte(stdin, p);
+ p = Sign24(p);
+ break;
+
+ case DPL_SGN4:
+ fGetLong(stdin, p);
+ break;
+
+ case DPL_UNS1:
+ p = UnSign8(getchar());
+ break;
+
+ case DPL_UNS2:
+ fGetWord(stdin, p);
+ p = UnSign16(p);
+ break;
+
+ case DPL_UNS3:
+ fGet3Byte(stdin, p);
+ p = UnSign24(p);
+ break;
+
+ default:
+ panic("DVI_OpLen(%d) = %d", c, DVI_OpLen(c));
+ /* NOTREACHED */
+ }
+
+ /*
+ * Now that we have the parameter, perform the
+ * command.
+ */
+ switch (DVI_DT(c)) {
+
+ case DT_SET:
+ advance = 1;
+ c = p;
+ if (c > 127) {
+ error(0, 0, chartoobig, c);
+ break;
+ }
+ goto do_char;
+
+ case DT_PUT:
+ advance = 0;
+ c = p;
+ if (c > 127) {
+ error(0, 0, chartoobig, c);
+ break;
+ }
+ advance = 0;
+ goto do_char;
+
+ case DT_SETRULE:
+ SetRule(1);
+ break;
+
+ case DT_PUTRULE:
+ SetRule(0);
+ break;
+
+ case DT_NOP:
+ break;
+
+ case DT_BOP:
+ BeginPage();
+ break;
+
+ case DT_EOP:
+ EndPage();
+ break;
+
+ case DT_PUSH:
+ dvi_stackp->stack_hh = hh;
+ dvi_stackp->stack_vv = vv;
+ dvi_stackp->stack_dvi = dvi_current;
+ dvi_stackp++;
+ break;
+
+ case DT_POP:
+ dvi_stackp--;
+ hh = dvi_stackp->stack_hh;
+ vv = dvi_stackp->stack_vv;
+ dvi_current = dvi_stackp->stack_dvi;
+ break;
+
+ case DT_W0: /* there should be a way to make these pretty */
+ p = dvi_w;
+ goto move_right;
+
+ case DT_W:
+ dvi_w = p;
+ goto move_right;
+
+ case DT_X0:
+ p = dvi_x;
+ goto move_right;
+
+ case DT_X:
+ dvi_x = p;
+ goto move_right;
+
+ case DT_RIGHT:
+move_right:
+ dvi_h += p;
+ /*
+ * DVItype tells us that we must round motions in this way:
+ * `When the horizontal motion is small, like a kern, hh
+ * changes by rounding the kern; but when the motion is
+ * large, hh changes by rounding the true position so that
+ * accumulated rounding errors disappear.'
+ */
+ if (p >= CurrentFont->pspace || p <= CurrentFont->nspace)
+ hh = fromSP(dvi_h);
+ else {
+ hh += fromSP(p);
+ p = fromSP(dvi_h);
+ FIXDRIFT(hh, p);
+ }
+ break;
+
+ case DT_Y0:
+ p = dvi_y;
+ goto move_down;
+
+ case DT_Y:
+ dvi_y = p;
+ goto move_down;
+
+ case DT_Z0:
+ p = dvi_z;
+ goto move_down;
+
+ case DT_Z:
+ dvi_z = p;
+ goto move_down;
+
+ case DT_DOWN:
+move_down:
+ dvi_v += p;
+ /*
+ * `Vertical motion is done similarly, but with the threshold
+ * between ``small'' and ``large'' increased by a factor of
+ * 5. The idea is to make fractions like $1\over2$ round
+ * consistently, but to absorb accumulated rounding errors in
+ * the baseline-skip moves.'
+ */
+ if (ABS(p) >= CurrentFont->vspace)
+ vv = fromSP(dvi_v);
+ else {
+ vv += fromSP(p);
+ p = fromSP(dvi_v);
+ FIXDRIFT(vv, p);
+ }
+ break;
+
+ case DT_FNTNUM:
+ SelectFont((i32) (c - DVI_FNTNUM0));
+ break;
+
+ case DT_FNT:
+ SelectFont(p);
+ break;
+
+ case DT_XXX:
+ DoSpecial(p);
+ break;
+
+ case DT_FNTDEF:
+ SkipFontDef(p);
+ break;
+
+ case DT_PRE:
+ GripeUnexpectedOp("PRE");
+ /* NOTREACHED */
+
+ case DT_POST:
+ if (!ExpectBOP)
+ GripeUnexpectedOp("POST");
+ if (!SFlag) {
+ (void) fprintf(stderr, "\n");
+ (void) fflush(stderr);
+ }
+ return;
+
+ case DT_POSTPOST:
+ GripeUnexpectedOp("POSTPOST");
+ /* NOTREACHED */
+
+ case DT_UNDEF:
+ GripeUndefinedOp(c);
+ /* NOTREACHED */
+
+ default:
+ panic("DVI_DT(%d) = %d", c, DVI_DT(c));
+ /* NOTREACHED */
+ }
+ goto loop;
+}
diff --git a/dviware/umddvi/dev/verser2.c b/dviware/umddvi/dev/verser2.c
new file mode 100644
index 0000000000..8969e7595d
--- /dev/null
+++ b/dviware/umddvi/dev/verser2.c
@@ -0,0 +1,758 @@
+/*
+ * Copyright (c) 1987 University of Maryland Department of Computer Science.
+ * All rights reserved. Permission to copy for any purpose is hereby granted
+ * so long as this copyright notice remains intact.
+ */
+
+#ifndef lint
+static char rcsid[] = "$Header: verser2.c,v 2.5 87/06/16 17:15:19 chris Exp $";
+#endif
+
+/*
+ * Verser2 -- Second half of DVI to Versatec driver
+ *
+ * Reads pre-sorted pages as put out by verser1, and shovels bitmaps
+ * out to the Versatec as fast as possible. Warning: there is some
+ * inline assembly code used in inner loops, where the C compiler
+ * produced particuarly poor code.
+ *
+ * We use a technique known as a `band buffer', where we keep track
+ * of what has yet to be written to the Versatec in a buffer that
+ * represents a `band' across the current page, analagous to a magnifying
+ * bar across the page. Only the region in the band can be written,
+ * and the band moves only downward; this is why verser1 must sort
+ * each page, at least by y coordinate. This also implies that the
+ * `tallest' object we can write is the same height as the band. This
+ * is a problem for large characters. For these there is some (as yet
+ * unimplemented) code that will ask for a `part' of each character
+ * to be drawn into the band. The character would then be repeated
+ * with a request for the next part when the band has moved down to
+ * just below the bottom of the previous part. Rules are also broken
+ * up as appropriate (and that code *is* implemented).
+ *
+ * Another important point is that the band buffer is treated as a
+ * `cylinder' rather than a `strip': we write bits onto the cylinder,
+ * then roll it forward over the page, moving the bits off the cylinder
+ * and onto the paper, leaving that part of the cylinder clean, ready
+ * for more bits. The variable `CurRow' points at the current row
+ * in the buffer/on the cylinder, and `FirstRow' and `LastRow' bound
+ * the `dirty' part of the cylinder. Modular arithmetic suffices to
+ * change linear to cylindrical.
+ *
+ * Whenever CurRow is more than MIN_OUT rows ahead of FirstRow, we
+ * write out that much of the cylinder, cleaning it. This keeps the
+ * paper moving, lest the developer soak one spot and produce `streaky'
+ * output.
+ *
+ * Yet another point of note is that because the band always moves
+ * `down' on the page, we need only a positive offset from the current
+ * row to move to a new row. This means (among other things) that we
+ * can use negative offsets for special purposes.
+ */
+
+#include <errno.h>
+#include <setjmp.h>
+#include <stdio.h>
+#include <sys/vcmd.h>
+#ifdef ACCOUNT_FILE
+#include <pwd.h>
+#endif ACCOUNT_FILE
+#include "types.h"
+#include "conv.h"
+#include "fio.h"
+#include "font.h"
+#include "verser.h"
+
+#define SPEED_HACK
+
+char *ProgName;
+extern int errno;
+extern char *optarg;
+extern int optind;
+
+/* Globals */
+jmp_buf failbuf; /* in case of Versatec write() problems */
+
+struct font *Fonts[NFONTS]; /* the fonts */
+
+char TeXFontDesc[256]; /* getenv("TEXFONTDESC") from verser1 */
+
+int RasterOrientation; /* ROT_NORM or ROT_RIGHT, based on HFlag */
+
+int DFlag; /* -d => output discarded */
+int HFlag; /* -h => horizontal (rotated bitmaps) */
+int SFlag; /* -s => silent processing */
+int TFlag; /* -t => output to tape */
+int Debug; /* -D => debug flag */
+
+char VBuffer[ROWS][COLUMNS]; /* Versatec band buffer */
+
+int CurRow; /* current row in buffer */
+int CurCol; /* current column in buffer */
+int FirstRow; /* the first row used */
+int LastRow; /* the last row used */
+int NLines; /* counts lines; used for pagefeeds */
+int Pages; /* counts pages; for accounting */
+
+int vp; /* Versatec file descriptor */
+
+int pltmd[] = {VPLOT, 0, 0};/* print & plot mode, for ioctl */
+int prtmd[] = {VPRINT, 0, 0};
+
+#ifdef ACCOUNT_FILE
+struct passwd *getpwuid();
+#endif ACCOUNT_FILE
+
+/*
+ * RowsBetween tells how many rows (in cylindrical arithmetic) there
+ * are between the first position and the second. If the second value
+ * is less than the first value, add ROWS to do the appropriate modular
+ * arithmetic. We cannot use `%' as C `%' is machine-dependent with
+ * respect to negative values.
+ */
+#define RowsBetween(f, n) ((n) >= (f) ? (n) - (f) : (n) - (f) + ROWS)
+
+/*
+ * This is it... on your marks ... get set ... main!
+ */
+main(argc, argv)
+ int argc;
+ register char **argv;
+{
+ register int c;
+ register char *s;
+ int dpi, usermag, num, denom, dvimag;
+ int VFlag = 0;
+#ifdef ACCOUNT_FILE
+ int acct_fd;
+
+ acct_fd = open(ACCOUNT_FILE, 1);
+ (void) setuid(getuid());
+#endif ACCOUNT_FILE
+
+ ProgName = *argv;
+
+ if (setjmp(failbuf)) { /* still have to do accounting */
+#ifdef ACCOUNT_FILE
+ /*
+ * Kind of strange to charge for a printout that failed
+ * because we ran out of paper, but that was the way they
+ * wanted it....
+ */
+ if (NLines)
+ Pages++;/* count the partial page */
+ DoAccount(acct_fd);
+#endif ACCOUNT_FILE
+ exit(1);
+ /* NOTREACHED */
+ }
+ while ((c = getopt(argc, argv, "dstv:D")) != EOF) {
+ switch (c) {
+
+ case 'd': /* output to /dev/null */
+ DFlag++;
+ break;
+
+ case 's': /* silent processing except for errors */
+ SFlag++;
+ break;
+
+ case 't': /* output to tape (not implemented) */
+ TFlag++;
+ error(0, 0, "tape option not yet implemented");
+ break;
+
+ case 'v': /* Versatec already open as fd <n> */
+ VFlag++;
+ vp = atoi(optarg);
+ break;
+
+ case 'D':
+ Debug++;
+ break;
+
+ case '?':
+ fprintf(stderr, "Usage: %s [-d] [-s] [-t] [file]\n",
+ ProgName);
+ exit(1);
+ }
+ }
+ if (optind < argc)
+ if (freopen(argv[optind], "r", stdin) == NULL)
+ error(1, 0, "can't open %s", argv[optind]);
+
+ HFlag = getchar();
+ if ((HFlag >> 1) != VERSION)
+ error(1, 0, "input file is not version %d", VERSION);
+ HFlag &= 1;
+ RasterOrientation = HFlag ? ROT_RIGHT : ROT_NORM;
+
+ s = TeXFontDesc;
+ c = GetLong(stdin);
+ while (--c >= 0)
+ *s++ = getchar();
+ if (feof(stdin))
+ (void) GetByte(stdin); /* let GetByte do error */
+ *s = 0;
+
+ dpi = GetLong(stdin);
+ usermag = GetLong(stdin);
+ num = GetLong(stdin);
+ denom = GetLong(stdin);
+ dvimag = GetLong(stdin);
+ SetConversion(dpi, usermag, num, denom, dvimag);
+
+ fontinit(*TeXFontDesc ? TeXFontDesc : (char *) NULL);
+ ReadFonts();
+
+ if (DFlag) {
+ (void) fprintf(stderr, "Output will be discarded\n");
+ (void) fflush(stderr);
+ vp = open("/dev/null", 1);
+ } else {
+ if (!VFlag) {
+ vp = open(VERSATEC_FILE, 1);
+ if (vp < 0) {
+ if (errno == ENXIO)
+ error(1, 0, "\
+can't open versatec---already in use");
+ if (errno == EIO)
+ error(1, 0, "\
+can't open versatec---device offline");
+ error(1, errno, "can't open %s",
+ VERSATEC_FILE);
+ }
+ }
+ ioctl(vp, VSETSTATE, pltmd);
+ }
+
+ if (!HFlag)
+ CutMarks(); /* initial cut marks */
+
+ ReadInput();
+
+ FormFeed(0); /* end up in print mode */
+
+ if (!SFlag)
+ (void) putc('\n', stderr);
+
+#ifdef ACCOUNT_FILE
+ DoAccounting(acct_fd);
+#endif ACCOUNT_FILE
+
+ exit(0);
+}
+
+#ifdef ACCOUNT_FILE
+/*
+ * Accounting is done by writing the program name ("tex"), the user name,
+ * and the number of pages at the end of the file. (The program name is
+ * for statistics.)
+ */
+DoAccounting(fd)
+ int fd;
+{
+ register struct passwd *p;
+ char buf[128];
+
+ if (fd < 0 || (p = getpwuid(getuid())) == 0)
+ return;
+
+ /*
+ * The '+ 2' is because there is an extra page at the end, and
+ * because the Versatec does pagefeeds when it is opened.
+ */
+ (void) sprintf(buf, "tex %s %d\n", p->pw_name, Pages + 2);
+ (void) lseek(fd, 0L, 2);
+ (void) write(fd, buf, strlen(buf));
+}
+#endif ACCOUNT_FILE
+
+/*
+ * Read the font definitions.
+ *
+ * Anti-streak hack: get the rasters ahead of time, #ifdef SPEED_HACK.
+ */
+ReadFonts()
+{
+ register struct font *f, **fp;
+ register int c;
+ register char *s;
+#ifdef SPEED_HACK
+ register struct glyph *g;
+#endif
+ i32 mag, dsize;
+ char *fname;
+ char nm[512];
+
+ if (!SFlag)
+ (void) fprintf(stderr, "[fonts:\n");
+ fp = Fonts;
+ while (GetByte(stdin) == 1) {
+ (void) GetLong(stdin); /* checksum */
+ mag = GetLong(stdin); /* magfactor */
+ dsize = GetLong(stdin); /* design size */
+ c = GetLong(stdin);
+ s = nm;
+ while (--c >= 0)
+ *s++ = getchar();
+ if (feof(stdin))
+ (void) GetByte(stdin); /* let GetByte do error */
+ *s = 0;
+ f = GetFont(nm, mag, dsize, "versatec", &fname);
+ if (f == NULL) {
+ GripeCannotGetFont(nm, mag, dsize, "versatec", fname);
+ exit(1);
+ /* NOTREACHED */
+ }
+ if (Debug) {
+ (void) fprintf(stderr, "[%s -> %s]\n",
+ Font_TeXName(f), fname);
+ (void) fflush(stderr);
+ }
+ if (!SFlag) {
+ register char *t = fname;
+
+ s = fname;
+ while (*s)
+ if (*s++ == '/' && *s)
+ t = s;
+ (void) fprintf(stderr, " %s\n", t);
+ }
+#ifdef SPEED_HACK
+ for (c = 0; c < 128; c++) {
+ g = GLYPH(f, c);
+ if (GVALID(g))
+ (void) RASTER(g, f, RasterOrientation);
+ }
+#endif
+ *fp++ = f;
+ }
+ if (!SFlag)
+ (void) fprintf(stderr, "]\n");
+}
+
+/*
+ * Read the input stream, decode it, and put character rasters or rules at
+ * the positions given.
+ */
+ReadInput()
+{
+ register int yx, fcp, height;
+
+ /*
+ * Loop forever. I had a `for (;;)' but everything crept off the
+ * right side of the screen.
+ */
+next:
+ fGetLong(stdin, yx); /* position */
+ fGetLong(stdin, fcp); /* character, most likely */
+ if (feof(stdin))
+ return; /* done */
+
+ /*
+ * A `position' of -1 indicates either a rule or an end of page.
+ * Anything else is a character.
+ */
+ if (yx != -1) { /* place character */
+ register struct glyph *g;
+ register struct font *f;
+ register int fnum;
+
+ /*
+ * Any delta-y required is stored in the upper 16 bits of yx.
+ */
+ if ((height = yx >> 16) != 0)
+ MoveDown(height);
+ /*
+ * Extract the x, font, char, and part info into CurCol,
+ * fnum, yx, and fcp.
+ */
+ CurCol = yx & 0xffff;
+ fnum = fcp >> FONTSHIFT;
+ yx = (fcp >> CHARSHIFT) & CHARMASK;
+ fcp = fcp & PARTMASK;
+ f = Fonts[fnum]; /* trusting */
+ g = GLYPH(f, yx);
+
+ /*
+ * In case this character does not fit, write
+ * out the used part of the band. It had better
+ * fit afterward....
+ */
+ height = g->g_height;
+ if (height >= ROWS - RowsBetween(FirstRow, CurRow))
+ DumpTopOfBand();
+ if (fcp) /* cannot handle these yet */
+ error(0, 0, "\
+part code not implemented; skipping char %d in %s",
+ yx, f->f_path);
+ else if (HASRASTER(g)) {
+#ifdef SPEED_HACK
+ /* XXX, but saves time */
+ VWriteChar(g->g_raster, height, g->g_width);
+#else
+ VWriteChar(RASTER(g, f, RasterOrientation),
+ height, g->g_width);
+#endif
+ }
+ /* dump if we can do at least MIN_OUT rows */
+ if (RowsBetween(FirstRow, CurRow) > MIN_OUT)
+ DumpTopOfBand();
+ goto next; /* done with character */
+ }
+
+ /*
+ * If the `character' is negative, we need to move down first,
+ * possibly because this is an end-of-page. If this is not the
+ * end of the page, it must be a rule.
+ */
+ if (fcp < 0) { /* move down */
+ yx = -fcp;
+ fGetLong(stdin, fcp); /* junk */
+ fGetLong(stdin, fcp);
+ if (fcp == 0) { /* end page */
+ /* dump entire band */
+ WriteBuf(&VBuffer[0][0], FirstRow, LastRow, 1);
+ CurRow = LastRow = FirstRow;
+ if (!HFlag) {
+ WriteBlanks(yx - NLines);
+ CutMarks();
+ } else
+ FormFeed(1);
+ if (!SFlag)
+ (void) fprintf(stderr, ".");
+ NLines = 0;
+ Pages++;
+ goto next; /* all done */
+ }
+
+ MoveDown(yx); /* must be a rule; move down by yx rows */
+ }
+
+ /*
+ * At this point we have a rule to put at the current
+ * position, CurRow.
+ */
+ height = (fcp & 0xff00) >> 8;
+ /* make sure it fits */
+ if (height >= ROWS - RowsBetween(FirstRow, CurRow))
+ DumpTopOfBand();
+ VWriteRule(fcp);
+ goto next; /* done with rule */
+}
+
+/*
+ * Write the given raster for the given character.
+ *
+ * Basically, the task is to move bits from the raster to the Versatec
+ * buffer. However, because the character being plotted can be on an
+ * arbitrary bit boundary, things are not as simple as we might like.
+ * The solution used here is to shift each raster value right, OR it
+ * into the buffer, then (at the next location) OR in the bits that
+ * `fell off the right edge'.
+ */
+VWriteChar(rastp, height, width)
+ char *rastp; /* raster pointer */
+ int height, width; /* height & width of char */
+{
+ register char *bp; /* Versatec buffer pointer [r11] */
+ register char *rp; /* raster pointer [r10] */
+ register int rshift; /* right shift index [r9] */
+ register int lshift; /* left shift index [r8] */
+ register int j; /* width loop downcounter */
+ register int o; /* offset to next row in buffer */
+ int row; /* current row in buffer */
+ int col; /* column in buffer of left edge */
+ int i; /* height loop downcounter */
+ int w; /* raster width (bytes) */
+
+ if ((rp = rastp) == NULL)
+ return; /* an all-white character (`cannot happen') */
+
+ row = CurRow;
+ col = CurCol >> 3;
+ i = height;
+ w = (width + 7) >> 3;
+ o = COLUMNS - w;
+
+#if defined(lint) || !defined(vax)
+ rshift = CurCol & 7;
+ lshift = 8 - rshift;
+#else lint || !vax
+ rshift = -(CurCol & 7); /* Vax does '>>' as negative '<<' */
+ lshift = 8 + rshift;
+#endif lint || !vax
+ bp = &VBuffer[row][col];
+
+#define avoiding_shifts_is_faster /* but is it??? */
+#ifdef avoiding_shifts_is_faster
+ /*
+ * One out of eight or so times, the shift values will be
+ * zero. This makes the code run faster.
+ */
+ if (rshift == 0) {
+ while (--i >= 0) {
+ j = w;
+ while (--j >= 0)
+ *bp++ |= *rp++;
+ if (++row >= ROWS) {
+ row = 0;
+ bp = &VBuffer[0][col];
+ } else
+ bp += o;
+ }
+ } else
+#endif
+ {
+ while (--i >= 0) {
+ j = w;
+ while (--j >= 0) {
+#if defined(lint) || !defined(vax)
+ *bp++ |= (*rp & 255) >> rshift;
+ *bp |= (*rp++ & 255) << lshift;
+#else lint || !vax
+ /*
+ * THE FOLLOWING ASSEMBLY CODE IS INSERTED
+ * BECAUSE THE COMPILER CAN'T OPTIMIZE THE
+ * C CODE WORTH A DARN
+ */
+ asm(" movzbl (r10)+,r1 # *rp++ & 255");
+ asm(" ashl r9,r1,r0 # >> rshift");
+ asm(" bisb2 r0,(r11)+ # *bp++ |=");
+ asm(" ashl r8,r1,r0 # << lshift");
+ asm(" bisb2 r0,(r11) # *bp |=");
+#endif lint || !vax
+ }
+ if (++row >= ROWS) {
+ row = 0;
+ bp = &VBuffer[0][col];
+ } else
+ bp += o;
+ }
+ }
+
+ j = height + CurRow - 1;/* have now set bits this far */
+ if (j >= ROWS)
+ j -= ROWS; /* keep it modular */
+
+ /*
+ * There are two cases. Either the buffer is not currently wrapped,
+ * in which case the regions past LastRow or before FirstRow extend
+ * it; or it is wrapped, in which case the region between LastRow
+ * and FirstRow extends it:
+ *
+ * case 1 case 2
+ * -------- --------
+ * | | last ->| XXXX |
+ * first ->| XXXX | | |
+ * | XXXX | | |
+ * last ->| XXXX | first ->| XXXX |
+ * | | | XXXX |
+ * -------- --------
+ *
+ * The `X's mark the region that is in use; the blank spaces
+ * mark the region that causes the `last' value to change.
+ */
+ if (FirstRow <= LastRow) {
+ /* first case: not wrapped */
+ if (j < FirstRow || j > LastRow)
+ LastRow = j;
+ } else {
+ /* second case: wrapped */
+ if (j > LastRow && j < FirstRow)
+ LastRow = j;
+ }
+}
+
+/*
+ * Write a rule at the current row according to the (packed) information in
+ * 'info'. This includes the x position and the height and width of the
+ * rule.
+ */
+VWriteRule(info)
+ int info;
+{
+ register char *bp; /* buffer pointer */
+ register int j;
+ register int lbits; /* bits along left */
+ register int rbits; /* bits along right */
+ register int o; /* offset to next row */
+ register int i;
+ register int full; /* number of 8 bit words to set */
+ register int height; /* rule height */
+ register int width; /* rule width */
+ register int row;
+ register int col;
+
+ i = info;
+ CurCol = (i & 0x7fff0000) >> 16;
+ height = (i & 0xff00) >> 8;
+ width = i & 0xff;
+ col = CurCol >> 3;
+ row = CurRow;
+ j = CurCol & 7; /* bit # of start position */
+ lbits = 0xff >> j; /* bits to set along left edge */
+ /* there are 8-j bits set in lbits */
+ o = 8 - j - width;
+ if (o > 0) { /* then lbits has o too many bits set */
+ lbits >>= o;
+ lbits <<= o; /* puts zeros into o righthand bits */
+ rbits = 0;
+ full = 0;
+ } else {
+ i = (CurCol + width) & 7; /* bit # of ending position */
+ rbits = 0xff00 >> i; /* bits to set along right edge */
+ /* there are i bits set in rbits (well, in the low byte) */
+ full = (width - i - (8 - j)) >> 3;
+ }
+ bp = &VBuffer[row][col];
+ i = height;
+
+ /* Often "full" is zero, which makes things faster */
+ if (full) { /* oh well */
+ o = COLUMNS - full - 1;
+ while (--i >= 0) {
+ *bp++ |= lbits;
+ for (j = full; --j >= 0;)
+ *bp++ |= 0xff;
+ *bp |= rbits;
+ if (++row >= ROWS) {
+ row = 0;
+ bp = &VBuffer[0][col];
+ } else
+ bp += o;
+ }
+ } else {
+ o = COLUMNS - 1;
+ while (--i >= 0) {
+ *bp++ |= lbits;
+ *bp |= rbits;
+ if (++row >= ROWS) {
+ row = 0;
+ bp = &VBuffer[0][col];
+ } else
+ bp += o;
+ }
+ }
+ i = CurRow + height - 1;
+ if (i >= ROWS)
+ i -= ROWS;
+ /*
+ * This is another way of expressing both cases 1 and 2 in
+ * VWriteChar(). I think the other way is likely to be
+ * faster, and characters occur far more frequently; but this
+ * is the more readable by far.
+ */
+ if (RowsBetween(FirstRow, LastRow) < RowsBetween(FirstRow, i))
+ LastRow = i;
+}
+
+/*
+ * Dump out the top portion of the band (rows [Firstrow, CurRow)).
+ */
+DumpTopOfBand()
+{
+
+ /*
+ * To exclude CurRow, subtract one, but modularly, modularly!
+ */
+ WriteBuf(&VBuffer[0][0], FirstRow, CurRow ? CurRow - 1 : ROWS - 1, 1);
+ FirstRow = CurRow;
+}
+
+/*
+ * Move the current row in the band buffer down by delta rows, by,
+ * if necessary, writing out the currently-used portion of the buffer.
+ */
+MoveDown(delta)
+ register int delta;
+{
+
+ if (delta >= ROWS - RowsBetween(FirstRow, CurRow)) {
+ /*
+ * Need to roll the cylinder forward. Write out the used
+ * part, and then write as many blank lines as necessary.
+ */
+ WriteBuf(&VBuffer[0][0], FirstRow, LastRow, 1);
+ WriteBlanks(delta - RowsBetween(CurRow, LastRow) - 1);
+ CurRow = LastRow = FirstRow; /* band is now empty */
+ } else {
+ /*
+ * Because RowsBetween returns nonnegative integers, we
+ * know delta <= ROWS, so can do mod more quickly thus:
+ */
+ CurRow += delta; /* result < 2*ROWS */
+ if (CurRow >= ROWS)
+ CurRow -= ROWS; /* now result < ROWS */
+ }
+}
+
+/*
+ * Write the lines between the first and last inclusive from the given
+ * buffer. If 'cl', clear after writing.
+ */
+WriteBuf(buf, first, last, cl)
+ register char *buf;
+ register int first, last;
+{
+
+ if (first > last) { /* recursively do wrapped part first */
+ WriteBuf(buf, first, ROWS - 1, cl);
+ first = 0;
+ }
+ buf = &buf[first * COLUMNS];
+ last = COLUMNS * (first = last - first + 1);
+
+ /*
+ * If the write fails, the Versatec is probably out of paper, and in
+ * any case, things are probably in bad shape.
+ */
+ if (write(vp, buf, last) != last) {
+ error(0, errno, "Versatec write error");
+ longjmp(failbuf, 1);
+ }
+ if (cl)
+ bzero(buf, (unsigned) last);
+ NLines += first;
+}
+
+/*
+ * Write 'n' blank lines.
+ */
+WriteBlanks(n)
+ register int n;
+{
+ register int k;
+ static char nullbuf[MIN_OUT][COLUMNS];
+
+ while (n > 0) {
+ k = n > MIN_OUT ? MIN_OUT : n;
+ WriteBuf(&nullbuf[0][0], 0, k - 1, 0);
+ n -= k;
+ }
+}
+
+/*
+ * Write cut marks. We borrow row 0 of VBuffer for this.
+ */
+CutMarks()
+{
+ register short *bp = (short *) &VBuffer[0][0];
+
+ *bp = 0xffff;
+ bp[(COLUMNS / 2) - 1] = 0xffff;
+ WriteBuf(&VBuffer[0][0], 0, 0, 1);
+}
+
+/*
+ * Perform a page feed. Restore plot mode if `setplot'.
+ */
+FormFeed(setplot)
+ int setplot;
+{
+ ioctl(vp, VSETSTATE, prtmd);
+ (void) write(vp, "\f", 2); /* \0 really IS required occasionally */
+ if (setplot)
+ ioctl(vp, VSETSTATE, pltmd);
+}
diff --git a/dviware/umddvi/doc/box.tex b/dviware/umddvi/doc/box.tex
new file mode 100644
index 0000000000..f33c727dfb
--- /dev/null
+++ b/dviware/umddvi/doc/box.tex
@@ -0,0 +1,30 @@
+% Fancy frames
+%
+% Usage:
+% \fancyframebox {rule thickness} {separation from inner guy} {inner guy}
+%
+% \makeemptybox {width} {height} {depth}
+
+\newbox\FancyboxA
+\newdimen\FancyboxD
+
+\def\makeemptybox#1#2#3{\setbox\FancyboxA=\hbox{}\wd\FancyboxA=#1\relax
+ \ht\FancyboxA=#2\relax \dp\FancyboxA=#3\relax \box\FancyboxA }
+
+\def\fancyframebox#1#2#3{%
+ \leavevmode
+ \setbox\FancyboxA=\hbox{#3}%
+ \dimen\FancyboxD=#1\relax
+ \advance\dimen\FancyboxD by #2\relax
+ \advance\dimen\FancyboxD by \dp\FancyboxA
+ \hbox{%
+ \lower\dimen\FancyboxD\hbox{%
+ \vbox{%
+ \hrule height #1\relax
+ \hbox{%
+ \vrule width #1\relax
+ \kern #2\relax
+ \vbox{\vskip #2\relax\box\FancyboxA\vskip #2\relax}%
+ \kern #2\relax
+ \vrule width #1\relax}%
+ \hrule height #1\relax}}}}
diff --git a/dviware/umddvi/doc/doc.tex b/dviware/umddvi/doc/doc.tex
new file mode 100644
index 0000000000..eb6fb4ce2f
--- /dev/null
+++ b/dviware/umddvi/doc/doc.tex
@@ -0,0 +1,82 @@
+% doc.tex - documentation on the C-TeX distribution code
+
+% 11pt
+\magnification=\magstephalf
+
+% Some of the information herein is duplicated in other files
+
+% This file itself is woefully incomplete.
+
+\font\titlebf=cmssbx10 scaled \magstep2
+\font\titlerm=cmr10 scaled \magstep2
+\font\smalltitlerm=cmr10 scaled \magstep1
+\font\csc=cmcsc10
+\chardef\pipe=`| \chardef\hat="5E \chardef\bs='134 \chardef\tilde="7E
+
+\headline={\tenrm\hfil\ifnum\pageno>0 C-\TeX\hfil\llap{\folio}\fi}
+\footline={}
+
+\input section % sections
+\input box % fancy boxes
+\input dow % day of week
+\input verb % verbatim text
+
+\def\today{\ifcase\month\or January\or February\or March\or April\or
+May\or June\or July\or August\or September\or October\or November\or
+December\ \number\day, \number\year}
+
+\def\ctex{C-\TeX}
+
+\parskip=.5\baselineskip plus1pt
+\DoContents
+\pageno=0
+\null\vskip 3cm
+\centerline{\titlerm \ctex}
+\vskip 1.5cm
+\centerline{\smalltitlerm Chris Torek}
+\vskip 1cm
+\centerline{Department of Computer Science}
+\centerline{University of Maryland}
+\centerline{College Park, Maryland 20742}
+\vskip 1cm
+
+\line{Revision 0 as of \DayOfWeek, \today}
+
+{\narrower\narrower\vskip.5\baselineskip
+abstract here
+
+}
+
+\vfill\eject
+\pageno=1
+
+\section 1 {Introduction}
+\input intro
+
+\section 1 {User Guide}
+%\input uguide
+
+\esection 2 {DVI-to-Device Conversion Programs (`Drivers')}
+\input dvitodev
+
+\section 2 {DVI-to-DVI Conversion Programs}
+\input dvitodvi
+
+\section 1 {Administration}
+\esection 2 {Installation}
+\input install
+
+\section 2 {Updates}
+\input updates
+
+\section 1 {Writing \ctex\ Software}
+\esection 2 {The \ctex\ Library}
+\input library
+
+\section 2 {An Overview of the Imagen Driver}
+\input exdriver
+
+% \section 1 {anything else I may think of}
+
+\PrintTOC
+\bye
diff --git a/dviware/umddvi/doc/dow.tex b/dviware/umddvi/doc/dow.tex
new file mode 100644
index 0000000000..8668247679
--- /dev/null
+++ b/dviware/umddvi/doc/dow.tex
@@ -0,0 +1,32 @@
+% From: minow@decvax.UUCP (Martin Minow)
+%
+% \DayOfWeek expands to the day of the week ("Sunday", etc.)
+%
+\newcount\dow
+\def\DayOfWeek{\ifcase\dow Sunday\or Monday\or Tuesday\or Wednesday\or
+ Thursday\or Friday\or Saturday\fi}
+
+%
+% Calculate day of the week (0=Sunday, 1=Monday, etc.), result
+% into \dow.
+%
+{ \countdef\leap=1 % Leap year fingaler
+ \countdef\x=2 % Temp register
+ \countdef\y=3 % Another temp register
+% leap = year + (month - 14)/12;
+ \leap=\month \advance\leap by -14 \divide\leap by 12 \advance\leap by \year
+% dow = (13 * (month + 10 - (month + 10)/13*12) - 1)/5
+ \dow=\month \advance\dow by 10 \y=\dow \divide\y by 13 \multiply\y by 12
+ \advance\dow by -\y \multiply\dow by 13 \advance\dow by -1 \divide\dow by 5
+% dow += day + 77 + 5 * (leap % 100)/4
+ \advance\dow by \day \advance\dow by 77
+ \x=\leap \y=\x \divide\y by 100 \multiply\y by 100 \advance\x by -\y
+ \multiply \x by 5 \divide\x by 4 \advance\dow by \x
+% dow += leap / 400
+ \x=\leap \divide\x by 400 \advance\dow by \x
+% dow -= leap / 100 * 2;
+% dow = (dow % 7)
+ \x=\leap \divide\x by 100 \multiply\x by 2 \advance\dow by -\x
+ \x=\dow \divide\x by 7 \multiply\x by 7 \advance\dow by -\x
+ \global\dow=\dow
+}
diff --git a/dviware/umddvi/doc/dvitodev.tex b/dviware/umddvi/doc/dvitodev.tex
new file mode 100644
index 0000000000..5618f7f2c5
--- /dev/null
+++ b/dviware/umddvi/doc/dvitodev.tex
@@ -0,0 +1,9 @@
+the task
+
+fonts, fontdesc
+
+maxdrift
+
+imagen specific stuff
+
+versatec specific stuff
diff --git a/dviware/umddvi/doc/dvitodvi.tex b/dviware/umddvi/doc/dvitodvi.tex
new file mode 100644
index 0000000000..24046503e6
--- /dev/null
+++ b/dviware/umddvi/doc/dvitodvi.tex
@@ -0,0 +1,5 @@
+why?
+
+dviselect
+
+dvipick? dviconcat?
diff --git a/dviware/umddvi/doc/figures.tex b/dviware/umddvi/doc/figures.tex
new file mode 100644
index 0000000000..103258d86a
--- /dev/null
+++ b/dviware/umddvi/doc/figures.tex
@@ -0,0 +1,19 @@
+\newcount\fignum
+\fignum=1
+
+\def\beginfigure{%
+% \goodbreak % dunno if I really want this yet
+ \midinsert
+ \hrule
+ \vskip\baselineskip
+}
+
+\def\endfigure#1{%
+ \vskip\baselineskip % 1 blank line
+ \centerline{Figure \the\fignum: #1} % caption
+ \medskip
+ \hrule
+ \vskip 1.5\baselineskip % extra space after the line
+ \advance\fignum by1
+ \endinsert
+}
diff --git a/dviware/umddvi/doc/install.tex b/dviware/umddvi/doc/install.tex
new file mode 100644
index 0000000000..2eab2c9488
--- /dev/null
+++ b/dviware/umddvi/doc/install.tex
@@ -0,0 +1,99 @@
+\def\bsd{{\csc BSD}}
+
+Before \ctex\ can be installed, it must be configured and compiled. As
+much of the configuration task as possible is deferred until after
+installation, but there is a bootstrap problem here: The runtime
+system must be configured to know where the runtime configuration is
+to be found. In addition, some of the library routines are necessarily
+system dependent. Clearly, the need for device drivers depends upon
+your devices. All of these should be properly configured in advance,
+though changing the configuration later is easy.
+
+All of the compile time configuration is intended to be performed by
+the makefiles. If you run a Unix machine, or even if this is the first
+and last time you will ever set up Unix software, you should be
+intimiately familiar with `make'. Once you have read the supplementary
+documentation on make, you are ready to peek at the Makefile in the
+{\tt lib} directory. This is the most system-dependent one, so we
+shall tackle it first.
+
+Scary, is it not? Well, whether or no, some explanation is in order.
+This Makefile has the same four standard targets as every other
+Makefile in the \ctex\ system: `all', `install', `clean', and
+`depend'. `All' puts the subsystem into shape for installation.
+`Install' copies the subsystem to its ultimate resting place. `Clean'
+removes anything that is not needed to remake the subsystem. And
+`depend'? This is the strangest one of all, and no doubt the scariest;
+alas, it is also one you may need to adjust. It uses a feature of the
+4.3\bsd\ compiler, the {\tt -M} flag, to get a list of
+dependencies, and inserts this list into the Makefile. Between the
+line marked `{\tt DO NOT DELETE THIS LINE}' and the end of the Makefile
+you will find a full (and I do mean {\it full}) list of dependencies.
+This list includes some of the standard system {\tt include} files,
+such as {\tt /usr/include/machine/machparam.h}. It may well be that
+your system does not {\it have} some of these files. This is not a
+problem; {\tt seek.c} should still compile and run. What {\it is} a
+problem is that `make' will believe it needs this file, even though (on
+your machine) it does not.
+
+If you are lucky enough to be using a 4.3\bsd\ compiler or one with the
+{\tt -M} flag, you can simply run `{\tt make depend}'. If you are on a
+4.2\bsd\ system, the dependency lists are probably already correct and
+can be left alone. If neither of these happy circumstances hold, a
+sure-fire fix is simply to remove the {\tt /usr/include} dependencies
+from the Makefile. Another option is to try, in place of the {\tt cc
+-M} command, the `{\tt getdep}' shell script provided in the `{\tt
+misc}' directory.
+
+The {\tt lib} directory Makefile exemplifies several more standard
+entries. {\tt DESTDIR} controls the top level directory for
+installation. Normally this is the null string: that is, files are
+installed in normal binary or manual directories. Setting it to (e.g.)
+`{\tt /nbsd}' would install everything in {\tt /nbsd/usr/}\dots. Two
+entries {\it not} in this Makefile are {\tt BINDIR} and {\tt MANDIR},
+which set the directories for executable programs (binaries) and for
+manuals. These default to {\tt /usr/local/bin} and {\tt /usr/man}.
+System V sites (if any run \TeX) may need to tailor the manual
+installation commands to conform to System V standards.
+
+This pretty well covers the standard Makefile entries. The {\tt lib}
+Makefile, however, is full of non-standard entries as well. Because it
+attempts to hide system dependencies from the rest of the \ctex\ code,
+it is itself necessarily system dependent. There are two assembly
+language files for 4.1BSD, and one `miscellaneous' file for 4.2BSD
+Vaxen and Pyramids. The former are listed in the {\tt ASSRC} and {\tt
+ASOBJ} macros, and the latter are listed in the {\tt MISCC} and {\tt
+MISCO} macros. These must be adjusted to match your system. If you
+are running some other system, you may need to write your own {\it bcopy} and
+{\it bzero} routines, starting with the C versions in the {\tt misc} directory.
+On System V machines, {\it memcpy} and {\it memset} may be used instead.
+
+BEGIN TRASH
+
+
+When you have the makefiles correct, run `make conf' to configure
+for the Imagen and/or Versatec. Then type `make' to compile
+everything. If all is successful, type `make install' to install
+everything.
+
+Versatec stuff:
+-------- -----
+
+The Versatec driver has page accounting built in. If compiled with
+ACCOUNT_FILE defined, it will write (to ACCOUNT_FILE) a line of
+the form
+
+ tex <username> <number of pages used>
+
+The account file can be defined in either dev/Makefile or h/verser.h.
+
+There is also a definition for the device name `/dev/vp0' in
+h/verser.h, although a redefinition in dev/Makefile will override
+it; alternatively, if your spooling program opens the Versatec
+itself, use the `-v' argument to verser2. `-v 1' implies that
+the Versatec is already open as standard output, for example.
+
+The Imagen driver ought to work for all of the Imagen printers,
+though all I've tested is the 8/300. The `iptex' shell script will
+have to be adjusted for the 10/240, which needs nonzero default
+margins.
diff --git a/dviware/umddvi/doc/intro.tex b/dviware/umddvi/doc/intro.tex
new file mode 100644
index 0000000000..cecb151e5b
--- /dev/null
+++ b/dviware/umddvi/doc/intro.tex
@@ -0,0 +1,20 @@
+% intro.tex - introduction
+
+\line{\qquad \dots or, Just what {\it is} \ctex\ anyway?}
+
+It is perhaps necessary first to define what \ctex\ is {\it not}.
+\ctex\ is not a complete rewrite of \TeX\ in C. It is a tribute to the
+skill of its author Donald E.~Knuth that, despite the fact that \TeX\
+was written in a subset of {\csc pascal} that does not include even,
+e.g., memory allocation, this has not yet proven necessary.
+
+Nor is \ctex\ a monolithic system. Rather, it is a collection of small
+programs---tools---that work together to provide a large number of
+operations from a small set of operators. The author believes that
+this has been a problem with older \TeX ware: each program has built
+into many of the same functions, but using different code that produces
+different results or requires differing and sometimes incompatible
+controls. This is an unnecessary complication that can be resolved by
+moving those functions, either into separate programs, or into library
+code that is then shared directly. This is the approach that has been
+taken in \ctex.
diff --git a/dviware/umddvi/doc/makefile b/dviware/umddvi/doc/makefile
new file mode 100644
index 0000000000..1f00582937
--- /dev/null
+++ b/dviware/umddvi/doc/makefile
@@ -0,0 +1,36 @@
+# Makefile for documentation
+
+doc.dvi: doc.tex
+ tex doc.tex
+
+clean:
+ rm -f *.dvi *.log texput.*
+
+install:
+
+depend:
+ for i in doc; do \
+ egrep "\\input" $$i.tex | egrep -v "[ ]*%" | \
+ sed -e "s/\\\\input/$$i.tex:/" -e "s/%.*//" -e "s/$$/.dvi/"; \
+ done | awk '{ if ($$1 != prev) { if (rec != "") print rec; \
+ rec = $$0; prev = $$1; } \
+ else { if (length(rec $$2) > 78) { print rec; rec = $$0; } \
+ else rec = rec " " $$2 } } \
+ END { print rec }' >makedep
+ echo '/^# DO NOT DELETE THIS LINE/+2,$$d' >eddep
+ echo '$$r makedep' >>eddep
+ echo 'w' >>eddep
+ cp Makefile Makefile.bak
+ ed - Makefile <eddep
+ rm eddep makedep
+ echo '# DEPENDENCIES MUST END AT END OF FILE' >>Makefile
+ echo '# IF YOU PUT STUFF HERE IT WILL GO AWAY' >>Makefile
+ echo '# see make depend above' >>Makefile
+
+# DO NOT DELETE THIS LINE -- make depend uses it
+
+doc.tex: intro.dvi dvitodev.dvi dvitodvi.dvi install.dvi updates.dvi
+doc.tex: library.dvi exdriver.dvi
+# DEPENDENCIES MUST END AT END OF FILE
+# IF YOU PUT STUFF HERE IT WILL GO AWAY
+# see make depend above
diff --git a/dviware/umddvi/doc/section.tex b/dviware/umddvi/doc/section.tex
new file mode 100644
index 0000000000..f56c1ef8a1
--- /dev/null
+++ b/dviware/umddvi/doc/section.tex
@@ -0,0 +1,105 @@
+% for automagic equation numbering
+
+\newcount\LastEqNum
+\LastEqNum=0
+\def\BuildEqBox#1{\hbox{{\rm\the\count1--\the#1}}}
+\def\nexteqnum{{\count9=\LastEqNum\advance\count9 by1
+ \BuildEqBox{\count9}}}
+\def\lasteqnum{\BuildEqBox{\LastEqNum}}
+\def\neweqnum{\global\advance\LastEqNum by1 \lasteqnum}
+\def\namelasteq#1{\xdef#1{\BuildEqBox{\LastEqNum}}}
+
+% for automagic section numbering
+
+\newcount\sectiondepth
+\newbox\sectnum
+\newif\iftoc
+\let\Z=\relax
+\def\SP{ }
+
+\def\sectA{\LastEqNum=0\goodbreak}
+\let\sectB=\goodbreak
+\let\sectC=\goodbreak
+\let\sectD=\goodbreak
+\let\sectE=\goodbreak
+\let\sectF=\goodbreak
+\let\sectG=\goodbreak
+\let\sectH=\goodbreak
+\let\sectI=\goodbreak
+
+% Start a new section. First argument is depth (1 to 9 please!), second
+% is caption. \esection is a section that has nothing above it and
+% shouldn't get a \goodbreak\bigskip.
+
+\outer\def\section{\bigskip\SECTION}
+\outer\def\esection{\nobreak\smallskip\SECTION}
+\def\SECTBAD{\errmessage{Section depths should be between 1 and 9}}
+\def\SECTION#1#2{%
+ \sectiondepth=#1
+ \ifcase\sectiondepth\SectBad\or\sectA\or\sectB\or\sectC\or
+ \sectD\or\sectE\or\sectF\or\sectG\or\sectH\or\sectI\else
+ \SECTBAD\fi
+ \advance\count\sectiondepth by1
+ \loop\advance\sectiondepth by1 % zero all lower levels
+ \ifnum\sectiondepth<10\count\sectiondepth=0\repeat
+ \sectiondepth=1
+ \setbox\sectnum=\hbox{\number\count1}%
+ \global\def\Sectnum{\number\count1}%
+ \loop\ifnum\sectiondepth<#1 % Glue together each level
+ \advance\sectiondepth by1
+ \ifnum0=\count\sectiondepth % force to 1
+ \set\count\sectiondepth=1
+ \fi
+ \setbox\sectnum=\hbox
+ {\unhbox\sectnum.\number\count\sectiondepth}%
+ \global\edef\Sectnum{\Sectnum.\number\count\sectiondepth}%
+ \repeat
+ \message{\Sectnum. #2}%
+ \setbox0=\hbox{\bf\copy\sectnum.\hskip1em#2}%
+ \def\text{\Sectnum.\SP!#2}%
+ \tocentry{#1}{\text}{\box0\hfil}
+ \ignorespaces
+}
+
+% unnumbered section
+\def\unsection#1{%
+ \message{#1}%
+ \setbox0=\hbox{\bf#1}%
+ \def\text{\SP!#1}%
+ \tocentry{0}{\text}{\box0\hfil}%
+ \ignorespaces
+}
+
+% print arg 3 as a line, put arg 2 into the table of contents with
+% a "level" of arg 1
+% takes care of putting box0 out as a line, and putting it into the
+% table of contents if required
+\def\tocentry#1#2#3{%
+ \line{#3}% stuff to appear in the text
+ \nobreak\smallskip\nobreak % now in vert mode
+ \iftoc{\let\the=0 % make it unexpandable
+ \xdef\ixout{\write\inx{\Z#1\SP!#2!\SP\the\pageno.}}\ixout
+ }\fi
+}
+
+\ifx\titlefont\undefinecontrolsequence
+ \font\titlefont=cmssbx10 scaled\magstep2
+\fi
+\newcount\Siz
+\newwrite\inx
+\def\DoContents{\toctrue\immediate\openout\inx=\jobname.toc}
+\def\PrintTOC{\vfill\supereject\immediate\closeout\inx
+ \def\LeadFill{\leaders\hbox to .75em{\hss.\hss}\hfill}
+ \def\Z##1!##2!##3!##4.{
+ \Siz=##1\count1=\Siz
+ \advance\Siz by 1 \multiply\Siz by \count1
+ \divide\Siz by 2 \advance\Siz by -1
+ \dimen0=1em\multiply\dimen0 by \Siz
+ \Siz=##1\advance\Siz by 1
+ \dimen1=1em\multiply\dimen1 by \Siz
+ \line{\hskip\dimen0\hbox to\dimen1{##2\hfil}{##3}\LeadFill\hbox{##4}}
+ }
+ \centerline{\titlefont Table of Contents}\vskip .75in
+ \global\count0=-1
+ \input\jobname.toc
+}
diff --git a/dviware/umddvi/doc/texx.tex b/dviware/umddvi/doc/texx.tex
new file mode 100644
index 0000000000..8f739a9f63
--- /dev/null
+++ b/dviware/umddvi/doc/texx.tex
@@ -0,0 +1,226 @@
+\subsection{The Previewers}
+texx\ is a {\em previewer} for \dvi\ files which uses the X-11 window system.
+\texsun\ is a previewer for \dvi\ files which uses the SunView window system.
+Both previewers allow you to
+view documents on your workstation before printing them.
+
+Everything in the following
+description applies to both \texx\ and \texsun\ unless
+otherwise stated.
+
+\subsubsection{Painting}
+When you start xdvi, a window will be created on your display
+\footnote{
+ The interaction for this varies with the window manager you're using
+ and between \texx\ and \texsun.
+}
+and your document will be {\em painted} in that window.
+The size of the window corresponds to the size of the tallest and widest
+page of your document.
+If your display is wide enough, the window will have two {\em leaves},
+otherwise it will have a single {\em leaf}.
+Each leaf will be painted with a page from your document.
+
+texx\ takes some pains to provide the most viewable document possible.
+Normally, a \TeX\ document has an inch of margin added at the left and
+top margin.
+If reduction of this white space allows your document to be viewed
+at a large size, that margin is reduced.
+If you are using \texx\ or \texsun\ to preview documents you are working
+on, you may find it advantageous to specify a smaller document size
+to \TeX\ or \LaTeX, allowing you to preview your document at a readable size.
+
+\subsubsection{Shrinks}
+Because most workstations do not have a screen resolution approaching that
+of a laser printer,
+sacrifices must be made to provide suitable fonts.
+
+One solution would be to generate the \TeX\ fonts at your display resolution.
+This requires at least two sets of fonts, one for your printer and one
+for each differing screen resolution.
+Another approach is to use the high-resolution fonts for the printer
+and {\em shrink} them.
+This is the method used by \texx\ and \texsun,
+because it reduces the number of fonts
+and works with a great number of display resolutions.
+
+Fonts are shrunk using a {\em shrink factor},
+which is an integer in the range of 1 to 9.
+As an example, with a shrink factor of 4, a 4 by 4 set of pixels
+is reduced to a single pixel on your display.
+The pixel is turned on if $1/\mbox{\em blackness}$ pixels in the
+original sample were turned on.
+Normally, {\em blackness} is $3$, which was chosen by trial \& error,
+but it can be set using the {\tt -bl} option or by setting the
+{\tt Blackness} option in your defaults file.
+
+A shrink factor of 1 is a direct view of the fonts at a normal resolution.
+
+There are usually two goals to previewing documents.
+One is to view the {\em overall structure} of the document, e.g.
+to check if tables, equations and figures appear at the right spot.
+Another is to check {\em detail structure}, e.g. to check
+if the spacing around an equation looks right.
+The interface for \texx\ provides a {\em normal shrink} and a
+{\em large shrink} view of your document.
+At the normal shrink size, an entire page is visible, providing an
+overall view.
+At the large shrink size, details are more visible.
+
+\subsubsection{Differences Between \texx\ and \texsun}
+When documents are being painted, the cursor icon for \texx\ changes to a
+clock, indicating that you need to wait for the painting to finish.
+For \texsun, the cursor changes to an hourglass.
+When \texx\ is waiting for input, the cursor changes to a spraycan.
+When \texsun\ is waiting for input, the cursor changes to a bulls-eye.
+
+Unless the \texx\ window is {\em obscured} by another window,
+the image is painted directly to the display.
+If the \texx\ window is {\em obscured} by another window,
+the image is painted to a {\em pixmap}, which is displayed when the
+page is painted.
+{\em You should only obscure the \texx\ window when the cursor is
+a spraycan, not when it is a clock.}
+If the window is covered or obscured while it is being painted, the
+final image will not be correct.
+However, if you obscure the window (e.g. overlay it with a
+window for editing your document) while the spray scan is present,
+the window will be correctly painted when you turn pages.
+\texx\ does not take advantage of resized windows.
+
+\texsun allows somewhat more flexibility.
+Pages are painted directly to memory, and displayed when they are painted.
+You can obscure the \texsun\ window at any time.
+You can also enlargen the window.
+While this will not change the amount of visible text for the
+normal shrink size, the entire window is used to display the
+large shrink size.
+
+\subsubsection{Moving Around}
+In both \texx\ and \texsun,
+you move forward in your document by hitting
+the {\tt RETURN} or {\tt NEWLINE} key.
+If there is a single leaf, it will be erased and painted with the next page.
+If there are two leaves, the right hand page will be put on the left leaf
+and the left leaf will be painted with the next page.
+To move backward in your document, hit the {\tt DELETE} or {\tt BACKSPACE} key.
+If you type a number before hitting a key, you move forward or backward
+that number of pages.
+
+To move to a given page, type the number of the page and the ``{\tt g}''.
+To quit \texx, type ``{\tt q}''.
+To view a part of your document at the large shrink size,
+point the cursor at the part you are interested in and hit any mouse button.
+The spray can will change to a clock while the page is painted
+at the larger size.
+Since the entire page will not fit on the display at the larger size,
+it is printed to memory, and the part you pointed to is displayed.
+If your window has a single leaf, that leaf is overwritten with the
+enlarged image.
+In \texx,
+if your window has two leaves, the enlarged image is painted on the
+leaf not pointed to.
+This allows you to see the overall structure and the detail at the same
+time.
+In \texsun, the entire window is always used.
+
+When you release the mouse button, the page which was previously displayed
+on the over written leaf is restored.
+If you point to another spot {\em on the same page}, the page will not
+need to be recomputed.
+texx\ remembers the enlarged page as long as the normal sized page
+is visible, i.e. if you turn forward several pages, and then back up,
+you will need to recompute the enlarged page if you want to see the
+detail view.
+
+\subsubsection{Options}
+\texx\ allows you to control the layout of the window, using either
+the \texx\ command line your {\tt .XDefaults} file.
+Similarly, \texsun\ allows you to control the layout of the window
+using either the command line or your Sun {\tt .defaults} file.
+Table \ref{table:xdvi-options} lists the available options.
+Options in {\bf bold-face} apply to both \texx\ and \texsun.
+Options in {\sl slant-face} apply only to \texx,
+and optioned in {\it italics} apply only to \texsun.
+Normally, you invoke \texx\ by simply saying {\tt xdvi yourfile}.
+You invoke \texsun\ by simply saying {\tt \texsun\ yourfile}.
+If ``{\tt yourfile}'' can not be found, then the suffix ``{\tt .dvi}''
+is appended.
+%
+\begin{table}[hbt]
+\centering
+ \begin{tabular}{|l|c|c|p{2in}|}
+ \hline
+ XDefault & Command Line & Argument Type & Meaning \\
+ \hline \hline
+
+ {\bf ReverseVideo} & -rv
+ & {\em none } & Display document in reverse video \\
+
+ {\sl BorderWidth} & -bw
+ & {\em integer } & Change the width of the display border. \\
+
+ {\sl ForeGround} & -fg
+ & {\em color} & Change the foreground display color\\
+
+ {\sl BackGround} & -bg
+ & {\em color} & Change the background display color\\
+
+ {\sl HighLight} & -hl
+ & {\em color} & Change the highlight color \\
+
+ {\sl Border} & -bd
+ & {\em color} & Change the border color \\
+
+ {\sl Mouse} & -ms
+ & {\em color} & Change the mouse color \\
+
+ {\bf NormalShrink} & -ns
+ & {\em integer} & Change the shrink size for the overview display \\
+
+ {\bf LargeShrink} & -ls
+ & {\em integer} & Change the shrink size for the detail display \\
+
+ {\bf Blackness} & -bl
+ & {\em integer} & Change the blackness threshold for shrunken fonts \\
+
+ {\bf Leaves} & -l
+ & {\em integer} & Change the number of leaves uses (1 or 2) \\
+
+ {\bf TopMargin} & -tm
+ & {\em float} & Set the top margin in inches \\
+
+ {\bf SideMargin} & -sm
+ & {\em float} & Set the left side margin in inches \\
+
+ {\bf Dpi} & -dpi
+ & {\em integer} & Set the desired font resolution in dots per inch \\
+ \hline
+ \end{tabular}
+\caption{Options For \texx\ and \texsun}
+\label{table:xdvi-options}
+\end{table}
+
+\subsubsection{Remembering where you were}
+Currently, this section only applies to \texsun.
+
+Since the normal use of \texsun\ involves the repeated viewing of a document
+to fix formatting problems,
+it would be nice to be able to return to the page you were viewing when
+you left \texsun.
+
+If you define the environment variable ``{\tt TEXSUN\_STATE}'' as the name
+of a file, a {\em viewing state} will be written to that file when you
+exit \texsun.
+The next time you start \texsun, this state will be added to your list of
+command-line arguments before any other argument.
+This allows you to override the saved state.
+If the first argument is {\tt -new}, the saved state is ignored.
+
+If you choose an absolute path name for {\tt TEXSUN\_STATE},
+then you can invoke \texsun\ from a menu, but all your previewer
+sessions will use the same state file.
+Choosing a relative path name (e.g. ``{\tt ./.texsun-state}'') allows
+you to have a state file for each different directory, but it's
+difficult to convince the SunView environment to start a
+tool in a given directory.
diff --git a/dviware/umddvi/doc/verb.tex b/dviware/umddvi/doc/verb.tex
new file mode 100644
index 0000000000..67ad6bac6f
--- /dev/null
+++ b/dviware/umddvi/doc/verb.tex
@@ -0,0 +1,36 @@
+% From: Tim Morgan <morgan@uci-icsa>
+% Produce verbatim listings of various sorts
+
+\def\uncatcodespecials{\def\do##1{\catcode`##1=12 } \dospecials}
+
+\def\setupverbatim{%
+ \par \tt \spaceskip=0pt % Make sure we get fixed tt spacing
+ \obeylines\uncatcodespecials\obeyspaces\verbatimdefs
+}
+
+% This macro turns on verbatim mode until ?endverbatim is seen.
+\def\verbatim{\begingroup \setupverbatim
+ \parskip=0pt plus .05\baselineskip \parindent=0pt
+ \catcode`\ =13 \catcode`\^^M=13 \catcode`\?=0
+ \verbatimgobble}
+{\catcode`\^^M=13{\catcode`\ =13\gdef\verbatimdefs{\def^^M{\ \par}\let =\ }}
+ \gdef\verbatimgobble#1^^M{}}
+
+% This defines ?endverbatim to end the group which begins with \verbatim
+\let\endverbatim=\endgroup
+
+% Input a file in verbatim mode. Sometimes useful for including
+% real-life examples into a paper.
+\def\verbfile#1{\begingroup\setupverbatim
+ \parskip=0pt plus .05\baselineskip \parindent=0pt
+ \input#1 \endgroup
+}
+
+% This is the same as the above, but it adds line numbers to each
+% line of the file printed.
+\newcount\lineno
+\def\listing#1{\lineno=0\begingroup\setupverbatim
+ \parskip=0pt plus .05\baselineskip \parindent=20pt
+ \everypar{\advance\lineno by 1 \llap{\the\lineno\ \ }}\input#1
+ \endgroup
+}
diff --git a/dviware/umddvi/dvi/dviselect.c b/dviware/umddvi/dvi/dviselect.c
new file mode 100644
index 0000000000..57e8665524
--- /dev/null
+++ b/dviware/umddvi/dvi/dviselect.c
@@ -0,0 +1,974 @@
+/*
+ * Copyright (c) 1987 University of Maryland Department of Computer Science.
+ * All rights reserved. Permission to copy for any purpose is hereby granted
+ * so long as this copyright notice remains intact.
+ */
+
+#ifndef lint
+static char rcsid[] = "$Header: dviselect.c,v 2.6 87/06/16 17:19:24 chris Exp $";
+#endif
+
+/*
+ * DVI page selection program
+ *
+ * Reads DVI version 2 files and selects pages, writing a new DVI
+ * file. The new DVI file is technically correct, though we do not
+ * adjust the tallest and widest page values, nor the DVI stack size.
+ * This is all right since the values will never become too small,
+ * but it might be nice to fix them up. Perhaps someday . . . .
+ */
+
+#include "types.h"
+#include "dvi.h"
+#include "dviclass.h"
+#include "dvicodes.h"
+#include "fio.h"
+#include "search.h"
+#include <stdio.h>
+#include <ctype.h>
+
+char *ProgName;
+extern int errno;
+extern char *optarg;
+extern int optind;
+
+/* Globals */
+char serrbuf[BUFSIZ]; /* buffer for stderr */
+
+/*
+ * We will try to keep output lines shorter than MAXCOL characters.
+ */
+#define MAXCOL 75
+
+/*
+ * We use the following structure to keep track of fonts we have seen.
+ * The final DVI file lists only the fonts it uses.
+ */
+struct fontinfo {
+ i32 fi_newindex; /* font number in output file */
+ int fi_reallyused; /* true => used on a page we copied */
+ i32 fi_checksum; /* the checksum */
+ i32 fi_mag; /* the magnification */
+ i32 fi_designsize; /* the design size */
+ short fi_n1; /* the name header length */
+ short fi_n2; /* the name body length */
+ char *fi_name; /* the name itself */
+};
+
+/*
+ * We need to remember which pages the user would like. We build a linked
+ * list that allows us to decide (for any given page) whether it should
+ * be included in the output file. Each page has ten \count variables
+ * associated with it. We put a bound on the values allowed for each, and
+ * keep a linked list of alternatives should any be outside the allowed
+ * range. For example, `dviselect *.3,10-15' would generate a two-element
+ * page list, with the first allowing any value for \count0 (and \counts 2 to
+ * 9) but \count1 restricted to the range 3-3, and the second restricting
+ * \count0 to the range 10-15 but leaving \counts 1 to 9 unrestrained.
+ *
+ * In case no bound is specified, the `nol' or `noh' flag is set (so that
+ * we need not fix some `large' number as a maximum value).
+ *
+ * We also allow `absolute' page references, where the first page is
+ * page 1, the second 2, and so forth. These are specified with an
+ * equal sign: `dviselect =4:10' picks up the fourth through tenth
+ * sequential pages, irrespective of \count values.
+ */
+struct pagesel {
+ i32 ps_low; /* lower bound */
+ int ps_nol; /* true iff no lower bound */
+ i32 ps_high; /* upper bound */
+ int ps_noh; /* true iff no upper bound */
+};
+struct pagelist {
+ struct pagelist *pl_alt; /* next in a series of alternates */
+ int pl_len; /* number of ranges to check */
+ int pl_abs; /* true iff absolute page ref */
+ struct pagesel pl_pages[10]; /* one for each \count variable */
+};
+
+int SFlag; /* true => -s, silent operation */
+
+struct search *FontFinder; /* maps from input indicies to fontinfo */
+i32 NextOutputFontIndex; /* generates output indicies */
+i32 CurrentFontIndex; /* current (old) index in input */
+i32 OutputFontIndex; /* current (new) index in ouput */
+
+struct pagelist *PageList; /* the list of allowed pages */
+
+FILE *inf; /* the input DVI file */
+FILE *outf; /* the output DVI file */
+
+int ExpectBOP; /* true => BOP ok */
+int ExpectEOP; /* true => EOP ok */
+
+long StartOfLastPage; /* The file position just before we started
+ the last page (this is later written to
+ the output file as the previous page
+ pointer). */
+long CurrentPosition; /* The current position of the file */
+
+int UseThisPage; /* true => current page is selected */
+
+i32 InputPageNumber; /* current absolute page in old DVI file */
+int NumberOfOutputPages; /* number of pages in new DVI file */
+
+i32 Numerator; /* numerator from DVI file */
+i32 Denominator; /* denominator from DVI file */
+i32 DVIMag; /* magnification from DVI file */
+
+i32 Count[10]; /* the 10 \count variables */
+
+/* save some string space: we use this a lot */
+char writeerr[] = "error writing DVI file";
+
+char *malloc(), *realloc(), *sprintf();
+
+/*
+ * lint gets rather confused with the current definitions of getc and putc,
+ * so we redefine them here (#if lint). This should really be in the
+ * standard I/O library, but I am not about to go change it now!
+ */
+#ifdef lint
+#undef putc
+#undef getc
+#define putc(c,f) (*(f)->_ptr++ = (unsigned) (c))
+#define getc(f) (*(f)->_ptr++)
+#endif
+
+/*
+ * Return true iff the 10 \counts are one of the desired output pages.
+ */
+DesiredPageP()
+{
+ register struct pagelist *pl;
+
+ for (pl = PageList; pl != NULL; pl = pl->pl_alt) {
+ register struct pagesel *ps = pl->pl_pages;
+ register int i;
+ register i32 *pagep;
+
+ pagep = pl->pl_abs ? &InputPageNumber : &Count[0];
+ for (i = 0; i < pl->pl_len; i++, ps++, pagep++)
+ if (!ps->ps_nol && *pagep < ps->ps_low ||
+ !ps->ps_noh && *pagep > ps->ps_high)
+ break; /* not within bounds */
+ if (i >= pl->pl_len)
+ return (1); /* success */
+ }
+ return (0);
+}
+
+/*
+ * Print a message to stderr, with an optional leading space, and handling
+ * long line wraps.
+ */
+message(space, str, len)
+ int space;
+ register char *str;
+ register int len;
+{
+ static int beenhere;
+ static int col;
+
+ if (!beenhere)
+ space = 0, beenhere++;
+ if (len == 0)
+ len = strlen(str);
+ col += len;
+ if (space) {
+ if (col >= MAXCOL)
+ (void) putc('\n', stderr), col = len;
+ else
+ (void) putc(' ', stderr), col++;
+ }
+ while (--len >= 0)
+ (void) putc(*str++, stderr);
+ (void) fflush(stderr);
+}
+
+/*
+ * Start a page (process a DVI_BOP).
+ */
+BeginPage()
+{
+ register i32 *i;
+
+ if (!ExpectBOP)
+ GripeUnexpectedOp("BOP");
+ ExpectBOP = 0;
+ ExpectEOP++; /* set the new "expect" state */
+
+ OutputFontIndex = -1; /* new page requires respecifying font */
+ InputPageNumber++; /* count it */
+ for (i = Count; i < &Count[10]; i++)
+ fGetLong(inf, *i);
+ (void) GetLong(inf); /* previous page pointer */
+
+ if ((UseThisPage = DesiredPageP()) == 0)
+ return;
+
+ (void) putc(DVI_BOP, outf);
+ for (i = Count; i < &Count[10]; i++)
+ PutLong(outf, *i);
+ PutLong(outf, StartOfLastPage);
+ if (ferror(outf))
+ error(1, errno, writeerr);
+
+ StartOfLastPage = CurrentPosition;
+ CurrentPosition += 45; /* we just wrote this much */
+
+ if (!SFlag) { /* write nice page usage messages */
+ register int z = 0;
+ register int mlen = 0;
+ char msg[80];
+
+ (void) sprintf(msg, "[%d", Count[0]);
+ mlen = strlen(msg);
+ for (i = &Count[1]; i < &Count[10]; i++) {
+ if (*i == 0) {
+ z++;
+ continue;
+ }
+ while (--z >= 0)
+ msg[mlen++] = '.', msg[mlen++] = '0';
+ z = 0;
+ (void) sprintf(msg + mlen, ".%d", *i);
+ mlen += strlen(msg + mlen);
+ }
+ message(1, msg, mlen);
+ }
+}
+
+/*
+ * End a page (process a DVI_EOP).
+ */
+EndPage()
+{
+ if (!ExpectEOP)
+ GripeUnexpectedOp("EOP");
+ ExpectEOP = 0;
+ ExpectBOP++;
+
+ if (!UseThisPage)
+ return;
+
+ if (!SFlag)
+ message(0, "]", 1);
+
+ putc(DVI_EOP, outf);
+ if (ferror(outf))
+ error(1, errno, writeerr);
+ CurrentPosition++;
+ NumberOfOutputPages++;
+}
+
+/*
+ * For each of the fonts used in the new DVI file, write out a definition.
+ */
+/* ARGSUSED */
+PostAmbleFontEnumerator(addr, key)
+ char *addr;
+ i32 key;
+{
+
+ if (((struct fontinfo *) addr)->fi_reallyused)
+ WriteFont((struct fontinfo *) addr);
+}
+
+HandlePostAmble()
+{
+ register i32 c;
+
+ (void) GetLong(inf); /* previous page pointer */
+ if (GetLong(inf) != Numerator)
+ GripeMismatchedValue("numerator");
+ if (GetLong(inf) != Denominator)
+ GripeMismatchedValue("denominator");
+ if (GetLong(inf) != DVIMag)
+ GripeMismatchedValue("\\magfactor");
+
+ putc(DVI_POST, outf);
+ PutLong(outf, StartOfLastPage);
+ PutLong(outf, Numerator);
+ PutLong(outf, Denominator);
+ PutLong(outf, DVIMag);
+ c = GetLong(inf);
+ PutLong(outf, c); /* tallest page height */
+ c = GetLong(inf);
+ PutLong(outf, c); /* widest page width */
+ c = GetWord(inf);
+ PutWord(outf, c); /* DVI stack size */
+ PutWord(outf, NumberOfOutputPages);
+ StartOfLastPage = CurrentPosition; /* point at post */
+ CurrentPosition += 29; /* count all those `put's */
+#ifdef notdef
+ (void) GetWord(inf); /* skip original number of pages */
+#endif
+
+ /*
+ * just ignore all the incoming font definitions; we are done with
+ * input file
+ */
+
+ /*
+ * run through the FontFinder table and dump definitions for the
+ * fonts we have used.
+ */
+ SEnumerate(FontFinder, PostAmbleFontEnumerator);
+
+ putc(DVI_POSTPOST, outf);
+ PutLong(outf, StartOfLastPage); /* actually start of postamble */
+ putc(DVI_VERSION, outf);
+ putc(DVI_FILLER, outf);
+ putc(DVI_FILLER, outf);
+ putc(DVI_FILLER, outf);
+ putc(DVI_FILLER, outf);
+ CurrentPosition += 10;
+ while (CurrentPosition & 3)
+ putc(DVI_FILLER, outf), CurrentPosition++;
+ if (ferror(outf))
+ error(1, errno, writeerr);
+}
+
+/*
+ * Write a font definition to the output file
+ */
+WriteFont(fi)
+ register struct fontinfo *fi;
+{
+ register int l;
+ register char *s;
+
+ if (fi->fi_newindex < 256) {
+ putc(DVI_FNTDEF1, outf);
+ putc(fi->fi_newindex, outf);
+ CurrentPosition += 2;
+ } else if (fi->fi_newindex < 65536) {
+ putc(DVI_FNTDEF2, outf);
+ PutWord(outf, fi->fi_newindex);
+ CurrentPosition += 3;
+ } else if (fi->fi_newindex < 16777216) {
+ putc(DVI_FNTDEF3, outf);
+ Put3Byte(outf, fi->fi_newindex);
+ CurrentPosition += 4;
+ } else {
+ putc(DVI_FNTDEF4, outf);
+ PutLong(outf, fi->fi_newindex);
+ CurrentPosition += 5;
+ }
+ PutLong(outf, fi->fi_checksum);
+ PutLong(outf, fi->fi_mag);
+ PutLong(outf, fi->fi_designsize);
+ putc(fi->fi_n1, outf);
+ putc(fi->fi_n2, outf);
+ l = fi->fi_n1 + fi->fi_n2;
+ CurrentPosition += 14 + l;
+ s = fi->fi_name;
+ while (--l >= 0)
+ putc(*s, outf), s++;
+}
+
+/*
+ * Handle the preamble. Someday we should update the comment field.
+ */
+HandlePreAmble()
+{
+ register int n, c;
+
+ if (GetByte(inf) != Sign8(DVI_PRE))
+ GripeMissingOp("PRE");
+ if (GetByte(inf) != Sign8(DVI_VERSION))
+ GripeMismatchedValue("DVI version number");
+ Numerator = GetLong(inf);
+ Denominator = GetLong(inf);
+ DVIMag = GetLong(inf);
+ putc(DVI_PRE, outf);
+ putc(DVI_VERSION, outf);
+ PutLong(outf, Numerator);
+ PutLong(outf, Denominator);
+ PutLong(outf, DVIMag);
+
+ n = UnSign8(GetByte(inf));
+ CurrentPosition = 15 + n; /* well, almost */
+ putc(n, outf);
+ while (--n >= 0) {
+ c = GetByte(inf);
+ putc(c, outf); /* never trust a macro, I always say */
+ }
+}
+
+main(argc, argv)
+ int argc;
+ register char **argv;
+{
+ register int c;
+ register char *s;
+ char *inname = NULL, *outname = NULL;
+
+ ProgName = *argv;
+ setbuf(stderr, serrbuf);
+
+ while ((c = getopt(argc, argv, "i:o:s")) != EOF) {
+ switch (c) {
+
+ case 's': /* silent */
+ SFlag++;
+ break;
+
+ case 'i':
+ if (inname != NULL)
+ goto usage;
+ inname = optarg;
+ break;
+
+ case 'o':
+ if (outname != NULL)
+ goto usage;
+ outname = optarg;
+ break;
+
+ case '?':
+usage:
+ fprintf(stderr, "\
+Usage: %s [-s] [-i infile] [-o outfile] pages [...] [infile [outfile]]\n",
+ ProgName);
+ (void) fflush(stderr);
+ exit(1);
+ }
+ }
+
+ while (optind < argc) {
+ s = argv[optind++];
+ c = *s;
+ if (!isalpha(c) && c != '/') {
+ if (ParsePages(s))
+ goto usage;
+ } else if (inname == NULL)
+ inname = s;
+ else if (outname == NULL)
+ outname = s;
+ else
+ goto usage;
+ }
+ if (PageList == NULL)
+ goto usage;
+ if (inname == NULL)
+ inf = stdin;
+ else if ((inf = fopen(inname, "r")) == 0)
+ error(1, errno, "cannot read %s", inname);
+ if (outname == NULL)
+ outf = stdout;
+ else if ((outf = fopen(outname, "w")) == 0)
+ error(1, errno, "cannot write %s", outname);
+
+ if ((FontFinder = SCreate(sizeof(struct fontinfo))) == 0)
+ error(1, 0, "cannot create font finder (out of memory?)");
+
+ ExpectBOP++;
+ StartOfLastPage = -1;
+ HandlePreAmble();
+ HandleDVIFile();
+ HandlePostAmble();
+ if (!SFlag)
+ fprintf(stderr, "\nWrote %d pages, %d bytes\n",
+ NumberOfOutputPages, CurrentPosition);
+ exit(0);
+}
+
+struct pagelist *
+InstallPL(ps, n, absolute)
+ register struct pagesel *ps;
+ register int n;
+ int absolute;
+{
+ register struct pagelist *pl;
+
+ pl = (struct pagelist *) malloc(sizeof *pl);
+ if (pl == NULL)
+ GripeOutOfMemory(sizeof *pl, "page list");
+ pl->pl_alt = PageList;
+ PageList = pl;
+ pl->pl_len = n;
+ while (--n >= 0)
+ pl->pl_pages[n] = ps[n];
+ pl->pl_abs = absolute;
+}
+
+/*
+ * Parse a string representing a list of pages. Return 0 iff ok. As a
+ * side effect, the page selection(s) is (are) prepended to PageList.
+ */
+ParsePages(s)
+ register char *s;
+{
+ register struct pagesel *ps;
+ register int c; /* current character */
+ register i32 n; /* current numeric value */
+ register int innumber; /* true => gathering a number */
+ int i; /* next index in page select list */
+ int range; /* true => saw a range indicator */
+ int negative; /* true => number being built is negative */
+ int absolute; /* true => absolute, not \count */
+ struct pagesel pagesel[10];
+
+#define white(x) ((x) == ' ' || (x) == '\t' || (x) == ',')
+
+ range = 0;
+ innumber = 0;
+ absolute = 0;
+ i = 0;
+ ps = pagesel;
+ /*
+ * Talk about ad hoc! (Not to mention convoluted.)
+ */
+ for (;;) {
+ c = *s++;
+ if (i == 0 && !innumber && !range) {
+ /* nothing special going on */
+ if (c == 0)
+ return 0;
+ if (white(c))
+ continue;
+ }
+ if (c == '_') {
+ /* kludge: should be '-' for negatives */
+ if (innumber || absolute)
+ return (-1);
+ innumber++;
+ negative = 1;
+ n = 0;
+ continue;
+ }
+ if (c == '=') {
+ /* absolute page */
+ if (innumber || range || i > 0)
+ return (-1);
+ absolute++;
+ /*
+ * Setting innumber means that there is always
+ * a lower bound, but this is all right since
+ * `=:4' is treated as if it were `=0:4'. As
+ * there are no negative absolute page numbers,
+ * this selects pages 1:4, which is the proper
+ * action.
+ */
+ innumber++;
+ negative = 0;
+ n = 0;
+ continue;
+ }
+ if (isdigit(c)) {
+ /* accumulate numeric value */
+ if (!innumber) {
+ innumber++;
+ negative = 0;
+ n = c - '0';
+ continue;
+ }
+ n *= 10;
+ n += negative ? '0' - c : c - '0';
+ continue;
+ }
+ if (c == '-' || c == ':') {
+ /* here is a range */
+ if (range)
+ return (-1);
+ if (innumber) { /* have a lower bound */
+ ps->ps_low = n;
+ ps->ps_nol = 0;
+ } else
+ ps->ps_nol = 1;
+ range++;
+ innumber = 0;
+ continue;
+ }
+ if (c == '*') {
+ /* no lower bound, no upper bound */
+ c = *s++;
+ if (innumber || range || i >= 10 ||
+ (c && c != '.' && !white(c)))
+ return (-1);
+ ps->ps_nol = 1;
+ ps->ps_noh = 1;
+ goto finishnum;
+ }
+ if (c == 0 || c == '.' || white(c)) {
+ /* end of this range */
+ if (i >= 10)
+ return (-1);
+ if (!innumber) { /* no upper bound */
+ ps->ps_noh = 1;
+ if (!range) /* no lower bound either */
+ ps->ps_nol = 1;
+ } else { /* have an upper bound */
+ ps->ps_high = n;
+ ps->ps_noh = 0;
+ if (!range) {
+ /* no range => lower bound == upper */
+ ps->ps_low = ps->ps_high;
+ ps->ps_nol = 0;
+ }
+ }
+finishnum:
+ i++;
+ if (c == '.') {
+ if (absolute)
+ return (-1);
+ ps++;
+ } else {
+ InstallPL(pagesel, i, absolute);
+ ps = pagesel;
+ i = 0;
+ absolute = 0;
+ }
+ if (c == 0)
+ return (0);
+ range = 0;
+ innumber = 0;
+ continue;
+ }
+ /* illegal character */
+ return (-1);
+ }
+#undef white
+}
+
+/*
+ * Handle a font definition.
+ */
+HandleFontDef(index)
+ i32 index;
+{
+ register struct fontinfo *fi;
+ register int i;
+ register char *s;
+ int def = S_CREATE | S_EXCL;
+
+ if ((fi = (struct fontinfo *) SSearch(FontFinder, index, &def)) == 0)
+ if (def & S_COLL)
+ error(1, 0, "font %d already defined", index);
+ else
+ error(1, 0, "cannot stash font %d (out of memory?)",
+ index);
+ fi->fi_reallyused = 0;
+ fi->fi_checksum = GetLong(inf);
+ fi->fi_mag = GetLong(inf);
+ fi->fi_designsize = GetLong(inf);
+ fi->fi_n1 = UnSign8(GetByte(inf));
+ fi->fi_n2 = UnSign8(GetByte(inf));
+ i = fi->fi_n1 + fi->fi_n2;
+ if ((s = malloc((unsigned) i)) == 0)
+ GripeOutOfMemory(i, "font name");
+ fi->fi_name = s;
+ while (--i >= 0)
+ *s++ = GetByte(inf);
+}
+
+/*
+ * Handle a \special.
+ */
+HandleSpecial(c, l, p)
+ int c;
+ register int l;
+ register i32 p;
+{
+ register int i;
+
+ if (UseThisPage) {
+ putc(c, outf);
+ switch (l) {
+
+ case DPL_UNS1:
+ putc(p, outf);
+ CurrentPosition += 2;
+ break;
+
+ case DPL_UNS2:
+ PutWord(outf, p);
+ CurrentPosition += 3;
+ break;
+
+ case DPL_UNS3:
+ Put3Byte(outf, p);
+ CurrentPosition += 4;
+ break;
+
+ case DPL_SGN4:
+ PutLong(outf, p);
+ CurrentPosition += 5;
+ break;
+
+ default:
+ panic("HandleSpecial l=%d", l);
+ /* NOTREACHED */
+ }
+ CurrentPosition += p;
+ while (--p >= 0) {
+ i = getc(inf);
+ putc(i, outf);
+ }
+ if (feof(inf))
+ error(1, 0, "unexpected EOF");
+ if (ferror(outf))
+ error(1, errno, writeerr);
+ } else
+ while (--p >= 0)
+ (void) getc(inf);
+}
+
+ReallyUseFont()
+{
+ register struct fontinfo *fi;
+ int look = S_LOOKUP;
+
+ fi = (struct fontinfo *) SSearch(FontFinder, CurrentFontIndex, &look);
+ if (fi == 0)
+ error(1, 0, "index %d not in font table!", CurrentFontIndex);
+ if (fi->fi_reallyused == 0) {
+ fi->fi_reallyused++;
+ fi->fi_newindex = NextOutputFontIndex++;
+ WriteFont(fi);
+ }
+ if (fi->fi_newindex != OutputFontIndex) {
+ PutFontSelector(fi->fi_newindex);
+ OutputFontIndex = fi->fi_newindex;
+ }
+}
+
+/*
+ * Write a font selection command to the output file
+ */
+PutFontSelector(index)
+ i32 index;
+{
+
+ if (index < 64) {
+ putc(index + DVI_FNTNUM0, outf);
+ CurrentPosition++;
+ } else if (index < 256) {
+ putc(DVI_FNT1, outf);
+ putc(index, outf);
+ CurrentPosition += 2;
+ } else if (index < 65536) {
+ putc(DVI_FNT2, outf);
+ PutWord(outf, index);
+ CurrentPosition += 3;
+ } else if (index < 16777216) {
+ putc(DVI_FNT3, outf);
+ Put3Byte(outf, index);
+ CurrentPosition += 4;
+ } else {
+ putc(DVI_FNT4, outf);
+ PutLong(outf, index);
+ CurrentPosition += 5;
+ }
+}
+
+/*
+ * The following table describes the length (in bytes) of each of the DVI
+ * commands that we can simply copy, starting with DVI_SET1 (128).
+ */
+char oplen[128] = {
+ 0, 0, 0, 0, /* DVI_SET1 .. DVI_SET4 */
+ 9, /* DVI_SETRULE */
+ 0, 0, 0, 0, /* DVI_PUT1 .. DVI_PUT4 */
+ 9, /* DVI_PUTRULE */
+ 1, /* DVI_NOP */
+ 0, /* DVI_BOP */
+ 0, /* DVI_EOP */
+ 1, /* DVI_PUSH */
+ 1, /* DVI_POP */
+ 2, 3, 4, 5, /* DVI_RIGHT1 .. DVI_RIGHT4 */
+ 1, /* DVI_W0 */
+ 2, 3, 4, 5, /* DVI_W1 .. DVI_W4 */
+ 1, /* DVI_X0 */
+ 2, 3, 4, 5, /* DVI_X1 .. DVI_X4 */
+ 2, 3, 4, 5, /* DVI_DOWN1 .. DVI_DOWN4 */
+ 1, /* DVI_Y0 */
+ 2, 3, 4, 5, /* DVI_Y1 .. DVI_Y4 */
+ 1, /* DVI_Z0 */
+ 2, 3, 4, 5, /* DVI_Z1 .. DVI_Z4 */
+ 0, /* DVI_FNTNUM0 (171) */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 172 .. 179 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 180 .. 187 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 188 .. 195 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 196 .. 203 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 204 .. 211 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 212 .. 219 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 220 .. 227 */
+ 0, 0, 0, 0, 0, 0, 0, /* 228 .. 234 */
+ 0, 0, 0, 0, /* DVI_FNT1 .. DVI_FNT4 */
+ 0, 0, 0, 0, /* DVI_XXX1 .. DVI_XXX4 */
+ 0, 0, 0, 0, /* DVI_FNTDEF1 .. DVI_FNTDEF4 */
+ 0, /* DVI_PRE */
+ 0, /* DVI_POST */
+ 0, /* DVI_POSTPOST */
+ 0, 0, 0, 0, 0, 0, /* 250 .. 255 */
+};
+
+/*
+ * Here we read the input DVI file and write relevant pages to the
+ * output DVI file. We also keep track of font changes, handle font
+ * definitions, and perform some other housekeeping.
+ */
+HandleDVIFile()
+{
+ register int c, l;
+ register i32 p;
+ register int CurrentFontOK = 0;
+
+ /* Only way out is via "return" statement */
+ for (;;) {
+ c = getc(inf); /* getc() returns unsigned values */
+ if (DVI_IsChar(c)) {
+ /*
+ * Copy chars, note font usage, but ignore if
+ * page is not interesting.
+ */
+ if (!UseThisPage)
+ continue;
+ if (!CurrentFontOK) {
+ ReallyUseFont();
+ CurrentFontOK++;
+ }
+ putc(c, outf);
+ CurrentPosition++;
+ continue;
+ }
+ if (DVI_IsFont(c)) { /* note font change */
+ CurrentFontIndex = c - DVI_FNTNUM0;
+ CurrentFontOK = 0;
+ continue;
+ }
+ if ((l = (oplen - 128)[c]) != 0) { /* simple copy */
+ if (!UseThisPage) {
+ while (--l > 0)
+ (void) getc(inf);
+ continue;
+ }
+ CurrentPosition += l;
+ putc(c, outf);
+ while (--l > 0) {
+ c = getc(inf);
+ putc(c, outf);
+ }
+ if (ferror(outf))
+ error(1, errno, writeerr);
+ continue;
+ }
+ if ((l = DVI_OpLen(c)) != 0) {
+ /*
+ * Handle other generics.
+ * N.B.: there should only be unsigned parameters
+ * here (save SGN4), for commands with negative
+ * parameters have been taken care of above.
+ */
+ switch (l) {
+
+ case DPL_UNS1:
+ p = getc(inf);
+ break;
+
+ case DPL_UNS2:
+ fGetWord(inf, p);
+ break;
+
+ case DPL_UNS3:
+ fGet3Byte(inf, p);
+ break;
+
+ case DPL_SGN4:
+ fGetLong(inf, p);
+ break;
+
+ default:
+ panic("HandleDVIFile l=%d", l);
+ }
+
+ /*
+ * Now that we have the parameter, perform the
+ * command.
+ */
+ switch (DVI_DT(c)) {
+
+ case DT_SET:
+ case DT_PUT:
+ if (!UseThisPage)
+ continue;
+ if (!CurrentFontOK) {
+ ReallyUseFont();
+ CurrentFontOK++;
+ }
+ putc(c, outf);
+ switch (l) {
+
+ case DPL_UNS1:
+ putc(p, outf);
+ CurrentPosition += 2;
+ continue;
+
+ case DPL_UNS2:
+ PutWord(outf, p);
+ CurrentPosition += 3;
+ continue;
+
+ case DPL_UNS3:
+ Put3Byte(outf, p);
+ CurrentPosition += 4;
+ continue;
+
+ case DPL_SGN4:
+ PutLong(outf, p);
+ CurrentPosition += 5;
+ continue;
+ }
+
+ case DT_FNT:
+ CurrentFontIndex = p;
+ CurrentFontOK = 0;
+ continue;
+
+ case DT_XXX:
+ HandleSpecial(c, l, p);
+ continue;
+
+ case DT_FNTDEF:
+ HandleFontDef(p);
+ continue;
+
+ default:
+ panic("HandleDVIFile DVI_DT(%d)=%d",
+ c, DVI_DT(c));
+ }
+ continue;
+ }
+
+ switch (c) { /* handle the few remaining cases */
+
+ case DVI_BOP:
+ BeginPage();
+ CurrentFontOK = 0;
+ break;
+
+ case DVI_EOP:
+ EndPage();
+ break;
+
+ case DVI_PRE:
+ GripeUnexpectedOp("PRE");
+ /* NOTREACHED */
+
+ case DVI_POST:
+ return;
+
+ case DVI_POSTPOST:
+ GripeUnexpectedOp("POSTPOST");
+ /* NOTREACHED */
+
+ default:
+ GripeUndefinedOp(c);
+ /* NOTREACHED */
+ }
+ }
+}
diff --git a/dviware/umddvi/dvi/makefile b/dviware/umddvi/dvi/makefile
new file mode 100644
index 0000000000..8bb89acff2
--- /dev/null
+++ b/dviware/umddvi/dvi/makefile
@@ -0,0 +1,61 @@
+#
+# Copyright (c) 1987 University of Maryland Department of Computer Science.
+# All rights reserved. Permission to copy for any purpose is hereby granted
+# so long as this copyright notice remains intact.
+#
+# $Header: Makefile,v 1.2 87/06/16 17:19:18 chris Exp $
+#
+# Makefile for ctex/dvi (DVI-to-DVI conversion programs)
+#
+DESTDIR=
+CFLAGS= -O -R -I../h
+
+# these are intended to be overridden by the definition in ../Makefile
+# but just in case, it's included here too
+BINDIR= ${DESTDIR}/usr/local/bin
+MANDIR= ${DESTDIR}/usr/local/man
+
+SRCS= dviselect.c
+
+all: dviselect
+
+install: inst-dviselect
+
+clean:
+ rm -f core *.o dviselect *.bak
+
+inst-dviselect: dviselect
+ install -s dviselect ${BINDIR}/dviselect
+ install -c -m 444 ../man/dviselect.1 ${MANDIR}/man1/dviselect.1
+
+depend: ${SRCS}
+ ${CC} -M ${CFLAGS} ${SRCS} |\
+ awk '{ if ($$1 != prev) { if (rec != "" ) print rec;\
+ rec = $$0; prev = $$1; }\
+ else { if (length(rec $$2) > 78) { print rec; rec = $$0; }\
+ else rec = rec " " $$2 } }\
+ END { print rec }' >makedep
+ echo '/^# DO NOT DELETE THIS LINE/+2,$$d' >eddep
+ echo '$$r makedep' >>eddep
+ echo 'w' >>eddep
+ cp Makefile Makefile.bak
+ ed - Makefile <eddep
+ rm eddep makedep
+ echo '# DEPENDENCIES MUST END AT END OF FILE' >>Makefile
+ echo '# IF YOU PUT STUFF HERE IT WILL GO AWAY' >>Makefile
+ echo '# see make depend above' >>Makefile
+
+dviselect: dviselect.o ../lib/lib.a
+ ${CC} ${CFLAGS} -o dviselect dviselect.o ../lib/lib.a
+
+lint: ${SRCS}
+ lint -I../h -hbxuL ../lib/llib-lib dviselect.c
+
+# DO NOT DELETE THIS LINE -- make depend uses it
+
+dviselect.o: dviselect.c ../h/types.h ../h/dvi.h ../h/dviclass.h
+dviselect.o: ../h/dvicodes.h ../h/fio.h ../h/search.h /usr/include/stdio.h
+dviselect.o: /usr/include/ctype.h
+# DEPENDENCIES MUST END AT END OF FILE
+# IF YOU PUT STUFF HERE IT WILL GO AWAY
+# see make depend above
diff --git a/dviware/umddvi/dvi/readme b/dviware/umddvi/dvi/readme
new file mode 100644
index 0000000000..817d10b7bf
--- /dev/null
+++ b/dviware/umddvi/dvi/readme
@@ -0,0 +1,2 @@
+This directory is for DVI to DVI conversion programs. Right now
+the only one is the page selection program.
diff --git a/dviware/umddvi/h/arith.h b/dviware/umddvi/h/arith.h
new file mode 100644
index 0000000000..bcb8267342
--- /dev/null
+++ b/dviware/umddvi/h/arith.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 1987 University of Maryland Department of Computer Science.
+ * All rights reserved. Permission to copy for any purpose is hereby granted
+ * so long as this copyright notice remains intact.
+ */
+
+/*
+ * Arithmetic with scaled dimensions
+ *
+ * From `TEX.WEB' by D. E. Knuth:
+ *
+ * `The principal computations performed by TeX are done entirely in terms
+ * of integers less than 2^31 in magnitude; and divisions are done only when
+ * both divident and divisor are nonnegative. Thus, the arithemtic specified
+ * in this program can be carried out in exactly the same way on a wide
+ * variety of computers, including some small ones. Why? Because the
+ * arithmetic calculations need to be spelled out precisely in order to
+ * guarantee that TeX will produce identical output on different machines.
+ * If some quantities were rounded differently in different implementations,
+ * we would find that line breaks and even page breaks might occur in
+ * different places. Hence the arithmetic of TeX has been designed with
+ * care, and systems that claim be be implementations of TeX82 should follow
+ * precisely the calculations as they appear in the present program.'
+ *
+ * Thus, this follows the given implementation with few (no) optimizations.
+ */
+
+/*
+ * We do fixed-point arithmetic on `scaled integers'. These should
+ * be (at least) 32 bits. Note also that it is assumed that certain
+ * `int' values may be stored in these (usually small, or else one
+ * of the magic 1<<n values).
+ */
+typedef i32 scaled;
+
+#define UNITY (1<<16) /* 2^{16}, or 1.00000 */
+#define TWO (1<<17) /* 2^{17}, or 2.00000 */
+#define MAXSCALED ((1<<30)-1) /* maximum scaled value, 2^{30}-1 */
+
+/*
+ * This works on two's complement machines. If you are not on one of those,
+ * you will need something different here.
+ */
+#define odd(n) ((n) & 1)
+
+/* half of an integer, unambiguous with respect to signed odd numbers */
+#define half(x) (odd (x) ? ((x) + 1) / 2 : (x) / 2)
+
+int ArithError; /* set true whenever an arithmetic overflow
+ occurs */
+
+char *UnScale (); /* return a pointer to the external
+ representation of a `scaled'.
+ (Alas, since I am returning it in
+ static storage, you can only use
+ it once without copying.) */
diff --git a/dviware/umddvi/h/binding.h b/dviware/umddvi/h/binding.h
new file mode 100644
index 0000000000..330ff2c170
--- /dev/null
+++ b/dviware/umddvi/h/binding.h
@@ -0,0 +1,194 @@
+/* C-TeX function and variable bindings */
+
+/*
+ * Copyright (c) 1987 University of Maryland Department of Computer Science.
+ * All rights reserved. Permission to copy for any purpose is hereby granted
+ * so long as this copyright notice remains intact.
+ */
+
+#ifdef StringSizeof
+/*
+ * If StringSizeof is defined, we assume that (sizeof "string_const") is
+ * equal to (strlen("string_const") + 1); see the DefXXX macros below.
+ */
+#endif
+
+/*
+ * Here are the various flags that can be in the b_flags field of a struct
+ * BoundName.
+ */
+#define BIsSpecial 1 /* a special int or dimen, or a font;
+ assignments to these are always
+ global */
+#define BIsOuter 2 /* \outer, may not appear in macro def'n */
+#define BIsLong 4 /* \long, may contain \outer s anyway */
+#define BIsUndef 8 /* not defined anymore - used when a def'n
+ local to a group is destroyed by exiting
+ the group */
+
+/*
+ * SPECIAL
+ * 1. Integers:
+ * \spacefactor \prevgraf \deadcycles \insertpenalties
+ * 2. Dimens:
+ * \prevdepth \pagegoal \pagetotal \pagestretch \pagefilstretch
+ * \pagefillstretch \pagefilllstretch \pageshrink \pagedepth
+ */
+
+enum BindingKind {
+ ProcBound, VarBound, IntBound, DimenBound, CodeBound,
+ FontBound
+};
+
+union BindUnion {
+ int (*b_proc)(); /* iff ProcBound */
+ struct node *b_var; /* iff VarBound */
+ i32 *b_int; /* iff IntBound */
+ scaled *b_dimen; /* iff DimenBound */
+ i32 b_code; /* iff CodeBound */
+ struct FontInfo *b_font; /* iff FontBound */
+};
+
+/*
+ * The basic entity of C-TeX is the `BoundName'. It is either a wired-in
+ * procedure (e.g. \let, \def, \vskip) or variable (\hsize, \parskip), or a
+ * user-defined macro/variable/whatnot. These are indistinguishable from
+ * one another (except that only wired procedures are ProcBound).
+ *
+ * There are also `CodeBound' things, which have no b_name and no b_flags.
+ * In fact, they are really BoundNameCodes, but they need similar treatment,
+ * so they get a similar structure.
+ */
+struct BoundName {
+ enum BindingKind b_binding; /* the kind of thing it is */
+ union BindUnion b_bound; /* the current binding */
+ struct SavedVal *b_AfterGroupRst;
+ /* The saved value for restoration
+ after the current group. This
+ is a pointer into the current
+ AfterGroupRst list. */
+ struct string b_name; /* the name of this thing */
+ int b_flags; /* various flags */
+};
+
+/*
+ * \catcodes, \lccodes, etc are CodeBound, and are really arrays of these:
+ */
+struct BoundNameCode {
+ enum BindingKind b_binding;
+ union BindUnion b_bound;
+ struct SavedVal *b_AfterGroupRst;
+};
+
+/*
+ * Saved values (changes that are local to a group) are stored in a doubly
+ * linked list; this is so that constructs like
+ * {\advance\count0 by1 \global\advance\count0 by1}
+ * can easily delete restorations that are no longer needed (having been
+ * overridden by a \global operation). In other words, we never have
+ * any `save stack buildup'. This requires the `spaghetti' below: a
+ * current group level (so if b_AfterGroupRst is set, we can tell whether
+ * the saved val is for this level) and moreover any inner saves for this
+ * BoundName.
+ *
+ * To illustrate what is going on, suppose that we have count1==0. Now we
+ * begin group number 1, then 2. Now we set count1 to 5, and since it has
+ * no AfterGroupRst we save the 0 at level 2. Now we increment count1, and
+ * since it has an AfterGroupRst, we check the level. It is 2; everything
+ * is fine, and count1 is set to 6. Now we begin group 3, and again increment
+ * count1. The level is 2, so we make a new SavedVal and set its level to
+ * 3. (We now have count1==7, save==6 when exiting level 3, save==0 when
+ * exiting 2.) Now the user does a \global\count1=42, so alas!, all those
+ * saved values are useless. To get rid of them, we delete the current
+ * SavedVal, and its inner, and its inner's inner, and so forth, then clear
+ * the AfterGroupRst pointer. Voila! A global \count1, set to 42.
+ *
+ * Note that we save CodeBound changes here too. Since CodeBound objects
+ * have no flags, some care is needed during restoration.
+ */
+struct SavedVal {
+ int sv_level; /* the level to which this belongs */
+ struct SavedVal *sv_next; /* linked list */
+ struct SavedVal *sv_prev; /* or more precisely, queue */
+ struct SavedVal *sv_inner; /* the inner saved value (from the
+ previous group that saved this) */
+ union BindUnion sv_val; /* the saved value (note that saved
+ values are always the same type
+ as current values---i.e., types
+ are fixed) */
+ struct BoundName *sv_b; /* the BoundName to which it belongs */
+ int sv_flags; /* the saved b_flags (if applicable) */
+};
+
+struct BoundName **NewNames; /* during initialization, each internal
+ BoundName is stashed in the table to
+ which this points */
+
+int CurrentGroup; /* the group level number of the current
+ group; incremented for { and decremented
+ for }, etc */
+
+struct SavedVal *AfterGroupRst;/* the current list for restoring locally
+ modified BoundNames */
+
+/*
+ * The following hackery will make the compiler complain in the event
+ * of a dropped semicolon, without making lint complain.
+ */
+#ifdef lint
+#define do_nothing (void) rand()
+#else
+#define do_nothing 0
+#endif
+
+/*
+ * Save a binding.
+ */
+#define SaveB(b) \
+ if ((b)->b_AfterGroupRst == NULL || \
+ (b)->b_AfterGroupRst->sv_level != CurrentGroup) \
+ DoSave(b); \
+ else \
+ do_nothing
+
+/*
+ * Undo a save.
+ */
+#define UnSaveB(b) \
+ if ((b)->b_AfterGroupRst) \
+ DoUnsave(b); \
+ else \
+ do_nothing
+
+#ifdef StringSizeof
+#define InitStrAndLen(str,cstr) (str.s_len = sizeof cstr-1, str.s_str = cstr)
+#else
+#define InitStrAndLen(str,cstr) (str.s_len = strlen(str.s_str = cstr))
+#endif
+
+#define SetBFlags(f) NewNames[-1].b_flags |= (f)
+
+#define DefIntVar(addr, name) { \
+ static struct BoundName _b; \
+ InitStrAndLen(_b.b_name, name); \
+ _b.b_binding = IntBound; \
+ _b.b_bound.b_int = addr; \
+ *NewNames++ = &_b; \
+}
+
+#define DefDimenVar(addr, name) { \
+ static struct BoundName _b; \
+ InitStrAndLen(_b.b_name, name); \
+ _b.b_binding = DimenBound; \
+ _b.b_bound.b_dimen = addr; \
+ *NewNames++ = &_b; \
+}
+
+#define DefProc(name, proc, flags) { \
+ static struct BoundName _b; \
+ InitStrAndLen(_b.b_name, name); \
+ _b.b_binding = ProcBound; \
+ _b.b_bound.b_proc = proc; \
+ _b.b_bound.b_flags = flags; \
+ *NewNames++ = &_b; \
+}
diff --git a/dviware/umddvi/h/box.h b/dviware/umddvi/h/box.h
new file mode 100644
index 0000000000..05314900ac
--- /dev/null
+++ b/dviware/umddvi/h/box.h
@@ -0,0 +1,395 @@
+/*
+ * Copyright (c) 1987 University of Maryland Department of Computer Science.
+ * All rights reserved. Permission to copy for any purpose is hereby granted
+ * so long as this copyright notice remains intact.
+ */
+
+/* Box structures */
+
+/* Magic constants. Note that these are stored into `scaled' types. */
+#define RunningRule (-(1 << 30))
+#define MFracDefaultThickness (1 << 31) /* => default rule thickness */
+
+/* Magic penalty values */
+#define InfPenalty 10000 /* infinity---no break at all */
+#define EjectPenalty (-10000) /* negative infinity---forced break */
+
+/* Ordinary list types */
+#define CharNode 0 /* character; also math char */
+#define HListNode 1 /* a horizontal list */
+#define VListNode 2 /* a vertical list */
+#define RuleNode 3 /* a rule */
+#define InsertNode 4 /* an insertion */
+#define MarkNode 5 /* a mark */
+#define AdjustNode 6 /* a \vadjust */
+#define LigatureNode 7 /* a ligature */
+#define DiscretionaryNode 8 /* a discretionary break */
+#define WhatsitNode 9 /* a "whatsit" */
+#define BeginMathNode 10 /* a begin-math */
+#define EndMathNode 11 /* an end-math */
+#define GlueNode 12 /* link to glue */
+#define KernNode 13 /* kerning */
+#define PenaltyNode 14 /* penalty */
+#define UnsetAlignNode 15 /* \halign or \valign that is incomplete */
+
+/* Types arising only in math lists */
+#define MathAtom 16 /* math atom */
+#define MathStyle 17 /* math style change */
+#define MathFraction 18 /* math fraction */
+#define MathLeft 19 /* math left delimiter \left */
+#define MathRight 20 /* math right delimiter \right */
+#define MathChoice 21 /* math 4-way choice */
+#define MathSubList 22 /* math list, possibly empty */
+#define MathSubBox 23 /* math box (\hlist or \vlist) */
+
+/* Kinds of math atoms */
+enum MKind {
+ MKindOrd, MKindOp, MKindOpLimits, MKindOpNoLimits, MKindBin, MKindRel,
+ MKindOpen, MKindClose, MKindPunct, MKindInner, MKindOver, MKindUnder,
+ MKindAcc, MKindRad, MKindVCent
+};
+
+/* Math text styles */
+#define MStyleCramped 1 /* added to others to get cramped style */
+#define MStyleDisplay 0 /* display style */
+#define MStyleText 2 /* text style */
+#define MStyleScript 4 /* script style */
+#define MStyleSScript 6 /* scriptscript style */
+
+/*
+ * A font and character. Note that these limit the number of fonts and
+ * characters/font to 256.
+ */
+struct fontchar {
+ char fc_font; /* font index */
+ char fc_char; /* character index within the font */
+};
+
+/* a box */
+struct box {
+ scaled bx_width; /* width of the box */
+ scaled bx_depth; /* depth of the box */
+ scaled bx_height; /* height of the box */
+ scaled bx_offset; /* offset (lower if h, right if v) */
+ struct node *bx_contents; /* contents of the box */
+ int bx_glueorder; /* -3=>minus hfilll; 3=>plus hfilll */
+ float bx_glueset; /* glue setting ratio */
+};
+
+/* a rule */
+struct rule {
+ scaled ru_width; /* width of the rule */
+ scaled ru_depth; /* depth of the rule */
+ scaled ru_height; /* height of the rule */
+};
+
+/* an insert */
+struct insert {
+ int ins_number; /* 0..254 (I hope) */
+ i32 ins_floatingpenalty; /* \floatingpenalty for this insert */
+ scaled ins_naturalheightplusdepth; /* what more can I say? */
+ scaled ins_splitmaxdepth; /* \splitmaxdepth for this insert */
+ struct node *ins_splittopskip; /* \splittopskip for this insert */
+ struct node *ins_contents; /* insertion contents */
+};
+
+/* a ligature */
+struct ligature {
+ struct fontchar lig_fc; /* the ligature character */
+ struct node *lig_orig; /* the original set of characters */
+};
+
+/* a discretionary break */
+struct discret {
+ struct node *disc_prebrk; /* characters to precede break */
+ struct node *disc_postbrk; /* characters to follow break */
+ int disc_replaces; /* replaces this many nodes */
+};
+
+/* a whatsit */
+struct whatsit {
+ int wh_type; /* type of whatsit */
+ char *wh_other; /* other stuff */
+};
+
+/*
+ * A glue specification. There may be multiple pointers to this glue spec,
+ * so we have a reference count attached.
+ */
+struct gluespec {
+ int gl_refcount; /* # pointers to here */
+ scaled gl_width; /* normal width */
+ scaled gl_stretch; /* strechability */
+ scaled gl_shrink; /* shrinkability */
+ short gl_stretchorder; /* 0..3 for <>, fil, fill, filll */
+ short gl_shrinkorder; /* same */
+};
+
+/* a link-to-glue node */
+#define GlueIsNormal 0 /* ordinary glue */
+#define GlueIsSkip 1 /* \hskip or \vskip */
+#define GlueIsNonScript 2 /* \nonscript */
+#define GlueIsMuGlue 3 /* mu glue */
+#define GlueIsALeaders 4 /* aligned leaders */
+#define GlueIsCLeaders 5 /* centered leaders */
+#define GlueIsXLeaders 6 /* expanded leaders */
+struct gluenode {
+ int gn_type; /* special glue types */
+ struct node *gn_glue; /* the glue itself */
+ struct BoundName *gn_skip; /* skip parameter that generated it */
+ struct box *gn_leaderbox; /* leader box if leaders */
+};
+
+/* a kern */
+#define ImplicitKern 0 /* kerning for things like "AV" */
+#define ExplicitKern 1 /* \kern or italic correction */
+#define MKern 2 /* \mkern */
+struct kern {
+ int kern_type; /* type of kern */
+ scaled kern_width; /* width of kern */
+};
+
+/*
+ * An unset (incomplete) alignment (\halign or \valign).
+ * This looks to be the largest node type, so I am using 'char' and 'short'
+ * to try to keep it small...
+ */
+struct unsetalign {
+ scaled unset_width; /* width of the unset box */
+ scaled unset_depth; /* depth of the unset box */
+ scaled unset_height; /* height of the unset box */
+ struct node *unset_contents; /* contents of the unset box */
+ scaled unset_glueshrink; /* total glue shrink */
+ scaled unset_gluestretch; /* total glue stretch */
+ char unset_shrinkorder; /* glue shrink order */
+ char unset_stretchorder; /* glue stretch order */
+ short unset_spancount; /* the number of spanned columns */
+};
+
+/* a token list */
+struct toklist {
+ int tok_refcount; /* the number of references */
+ struct node *tok_list; /* the tokens or the macro def'n */
+};
+
+/* Math delimiter */
+struct delim {
+ char smallfam; /* family number for small char */
+ char smallchar; /* character in small family */
+ char largefam; /* family number for large char */
+ char largechar; /* character in large family */
+};
+
+/* Math atoms, radicals, \left s, \right s, accents */
+struct matom {
+ enum MKind kind; /* atom kind (if not \left, \right) */
+ struct node *nucleus; /* nucleus */
+ struct node *supscr; /* superscript (optional) */
+ struct node *subscr; /* subscript (optional) */
+ struct delim delimiter; /* delimiter(s) (optional) */
+ /* accents are stored in the small delim */
+};
+
+/* Math fraction */
+struct mfrac {
+ struct node *numerator; /* numerator */
+ struct node *denominator; /* denominator */
+ scaled thickness; /* dividing rule thickness */
+ struct delim leftdelim; /* left delimiter (optional) */
+ struct delim rightdelim; /* right delimiter (optional) */
+};
+
+/* Math choice */
+struct mchoice {
+ struct node *ifdisplay;
+ struct node *iftext;
+ struct node *ifscript;
+ struct node *ifsscript;
+};
+
+/*
+ * This structure exists mainly for `sizeof'. Character nodes are by far the
+ * most common nodes, so to save memory space, nodes of type CharNode are kept
+ * in a separate free list and do not get a full size node. This means that
+ * node lists must be handled carefully, but that is already necessary, so it
+ * is no loss.
+ */
+struct charnode {
+ struct node *next;
+ short type;
+ struct fontchar fc;
+};
+
+/*
+ * A node in a list. Note that the first part of this structure is shared
+ * with the struct charnode.
+ */
+struct node {
+ struct node *next; /* next in linked list */
+ short type; /* type of this node */
+ struct fontchar fc; /* value iff char */
+ union {
+ struct box un_box; /* value iff box */
+ struct rule un_rule; /* value iff rule */
+ struct insert un_ins; /* value iff insert */
+ struct toklist *un_mark; /* value iff mark */
+ struct ligature un_lig; /* value iff ligature */
+ struct discret un_disc; /* value iff discret. brk */
+ struct whatsit un_whatsit; /* value iff whatsit */
+ struct gluespec un_gluespec; /* value iff glue */
+ struct gluenode un_gluenode; /* value iff link to glue */
+ struct kern un_kern; /* value iff kern */
+ i32 un_integer; /* value if integer */
+ struct unsetalign un_unset; /* value iff unset alignment */
+ struct matom un_matom; /* value if math atom */
+ struct mfrac un_mfrac; /* value iff math fraction */
+ struct mchoice un_mchoice; /* value iff math choice */
+ struct node *un_node; /* value if node list */
+ } node_un;
+};
+
+/* Shorthand */
+#define FC fc
+#define Font fc.fc_font
+#define Char fc.fc_char
+
+#define BoxWidth node_un.un_box.bx_width
+#define BoxDepth node_un.un_box.bx_depth
+#define BoxHeight node_un.un_box.bx_height
+#define BoxOffset node_un.un_box.bx_offset
+#define BoxContents node_un.un_box.bx_contents
+#define BoxGlueOrder node_un.un_box.bx_glueorder
+#define BoxGlueSet node_un.un_box.bx_glueset
+
+#define RuleWidth node_un.un_rule.ru_width
+#define RuleDepth node_un.un_rule.ru_depth
+#define RuleHeight node_un.un_rule.ru_height
+
+#define InsertNumber node_un.un_ins.ins_number
+#define InsertFloatingPenalty node_un.un_ins.ins_floatingpenalty
+#define InsertNaturalHeightPlusDepth node_un.un_ins.ins_naturalheightplusdepth
+#define InsertSplitMaxDepth node_un.un_ins.ins_splitmaxdepth
+#define InsertSplitTopSkip node_un.un_ins.ins_splittopskip
+#define InsertContents node_un.un_ins.ins_contents
+
+#define Mark node_un.un_mark
+
+#define LigatureFC node_un.un_lig.lig_fc
+#define LigatureOrig node_un.un_lig.lig_orig
+
+#define DiscretPreBreak node_un.un_disc.disc_prebrk
+#define DiscretPostBreak node_un.un_disc.disc_postbrk
+#define DiscretReplaces node_un.un_disc.disc_replaces
+
+#define WhatsitType node_un.un_whatsit.wh_type
+#define WhatsitOther node_un.un_whatsit.wh_other
+
+#define GlueRefCount node_un.un_gluespec.gl_refcount
+#define GlueWidth node_un.un_gluespec.gl_width
+#define GlueStretch node_un.un_gluespec.gl_stretch
+#define GlueShrink node_un.un_gluespec.gl_shrink
+#define GlueStretchOrder node_un.un_gluespec.gl_stretchorder
+#define GlueShrinkOrder node_un.un_gluespec.gl_shrinkorder
+
+#define Glue node_un.un_gluenode.gn_glue
+#define GlueSkip node_un.un_gluenode.gn_skip
+#define GlueType node_un.un_gluenode.gn_type
+#define GlueLeaderBox node_un.un_gluenode.gn_leaderbox
+
+#define KernWidth node_un.un_kern.kern_width
+#define KernType node_un.un_kern.kern_type
+
+#define Penalty node_un.un_integer
+
+#define UnsetWidth node_un.un_unset.unset_width
+#define UnsetDepth node_un.un_unset.unset_depth
+#define UnsetHeight node_un.un_unset.unset_height
+#define UnsetContents node_un.un_unset.unset_contents
+#define UnsetGlueShrink node_un.un_unset.unset_glueshrink
+#define UnsetGlueStretch node_un.un_unset.unset_gluestretch
+#define UnsetShrinkOrder node_un.un_unset.unset_shrinkorder
+#define UnsetStretchOrder node_un.un_unset.unset_stretchorder
+#define UnsetSpanCount node_un.un_unset.unset_spancount
+
+#define MAtomKind node_un.un_matom.kind
+#define MAtomNucleus node_un.un_matom.nucleus
+#define MAtomSupscr node_un.un_matom.supscr
+#define MAtomSubscr node_un.un_matom.subscr
+#define MAtomDelimiter node_un.un_matom.delimiter
+#define MAtomAccFam node_un.un_matom.delimiter.smallfam
+#define MAtomAccChar node_un.un_matom.delimiter.smallchar
+
+#define MFracNumerator node_un.un_mfrac.numerator
+#define MFracDenominator node_un.un_mfrac.denominator
+#define MFracThickness node_un.un_mfrac.thickness
+#define MFracLeftDelim node_un.un_mfrac.leftdelim
+#define MFracRightDelim node_un.un_mfrac.rightdelim
+
+#define MChoiceDisplay node_un.un_mchoice.ifdisplay
+#define MChoiceText node_un.un_mchoice.iftext
+#define MChoiceScript node_un.un_mchoice.ifscript
+#define MChoiceSScript node_un.un_mchoice.ifsscript
+
+#define MStyle node_un.un_integer
+
+#define MSub node_un.un_node
+
+struct node *FreeNodes;
+struct node *FreeChars;
+
+struct node *MoreNodes();
+struct node *MoreChars();
+
+/*
+ * These macros quickly allocate and dispose of nodes. Watch out; the
+ * arguments to NewNode and NewCharNode should be pointers that are to
+ * be filled in. Moreover, the argument is accessed twice, so beware
+ * side effects!
+ */
+#define NewNode(n) \
+ if (((n) = FreeNodes) == NULL) \
+ (n) = MoreNodes(); \
+ else \
+ FreeNodes = (n)->next
+
+#define NewCharNode(n) \
+ if (((n) = FreeChars) == NULL) \
+ (n) = MoreChars(); \
+ else \
+ FreeChars = (n)->next
+
+#define FreeNode(n) ((n)->next = FreeNodes, FreeNodes = (n))
+#define FreeChar(n) ((n)->next = FreeChars, FreeChars = (n))
+
+/* To free either a CharNode or a Node, use FreeEither! */
+#define FreeEither(n) ((n)->type ? FreeNode(n) : FreeChar(n))
+
+#define DelTokRef(p) (--(p)->tok_refcount < 0 ? FlushList(p) : NULL)
+#define DelGlueRef(p) (--(p)->GlueRefCount < 0 ? FreeNode(p) : NULL)
+
+/* These determine the granularity of node allocation */
+#define NodeAllocSize 300 /* Nodes per MoreNodes() */
+#define CharAllocSize 2500 /* CharNodes per MoreChars() */
+
+struct node *CopyGlueSpec();
+struct node *LinkToSkipParam();
+struct node *LinkToGlueSpec();
+struct node *LinkToCopyOfSkipParam();
+
+#define NodeListDisplay(p) (s_addc('.'), ShowNodeList(p), s_delc())
+
+/*
+ * The ordering of the types is important here, because it allows simple
+ * decisions for common operations.
+ */
+#define CanBreakAtGlue(n) ((n)->type < BeginMathNode)
+#define CanDiscardAfterBreak(n) ((n)->type >= BeginMathNode)
+
+struct node ZeroGlue; /* the zero-amount glue (0pt) */
+struct node FilGlue; /* 0pt plus1fil minus0pt */
+struct node FillGlue; /* 0pt plus1fill minus0pt */
+struct node SSGlue; /* 0pt plus1fil minus1fil */
+struct node FilNegGlue; /* 0pt plus-1fil minus0pt */
+i32 ShowBoxMaxDepth; /* max nesting depth in box displays */
+i32 ShowBoxMaxBreadth; /* max number of items per list level */
+int FontInShortDisplay; /* the "current font" during a ShortDisplay */
diff --git a/dviware/umddvi/h/conv.h b/dviware/umddvi/h/conv.h
new file mode 100644
index 0000000000..0f10cf8536
--- /dev/null
+++ b/dviware/umddvi/h/conv.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 1987 University of Maryland Department of Computer Science.
+ * All rights reserved. Permission to copy for any purpose is hereby granted
+ * so long as this copyright notice remains intact.
+ */
+
+/*
+ * Conversions. Conversion factors convert between values in scaled
+ * points and values in device-dependenent units. The results of all
+ * conversions are rounded to the nearest integral value, of type (i32).
+ */
+
+/*
+ * This is now done using `double' values, but may be changed to
+ * fixed-point or some other `fast' method, as long as the results
+ * are consistent and reasonably accurate. The structure `conversion'
+ * holds the conversion-method-dependent quantities; the macros
+ * fromSP and toSP apply the conversion to a value. (Note that
+ * fromSP and toSP need not be macros, but should be fast.)
+ *
+ * SetConversion sets the (single, global) conversion factor.
+ * If a driver needs special conversions, there is another routine,
+ * CSetConversion that sets a specific conversion, and cfromSP and
+ * ctoSP to apply these.
+ *
+ * IS USING DOTS PER INCH SUFFICIENT? (Pixels per point might be better.)
+ *
+ * Note that it is necessary to set the global conversion factor before
+ * using any fonts.
+ */
+struct conversion {
+ double c_fromsp; /* multiplier to convert from scaled points */
+ double c_tosp; /* multiplier to convert to scaled points:
+ could divide by c_fromsp, but this should
+ be faster and more accurate */
+ double c_mag; /* the magnification this conversion
+ represents; mainly for GetFont() */
+ double c_dpi; /* dpi (should be pixels per point?) */
+} Conversion;
+
+/*
+ * In order to do this, we need to round properly. The compilers I
+ * have tend to generate very poor code for this. The following is
+ * intended to help them out. Smarter compilers can do better, but
+ * if they are smart enough, they will realise that the variables
+ * here are not used anywhere else, and discard them. (For a compiler
+ * to do this given separate compliation, `static' is a must.)
+ */
+#ifdef lint /* or a smart compiler */
+#define ROUND(f) ((i32) ((f) < 0.0 ? (f) - 0.5 : (f) + 0.5))
+#define CEIL(f) ((double) (i32) (f) < (f) ? (i32) (f) + 1 : (i32) (f))
+#else
+static double _half = 0.5;
+static double _zero = 0.0;
+static double _d;
+#define ROUND(f) ((i32) (_d = (f), _d < _zero ? _d - _half : _d + _half))
+#ifdef NEGATIVE_FLOAT_ROUNDS_TO_NEGATIVE_INFINITY
+#define CEIL(f) (-(i32) -(f))
+#else /* we will assume that floating to integer truncates */
+static i32 _i;
+#define CEIL(f) (_i = _d = (f), _i < _d ? _i + 1 : _i)
+#endif /* round towards negative infinity */
+#endif /* lint */
+
+#define SetConversion(dpi, usermag, num, denom, dvimag) \
+ CSetConversion(&Conversion, dpi, usermag, num, denom, dvimag)
+
+#define cfromSP(c, v) ROUND((c)->c_fromsp * (v))
+#define ctoSP(c, v) ROUND((c)->c_tosp * (v))
+
+#define fromSP(v) cfromSP(&Conversion, v)
+#define toSP(v) ctoSP(&Conversion, v)
+
+/*
+ * Conversions for rules are a bit different: we must round up, rather
+ * than off. ConvRule applies the global conversion value for a rule
+ * value (height or width); CConvRule applies a specific conversion.
+ */
+#define CConvRule(c, v) CEIL((c)->c_fromsp * (v))
+#define ConvRule(v) CConvRule(&Conversion, v)
+
+void CSetConversion();
diff --git a/dviware/umddvi/h/dmddev.h b/dviware/umddvi/h/dmddev.h
new file mode 100644
index 0000000000..d536ad8169
--- /dev/null
+++ b/dviware/umddvi/h/dmddev.h
@@ -0,0 +1,19 @@
+/* dmd globals */
+
+/* Accounting: */
+#ifndef ACCOUNT_FILE
+/*
+#define ACCOUNT_FILE "/usr/adm/imagen_acct"/* if defined, the name of the
+ imagen page accounting file */
+#endif ACCOUNT_FILE
+
+#define NFONTS 128 /* Max number of fonts. 128 is a hardware
+ limitation. */
+#define DefaultDPI 118 /* 300 for Imagen 8/300, 240 for Imprint-10 */
+
+#define DefaultMaxDrift 3 /* default value for MaxDrift */
+
+/* Default margins, in dots */
+/* CRUFT ALERT: depending on DPI variable */
+#define DefaultTopMargin (0) /* 1" margins */
+#define DefaultLeftMargin (0)
diff --git a/dviware/umddvi/h/dvi.h b/dviware/umddvi/h/dvi.h
new file mode 100644
index 0000000000..94640b0678
--- /dev/null
+++ b/dviware/umddvi/h/dvi.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 1987 University of Maryland Department of Computer Science.
+ * All rights reserved. Permission to copy for any purpose is hereby granted
+ * so long as this copyright notice remains intact.
+ */
+
+/* DVI file info */
+
+/*
+ * Units of distance are stored in scaled points, but we can convert to
+ * units of 10^-7 meters by multiplying by the numbers in the preamble.
+ */
+
+/* the structure of the stack used to hold the values (h,v,w,x,y,z) */
+struct dvi_stack {
+ i32 h; /* the saved h */
+ i32 v; /* the saved v */
+ i32 w; /* etc */
+ i32 x;
+ i32 y;
+ i32 z;
+};
+
+struct dvi_stack dvi_current; /* the current values of h, v, etc */
+
+int dvi_f; /* the current font */
+
+#define dvi_h dvi_current.h
+#define dvi_v dvi_current.v
+#define dvi_w dvi_current.w
+#define dvi_x dvi_current.x
+#define dvi_y dvi_current.y
+#define dvi_z dvi_current.z
diff --git a/dviware/umddvi/h/dviclass.h b/dviware/umddvi/h/dviclass.h
new file mode 100644
index 0000000000..0ffef36b81
--- /dev/null
+++ b/dviware/umddvi/h/dviclass.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 1987 University of Maryland Department of Computer Science.
+ * All rights reserved. Permission to copy for any purpose is hereby granted
+ * so long as this copyright notice remains intact.
+ */
+
+/*
+ * Macros to convert DVI opcodes to (hopefully) simpler values.
+ */
+
+/*
+ * Large range types.
+ */
+#define DVI_IsChar(code) ((code) < 128)
+#define DVI_IsFont(code) ((code) >= 171 && (code) < 235)
+
+/*
+ * Symbolic names for generic types (for things with parameters).
+ * These are obtained via the macro DVI_DT(int c), where 0 <= c <= 255.
+ */
+#define DT_CHAR 0
+#define DT_SET 1
+#define DT_SETRULE 2
+#define DT_PUT 3
+#define DT_PUTRULE 4
+#define DT_NOP 5
+#define DT_BOP 6
+#define DT_EOP 7
+#define DT_PUSH 8
+#define DT_POP 9
+#define DT_RIGHT 10
+#define DT_W0 11
+#define DT_W 12
+#define DT_X0 13
+#define DT_X 14
+#define DT_DOWN 15
+#define DT_Y0 16
+#define DT_Y 17
+#define DT_Z0 18
+#define DT_Z 19
+#define DT_FNTNUM 20
+#define DT_FNT 21
+#define DT_XXX 22
+#define DT_FNTDEF 23
+#define DT_PRE 24
+#define DT_POST 25
+#define DT_POSTPOST 26
+#define DT_UNDEF 27
+
+/*
+ * Symbolic names for parameter lengths, obtained via the macro
+ * DVL_OpLen(int c).
+ *
+ * N.B.: older drivers may assume that 0 => none, 1-4 => 1-4 bytes
+ * and 5-7 => unsigned version of 1-4---so DO NOT change these values!
+ */
+#define DPL_NONE 0
+#define DPL_SGN1 1
+#define DPL_SGN2 2
+#define DPL_SGN3 3
+#define DPL_SGN4 4
+#define DPL_UNS1 5
+#define DPL_UNS2 6
+#define DPL_UNS3 7
+/* there are no unsigned four byte parameters */
+
+#define DVI_OpLen(code) (dvi_oplen[code])
+#define DVI_DT(code) (dvi_dt[code])
+extern char dvi_oplen[];
+extern char dvi_dt[];
diff --git a/dviware/umddvi/h/dvicodes.h b/dviware/umddvi/h/dvicodes.h
new file mode 100644
index 0000000000..de5a80b5a8
--- /dev/null
+++ b/dviware/umddvi/h/dvicodes.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 1987 University of Maryland Department of Computer Science.
+ * All rights reserved. Permission to copy for any purpose is hereby granted
+ * so long as this copyright notice remains intact.
+ */
+
+/* DVI opcodes */
+
+#define DVI_VERSION 2 /* version number that should appear in
+ pre- and post-ambles */
+
+#define DVI_SET1 128 /* set character, 1 byte param */
+#define DVI_SET2 129 /* set character, 2 byte param */
+#define DVI_SET3 130 /* set character, 3 byte param */
+#define DVI_SET4 131 /* set character, 4 byte param */
+#define DVI_SETRULE 132 /* set a rule */
+#define DVI_PUT1 133 /* put char, don't move right */
+#define DVI_PUT2 134 /* put char, 2 byte */
+#define DVI_PUT3 135 /* etc */
+#define DVI_PUT4 136
+#define DVI_PUTRULE 137 /* put rule, don't move right */
+#define DVI_NOP 138 /* no-op */
+#define DVI_BOP 139 /* begin page */
+#define DVI_EOP 140 /* end page */
+#define DVI_PUSH 141 /* push h,v,w,x,y,z */
+#define DVI_POP 142 /* pop h,v,w,x,y,z */
+#define DVI_RIGHT1 143 /* move right, 1 byte signed param */
+#define DVI_RIGHT2 144 /* move right, 2 byte signed param */
+#define DVI_RIGHT3 145 /* etc */
+#define DVI_RIGHT4 146
+#define DVI_W0 147 /* h += w */
+#define DVI_W1 148 /* w = 1 byte signed param, h += w */
+#define DVI_W2 149 /* w = 2 byte etc, h += w */
+#define DVI_W3 150
+#define DVI_W4 151
+#define DVI_X0 152 /* like DVI_W0 but for x */
+#define DVI_X1 153 /* etc */
+#define DVI_X2 154
+#define DVI_X3 155
+#define DVI_X4 156
+#define DVI_DOWN1 157 /* v += 1 byte signed param */
+#define DVI_DOWN2 158 /* v += 2 byte signed param */
+#define DVI_DOWN3 159 /* etc */
+#define DVI_DOWN4 160
+#define DVI_Y0 161 /* y = 1 byte signed param, v += y */
+#define DVI_Y1 162 /* etc */
+#define DVI_Y2 163
+#define DVI_Y3 164
+#define DVI_Y4 165
+#define DVI_Z0 166 /* z = 1 byte signed param, v += z */
+#define DVI_Z1 167 /* etc */
+#define DVI_Z2 168
+#define DVI_Z3 169
+#define DVI_Z4 170
+#define DVI_FNTNUM0 171
+
+#define DVI_FNT1 235 /* select font, 1 byte param */
+#define DVI_FNT2 236 /* etc */
+#define DVI_FNT3 237
+#define DVI_FNT4 238
+#define DVI_XXX1 239 /* for \special: if length < 256 */
+#define DVI_XXX2 240 /* etc */
+#define DVI_XXX3 241
+#define DVI_XXX4 242
+#define DVI_FNTDEF1 243 /* Define font, 1 byte param (0 to 63) */
+#define DVI_FNTDEF2 244 /* etc */
+#define DVI_FNTDEF3 245
+#define DVI_FNTDEF4 246
+#define DVI_PRE 247 /* preamble */
+#define DVI_POST 248 /* postamble */
+#define DVI_POSTPOST 249 /* end of postamble */
+#define DVI_FILLER 223 /* filler bytes at end of dvi file */
diff --git a/dviware/umddvi/h/error.h b/dviware/umddvi/h/error.h
new file mode 100644
index 0000000000..49423042db
--- /dev/null
+++ b/dviware/umddvi/h/error.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 1987 University of Maryland Department of Computer Science.
+ * All rights reserved. Permission to copy for any purpose is hereby granted
+ * so long as this copyright notice remains intact.
+ */
+
+char *HelpMsg; /* the current help message, if any */
+int UseErrHelp; /* true iff HelpMsg makes sense */
+int ErrHistory; /* the error history */
+int Interaction; /* the interaction level */
+int ErrCount; /* total errors since last paragraph */
+int DeletionsAllowed; /* true iff user is allowed to delete tokens
+ in the error recovery code */
+
+/* values for ErrHistory, in increasing order of severity */
+#define EH_Spotless 0 /* no errors */
+#define EH_Warning 1 /* gave a warning (diagnostic) */
+#define EH_ErrMessage 2 /* gave an error message */
+#define EH_FatalErr 3 /* died on a fatal error */
+
+/* values for Interaction */
+#define IA_ErrStop 0 /* stop on error */
+#define IA_ErrScroll 1 /* do not stop on error */
+#define IA_NonStop 2 /* do not ever stop */
+#define IA_Batch 3 /* neither stop nor produce tty output */
+
+/* pick an output descriptor; there is no log file right now */
+#define NoLogErrFD() (Interaction == IA_Batch ? OutIgnore : OutTerm)
diff --git a/dviware/umddvi/h/fio.h b/dviware/umddvi/h/fio.h
new file mode 100644
index 0000000000..46b3851fb3
--- /dev/null
+++ b/dviware/umddvi/h/fio.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 1987 University of Maryland Department of Computer Science.
+ * All rights reserved. Permission to copy for any purpose is hereby granted
+ * so long as this copyright notice remains intact.
+ */
+
+/*
+ * File I/O: numbers.
+ *
+ * We deal in fixed format numbers and (FILE *)s here.
+ * For pointer I/O, see pio.h.
+ *
+ * N.B.: These do the `wrong thing' at EOF. It is imperative
+ * that the caller add appropriate `if (feof(fp))' statements.
+ */
+
+/*
+ * Get one unsigned byte. Note that this is a proper expression.
+ * The reset have more limited contexts, and are therefore OddLy
+ * CapItaliseD.
+ */
+#define fgetbyte(fp) (getc(fp))
+
+/*
+ * Get a two-byte unsigned integer, a three-byte unsigned integer,
+ * or a four-byte signed integer.
+ */
+#define fGetWord(fp, r) ((r) = getc(fp) << 8, (r) |= getc(fp))
+#define fGet3Byte(fp,r) ((r) = getc(fp) << 16, (r) |= getc(fp) << 8, \
+ (r) |= getc(fp))
+#define fGetLong(fp, r) ((r) = getc(fp) << 24, (r) |= getc(fp) << 16, \
+ (r) |= getc(fp) << 8, (r) |= getc(fp))
+
+/*
+ * Fast I/O write (and regular write) macros.
+ */
+#define putbyte(fp, r) (putc((r), fp))
+
+#define PutWord(fp, r) (putc((r) >> 8, fp), putc((r), fp))
+#define Put3Byte(fp, r) (putc((r) >> 16, fp), putc((r) >> 8, fp), \
+ putc((r), fp))
+#define PutLong(fp, r) (putc((r) >> 24, fp), putc((r) >> 16, fp), \
+ putc((r) >> 8, fp), putc((r), fp))
+
+/*
+ * Function types
+ */
+i32 GetByte(), GetWord(), Get3Byte(), GetLong();
diff --git a/dviware/umddvi/h/font.h b/dviware/umddvi/h/font.h
new file mode 100644
index 0000000000..2f1e7e7da2
--- /dev/null
+++ b/dviware/umddvi/h/font.h
@@ -0,0 +1,223 @@
+/*
+ * Copyright (c) 1987 University of Maryland Department of Computer Science.
+ * All rights reserved. Permission to copy for any purpose is hereby granted
+ * so long as this copyright notice remains intact.
+ */
+
+/*
+ * Font file information, readers, etc.
+ */
+
+#ifndef _CTEX_TYPES_
+#include "types.h"
+#endif
+
+/*
+ * First, font independent information: per glyph info, and per font
+ * info.
+ */
+struct glyph {
+ short g_flags; /* see below */
+ /*
+ * The following cannot be used with GetRasterlessFont
+ */
+ short g_rotation; /* see below */
+ char *g_raster; /* raster, if known */
+ /*
+ * These, however, do come with rasterless fonts,
+ * even though they relate only to the raster.
+ */
+ i32 g_height; /* height of bounding box */
+ i32 g_width; /* width of bounding box */
+ i32 g_yorigin; /* y origin (>= 0 -> within box) */
+ i32 g_xorigin; /* x origin (>= 0 -> within box) */
+ /*
+ * This of course comes with every font.
+ */
+ i32 g_tfmwidth; /* width in scaled points (not FIXes!) */
+#ifdef notyet /* THESE NEED MORE THOUGHT */
+ i32 g_xescapement; /* x escapement (`chardx') */
+ i32 g_yescapement; /* y escapement (`chardy') */
+#endif
+ /*
+ * This is provided purely for DVI to device conversion programs.
+ */
+ int g_pixwidth; /* width in pixels */
+ /*
+ * Mainly for internal use, index is the glyph index within the
+ * font. That is, f->f_gly[i]->g_index == i.
+ */
+ int g_index; /* character index */
+ /*
+ * g_details and g_integer are purely for the font reading
+ * subroutines to use however they will. g_next makes lists
+ * of glyphs while the glyphs are free.
+ */
+ union { /* various options */
+ char *g_details; /* details: arbitrary */
+ i32 g_integer; /* 32 bit integer */
+ struct glyph *g_next; /* linked list */
+ } g_un;
+};
+
+/*
+ * Glyph flags.
+ */
+#define GF_VALID 0x0001 /* glyph is `real' */
+#define GF_USR0 0x0100 /* reserved to user code */
+#define GF_USR1 0x0200 /* reserved to user code */
+#define GF_USR2 0x0400 /* reserved to user code */
+#define GF_USR3 0x0800 /* reserved to user code */
+
+/*
+ * Rotations are in quarter-pi steps, counterclockwise of course.
+ * This order must be maintained; see rotate.c.
+ */
+#define ROT_NORM 0 /* no rotation: `normal' position */
+#define ROT_LEFT 1 /* 1/4 turn counterclockwise */
+#define ROT_DOWN 2 /* 1/2 turn, i.e., upside-down */
+#define ROT_RIGHT 3 /* 3/4 turn ccw, or 1/4 turn cw */
+
+struct font {
+ int f_flags; /* see below */
+ struct fontops *f_ops; /* operations */
+ /*
+ * f_details is provided for font reading subroutines.
+ * It is intended to be cast to a pointer to a structure
+ * that is allocated by those routines, and used to keep
+ * track of whatever information those routines need to
+ * determine glyph boxes and (if asked for) rasters.
+ */
+ char *f_details; /* type dependent stuff */
+ /*
+ * f_path is the full pathname to the font file, filled in
+ * by GetFont and GetRasterlessFont. Note that since we
+ * hold on to the path until the font is freed, it should be
+ * possible to cache glyph accesses on memory-poor machines.
+ */
+ char *f_path; /* font file pathname */
+ /*
+ * f_dvimag and f_dvidsz are the magnification and design size
+ * values from the DVI file. f_font and f_scaled correspond to
+ * TeX's idea of the proper name for the font (e.g., `cmr10',
+ * `cmbx10 scaled 1440'). (Note that f_scaled is just the
+ * ratio of f_dvimag and f_dvidsz; you could save a bit of memory
+ * by eliminating it and altering the routine Font_TeXName()).
+ * f_checksum should be set by the font reading routines to
+ * the font checksum. If the value is nonzero, it will be
+ * compared to the checksum in the DVI file.
+ */
+ i32 f_dvimag; /* magnification from DVI file */
+ i32 f_dvidsz; /* design size from DVI file */
+ char *f_font; /* TeX's name for the font */
+ int f_scaled; /* the ratio of dvimag to dvidsz, x1000 */
+ i32 f_checksum; /* font checksum, or 0 */
+#ifdef notyet /* THESE NEED MORE THOUGHT */
+ i32 f_hppp; /* horizontal pixels per point */
+ i32 f_vppp; /* vertical pixels per point */
+#endif
+ /*
+ * f_lowch and f_highch bound the region in which f_gly
+ * indicies are valid. Specificially, f_gly[i] may be
+ * read or written if and only if i is in the half-open
+ * interval [f_lowch..f_highch). f_gly is an array of
+ * pointers to glyph structures. The structures themselves
+ * are not allocated until requested.
+ *
+ * f_glybase is the actual return from malloc(), since it
+ * is theoretically possible for f_gly-f_lowch to become
+ * NULL.
+ */
+ int f_lowch; /* first character */
+ int f_highch; /* last character, plus 1 */
+ struct glyph **f_gly; /* glyphs */
+ struct glyph **f_glybase;
+};
+
+/*
+ * Font flags.
+ */
+#define FF_RASTERS 0x0001 /* font has rasters */
+#define FF_USR0 0x0100 /* reserved to user code */
+#define FF_USR1 0x0200 /* reserved to user code */
+#define FF_USR2 0x0400 /* reserved to user code */
+#define FF_USR3 0x0800 /* reserved to user code */
+
+/*
+ * Operations on fonts.
+ *
+ * The `fo_dpitomag' field is used as a multiplier for a desired
+ * resolution in dots per inch. The result of the multiplication
+ * is converted to a font name by multipying by 1000.0 and rounding.
+ * The idea is that PXL files will have a multiplier of 5.0, and
+ * others will have a multiplier of 1.0. This suffices for the
+ * present, at any rate; in the future, this field may be replaced
+ * with something more general.
+ *
+ * N.B.: more operations may be added as they are discovered to be
+ * useful.
+ */
+struct fontops {
+ char *fo_name; /* name, e.g., "gf" */
+ double fo_dpitomag; /* multiplier */
+ int (*fo_read)(); /* open and read the font itself */
+ int (*fo_getgly)(); /* obtain specified glyphs (range) */
+#ifdef notdef
+ int (*fo_freegly)(); /* release specified glyphs */
+#endif
+ int (*fo_rasterise)(); /* rasterise specified glyphs */
+ int (*fo_freefont)(); /* discard font (free details) */
+ struct fontops *fo_next; /* purely for font.c */
+};
+
+/*
+ * Return a pointer to the glyph information for character `c' in
+ * font `f'.
+ */
+#define GLYPH(f, c) \
+ ((c) < (f)->f_lowch || (c) >= (f)->f_highch ? (struct glyph *) 0 : \
+ ((f)->f_gly[c] ? (f)->f_gly[c] : GetGlyph(f, c)))
+
+/*
+ * True iff glyph `g' is valid. Useful for checking return values
+ * from GLYPH().
+ */
+#define GVALID(g) ((g) && ((g)->g_flags & GF_VALID))
+
+/*
+ * True iff glyph g has a raster.
+ */
+#define HASRASTER(g) ((g)->g_height || (g)->g_width)
+
+/*
+ * Return a pointer to the raster information for glyph `g' in font
+ * `f' at rotation `r'.
+ */
+#define RASTER(g, f, r) ((g)->g_rotation == (r) && (g)->g_raster ? \
+ (g)->g_raster : GetRaster(g, f, r))
+
+/*
+ * Function types.
+ */
+struct font *GetFont(), *GetRasterlessFont();
+struct glyph *GetGlyph();
+char *GetRaster();
+void FreeFont();
+void FreeGlyph();
+void FreeRaster();
+char *Font_TeXName();
+double DMagFactor(); /* from magfactor.c */
+
+/*
+ * Normally from stdio.h
+ */
+#ifndef NULL
+#define NULL 0
+#endif
+
+/*
+ * The following environment variable overrides the default font
+ * configuration file. That default is used when fontinit() is not
+ * called, or is passed a null pointer.
+ */
+#define CONFENV "TEXFONTDESC"
diff --git a/dviware/umddvi/h/gfclass.h b/dviware/umddvi/h/gfclass.h
new file mode 100644
index 0000000000..cd392ac2bb
--- /dev/null
+++ b/dviware/umddvi/h/gfclass.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 1987 University of Maryland Department of Computer Science.
+ * All rights reserved. Permission to copy for any purpose is hereby granted
+ * so long as this copyright notice remains intact.
+ */
+
+/*
+ * GF classification codes
+ */
+
+/*
+ * Predicate for simple paint commands. This is presumably the most
+ * common GF operation; it may be profitable to check for this before
+ * switching out on the command type.
+ */
+#define GF_IsPaint(c) ((c) < 64)
+
+/*
+ * Symbolic names for command `types', as returned by the macro
+ * GT_TYPE(int c).
+ */
+#define GT_PAINT0 0 /* paint without parameter */
+#define GT_PAINT 1 /* paint with parameter */
+#define GT_BOC 2 /* long BOC */
+#define GT_BOC1 3 /* short BOC */
+#define GT_EOC 4 /* EOC */
+#define GT_SKIP0 5 /* parameterless SKIP */
+#define GT_SKIP 6 /* parmeterised SKIP */
+#define GT_NEW_ROW 7 /* NEW_ROW_n */
+#define GT_XXX 8 /* XXXn */
+#define GT_YYY 9 /* YYY */
+#define GT_NOP 10 /* no op */
+#define GT_CHAR_LOC 11 /* CHAR_LOC */
+#define GT_CHAR_LOC0 12 /* abbreviated CHAR_LOC */
+#define GT_PRE 13
+#define GT_POST 14
+#define GT_POSTPOST 15
+#define GT_UNDEF 16
+
+/*
+ * Symbolic names for parameter lengths, obtained via the macro
+ * GT_OpLen(int c).
+ */
+#define GPL_NONE 0 /* no parameter, or too complex */
+#define GPL_UNS1 1 /* one one-byte parameter in 0..255 */
+#define GPL_UNS2 2 /* one two-byte parameter in 0..65535 */
+#define GPL_UNS3 3 /* one three-byte parameter in 0..16777215 */
+#define GPL_SGN4 4 /* one four-byte signed parameter */
+/*
+ * there are no unsigned four byte parameters, and no shorter signed
+ * parameters
+ */
+
+#define GF_OpLen(code) (gf_oplen[code])
+#define GF_TYPE(code) (gf_gt[code])
+extern char gf_oplen[];
+extern char gf_gt[];
diff --git a/dviware/umddvi/h/gfcodes.h b/dviware/umddvi/h/gfcodes.h
new file mode 100644
index 0000000000..b4d293ee13
--- /dev/null
+++ b/dviware/umddvi/h/gfcodes.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 1987 University of Maryland Department of Computer Science.
+ * All rights reserved. Permission to copy for any purpose is hereby granted
+ * so long as this copyright notice remains intact.
+ */
+
+/*
+ * GF (generic font) opcodes.
+ */
+
+#define GF_PAINT_0 0 /* paint with `d' = 0 */
+ /* ... through PAINT_63, d = 63 */
+#define GF_PAINT1 64 /* paint, with a one-byte parameter */
+#define GF_PAINT2 65 /* paint, with a two-byte parameter */
+#define GF_PAINT3 66 /* paint, with a three-byte parameter */
+#define GF_BOC 67 /* beginning of character */
+#define GF_BOC1 68 /* compressed form of BOC */
+#define GF_EOC 69 /* end of character */
+#define GF_SKIP0 70 /* finish this row, begin next with white */
+#define GF_SKIP1 71 /* finish row, one byte parameter */
+#define GF_SKIP2 72
+#define GF_SKIP3 73
+#define GF_NEW_ROW_0 74 /* begin a new row, ready to blacken */
+#define GF_NEW_ROW_1 75 /* begin a new row, but one col. from left */
+ /* through GF_NEW_ROW_164 */
+#define GF_XXX1 239 /* special (interpreter dependent) command */
+#define GF_XXX2 240 /* like XXX1, but two byte length parameter */
+#define GF_XXX3 241
+#define GF_XXX4 242
+#define GF_YYY 243 /* takes four byte parameter, otherwise nop */
+ /* (generated by METAFONT for numspecial) */
+#define GF_NOP 244 /* no op */
+#define GF_CHAR_LOC 245 /* character locator */
+#define GF_CHAR_LOC0 246 /* abbreviated form of CHAR_LOC */
+#define GF_PRE 247 /* introduces preamble */
+#define GF_POST 248 /* introduces postamble */
+#define GF_POSTPOST 249 /* marks end of postamble */
+
+ /* codes 250 through 255 are undefined */
+
+#define GF_ID 131 /* identifies this revision of GF */
+
+#define GF_FILLER 223 /* filler bytes at end of GF file */
diff --git a/dviware/umddvi/h/imagen.h b/dviware/umddvi/h/imagen.h
new file mode 100644
index 0000000000..fc80350172
--- /dev/null
+++ b/dviware/umddvi/h/imagen.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 1987 University of Maryland Department of Computer Science.
+ * All rights reserved. Permission to copy for any purpose is hereby granted
+ * so long as this copyright notice remains intact.
+ */
+
+/* imagen globals */
+
+/* Accounting: */
+#ifndef ACCOUNT_FILE
+/*
+#define ACCOUNT_FILE "/usr/adm/imagen_acct"/* if defined, the name of the
+ imagen page accounting file */
+#endif ACCOUNT_FILE
+
+#define MaxImFamily 128 /* hardware limitation on font family index */
+#define DefaultDPI 300 /* 300 for Imagen 8/300, 240 for Imprint-10 */
+
+#define DefaultMaxDrift 3 /* default value for MaxDrift */
+
+/* Default margins, in dots */
+/* CRUFT ALERT: depending on DPI variable */
+#define DefaultTopMargin (DPI) /* 1" margins */
+#define DefaultLeftMargin (DPI)
diff --git a/dviware/umddvi/h/impcodes.h b/dviware/umddvi/h/impcodes.h
new file mode 100644
index 0000000000..1fd946b8ce
--- /dev/null
+++ b/dviware/umddvi/h/impcodes.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 1987 University of Maryland Department of Computer Science.
+ * All rights reserved. Permission to copy for any purpose is hereby granted
+ * so long as this copyright notice remains intact.
+ */
+
+/* imPRESS command codes */
+
+#define imP_SP 128 /* advance one space */
+#define imP_SP1 129 /* advance one space plus 1 pixel */
+
+#define imP_Forw 131 /* one pixel forward */
+#define imP_Backw 132 /* one pixel backward */
+#define imP_MMove 133 /* move in main advance dir. */
+#define imP_SMove 134 /* move in secondary advance dir. */
+#define imP_SetHAbs 135 /* set absolute H pos */
+#define imP_SetHRel 136 /* set relative H pos */
+#define imP_SetVAbs 137 /* set absolute V pos */
+#define imP_SetVRel 138 /* set relative V pos */
+
+#define imP_Rule 193 /* print a rule */
+
+#define imP_CRLF 197 /* move to begin. of line */
+
+#define imP_DefGlyph 199 /* define a glyph */
+#define imP_DelGlyph 200 /* mark a glyph for deletion */
+
+#define imP_SetHVSystem 205 /* set the H/V coordinate system */
+#define imP_SetAdvDirs 206 /* set the advance directions */
+#define imP_SetFamily 207 /* use this particular family */
+#define imP_SetILSpace 208 /* set the interline spacing */
+#define imP_SetBOL 209 /* define the beginning of line */
+#define imP_SetSP 210 /* define the space between words */
+#define imP_CreateFam 211 /* define a family table */
+
+#define imP_Page 213 /* go to (0,0) */
+
+#define imP_EndPage 219 /* print the current page */
+
+#define imP_ForceDel 240 /* force glyph deletion */
+#define imP_EOF 255 /* end of document */
diff --git a/dviware/umddvi/h/io.h b/dviware/umddvi/h/io.h
new file mode 100644
index 0000000000..ce9bb4029c
--- /dev/null
+++ b/dviware/umddvi/h/io.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 1987 University of Maryland Department of Computer Science.
+ * All rights reserved. Permission to copy for any purpose is hereby granted
+ * so long as this copyright notice remains intact.
+ */
+
+/* C-Tex I/O definitions */
+
+/*
+ * For non-ASCII systems, someone would have to do a great deal of work
+ * in the various I/O routines to use the two translation tables. I have
+ * not the motivation.
+ */
+#ifdef notdef
+int InX[128]; /* input translation table */
+int OutX[128]; /* output translation table */
+#endif
+
+/*
+ * These `magic constants' are really the best we can do. Using termcap
+ * would not be quite right, because (1) the C-TeX run may not be on a
+ * terminal at all, and (2) the log file could very likely be viewed from
+ * a different terminal than was used for the C-TeX run.
+ */
+#define MaxPrLineLen 72 /* will try to never print lines longer
+ than this */
+#define MaxErrLineLen 72 /* errors (context actually) will never
+ be longer than this */
+#define HalfErrLine 42 /* about 1/2 MaxErrLineLen; this will be
+ the width of first lines of contexts */
+
+/*
+ * Input will be read into lines of InBufLen characters. This limits
+ * several things, including control sequence name length and length of
+ * strings read by \read.
+ */
+#define InBufLen 512
+
+/* Output descriptors. Note that 0-15 are indexes into OutF. */
+#define OutIgnore 16 /* nowhere; output is silently discarded */
+#define OutTerm 17 /* to terminal (stdout) */
+#define OutLog 18 /* to log file */
+#define OutTermAndLog 19 /* to terminal & log file both */
+#define OutString 20 /* to PoolString */
+#define OutCircBuf 21 /* to CircBuf */
+
+int OutFD; /* the current output descriptor */
+FILE *LogF; /* the log file */
+FILE *InF[16]; /* the 16 \read descriptors */
+FILE *OutF[16]; /* the 16 \write descriptors */
+char CircBuf[MaxErrLineLen]; /* this will be used for showing error
+ context; its length determines the
+ maximum amount of context that can
+ be shown. This is a way of getting
+ around a possibly massive amount of
+ stuff leading up to the point of the
+ error, without using backpointers.
+ Inefficient perhaps, but it does not
+ occur often. */
+
+/*
+ * On occasion it is nice to be able to interrupt the current output
+ * descriptor and switch to a new one. This does not happen often,
+ * so we just have a small stack of them here.
+ */
+int OutFDstack[20];
+int *OutFDsp;
+
+/* macros to switch to a new output, then restore the old */
+#define PushOut(fd) (*OutFDsp++ = OutFD, OutFD = (fd))
+#define PopOut() (OutFD = *--OutFDsp)
+
+/*
+ * The following magic variables are used by ShowContext to control the info
+ * being inserted into the CircBuf.
+ */
+int OutTally; /* total characters recently printed */
+int OutSC_max; /* max needed by ShowContext */
+
+/*
+ * UpdateTerminal makes sure that all output is visible by the user.
+ * In this case all we need to do is fflush(stdout).
+ */
+#define UpdateTerminal() ((void) fflush(stdout))
diff --git a/dviware/umddvi/h/num.h b/dviware/umddvi/h/num.h
new file mode 100644
index 0000000000..823bb3f5b5
--- /dev/null
+++ b/dviware/umddvi/h/num.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 1987 University of Maryland Department of Computer Science.
+ * All rights reserved. Permission to copy for any purpose is hereby granted
+ * so long as this copyright notice remains intact.
+ */
+
+/*
+ * Pointer I/O: numbers.
+ *
+ * We deal in fixed format numbers and pointers here.
+ * For file I/O, see fio.h.
+ */
+
+/*
+ * Get one unsigned byte. Note that this is a proper expression.
+ * The rest have more limited contexts, and are therefore OddLy
+ * CapItaliseD.
+ */
+#define pgetbyte(p) UnSign8(*(p)++)
+
+/*
+ * Get a two-byte unsigned integer, a three-byte unsigned integer,
+ * or a four-byte signed integer.
+ */
+#define pGetWord(p, r) ((r) = UnSign8(*(p)++) << 8, \
+ (r) |= UnSign8(*(p)++))
+#define pGet3Byte(p,r) ((r) = UnSign8(*(p)++) << 16, \
+ (r) |= UnSign8(*(p)++) << 8, \
+ (r) |= UnSign8(*(p)++))
+#define pGetLong(p, r) ((r) = UnSign8(*(p)++) << 24, \
+ (r) |= UnSign8(*(p)++) << 16, \
+ (r) |= UnSign8(*(p)++) << 8, \
+ (r) |= UnSign8(*(p)++))
+
+/*
+ * ADD pputbyte, pPutWord, pPut3Byte, pPutLong HERE IF THEY PROVE
+ * USEFUL. (But then must consider changing PutWord &c in fio.h.)
+ */
diff --git a/dviware/umddvi/h/postamble.h b/dviware/umddvi/h/postamble.h
new file mode 100644
index 0000000000..68f4df8ac2
--- /dev/null
+++ b/dviware/umddvi/h/postamble.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 1987 University of Maryland Department of Computer Science.
+ * All rights reserved. Permission to copy for any purpose is hereby granted
+ * so long as this copyright notice remains intact.
+ */
+
+/* Definitions for ScanPostAmble */
+
+/*
+ * ScanPostAmble reads the postamble of a DVI file from the (stdio)
+ * file specified in its first argument. It is handed two pointers to
+ * functions. The first (ScanPostAmble's second argument) is called
+ * after the header information has been read, and given a pointer to a
+ * PostAmbleInfo structure. It is the job of this function to extract the
+ * required information from this structure (which is deallocated when
+ * ScanPostAmble returns).
+ *
+ * The second function is called once for each font definition occurring in
+ * the postamble, and is given a pointer to a PostAmbleFont structure. This
+ * function should do whatever the device needs to read the actual font.
+ *
+ * If the DVI file appears malformed, ScanPostAmble will print an error
+ * message and exit. (Drastic, perhaps, but effective.)
+ */
+
+struct PostAmbleInfo {
+ i32 pai_PrevPagePointer; /* previous page pointer */
+ i32 pai_Numerator; /* numerator from dvi file */
+ i32 pai_Denominator; /* denominator from dvi file*/
+ i32 pai_DVIMag; /* \magnification */
+ i32 pai_TallestPageHeight; /* height of tallest page */
+ i32 pai_WidestPageWidth; /* width of widest page */
+ int pai_DVIStackSize; /* DVI stack size required */
+ int pai_NumberOfPages; /* total number of pages in DVI file */
+};
+
+struct PostAmbleFont {
+ char *paf_name; /* name of font (null terminated) */
+ int paf_n1; /* length of first part of name */
+ int paf_n2; /* length of second part of name */
+ i32 paf_DVIFontIndex; /* font index number */
+ i32 paf_DVIChecksum; /* checksum from DVI file */
+ i32 paf_DVIMag; /* "at size" */
+ i32 paf_DVIDesignSize; /* design size of font */
+};
diff --git a/dviware/umddvi/h/readme b/dviware/umddvi/h/readme
new file mode 100644
index 0000000000..402aff89d5
--- /dev/null
+++ b/dviware/umddvi/h/readme
@@ -0,0 +1 @@
+This directory is for header files.
diff --git a/dviware/umddvi/h/search.h b/dviware/umddvi/h/search.h
new file mode 100644
index 0000000000..1ba492d414
--- /dev/null
+++ b/dviware/umddvi/h/search.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 1987 University of Maryland Department of Computer Science.
+ * All rights reserved. Permission to copy for any purpose is hereby granted
+ * so long as this copyright notice remains intact.
+ */
+
+/* search structures and routines for 32-bit key, arbitrary data */
+
+struct search {
+ unsigned s_dsize; /* data object size (includes key size) */
+ unsigned s_space; /* space left (in terms of objects) */
+ unsigned s_n; /* number of objects in the table */
+ char *s_data; /* data area */
+};
+
+/* returns a pointer to the search table (for future search/installs) */
+struct search *SCreate(); /* create a search table */
+
+/* returns a pointer to the data object found or created */
+char *SSearch(); /* search for a data object */
+
+/* the third argument to SSearch controls operation as follows: */
+#define S_LOOKUP 0x00 /* pseudo flag */
+#define S_CREATE 0x01 /* create object if not found */
+#define S_EXCL 0x02 /* complain if already exists */
+
+/* in addition, it is modified before return to hold status: */
+#define S_COLL 0x04 /* collision (occurs iff S_EXCL set) */
+#define S_FOUND 0x08 /* found (occurs iff existed already) */
+#define S_NEW 0x10 /* created (occurs iff S_CREATE && !S_EXCL) */
+#define S_ERROR 0x20 /* problem creating (out of memory) */
diff --git a/dviware/umddvi/h/str.h b/dviware/umddvi/h/str.h
new file mode 100644
index 0000000000..8f5dabdfbe
--- /dev/null
+++ b/dviware/umddvi/h/str.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 1987 University of Maryland Department of Computer Science.
+ * All rights reserved. Permission to copy for any purpose is hereby granted
+ * so long as this copyright notice remains intact.
+ */
+
+/*
+ * Internal strings have both a length and a string area, so that they may
+ * contain nulls.
+ */
+typedef struct string {
+ int s_len;
+ char *s_str;
+} String;
+
+#define s_eq(s1,s2) ((s1)->s_len == (s2)->s_len && _s_eq(s1, s2))
+
+/*
+ * Strings are created by appending characters to the current "string pool".
+ * Once a string has been completed, it is fixed in place and cannot be
+ * changed. Until the string is complete, characters may be added to, and
+ * removed from, the end.
+ */
+#define PoolExpandSize 1024 /* bytes per ExpandPool */
+
+String PoolString; /* the current string */
+char *PoolPtr; /* the current position in the pool */
+int PoolLen; /* amount of space left in the pool */
+
+#define s_addc(c) (--PoolLen >= 0 ? *PoolPtr++ = (c), PoolString.s_len++ \
+ : ExpandPool(c))
+#define s_delc() (PoolLen++, PoolPtr--, PoolString.s_len--)
+#define s_kill() (PoolLen += PoolString.s_len, \
+ PoolPtr -= PoolString.s_len, PoolString.s_len = 0)
diff --git a/dviware/umddvi/h/tfm.h b/dviware/umddvi/h/tfm.h
new file mode 100644
index 0000000000..95ed6eb41c
--- /dev/null
+++ b/dviware/umddvi/h/tfm.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 1987 University of Maryland Department of Computer Science.
+ * All rights reserved. Permission to copy for any purpose is hereby granted
+ * so long as this copyright notice remains intact.
+ */
+
+/*
+ * TFM file information.
+ */
+
+/*
+ * TFM files start with a series of unsigned 16 bit integers. We
+ * read this into the structure `tfm_header'. These are type i32
+ * so that they may be used as integer quantities without concern
+ * as to sign extension.
+ */
+struct tfmheader {
+ i32 th_lf; /* length of the file (16 bit words) */
+ i32 th_lh; /* length of the header data (words) */
+ i32 th_bc; /* beginning character */
+ i32 th_ec; /* ending character (inclusive) */
+ i32 th_nw; /* number of words in width table */
+ i32 th_nh; /* number of words in height table */
+ i32 th_nd; /* number of words in depth table */
+ i32 th_ni; /* words in italic correction table */
+ i32 th_nl; /* words in ligature/kern table */
+ i32 th_nk; /* words in kern table */
+ i32 th_ne; /* words in extensible character table */
+ i32 th_np; /* number of font parameter words */
+};
+
+/*
+ * The remainder of the TFM file comprises the following information,
+ * all of which are 32 bit quantities:
+ *
+ * header: array [0..lh-1] of stuff
+ * char_info: array [bc..ec] of char_info_word
+ * width: array [0..nw-1] of fix_word
+ * height: array [0..nh-1] of fix_word
+ * depth: array [0..nd-1] of fix_word
+ * italic: array [0..ni-1] of fix_word
+ * lig_kern: array [0..nl-1] of lig_kern_command
+ * kern: array [0..ne-1] of extensible_recipie
+ * param: array [0..np-1] of fix_word
+ */
+
+/*
+ * A char_info_word is built of four unsigned eight-bit quantities. The first
+ * is an index into the width table (this saves 24 bits for every
+ * character that has the same width as another character). The
+ * second is a composite height and depth index. The third is a
+ * composite italic index and tag, and the fourth is a remainder.
+ *
+ * XXX needs explaining
+ */
+struct char_info_word {
+ char ci_width; /* width index */
+ char ci_h_d; /* height and depth index */
+ char ci_i_t; /* italic index and tag */
+ char ci_remainder; /* ??? */
+};
+
+/*
+ * These macros split up h_and_d and i_and_t values.
+ */
+#define T_CI_H(ci) (((ci)->ci_h_d >> 4) & 0xf)
+#define T_CI_D(ci) ((ci)->ci_h_d & 0xf)
+#define T_CI_I(ci) (((ci)->ci_i_t >> 2) & 0x3f)
+#define T_CI_T(ci) ((ci)->ci_i_t & 3)
+
+/*
+ * This structure contains everything one might need to know about
+ * a TFM file at run-time.
+ *
+ * XXX incomplete, or wrong, as yet
+ */
+struct tfmdata {
+ struct tfmheader t_hdr; /* full header */
+ struct char_info_word *t_ci; /* char info */
+ i32 *t_width; /* widths table */
+ i32 *t_height; /* heights */
+ i32 *t_depth; /* depths */
+};
diff --git a/dviware/umddvi/h/types.h b/dviware/umddvi/h/types.h
new file mode 100644
index 0000000000..bd34bc49e0
--- /dev/null
+++ b/dviware/umddvi/h/types.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 1987 University of Maryland Department of Computer Science.
+ * All rights reserved. Permission to copy for any purpose is hereby granted
+ * so long as this copyright notice remains intact.
+ */
+
+/*
+ * C-TeX types (system dependent).
+ */
+
+#ifndef _CTEX_TYPES_
+#define _CTEX_TYPES_
+
+/* a 16 bit integer (signed) */
+typedef short i16;
+
+/* a 32 bit integer (signed) */
+typedef long i32;
+
+/* macros to sign extend quantities that are less than 32 bits long */
+#if defined(u3b) || defined(u3b2) || defined(u3b5)
+#define Sign8(n) ((n) & (1 << 7) ? ((n) | 0xffffff00) : (n))
+#define Sign16(n) ((i32) (short) (n))
+#define Sign24(n) ((n) & (1 << 23) ? ((n) | 0xff000000) : (n))
+#else
+#ifdef sun
+/* Sun mishandles (int)(char)(constant), but this subterfuge works: */
+#define Sign8(n) ((i32) (char) (int) (n))
+#else
+#define Sign8(n) ((i32) (char) (n))
+#endif /* sun */
+#define Sign16(n) ((i32) (short) (n))
+#define Sign24(n) (((n) << 8) >> 8)
+#endif /* u3b || u3b2 || u3b5 */
+
+/* macros to truncate quantites that are signed but shouldn't be */
+#define UnSign8(n) ((n) & 0xff)
+#define UnSign16(n) ((n) & 0xffff)
+#define UnSign24(n) ((n) & 0xffffff)
+
+/* note that we never have unsigned 32 bit integers */
+
+#endif /* _CTEX_TYPES_ */
diff --git a/dviware/umddvi/h/verser.h b/dviware/umddvi/h/verser.h
new file mode 100644
index 0000000000..a7d0f43594
--- /dev/null
+++ b/dviware/umddvi/h/verser.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 1987 University of Maryland Department of Computer Science.
+ * All rights reserved. Permission to copy for any purpose is hereby granted
+ * so long as this copyright notice remains intact.
+ */
+
+/* verser globals */
+
+/*
+ * Verser was rewritten based on another program by the same name.
+ * The original program was written by Janet Incerpi of Brown University
+ * and was for the original version of TeX which also used a different kind
+ * of font file. It was modified at the University of Washington by
+ * Richard Furuta (bringing it up to TeX82 and PXL files) and Carl Binding
+ * (adding horizontal printing). I then tore it to shreds and rebuilt
+ * it; the new one is much faster (though less portable: it has inline
+ * assembly code in various critical routines).
+ *
+ * Chris Torek, 20 May 1984, University of Maryland CS/EE
+ *
+ * The program has since gone through much revision. The details are
+ * rather boring, but there is one important point: The intermediate
+ * file format has changed.
+ */
+
+/*
+ * Version number. Increment this iff the intermediate file format
+ * makes an incompatible change. This number may not be > 127.
+ */
+#define VERSION 1 /* was version 0 */
+
+#ifndef ACCOUNT_FILE
+/*
+#define ACCOUNT_FILE "/usr/adm/vpacct" /* if defined, the name of
+ the paper accounting file */
+#endif ACCOUNT_FILE
+
+#ifndef VERSATEC_FILE
+#define VERSATEC_FILE "/dev/vp0"/* the name of the Versatec */
+#endif VERSATEC_FILE
+
+#define NFONTS 100 /* max number of fonts */
+
+#define FONTSHIFT 14 /* font shift in fcp's */
+#define CHARSHIFT 7 /* char shift in fcp's */
+#define CHARMASK 127 /* char mask in fcp's - 128 chars/font */
+#define PARTMASK 127 /* part mask in fcp's */
+
+#define ROWS 400 /* lines in buffer (200 lines/inch) */
+#define COLUMNS 264 /* 2112 bits per line / 8 bits per char */
+#define MIN_OUT 30 /* MIN_OUT lines in buffer causes output
+ to be written right away */
+#define MaxCharHeight (ROWS-1) /* max bit height of a single char or rule */
+#define MaxPageHeight 1685 /* max bit height of a page */
+#define MaxPageWidth 2112 /* max bit width of a page */
+#define FFMargin 39 /* vert. offset after a formfeed (bits) */
+
+#define DefaultMaxDrift 2
+
+#define DefaultLeftMargin 150
+#define MinimumLeftMargin 10
+#define DefaultTopMargin 200
+#define MinimumTopMargin 10
+#define DefaultBottomMargin 200
+
+#ifndef min
+#define min(a,b) ((a) < (b) ? (a) : (b))
+#endif min
diff --git a/dviware/umddvi/installation b/dviware/umddvi/installation
new file mode 100644
index 0000000000..cf0b6d1e93
--- /dev/null
+++ b/dviware/umddvi/installation
@@ -0,0 +1 @@
+This should point people towards doc/doc.tex, or doc/install.tex
diff --git a/dviware/umddvi/lib/bcopy.s b/dviware/umddvi/lib/bcopy.s
new file mode 100644
index 0000000000..1577615969
--- /dev/null
+++ b/dviware/umddvi/lib/bcopy.s
@@ -0,0 +1,29 @@
+#
+# Copyright (c) 1987 University of Maryland Department of Computer Science.
+# All rights reserved. Permission to copy for any purpose is hereby granted
+# so long as this copyright notice remains intact.
+#
+
+rcsid: .asciz "$Header: bcopy.s,v 1.2 87/06/16 18:27:33 chris Exp $"
+
+# bcopy (from, to, count) char *from, *to; int count;
+#
+# Copy "count" bytes from "from" to "to"; not guaranteed to
+# work if "from" and "to" overlap.
+
+ .align 2
+ .globl _bcopy
+_bcopy:
+ .word 0
+ movl 4(ap),r1 # r1 = from
+ movl 8(ap),r3 # r3 = to
+ brb 2f
+1:
+ subl2 r0,12(ap) # count-=65535 (bytes moved this time)
+ movc3 r0,(r1),(r3) # r1, r3 magically point to next 65K
+2:
+ movzwl $65535,r0
+ cmpl 12(ap),r0 # <= 65535 bytes to move?
+ jgtr 1b # brif not, move 65535 and try again
+ movc3 12(ap),(r1),(r3) # move up to 65535 bytes
+ ret
diff --git a/dviware/umddvi/lib/bzero.s b/dviware/umddvi/lib/bzero.s
new file mode 100644
index 0000000000..4c4e69fc68
--- /dev/null
+++ b/dviware/umddvi/lib/bzero.s
@@ -0,0 +1,27 @@
+#
+# Copyright (c) 1987 University of Maryland Department of Computer Science.
+# All rights reserved. Permission to copy for any purpose is hereby granted
+# so long as this copyright notice remains intact.
+#
+
+rcsid: .asciz "$Header: bzero.s,v 1.2 87/06/16 18:27:36 chris Exp $"
+
+# bzero (addr, count) char *addr; int count;
+#
+# Zero "count" bytes at address "addr"
+
+ .align 2
+ .globl _bzero
+_bzero:
+ .word 0
+ movl 4(ap),r3 # r3 = addr
+ brb 2f
+1:
+ subl2 r0,8(ap) # count-=65535 (bytes zeroed this time)
+ movc5 $0,(sp),$0,r0,(r3) # r3 magically points to next 65K
+2:
+ movzwl $65535,r0
+ cmpl 8(ap),r0 # <= 65535 bytes to zero?
+ jgtr 1b # brif not, zero 65535 and try again
+ movc5 $0,(sp),$0,8(ap),(r3) # zero up to 65535 bytes
+ ret
diff --git a/dviware/umddvi/lib/conv.c b/dviware/umddvi/lib/conv.c
new file mode 100644
index 0000000000..91f2088cda
--- /dev/null
+++ b/dviware/umddvi/lib/conv.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 1987 University of Maryland Department of Computer Science.
+ * All rights reserved. Permission to copy for any purpose is hereby granted
+ * so long as this copyright notice remains intact.
+ */
+
+#ifndef lint
+static char rcsid[] = "$Header: conv.c,v 1.3 87/06/16 18:27:39 chris Exp $";
+#endif
+
+/*
+ * Conversions.
+ */
+
+#include "types.h"
+#include "conv.h"
+
+double DMagFactor();
+
+/*
+ * Set a conversion (possibly the global conversion).
+ */
+void
+CSetConversion(c, dpi, usermag, num, denom, dvimag)
+ register struct conversion *c;
+ int dpi, usermag;
+ i32 num, denom, dvimag;
+{
+ double ddpi = dpi;
+
+ c->c_mag = DMagFactor((int) dvimag) * DMagFactor(usermag);
+ c->c_dpi = ddpi;
+
+ /*
+ * The conversion facture is figured as follows: there are exactly
+ * num/denom DVI units per decimicron, and 254000 decimicrons per
+ * inch, and dpi pixels per inch. Then we have to adjust this by
+ * the stated magnification.
+ */
+ c->c_fromsp = (num / 254000.0) * (ddpi / denom) * c->c_mag;
+
+ /*
+ * c->c_tosp is 1/c->c_fromsp, but we will invert the expression
+ * above in the hopes of some extra accuracy.
+ *
+ * IS THIS ANY GOOD? I NEED A NUMERICAL ANALYST!
+ */
+ c->c_tosp = (254000.0 / num) * (denom / ddpi) * (1.0 / c->c_mag);
+}
diff --git a/dviware/umddvi/lib/dviclass.c b/dviware/umddvi/lib/dviclass.c
new file mode 100644
index 0000000000..f409f994a0
--- /dev/null
+++ b/dviware/umddvi/lib/dviclass.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 1987 University of Maryland Department of Computer Science.
+ * All rights reserved. Permission to copy for any purpose is hereby granted
+ * so long as this copyright notice remains intact.
+ */
+
+#ifndef lint
+static char rcsid[] = "$Header: dviclass.c,v 2.3 87/06/16 18:27:42 chris Exp $";
+#endif
+
+/*
+ * dviclass - DVI code classification tables.
+ */
+
+#include "dviclass.h"
+
+/* shorthand---in lowercase for contrast (read on!) */
+#define four(x) x, x, x, x
+#define six(x) four(x), x, x
+#define sixteen(x) four(x), four(x), four(x), four(x)
+#define sixty_four(x) sixteen(x), sixteen(x), sixteen(x), sixteen(x)
+#define one_twenty_eight(x) sixty_four(x), sixty_four(x)
+
+/*
+ * This table contains the byte length of the single operand, or DPL_NONE
+ * if no operand, or if it cannot be decoded this way.
+ *
+ * The sequences UNS1, UNS2, UNS3, SGN4 (`SEQ_U') and SGN1, SGN2, SGN3,
+ * SGN4 (`SEQ_S') are rather common, and so we define macros for these.
+ */
+#define SEQ_U DPL_UNS1, DPL_UNS2, DPL_UNS3, DPL_SGN4
+#define SEQ_S DPL_SGN1, DPL_SGN2, DPL_SGN3, DPL_SGN4
+
+char dvi_oplen[256] = {
+ one_twenty_eight(DPL_NONE),
+ /* characters 0 through 127 */
+ SEQ_U, /* DVI_SET1 through DVI_SET4 */
+ DPL_NONE, /* DVI_SETRULE */
+ SEQ_U, /* DVI_PUT1 through DVI_PUT4 */
+ DPL_NONE, /* DVI_PUTRULE */
+ DPL_NONE, /* DVI_NOP */
+ DPL_NONE, /* DVI_BOP */
+ DPL_NONE, /* DVI_EOP */
+ DPL_NONE, /* DVI_PUSH */
+ DPL_NONE, /* DVI_POP */
+ SEQ_S, /* DVI_RIGHT1 through DVI_RIGHT4 */
+ DPL_NONE, /* DVI_W0 */
+ SEQ_S, /* DVI_W1 through DVI_W4 */
+ DPL_NONE, /* DVI_X0 */
+ SEQ_S, /* DVI_X1 through DVI_X4 */
+ SEQ_S, /* DVI_DOWN1 through DVI_DOWN4 */
+ DPL_NONE, /* DVI_Y0 */
+ SEQ_S, /* DVI_Y1 through DVI_Y4 */
+ DPL_NONE, /* DVI_Z0 */
+ SEQ_S, /* DVI_Z1 through DVI_Z4 */
+ sixty_four(DPL_NONE), /* DVI_FNTNUM0 through DVI_FNTNUM63 */
+ SEQ_U, /* DVI_FNT1 through DVI_FNT4 */
+ SEQ_U, /* DVI_XXX1 through DVI_XXX4 */
+ SEQ_U, /* DVI_FNTDEF1 through DVI_FNTDEF4 */
+ DPL_NONE, /* DVI_PRE */
+ DPL_NONE, /* DVI_POST */
+ DPL_NONE, /* DVI_POSTPOST */
+ six(DPL_NONE) /* 250 through 255 */
+};
+
+char dvi_dt[256] = {
+ one_twenty_eight(DT_CHAR),
+ /* characters 0 through 127 */
+ four(DT_SET), /* DVI_SET1 through DVI_SET4 */
+ DT_SETRULE, /* DVI_SETRULE */
+ four(DT_PUT), /* DVI_PUT1 through DVI_PUT4 */
+ DT_PUTRULE, /* DVI_PUTRULE */
+ DT_NOP, /* DVI_NOP */
+ DT_BOP, /* DVI_BOP */
+ DT_EOP, /* DVI_EOP */
+ DT_PUSH, /* DVI_PUSH */
+ DT_POP, /* DVI_POP */
+ four(DT_RIGHT), /* DVI_RIGHT1 through DVI_RIGHT4 */
+ DT_W0, /* DVI_W0 */
+ four(DT_W), /* DVI_W1 through DVI_W4 */
+ DT_X0, /* DVI_X0 */
+ four(DT_X), /* DVI_X1 through DVI_X4 */
+ four(DT_DOWN), /* DVI_DOWN1 through DVI_DOWN4 */
+ DT_Y0, /* DVI_Y0 */
+ four(DT_Y), /* DVI_Y1 through DVI_Y4 */
+ DT_Z0, /* DVI_Z0 */
+ four(DT_Z), /* DVI_Z1 through DVI_Z4 */
+ sixty_four(DT_FNTNUM), /* DVI_FNTNUM0 through DVI_FNTNUM63 */
+ four(DT_FNT), /* DVI_FNT1 through DVI_FNT4 */
+ four(DT_XXX), /* DVI_XXX1 through DVI_XXX4 */
+ four(DT_FNTDEF), /* DVI_FNTDEF1 through DVI_FNTDEF4 */
+ DT_PRE, /* DVI_PRE */
+ DT_POST, /* DVI_POST */
+ DT_POSTPOST, /* DVI_POSTPOST */
+ six(DT_UNDEF) /* 250 through 255 */
+};
diff --git a/dviware/umddvi/lib/error.c b/dviware/umddvi/lib/error.c
new file mode 100644
index 0000000000..e8e4d342d6
--- /dev/null
+++ b/dviware/umddvi/lib/error.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 1987 University of Maryland Department of Computer Science.
+ * All rights reserved. Permission to copy for any purpose is hereby granted
+ * so long as this copyright notice remains intact.
+ */
+
+#ifndef lint
+static char rcsid[] = "$Header: error.c,v 2.7 87/06/16 18:27:46 chris Exp $";
+#endif
+
+/*
+ * Print an error message with an optional system error number, and
+ * optionally quit.
+ *
+ * THIS CODE IS SYSTEM DEPENDENT UNLESS varargs WORKS WITH vprintf
+ * OR _doprnt. It should work properly under System V using vprintf.
+ * (If you have vprintf, define HAVE_VPRINTF.)
+ */
+
+#include <stdio.h>
+#include <varargs.h>
+
+#ifdef lint
+
+/* VARARGS3 ARGSUSED */
+error(quit, e, fmt) int quit, e; char *fmt; {;}
+
+/* VARARGS1 ARGSUSED */
+panic(fmt) char *fmt; { exit(1); /* NOTREACHED */ }
+
+#else lint
+
+extern char *ProgName;
+extern int errno;
+extern char *sys_errlist[];
+extern int sys_nerr;
+
+error(va_alist)
+ va_dcl
+{
+ va_list l;
+ int quit, e;
+ char *fmt;
+
+ (void) fflush(stdout); /* sync error messages */
+ (void) fprintf(stderr, "%s: ", ProgName);
+ va_start(l);
+ /* pick up the constant arguments: quit, errno, printf format */
+ quit = va_arg(l, int);
+ e = va_arg(l, int);
+ if (e < 0)
+ e = errno;
+ fmt = va_arg(l, char *);
+#if defined(sys5) || defined(HAVE_VPRINTF)
+ (void) vfprintf(stderr, fmt, l);
+#else
+ _doprnt(fmt, l, stderr);
+#endif
+ va_end(l);
+ if (e) {
+ if (e < sys_nerr)
+ (void) fprintf(stderr, ": %s", sys_errlist[e]);
+ else
+ (void) fprintf(stderr, ": Unknown error code %d", e);
+ }
+ (void) putc('\n', stderr);
+ (void) fflush(stderr); /* just in case */
+ if (quit)
+ exit(quit);
+}
+
+panic(va_alist)
+ va_dcl
+{
+ va_list l;
+ char *fmt;
+
+ (void) fflush(stdout);
+ (void) fprintf(stderr, "%s: panic: ", ProgName);
+ va_start(l);
+ /* pick up the constant argument: printf format */
+ fmt = va_arg(l, char *);
+#if defined(sys5) || defined(HAVE_VPRINTF)
+ (void) vfprintf(stderr, fmt, l);
+#else
+ _doprnt(fmt, l, stderr);
+#endif
+ va_end(l);
+ (void) putc('\n', stderr);
+ (void) fflush(stderr);
+ abort();
+}
+
+#endif /* lint */
diff --git a/dviware/umddvi/lib/findpost.c b/dviware/umddvi/lib/findpost.c
new file mode 100644
index 0000000000..33d6aca0ad
--- /dev/null
+++ b/dviware/umddvi/lib/findpost.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 1987 University of Maryland Department of Computer Science.
+ * All rights reserved. Permission to copy for any purpose is hereby granted
+ * so long as this copyright notice remains intact.
+ */
+
+#ifndef lint
+static char rcsid[] = "$Header: findpost.c,v 2.2 87/06/16 18:27:50 chris Exp $";
+#endif
+
+/*
+ * FindPostAmble - Find the postamble of a DVI file.
+ *
+ * N.B.: This routine assumes that ftell() returns byte offsets,
+ * not magic cookies.
+ */
+
+#include <stdio.h>
+#include "types.h"
+#include "dvicodes.h"
+#include "fio.h"
+
+/*
+ * I am making the assumption that 530 bytes will always be enough
+ * to find the end of the DVI file. 12 should suffice, as there
+ * should be at most seven DVI_FILLER bytes, preceded by the version
+ * number, preceded by the four byte postamble pointer; but at least
+ * one VMS TeX must pad to a full `sector'.
+ */
+#ifdef vms
+#define POSTSIZE 530 /* make only VMS pay for its errors; */
+#else
+#define POSTSIZE 16 /* others get to use something reasonable */
+#endif
+
+long ftell();
+
+FindPostAmble(f)
+ register FILE *f;
+{
+ register long offset;
+ register char *p;
+ register int i;
+ register i32 n;
+ char postbuf[POSTSIZE];
+
+ /*
+ * Avoid fseek'ing beyond beginning of file; it may
+ * give odd results.
+ */
+ fseek(f, 0L, 2); /* seek to end */
+ offset = ftell(f) - POSTSIZE; /* and compute where to go next */
+ if (offset < 0L) /* but make sure it is positive */
+ offset = 0L;
+ fseek(f, offset, 0);
+ p = postbuf;
+ for (i = 0; i < POSTSIZE; i++) {
+ *p++ = getc(f);
+ if (feof(f)) {
+ p--;
+ break;
+ }
+ }
+
+ /*
+ * Now search backwards for the VERSION byte. The postamble
+ * pointer will be four bytes behind that.
+ */
+ while (--i >= 0) {
+ if (UnSign8(*--p) == DVI_VERSION)
+ goto foundit;
+ if (UnSign8(*p) != DVI_FILLER)
+ break;
+ }
+ return (-1); /* cannot find postamble ptr */
+
+foundit:
+ /*
+ * Change offset from the position at the beginning of postbuf
+ * to the position of the VERSION byte, and seek to four bytes
+ * before that. Then get a long and use its value to seek to
+ * the postamble itself.
+ */
+ offset += p - postbuf;
+ fseek(f, offset - 4L, 0);
+ fGetLong(f, n);
+ offset = n;
+ fseek(f, offset, 0);
+ return (0); /* success */
+}
diff --git a/dviware/umddvi/lib/fio.c b/dviware/umddvi/lib/fio.c
new file mode 100644
index 0000000000..6d216ac887
--- /dev/null
+++ b/dviware/umddvi/lib/fio.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 1987 University of Maryland Department of Computer Science.
+ * All rights reserved. Permission to copy for any purpose is hereby granted
+ * so long as this copyright notice remains intact.
+ */
+
+#ifndef lint
+static char rcsid[] = "$Header: fio.c,v 2.3 87/06/16 18:27:54 chris Exp $";
+#endif
+
+/*
+ * File I/O subroutines for getting bytes, words, 3bytes, and longwords.
+ */
+
+#include <stdio.h>
+#include "types.h"
+#include "fio.h"
+
+static char eofmsg[] = "unexpected EOF";
+
+/* for symmetry: */
+#define fGetByte(fp, r) ((r) = getc(fp))
+#define Sign32(i) (i)
+
+#define make(name, func, signextend) \
+i32 \
+name(fp) \
+ register FILE *fp; \
+{ \
+ register i32 n; \
+ \
+ func(fp, n); \
+ if (feof(fp)) \
+ error(1, 0, eofmsg); \
+ return (signextend(n)); \
+}
+
+make(GetByte, fGetByte, Sign8)
+make(GetWord, fGetWord, Sign16)
+make(Get3Byte, fGet3Byte, Sign24)
+make(GetLong, fGetLong, Sign32)
diff --git a/dviware/umddvi/lib/font.c b/dviware/umddvi/lib/font.c
new file mode 100644
index 0000000000..3b1e69bc8a
--- /dev/null
+++ b/dviware/umddvi/lib/font.c
@@ -0,0 +1,417 @@
+/*
+ * Copyright (c) 1987 University of Maryland Department of Computer Science.
+ * All rights reserved. Permission to copy for any purpose is hereby granted
+ * so long as this copyright notice remains intact.
+ */
+
+#ifndef lint
+static char rcsid[] = "$Header: font.c,v 2.6 87/06/16 18:27:56 chris Exp $";
+#endif
+
+/*
+ * Routines for working with fonts. In particular, the configuration
+ * dependent code is here.
+ *
+ * Specific fonts (GF, PXL, etc.) have functions in separate files.
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include "types.h"
+#include "conv.h"
+#include "font.h"
+
+/*
+ * Define the default configuration file.
+ * Also define the maximum path name length.
+ */
+#ifndef CONFFILE
+#define CONFFILE "/usr/local/lib/tex/fontdesc"
+#endif
+
+#define PATHLEN 1024
+
+/*
+ * A font configuration. The font list is ordered.
+ *
+ * A specifier is typically a particular print engine, since
+ * different engines need slightly different fonts.
+ */
+struct fontconf {
+ struct fontconf *fc_next;
+ struct fontops *fc_ops;
+ char *fc_path; /* path, with metacharacters */
+ char *fc_spec; /* specifier */
+ int fc_slop; /* slop value */
+};
+
+/*
+ * EQ is a fast way to check for string equivalence.
+ */
+#define EQ(a, b) (*(a) == *(b) && strcmp(a, b) == 0)
+
+/*
+ * Private variables.
+ */
+static int didinit; /* true => initialised already */
+static char *cfname; /* config file name, for errors */
+static int cfline; /* config file line, likewise */
+static struct fontops *fontops;/* font operations code: list head */
+static struct fontconf *fonts; /* font list */
+static struct fontconf **nextfc;/* used during initialisation */
+static char spec_any[] = "*"; /* the `anything' specifier */
+
+/*
+ * Imports.
+ */
+extern int errno;
+char *getenv(), *malloc(), *strsave();
+#ifndef sys5
+char *sprintf();
+#endif
+
+/*
+ * Here, alas, we know about all the kinds of fonts.
+ * This also means that every DVI interpreter pulls in
+ * the full set of font manipulation routines.
+ *
+ * PERHAPS THIS SHOULD BE CONFIGURABLE.
+ */
+#define ADDFONT(x) { \
+ extern struct fontops x; \
+ x.fo_next = fontops; \
+ fontops = &x; \
+}
+
+fontinit(file)
+ char *file;
+{
+
+ if (didinit) {
+ /*
+ * Could free the old configuration and fire up
+ * a new one, but for now . . .
+ */
+ error(1, 0, "attempt to reinit fonts");
+ /* NOTREACHED */
+ }
+ didinit++;
+ ADDFONT(boxops);
+ ADDFONT(blankops);
+ ADDFONT(invisops);
+ ADDFONT(pxlops);
+ ADDFONT(pkops);
+ ADDFONT(gfops);
+ nextfc = &fonts;
+ if (file == NULL)
+ if ((file = getenv(CONFENV)) == NULL)
+ file = CONFFILE;
+ readconf(file);
+}
+
+/*
+ * A proto resembles a fontspec (indeed, it is a prototype
+ * fontspec) but is not quite the same. It is used to gather
+ * the information needed per fontspec before allocating
+ * the fontspec itself.
+ */
+struct proto {
+ char *p_type;
+ char *p_spec;
+ char *p_slop;
+ char *p_path;
+};
+
+/*
+ * Read the named configuration file. The file is split into
+ * lines, and lines are split into words; if the first word is
+ * "font", this is a fontconf, and we read the remainder of the
+ * words and make a fontconf entry.
+ */
+static
+readconf(name)
+ char *name;
+{
+ register FILE *f; /* config file */
+ register char **p; /* pointer into word vector */
+ register int c;
+ char line[1024]; /* input line */
+ char *v[100]; /* word vector */
+ struct proto proto; /* prototype fontconf */
+
+#define GETWORD(x, ifnone) \
+ if (--c <= 0) \
+ badcf(ifnone); \
+ else \
+ (x) = *p++
+
+ if ((f = fopen(name, "r")) == NULL)
+ error(1, errno, "cannot read font configuration file \"\%s\"",
+ name);
+ cfname = name;
+ cfline = 0;
+ while (fgets(line, sizeof (line), f) != NULL) {
+ cfline++;
+ if ((c = strlen(line)) > 0) {
+ if (line[--c] != '\n')
+ badcf("line too long");
+ line[c] = 0;
+ }
+ if ((c = split(line, v, sizeof (v) / sizeof (*v))) < 0)
+ badcf("too many words");
+ p = v;
+ /* skip things that are not fonts */
+ if (c == 0 || !EQ(*p, "font"))
+ continue;
+ p++;
+ GETWORD(proto.p_type, "missing font typename");
+ GETWORD(proto.p_spec, "missing font spec (engine)");
+ GETWORD(proto.p_slop, "missing slop value");
+ GETWORD(proto.p_path, "need pathname");
+ (void) setfont(&proto);
+ }
+}
+
+/*
+ * Find a font's operations, given its name.
+ */
+static struct fontops *
+findops(name)
+ register char *name;
+{
+ register struct fontops *fo;
+
+ for (fo = fontops; fo != NULL; fo = fo->fo_next)
+ if (EQ(fo->fo_name, name))
+ return (fo);
+ return (NULL);
+}
+
+/*
+ * Turn a prototype fontconf into a real one.
+ */
+static int
+setfont(p)
+ register struct proto *p;
+{
+ register struct fontconf *fc;
+ struct fontops *ops = findops(p->p_type);
+
+ if (ops == NULL) {
+ error(0, 0,
+ "\"%s\", line %d: unknown font type \"%s\" ignored",
+ cfname, cfline, p->p_type);
+ return (-1);
+ }
+ if ((fc = (struct fontconf *) malloc(sizeof (*fc))) == NULL)
+ error(1, errno,
+ "out of memory for font configuration (sorry)");
+ fc->fc_ops = ops;
+ fc->fc_next = NULL;
+ fc->fc_path = strsave(p->p_path);
+ fc->fc_spec = EQ(p->p_spec, spec_any) ? NULL : strsave(p->p_spec);
+ fc->fc_slop = atoi(p->p_slop);
+ if (fc->fc_slop < 1) /* quietly enforce proper slops */
+ fc->fc_slop = 1;
+ *nextfc = fc;
+ nextfc = &fc->fc_next;
+ return (0);
+}
+
+/*
+ * Complain about a problem in the configuration file.
+ */
+static
+badcf(why)
+ char *why;
+{
+
+ error(1, 0, "\"%s\", line %d: %s", cfname, cfline, why);
+ /* NOTREACHED */
+}
+
+/*
+ * Turn a prototype path, name, and magnification into a full
+ * path.
+ */
+static
+pave(result, proto, name, mag)
+ char *result, *proto, *name;
+ int mag;
+{
+ register int c;
+ register char *s, *d, *p;
+ char num[30];
+
+ d = result;
+ p = proto;
+ s = NULL;
+ num[0] = 0; /* will need changing for other bases */
+
+ while (p != NULL) {
+ /*
+ * If sourcing from s, take its next character, and
+ * insert it directly. Otherwise take the next path
+ * character and interpret it.
+ */
+ if (s != NULL) {
+ if ((c = *s++) == 0) {
+ s = NULL;
+ continue;
+ }
+ goto put;
+ }
+ if ((c = *p++) == 0)
+ p = NULL;
+ if (c != '%')
+ goto put;
+
+ switch (c = *p++) {
+
+ case 'f':
+ case 'n':
+ case 's':
+ s = name;
+ continue;
+
+ case 'd':
+ case 'm':
+ if (num[0] == 0)
+ (void) sprintf(num, "%d", mag);
+ s = num;
+ continue;
+
+ case 0:
+ c = '%';
+ p--;
+ /* FALLTHROUGH */
+ }
+put:
+ if (d - result >= PATHLEN)
+ error(1, 0, "font path `%s' too long (sorry)", proto);
+ *d++ = c;
+ }
+}
+
+struct font *getafont(); /* get a font and optional rasters */
+
+/*
+ * Given a font name and size, return the first font that fits, along
+ * with its name (via fname). If we cannot find such a font, we set
+ * *fname to point to a `canonical' example font name, unless there are
+ * are no fonts for the device, in which case we set *fname to NULL.
+ */
+struct font *
+GetFont(nm, dvimag, dvidsz, dev, fname)
+ char *nm;
+ i32 dvimag, dvidsz;
+ char *dev, **fname;
+{
+
+ return (getafont(nm, dvimag, dvidsz, dev, fname, 1));
+}
+
+/*
+ * Same as GetFont, but caller promises never to ask for rasters.
+ */
+struct font *
+GetRasterlessFont(nm, dvimag, dvidsz, dev, fname)
+ char *nm;
+ i32 dvimag, dvidsz;
+ char *dev, **fname;
+{
+
+ return (getafont(nm, dvimag, dvidsz, dev, fname, 0));
+}
+
+/*
+ * NEED TO THINK ABOUT gf NAMING CONVENTIONS HERE: ARE THEY LIKE pxl?
+ * WHAT ABOUT OTHERS?
+ */
+static struct font *
+getafont(nm, dvimag, dvidsz, dev, fname, wantrast)
+ char *nm;
+ i32 dvimag, dvidsz;
+ char *dev, **fname;
+ int wantrast;
+{
+ register int slop, fmag;
+ register struct font *f;
+ register struct fontconf *fc;
+ register char *path;
+ static char firstpath[PATHLEN], laterpath[PATHLEN];
+ double mag;
+ int scaled;
+
+ if (!didinit)
+ fontinit((char *) NULL);
+
+ /*
+ * The equation below means, approximately, `the font is
+ * magnified by the ratio of the actual size dvimag to the
+ * design size dvidsz, and then further scaled by the
+ * global magnification.' We multiply this by the printer's
+ * resolution in dots per inch, then use the per-font
+ * conversion factor to convert a dots-per-inch value to
+ * a font name `%m' magnification (extension).
+ */
+ mag = (double) dvimag / (double) dvidsz;
+ scaled = mag * 1000.0 + 0.5;
+ mag *= Conversion.c_mag * Conversion.c_dpi;
+
+ path = firstpath;
+ for (fc = fonts; fc != NULL; fc = fc->fc_next) {
+ if (dev != NULL && fc->fc_spec != NULL &&
+ !EQ(dev, fc->fc_spec))
+ continue;
+ fmag = mag * fc->fc_ops->fo_dpitomag + 0.5;
+ for (slop = 0; slop < fc->fc_slop; slop++) {
+ pave(path, fc->fc_path, nm, fmag + slop);
+ if (access(path, 4) == 0)
+ goto found;
+ if (slop) {
+ pave(path, fc->fc_path, nm, fmag - slop);
+ if (access(path, 4) == 0)
+ goto found;
+ }
+ path = laterpath;
+ }
+ }
+
+ /* not found */
+ if (path == firstpath) { /* never got to try any paths */
+ *fname = NULL;
+ errno = ENXIO;
+ } else {
+ *fname = firstpath;
+ errno = ENOENT;
+ }
+ return (NULL);
+
+found:
+ *fname = path;
+
+ /* allocate space for the per-font info, and read it in */
+ f = (struct font *) malloc(sizeof (struct font));
+ if (f == NULL)
+ return (NULL);
+ f->f_flags = wantrast ? FF_RASTERS : 0;
+ f->f_ops = fc->fc_ops;
+ f->f_path = strsave(path);
+ f->f_font = strsave(nm);
+ f->f_dvimag = dvimag;
+ f->f_dvidsz = dvidsz;
+ f->f_scaled = scaled;
+ f->f_checksum = 0; /* in case the font reader cannot get one */
+ errno = 0;
+ if ((*f->f_ops->fo_read)(f)) {
+ int e = errno; /* paranoid */
+
+ free(f->f_path);
+ free(f->f_font);
+ free((char *) f);
+ errno = e;
+ return (NULL);
+ }
+ return (f);
+}
diff --git a/dviware/umddvi/lib/font_subr.c b/dviware/umddvi/lib/font_subr.c
new file mode 100644
index 0000000000..3ed5677cda
--- /dev/null
+++ b/dviware/umddvi/lib/font_subr.c
@@ -0,0 +1,238 @@
+/*
+ * Copyright (c) 1987 University of Maryland Department of Computer Science.
+ * All rights reserved. Permission to copy for any purpose is hereby granted
+ * so long as this copyright notice remains intact.
+ */
+
+#ifndef lint
+static char rcsid[] = "$Header: font_subr.c,v 2.4 87/06/16 18:28:02 chris Exp $";
+#endif
+
+/*
+ * Subroutines common to all fonts.
+ */
+
+#include "font.h"
+
+static struct glyph *freeglyphs;
+
+char *malloc();
+extern errno;
+
+/*
+ * Set up the font structures to note that a font has glyphs in
+ * the half-open interval [low, high).
+ *
+ * SHOULD I ALLOW ADDITIONS TO THE RANGE VIA SUBSEQUENT CALLS TO
+ * FontHasGlyphs?
+ */
+FontHasGlyphs(f, low, high)
+ register struct font *f;
+ register int low, high;
+{
+ register struct glyph **gp;
+
+ /* record bounds */
+ f->f_lowch = low;
+ f->f_highch = high;
+
+ /*
+ * Allocate space for all the glyph pointers, and set
+ * them all to NULL.
+ */
+ if (low >= high) /* no glyphs */
+ gp = NULL;
+ else {
+ gp = (struct glyph **) malloc((unsigned) (high - low) *
+ sizeof (*gp));
+ if (gp == NULL)
+ return (-1);
+ }
+ f->f_glybase = gp;
+ f->f_gly = gp - low;
+ while (++low <= high)
+ *gp++ = NULL;
+ return (0);
+}
+
+/*
+ * AllocGlyph allocates a new glyph. ReleaseGlyph puts one onto the free
+ * list. We maintain a local list of free glyphs.
+ */
+#define ReleaseGlyph(g) \
+ ((g)->g_un.g_next = freeglyphs, freeglyphs = (g))
+
+static struct glyph *
+AllocGlyph(n)
+ int n;
+{
+ register struct glyph *g;
+ register int i;
+
+ if ((g = freeglyphs) == NULL) {
+ g = (struct glyph *) malloc((unsigned) (128 * sizeof (*g)));
+ if (g == NULL)
+ error(1, errno, "out of glyph memory");
+ g += (i = 128);
+ while (--i >= 0) {
+ g--;
+ ReleaseGlyph(g);
+ }
+ }
+ freeglyphs = g->g_un.g_next;
+ g->g_flags = 0;
+ g->g_raster = NULL;
+ g->g_index = n;
+ return (g);
+}
+
+/*
+ * Free one glyph.
+ */
+void
+FreeGlyph(f, n)
+ struct font *f;
+ register int n;
+{
+ register struct glyph *g;
+
+ if (n < f->f_lowch || n >= f->f_highch)
+ return;
+#ifdef notdef
+ (*f->f_ops->fo_freegly)(f, n, n);
+#endif
+ if ((g = f->f_gly[n]) == NULL)
+ return;
+ if (g->g_raster != NULL)
+ free(g->g_raster);
+ ReleaseGlyph(g);
+}
+
+/*
+ * Free a font.
+ */
+void
+FreeFont(f)
+ register struct font *f;
+{
+ register struct glyph *g;
+ register int i;
+
+#ifdef notdef
+ (*f->f_ops->fo_freegly)(f, f->f_lowch, f->f_highch);
+#endif
+ for (i = f->f_lowch; i < f->f_highch; i++) {
+ if ((g = f->f_gly[i]) == NULL)
+ continue;
+ if (g->g_raster != NULL)
+ free(g->g_raster);
+ ReleaseGlyph(g);
+ }
+ if (f->f_glybase != NULL)
+ free((char *) f->f_glybase);
+ (*f->f_ops->fo_freefont)(f);
+ free(f->f_path);
+ free(f->f_font);
+ free((char *) f);
+}
+
+/*
+ * Get glyph `c' in font `f'. We pull in a few adjacent glyphs here
+ * under the (perhaps naive) assumption that things will go faster
+ * that way.
+ *
+ * TODO:
+ * try different adjacency values
+ * make adjacency a font attribute? (or an op)
+ */
+#define ADJ 8 /* must be a power of 2 */
+#define GET_ADJ(c, l, h) ((h) = ADJ + ((l) = (c) & ~(ADJ - 1)))
+
+struct glyph *
+GetGlyph(f, c)
+ register struct font *f;
+ int c;
+{
+ register int i, h, l;
+
+ GET_ADJ(c, l, h);
+ if (l < f->f_lowch)
+ l = f->f_lowch;
+ if (h > f->f_highch)
+ h = f->f_highch;
+ if (l >= h)
+ return (NULL);
+ for (i = l; i < h; i++)
+ if (f->f_gly[i] == NULL)
+ f->f_gly[i] = AllocGlyph(i);
+
+ if ((*f->f_ops->fo_getgly)(f, l, h)) {
+ /*
+ * I do not know what to do about this just yet, so:
+ */
+ panic("getgly fails and I am confused ... help!");
+ }
+
+ /*
+ * Apply the appropriate scale factor to the TFM widths.
+ * This makes them come out in scaled points, instead of FIXes.
+ */
+ ScaleGlyphs(f, l, h); /* ??? */
+
+ return (f->f_gly[c]);
+}
+
+/*
+ * Get the raster for glyph g in font f at rotation r.
+ */
+char *
+GetRaster(g, f, r)
+ register struct glyph *g;
+ register struct font *f;
+ int r;
+{
+ int l, h;
+
+ /* abort if caller did not ask for rasters in advance */
+ if ((f->f_flags & FF_RASTERS) == 0)
+ panic("GetRaster(%s)", f->f_path);
+
+ /*
+ * If there is no raster, get one. Blank characters,
+ * however, never have rasters.
+ */
+ if (g->g_raster == NULL) {
+ if (!HASRASTER(g))
+ return (NULL);
+ /*
+ * THE FOLLOWING DEPENDS ON THE ADJACENCY MATCHING THAT IN
+ * GetGlyph() ABOVE.
+ */
+ GET_ADJ(g->g_index, l, h);
+ if (l < f->f_lowch)
+ l = f->f_lowch;
+ if (h > f->f_highch)
+ h = f->f_highch;
+ if ((*f->f_ops->fo_rasterise)(f, l, h))
+ error(1, 0, "rasterise fails (out of memory?)");
+ }
+ if (g->g_rotation != r)
+ SetRotation(g, r);
+ return (g->g_raster);
+}
+
+/*
+ * Return a TeX-style font name, including scale factor.
+ * SHOULD I BOTHER WITH \magstep STYLE NAMES?
+ */
+char *
+Font_TeXName(f)
+ register struct font *f;
+{
+ static char result[200];
+
+ if (f->f_scaled == 1000)
+ return (f->f_font);
+ sprintf(result, "%s scaled %d", f->f_font, f->f_scaled);
+ return (result);
+}
diff --git a/dviware/umddvi/lib/getopt.c b/dviware/umddvi/lib/getopt.c
new file mode 100644
index 0000000000..058c8950e9
--- /dev/null
+++ b/dviware/umddvi/lib/getopt.c
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 1987 University of Maryland Department of Computer Science.
+ * All rights reserved. Permission to copy for any purpose is hereby granted
+ * so long as this copyright notice remains intact.
+ */
+
+/*
+ * getopt - get option letter from argv
+ * (From Henry Spencer @ U of Toronto Zoology, slightly edited)
+ */
+
+#include <stdio.h>
+
+char *optarg; /* Global argument pointer. */
+int optind; /* Global argv index. */
+
+static char *scan; /* Private scan pointer. */
+
+extern char *index();
+
+int
+getopt(argc, argv, optstring)
+ register int argc;
+ register char **argv;
+ char *optstring;
+{
+ register int c;
+ register char *place;
+
+ optarg = NULL;
+ if (scan == NULL || *scan == 0) {
+ if (optind == 0)
+ optind++;
+ if (optind >= argc || argv[optind][0] != '-' ||
+ argv[optind][1] == 0)
+ return (EOF);
+ if (strcmp(argv[optind], "--") == 0) {
+ optind++;
+ return (EOF);
+ }
+ scan = argv[optind] + 1;
+ optind++;
+ }
+ c = *scan++;
+ place = index(optstring, c);
+
+ if (place == NULL || c == ':') {
+ fprintf(stderr, "%s: unknown option -%c\n", argv[0], c);
+ return ('?');
+ }
+ place++;
+ if (*place == ':') {
+ if (*scan != '\0') {
+ optarg = scan;
+ scan = NULL;
+ } else {
+ if (optind >= argc) {
+ fprintf(stderr,
+ "%s: missing argument after -%c\n",
+ argv[0], c);
+ return ('?');
+ }
+ optarg = argv[optind];
+ optind++;
+ }
+ }
+ return (c);
+}
diff --git a/dviware/umddvi/lib/gfclass.c b/dviware/umddvi/lib/gfclass.c
new file mode 100644
index 0000000000..535c78917c
--- /dev/null
+++ b/dviware/umddvi/lib/gfclass.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 1987 University of Maryland Department of Computer Science.
+ * All rights reserved. Permission to copy for any purpose is hereby granted
+ * so long as this copyright notice remains intact.
+ */
+
+#ifndef lint
+static char rcsid[] = "$Header: gfclass.c,v 2.2 87/06/16 18:28:10 chris Exp $";
+#endif
+
+/*
+ * gfclass - GF code classification tables.
+ */
+
+#include "gfclass.h"
+
+/* shorthand---in lowercase for contrast (read on!) */
+#define three(x) x, x, x
+#define four(x) x, x, x, x
+#define five(x) four(x), x
+#define six(x) four(x), x, x
+#define eight(x) four(x), four(x)
+#define sixteen(x) eight(x), eight(x)
+#define thirty_two(x) sixteen(x), sixteen(x)
+#define sixty_four(x) thirty_two(x), thirty_two(x)
+#define one_twenty_eight(x) sixty_four(x), sixty_four(x)
+#define one_sixty_five(x) one_twenty_eight(x), thirty_two(x), five(x)
+
+/*
+ * Length of the single (or first) operand, if any.
+ */
+char gf_oplen[256] = {
+ sixty_four(GPL_NONE), /* GF_PAINT_0 through GF_PAINT_63 */
+ GPL_UNS1, /* GF_PAINT1 */
+ GPL_UNS2, /* GF_PAINT2 */
+ GPL_UNS3, /* GF_PAINT3 */
+ GPL_NONE, /* GF_BOC */
+ GPL_NONE, /* GF_BOC1 */
+ GPL_NONE, /* GF_EOC */
+ GPL_NONE, /* GF_SKIP0 */
+ GPL_UNS1, /* GF_SKIP1 */
+ GPL_UNS2, /* GF_SKIP2 */
+ GPL_UNS3, /* GF_SKIP3 */
+ one_sixty_five(GPL_NONE),/* GF_NEW_ROW_0 through GF_NEW_ROW_164 */
+ GPL_UNS1, /* GF_XXX1 */
+ GPL_UNS2, /* GF_XXX2 */
+ GPL_UNS3, /* GF_XXX3 */
+ GPL_SGN4, /* GF_XXX4 */
+ GPL_SGN4, /* GF_YYY */
+ GPL_NONE, /* GF_NOP */
+ GPL_NONE, /* GF_CHAR_LOC */
+ GPL_NONE, /* GF_CHAR_LOC0 */
+ GPL_NONE, /* GF_PRE */
+ GPL_NONE, /* GF_POST */
+ GPL_NONE, /* GF_POSTPOST */
+ six(GPL_NONE) /* 250 through 255 */
+};
+
+/*
+ * Types of the various opcodes.
+ */
+char gf_gt[256] = {
+ sixty_four(GT_PAINT0), /* GF_PAINT_0 through GF_PAINT_63 */
+ three(GT_PAINT), /* GF_PAINT1 through GF_PAINT3 */
+ GT_BOC, /* GF_BOC */
+ GT_BOC1, /* GF_BOC1 */
+ GT_EOC, /* GF_EOC */
+ GT_SKIP0, /* GF_SKIP0 */
+ three(GT_SKIP), /* GF_SKIP1 through GF_SKIP3 */
+ one_sixty_five(GT_NEW_ROW),/* GF_NEW_ROW_0 throgh GF_NEW_ROW_164 */
+ four(GT_XXX), /* GF_XXX1 through GF_XXX4 */
+ GT_YYY, /* GF_YYY */
+ GT_NOP, /* GF_NOP */
+ GT_CHAR_LOC, /* GF_CHAR_LOC */
+ GT_CHAR_LOC0, /* GF_CHAR_LOC0 */
+ GT_PRE, /* GF_PRE */
+ GT_POST, /* GF_POST */
+ GT_POSTPOST, /* GF_POSTPOST */
+ six(GT_UNDEF) /* 250 through 255 */
+};
diff --git a/dviware/umddvi/lib/gffont.c b/dviware/umddvi/lib/gffont.c
new file mode 100644
index 0000000000..49d18e6913
--- /dev/null
+++ b/dviware/umddvi/lib/gffont.c
@@ -0,0 +1,920 @@
+/*
+ * Copyright (c) 1987 University of Maryland Department of Computer Science.
+ * All rights reserved. Permission to copy for any purpose is hereby granted
+ * so long as this copyright notice remains intact.
+ */
+
+#ifndef lint
+static char rcsid[] = "$Header: gffont.c,v 2.5 87/06/16 18:28:13 chris Exp $";
+#endif
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "types.h"
+#include "font.h"
+#include "gfcodes.h"
+#include "gfclass.h"
+#include "num.h"
+
+/*
+ * GF font operations.
+ *
+ * GF files may be compact, but this code surely is not!
+ *
+ * TODO:
+ * think about fonts with characters outside [0..255]
+ * find some way to free gf body when done
+ */
+int gf_read(), gf_getgly(), gf_rasterise(), gf_freefont();
+
+struct fontops gfops =
+ { "gf", 1.0, gf_read, gf_getgly, gf_rasterise, gf_freefont };
+
+/*
+ * Local info.
+ */
+
+/*
+ * A bounding box. The names follow those in the GF documentation.
+ */
+struct bounds {
+ i32 min_m, max_m; /* min and max `m' (colunm) values */
+ i32 min_n, max_n; /* min and max `n' (row) values */
+};
+
+/*
+ * char_loc is one `character locator' from a GF file, save for the
+ * `character residue', which we need not.
+ */
+struct char_loc {
+ i32 cl_dx; /* x escapement (scaled pixels) */
+ i32 cl_dy; /* y escapement (scaled pixels) */
+ i32 cl_w; /* TFM width */
+ i32 cl_p; /* pointer to BOC (or specials) */
+};
+
+/*
+ * GF details include:
+ * -> the main body of the GF file (all bytes save pre- and post-amble);
+ * -> global box boundaries;
+ * and character locators, addressed by `character residue'. Empty
+ * slots are indicated by a -1 `pointer'.
+ */
+struct gf_details {
+ char *gd_body; /* GF body */
+ char *gd_base; /* == gd_body - preamble_size */
+ struct bounds gd_gb; /* global boundaries */
+ struct char_loc gd_cl[256]; /* character locators */
+};
+
+/*
+ * Get the gf_details from font f.
+ */
+#define ftogd(f) ((struct gf_details *) (f)->f_details)
+
+extern int errno;
+char *malloc(), *copyit();
+
+/*
+ * I am making the assumption that 530 bytes will always be enough
+ * to find the end of the GF file. 12 should suffice, as there
+ * should be at most seven GF_FILLER bytes, preceded by the GF ID,
+ * preceded by the four byte postamble pointer; but at least one
+ * VMS TeX pads pads DVI files to a full `sector', so I am assuming
+ * it may do the same to GF files.
+ */
+#ifdef vms
+#define POSTSIZE 530 /* make only VMS pay for its ways; */
+#else
+#define POSTSIZE 16 /* others get to use something reasonable */
+#endif
+
+/*
+ * Find the GF postamble. Store the offsets of the POST and POSTPOST
+ * opcodes through postp and postpostp.
+ */
+static
+findGFpostamble(fd, postp, postpostp)
+ int fd;
+ long *postp, *postpostp;
+{
+ register long offset;
+ register char *p;
+ register int i;
+ register i32 n;
+ char postbuf[POSTSIZE];
+
+ /*
+ * Avoid lseek()ing beyond beginning of file; it may give odd
+ * results. Read the last POSTSIZE bytes (or however many we
+ * can get).
+ */
+ offset = lseek(fd, 0L, 2) - (long) POSTSIZE;
+ if (offset < 0L)
+ offset = 0L;
+ (void) lseek(fd, offset, 0);
+ i = read(fd, postbuf, POSTSIZE);
+ if (i <= 0)
+ return (-1);
+ p = &postbuf[i];
+ i -= 4; /* account for the pointer in advance */
+
+ /*
+ * Now search backwards for the GF_ID byte. The postamble
+ * pointer will be four bytes behind that.
+ */
+ while (--i >= 0) {
+ if (UnSign8(*--p) == GF_ID)
+ goto foundit;
+ if (UnSign8(*p) != GF_FILLER)
+ break;
+ }
+ return (-1); /* cannot find postamble ptr */
+
+foundit:
+ /*
+ * Store the (presumed) position of the POSTPOST byte, which
+ * is i-1 bytes beyond `offset'.
+ */
+ *postpostp = offset + i - 1;
+
+ /*
+ * Read out the postamble pointer and seek to the postamble,
+ * also saving the offset.
+ */
+ p -= 4;
+ pGetLong(p, n);
+ *postp = offset = n;
+ (void) lseek(fd, offset, 0);
+ return (0); /* made it */
+}
+
+/*
+ * Read a GF file.
+ */
+static int
+gf_read(f)
+ register struct font *f;
+{
+ register struct gf_details *gd;
+ register char *p;
+ register struct char_loc *cl;
+ register int i;
+ int fd, presize, postsize, bodysize, firstc, lastc;
+ char *postamble;
+ long postaddr, postpostaddr;
+ i32 lasteoc;
+ char *problem = NULL;
+ struct stat st;
+ char b[4];
+ int saverr;
+
+ if ((fd = open(f->f_path, 0)) < 0)
+ return (-1);
+ gd = NULL; /* prepare for failure */
+ postamble = NULL;
+
+ /*
+ * The file had best be at least 50 bytes long. A
+ * `completely empty' GF file might consist of a PRE, a GF_ID,
+ * no comment (one zero byte), then: POST, pointer to last
+ * EOC, design size, checksum, hppp, vppp, min_m, max_m,
+ * min_n, max_n, POSTPOST, pointer to POST, GF_ID, and four
+ * FILLERs.
+ */
+ (void) fstat(fd, &st);
+ if (st.st_size < 50) { /* too small to be a GF file */
+ problem = "file is too short";
+ goto fail;
+ }
+
+ /*
+ * Read the very beginning and pick up the preamble size.
+ */
+ if (read(fd, b, 4) != 4)
+ goto fail;
+ if (UnSign8(b[0]) != GF_PRE) {
+ problem = "file does not begin with PRE";
+ goto fail;
+ }
+ i = UnSign8(b[1]);
+ if (i != GF_ID)
+ error(0, 0, "Warning: strange GF id (%d) in \"%s\"", i,
+ f->f_path);
+ presize = 3 + UnSign8(b[2]);
+
+ /*
+ * Find the postamble, allocate space, and read it in.
+ */
+ if (findGFpostamble(fd, &postaddr, &postpostaddr)) {
+ problem = "cannot find postamble";
+ goto fail;
+ }
+ postsize = postpostaddr - postaddr + 1;
+ if ((p = malloc(postsize)) == NULL)
+ goto fail;
+ if (read(fd, p, postsize) != postsize)
+ goto fail;
+ postamble = p;
+
+ /*
+ * Make sure we found it.
+ */
+ if (pgetbyte(p) != GF_POST) {
+ problem = "no GF_POST at postamble";
+ goto fail;
+ }
+
+ /*
+ * Looks okay. Allocate detail space and poke through the postamble.
+ */
+ if ((gd = (struct gf_details *) malloc(sizeof (*gd))) == NULL)
+ goto fail;
+ gd->gd_body = NULL;
+
+ pGetLong(p, lasteoc); /* actually one past last EOC */
+ p += 4; /* skip design size */
+ pGetLong(p, f->f_checksum);
+ p += 2 * 4; /* hppp, vppp */
+
+ pGetLong(p, gd->gd_gb.min_m);
+ pGetLong(p, gd->gd_gb.max_m);
+ pGetLong(p, gd->gd_gb.min_n);
+ pGetLong(p, gd->gd_gb.max_n);
+
+ /*
+ * Zap all the character locators, then read those that are
+ * defined in the postamble. Remember the first and last
+ * characters so that we know which glyphs are defined. Lastc
+ * is actually the last-plus-one'th character.
+ */
+ for (cl = gd->gd_cl, i = 256; --i >= 0; cl++)
+ cl->cl_p = -1;
+ firstc = 256;
+ lastc = 0;
+ for (;;) {
+ i32 dx, dy;
+
+ switch (pgetbyte(p)) {
+
+ case GF_CHAR_LOC:
+ i = pgetbyte(p);
+ pGetLong(p, dx);
+ pGetLong(p, dy);
+ goto merge;
+
+ case GF_CHAR_LOC0:
+ i = pgetbyte(p);
+ dx = ((i32) pgetbyte(p)) << 16;
+ dy = 0;
+merge:
+ if (i < firstc)
+ firstc = i;
+ if (i >= lastc)
+ lastc = i + 1;
+ cl = &gd->gd_cl[i];
+ cl->cl_dx = dx;
+ cl->cl_dy = dy;
+ pGetLong(p, cl->cl_w);
+ pGetLong(p, cl->cl_p);
+ break;
+
+ case GF_POSTPOST:
+ goto done;
+
+ default:
+ error(0, 0, "I do not understand %d here",
+ UnSign8(p[-1]));
+ problem = "unexpected opcode in postamble";
+ goto fail;
+ }
+ }
+done:
+ free(postamble);
+ postamble = NULL; /* all done with it */
+
+ /*
+ * Alas, we need the instructions whether or not we need
+ * the rasters, since the raster bounding box information
+ * can only be properly determined by converting the rasters.
+ * Compute the size of the main body of the GF file, then
+ * read it in.
+ */
+ bodysize = lasteoc - presize;
+ if ((gd->gd_body = malloc(bodysize + 1)) == NULL)
+ goto fail;
+ (void) lseek(fd, (long) presize, 0);
+ if (read(fd, gd->gd_body, bodysize) != bodysize)
+ goto fail;
+ /*
+ * The next byte might be a special, so we just
+ * arbitrarily stuff in a POST.
+ */
+ gd->gd_body[bodysize] = GF_POST;
+ gd->gd_base = gd->gd_body - presize;
+
+ f->f_details = (char *) gd;
+ if (FontHasGlyphs(f, firstc, lastc))
+ goto fail2;
+ (void) close(fd);
+ return (0);
+
+fail:
+ if (problem == NULL)
+ error(0, errno, "trouble reading \"%s\"", f->f_path);
+ else
+ error(0, 0, "%s\n\t(are you sure \"%s\" is a GF file?)",
+ problem, f->f_path);
+ errno = 0;
+fail2:
+ saverr = errno;
+ if (postamble != NULL)
+ free(postamble);
+ if (gd != NULL) {
+ if (gd->gd_body != NULL)
+ free(gd->gd_body);
+ free((char *) gd);
+ }
+ (void) close(fd);
+ errno = saverr;
+ return (-1);
+}
+
+/*
+ * Some global variables, used while building rasters. (These are
+ * referenced also in copyit(), so must be global. Fortunately, no
+ * one yet requires the font routines to be re-entrant.)
+ */
+static char *buildraster; /* raster being built */
+static int buildsize; /* size of buildraster (bytes) */
+
+static struct bounds tempb; /* bounds used during buildraster */
+static struct bounds ob; /* observed bounds */
+
+/*
+ * Bit tables: `left' and `right' bits. lbits[b] has all the bits
+ * that are to the left of bit b set; rbits[b] has all the bits
+ * that are to the right of bit b set, as well as bit b itself.
+ */
+static char lbits[] = { 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe };
+static char rbits[] = { 0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01 };
+
+/*
+ * The magic address `nullraster' is known in getgly() as a valid
+ * but empty raster, and changed there to NULL. A NULL return from
+ * drawchar indicates failure; we need something to distinguish the
+ * empty raster.
+ */
+static char nullraster[1];
+
+/*
+ * `Inline functions':
+ * -> convert a bit number to a byte number (round down);
+ * -> convert a number of bits to a number of bytes (round up);
+ * and convert a bit to a bit index.
+ */
+#define btoby(b) ((b) >> 3)
+#define btonb(b) (((b) + 7) >> 3)
+#define btobi(b) ((b) & 7)
+
+/*
+ * Helper function for getgly: build the raster, and compute its
+ * minimal bounding box. Called with `p' pointing past the backpointer
+ * field of the BOC command (i.e., at min_m or del_m). `abbrev' is true
+ * iff this was a BOC1. `globalb' are the global bounds from the GF file,
+ * whose name is pointed to by gfname.
+ */
+static char *
+drawchar(p, abbrev, globalb, gfname)
+ register char *p;
+ int abbrev;
+ struct bounds globalb;
+ char *gfname;
+{
+ register i32 m; /* m register (column) */
+ register char *colp; /* pointer to byte corresponding to m */
+ register int c; /* temporary */
+ register i32 i; /* temporary */
+ register int black; /* true when paint_switch==black */
+ register i32 n; /* n register (row) */
+ int stride; /* multiplier to convert linear to 2d array */
+ int wrotethisrow; /* true iff we wrote in the current row */
+ char *virtrast; /* virtual origin version of buildraster */
+ int mustcopy; /* true if we must copy the built raster */
+ struct bounds gb; /* bounds from the GF file */
+
+ /* get the bounds */
+ if (abbrev) {
+ c = pgetbyte(p);/* del_m */
+ gb.min_m = (gb.max_m = pgetbyte(p)) - c;
+ c = pgetbyte(p);/* del_n */
+ gb.min_n = (gb.max_n = pgetbyte(p)) - c;
+ } else {
+ pGetLong(p, gb.min_m);
+ pGetLong(p, gb.max_m);
+ pGetLong(p, gb.min_n);
+ pGetLong(p, gb.max_n);
+ }
+
+ /*
+ * Trim the GF bounds according to the global bounds. We
+ * use the trimmed values to allocate the build space.
+ */
+ tempb = gb;
+#define GB_ADJ(field, cmp) \
+ if (tempb.field cmp globalb.field) \
+ tempb.field = globalb.field
+ GB_ADJ(min_m, <);
+ GB_ADJ(max_m, >);
+ GB_ADJ(min_n, <);
+ GB_ADJ(max_n, >);
+#undef GB_ADJ
+
+ /*
+ * Compute the distance between rows (the number of bytes per
+ * column), then make sure there is room in the build space
+ * for [min_n..max_n] of these, possibly by allocating a new raster.
+ */
+ stride = btonb(tempb.max_m - tempb.min_m + 1);
+ c = stride * (tempb.max_n - tempb.min_n + 1);
+ if (c <= 0) /* completely empty character */
+ return (nullraster);
+ if (c > buildsize) {
+ if (buildraster != NULL)
+ free(buildraster);
+ if ((buildraster = malloc(c)) == NULL) {
+ buildsize = 0;
+ return (NULL);
+ }
+ buildsize = c;
+ }
+
+ /*
+ * If we are using an old raster that is too big, remember to
+ * scrunch it down later.
+ */
+ mustcopy = buildsize > c;
+
+ /* clear the raster to white */
+ bzero(buildraster, c);
+
+ /*
+ * Make a virtual origin raster pointer. The virtual origin is
+ * where raster[0][0] is, whether or not there is a raster[0][0].
+ * Normally, this would be
+ * &buildraster[-gb.min_n * stride - btoby(gb.min_m)],
+ * but it is complicated by two things. Firstly, we would like
+ * n==max_n to be the bottommost point in the raster (low
+ * addresses), and n==min_n to be the topmost (high addresses).
+ * In other words, we need to reflect the n (Y) values about
+ * the X axis: negate them. Secondly, the raster we create
+ * must be `flush left'. That is, somewhere along its rows,
+ * bit 0x80 must be set at the left edge of one of its columns.
+ * We need to subtract away the minimum bit index before
+ * calculating bit values. This cannot really be done in
+ * advance, since we cannot address bits directly.
+ */
+ virtrast = &buildraster[gb.max_n * stride];
+
+ /*
+ * Set up the bounds-trimming variables. The observed m bounds
+ * are kept offset by gb.min_m until we finish drawing the
+ * character.
+ */
+ ob.min_m = tempb.max_m - gb.min_m + 1;
+ ob.max_m = tempb.min_m - gb.min_m - 1;
+ ob.min_n = tempb.max_n + 1;
+ ob.max_n = tempb.min_n - 1;
+ wrotethisrow = 0;
+
+#define FIX_N_BOUNDS() { \
+ if (wrotethisrow) { \
+ c = -n; /* recall that n is reflected about X axis */ \
+ if (c < ob.min_n) \
+ ob.min_n = c; \
+ if (c > ob.max_n) \
+ ob.max_n = c; \
+ wrotethisrow = 0; \
+ } \
+}
+
+ /*
+ * Initialise state variables: m = min_m, n = max_n,
+ * paint_switch = white.
+ */
+ m = 0; /* gb.min_m - gb.min_m */
+ n = -gb.max_n; /* reflected */
+ colp = &virtrast[n * stride];
+if (colp != buildraster)
+panic("gffont drawchar colp != buildraster");
+ black = 0;
+
+ /*
+ * Now interpret the character.
+ * `for (;;)' pushes everything off the right edge, alas.
+ */
+more:
+ c = pgetbyte(p);
+ if (GF_IsPaint(c)) /* faster? */
+ goto paint;
+ switch (GF_OpLen(c)) {
+
+ case GPL_NONE:
+ break;
+
+ case GPL_UNS1:
+ i = pgetbyte(p);
+ break;
+
+ case GPL_UNS2:
+ pGetWord(p, i);
+ break;
+
+ case GPL_UNS3:
+ pGet3Byte(p, i);
+ break;
+
+ case GPL_SGN4:
+ pGetLong(p, i);
+ break;
+
+ default:
+ panic("gffont drawchar GF_OpLen(%d) = %d", c, GF_OpLen(c));
+ /* NOTREACHED */
+ }
+
+ switch (GF_TYPE(c)) {
+
+ case GT_PAINT0:
+paint:
+ i = c - GF_PAINT_0;
+ /* FALLTHROUGH */
+
+ case GT_PAINT:
+ /*
+ * Paint `i' bits in the current row at columns [m..m+i).
+ */
+ if (i && black) {
+ /* remember to adjust n bounds later */
+ wrotethisrow = 1;
+ /* adjust minimum m bound */
+ if (m < ob.min_m)
+ ob.min_m = m;
+
+ /*
+ * Finish the partial byte at colp. There are 8-k
+ * bits to set to finish it, where k is the bit
+ * index value from m. If we need to set fewer
+ * than 8-k bits, set them now and skip the rest
+ * of this.
+ */
+ c = 8 - btobi(m);
+ if (i < c) { /* cannot finish it off */
+ *colp |= UnSign8(lbits[i]) >> btobi(m);
+ m += i;
+ } else { /* finish it off */
+ *colp++ |= rbits[btobi(m)];
+ i -= c;
+ m += c;
+
+ /*
+ * Update m to reflect having written the
+ * remaining i bits, then write them.
+ * First write all the full bytes, then
+ * start a partial byte with whatever
+ * is left over, if anything.
+ */
+ m += i;
+ i >>= 3;
+ while (--i >= 0)
+ *colp++ = 0xff;
+ *colp |= lbits[btobi(m)];
+ }
+
+ /* adjust maximum m bound */
+ if (m > ob.max_m)
+ ob.max_m = m;
+ } else {
+ /*
+ * Add the bit index so that we round up whenever
+ * this fills the partial byte at colp.
+ */
+ colp += (i + btobi(m)) >> 3;
+ m += i;
+ }
+ black = !black;
+ break;
+
+ case GT_EOC: /* all done */
+ FIX_N_BOUNDS();
+ goto done;
+
+ case GT_SKIP0: /* skip no rows */
+ i = 0;
+ /* FALLTHROUGH */
+
+ case GT_SKIP: /* skip some rows, draw white */
+ m = 0;
+ black = 0;
+ goto skip_or_new_row;
+
+ case GT_NEW_ROW: /* next row near left col, draw black */
+ m = c - GF_NEW_ROW_0;
+ black = 1;
+ i = 0; /* n offset is 1: skip no rows */
+skip_or_new_row:
+ FIX_N_BOUNDS();
+ n += i + 1; /* += because reflected */
+ colp = &virtrast[n * stride + btoby(m)];
+ break;
+
+ case GT_XXX: /* special */
+ p += i;
+ break;
+
+ case GT_YYY: /* numspecial */
+ break;
+
+ case GT_NOP: /* dull */
+ break;
+
+ case GT_BOC: /* should not appear */
+ case GT_BOC1:
+ case GT_CHAR_LOC:
+ case GT_CHAR_LOC0:
+ case GT_PRE:
+ case GT_POST:
+ case GT_POSTPOST:
+ case GT_UNDEF:
+ error(0, 0, "unexpected GF opcode %d", c);
+ error(1, 0, "bad GF file \"%s\"", gfname);
+ /* NOTREACHED */
+
+ default:
+ panic("gffont drawchar GF_TYPE(%d) = %d", c, GF_TYPE(c));
+ /* NOTREACHED */
+ }
+ goto more;
+
+done:
+ /*
+ * The observed bounds `m' values are both off by gb.min_m, so
+ * fix them now. CONSIDER ADJUSTING n HERE TOO
+ */
+ ob.min_m += gb.min_m;
+ ob.max_m += gb.min_m;
+
+ /*
+ * If we used too much memory for the raster, copy it now.
+ */
+ if (mustcopy || tempb.min_n != ob.min_n || tempb.max_n != ob.max_n ||
+ btonb(ob.max_m - ob.min_m + 1) != stride)
+ return (copyit());
+
+ /*
+ * If the left column bounds match, just move the raster in place.
+ */
+ if (tempb.min_m == ob.min_m) {
+ p = buildraster;
+ buildraster = NULL;
+ buildsize = 0;
+ return (p);
+ }
+
+ /*
+ * The raster must be copied, but only because it is not
+ * `left justified'.
+ *
+ * CONSIDER DEFERRING THIS PHASE UNTIL THE RASTER IS USED
+ */
+ return (copyit());
+}
+
+/*
+ * Copy the built raster to newly allocated space.
+ * We may need to shift all the bits left as well.
+ */
+char *
+copyit()
+{
+ register char *o, *p;
+ register int i, oldoff, newoff;
+ char *n;
+
+ /*
+ * Compute the observed minimum stride. If it is zero or negative,
+ * there is no raster at all, else allocate just enough space
+ * to hold the new raster.
+ */
+ newoff = btonb(ob.max_m - ob.min_m + 1);
+ if (newoff <= 0)
+ return (nullraster);
+if (ob.max_n < ob.min_n)
+panic("gffont copyit max_n < min_n");
+ n = malloc((unsigned) (newoff * (ob.max_n - ob.min_n + 1)));
+ if ((p = n) == NULL)
+ return (NULL);
+
+ /*
+ * Compute the old stride.
+ */
+ oldoff = btonb(tempb.max_m - tempb.min_m + 1);
+if (oldoff < newoff)
+panic("gffont copyit oldoff < newoff");
+
+ /*
+ * Point at the old raster, then add the offset to the first
+ * written row, and then the offset to the first written column.
+ */
+ o = buildraster;
+ o += (ob.max_n - tempb.max_n) * oldoff;
+ i = ob.min_m - tempb.min_m;
+ o += btoby(i);
+
+ /*
+ * Now copy each row, doing shifting if required.
+ */
+ if ((i = btobi(i)) != 0) { /* must shift, alas */
+ register int r = 8 - i, j, k;
+
+ oldoff -= newoff;
+ for (k = ob.max_n; k >= ob.min_n; k--) {
+ for (j = newoff; --j >= 0;) {
+ *p++ = *o++ << i;
+ p[-1] |= UnSign8(*o) >> r;
+ }
+ o += oldoff;
+ }
+ } else if (oldoff > newoff) { /* compressing columns */
+ for (i = ob.max_n; i >= ob.min_n; i--) {
+ bcopy(o, p, newoff);
+ o += oldoff;
+ p += newoff;
+ }
+ } else /* just squeezing out extra rows */
+ bcopy(o, p, newoff * (ob.max_n - ob.min_n + 1));
+
+ /* finally, return the copy */
+ return (n);
+}
+
+/*
+ * Obtain the specified range of glyphs.
+ */
+static int
+gf_getgly(f, l, h)
+ register struct font *f;
+ int l, h;
+{
+ register struct glyph *g;
+ register struct char_loc *cl;
+ register char *p;
+ register i32 c;
+ register int i;
+ register i32 thisboc;
+ int abbrev;
+ struct gf_details *gd = ftogd(f);
+
+ /*
+ * For each glyph, make sure there exists an instance of that
+ * character residue. Go find the actual glyph (which may be
+ * arbitrarily far down a chain of pointers) and get its info.
+ */
+ for (cl = &gd->gd_cl[i = l]; i < h; i++, cl++) {
+ g = f->f_gly[i];
+ thisboc = cl->cl_p;
+
+ /*
+ * Screw around locating the character for real.
+ */
+ while (thisboc != -1) {
+ p = gd->gd_base + thisboc;
+skip:
+ c = pgetbyte(p);
+ switch (GF_TYPE(c)) {
+
+ case GT_XXX:
+ switch (GF_OpLen(c)) {
+
+ case GPL_UNS1:
+ c = pgetbyte(p);
+ break;
+
+ case GPL_UNS2:
+ pGetWord(p, c);
+ break;
+
+ case GPL_UNS3:
+ pGet3Byte(p, c);
+ break;
+
+ case GPL_SGN4:
+ pGetLong(p, c);
+ break;
+
+ default:
+ panic("gf_getgly GF_OpLen(%d) = %d",
+ c, GF_OpLen(c));
+ /* NOTREACHED */
+ }
+ p += c;
+ goto skip;
+
+ case GT_YYY:
+ p += 4;
+ goto skip;
+
+ case GT_BOC:
+ abbrev = 0;
+ pGetLong(p, c);
+ break;
+
+ case GT_BOC1:
+ abbrev = 1;
+ c = pgetbyte(p);
+ break;
+
+ default:
+ error(0, 0, "GF code %d; I expected BOC", c);
+ error(1, 0, "bad GF file \"%s\"", f->f_path);
+ /* NOTREACHED */
+ }
+ /*
+ * Found a BOC. If it is the right character,
+ * go handle it.
+ */
+ if (c == i)
+ goto handleit;
+ if ((c & 255) != i) {
+ error(0, 0, "%d != %d mod 256", c, i);
+ error(1, 0, "Bad GF file \"%s\"", f->f_path);
+ }
+ /*
+ * Follow the backpointer.
+ */
+ if (abbrev)
+ thisboc = -1;
+ else
+ pGetLong(p, thisboc);
+ }
+
+ /*
+ * If we get here, the glyph is not valid after all.
+ */
+ continue;
+
+ /*
+ * The glyph is okay. Set it up.
+ */
+handleit:
+ g->g_flags = GF_VALID;
+#ifdef notyet
+ g->g_xescapement = cl->cl_dx;
+ g->g_yescapement = cl->cl_dy;
+#endif
+ g->g_tfmwidth = cl->cl_w;
+ if (!abbrev)
+ p += 4; /* skip backpointer */
+ if ((p = drawchar(p, abbrev, gd->gd_gb, f->f_path)) == NULL)
+ return (-1); /* ??? */
+ if (p == nullraster)
+ p = NULL;
+ /* set height &c based on observed bounds */
+ g->g_height = ob.max_n - ob.min_n + 1;
+ g->g_width = ob.max_m - ob.min_m + 1;
+ g->g_yorigin = ob.max_n;
+ g->g_xorigin = -ob.min_m;
+ g->g_raster = p;
+ g->g_rotation = ROT_NORM;
+ }
+ return (0);
+}
+
+/*
+ * Obtain rasters for the specified glyphs. We did this above, while
+ * adjusting the bounding boxes, so this routine should never get called.
+ */
+static int
+gf_rasterise(f, l, h)
+ struct font *f;
+ int l, h;
+{
+
+ panic("gf_rasterise(%s, %d, %d)", f->f_path, l, h);
+}
+
+/*
+ * Discard the font details.
+ */
+static
+gf_freefont(f)
+ struct font *f;
+{
+ struct gf_details *gd;
+
+ if ((gd = ftogd(f)) != NULL) {
+ free(gd->gd_body);
+ free((char *) gd);
+ }
+}
diff --git a/dviware/umddvi/lib/gripes.c b/dviware/umddvi/lib/gripes.c
new file mode 100644
index 0000000000..de70bc0c3a
--- /dev/null
+++ b/dviware/umddvi/lib/gripes.c
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 1987 University of Maryland Department of Computer Science.
+ * All rights reserved. Permission to copy for any purpose is hereby granted
+ * so long as this copyright notice remains intact.
+ */
+
+#ifndef lint
+static char rcsid[] = "$Header: gripes.c,v 2.3 87/06/16 18:28:25 chris Exp $";
+#endif
+
+/*
+ * Common errors (`gripes').
+ */
+
+#include <stdio.h>
+#include "types.h"
+
+static char areyousure[] = "Are you sure this is a DVI file?";
+
+extern errno;
+
+/*
+ * DVI file requests a font it never defined.
+ */
+GripeNoSuchFont(n)
+ i32 n;
+{
+
+ error(0, 0, "DVI file wants font %ld, which it never defined", n);
+ error(1, 0, areyousure);
+ /* NOTREACHED */
+}
+
+/*
+ * DVI file redefines a font.
+ */
+GripeFontAlreadyDefined(n)
+ i32 n;
+{
+
+ error(0, 0, "DVI file redefines font %ld", n);
+ error(1, 0, areyousure);
+ /* NOTREACHED */
+}
+
+/*
+ * Unexpected DVI opcode.
+ */
+GripeUnexpectedOp(s)
+ char *s;
+{
+
+ error(0, 0, "unexpected %s", s);
+ error(1, 0, areyousure);
+ /* NOTREACHED */
+}
+
+/*
+ * Missing DVI opcode.
+ */
+GripeMissingOp(s)
+ char *s;
+{
+
+ error(0, 0, "missing %s", s);
+ error(1, 0, areyousure);
+ /* NOTREACHED */
+}
+
+/*
+ * Cannot find DVI postamble.
+ */
+GripeCannotFindPostamble()
+{
+
+ error(0, 0, "cannot find postamble");
+ error(1, 0, areyousure);
+ /* NOTREACHED */
+}
+
+/*
+ * Inconsistent DVI value.
+ */
+GripeMismatchedValue(s)
+ char *s;
+{
+
+ error(0, 0, "mismatched %s", s);
+ error(1, 0, areyousure);
+ /* NOTREACHED */
+}
+
+/*
+ * Undefined DVI opcode.
+ */
+GripeUndefinedOp(n)
+ int n;
+{
+
+ error(0, 0, "undefined DVI opcode %d");
+ error(1, 0, areyousure);
+ /* NOTREACHED */
+}
+
+/*
+ * Cannot allocate memory.
+ */
+GripeOutOfMemory(n, why)
+ int n;
+ char *why;
+{
+
+ error(1, errno, "ran out of memory allocating %d bytes for %s",
+ n, why);
+ /* NOTREACHED */
+}
+
+/*
+ * Cannot get a font.
+ * RETURNS TO CALLER
+ */
+GripeCannotGetFont(name, mag, dsz, dev, fullname)
+ char *name;
+ i32 mag, dsz;
+ char *dev, *fullname;
+{
+ int e = errno;
+ char scale[40];
+
+ if (mag == dsz) /* no scaling */
+ scale[0] = 0;
+ else
+ (void) sprintf(scale, " scaled %d",
+ (int) ((double) mag / (double) dsz * 1000.0 + .5));
+
+ error(0, e, "cannot get font %s%s", name, scale);
+ if (fullname)
+ error(0, 0, "(wanted, e.g., \"%s\")", fullname);
+ else {
+ if (dev)
+ error(1, 0, "(there are no fonts for the %s engine!)",
+ dev);
+ else
+ error(1, 0, "(I cannot find any fonts!)");
+ /* NOTREACHED */
+ }
+}
+
+/*
+ * Font checksums do not match.
+ * RETURNS TO CALLER
+ */
+GripeDifferentChecksums(font, tfmsum, fontsum)
+ char *font;
+ i32 tfmsum, fontsum;
+{
+
+ error(0, 0, "\
+WARNING: TeX and I have different checksums for font\n\
+\t\"%s\"\n\
+\tPlease notify your TeX maintainer\n\
+\t(TFM checksum = 0%o, my checksum = 0%o)",
+ font, tfmsum, fontsum);
+}
+
+/*
+ * A font, or several fonts, are missing, so no output.
+ */
+GripeMissingFontsPreventOutput(n)
+ int n;
+{
+ static char s[2] = {'s', 0};
+
+ error(1, 0, "%d missing font%s prevent%s output (sorry)", n,
+ n > 1 ? s : &s[1], n == 1 ? s : &s[1]);
+ /* NOTREACHED */
+}
diff --git a/dviware/umddvi/lib/llib-lib b/dviware/umddvi/lib/llib-lib
new file mode 100644
index 0000000000..aa2be831d7
--- /dev/null
+++ b/dviware/umddvi/lib/llib-lib
@@ -0,0 +1,65 @@
+ /* LINTLIBRARY */
+
+#include <stdio.h>
+#include "../h/types.h"
+#include "../h/dviclass.h"
+#include "../h/dvicodes.h"
+#include "../h/fio.h"
+#include "../h/font.h"
+#include "../h/postamble.h"
+#include "../h/search.h"
+
+int optind;
+char *optarg;
+
+char dvi_oplen[];
+char dvi_dt[];
+
+ bcopy(from, to, count) char *from, *to; unsigned count; {;}
+ bzero(addr, count) char *addr; unsigned count; {;}
+ /* VARARGS 3 */
+ error(quit, errno, fmt) int quit, errno; char *fmt; {;}
+ /* VARARGS 1 */
+ panic(fmt) char *fmt; { exit(1); }
+int FindPostAmble(f) FILE *f; { return 0; }
+i32 GetLong(f) FILE *f; { return 0; }
+i32 Get3Byte(f) FILE *f; { return 0; }
+i32 GetWord(f) FILE *f; { return 0; }
+i32 GetByte(f) FILE *f; { return 0; }
+int getopt(argc, argv, optstring) int argc; char **argv, *optstring;
+ { return 'a'; }
+void CSetConversion(c, dpi, mag, num, den, dvimag)
+ struct conversion *c; int dpi, mag; i32 num, den, dvimag; {;}
+double DMagFactor(magfactor) int magfactor; { return 1000.0; }
+ fontinit(file) char *file; {;}
+struct font *
+ GetFont(nm, dvimag, dvidsz, dev, fname)
+ char *nm; i32 dvimag, dvidsz; int globalmag;
+ char *dev, **fname;
+ { *fname = 0; return ((struct font *) 0); }
+struct font *
+ GetRasterlessFont(nm, dvimag, dvidsz, dev, fname)
+ char *nm; i32 dvimag, dvidsz; int globalmag;
+ char *dev, **fname;
+ { *fname = 0; return ((struct font *) 0); }
+char *Font_TeXName();
+ GripeCannotFindPostamble() {;}
+ GripeCannotGetFont(name, dvimag, dvidsz, dev, fullname)
+ char *name; i32 dvimag, dvidsz; char *dev, *fullname; {;}
+ GripeDifferentChecksums(font, tfmsum, fontsum)
+ char *font; i32 tfmsum, fontsum; {;}
+ GripeFontAlreadyDefined(n) i32 n; {;}
+ GripeMismatchedValue(s) char *s; {;}
+ GripeMissingFontsPreventOutput(n) int n; {;}
+ GripeMissingOp(s) char *s; {;}
+ GripeNoSuchFont(n) i32 n; {;}
+ GripeOutOfMemory(n, why) int n; char *why; {;}
+ GripeUndefinedOp(n) int n; {;}
+ GripeUnexpectedOp(s) char *s; {;}
+i32 ScaleOneWidth(t, z) i32 t, z; { return (t * z >> 4); }
+ ScanPostAmble(f, hfun, ffun) FILE *f; int (*hfun)(), (*ffun)(); {;}
+struct search *
+ SCreate(dsize) unsigned dsize; { return 0; }
+ SEnumerate(s, f) struct search *s; int (*f)(); {;}
+char *SSearch(s, key, disp) struct search *s; i32 key; int *disp;
+ { return 0; }
diff --git a/dviware/umddvi/lib/magfactor.c b/dviware/umddvi/lib/magfactor.c
new file mode 100644
index 0000000000..0b44b83863
--- /dev/null
+++ b/dviware/umddvi/lib/magfactor.c
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 1987 University of Maryland Department of Computer Science.
+ * All rights reserved. Permission to copy for any purpose is hereby granted
+ * so long as this copyright notice remains intact.
+ */
+
+/*
+ * Convert a magnification factor to floating point. This is used in
+ * conjunction with the FONT_SLOP stuff to try to get the file names
+ * right, and may also be used by DVI reading programs to get slightly
+ * more accurate values for (mag/1000.0).
+ */
+double
+DMagFactor(mag)
+ int mag;
+{
+
+ switch (mag) {
+
+ case 1095: /* stephalf */
+ return (1.095445);
+
+ case 1315: /* stepihalf */
+ return (1.314534);
+
+ case 2074: /* stepiv */
+ return (2.0736);
+
+ case 2488: /* stepv */
+ return (2.48832);
+
+ case 2986: /* stepiv */
+ return (2.985984);
+
+ default: /* remaining mags have been ok */
+ return ((double) mag / 1000.);
+ }
+ /* NOTREACHED */
+}
diff --git a/dviware/umddvi/lib/makefile b/dviware/umddvi/lib/makefile
new file mode 100644
index 0000000000..515a9d49d5
--- /dev/null
+++ b/dviware/umddvi/lib/makefile
@@ -0,0 +1,140 @@
+#
+# Copyright (c) 1987 University of Maryland Department of Computer Science.
+# All rights reserved. Permission to copy for any purpose is hereby granted
+# so long as this copyright notice remains intact.
+#
+# Makefile for ctex/lib (C-TeX library routines)
+#
+# $Header: Makefile,v 1.2 87/06/16 18:27:29 chris Exp $
+#
+DESTDIR=
+# Alas, -R makes ALL initialised variables read-only, and we cannot
+# use it on font files; hence, FCFLAGS.
+CFLAGS= -O -R -I../h
+FCFLAGS=-O -I../h
+
+# This will be overridden by ../Makefile, but just in case...
+CONFFILE=/usr/local/lib/tex/fontdesc
+
+# 4.1BSD Vax:
+#ASSRC= bcopy.s bzero.s
+#ASOBJ= bcopy.o bzero.o
+#MISCC= getopt.c
+#MISCO= getopt.o
+
+# 4.2BSD Vax:
+#ASSRC=
+#ASOBJ=
+#MISCC= getopt.c
+#MISCO= getopt.o
+
+# 4.2BSD Sun:
+#ASSRC=
+#ASOBJ=
+#MISCC=
+#MISCO=
+
+# 4.2BSD Pyramid:
+#ASSRC=
+#ASOBJ=
+#MISCC= getopt.c
+#MISCO= getopt.o
+
+# 4.3BSD Vax:
+ASSRC=
+ASOBJ=
+MISCC=
+MISCO=
+
+# all
+CSRC= conv.c dviclass.c error.c findpost.c fio.c font.c font_subr.c \
+ gfclass.c gripes.c magfactor.c rotate.c scaletfm.c scanpost.c \
+ search.c seek.c split.c strsave.c tfm.c ${MISCC}
+COBJ= conv.o dviclass.o error.o findpost.o fio.o font.o font_subr.o \
+ gfclass.o gripes.o magfactor.o rotate.o scaletfm.o scanpost.o \
+ search.o seek.o split.o strsave.o tfm.o ${MISCO}
+FSRC= gffont.c pkfont.c pxlfont.c tfmfont.c
+FOBJ= gffont.o pkfont.o pxlfont.o tfmfont.o
+
+OBJS= ${COBJ} ${ASOBJ} ${FOBJ}
+
+all: lib.a
+
+lib.a: ${OBJS}
+ ar cr lib.a ${OBJS}
+ ranlib lib.a
+
+# no installation is necessary; this entry is just for standardisation
+install:
+
+clean:
+ rm -f *.o lib.a
+
+depend: ${CSRC} ${FSRC}
+ ${CC} -M ${CFLAGS} ${CSRC} ${FSRC} | \
+ awk '{ if ($$1 != prev) { if (rec != "") print rec; \
+ rec = $$0; prev = $$1; } \
+ else { if (length(rec $$2) > 78) { print rec; rec = $$0; } \
+ else rec = rec " " $$2 } } \
+ END { print rec }' >makedep
+ echo '/^# DO NOT DELETE THIS LINE/+2,$$d' >eddep
+ echo '$$r makedep' >>eddep
+ echo 'w' >>eddep
+ cp Makefile Makefile.bak
+ ed - Makefile <eddep
+ rm eddep makedep
+ echo '# DEPENDENCIES MUST END AT END OF FILE' >>Makefile
+ echo '# IF YOU PUT STUFF HERE IT WILL GO AWAY' >>Makefile
+ echo '# see make depend above' >>Makefile
+
+#pxl.o:
+# ${CC} ${CFLAGS} -c -DPXLPATH=\"${PXLPATH}\" pxl.c
+
+# font.o needs to know where to find the font description file
+font.o:
+ ${CC} ${CFLAGS} -c -DCONFFILE=\"${CONFFILE}\" font.c
+
+# special rules for font objects
+${FOBJ}:
+ ${CC} ${FCFLAGS} -c $*.c
+
+# DO NOT DELETE THIS LINE -- make depend uses it
+
+conv.o: conv.c ../h/types.h ../h/conv.h
+dviclass.o: dviclass.c ../h/dviclass.h
+error.o: error.c /usr/include/stdio.h /usr/include/varargs.h
+findpost.o: findpost.c /usr/include/stdio.h ../h/types.h ../h/dvicodes.h
+findpost.o: ../h/fio.h
+fio.o: fio.c /usr/include/stdio.h ../h/types.h ../h/fio.h
+font.o: font.c /usr/include/stdio.h /usr/include/errno.h ../h/types.h
+font.o: ../h/conv.h ../h/font.h
+font_subr.o: font_subr.c ../h/font.h ../h/types.h
+gfclass.o: gfclass.c ../h/gfclass.h
+gripes.o: gripes.c /usr/include/stdio.h ../h/types.h
+magfactor.o: magfactor.c
+rotate.o: rotate.c ../h/font.h ../h/types.h
+scaletfm.o: scaletfm.c ../h/types.h ../h/font.h
+scanpost.o: scanpost.c /usr/include/stdio.h ../h/types.h ../h/dvicodes.h
+scanpost.o: ../h/fio.h ../h/postamble.h
+search.o: search.c ../h/types.h ../h/search.h
+seek.o: seek.c /usr/include/stdio.h /usr/include/sys/param.h
+seek.o: /usr/include/machine/machparam.h /usr/include/signal.h
+seek.o: /usr/include/sys/types.h /usr/include/sys/file.h
+seek.o: /usr/include/sys/stat.h
+split.o: split.c /usr/include/ctype.h
+strsave.o: strsave.c
+tfm.o: tfm.c /usr/include/stdio.h ../h/types.h ../h/fio.h ../h/tfm.h
+gffont.o: gffont.c /usr/include/stdio.h /usr/include/sys/types.h
+gffont.o: /usr/include/sys/stat.h ../h/types.h ../h/font.h ../h/gfcodes.h
+gffont.o: ../h/gfclass.h ../h/num.h
+pkfont.o: pkfont.c /usr/include/stdio.h /usr/include/sys/types.h
+pkfont.o: /usr/include/sys/stat.h ../h/types.h ../h/font.h ../h/num.h
+pxlfont.o: pxlfont.c /usr/include/stdio.h /usr/include/sys/types.h
+pxlfont.o: /usr/include/sys/stat.h /usr/include/errno.h ../h/types.h
+pxlfont.o: ../h/font.h ../h/fio.h
+tfmfont.o: tfmfont.c /usr/include/stdio.h /usr/include/sys/types.h
+tfmfont.o: /usr/include/sys/stat.h ../h/types.h ../h/conv.h ../h/font.h
+tfmfont.o: ../h/tfm.h
+# DEPENDENCIES MUST END AT END OF FILE
+# IF YOU PUT STUFF HERE IT WILL GO AWAY
+# see make depend above
diff --git a/dviware/umddvi/lib/makefile.3b b/dviware/umddvi/lib/makefile.3b
new file mode 100644
index 0000000000..1cd59b1f2c
--- /dev/null
+++ b/dviware/umddvi/lib/makefile.3b
@@ -0,0 +1,132 @@
+# Makefile for ctex/lib (C-TeX library routines)
+#
+DESTDIR=
+# Alas, -R makes ALL initialised variables read-only, and we cannot
+# use it on font files; hence, FCFLAGS.
+CFLAGS= -O -I../h -Dsys5
+FCFLAGS=-O -I../h -Dsys5
+
+# This will be overridden by ../Makefile, but just in case...
+CONFFILE=/usr/local/lib/tex/fontdesc
+
+# 4.1BSD Vax:
+#ASSRC= bcopy.s bzero.s
+#ASOBJ= bcopy.o bzero.o
+#MISCC= getopt.c
+#MISCO= getopt.o
+
+# 4.2BSD Vax:
+#ASSRC=
+#ASOBJ=
+#MISCC= getopt.c
+#MISCO= getopt.o
+
+# 4.2BSD Sun:
+#ASSRC=
+#ASOBJ=
+#MISCC=
+#MISCO=
+
+# 4.2BSD Pyramid:
+#ASSRC=
+#ASOBJ=
+#MISCC= getopt.c
+#MISCO= getopt.o
+
+# 4.3BSD Vax:
+ASSRC=
+ASOBJ=
+MISCC=
+MISCO=
+
+# all
+CSRC= conv.c dviclass.c error.c findpost.c fio.c font.c font_subr.c \
+ gfclass.c gripes.c magfactor.c rotate.c scaletfm.c scanpost.c \
+ search.c seek.c split.c strsave.c tfm.c ${MISCC}
+COBJ= conv.o dviclass.o error.o findpost.o fio.o font.o font_subr.o \
+ gfclass.o gripes.o magfactor.o rotate.o scaletfm.o scanpost.o \
+ search.o seek.o split.o strsave.o tfm.o ${MISCO}
+FSRC= gffont.c pkfont.c pxlfont.c tfmfont.c
+FOBJ= gffont.o pkfont.o pxlfont.o tfmfont.o
+
+OBJS= ${COBJ} ${ASOBJ} ${FOBJ}
+
+all: lib.a
+
+lib.a: ${OBJS}
+ ar cr lib.a ${OBJS}
+
+# no installation is necessary; this entry is just for standardisation
+install:
+
+clean:
+ rm -f *.o lib.a
+
+depend: ${CSRC} ${FSRC}
+ ${CC} -M ${CFLAGS} ${CSRC} ${FSRC} | \
+ awk '{ if ($$1 != prev) { if (rec != "") print rec; \
+ rec = $$0; prev = $$1; } \
+ else { if (length(rec $$2) > 78) { print rec; rec = $$0; } \
+ else rec = rec " " $$2 } } \
+ END { print rec }' >makedep
+ echo '/^# DO NOT DELETE THIS LINE/+2,$$d' >eddep
+ echo '$$r makedep' >>eddep
+ echo 'w' >>eddep
+ cp Makefile Makefile.bak
+ ed - Makefile <eddep
+ rm eddep makedep
+ echo '# DEPENDENCIES MUST END AT END OF FILE' >>Makefile
+ echo '# IF YOU PUT STUFF HERE IT WILL GO AWAY' >>Makefile
+ echo '# see make depend above' >>Makefile
+
+#pxl.o:
+# ${CC} ${CFLAGS} -c -DPXLPATH=\"${PXLPATH}\" pxl.c
+
+# font.o needs to know where to find the font description file
+font.o:
+ ${CC} ${CFLAGS} -c -DCONFFILE=\"${CONFFILE}\" font.c
+
+# special rules for font objects
+${FOBJ}:
+ ${CC} ${FCFLAGS} -c $*.c
+
+# DO NOT DELETE THIS LINE -- make depend uses it
+
+conv.o: conv.c ../h/types.h ../h/conv.h
+dviclass.o: dviclass.c ../h/dviclass.h
+error.o: error.c /usr/include/stdio.h /usr/include/varargs.h
+findpost.o: findpost.c /usr/include/stdio.h ../h/types.h ../h/dvicodes.h
+findpost.o: ../h/fio.h
+fio.o: fio.c /usr/include/stdio.h ../h/types.h ../h/fio.h
+font.o: font.c /usr/include/stdio.h /usr/include/errno.h ../h/types.h
+font.o: ../h/conv.h ../h/font.h
+font_subr.o: font_subr.c ../h/font.h ../h/types.h
+gfclass.o: gfclass.c ../h/gfclass.h
+gripes.o: gripes.c /usr/include/stdio.h ../h/types.h
+magfactor.o: magfactor.c
+rotate.o: rotate.c ../h/font.h ../h/types.h
+scaletfm.o: scaletfm.c ../h/types.h ../h/font.h
+scanpost.o: scanpost.c /usr/include/stdio.h ../h/types.h ../h/dvicodes.h
+scanpost.o: ../h/fio.h ../h/postamble.h
+search.o: search.c ../h/types.h ../h/search.h
+seek.o: seek.c /usr/include/stdio.h /usr/include/sys/param.h
+seek.o: /usr/include/signal.h
+seek.o: /usr/include/sys/types.h /usr/include/sys/fcntl.h
+seek.o: /usr/include/sys/stat.h
+split.o: split.c /usr/include/ctype.h
+strsave.o: strsave.c
+tfm.o: tfm.c /usr/include/stdio.h ../h/types.h ../h/fio.h ../h/tfm.h
+gffont.o: gffont.c /usr/include/stdio.h /usr/include/sys/types.h
+gffont.o: /usr/include/sys/stat.h ../h/types.h ../h/font.h ../h/gfcodes.h
+gffont.o: ../h/gfclass.h ../h/num.h
+pkfont.o: pkfont.c /usr/include/stdio.h /usr/include/sys/types.h
+pkfont.o: /usr/include/sys/stat.h ../h/types.h ../h/font.h ../h/num.h
+pxlfont.o: pxlfont.c /usr/include/stdio.h /usr/include/sys/types.h
+pxlfont.o: /usr/include/sys/stat.h /usr/include/errno.h ../h/types.h
+pxlfont.o: ../h/font.h ../h/fio.h
+tfmfont.o: tfmfont.c /usr/include/stdio.h /usr/include/sys/types.h
+tfmfont.o: /usr/include/sys/stat.h ../h/types.h ../h/conv.h ../h/font.h
+tfmfont.o: ../h/tfm.h
+# DEPENDENCIES MUST END AT END OF FILE
+# IF YOU PUT STUFF HERE IT WILL GO AWAY
+# see make depend above
diff --git a/dviware/umddvi/lib/man/all.tex b/dviware/umddvi/lib/man/all.tex
new file mode 100644
index 0000000000..0805fa4346
--- /dev/null
+++ b/dviware/umddvi/lib/man/all.tex
@@ -0,0 +1,5 @@
+\input Base.tex
+\input bstring.tex
+\input dviclass.tex
+\input magfactor.tex
+\bye
diff --git a/dviware/umddvi/lib/man/base.tex b/dviware/umddvi/lib/man/base.tex
new file mode 100644
index 0000000000..af5e55fc3c
--- /dev/null
+++ b/dviware/umddvi/lib/man/base.tex
@@ -0,0 +1,67 @@
+%
+% Base file for manuals
+%
+% define macros, fonts, etc.
+
+\def\makeatletter{\catcode`\@=11} \def\makeatother{\catcode`\@=12}
+
+\makeatletter
+
+% manual: title, section, message-to-center
+\def\manual#1(#2)#3{\vfill\eject
+ \gdef\man@title{#1(#2)} \gdef\man@center{#3}
+ \global\pageno=1
+}
+
+% sections
+\def\section#1{\par\unskip\line{#1\hfil}\vskip-\parskip}
+
+% line breaks without vertical space
+\def\l{\par\nobreak\vskip-\parskip}
+
+% sections: name, synopsis, description, files, author, bugs
+
+\def\name{\section{NAME}}
+
+% synopsis is in tt, obeys lines
+\def\synopsis{\bgroup\section{SYNOPSIS}\obeylines\let\^^M=\l\tt}
+\def\endsyn{\egroup}
+
+\def\description{\section{DESCRIPTION}}
+\def\author{\section{AUTHOR}}
+\def\files{\section{FILES}}
+\def\bugs{\section{BUGS}}
+
+% list environment, of sorts
+\newdimen\listdent \listdent=5em
+\def\beginlist#1{\par\bgroup\listdent=#1
+ \advance\leftskip\listdent\advance\rightskip\listdent\relax}
+\def\endlist{\par\egroup}
+\def\listentry#1{\par
+ \setbox0=\hbox{#1\quad}\ifdim\wd0>\listdent
+ \line{\hskip-\listdent\box0\hfil}\else
+ \wd0=\listdent \llap{\box0}\fi}
+
+% code fragments
+\def\begincode{\bgroup\obeylines\let\^^M=\l\tt}
+\def\endcode{\egroup}
+
+% fonts
+\def\b#1{{\bf #1}}
+\def\i#1{{\it #1}}
+
+% TeX expression
+\def\texword#1{{\tt\char`\\ #1}}
+
+% literal word
+\def\lit#1{{\tt #1}}
+
+% basic formatting
+\headline={\rlap{\man@title}\hfil C-\TeX\ Programmer's
+ Manual\hfil\llap{\man@title}}
+\footline={\rlap{Printed \the\month/\the\day/\the\year}\hfil
+ \man@center\hfil\llap{\folio}}
+
+\leftskip=5em \parskip=.5\baselineskip \parindent=0pt
+
+\makeatother
diff --git a/dviware/umddvi/lib/man/bstring.tex b/dviware/umddvi/lib/man/bstring.tex
new file mode 100644
index 0000000000..367222e2f5
--- /dev/null
+++ b/dviware/umddvi/lib/man/bstring.tex
@@ -0,0 +1,23 @@
+\manual BSTRING(3){}
+\name
+bcopy, bzero, ffs---bit and byte string operations
+\synopsis
+bcopy(src, dst, length)
+char *src, *dst;
+int length;
+
+bzero(b, length)
+char *b;
+int length;
+\endsyn
+\description
+The routines \i{bcopy} and \i{bzero} operate on variable length
+strings of bytes. They do not check for null bytes as the routines
+in \i{string}(3) do.
+
+\i{Bcopy} copies \i{length} bytes from string \i{src} to the string
+\i{dst}.
+
+\i{Bzero} places \i{length} 0 bytes in the string \i{b1}.
+\bugs
+The \i{bcopy} routine take parameters backwards from \i{strcpy}.
diff --git a/dviware/umddvi/lib/man/dviclass.tex b/dviware/umddvi/lib/man/dviclass.tex
new file mode 100644
index 0000000000..07486ef98a
--- /dev/null
+++ b/dviware/umddvi/lib/man/dviclass.tex
@@ -0,0 +1,169 @@
+\manual DVICLASS(3){}
+\name
+DVI\_DT, DVI\_OpLen---DVI opcode classification tables
+\synopsis
+DVI\_DT(code)
+int code;
+
+DVI\_OpLen(code)
+int code;
+\endsyn
+\description
+These macros compress DVI code values according to `classification'
+and `opcode length'. \i{DVI\_DT} returns one of the following values:
+
+\beginlist{5em}
+
+\listentry{\lit{DT\_CHAR}}
+A literal character code ($0 \le code \le 127$).
+
+\listentry{\lit{DT\_SET}}
+A \lit{set} code (set a character and advance).
+
+\listentry{\lit{DT\_SETRULE}}
+A \lit{set\_rule} code.
+
+\listentry{\lit{DT\_PUT}}
+A \lit{put} code (set a character but do not advance).
+
+\listentry{\lit{DT\_PUTRULE}}
+A \lit{put\_rule} code (set a rule but do not advance).
+
+\listentry{\lit{DT\_NOP}}
+A \lit{nop} code.
+
+\listentry{\lit{DT\_BOP}}
+A \lit{bop} code.
+
+\listentry{\lit{DT\_EOP}}
+An \lit{eop} code.
+
+\listentry{\lit{DT\_PUSH}}
+A \lit{push}.
+
+\listentry{\lit{DT\_POP}}
+A \lit{pop}.
+
+\listentry{\lit{DT\_RIGHT}}
+Any of the several \lit{right} codes.
+
+\listentry{\lit{DT\_W0}}
+A \lit{w0}.
+
+\listentry{\lit{DT\_W}}
+One of the \lit{w}s.
+
+\listentry{\lit{DT\_X0}}
+An \lit{x0}.
+
+\listentry{\lit{DT\_X}}
+One of the \lit{x}s.
+
+\listentry{\lit{DT\_DOWN}}
+A \lit{down}.
+
+\listentry{\lit{DT\_Y0}}
+A \lit{y0}.
+
+\listentry{\lit{DT\_Y}}
+A \lit{y}.
+
+\listentry{\lit{DT\_Z0}}
+A \lit{z0}.
+
+\listentry{\lit{DT\_Z}}
+A \lit{z}.
+
+\listentry{\lit{DT\_FNTNUM}}
+A parameterless font selector (\lit{fntnum0}, \lit{fntnum1}, \dots,
+\lit{fntnum63}).
+
+\listentry{\lit{DT\_FNT}}
+A parameterised font selector (\lit{fnt1}, \dots, \lit{fnt4}).
+
+\listentry{\lit{DT\_XXX}}
+A \lit{xxx}: a special.
+
+\listentry{\lit{DT\_FNTDEF}}
+A \lit{fntdef}.
+
+\listentry{\lit{DT\_PRE}}
+A \lit{pre}.
+
+\listentry{\lit{DT\_POST}}
+A \lit{post}.
+
+\listentry{\lit{DT\_POSTPOST}}
+A \lit{postpost}.
+
+\listentry{\lit{DT\_UNDEF}}
+An undefined DVI opcode (in $[250..255]$).
+
+\endlist
+
+\i{DVI\_OpLen} returns the length of the first parameter, as one
+of the following values:
+
+\beginlist{5em}
+\listentry{\lit{DPL\_NONE}}
+No (or implicit) parameter, or it cannot be determined so simply, e.g.,
+\lit{bop}, or \lit{post}.
+
+\listentry{\lit{DPL\_SGN1}}
+A signed one-byte parameter $-128 \le p \le 127$.
+
+\listentry{\lit{DPL\_SGN2}}
+A signed two-byte parameter $-32768 \le p \le 32767$.
+
+\listentry{\lit{DPL\_SGN3}}
+A signed three-byte parameter $-8388608 \le p \le 8388607$.
+
+\listentry{\lit{DPL\_SGN4}}
+A signed four-byte parameter $-2147483648 \le p \le 2147483647$.
+
+\listentry{\lit{DPL\_UNS1}}
+An unsigned one-byte parameter $0 \le p \le 255$.
+
+\listentry{\lit{DPL\_UNS2}}
+An unsigned two-byte parameter $0 \le p \le 65535$.
+
+\listentry{\lit{DPL\_UNS3}}
+An unsigned three-byte parameter $0 \le p \le 16777215$.
+
+\endlist
+
+These values are intended to be used to simplify \lit{switch} statements
+that decode DVI files. A program that must interpret the opcodes can
+use code similar to the following:
+
+\vskip 0pt plus1fil
+\begincode \vbox{
+ op = getc(dvi\_file);
+ switch (DVI\_OpLen(op)) {
+ case DPL\_NONE: {\it /* do nothing */}
+ break;
+ case DPL\_SGN1: {\it /* get a one byte signed parameter */}
+ param = Sign8(getc(dvi\_file));
+ break;
+ case DPL\_SGN2: {\it /* get a two byte signed parameter */}
+ fGetWord(dvi\_file, param);
+ param = Sign16(param);
+ break;
+ {\rm$\vdots$}
+ case DPL\_UNS3: {\it /* get a three byte unsigned parameter */}
+ fGet3Byte(dvi\_file, param);
+ break;
+ }
+
+ switch (DVI\_DT(op)) {
+ case DT\_CHAR:
+ set\_char\_and\_advance(op);
+ break;
+ case DT\_SET:
+ set\_char\_and\_advance(param);
+ break;
+ {\rm$\vdots$}
+ }
+} \endcode
+
+In other words, ## other words ##
diff --git a/dviware/umddvi/lib/man/magfactor.tex b/dviware/umddvi/lib/man/magfactor.tex
new file mode 100644
index 0000000000..135d073b7a
--- /dev/null
+++ b/dviware/umddvi/lib/man/magfactor.tex
@@ -0,0 +1,12 @@
+\manual DMAGFACTOR(3){}
+\name
+DMagFactor---double precision \texword{magfactor}
+\synopsis
+double
+DMagFactor(magfactor)
+int magfactor;
+\endsyn
+\description
+\i{DMagFactor} returns $\i{magfactor}/1000.0$, with some extra
+fiddling to get more precise values for the various \texword{magstep}s
+that are commonly used.
diff --git a/dviware/umddvi/lib/man/makefile b/dviware/umddvi/lib/man/makefile
new file mode 100644
index 0000000000..8036a1a8af
--- /dev/null
+++ b/dviware/umddvi/lib/man/makefile
@@ -0,0 +1,21 @@
+# Makefile for C-TeX library manual
+#
+# Run off all the manuals.
+
+TEX= tex
+PRINT= iptex
+
+all: all.dvi
+ ${PRINT} all.dvi
+
+all.dvi: FRC
+ rm -f all.*
+ (echo *.tex | tr ' ' '\012' | sed -e 's/^/\\input /'; \
+ echo '\bye') > all.tmp
+ mv all.tmp all.tex
+ ${TEX} all.tex
+
+FRC:
+
+clean:
+ rm -f all.* texput.* *.dvi *.log
diff --git a/dviware/umddvi/lib/man/xx b/dviware/umddvi/lib/man/xx
new file mode 100644
index 0000000000..b13278ce33
--- /dev/null
+++ b/dviware/umddvi/lib/man/xx
@@ -0,0 +1,7 @@
+\manual FONT(3){}
+\name
+\synopsis
+\endsyn
+\description
+\author
+Chris Torek <chris@mimsy.umd.edu>
diff --git a/dviware/umddvi/lib/note b/dviware/umddvi/lib/note
new file mode 100644
index 0000000000..7b1102a7d2
--- /dev/null
+++ b/dviware/umddvi/lib/note
@@ -0,0 +1,16 @@
+There are two VAX-dependent file in this directory:
+
+- bcopy.s block copy routine. You can simply remove this from
+ the Makefile if you are running 4.2; bcopy is already
+ provided.
+
+- bzero.s block zero routine. As above.
+
+There is one more system-dependent file:
+
+- error.c error and panic routines. These make calls to stdio
+ internals, except on System V or other machines on
+ which there are `vprintf' routines. Define HAVE_VPRINTF
+ if you have the vprintf routines.
+
+See the manuals for the parameters to these.
diff --git a/dviware/umddvi/lib/pkfont.c b/dviware/umddvi/lib/pkfont.c
new file mode 100644
index 0000000000..87224cd299
--- /dev/null
+++ b/dviware/umddvi/lib/pkfont.c
@@ -0,0 +1,767 @@
+/*
+ * Copyright (c) 1987 University of Maryland Department of Computer Science.
+ * All rights reserved. Permission to copy for any purpose is hereby granted
+ * so long as this copyright notice remains intact.
+ */
+
+#ifndef lint
+static char rcsid[] = "$Header: pkfont.c,v 2.8 87/08/21 12:44:28 chris Exp $";
+#endif
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "types.h"
+#include "font.h"
+#include "num.h"
+
+/*
+ * PK font operations.
+ *
+ * The spelling `nybble' is a concession to the authors of the PK format.
+ */
+int pk_read(), pk_getgly(), pk_rasterise(), pk_freefont();
+
+struct fontops pkops =
+ { "pk", 1.0, pk_read, pk_getgly, pk_rasterise, pk_freefont };
+
+/*
+ * Local info.
+ */
+
+/*
+ * Commands.
+ */
+#define PK_XXX1 240 /* 1 byte special */
+#define PK_XXX2 241 /* 2 byte special */
+#define PK_XXX3 242 /* 3 byte special */
+#define PK_XXX4 243 /* 4 byte special */
+#define PK_YYY 244 /* METAFONT numspecial */
+#define PK_POST 245 /* marks postamble */
+#define PK_NO_OP 246 /* do nothing */
+#define PK_PRE 247 /* marks preamble */
+ /* 248..255 undefined */
+#define PK_IsUndef(c) ((c) > PK_PRE)
+
+#define PK_ID 89 /* marks this brand of PK file */
+
+/*
+ * Information about a character packet.
+ */
+struct cp {
+ char *cp_packet; /* the beginning of the packet */
+ int cp_type; /* decoded pre type, see below */
+};
+
+#define CP_SHORT 0 /* short preamble */
+#define CP_EXT_SHORT 1 /* extended short preamble */
+#define CP_LONG 2 /* long preamble */
+
+/*
+ * The PK details include:
+ * -> a pointer to the next byte to fetch;
+ * -> the most recent byte fetched (when we are using nextnyb());
+ * -> a flag indicating that we have used nybble 0 (bits 4..7) and
+ * should use nybble 1 next;
+ * -> the base address of the memory allocated for the PK file;
+ * -> the value of dyn_f (during character translation);
+ * -> the repeat count (during rasterisation);
+ * -> the lowest glyph number that is legal;
+ * -> the highest glyph number that is legal;
+ * -> glyph instructions for the standard glyphs;
+ * -> glyph instructions for more (nonstandard) glyphs;
+ * and the number of glyphs left unrasterised.
+ */
+struct pk_details {
+ char *pk_ptr; /* next byte to fetch */
+ int pk_c; /* most recent byte fetched, if nybbling */
+ int pk_1nyb; /* true => nybble 1 is next (bits 0..3) */
+ char *pk_base; /* base of allocated memory */
+ int pk_dyn_f; /* the dyn_f value */
+ int pk_repeat; /* the repeat count */
+ int pk_minc; /* minimum character value */
+ int pk_maxc; /* maximum character value */
+#define MAXSTD 256 /* maximum `standard' character value */
+ int pk_gleft; /* number of valid glyphs left uninterpreted */
+ struct cp pk_cpack[MAXSTD]; /* for characters in [0..MAXSTD) */
+ struct cp *pk_morec; /* for characters in [MAXSTD..maxc] */
+};
+
+/*
+ * Fetch the next byte from the PK file.
+ */
+#define nextbyte(pk) pgetbyte((pk)->pk_ptr)
+
+/*
+ * PK packed number encoding. Nybbles in [1..dyn_f] represent themselves.
+ * Values in (dyn_f..13] are two-nybble values, and represent values
+ * dyn_f+1 through (13-dyn_f+1)*16+15. Zero marks a long number; 14 and
+ * 15 specify repeat counts instead (which are another packed number).
+ * Note that we cannot represent the number zero as a packed number.
+ */
+#define PK_LONGNUM 0 /* a `long number' */
+#define PK_REPEAT 14 /* set repeat count */
+#define PK_REPEAT1 15 /* set repeat to 1 */
+
+/*
+ * Get the next nybble. This is an expression rendition of
+ * if (--pk->pk_1nyb < 0) {
+ * pk->pk_1nyb = 1;
+ * pk->pk_c = nextbyte(pk);
+ * return (pk->pk_c >> 4);
+ * } else
+ * return (pk->pk_c & 0xf);
+ */
+#define nextnyb(f) \
+ (--(pk)->pk_1nyb < 0 ? \
+ ((pk)->pk_1nyb = 1, ((pk)->pk_c = nextbyte(pk)) >> 4) : \
+ (pk)->pk_c & 0xf)
+
+/*
+ * Get the pk_details from font f.
+ */
+#define ftopk(f) ((struct pk_details *) (f)->f_details)
+
+extern int errno;
+char *malloc();
+
+/*
+ * PK subroutines.
+ */
+
+/*
+ * Unpack a packed number.
+ */
+static int
+pk_unpack(pk)
+ register struct pk_details *pk;
+{
+ register int i, j;
+
+top:
+ if ((i = nextnyb(pk)) == PK_LONGNUM) {
+#if PK_LONGNUM != 0 /* this may be silly, but . . . */
+ i = 0;
+#endif
+ /*
+ * Expand a long number. There are one fewer leading
+ * zeros than there are nonzero digits to obtain, so
+ * count up the leading zeros, add one, and get that
+ * many digits. (The `digits' are hexadecimal values.)
+ */
+ do {
+ i++;
+ } while ((j = nextnyb(pk)) == 0);
+ while (--i >= 0) {
+ j <<= 4;
+ j += nextnyb(pk);
+ }
+ return (j - 15 + (13 - pk->pk_dyn_f) * 16 + pk->pk_dyn_f);
+ }
+ if (i <= pk->pk_dyn_f)
+ return (i);
+ if (i < PK_REPEAT)
+ return ((i - pk->pk_dyn_f - 1) * 16 + nextnyb(pk) +
+ pk->pk_dyn_f + 1);
+
+ /*
+ * There is a repeat count, either one or a packed number.
+ * Get it first, then start over. (tail recursion)
+ */
+ if (i == PK_REPEAT)
+ pk->pk_repeat = pk_unpack(pk);
+ else
+ pk->pk_repeat = 1;
+ goto top;
+}
+
+/*
+ * Skip over special commands (PK_XXX?, PK_YYY).
+ */
+static
+skip_specials(f)
+ struct font *f;
+{
+ struct pk_details *pk = ftopk(f);
+ register char *p = pk->pk_ptr;
+ register i32 i;
+
+ for (;;) {
+ switch (UnSign8(*p++)) {
+
+ case PK_XXX1:
+ i = UnSign8(*p++);
+ p += i;
+ break;
+
+ case PK_XXX2:
+ pGetWord(p, i);
+ p += i;
+ break;
+
+ case PK_XXX3:
+ pGet3Byte(p, i);
+ p += i;
+ break;
+
+ case PK_XXX4:
+ pGetLong(p, i);
+ p += i;
+ break;
+
+ case PK_YYY:
+ p += 4;
+ break;
+
+ case PK_NO_OP:
+ break;
+
+ case PK_PRE:
+ error(1, 0, "unexpected PK_PRE in \"%s\"", f->f_path);
+ break;
+
+ default:
+ p--;
+ if (PK_IsUndef(UnSign8(*p)))
+ error(1, 0, "invalid opcode %d in \"%s\"",
+ f->f_path);
+ pk->pk_ptr = p;
+ return;
+ }
+ }
+}
+
+/*
+ * Read a PK file.
+ */
+static int
+pk_read(f)
+ register struct font *f;
+{
+ register struct pk_details *pk;
+ register char *p;
+ int i, fd, minc;
+ struct stat st;
+ char *reason;
+
+ if ((fd = open(f->f_path, 0)) < 0)
+ return (-1);
+ pk = NULL; /* prepare for failure */
+ reason = NULL;
+ (void) fstat(fd, &st);
+ if (st.st_size < 4) { /* ??? */
+ reason = "file is too small";
+ goto fail;
+ }
+ if ((pk = (struct pk_details *) malloc(sizeof (*pk))) == NULL)
+ goto fail;
+ pk->pk_morec = NULL;
+ if ((pk->pk_base = malloc(st.st_size)) == NULL)
+ goto fail;
+ if (read(fd, pk->pk_base, st.st_size) != st.st_size)
+ goto fail;
+ pk->pk_ptr = pk->pk_base;
+ if (nextbyte(pk) != PK_PRE) {
+ reason = "file does not begin with PK_PRE";
+ goto fail;
+ }
+ if (nextbyte(pk) != PK_ID) {
+ reason = "bad PK_ID";
+ goto fail;
+ }
+ i = nextbyte(pk);
+ p = pk->pk_ptr + i + 4; /* skip comment and design size */
+ pGetLong(p, f->f_checksum);
+ pk->pk_ptr = p + 4 + 4; /* skip hppp, vppp */
+
+ f->f_details = (char *) pk;
+
+ /* scan the characters, fail if necessary */
+ if (scan_characters(f, &reason))
+ goto fail;
+
+ /* ignore the postamble */
+
+ /* COMPRESS pk->pk_base DATA? */
+
+ if (FontHasGlyphs(f, pk->pk_minc, pk->pk_maxc + 1))
+ goto fail;
+ (void) close(fd);
+ return (0);
+
+fail:
+ if (reason) {
+ error(0, 0, "%s", reason);
+ error(0, 0, "(are you sure %s is a PK file?)", f->f_path);
+ errno = 0;
+ }
+ if (pk != NULL) {
+ if (pk->pk_base != NULL)
+ free(pk->pk_base);
+ if (pk->pk_morec != NULL)
+ free((char *) pk->pk_morec);
+ free((char *) pk);
+ }
+ (void) close(fd);
+ return (-1);
+}
+
+/*
+ * Scan through the characters in the PK file, and set the offsets
+ * and preamble types for each of the character packets.
+ */
+static int
+scan_characters(f, reason)
+ struct font *f;
+ char **reason;
+{
+ register struct pk_details *pk = ftopk(f);
+ register i32 c, pl;
+ register char *p;
+ register struct cp *cp;
+ int type;
+
+#ifdef lint
+ /* reason will be used someday ... I think */
+ reason = reason;
+#endif
+
+ /* set up the minimisers and the glyph count */
+ pk->pk_minc = 1;
+ pk->pk_maxc = 0;
+ pk->pk_gleft = 0;
+
+ /* mark all character packets as untouched */
+ for (cp = pk->pk_cpack, c = MAXSTD; --c >= 0; cp++)
+ cp->cp_packet = NULL;
+
+ /*
+ * Loop through the packets until we reach a POST, skipping
+ * the glyph instructions themselves after each definition,
+ * and specials (if any) before each.
+ */
+ for (;; pk->pk_ptr = p + pl) {
+ skip_specials(f);
+ p = pk->pk_ptr;
+ if ((c = pgetbyte(p)) == PK_POST)
+ break; /* whoops, done after all */
+
+ /*
+ * Look at the low three bits to decide preamble size.
+ * A value of 7 is a `long preamble'; 4, 5, and 6 are
+ * `extended short preambles'; and 0, 1, 2, and 3 are
+ * `short preambles'.
+ *
+ * We ignore most of the preamble, reading only the
+ * `packet length' and the character code at this time.
+ */
+ switch (c & 7) {
+
+ case 7: /* long */
+ type = CP_LONG;
+ pGetLong(p, pl);
+ pGetLong(p, c);
+ break;
+
+ case 6:
+ case 5:
+ case 4: /* extended short */
+ type = CP_EXT_SHORT;
+ pGetWord(p, pl);
+ pl += (c & 3) << 16;
+ c = pgetbyte(p);
+ break;
+
+ default: /* short */
+ type = CP_SHORT;
+ pl = ((c & 3) << 8) + pgetbyte(p);
+ c = pgetbyte(p);
+ break;
+ }
+
+ if (c >= MAXSTD) {
+ /*
+ * BEGIN XXX - should alloc pk_morec, but is hard
+ * and not now useful
+ */
+ error(0, 0, "ignoring character %d in \"%s\"",
+ f->f_path);
+ error(0, 0, "because some darn programmer was lazy!");
+ continue;
+ /* END XXX */
+ } else
+ cp = &pk->pk_cpack[c];
+
+ cp->cp_packet = pk->pk_ptr;
+ cp->cp_type = type;
+
+ /* adjust range */
+ if (c < pk->pk_minc)
+ pk->pk_minc = c;
+ if (c > pk->pk_maxc)
+ pk->pk_maxc = c;
+
+ pk->pk_gleft++; /* and count the glyph */
+ }
+ return (0); /* no problems */
+}
+
+/*
+ * Obtain the specified range of glyphs.
+ */
+static int
+pk_getgly(f, l, h)
+ register struct font *f;
+ int l, h;
+{
+ register struct pk_details *pk = ftopk(f);
+ register char *p;
+ register struct glyph *g;
+ register int i;
+ register struct cp *cp;
+
+ if (pk == NULL)
+ panic("pk_getgly(%s)", f->f_path);
+ for (i = l; i < h; i++) {
+ if (i < MAXSTD)
+ cp = &pk->pk_cpack[i];
+ else {
+ if (i > pk->pk_maxc)
+ panic("pk_getgly(%s, %d)", f->f_path, i);
+ cp = &pk->pk_morec[i - MAXSTD];
+ }
+ p = cp->cp_packet;
+ if (p == NULL) /* glyph is not valid */
+ continue;
+ g = f->f_gly[i];
+ p++; /* skip flag */
+ switch (cp->cp_type) {
+
+ case CP_LONG:
+ p += 8; /* skip packet len, character code */
+ pGetLong(p, g->g_tfmwidth);
+#ifdef notyet
+ pGetLong(p, g->g_xescapement);
+ pGetLong(p, g->g_yescapement);
+#else
+ p += 8;
+#endif
+ pGetLong(p, g->g_width);
+ pGetLong(p, g->g_height);
+ pGetLong(p, g->g_xorigin);
+ pGetLong(p, g->g_yorigin);
+ break;
+
+ case CP_EXT_SHORT:
+ p += 3; /* skip packet len, character code */
+ pGet3Byte(p, g->g_tfmwidth);
+#ifdef notyet
+ { i32 dm; pGetWord(p, dm);
+ g->g_xescapement = dm << 16; }
+ g->g_yescapement = 0;
+#else
+ p += 2; /* skip dm */
+#endif
+ pGetWord(p, g->g_width);
+ pGetWord(p, g->g_height);
+ pGetWord(p, g->g_xorigin);
+ g->g_xorigin = Sign16(g->g_xorigin);
+ pGetWord(p, g->g_yorigin);
+ g->g_yorigin = Sign16(g->g_yorigin);
+ break;
+
+ case CP_SHORT:
+ p += 2; /* skip packet len, character code */
+ pGet3Byte(p, g->g_tfmwidth);
+#ifdef notyet
+ g->g_xescapement = pgetbyte(p) << 16;
+ g->g_yescapement = 0;
+#else
+ p++; /* skip dm */
+#endif
+ g->g_width = pgetbyte(p);
+ g->g_height = pgetbyte(p);
+ g->g_xorigin = pgetbyte(p);
+ g->g_xorigin = Sign8(g->g_xorigin);
+ g->g_yorigin = pgetbyte(p);
+ g->g_yorigin = Sign8(g->g_yorigin);
+ break;
+ }
+ g->g_flags = GF_VALID;
+ g->g_un.g_details = p;
+ }
+ return (0);
+}
+
+/*
+ * Bit masks for pk_rasterise().
+ */
+static char bmask[8] = {0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe};
+static char rbits[9] = {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
+
+/*
+ * Obtain rasters for the specified glyphs.
+ */
+static int
+pk_rasterise(f, l, h)
+ struct font *f;
+ int l, h;
+{
+ struct pk_details *pk0;
+ struct glyph *g0;
+ char *p0, *rp0;
+ int flag, ii;
+
+ if ((pk0 = ftopk(f)) == NULL)
+ panic("pk_rasterise(%s)", f->f_path);
+ for (ii = l; ii < h; ii++) {
+ {
+ register struct glyph *g;
+ register char *p;
+ register int i;
+
+ g = f->f_gly[i = ii];
+ if ((g->g_flags & GF_VALID) == 0)
+ continue; /* no glyph */
+ if (!HASRASTER(g)) /* empty raster */
+ goto done;
+
+ /*
+ * Allocate a raster.
+ */
+ rp0 = malloc(((g->g_width + 7) >> 3) * g->g_height);
+ if ((g->g_raster = rp0) == NULL)
+ return (-1);/* ??? */
+ g->g_rotation = ROT_NORM;
+
+ /*
+ * Pick up the flag byte, then start at the real
+ * packet, which we saved in g_details.
+ */
+ if (i < MAXSTD)
+ p = pk0->pk_cpack[i].cp_packet;
+ else
+ p = pk0->pk_morec[i - MAXSTD].cp_packet;
+ flag = UnSign8(*p);
+ p0 = g->g_un.g_details;
+ g0 = g;
+ }
+ if ((pk0->pk_dyn_f = flag >> 4) == 14) {
+ register char *p = p0, *rp = rp0;
+ register int j, ls, rs, i, w;
+
+ /*
+ * Expand a bit-packed representation.
+ * If we get lucky, it is byte packed and
+ * we can just copy it over.
+ */
+ i = g0->g_height;
+ j = g0->g_width;
+ if ((j & 7) == 0) {
+ bcopy(p, rp, i * (j >> 3));
+ goto done;
+ }
+
+ /*
+ * No such luck.
+ */
+ w = j;
+ ls = 0;
+ while (--i >= 0) {
+#if defined(vax) && !defined(lint)
+ /* have to work on the compiler someday */
+ rs = ls - 8;
+#else
+ rs = 8 - ls;
+#endif
+ /* know j always != 8 */
+ for (j = w; j > 8; j -= 8) {
+#if defined(vax) && !defined(lint)
+ asm(" movb (r11)+,r0");
+ asm(" ashl r8,r0,r0");
+ asm(" movb r0,(r10)");
+ asm(" movzbl (r11),r0");
+ asm(" ashl r7,r0,r0");
+ asm(" bisb2 r0,(r10)+");
+#else
+ *rp = *p++ << ls;
+ *rp++ |= UnSign8(*p) >> rs;
+#endif
+ }
+
+ /*
+ * We need j more bits; there are rs
+ * bits available at *p. Ask for j,
+ * which gets min(j, rs).
+ */
+#if defined(vax) && !defined(lint)
+ /*void*/; /* avoid asm() label botch */
+ asm(" movb (r11),r0");
+ asm(" ashl r8,r0,r0");
+ asm(" mcomb _bmask[r9],r1");
+ asm(" bicb2 r1,r0");
+ asm(" movb r0,(r10)+");
+#else
+ *rp++ = (*p << ls) & bmask[j];
+#endif
+ /* account for j bits */
+ ls += j; ls &= 7;
+ /* then adjust j based on rs */
+#if defined(vax) && !defined(lint)
+ j += rs;
+#else
+ j -= rs;
+#endif
+ /* still need j more bits */
+ if (j < 0) /* got them all */
+ continue;
+ p++;
+ if (j == 0) /* there were just enough */
+ continue;
+ /* take j more bits */
+#if defined(vax) && !defined(lint)
+ /*void*/; /* avoid asm() label botch */
+ asm(" mcomb _bmask[r9],r0");
+ asm(" bicb3 r0,(r11),r0");
+ asm(" movzbl r0,r0");
+ asm(" ashl r7,r0,r0");
+ asm(" bisb2 r0,-1(r10)");
+#else
+ rp[-1] |= UnSign8(*p & bmask[j]) >> rs;
+#endif
+ }
+ } else {
+ register struct pk_details *pk = pk0;
+ register int on = flag & 8 ? 0xff : 0;
+ register char *rowp; /* pointer into this row */
+ register int j; /* trimmed run count */
+ register int k; /* misc */
+ register int b; /* bit index in current col */
+ register int i; /* run count */
+ register int colsleft; /* columns left this row */
+ register int rowsleft; /* rows left */
+ static char *row; /* a one-row buffer */
+ static int rowsize; /* and its size in bytes */
+ int wb; /* row width in bytes */
+
+ wb = (g0->g_width + 7) >> 3;
+ if (rowsize < wb) { /* get more row space */
+ if (row)
+ free(row);
+ /* keep a slop byte */
+ row = malloc((unsigned) (wb + 1));
+ if (row == NULL)
+ return (-1); /* ??? */
+ rowsize = wb;
+ }
+ bzero(row, wb);
+ rowsleft = g0->g_height;
+ colsleft = g0->g_width;
+ pk->pk_repeat = 0;
+ pk->pk_ptr = p0;
+ pk->pk_1nyb = 0; /* start on nybble 0 */
+ rowp = row;
+ b = 0;
+ while (rowsleft > 0) { /* do all rows */
+ /* EXPAND IN LINE? */
+ i = pk_unpack(pk);
+ /*
+ * Work until the run count is exhausted
+ * (or at least pretty tired).
+ *
+ * (Okay, so the joke is stolen!)
+ */
+ while ((j = i) > 0) {
+ /*
+ * If the count is more than the
+ * rest of this row, trim it down.
+ */
+ if (j > colsleft)
+ j = colsleft;
+ i -= j; /* call them done */
+ /*
+ * We need k=8-b bits to finish
+ * up the current byte. If we
+ * can finish it, do so; the proper
+ * bits to set are in rbits[k].
+ */
+ if (j >= (k = 8 - b)) {
+ j -= k;
+ colsleft -= k;
+ *rowp++ |= on & rbits[k];
+ b = 0;
+ }
+ /*
+ * Set any full bytes.
+ */
+ while (j >= 8) {
+ *rowp++ = on;
+ j -= 8;
+ colsleft -= 8;
+ }
+ /*
+ * Finally, begin a new byte, or
+ * add to the current byte, with
+ * j more bits. We know j <= 8-b.
+ * (If j==0, we may be writing on
+ * our slop byte, which is why we
+ * keep one around....)
+ */
+if (j > 8-b) panic("pk_rasterise j>8-b");
+ *rowp |= (on & bmask[j]) >> b;
+ colsleft -= j;
+ b += j; b &= 7;
+ if (colsleft == 0) {
+ pk->pk_repeat++;
+ rowsleft -= pk->pk_repeat;
+ while (--pk->pk_repeat >= 0) {
+ bcopy(row, rp0, wb);
+ rp0 += wb;
+ }
+if (rowsleft == 0 && i) panic("pk_rasterise leftover bits");
+ pk->pk_repeat = 0;
+ rowp = row;
+ colsleft = g0->g_width;
+ bzero(row, wb);
+ b = 0;
+ }
+ }
+ on = 0xff - on;
+ }
+ }
+
+done:
+ /*
+ * Successfully converted another glyph.
+ */
+ pk0->pk_gleft--;
+ }
+
+if (pk0->pk_gleft < 0)
+panic("%s: gleft==%d", f->f_path, pk0->pk_gleft);
+ if (pk0->pk_gleft == 0) {
+ free(pk0->pk_base);
+ if (pk0->pk_morec != NULL)
+ free((char *) pk0->pk_morec);
+ free((char *) pk0);
+ f->f_details = NULL;
+ }
+ return (0);
+}
+
+/*
+ * Discard the font details.
+ */
+static
+pk_freefont(f)
+ struct font *f;
+{
+ register struct pk_details *pk = ftopk(f);
+
+ if (pk != NULL) {
+ free(pk->pk_base);
+ if (pk->pk_morec != NULL)
+ free((char *) pk->pk_morec);
+ free((char *) pk);
+ }
+}
diff --git a/dviware/umddvi/lib/pxlfont.c b/dviware/umddvi/lib/pxlfont.c
new file mode 100644
index 0000000000..76fc15fc41
--- /dev/null
+++ b/dviware/umddvi/lib/pxlfont.c
@@ -0,0 +1,301 @@
+/*
+ * Copyright (c) 1987 University of Maryland Department of Computer Science.
+ * All rights reserved. Permission to copy for any purpose is hereby granted
+ * so long as this copyright notice remains intact.
+ */
+
+#ifndef lint
+static char rcsid[] = "$Header: pxlfont.c,v 2.4 87/06/16 18:28:39 chris Exp $";
+#endif
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include "types.h"
+#include "font.h"
+#include "fio.h"
+
+/*
+ * PXL font operations.
+ */
+int pxl_read(), pxl_getgly(), pxl_rasterise(), pxl_freefont();
+
+struct fontops pxlops =
+ { "pxl", 5.0, pxl_read, pxl_getgly, pxl_rasterise, pxl_freefont };
+
+/*
+ * Local info.
+ */
+#define PXLID 1001 /* ID denoting PXL files */
+#define TAILSIZE (517 * 4) /* size of pxl tail info */
+
+/*
+ * pc describes one PXL character information block.
+ */
+struct pc {
+ i16 pc_width; /* character width (pixels) */
+ i16 pc_height; /* character height (pixels) */
+ i16 pc_xoffset; /* X offset of reference point */
+ i16 pc_yoffset; /* Y offset of reference point */
+ i32 pc_rastoff; /* raster offset */
+ i32 pc_TFMwidth; /* TFM width (FIXes) */
+};
+
+/*
+ * pxl_details are the PXL-specific font details.
+ *
+ * We keep track of the number of characters converted to internal
+ * glyph form, and when all have been done, we discard the now-
+ * useless details.
+ */
+struct pxl_details {
+ int pd_nconv; /* number of characters converted */
+ char *pd_ras; /* raster space, until converted */
+ struct pc pd_pc[128]; /* `font directory' */
+};
+
+/*
+ * Get the pxl_details from font f.
+ */
+#define ftopd(f) ((struct pxl_details *) (f)->f_details)
+
+extern errno;
+char *malloc();
+
+/*
+ * Read a PXL file.
+ */
+static int
+pxl_read(f)
+ struct font *f;
+{
+ register struct pxl_details *pd;
+ register FILE *fp;
+ register struct pc *pc;
+ register int i;
+ int fd, saverr;
+ i32 pxlid;
+ struct stat st;
+
+ if ((fd = open(f->f_path, 0)) < 0)
+ return (-1);
+
+ fp = NULL;
+ if ((pd = (struct pxl_details *) malloc(sizeof (*pd))) == 0)
+ goto fail;
+ pd->pd_ras = 0;
+
+ /*
+ * There should be 4n bytes, with an absolute minimum of TAILSIZE+4
+ * (+4 for the initial PXLID).
+ */
+ (void) fstat(fd, &st);
+ if ((st.st_size & 3) != 0 || st.st_size < (TAILSIZE + 4)) {
+ errno = EINVAL;
+ goto fail;
+ }
+
+ /*
+ * Set up the raster pointer (if we need rasters).
+ */
+ if (f->f_flags & FF_RASTERS) {
+ i = st.st_size - (TAILSIZE + 4);
+ if (i != 0) {
+ if ((pd->pd_ras = malloc((unsigned) i)) == 0)
+ goto fail;
+ (void) lseek(fd, 4L, 0);
+ if (read(fd, pd->pd_ras, i) != i)
+ goto fail;
+ }
+ }
+
+ /*
+ * Read the glyph information.
+ */
+ errno = 0; /* try to make errno meaningful */
+ if ((fp = fdopen(fd, "r")) == NULL) {
+ if (errno == 0)
+ errno = EMFILE;
+ goto fail;
+ }
+ (void) fseek(fp, (long) -TAILSIZE, 2);
+ for (i = 128, pc = pd->pd_pc; --i >= 0; pc++) {
+ fGetWord(fp, pc->pc_width);
+ fGetWord(fp, pc->pc_height);
+ fGetWord(fp, pc->pc_xoffset);
+ fGetWord(fp, pc->pc_yoffset);
+ fGetLong(fp, pc->pc_rastoff);
+ fGetLong(fp, pc->pc_TFMwidth);
+ }
+ f->f_checksum = GetLong(fp);
+ (void) GetLong(fp); /* mag */
+ (void) GetLong(fp); /* designsize */
+ (void) GetLong(fp); /* dirpointer */
+ pxlid = GetLong(fp);
+ if (pxlid != PXLID)
+ error(0, 0, "Warning: strange PXL id (%d) in \"%s\"",
+ pxlid, f->f_path);
+
+ f->f_details = (char *) pd;
+ if (FontHasGlyphs(f, 0, 128))
+ goto fail;
+ (void) fclose(fp);
+ pd->pd_nconv = 0;
+ return (0);
+
+fail:
+ saverr = errno;
+ if (pd) {
+ if (pd->pd_ras)
+ free(pd->pd_ras);
+ free((char *) pd);
+ }
+ if (fp)
+ (void) fclose(fp);
+ else
+ (void) close(fd);
+ errno = saverr;
+ return (-1);
+}
+
+/*
+ * Obtain the specified range of glyphs.
+ */
+static int
+pxl_getgly(f, l, h)
+ register struct font *f;
+ int l;
+ register int h;
+{
+ register struct glyph *g;
+ register struct pc *pc;
+ register int i;
+ struct pxl_details *pd;
+
+ if ((pd = ftopd(f)) == NULL)
+ error(1, 0, "pxl_getgly details==0: cannot happen");
+ /*
+ * By definition, all 128 glyphs are valid. Just copy the
+ * PXL information.
+ */
+ for (pc = &pd->pd_pc[i = l]; i < h; i++, pc++) {
+ g = f->f_gly[i];
+ g->g_flags = GF_VALID;
+ g->g_height = pc->pc_height;
+ g->g_width = pc->pc_width;
+ g->g_yorigin = pc->pc_yoffset;
+ g->g_xorigin = pc->pc_xoffset;
+ g->g_tfmwidth = pc->pc_TFMwidth;
+ }
+ return (0);
+}
+
+/*
+ * Helper function for rasterise: return a pointer to a converted
+ * (malloc()ed and minimised) raster.
+ */
+static char *
+makeraster(h, w, rp)
+ register int h, w;
+ register char *rp;
+{
+ register char *cp;
+ register int i, o;
+ char *rv;
+
+ /*
+ * The height and width values are in bits. Convert width to
+ * bytes, rounding up. The raw raster (at rp) is almost what
+ * we want, but not quite: it has `extra' bytes at the end of
+ * each row, to pad out to a multiple of four bytes.
+ */
+ w = (w + 7) >> 3;
+ o = (4 - w) & 3; /* offset (number of `extra' bytes) */
+ if ((cp = malloc((unsigned) (h * w))) == NULL)
+ return (NULL);
+ if (o == 0) {
+ /*
+ * The raster fits exactly; just copy it to the allocated
+ * memory space. (We must copy anyway, so that glyphs
+ * can be freed, e.g., after rotation.)
+ */
+ bcopy(rp, cp, h * w);
+ return (cp);
+ }
+ rv = cp;
+ while (--h >= 0) {
+ /*
+ * Copy each row, then skip over the extra stuff.
+ */
+ for (i = w; --i >= 0;)
+ *cp++ = *rp++;
+ rp += o;
+ }
+ return (rv);
+}
+
+/*
+ * Obtain rasters for the specified glyphs.
+ */
+static int
+pxl_rasterise(f, l, h)
+ register struct font *f;
+ int l;
+ register int h;
+{
+ register struct glyph *g;
+ register struct pc *pc;
+ register int i;
+ register struct pxl_details *pd;
+
+ if ((pd = ftopd(f)) == NULL)
+ error(1, 0, "pxl_rasterise details==0: cannot happen");
+ if (pd->pd_ras == NULL)
+ error(1, 0, "pxl_rasterise pd_ras==NULL: cannot happen");
+ for (pc = &pd->pd_pc[i = l]; i < h; i++, pc++) {
+ g = f->f_gly[i];
+ if (pc->pc_rastoff == 0) {
+ /*
+ * g should not claim a raster, since it has none.
+ */
+ if (HASRASTER(g))
+ error(1, 0, "bad PXL glyph %d in \"%s\"",
+ g->g_index, f->f_path);
+ } else {
+ g->g_raster = makeraster(pc->pc_height, pc->pc_width,
+ pd->pd_ras + ((pc->pc_rastoff - 1) << 2));
+ if (g->g_raster == NULL)
+ return (-1); /* ??? */
+ g->g_rotation = ROT_NORM;
+ }
+ }
+
+ /*
+ * If we have converted all the characters, dump the
+ * pre-conversion rasters. In fact, dump everything.
+ */
+ pd->pd_nconv += h - l;
+ if (pd->pd_nconv == 128) {
+ free(pd->pd_ras);
+ free((char *) pd);
+ f->f_details = NULL;
+ }
+ return (0);
+}
+
+/*
+ * Discard the font details.
+ */
+static
+pxl_freefont(f)
+ struct font *f;
+{
+ struct pxl_details *pd;
+
+ if ((pd = ftopd(f)) != NULL) {
+ if (pd->pd_ras != NULL)
+ free(pd->pd_ras);
+ free((char *) pd);
+ }
+}
diff --git a/dviware/umddvi/lib/readme b/dviware/umddvi/lib/readme
new file mode 100644
index 0000000000..521f2dedad
--- /dev/null
+++ b/dviware/umddvi/lib/readme
@@ -0,0 +1,248 @@
+This directory is for library routines. They are hopefully now 99%
+portable, but only time (and new machines) will tell.
+
+File Functions
+----------------------------------------------------------------------
+bcopy.s bcopy(from, to, count)
+ char *from, *to;
+ int count;
+
+ Copies `count' bytes from location `from' to
+ location `to'
+----------------------------------------------------------------------
+bzero.s bzero(addr, count)
+ char *addr;
+ int count;
+
+ Zeroes `count' bytes starting at location `addr'
+----------------------------------------------------------------------
+error.c error(quit, errno, fmt, arg1, arg2, ...)
+ int quit, errno;
+ char *fmt;
+
+ Prints the message in `fmt' to stderr as would
+ fprintf, along with the (optional) system error
+ associated with `errno'. If `quit' is nonzero,
+ does an exit(quit). Give 0 for errno to suppress
+ the system error part.
+----------------------------------------------------------------------
+findpost.c FindPostAmble(f)
+ FILE *f;
+
+ Repositions the file `f' (using fseek(3S)) to
+ the beginning of the postamble, such that the next
+ getc from f should return DVI_POST.
+
+ Returns 0 if successful, -1 otherwise.
+----------------------------------------------------------------------
+fio.c GetLong(f)
+[See also FILE *f;
+../h/fio.h]
+ Gets a `long' from file `f' in the format written
+ by PutLong. [This should actually be an `i32'
+ function but I am too lazy to go fix that now.]
+ ------------------------------------------------------
+ Get3Byte(f)
+ FILE *f;
+
+ Gets a 3 byte integer from file `f' in the format
+ written by Put3Byte. The value is sign extended.
+ ------------------------------------------------------
+ GetWord(f)
+ FILE *f;
+
+ Gets a 2 byte integer from file `f'. The value is
+ sign extended.
+ ------------------------------------------------------
+ GetByte(f)
+ FILE *f;
+
+ Gets a 1 byte integer from file `f'. The value is
+ sign extended.
+
+ All of these have counterparts in ../h/fio.h which
+ may be used in speed-critical routines. However, these
+ differ from the fGet* versions in that:
+ + these check for EOF (and call error if found);
+ + these sign extend their return values.
+----------------------------------------------------------------------
+getopt.c extern char *optarg;
+[From Henry extern int optind;
+Spencer @
+U of Toronto int
+Zoology] getopt(argc, argv, optstring)
+ int argc;
+ char **argv;
+ char *optstring;
+
+ `argv' and `argc' should be those given to main().
+ getopt scans command line arguments according to the
+ string in `optstring'. Arguments are considered to
+ start with `-'. A quick example:
+
+ switch (getopt(argc, argv, "bco:s:")) {
+ case 'b': ...
+
+ would allow the options `-b', `-c', `-o argument', and
+ and `-s argument', and would return 'b', 'c', 'o', or
+ 's', if one of those were specified. If getopt runs out
+ of arguments, it returns EOF; if it encounters an invalid
+ option letter (e.g., `-z' in this example) it returns '?'.
+
+ If the option has an argument, getopt leaves `optarg'
+ pointing to it.
+
+ After getopt returns EOF, the remaining arguments (if
+ any) are in argv[optind] through argv[argc - 1].
+----------------------------------------------------------------------
+***deprecated***
+machint.s machint(addr, count)
+ int *addr;
+ int count;
+
+ Converts `count' 4 byte integers at location `addr'
+ to machine order. This is used to convert arrays of
+ integers in the order generated and written by PutLong
+ and GetLong to and from machine order.
+----------------------------------------------------------------------
+***deprecated***
+machintnop.c machint(addr, count)
+ int *addr;
+ int count;
+
+ No-op version for Suns & Pyramids.
+----------------------------------------------------------------------
+***deprecated***
+pxl.c double DMagFactor(magfactor)
+ int magfactor;
+
+ Returns magfactor/1000.0, with some extra fiddling
+ to get more precise values for the various \magstep's
+ that are commonly used.
+ ------------------------------------------------------
+ char *GenPXLFileName(nm, mag, designsize, globalmag, path)
+ char *nm;
+ int mag, designsize, globalmag;
+ char *path;
+
+ Returns (in static storage) the name of the PXL
+ file given the name of the font `nm', the DVI
+ magnification (`at size') `mag', the design
+ size `designsize', an additional magnification
+ of `globalmag/1000.0', and the assumed path
+ `path'. If path is zero (or *path is 0), the
+ constant PXLPATH (from ../h/pxl.h) is used instead.
+ `Path' should normally be the value of the
+ environment variable ``TEXFONTS''.
+ ------------------------------------------------------
+ struct pxltail *ReadPXLFile(nm, getrast)
+ char *nm;
+ int getrast;
+
+ Reads the named PXL file and returns a pointer to
+ a built-up struct pxltail. `Nm' should be the
+ name as returned by GenPXLFileName. If `getrast'
+ is nonzero, the character rasters will also be
+ read in, and the raster pointers in the chinfo
+ structures will be set to point to each character's
+ raster (or to 0 if the raster is completely blank).
+----------------------------------------------------------------------
+***XXX***
+rotate.c PerformRotation(ch, deg)
+ struct chinfo *ch;
+ int deg;
+
+ Rotates the bitmap of the character `ch', and
+ exchanges the height and width fields so that the
+ new bitmap is indistinguishable from the original
+ as far as those values are concerned. `deg' is
+ the number of degrees of rotation desired and must
+ be a multiple of 90. Currently only -90 (and 270)
+ degree rotations are supported (this is one quarter
+ turn clockwise).
+
+ The rotation is done in place.
+
+ In general, this should only be used in the final
+ output stages of a device that needs `landscape
+ mode' output.
+----------------------------------------------------------------------
+***XXX***
+scaletfm.c ScaleTFMWidths(px, z)
+ struct pxltail *px;
+ i32 z;
+
+ Scales all the TFM widths in px->px_info according to
+ the scale factor `z', which should be the `at size'
+ from a DVI file (i.e., a number in scaled points).
+
+ i32 ScaleOneWidth(width, z)
+ i32 width, z;
+
+ Scales the (single) TFM width `width' by `z'.
+----------------------------------------------------------------------
+scanpost.c ScanPostAmble(f, headerfunc, fontfunc)
+ FILE *f;
+ int (*headerfunc)(), (*fontfunc)();
+
+ Scans the postamble of a DVI file. The given functions
+ are called with the information gleaned from reading the
+ postamble. Headerfunc is called once, and fontfunc once
+ per font definition.
+
+ See ../h/postamble.h for the definitions of the
+ parameters passed to the two functions.
+----------------------------------------------------------------------
+search.c struct search *SCreate(dsize)
+ unsigned dsize;
+
+ Creates a search table; keys are i32 integers, data
+ objects are of size dsize and of unspecified type. A
+ null pointer is returned if the table cannot be created.
+
+ SEnumerate(table, func)
+ struct search *table;
+ int (*func)();
+
+ Invokes the given function on each object in the table.
+ The function is handed a "char *" pointer to the objects
+ as its first argument and the i32 key as its second.
+ (The return value from (*func)(), if any, is ignored;
+ technically it should be void (*func)(), but that is
+ not implemented quite right in many Unix compilers...)
+
+ char *SSearch(table, key, disp)
+ struct search *table;
+ i32 key;
+ int *disp;
+
+ Searches for a given key within the given search
+ table. A number of dispositions can be specified;
+ see ../h/search.h for the flags that can be specified
+ in *disp. *disp is modified before return to set
+ the reason for the search success or failure. The
+ return value is a pointer to the user data area
+ for the given key if found, otherwise NULL.
+
+ WARNING: data areas may move on future searches that
+ create new data objects.
+----------------------------------------------------------------------
+seek.c int Seekable(fd)
+ int fd;
+
+ Returns true iff the Unix file fd is randomly
+ accessible. (In particular, pipes are not.)
+
+ int MakeSeekable(f)
+ FILE *f;
+
+ If the stdio file f is not seekable, MakeSeekable
+ forces it to be so, by copying it to a temporary
+ file. MakeSeekable returns zero on success; -1
+ indicates failure.
+----------------------------------------------------------------------
+strsave.c char *strsave(s)
+ char *s;
+
+ Saves a malloc()ed copy of the C string s. (Beware:
+ exits if out of memory.)
diff --git a/dviware/umddvi/lib/rotate.c b/dviware/umddvi/lib/rotate.c
new file mode 100644
index 0000000000..3107ca986f
--- /dev/null
+++ b/dviware/umddvi/lib/rotate.c
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 1987 University of Maryland Department of Computer Science.
+ * All rights reserved. Permission to copy for any purpose is hereby granted
+ * so long as this copyright notice remains intact.
+ */
+
+#ifndef lint
+static char rcsid[] = "$Header: rotate.c,v 2.3 87/06/16 18:28:45 chris Exp $";
+#endif
+
+/*
+ * Routines to generate rotated bitmaps given unrotated inputs.
+ *
+ * The rotated bitmap is indistinguishable from the unrotated one (aside
+ * from being rotated of course!).
+ */
+
+#include "font.h"
+
+extern int errno;
+
+char *malloc();
+
+/*
+ * Rounding, but by powers of two only.
+ */
+#define ROUND(n,r) (((n) + ((r) - 1)) & ~((r) - 1))
+
+/*
+ * Set the rotation of glyph g to r.
+ */
+SetRotation(g, r)
+ register struct glyph *g;
+ int r;
+{
+
+ if (r < ROT_NORM || r > ROT_RIGHT)
+ error(1, 0, "bad rotation value %d", r);
+
+ /*
+ * The null glyph is trivial to rotate by any amount.
+ *
+ * Note that this assumes that any raster has been obtained
+ * BEFORE calling SetRotation()!
+ */
+ if (g->g_raster == NULL) {
+ g->g_rotation = r;
+ return;
+ }
+
+ /*
+ * This is hardly efficient, but it *is* expedient....
+ */
+ while (g->g_rotation != r) {
+ RotateClockwise(g);
+ g->g_rotation = (g->g_rotation - 1) & 3;
+ }
+}
+
+/*
+ * Rotation by 1/4 turn clockwise (from ROT_NORM to ROT_RIGHT, e.g.).
+ */
+static
+RotateClockwise(glyph)
+ struct glyph *glyph;
+{
+ register char *nrast; /* new raster */
+ register char *orast; /* old raster */
+ register int oheight; /* old raster height, new raster width */
+ register int owidth; /* old raster width, new raster height */
+ unsigned int size; /* size of new raster (in bytes) */
+ int nplus; /* offset between rows in nrast */
+
+ /*
+ * First, get a new raster.
+ */
+ {
+ register struct glyph *g = glyph;
+ register int t;
+
+ oheight = g->g_height;
+ owidth = g->g_width;
+
+ /*
+ * Offset is (new width) rounded to bytes.
+ */
+ nplus = ROUND(oheight, 8) >> 3;
+
+ /*
+ * Size of new raster is (new height) * (new rounded width,
+ * in bytes).
+ */
+ size = nplus * owidth;
+ if ((nrast = malloc(size)) == NULL)
+ error(1, errno, "out of memory");
+ bzero(nrast, size);
+
+ /*
+ * New y origin is old x origin; new x origin is old height
+ * minus old y origin - 1.
+ */
+ t = g->g_yorigin;
+ g->g_yorigin = g->g_xorigin;
+ g->g_xorigin = oheight - t - 1;
+
+ /* While we are at it, exchange height & width... */
+ g->g_height = owidth;
+ g->g_width = oheight;
+
+ /* and grab a pointer to the old raster. */
+ orast = g->g_raster;
+ }
+
+ /*
+ * Now copy bits from the old raster to the new one. The mapping
+ * function is
+ *
+ * for i in [0..height)
+ * for j in [0..width)
+ * new[j, height-i-1] = old[i, j]
+ *
+ * Thus i maps to height-i-1 and (since we have to do our own 2
+ * dimensional array indexing) j to nplus*j. We call the mapped
+ * variables mapi and mapj, and, since we scan sequentially through
+ * the old raster, can discard the original i and j.
+ */
+ {
+ register int mapj, c, k, mapi;
+
+ mapi = oheight;
+ owidth *= nplus;
+ while (--mapi >= 0) {
+ k = 7;
+ for (mapj = 0; mapj < owidth; mapj += nplus) {
+ if (++k == 8) /* get another byte */
+ c = *orast++, k = 0;
+ if (c & 0x80) /* old[i,j] was set */
+ nrast[mapj + (mapi >> 3)] |=
+ 1 << (7 - (mapi & 7));
+ c <<= 1;
+ }
+ }
+ }
+
+ /*
+ * Finally, free the storage associated with the original raster.
+ */
+ free(glyph->g_raster);
+ glyph->g_raster = nrast;
+}
diff --git a/dviware/umddvi/lib/scaletfm.c b/dviware/umddvi/lib/scaletfm.c
new file mode 100644
index 0000000000..c04fd62c04
--- /dev/null
+++ b/dviware/umddvi/lib/scaletfm.c
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 1987 University of Maryland Department of Computer Science.
+ * All rights reserved. Permission to copy for any purpose is hereby granted
+ * so long as this copyright notice remains intact.
+ */
+
+#ifndef lint
+static char rcsid[] = "$Header: scaletfm.c,v 2.5 87/06/16 18:28:49 chris Exp $";
+#endif
+
+#include "types.h"
+#include "font.h"
+
+/*
+ * From DVITYPE.WEB:
+ *
+ * ``The most important part of in_TFM is the width computation, which
+ * involvles multiplying the relative widths in the TFM file by the scaling
+ * factor in the DVI file. This fixed-point multiplication must be done with
+ * precisely the same accuracy by all DVI-reading programs, in order to
+ * validate the assumptions made by DVI-writing programs like \TeX 82.
+ *
+ * Let us therefore summarize what needs to be done. Each width in a TFM
+ * file appears as a four-byte quantity called a fix_word. A fix_word whose
+ * respective bytes are (a,b,c,d) represents the number
+ *
+ * {{ b * 2^{-4} + c * 2^{-12} + d * 2^{-20}, if a = 0;
+ * x = {{
+ * {{ -16 + b * 2^{-4} + c * 2^{-12} + d * 2^{-20}, if a = 255.
+ *
+ * (No other choices of a are allowed, since the magnitude of a TFM dimension
+ * must be less than 16.) We want to multiply this quantity by the integer
+ * z, which is known to be less than 2^{27}. Let \alpha = 16z. If z <
+ * 2^{23}, the individual multiplications b * z, c * z, d * z cannot
+ * overflow; otherwise we will divide z by 2, 4, 8, or 16, to obtain a
+ * multiplier less than 2^{23}, and we can compensate for this later. If z
+ * has thereby been replaced by z' = z/2^e, let \beta = 2^{4-e}; we shall
+ * compute
+ *
+ * \lfloor (b + c * 2^{-8} + d * 2^{-16})z' / \beta \rfloor
+ *
+ * if a = 0, or the same quantity minus \alpha if a = 255. This calculation
+ * must be done exactly, for the reasons stated above; the following program
+ * does the job in a system-independent way, assuming that arithmetic is
+ * exact on numbers less than 2^{31} in magnitude.''
+ */
+
+/*
+ * Scale the single TFM width t by z.
+ */
+i32
+ScaleOneWidth(t, z)
+ register i32 t, z;
+{
+ register i32 alpha, log2beta;
+
+ /* First compute \alpha, \beta, and z': */
+ alpha = 16 * z;
+ log2beta = 4;
+ while (z >= (1 << 23)) {
+ z >>= 1;
+ log2beta--;
+ }
+
+ /* The four values 'a', 'b', 'c', and 'd' are fields within t: */
+#define a (UnSign8(t >> 24))
+#define b (UnSign8(t >> 16))
+#define c (UnSign8(t >> 8))
+#define d (UnSign8(t))
+ if (t) {
+ t = (((((d * z) >> 8) + c * z) >> 8) + b * z) >> log2beta;
+ if (a) {
+ if (a != 255)
+ error(0, 0, "bad TFM width! [ScaleOneWidth]");
+ t -= alpha;
+ }
+ }
+ return (t);
+}
+
+/*
+ * Scale a set of glyphs [l..h) in font f according to f->f_dvimag.
+ */
+ScaleGlyphs(f, l, h)
+ register struct font *f;
+ int l, h;
+{
+ register int i;
+ register i32 t, z, alpha, log2beta;
+
+ z = f->f_dvimag;
+ alpha = 16 * z;
+ log2beta = 4;
+ while (z >= (1 << 23)) {
+ z >>= 1;
+ log2beta--;
+ }
+
+ for (i = l; i < h; i++) {
+ if ((t = f->f_gly[i]->g_tfmwidth) == 0)
+ continue;
+ t = (((((d * z) >> 8) + c * z) >> 8) + b * z) >> log2beta;
+ if (a) {
+ if (a != 255)
+ error(0, 0, "\"%s\", glyph %d: bad TFM width",
+ f->f_path, i);
+ t -= alpha;
+ }
+ f->f_gly[i]->g_tfmwidth = t;
+ }
+}
diff --git a/dviware/umddvi/lib/scanpost.c b/dviware/umddvi/lib/scanpost.c
new file mode 100644
index 0000000000..c382731e6e
--- /dev/null
+++ b/dviware/umddvi/lib/scanpost.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 1987 University of Maryland Department of Computer Science.
+ * All rights reserved. Permission to copy for any purpose is hereby granted
+ * so long as this copyright notice remains intact.
+ */
+
+#ifndef lint
+static char rcsid[] = "$Header: scanpost.c,v 2.3 87/06/16 18:28:54 chris Exp $";
+#endif
+
+/*
+ * ScanPostAmble - read a DVI postamble.
+ */
+
+#include <stdio.h>
+#include "types.h"
+#include "dvicodes.h"
+#include "fio.h"
+#include "postamble.h"
+
+ScanPostAmble(f, headerfunc, fontfunc)
+ register FILE *f;
+ int (*headerfunc)();
+ register int (*fontfunc)();
+{
+ register int n;
+ register char *s;
+ char name[512];
+
+ if (FindPostAmble(f))
+ GripeCannotFindPostamble();
+ if (GetByte(f) != Sign8(DVI_POST))
+ GripeMissingOp("POST");
+
+ /* Read the postamble info stuff. */
+ {
+ struct PostAmbleInfo pai;
+ register struct PostAmbleInfo *p = &pai;
+
+ p->pai_PrevPagePointer = GetLong(f);
+ p->pai_Numerator = GetLong(f);
+ p->pai_Denominator = GetLong(f);
+ p->pai_DVIMag = GetLong(f);
+ p->pai_TallestPageHeight = GetLong(f);
+ p->pai_WidestPageWidth = GetLong(f);
+ p->pai_DVIStackSize = GetWord(f);
+ p->pai_NumberOfPages = GetWord(f);
+
+ (*headerfunc)(p);
+ }
+
+ /* Now read all the font definitions. */
+ {
+ struct PostAmbleFont paf;
+ register struct PostAmbleFont *p = &paf;
+
+ for (;;) {
+ switch (UnSign8(getc(f))) {
+
+ case DVI_FNTDEF1:
+ p->paf_DVIFontIndex = UnSign8(getc(f));
+ break;
+
+ case DVI_FNTDEF2:
+ p->paf_DVIFontIndex = UnSign16(GetWord(f));
+ break;
+
+ case DVI_FNTDEF3:
+ p->paf_DVIFontIndex = UnSign24(Get3Byte(f));
+ break;
+
+ case DVI_FNTDEF4:
+ p->paf_DVIFontIndex = GetLong(f);
+ break;
+
+ case DVI_POSTPOST:
+ return;
+
+ default:
+ GripeMissingOp("POSTPOST");
+ /*NOTREACHED*/
+ }
+ p->paf_DVIChecksum = GetLong(f);
+ p->paf_DVIMag = GetLong(f);
+ p->paf_DVIDesignSize = GetLong(f);
+ p->paf_n1 = UnSign8(getc(f));
+ p->paf_n2 = UnSign8(getc(f));
+ p->paf_name = name; /* never trust people not to
+ clobber it */
+ n = p->paf_n1 + p->paf_n2;
+ s = name;
+ while (--n >= 0)
+ *s++ = GetByte(f);
+ *s = 0;
+ (*fontfunc)(p);
+ }
+ }
+}
diff --git a/dviware/umddvi/lib/search.c b/dviware/umddvi/lib/search.c
new file mode 100644
index 0000000000..071fa07c0d
--- /dev/null
+++ b/dviware/umddvi/lib/search.c
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 1987 University of Maryland Department of Computer Science.
+ * All rights reserved. Permission to copy for any purpose is hereby granted
+ * so long as this copyright notice remains intact.
+ */
+
+#ifndef lint
+static char rcsid[] = "$Header: search.c,v 2.3 87/06/16 18:28:58 chris Exp $";
+#endif
+
+/*
+ * Key search routines (for a 32 bit key)
+ *
+ * SCreate initializes the search control area.
+ *
+ * SSearch returns the address of the data area (if found or created)
+ * or a null pointer (if not). The last argument controls the disposition
+ * in various cases, and is a ``value-result'' parameter.
+ *
+ * SEnumerate calls the given function on each data object within the
+ * search table. Note that no ordering is specified (though currently
+ * it runs in increasing-key-value sequence).
+ */
+
+#include "types.h"
+#include "search.h"
+
+#if vax || mc68000 || ns32000 || pyr
+#define HARD_ALIGNMENT 4
+#else
+#define HARD_ALIGNMENT 16 /* should suffice for most everyone */
+#endif
+
+static int DOffset; /* part of alignment code */
+
+char *malloc(), *realloc();
+
+struct search *
+SCreate(dsize)
+ register unsigned int dsize;
+{
+ register struct search *s;
+
+ if ((s = (struct search *) malloc(sizeof *s)) == 0)
+ return (0);
+
+ if (DOffset == 0) {
+#ifndef HARD_ALIGNMENT
+ DOffset = sizeof(i32);
+#else
+ DOffset = (sizeof(i32) + HARD_ALIGNMENT - 1) &
+ ~(HARD_ALIGNMENT - 1);
+#endif
+ }
+ dsize += DOffset; /* tack on space for keys */
+
+#ifdef HARD_ALIGNMENT
+ /*
+ * For machines with strict alignment constraints, it may be
+ * necessary to align the data at a multiple of some positive power
+ * of two. In general, it would suffice to make dsize a power of
+ * two, but this could be very space-wasteful, so instead we align it
+ * to HARD_ALIGNMENT. 64 bit machines might ``#define HARD_ALIGNMENT
+ * 8'', for example. N.B.: we assume that HARD_ALIGNMENT is a power
+ * of two.
+ */
+
+ dsize = (dsize + HARD_ALIGNMENT - 1) & ~(HARD_ALIGNMENT - 1);
+#endif
+
+ s->s_dsize = dsize; /* save data object size */
+ s->s_space = 10; /* initially, room for 10 objects */
+ s->s_n = 0; /* and none in the table */
+ if ((s->s_data = malloc(s->s_space * dsize)) == 0) {
+ free((char *) s);
+ return (0);
+ }
+ return (s);
+}
+
+/*
+ * We actually use a binary search right now - this may change.
+ */
+char *
+SSearch(s, key, disp)
+ register struct search *s;
+ register i32 key;
+ int *disp;
+{
+ register char *keyaddr;
+ int itemstomove;
+
+ *disp &= S_CREATE | S_EXCL; /* clear return codes */
+ if (s->s_n) { /* look for the key */
+ register int h, l, m;
+
+ h = s->s_n - 1;
+ l = 0;
+ while (l <= h) {
+ m = (l + h) >> 1;
+ keyaddr = s->s_data + m * s->s_dsize;
+ if (*(i32 *) keyaddr > key)
+ h = m - 1;
+ else if (*(i32 *) keyaddr < key)
+ l = m + 1;
+ else { /* found it, now what? */
+ if (*disp & S_EXCL) {
+ *disp |= S_COLL;
+ return (0); /* collision */
+ }
+ *disp |= S_FOUND;
+ return (keyaddr + DOffset);
+ }
+ }
+ keyaddr = s->s_data + l * s->s_dsize;
+ } else
+ keyaddr = s->s_data;
+
+ /* keyaddr is now where the key should have been found, if anywhere */
+ if ((*disp & S_CREATE) == 0)
+ return (0); /* not found */
+
+ /* avoid using realloc so as to retain old data if out of memory */
+ if (s->s_space <= 0) { /* must expand; double it */
+ register char *new;
+
+ if ((new = malloc((s->s_n << 1) * s->s_dsize)) == 0) {
+ *disp |= S_ERROR; /* no space */
+ return (0);
+ }
+ keyaddr = (keyaddr - s->s_data) + new; /* relocate */
+ bcopy(s->s_data, new, s->s_n * s->s_dsize);
+ free(s->s_data);
+ s->s_data = new;
+ s->s_space = s->s_n;
+ }
+ /* now move any keyed data that is beyond keyaddr down */
+ itemstomove = s->s_n - (keyaddr - s->s_data) / s->s_dsize;
+ if (itemstomove) {
+#ifndef USE_BCOPY /* often bcopy doesn't handle overlap */
+ register char *from, *to;
+
+ from = s->s_data + s->s_n * s->s_dsize;
+ to = from + s->s_dsize;
+ while (from > keyaddr)
+ *--to = *--from;
+#else
+ bcopy(keyaddr + s->s_dsize, keyaddr + (s->s_dsize << 1),
+ itemstomove * s->s_dsize);
+#endif
+ }
+ *disp |= S_NEW;
+ s->s_n++;
+ s->s_space--;
+ *(i32 *) keyaddr = key;
+ keyaddr += DOffset; /* now actually dataaddr */
+ /* the bzero is just a frill... */
+ bzero(keyaddr, s->s_dsize - DOffset);
+ return (keyaddr);
+}
+
+/*
+ * Call function `f' for each element in the search table `s'.
+ */
+SEnumerate(s, f)
+ register struct search *s;
+ register int (*f)();
+{
+ register int n;
+ register char *p;
+
+ n = s->s_n;
+ p = s->s_data;
+ while (--n >= 0) {
+ (*f)(p + DOffset, *(i32 *) p);
+ p += s->s_dsize;
+ }
+}
diff --git a/dviware/umddvi/lib/seek.c b/dviware/umddvi/lib/seek.c
new file mode 100644
index 0000000000..5f3274af65
--- /dev/null
+++ b/dviware/umddvi/lib/seek.c
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 1987 University of Maryland Department of Computer Science.
+ * All rights reserved. Permission to copy for any purpose is hereby granted
+ * so long as this copyright notice remains intact.
+ */
+
+#ifndef lint
+static char rcsid[] = "$Header: seek.c,v 2.4 87/06/16 18:29:03 chris Exp $";
+#endif
+
+/*
+ * Seekable is a predicate which returns true iff a Unix fd is seekable.
+ *
+ * MakeSeekable forces an input stdio file to be seekable, by copying to
+ * a temporary file if necessary.
+ */
+
+#include <stdio.h>
+#ifdef sys5
+#include <sys/types.h>
+#include <sys/fcntl.h>
+#else
+#include <sys/param.h>
+#endif
+#include <sys/file.h>
+#include <sys/stat.h>
+
+long lseek();
+char *getenv();
+
+int
+Seekable(fd)
+ int fd;
+{
+
+ return (lseek(fd, 0L, 1) >= 0 && !isatty(fd));
+}
+
+/*
+ * We use the despicable trick of unlinking an open temporary file.
+ * The alternatives are too painful. If it becomes necessary to
+ * do this another way, however, here is a method suggested by Fred
+ * Blonder: fork, and have the parent wait for the child to exit.
+ * (The parent must avoid being killed during this phase.) When
+ * the child exits, the parent should then remove the temporary file,
+ * then exit with the same status, or send itself the same signal.
+ */
+int
+MakeSeekable(f)
+ register FILE *f;
+{
+ register int tf, n;
+ int mypid, tries, blksize;
+ char *tmpdir;
+#ifdef MAXBSIZE
+ char buf[MAXBSIZE];
+ struct stat st;
+#else
+ char buf[BUFSIZ];
+#endif
+
+ if (Seekable(fileno(f)))
+ return (0);
+
+ if ((tmpdir = getenv("TMPDIR")) == 0)
+ tmpdir = "/tmp";
+
+ /* compose a suitable temporary file name, and get an r/w descriptor */
+ mypid = getpid();
+ n = 0;
+ tries = 0;
+ do {
+ sprintf(buf, "%s/#%d.%d", tmpdir, mypid, n++);
+ (void) unlink(buf);
+#ifdef O_CREAT /* have three-argument open syscall */
+ tries++;
+ tf = open(buf, O_RDWR | O_CREAT | O_EXCL, 0666);
+#else
+ if (access(buf, 0) == 0) {
+ /*
+ * Skip existing files. Note that tf might
+ * not be set yet.
+ */
+ tf = -1;
+ continue;
+ }
+ tries++;
+ tf = creat(buf, 0666);
+ if (tf >= 0) {
+ (void) close(tf);
+ tf = open(buf, 2);
+ if (tf < 0)
+ (void) unlink(buf);
+ }
+#endif
+ } while (tf < 0 && tries < 20);
+ if (tf < 0) /* probably unrecoverable user error */
+ return (-1);
+
+ (void) unlink(buf);
+
+ /* copy from input file to temp file */
+#ifdef MAXBSIZE
+ if (fstat(tf, &st)) /* how can this ever fail? */
+ blksize = MAXBSIZE;
+ else
+ blksize = MIN(MAXBSIZE, st.st_blksize);
+#else
+ blksize = BUFSIZ;
+#endif
+ while ((n = fread(buf, 1, blksize, f)) > 0) {
+ if (write(tf, buf, n) != n) {
+ (void) close(tf);
+ return (-1);
+ }
+ }
+ /* ferror() is broken in Ultrix 1.2; hence the && */
+ if (ferror(f) && !feof(f)) {
+ (void) close(tf);
+ return (-1);
+ }
+
+ /*
+ * Now switch f to point at the temp file. Since we hit EOF, there
+ * is nothing in f's stdio buffers, so we can play a dirty trick:
+ */
+ clearerr(f);
+ if (dup2(tf, fileno(f))) {
+ (void) close(tf);
+ return (-1);
+ }
+ (void) close(tf);
+ return (0);
+}
diff --git a/dviware/umddvi/lib/split.c b/dviware/umddvi/lib/split.c
new file mode 100644
index 0000000000..93990f4735
--- /dev/null
+++ b/dviware/umddvi/lib/split.c
@@ -0,0 +1,219 @@
+/*
+ * Copyright (c) 1987 University of Maryland Department of Computer Science.
+ * All rights reserved. Permission to copy for any purpose is hereby granted
+ * so long as this copyright notice remains intact.
+ */
+
+#ifndef lint
+static char rcsid[] = "$Header: split.c,v 2.2 87/06/16 18:29:07 chris Exp $";
+#endif
+
+#include <ctype.h>
+
+/*
+ * Split a line into an array of words. This is destructive of
+ * the original line; the word pointers point to places within
+ * that line.
+ *
+ * Return the number of words made, or -1 for overflow.
+ */
+
+/*
+ * The lexical states are much like `sh's, except that we also do
+ * C-style backslash-escapes.
+ */
+enum lexstate {
+ S_BLANK, /* outside a word */
+ S_WORD, /* inside a word, no quoting */
+ S_SQUOTE, /* inside a single quote */
+ S_DQUOTE, /* inside a double quote */
+ S_BKSL0, /* last char was \ */
+ S_BKSL1, /* last chars were \, [0-7] */
+ S_BKSL2 /* last chars were \, [0-7][0-7] */
+};
+
+int
+split(s, w, nw)
+ register char *s, **w;
+ int nw;
+{
+ register int c;
+ register char *canon = s;
+ register int wleft = nw;
+ enum lexstate state, prebkstate;
+
+ /*
+ * Start out in the `blank' state (outside a word). Handle
+ * quotes and things. Backslashes are handled by saving the
+ * `pre-backslash' state, doing the backslash, and restoring
+ * that state at the end of the backslash sequence.
+ */
+ state = S_BLANK;
+ while ((c = *s++) != 0) {
+reswitch:
+ switch (state) {
+
+ /*
+ * Blanks: spaces stay in blank state; anything
+ * else starts a word. However, quotes may put
+ * us into quote states, rather than word states.
+ */
+ case S_BLANK:
+ if (isspace(c))
+ continue;
+ if (--wleft < 0)
+ return (-1);
+ *w++ = canon;
+ state = S_WORD;
+ /* FALLTHROUGH */
+
+ /*
+ * In a word. Spaces take us out (and end the
+ * current word). Quotes, however, put us into
+ * quote states.
+ */
+ case S_WORD:
+ if (isspace(c)) {
+ *canon++ = 0;
+ state = S_BLANK;
+ break;
+ }
+ if (c == '\'') {
+ state = S_SQUOTE;
+ break;
+ }
+ if (c == '"') {
+ state = S_DQUOTE;
+ break;
+ }
+ if (c == '\\') {
+ prebkstate = S_WORD;
+ state = S_BKSL0;
+ break;
+ }
+ *canon++ = c;
+ break;
+
+ /*
+ * Inside a single quote, the only special character
+ * is another single quote. This matches the Bourne
+ * shell quoting convention exactly.
+ */
+ case S_SQUOTE:
+ if (c == '\'')
+ state = S_WORD;
+ else
+ *canon++ = c;
+ break;
+
+ /*
+ * Inside a double quote, double quotes get us out,
+ * but backslashes must be interpreted.
+ */
+ case S_DQUOTE:
+ if (c == '\\') {
+ prebkstate = S_DQUOTE;
+ state = S_BKSL0;
+ } else if (c == '"')
+ state = S_WORD;
+ else
+ *canon++ = c;
+ break;
+
+ /*
+ * If we are handling a backslash, we will either
+ * restore the state, or go to BKSL1 state. In
+ * the latter case, do not advance the canonicalisation
+ * pointer, since we might have more octal digits
+ * to insert.
+ */
+ case S_BKSL0:
+ state = prebkstate; /* probably */
+ switch (c) {
+
+ case 'b':
+ *canon++ = '\b';
+ break;
+
+ case 'f':
+ *canon++ = '\f';
+ break;
+
+ case 'n':
+ *canon++ = '\n';
+ break;
+
+ case 'r':
+ *canon++ = '\r';
+ break;
+
+ case 't':
+ *canon++ = '\t';
+ break;
+
+ case '0': case '1': case '2': case '3':
+ case '4': case '5': case '6': case '7':
+ *canon = c - '0';
+ state = S_BKSL1;
+ break;
+
+ default:
+ *canon++ = c;
+ break;
+ }
+ break;
+
+
+ /*
+ * In BKSL1, we have seen backslash and one octal
+ * digit. There may be more (in which case just
+ * count them on in), or there might be something
+ * that requires we restore the state and try again.
+ */
+ case S_BKSL1:
+ switch (c) {
+
+ case '0': case '1': case '2': case '3':
+ case '4': case '5': case '6': case '7':
+ *canon <<= 3;
+ *canon |= c - '0';
+ state = S_BKSL2;
+ break;
+
+ default:
+ canon++;
+ state = prebkstate;
+ goto reswitch;
+ }
+ break;
+
+ /*
+ * BKSL2 is like BKSL1, except that it cannot
+ * help but restore the original state, since
+ * there are no four-character octal sequences.
+ */
+ case S_BKSL2:
+ state = prebkstate; /* assuredly */
+ switch (c) {
+
+ case '0': case '1': case '2': case '3':
+ case '4': case '5': case '6': case '7':
+ *canon <<= 3;
+ *canon++ |= c - '0';
+ break;
+
+ default:
+ canon++;
+ goto reswitch;
+ }
+ break;
+ }
+ }
+#ifdef notdef
+ if (state != S_WORD && state != S_BLANK)
+ error(0, 0, "warning: unclosed quote");
+#endif
+ if (state != S_BLANK)
+ *canon = 0;
+ return (nw - wleft);
+}
diff --git a/dviware/umddvi/lib/strsave.c b/dviware/umddvi/lib/strsave.c
new file mode 100644
index 0000000000..47e29326cb
--- /dev/null
+++ b/dviware/umddvi/lib/strsave.c
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 1987 University of Maryland Department of Computer Science.
+ * All rights reserved. Permission to copy for any purpose is hereby granted
+ * so long as this copyright notice remains intact.
+ */
+
+/*
+ * Save a string in managed memory.
+ */
+
+char *malloc(), *realloc();
+extern int errno;
+
+char *
+strsave(s)
+ register char *s;
+{
+ register int l = strlen(s) + 1;
+ register char *p = malloc((unsigned) l);
+
+ if (p == 0)
+ error(1, errno, "no room for %d bytes of string", l);
+ bcopy(s, p, l);
+ return (p);
+}
diff --git a/dviware/umddvi/lib/tfm.c b/dviware/umddvi/lib/tfm.c
new file mode 100644
index 0000000000..3c3ba5147c
--- /dev/null
+++ b/dviware/umddvi/lib/tfm.c
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 1987 University of Maryland Department of Computer Science.
+ * All rights reserved. Permission to copy for any purpose is hereby granted
+ * so long as this copyright notice remains intact.
+ */
+
+#ifndef lint
+static char rcsid[] = "$Header: tfm.c,v 2.4 87/06/16 18:29:14 chris Exp $";
+#endif
+
+/*
+ * TFM file reading routines.
+ *
+ * TODO:
+ * finish
+ */
+
+#include <stdio.h>
+#include "types.h"
+#include "fio.h"
+#include "tfm.h"
+
+char *malloc();
+
+#define ALLOC(n, type) ((type *) malloc((unsigned) ((n) * sizeof (type))))
+
+int
+readtfmfile(f, t, stopafterwidth)
+ register FILE *f;
+ register struct tfmdata *t;
+ int stopafterwidth; /* ??? */
+{
+ i32 nc;
+
+ if (trd_header(f, &t->t_hdr))
+ return (-1);
+ nc = t->t_hdr.th_ec - t->t_hdr.th_bc + 1;
+
+ t->t_ci = NULL;
+ t->t_width = NULL;
+ t->t_height = NULL;
+ t->t_depth = NULL;
+
+ (void) fseek(f, t->t_hdr.th_lh * 4L, 1); /* XXX */
+
+ if ((t->t_ci = ALLOC(nc, struct char_info_word)) == NULL ||
+ trd_ci(f, nc, t->t_ci) ||
+ (t->t_width = ALLOC(t->t_hdr.th_nw, i32)) == NULL ||
+ trd_fix(f, t->t_hdr.th_nw, t->t_width))
+ goto bad;
+ if (stopafterwidth)
+ return (0);
+ if ((t->t_height = ALLOC(t->t_hdr.th_nh, i32)) == NULL ||
+ trd_fix(f, t->t_hdr.th_nh, t->t_height) ||
+ (t->t_depth = ALLOC(t->t_hdr.th_nd, i32)) == NULL ||
+ trd_fix(f, t->t_hdr.th_nd, t->t_depth))
+ goto bad;
+ return (0);
+
+bad:
+ if (t->t_ci != NULL)
+ free((char *) t->t_ci);
+ if (t->t_width != NULL)
+ free((char *) t->t_width);
+ if (t->t_height != NULL)
+ free((char *) t->t_height);
+ if (t->t_depth != NULL)
+ free((char *) t->t_depth);
+ return (-1);
+}
+
+static int
+trd_header(f, th)
+ register FILE *f;
+ register struct tfmheader *th;
+{
+ register i32 *p;
+
+ for (p = &th->th_lf; p <= &th->th_np; p++)
+ fGetWord(f, *p);
+ if (feof(f))
+ return (-1);
+ return (0);
+}
+
+static int
+trd_ci(f, nc, ci)
+ register FILE *f;
+ register int nc;
+ register struct char_info_word *ci;
+{
+
+ while (--nc >= 0) {
+ ci->ci_width = fgetbyte(f);
+ ci->ci_h_d = fgetbyte(f);
+ ci->ci_i_t = fgetbyte(f);
+ ci->ci_remainder = fgetbyte(f);
+ ci++;
+ }
+ if (feof(f))
+ return (-1);
+ return (0);
+}
+
+static int
+trd_fix(f, nf, p)
+ register FILE *f;
+ register int nf;
+ register i32 *p;
+{
+
+ while (--nf >= 0) {
+ fGetLong(f, *p);
+ p++;
+ }
+ if (feof(f))
+ return (-1);
+ return (0);
+}
diff --git a/dviware/umddvi/lib/tfmfont.c b/dviware/umddvi/lib/tfmfont.c
new file mode 100644
index 0000000000..22ebcc2f27
--- /dev/null
+++ b/dviware/umddvi/lib/tfmfont.c
@@ -0,0 +1,247 @@
+/*
+ * Copyright (c) 1987 University of Maryland Department of Computer Science.
+ * All rights reserved. Permission to copy for any purpose is hereby granted
+ * so long as this copyright notice remains intact.
+ */
+
+#ifndef lint
+static char rcsid[] = "$Header: tfmfont.c,v 2.4 87/06/16 18:29:18 chris Exp $";
+#endif
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "types.h"
+#include "conv.h"
+#include "font.h"
+#include "tfm.h"
+
+/*
+ * TFM font operations. This defines three fonts:
+ *
+ * box - prints as little square boxes, outlining what TeX
+ * thinks is the character.
+ * blank - prints as entirely blank.
+ * invis - prints as entirely blank.
+ *
+ * The first two also complain that no font is available in the
+ * requested size; these are intended to be used as a last resort
+ * so that users can always print DVI files. You should configure
+ * in exactly one of box or blank.
+ *
+ * TODO:
+ * base box edge widths on Conversion.c_dpi
+ */
+int box_read(), blank_read(), invis_read();
+int tfm_getgly(), tfm_rasterise(), tfm_freefont();
+
+ /* magnifications are unused in tfm fonts */
+struct fontops boxops = /* `boxtops'? Is this a cereal driver? */
+ { "box", 0.0, box_read, tfm_getgly, tfm_rasterise, tfm_freefont };
+struct fontops blankops =
+ { "blank", 0.0, blank_read, tfm_getgly, tfm_rasterise, tfm_freefont };
+struct fontops invisops =
+ { "invis", 0.0, invis_read, tfm_getgly, tfm_rasterise, tfm_freefont };
+
+/*
+ * Local info.
+ */
+struct tfm_details {
+ int tfm_edge; /* box edge widths, in pixels */
+ struct conversion tfm_conv; /* conv. from scaled pts to pixels */
+ struct tfmdata tfm_data; /* the TFM file data */
+};
+
+/*
+ * Get the tfm_details from font f.
+ */
+#define ftotfm(f) ((struct tfm_details *) (f)->f_details)
+
+extern int errno;
+char *malloc();
+
+/*
+ * Read a Box font.
+ */
+static int
+box_read(f)
+ struct font *f;
+{
+
+ return (do_read(f, 0, 1));
+}
+
+/*
+ * Read a Blank font.
+ */
+static int
+blank_read(f)
+ struct font *f;
+{
+
+ return (do_read(f, 1, 1));
+}
+
+/*
+ * Read an Invisible font.
+ */
+static int
+invis_read(f)
+ struct font *f;
+{
+
+ return (do_read(f, 1, 0));
+}
+
+/*
+ * Read a TFM font. It is blank if `blank'; complain if `complain'.
+ */
+static int
+do_read(f, blank, complain)
+ register struct font *f;
+ int blank, complain;
+{
+ register struct tfm_details *tfm;
+ FILE *fd;
+
+ if ((fd = fopen(f->f_path, "r")) < 0)
+ return (-1);
+ if ((tfm = (struct tfm_details *) malloc(sizeof (*tfm))) == NULL)
+ goto fail;
+ if (readtfmfile(fd, &tfm->tfm_data, blank))
+ goto fail;
+ if (blank)
+ tfm->tfm_edge = 0;
+ else {
+ tfm->tfm_edge = 2; /* XXX should be based on dpi */
+ tfm->tfm_conv = Conversion;
+ tfm->tfm_conv.c_fromsp *= DMagFactor(f->f_scaled);
+ /* XXX !data abstraction */
+ }
+ if (FontHasGlyphs(f, tfm->tfm_data.t_hdr.th_bc,
+ tfm->tfm_data.t_hdr.th_ec + 1))
+ goto fail;
+ f->f_details = (char *) tfm;
+ (void) fclose(fd);
+ if (complain)
+ error(0, 0, "Warning: no font for %s", Font_TeXName(f));
+ return (0);
+
+fail:
+ (void) fclose(fd);
+ if (tfm != NULL)
+ free((char *) tfm);
+ return (-1);
+}
+
+/*
+ * Obtain the specified range of glyphs.
+ */
+static int
+tfm_getgly(f, l, h)
+ register struct font *f;
+ int l;
+ register int h;
+{
+ register struct tfm_details *tfm = ftotfm(f);
+ register struct glyph *g;
+ register int i;
+ register struct char_info_word *ci;
+#define t (&tfm->tfm_data)
+ i32 ScaleOneWidth();
+#define ftop(fix) cfromSP(&tfm->tfm_conv, ScaleOneWidth(fix, f->f_dvimag))
+
+ for (i = l; i < h; i++) {
+ ci = &t->t_ci[i - t->t_hdr.th_bc];
+ /* zero widths mark invalid characters */
+ if (ci->ci_width == 0)
+ continue;
+ g = f->f_gly[i];
+ g->g_flags = GF_VALID;
+ g->g_tfmwidth = t->t_width[UnSign8(ci->ci_width)];
+ if (tfm->tfm_edge != 0) {
+ g->g_xorigin = 0;
+ g->g_yorigin = ftop(t->t_height[T_CI_H(ci)]);
+ g->g_width = ftop(g->g_tfmwidth);
+ g->g_height = g->g_yorigin +
+ ftop(t->t_depth[T_CI_D(ci)]);
+ }
+ }
+ return (0);
+#undef t
+}
+
+/*
+ * Obtain rasters for the specified glyphs.
+ *
+ * IGNORES tfm->tfm_edge: 2 HARDCODED FOR NOW
+ */
+static int
+tfm_rasterise(f, l, h)
+ struct font *f;
+ int l, h;
+{
+ register struct glyph *g;
+ register char *p;
+ register int w, j, i;
+ struct tfm_details *tfm = ftotfm(f);
+#define EDGE 2
+
+ if (tfm->tfm_edge == 0)
+ return;
+if (tfm->tfm_edge != 2) panic("tfm_rasterise");
+ for (i = l; i < h; i++) {
+ g = f->f_gly[i];
+ if ((g->g_flags & GF_VALID) == 0 || !HASRASTER(g))
+ continue;
+ w = (g->g_width + 7) >> 3;
+ p = malloc((unsigned) (g->g_height * w));
+ if (p == NULL)
+ return (-1);
+ g->g_raster = p;
+ g->g_rotation = ROT_NORM;
+ if (g->g_width < 2 * EDGE) {
+ w = 2 * EDGE - g->g_width;
+ for (j = g->g_height; --j >= 0;)
+ *p++ = 0xf0 << w;
+ } else {
+ bzero(p, g->g_height * w);
+ for (j = 0; j < g->g_height;) {
+ if (j < EDGE || j >= g->g_height - EDGE) {
+ register int k = w;
+
+ while (--k > 0)
+ *p++ = 0xff;
+ *p++ = 0xff << ((8 - g->g_width) & 7);
+ j++;
+ continue;
+ }
+ /* the following depends on EDGE==2 */
+ *p = 0xc0;
+ p += w - ((g->g_width & 7) == 1 ? 2 : 1);
+ *p++ |= 0xc0 >> ((g->g_width - EDGE) & 7);
+ if ((g->g_width & 7) == 1)
+ *p++ = 0x80;
+ /* end dependencies */
+ if (++j == EDGE && g->g_height >= 2 * EDGE) {
+ register int n = g->g_height - EDGE;
+
+ p += (n - j) * w;
+ j = n;
+ }
+ }
+ }
+ }
+ return (0);
+}
+
+/*
+ * Discard the font details.
+ */
+static
+tfm_freefont(f)
+ struct font *f;
+{
+
+ free(f->f_details);
+}
diff --git a/dviware/umddvi/libcompat/bcmp.c b/dviware/umddvi/libcompat/bcmp.c
new file mode 100644
index 0000000000..8281589406
--- /dev/null
+++ b/dviware/umddvi/libcompat/bcmp.c
@@ -0,0 +1,6 @@
+bcmp(a, b, n)
+ char *a, *b;
+ int n;
+{
+ return(memcmp(a, b, n));
+}
diff --git a/dviware/umddvi/libcompat/bcopy.c b/dviware/umddvi/libcompat/bcopy.c
new file mode 100644
index 0000000000..6c9627181b
--- /dev/null
+++ b/dviware/umddvi/libcompat/bcopy.c
@@ -0,0 +1,6 @@
+bcopy(a, b, n)
+ char *a, *b;
+ int n;
+{
+ memcpy(b, a, n);
+}
diff --git a/dviware/umddvi/libcompat/bzero.c b/dviware/umddvi/libcompat/bzero.c
new file mode 100644
index 0000000000..6ef7fa5c93
--- /dev/null
+++ b/dviware/umddvi/libcompat/bzero.c
@@ -0,0 +1,6 @@
+bzero(a, n)
+ char *a;
+ int n;
+{
+ memset(a, 0, n);
+}
diff --git a/dviware/umddvi/libcompat/closedir.c b/dviware/umddvi/libcompat/closedir.c
new file mode 100644
index 0000000000..9585c50feb
--- /dev/null
+++ b/dviware/umddvi/libcompat/closedir.c
@@ -0,0 +1,18 @@
+/*
+ closedir -- C library extension routine
+
+ last edit: 21-Jan-1984 D A Gwyn
+*/
+
+#include <dir.h>
+
+extern void free();
+extern int close();
+
+void
+closedir( dirp )
+ register DIR *dirp; /* stream from opendir() */
+ {
+ (void)close( dirp->dd_fd );
+ free( (char *)dirp );
+ }
diff --git a/dviware/umddvi/libcompat/dir.h b/dviware/umddvi/libcompat/dir.h
new file mode 100644
index 0000000000..140f330cbc
--- /dev/null
+++ b/dviware/umddvi/libcompat/dir.h
@@ -0,0 +1,33 @@
+/*
+ <dir.h> -- definitions for 4.2BSD-compatible directory access
+
+ last edit: 09-Jul-1983 D A Gwyn
+*/
+
+#define DIRBLKSIZ 512 /* size of directory block */
+#define MAXNAMLEN 15 /* maximum filename length */
+ /* NOTE: MAXNAMLEN must be one less than a multiple of 4 */
+
+struct direct /* data from readdir() */
+ {
+ long d_ino; /* inode number of entry */
+ unsigned short d_reclen; /* length of this record */
+ unsigned short d_namlen; /* length of string in d_name */
+ char d_name[MAXNAMLEN+1]; /* name of file */
+ };
+
+typedef struct
+ {
+ int dd_fd; /* file descriptor */
+ int dd_loc; /* offset in block */
+ int dd_size; /* amount of valid data */
+ char dd_buf[DIRBLKSIZ]; /* directory block */
+ } DIR; /* stream data from opendir() */
+
+extern DIR *opendir();
+extern struct direct *readdir();
+extern long telldir();
+extern void seekdir();
+extern void closedir();
+
+#define rewinddir( dirp ) seekdir( dirp, 0L )
diff --git a/dviware/umddvi/libcompat/dup2.c b/dviware/umddvi/libcompat/dup2.c
new file mode 100644
index 0000000000..9cb749b4ec
--- /dev/null
+++ b/dviware/umddvi/libcompat/dup2.c
@@ -0,0 +1,7 @@
+#include <sys/fcntl.h>
+
+dup2(a, b)
+{
+ close(b);
+ return(fcntl(a, F_DUPFD, b));
+}
diff --git a/dviware/umddvi/libcompat/errs b/dviware/umddvi/libcompat/errs
new file mode 100644
index 0000000000..8a91cace96
--- /dev/null
+++ b/dviware/umddvi/libcompat/errs
@@ -0,0 +1,8 @@
+ cc -O -I. -c closedir.c
+ cc -O -I. -c opendir.c
+ cc -O -I. -c readdir.c
+ cc -O -I. -c seekdir.c
+ cc -O -I. -c telldir.c
+ rm -f libdir.a
+ ar rcv closedir.o opendir.o readdir.o seekdir.o telldir.o
+*** Error code 1
diff --git a/dviware/umddvi/libcompat/index.c b/dviware/umddvi/libcompat/index.c
new file mode 100644
index 0000000000..4c5065ee36
--- /dev/null
+++ b/dviware/umddvi/libcompat/index.c
@@ -0,0 +1,9 @@
+#include <string.h>
+
+char *
+index(a, c)
+ char *a;
+ int c;
+{
+ return(strchr(a, c));
+}
diff --git a/dviware/umddvi/libcompat/makefile b/dviware/umddvi/libcompat/makefile
new file mode 100644
index 0000000000..a41e7d2a44
--- /dev/null
+++ b/dviware/umddvi/libcompat/makefile
@@ -0,0 +1,11 @@
+OBJS= closedir.o opendir.o readdir.o seekdir.o telldir.o \
+ bcmp.o bcopy.o bzero.o index.o rindex.o regex.o dup2.o rename.o
+
+CFLAGS= -O -I.
+
+libdir.a: $(OBJS)
+ rm -f libcompat.a
+ ar rcv libcompat.a $(OBJS)
+
+clean:
+ rm -f *.o libcompat.a
diff --git a/dviware/umddvi/libcompat/opendir.c b/dviware/umddvi/libcompat/opendir.c
new file mode 100644
index 0000000000..833e21f576
--- /dev/null
+++ b/dviware/umddvi/libcompat/opendir.c
@@ -0,0 +1,43 @@
+/*
+ opendir -- C library extension routine
+
+ last edit: 09-Jul-1983 D A Gwyn
+*/
+
+#include <dir.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#ifdef BRL
+#define open _open /* avoid emulation */
+#endif
+
+extern char *malloc();
+extern int open(), close(), fstat();
+
+#define NULL 0
+
+DIR *
+opendir( filename )
+ char *filename; /* name of directory */
+ {
+ register DIR *dirp; /* -> malloc'ed storage */
+ register int fd; /* file descriptor for read */
+ struct stat sbuf; /* result of fstat() */
+
+ if ( (fd = open( filename, 0 )) < 0 )
+ return NULL;
+
+ if ( fstat( fd, &sbuf ) < 0
+ || (sbuf.st_mode & S_IFMT) != S_IFDIR
+ || (dirp = (DIR *)malloc( sizeof(DIR) )) == NULL
+ ) {
+ (void)close( fd );
+ return NULL; /* bad luck today */
+ }
+
+ dirp->dd_fd = fd;
+ dirp->dd_loc = dirp->dd_size = 0; /* refill needed */
+
+ return dirp;
+ }
diff --git a/dviware/umddvi/libcompat/read_me b/dviware/umddvi/libcompat/read_me
new file mode 100644
index 0000000000..6b90682c47
--- /dev/null
+++ b/dviware/umddvi/libcompat/read_me
@@ -0,0 +1,8 @@
+These routines implement the portable directory access interface
+introduced in 4.2BSD. They are in the public domain.
+
+Programs that need to read directories must be changed to use these
+directory access routines (see also ../include/dir.h), which should
+be bundled into the standard system C library for convenience.
+
+/usr/include/sys/dir.h should be removed to encourage conversion.
diff --git a/dviware/umddvi/libcompat/readdir.c b/dviware/umddvi/libcompat/readdir.c
new file mode 100644
index 0000000000..41ea038ec3
--- /dev/null
+++ b/dviware/umddvi/libcompat/readdir.c
@@ -0,0 +1,59 @@
+/*
+ readdir -- C library extension routine for non-BSD UNIX
+
+ last edit: 09-Jul-1983 D A Gwyn
+*/
+
+#include <dir.h>
+#include <sys/types.h>
+
+extern char *strncpy();
+extern int read(), strlen();
+
+#define NULL 0
+
+#define DIRSIZ 14
+struct olddir
+ {
+ ino_t od_ino; /* inode */
+ char od_name[DIRSIZ]; /* filename */
+ };
+
+struct direct *
+readdir( dirp )
+ register DIR *dirp; /* stream from opendir() */
+ {
+ register struct olddir *dp; /* -> directory data */
+
+ for ( ; ; )
+ {
+ if ( dirp->dd_loc >= dirp->dd_size )
+ dirp->dd_loc = dirp->dd_size = 0;
+
+ if ( dirp->dd_size == 0 /* refill buffer */
+ && (dirp->dd_size = read( dirp->dd_fd, dirp->dd_buf,
+ DIRBLKSIZ
+ )
+ ) <= 0
+ )
+ return NULL; /* error or EOF */
+
+ dp = (struct olddir *)&dirp->dd_buf[dirp->dd_loc];
+ dirp->dd_loc += sizeof(struct olddir);
+
+ if ( dp->od_ino != 0 ) /* not deleted entry */
+ {
+ static struct direct dir; /* simulated */
+
+ dir.d_ino = dp->od_ino;
+ (void)strncpy( dir.d_name, dp->od_name, DIRSIZ
+ );
+ dir.d_name[DIRSIZ] = '\0';
+ dir.d_namlen = strlen( dir.d_name );
+ dir.d_reclen = sizeof(struct direct)
+ - MAXNAMLEN + 3
+ + dir.d_namlen - dir.d_namlen % 4;
+ return &dir; /* -> simulated structure */
+ }
+ }
+ }
diff --git a/dviware/umddvi/libcompat/regex.c b/dviware/umddvi/libcompat/regex.c
new file mode 100644
index 0000000000..73c1e0cf73
--- /dev/null
+++ b/dviware/umddvi/libcompat/regex.c
@@ -0,0 +1,401 @@
+/*
+ * Copyright (c) 1980 Regents of the University of California.
+ * All rights reserved. The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)regex.c 5.2 (Berkeley) 3/9/86";
+#endif LIBC_SCCS and not lint
+
+#
+
+/*
+ * routines to do regular expression matching
+ *
+ * Entry points:
+ *
+ * re_comp(s)
+ * char *s;
+ * ... returns 0 if the string s was compiled successfully,
+ * a pointer to an error message otherwise.
+ * If passed 0 or a null string returns without changing
+ * the currently compiled re (see note 11 below).
+ *
+ * re_exec(s)
+ * char *s;
+ * ... returns 1 if the string s matches the last compiled regular
+ * expression,
+ * 0 if the string s failed to match the last compiled
+ * regular expression, and
+ * -1 if the compiled regular expression was invalid
+ * (indicating an internal error).
+ *
+ * The strings passed to both re_comp and re_exec may have trailing or
+ * embedded newline characters; they are terminated by nulls.
+ *
+ * The identity of the author of these routines is lost in antiquity;
+ * this is essentially the same as the re code in the original V6 ed.
+ *
+ * The regular expressions recognized are described below. This description
+ * is essentially the same as that for ed.
+ *
+ * A regular expression specifies a set of strings of characters.
+ * A member of this set of strings is said to be matched by
+ * the regular expression. In the following specification for
+ * regular expressions the word `character' means any character but NUL.
+ *
+ * 1. Any character except a special character matches itself.
+ * Special characters are the regular expression delimiter plus
+ * \ [ . and sometimes ^ * $.
+ * 2. A . matches any character.
+ * 3. A \ followed by any character except a digit or ( )
+ * matches that character.
+ * 4. A nonempty string s bracketed [s] (or [^s]) matches any
+ * character in (or not in) s. In s, \ has no special meaning,
+ * and ] may only appear as the first letter. A substring
+ * a-b, with a and b in ascending ASCII order, stands for
+ * the inclusive range of ASCII characters.
+ * 5. A regular expression of form 1-4 followed by * matches a
+ * sequence of 0 or more matches of the regular expression.
+ * 6. A regular expression, x, of form 1-8, bracketed \(x\)
+ * matches what x matches.
+ * 7. A \ followed by a digit n matches a copy of the string that the
+ * bracketed regular expression beginning with the nth \( matched.
+ * 8. A regular expression of form 1-8, x, followed by a regular
+ * expression of form 1-7, y matches a match for x followed by
+ * a match for y, with the x match being as long as possible
+ * while still permitting a y match.
+ * 9. A regular expression of form 1-8 preceded by ^ (or followed
+ * by $), is constrained to matches that begin at the left
+ * (or end at the right) end of a line.
+ * 10. A regular expression of form 1-9 picks out the longest among
+ * the leftmost matches in a line.
+ * 11. An empty regular expression stands for a copy of the last
+ * regular expression encountered.
+ */
+
+/*
+ * constants for re's
+ */
+#define CBRA 1
+#define CCHR 2
+#define CDOT 4
+#define CCL 6
+#define NCCL 8
+#define CDOL 10
+#define CEOF 11
+#define CKET 12
+#define CBACK 18
+
+#define CSTAR 01
+
+#define ESIZE 512
+#define NBRA 9
+
+static char expbuf[ESIZE], *braslist[NBRA], *braelist[NBRA];
+static char circf;
+
+/*
+ * compile the regular expression argument into a dfa
+ */
+char *
+re_comp(sp)
+ register char *sp;
+{
+ register int c;
+ register char *ep = expbuf;
+ int cclcnt, numbra = 0;
+ char *lastep = 0;
+ char bracket[NBRA];
+ char *bracketp = &bracket[0];
+ static char *retoolong = "Regular expression too long";
+
+#define comerr(msg) {expbuf[0] = 0; numbra = 0; return(msg); }
+
+ if (sp == 0 || *sp == '\0') {
+ if (*ep == 0)
+ return("No previous regular expression");
+ return(0);
+ }
+ if (*sp == '^') {
+ circf = 1;
+ sp++;
+ }
+ else
+ circf = 0;
+ for (;;) {
+ if (ep >= &expbuf[ESIZE])
+ comerr(retoolong);
+ if ((c = *sp++) == '\0') {
+ if (bracketp != bracket)
+ comerr("unmatched \\(");
+ *ep++ = CEOF;
+ *ep++ = 0;
+ return(0);
+ }
+ if (c != '*')
+ lastep = ep;
+ switch (c) {
+
+ case '.':
+ *ep++ = CDOT;
+ continue;
+
+ case '*':
+ if (lastep == 0 || *lastep == CBRA || *lastep == CKET)
+ goto defchar;
+ *lastep |= CSTAR;
+ continue;
+
+ case '$':
+ if (*sp != '\0')
+ goto defchar;
+ *ep++ = CDOL;
+ continue;
+
+ case '[':
+ *ep++ = CCL;
+ *ep++ = 0;
+ cclcnt = 1;
+ if ((c = *sp++) == '^') {
+ c = *sp++;
+ ep[-2] = NCCL;
+ }
+ do {
+ if (c == '\0')
+ comerr("missing ]");
+ if (c == '-' && ep [-1] != 0) {
+ if ((c = *sp++) == ']') {
+ *ep++ = '-';
+ cclcnt++;
+ break;
+ }
+ while (ep[-1] < c) {
+ *ep = ep[-1] + 1;
+ ep++;
+ cclcnt++;
+ if (ep >= &expbuf[ESIZE])
+ comerr(retoolong);
+ }
+ }
+ *ep++ = c;
+ cclcnt++;
+ if (ep >= &expbuf[ESIZE])
+ comerr(retoolong);
+ } while ((c = *sp++) != ']');
+ lastep[1] = cclcnt;
+ continue;
+
+ case '\\':
+ if ((c = *sp++) == '(') {
+ if (numbra >= NBRA)
+ comerr("too many \\(\\) pairs");
+ *bracketp++ = numbra;
+ *ep++ = CBRA;
+ *ep++ = numbra++;
+ continue;
+ }
+ if (c == ')') {
+ if (bracketp <= bracket)
+ comerr("unmatched \\)");
+ *ep++ = CKET;
+ *ep++ = *--bracketp;
+ continue;
+ }
+ if (c >= '1' && c < ('1' + NBRA)) {
+ *ep++ = CBACK;
+ *ep++ = c - '1';
+ continue;
+ }
+ *ep++ = CCHR;
+ *ep++ = c;
+ continue;
+
+ defchar:
+ default:
+ *ep++ = CCHR;
+ *ep++ = c;
+ }
+ }
+}
+
+/*
+ * match the argument string against the compiled re
+ */
+int
+re_exec(p1)
+ register char *p1;
+{
+ register char *p2 = expbuf;
+ register int c;
+ int rv;
+
+ for (c = 0; c < NBRA; c++) {
+ braslist[c] = 0;
+ braelist[c] = 0;
+ }
+ if (circf)
+ return((advance(p1, p2)));
+ /*
+ * fast check for first character
+ */
+ if (*p2 == CCHR) {
+ c = p2[1];
+ do {
+ if (*p1 != c)
+ continue;
+ if (rv = advance(p1, p2))
+ return(rv);
+ } while (*p1++);
+ return(0);
+ }
+ /*
+ * regular algorithm
+ */
+ do
+ if (rv = advance(p1, p2))
+ return(rv);
+ while (*p1++);
+ return(0);
+}
+
+/*
+ * try to match the next thing in the dfa
+ */
+static int
+advance(lp, ep)
+ register char *lp, *ep;
+{
+ register char *curlp;
+ int ct, i;
+ int rv;
+
+ for (;;)
+ switch (*ep++) {
+
+ case CCHR:
+ if (*ep++ == *lp++)
+ continue;
+ return(0);
+
+ case CDOT:
+ if (*lp++)
+ continue;
+ return(0);
+
+ case CDOL:
+ if (*lp == '\0')
+ continue;
+ return(0);
+
+ case CEOF:
+ return(1);
+
+ case CCL:
+ if (cclass(ep, *lp++, 1)) {
+ ep += *ep;
+ continue;
+ }
+ return(0);
+
+ case NCCL:
+ if (cclass(ep, *lp++, 0)) {
+ ep += *ep;
+ continue;
+ }
+ return(0);
+
+ case CBRA:
+ braslist[*ep++] = lp;
+ continue;
+
+ case CKET:
+ braelist[*ep++] = lp;
+ continue;
+
+ case CBACK:
+ if (braelist[i = *ep++] == 0)
+ return(-1);
+ if (backref(i, lp)) {
+ lp += braelist[i] - braslist[i];
+ continue;
+ }
+ return(0);
+
+ case CBACK|CSTAR:
+ if (braelist[i = *ep++] == 0)
+ return(-1);
+ curlp = lp;
+ ct = braelist[i] - braslist[i];
+ while (backref(i, lp))
+ lp += ct;
+ while (lp >= curlp) {
+ if (rv = advance(lp, ep))
+ return(rv);
+ lp -= ct;
+ }
+ continue;
+
+ case CDOT|CSTAR:
+ curlp = lp;
+ while (*lp++)
+ ;
+ goto star;
+
+ case CCHR|CSTAR:
+ curlp = lp;
+ while (*lp++ == *ep)
+ ;
+ ep++;
+ goto star;
+
+ case CCL|CSTAR:
+ case NCCL|CSTAR:
+ curlp = lp;
+ while (cclass(ep, *lp++, ep[-1] == (CCL|CSTAR)))
+ ;
+ ep += *ep;
+ goto star;
+
+ star:
+ do {
+ lp--;
+ if (rv = advance(lp, ep))
+ return(rv);
+ } while (lp > curlp);
+ return(0);
+
+ default:
+ return(-1);
+ }
+}
+
+backref(i, lp)
+ register int i;
+ register char *lp;
+{
+ register char *bp;
+
+ bp = braslist[i];
+ while (*bp++ == *lp++)
+ if (bp >= braelist[i])
+ return(1);
+ return(0);
+}
+
+int
+cclass(set, c, af)
+ register char *set, c;
+ int af;
+{
+ register int n;
+
+ if (c == 0)
+ return(0);
+ n = *set++;
+ while (--n)
+ if (*set++ == c)
+ return(af);
+ return(! af);
+}
diff --git a/dviware/umddvi/libcompat/rename.c b/dviware/umddvi/libcompat/rename.c
new file mode 100644
index 0000000000..3cb2665621
--- /dev/null
+++ b/dviware/umddvi/libcompat/rename.c
@@ -0,0 +1,14 @@
+rename(a, b)
+ char *a, *b;
+{
+ if (access(a, 0) == -1)
+ return(-1);
+ unlink(b);
+ if (link(a, b) == -1)
+ return(-1);
+ if (unlink(a) == -1) {
+ unlink(b);
+ return(-1);
+ }
+ return(0);
+}
diff --git a/dviware/umddvi/libcompat/rindex.c b/dviware/umddvi/libcompat/rindex.c
new file mode 100644
index 0000000000..0c15086254
--- /dev/null
+++ b/dviware/umddvi/libcompat/rindex.c
@@ -0,0 +1,9 @@
+#include <string.h>
+
+char *
+rindex(a, c)
+ char *a;
+ int c;
+{
+ return(strrchr(a, c));
+}
diff --git a/dviware/umddvi/libcompat/seekdir.c b/dviware/umddvi/libcompat/seekdir.c
new file mode 100644
index 0000000000..dc29f48baa
--- /dev/null
+++ b/dviware/umddvi/libcompat/seekdir.c
@@ -0,0 +1,33 @@
+/*
+ seekdir -- C library extension routine
+
+ last edit: 21-Jan-1984 D A Gwyn
+*/
+
+#include <dir.h>
+
+extern long lseek();
+
+#define NULL 0
+
+void
+seekdir( dirp, loc )
+ register DIR *dirp; /* stream from opendir() */
+ long loc; /* position from telldir() */
+ {
+ long base; /* file location of block */
+ long offset; /* offset within block */
+
+ if ( telldir( dirp ) == loc )
+ return; /* save time */
+
+ offset = loc % DIRBLKSIZ;
+ base = loc - offset;
+
+ (void)lseek( dirp->dd_fd, base, 0 ); /* change blocks */
+ dirp->dd_loc = dirp->dd_size = 0;
+
+ while ( dirp->dd_loc < offset ) /* skip entries */
+ if ( readdir( dirp ) == NULL )
+ return; /* "can't happen" */
+ }
diff --git a/dviware/umddvi/libcompat/telldir.c b/dviware/umddvi/libcompat/telldir.c
new file mode 100644
index 0000000000..239055bbd8
--- /dev/null
+++ b/dviware/umddvi/libcompat/telldir.c
@@ -0,0 +1,17 @@
+/*
+ telldir -- C library extension routine
+
+ last edit: 09-Jul-1983 D A Gwyn
+*/
+
+#include <dir.h>
+
+extern long lseek();
+
+long
+telldir( dirp )
+ DIR *dirp; /* stream from opendir() */
+ {
+ return lseek( dirp->dd_fd, 0L, 1 ) - (long)dirp->dd_size
+ + (long)dirp->dd_loc;
+ }
diff --git a/dviware/umddvi/makefile b/dviware/umddvi/makefile
new file mode 100644
index 0000000000..cca3865efe
--- /dev/null
+++ b/dviware/umddvi/makefile
@@ -0,0 +1,54 @@
+# Makefile for everything
+#
+# Eventually, it would be nice to have various targets depending on
+# the output devices, and pass that info down to the dev/ directory.
+# For now, this will do.
+DESTDIR=
+MAKE= make
+MFLAGS=
+
+# where to find the font description file
+CONFFILE=/usr/lib/tex/fontdesc
+# where things get installed
+BINDIR= ${DESTDIR}/usr/local/bin
+# where manuals get installed---note that `/man1' is tacked on
+# for section 1 manuals, etc
+MANDIR= ${DESTDIR}/usr/man
+
+# The subdirectories. N.B.: "lib" must appear first!
+SUBDIR= lib dev dvi
+
+OPTS= MFLAGS="${MFLAGS}" BINDIR=${BINDIR} MANDIR=${MANDIR} \
+ CONFFILE=${CONFFILE} DESTDIR=${DESTDIR} CC=${CC} ${MFLAGS}
+
+all:
+ for i in ${SUBDIR}; do (cd $$i; ${MAKE} ${OPTS}); done
+
+install clean depend:
+ for i in ${SUBDIR}; do (cd $$i; ${MAKE} ${OPTS} $@); done
+
+# this one is special
+conf:
+ cd dev; ${MAKE} conf
+
+# make the distribution directory -- assumes no RCS files in top level
+# `doc' is not yet ready
+dist:
+ rm -rf ../ctex_dist
+ -mkdir ../ctex_dist
+ -set -x +e; \
+ for i in *; do \
+ if [ $$i != ctex ]; then \
+ if [ -d $$i ]; then \
+ cp -r $$i ../ctex_dist; \
+ (cd ../ctex_dist/$$i; rm -rf RCS); \
+ else \
+ cp $$i ../ctex_dist; \
+ fi; \
+ fi; \
+ done
+ -cd ../ctex_dist; \
+ echo '/CONFFILE=/s,local/,,!/MANDIR= /s,local/,,!w!q' | \
+ tr ! '\012' | ed Makefile
+ -cd ../ctex_dist; make clean
+ -cd ../ctex_dist/dev; make dist
diff --git a/dviware/umddvi/makefile.3b b/dviware/umddvi/makefile.3b
new file mode 100644
index 0000000000..34bb7d0b95
--- /dev/null
+++ b/dviware/umddvi/makefile.3b
@@ -0,0 +1,54 @@
+# Makefile for everything
+#
+# Eventually, it would be nice to have various targets depending on
+# the output devices, and pass that info down to the dev/ directory.
+# For now, this will do.
+DESTDIR=
+MAKE= make
+MFLAGS=
+
+# where to find the font description file
+CONFFILE=/usr/lib/tex/fonts
+# where things get installed
+BINDIR= ${DESTDIR}/usr/local/bin
+# where manuals get installed---note that `/man1' is tacked on
+# for section 1 manuals, etc
+MANDIR= ${DESTDIR}/usr/man
+
+# The subdirectories. N.B.: "lib" must appear first!
+SUBDIR= lib dev dvi
+
+OPTS= MFLAGS="${MFLAGS}" BINDIR=${BINDIR} MANDIR=${MANDIR} \
+ CONFFILE=${CONFFILE} DESTDIR=${DESTDIR} CC=${CC} ${MFLAGS}
+
+all:
+ for i in ${SUBDIR}; do (cd $$i; ${MAKE} ${OPTS}); done
+
+install clean depend:
+ for i in ${SUBDIR}; do (cd $$i; ${MAKE} ${OPTS} $@); done
+
+# this one is special
+conf:
+ cd dev; ${MAKE} conf
+
+# make the distribution directory -- assumes no RCS files in top level
+# `doc' is not yet ready
+dist:
+ rm -rf ../ctex_dist
+ -mkdir ../ctex_dist
+ -set -x +e; \
+ for i in *; do \
+ if [ $$i != ctex ]; then \
+ if [ -d $$i ]; then \
+ cp -r $$i ../ctex_dist; \
+ (cd ../ctex_dist/$$i; rm -rf RCS); \
+ else \
+ cp $$i ../ctex_dist; \
+ fi; \
+ fi; \
+ done
+ -cd ../ctex_dist; \
+ echo '/CONFFILE=/s,local/,,!/MANDIR= /s,local/,,!w!q' | \
+ tr ! '\012' | ed Makefile
+ -cd ../ctex_dist; make clean
+ -cd ../ctex_dist/dev; make dist
diff --git a/dviware/umddvi/man/dvidmd.1 b/dviware/umddvi/man/dvidmd.1
new file mode 100644
index 0000000000..df5f293801
--- /dev/null
+++ b/dviware/umddvi/man/dvidmd.1
@@ -0,0 +1,186 @@
+.TH DVIDMD 1
+.SH NAME
+dvidmd \- DVI previewer for DMD 5620 display
+.SH SYNOPSIS
+.B
+dvidmd [-x] [-m mag] [-R res] [-d drift] [-X xoffset] [-Y yoffset] [file]
+.SH DESCRIPTION
+.I dvidmd
+is used to display DVI files on the 5620 DMD terminal.
+DVI files are generated by programs such as TeX and LaTeX.
+.PP
+Like all DMD applications,
+.I dvidmd
+is really two separate programs, one of which runs in the host
+and the other which runs in the terminal. For
+.I dvidmd ,
+the host program's main job is to interpret DVI commands and
+read files that contain font information. The slave's main job
+is to handle display operations such as copying character
+rasters to the correct positions on the screen.
+.PP
+When the host program is started, it will check if the slave
+program is already running in that terminal window. If the slave
+program is not running, it will automatically be downloaded into
+that window by the host program. While the download is in progress,
+a coffee-cup cursor will appear in that window.
+.LP
+.B "Host Program Options"
+.PP
+The host program supports a variety of options:
+.TP 10
+-x
+Cause the
+.I dvidmd
+slave program to exit
+once the host program has finished. By default the slave program
+switches to terminal emulation mode (see below).
+.TP 10
+-m mag
+Explicitly magnify the image by the specified amount. A typically
+value might be 1.2, corresponding to \emagstep1 in TeX.
+.TP 10
+-R \fIres\fP
+Specify the assumed output resolution of the DMD display. This
+value defaults to 118 dots per inch. Although this is not the
+actual resolution of the DMD 5620, it is a standard
+resolution that font files are distributed for in the TeX
+distribution. Other reasonable device resolutions (disk space
+permitting) are 200 and 300 dots per inch, which in effect
+magnify the image a corresponding amount.
+.TP 10
+-d \fIdrift\fP
+A spacing parameter used in setting type on the display. The
+default value is generally fine.
+.TP 10
+-X \fIxoffset\fP
+Specify the horizontal offset in tenths of an inch.
+.TP 10
+-Y \fIyoffset\fP
+Specify the vertical offset in tenths of an inch.
+.LP
+If no
+.I file
+argument is specified then the host program exits, but only after
+loading the slave program if necessary.
+.LP
+.B "Slave Emulation Modes"
+.PP
+The slave program can be in one of two modes: typesetter emulation
+mode and terminal emulation mode. Typesetter emulation mode
+is used by the
+.I dvidmd
+host program to display DVI files; it allows arbitrary glyphs to
+be displayed anywhere on the screen.
+.PP
+Terminal emulation mode
+can be used by arbitrary programs to interact with the user;
+this mode uses the default terminal font for its display.
+However, only a few escape sequences are interpreted by
+the terminal emulator, so it can only be used by programs
+that work properly on ``dumb'' terminals. In particular,
+a screen editor such as
+.IR vi (1)
+will not work properly in terminal emulation mode; use another
+window for these more sophisticated programs.
+.PP
+Note that glyphs downloaded by the
+.I dvidmd
+host program in typesetter mode are saved by the slave program in
+terminal memory. Therefore, future runs of
+.I dvidmd
+(in the same window) run much faster since they need not reload the
+(rather large) raster data.
+.LP
+.B "Page Commands"
+.PP
+When the slave program is in typesetter emulation mode, it will display
+data until it receives an end of page command. At this point it will
+change the cursor to a "CMD" prompt and wait for input from the user.
+If the user holds down mouse button 3, a menu will appear with various
+choices:
+.TP 10
+\fBredraw\fP
+Redraw the current screen, resetting the origin to the upper left hand
+corner of the page.
+.TP 10
+\fBnext\fP
+Display the next screen-full of data.
+If the bottom of the page is currently being displayed,
+the next page of data is requested from the host program.
+.TP 10
+\fBprev\fP
+Display the previous screen-full of data.
+If the top of the page is currently being displayed,
+the previous page of data is requested from the host program.
+.TP 10
+\fBquit\fP
+Cause the slave program to leave the typesetter emulation mode and enter
+the terminal emulation mode. Choose this option if you plan to run
+.I dvidmd
+again.
+.TP 10
+\fPexit\fP
+Causes the slave program to exit. The default DMD 5620 terminal emulator
+is reloaded into the window. All glyphs downloaded into the terminal
+are freed.
+.LP
+Alternatively, you can invoke the above paging commands by typing
+the first letter of the command name. So, for example, type `p'
+for previous, `n' for next, and `q' for quit. In addition, the
+following character commands are also available:
+.TP 10
+\fB+\fP or \fB<RET>\fP
+Request the next page of data from the host program, resetting the
+origin to the upper left hand corner of the page.
+.TP 10
+\fB-\fP
+Request the previous page of data from the host program, resetting the
+origin to the upper left hand corner of the page.
+.TP 10
+\fB<SPACE>\fP
+Another way of typing the next command.
+.TP 10
+\fB^L\fP
+Another way of typing the redraw command.
+.LP
+.B "Scrolling Commands"
+.PP
+At the end of page, the user can scroll the display by moving the mouse
+cursor into the scrolling area. The scrolling area is along the left
+and bottom edges of the screen, and its edges are marked by small segments
+in the corners of the display. When the mouse is positioned in the scrolling
+area, the mouse cursor will change into a cross-hair shape.
+.PP
+For vertical scrolling, position the mouse in the left scroll bar (between
+the two horizontal marks at the top and bottom of the screen).
+Clicking button 1 in the left scroll bar will
+bring the line at the current mouse position to the top of the window,
+while clicking button 3 will bring the line at the top of the
+screen down to the current mouse position. Thus these two buttons
+function as inverses of each other.
+.PP
+For horizontal scrolling, position the mouse in the bottom scroll bar,
+and then use button 1 to bring the current mouse position
+to the left edge of the screen. As expected, button 3 performs the
+inverse operation: it brings the left edge of the screen to the current
+mouse position.
+.PP
+If the mouse is positioned in the scroll ``box'' in the lower left corner
+of the screen, clicking button 1 will advance to the next screen,
+clicking button 2 will redraw the screen, and clicking button 3 will go
+back to the previous screen.
+.SH "SEE ALSO
+tex(1), tpic(1)
+.SH FILES
+/usr/local/bin/dvidmd.j \- layers slave program
+.br
+/usr/local/bin/dvidmd.m \- host slave program
+.SH BUGS
+The scrolling interface needs some work and is too slow.
+.br
+The terminal emulation mode needs to support more escape sequences.
+.br
+More graphics commands should be interpreted. Right now only the
+.IR tpic (1)
+primitives are supported.
diff --git a/dviware/umddvi/man/dvipr.1 b/dviware/umddvi/man/dvipr.1
new file mode 100644
index 0000000000..4d1acc7767
--- /dev/null
+++ b/dviware/umddvi/man/dvipr.1
@@ -0,0 +1,96 @@
+.TH DVIPR 1
+.SH NAME
+dvipr \- print dvi version 2 files, produced by TeX82, to the Versatec
+.SH SYNOPSIS
+.B dvipr
+[
+.B \-q
+] [
+.B \-v
+] [
+.B \-c
+] [
+.B \-m
+.I number
+] [
+.B \-h
+] [
+.B \-s
+] [
+.B \-d
+.I number
+]
+.I .dvi file name
+.SH DESCRIPTION
+.I dvipr
+prints .dvi files produced by
+.IR TeX (1)
+on the Versatec. The basic process involves two passes. In the first
+pass, the .dvi file is converted into a list of characters.
+The second pass takes this list and prints it onto the Versatec. When
+the
+.B \-q
+option (for quiescent) is invoked, intermediate output is not spooled
+to the Versatec; instead, it is written to the standard output. The
+.B \-v
+option (for Versatec) is used to print this intermediate output.
+The
+.B \-c
+option indicates you want to have your output centered on the page.
+Otherwise, a default left margin is used. The
+.B \-m
+.I number
+option is used to change the device magnification (which is in addition to
+any magnification defined in the TeX source file).
+.I number
+should be replaced by an integer which is 1000 times the magnification
+you want.
+for example,
+.B \-m 1315
+would produce output magnified to 131.5% of true size. Using device
+magnification is most useful when you are trying to produce a output for
+publication. (Many photocopiers will reduce output to 77% of size. When you
+reduce output printed at 131.5% to 77%, you
+get close to the true size.) The default is
+no magnification (1000). Note, however, that a site will only
+support particular magnifications. If you get error messages indicating that
+fonts are missing when using this option, you probably have picked an
+unsupported magnification.
+.PP
+The
+.B \-h
+flag, when
+supplied, causes printing to be done vertically on the page.
+This is only useful if you plan to use a reducing copier.
+.PP
+Normally the first pass prints the page numbers from the .dvi file. The
+.B \-s
+flag suppresses these.
+.PP
+The default
+.I maxdrift
+parameter is 2 pixels (1/100th of an inch); the
+.B \-d
+option may be used to alter this. The
+.I maxdrift
+parameter determines just how much font spacing is allowed to
+influence character positioning. The value 2 allows a small amount of
+variation within words without allowing any letters to become too far
+out of position; this had been happening in rare cases before the
+.I maxdrift
+code was added.
+.SH FILES
+/usr/local/dvipr
+.br
+/usr/local/verser1 first pass
+.br
+/usr/local/verser2 second pass
+.SH SEE ALSO
+dviselect(1), iptex(1), tex(1)
+.SH AUTHOR
+The original version was written by Janet Incerpi of Brown University.
+Richard Furuta and Carl Binding of the University of Washington
+modified the programs for DVI version 2 files. Chris Torek of
+the University of Maryland rewrote
+both passes in order to make them run at reasonable speeds.
+.SH BUGS
diff --git a/dviware/umddvi/man/dviselect.1 b/dviware/umddvi/man/dviselect.1
new file mode 100644
index 0000000000..79d9df926a
--- /dev/null
+++ b/dviware/umddvi/man/dviselect.1
@@ -0,0 +1,110 @@
+.TH DVISELECT 1
+.SH NAME
+dviselect \- extract pages from DVI files
+.SH SYNOPSIS
+.B dviselect
+[
+.B \-s
+] [
+.B \-i
+.I infile
+] [
+.B \-o
+.I outfile
+]
+.I "list of pages"
+[
+.I infile
+[
+.I outfile
+] ]
+.SH DESCRIPTION
+.I Dviselect
+selects pages from a DVI file produced by TeX, creating a new DVI
+file usable by any of TeX's conversion program (e.g., iptex), or even
+by dviselect itself.
+.PP
+A
+.I range
+is a string of the form
+.I first:last
+where both
+.I first
+and
+.I last
+are optional numeric strings, with negative numbers indicated by
+a leading underscore character ``_''. If both
+.I first
+and
+.I last
+are omitted, the colon may also be omitted, or may be replaced
+with an asterisk ``*''. A
+.I page range
+is a list of ranges separated by periods. A
+.I "list of pages"
+is described by a set of page ranges separated by commas and/or white space.
+.PP
+.I Dviselect
+actually looks at the ten
+.I count
+variables that TeX writes; the first of these (\ecount0) is the
+page number, with \ecount1 through \ecount9 having varied uses
+depending on which macro packages are in use. (Typically \ecount1
+is a chapter or section number.) A page is included in
+.IR dviselect 's
+output if all its \ecount values are within any one of the ranges
+listed on the command line. For example, the command
+``dviselect *.1,35:''
+might select everything in chapter 1, as well as pages 35 and up.
+``dviselect 10:30'' would select pages 10 through 30 (inclusive).
+``:43'' means everything up to and including page 43 (including
+negative-numbered pages).
+If a Table of Contents has negative page numbers, ``:_1'' will select it.
+``*.4 .........1'' might
+mean everything in every chapter 4 and an index, presuming \ecount9
+was set to 1 in the index. (``*'' must be quoted from the shell;
+the null string is more convenient to use, if harder to read.)
+.PP
+Instead of \ecount values,
+.I dviselect
+can also select by ``absolute page number'', where the first page
+is page 1, the second page 2, and so forth. Absolute page numbers
+are indicated by a leading equal sign ``=''. Ranges of absolute
+pages are also allowed: ``dviselect =3:7'' will extract the third
+through seventh pages. Dot separators are not legal in absolute
+ranges, and there are no negative absolute page numbers.
+.PP
+More precisely, an asterisk or a null string implies no limit;
+an equal sign means absolute pages rather than \ecounts;
+a leading colon means everything up to and including the given page; a
+trailing colon means everything from the given page on; and
+a period indicates that the next \ecount should be examined.
+If fewer than 10 ranges are specified, the remaining \ecounts
+are left unrestricted (that is, ``1:5'' and ``1:5.*'' are equivalent).
+A single number \fIn\fP is treated as if it were the range \fIn:n\fP.
+An arbitrary number of page selectors may be given, separated by commas
+or whitespace; a page is selected if any of the selectors matches
+its \ecounts or absolute page number.
+.PP
+Dviselect normally prints the page numbers of the pages selected; the
+.I \-s
+option suppresses this.
+.SH AUTHOR
+Chris Torek, University of Maryland
+.SH "SEE ALSO"
+dvipr(1), iptex(1), tex(1), \fIThe TeXbook\fP
+.SH BUGS
+A leading ``-'' ought to be allowed for negative numbers, but it
+is currently used as a synonym for ``:'', for backwards compatibility.
+.PP
+Section or subsection selection will sometimes fail, for the DVI
+file lists only the \ecount values that were active when the page
+ended. Clever macro packages can alleviate this by making use of
+other ``free'' \ecount registers. Chapters normally begin on new
+pages, and do not suffer from this particular problem.
+.PP
+.I Dviselect
+does not adjust the parameters in the postamble; however, since these
+values are normally used only to size certain structures in the output
+conversion programs, and the parameters never need to be adjusted upward,
+this has not proven to be a problem.
diff --git a/dviware/umddvi/man/iptex.1 b/dviware/umddvi/man/iptex.1
new file mode 100644
index 0000000000..5af0c74d31
--- /dev/null
+++ b/dviware/umddvi/man/iptex.1
@@ -0,0 +1,126 @@
+.TH IPTEX 1
+.SH NAME
+iptex \- print DVI files on the Imagen
+.SH SYNOPSIS
+.B iptex
+[
+.B \-c
+] [
+.B \-d
+.I maxdrift
+] [
+.B \-l
+] [
+.B \-m
+.I magnification
+] [
+.B \-p
+] [
+.B \-r
+.I resolution
+] [
+.B \-s
+] [
+.B \-X
+.I x-offset
+] [
+.B \-Y
+.I y-offset
+]
+.I filename
+.SH DESCRIPTION
+.I Iptex
+takes a DVI file produced by TeX and converts it to a format suitable
+for the Imagen series printers.
+.I filename
+should be the name of a
+.B .dvi
+file, or ``\-'' for standard input (useful for reading the output
+of the
+.I dviselect
+program). By default,
+.I iptex
+produces output for
+a 300 dpi printer (the 8/300) but this may be overridden with the
+.I \-r
+flag:
+.B "\-r 240"
+produces output suitable for the Imprint-10 (a.k.a. the 10/240).
+.PP
+To get landscape mode (rather than portrait mode) output, use the
+.B \-l
+flag. However, this has not been extensively tested.
+.PP
+The
+.I \-m
+flag applies a global magnification to the output. If you have slides
+that are to be reduced, you can fiddle with the output size using \-m.
+(By the way, \-r is really \-m in disguise.)
+.PP
+Normally, iptex will print the page number of each page (actually
+the value in \\count0) as it runs, to demonstrate its blinding speed.
+If this is not desired, use the
+.I \-s
+option to suppress unnecessary verbiage. (And yes, it really
+.I is
+supposed to count down from the last page.)
+.PP
+.I Iptex
+is actually a shell script that invokes the conversion program and
+feeds its output to Imagen's
+.I ipr
+command. Normally this is done by creating a file in $TMPDIR
+(default /tmp), so that missing fonts can be caught before ipr
+runs away with the output. However, if desired, you can force
+the output to be piped directly to ipr with the
+.I \-c
+flag.
+.PP
+The
+.I maxdrift
+parameter controls
+.BR iptex 's
+behaviour under certain obscure conditions. Because it is so rarely
+needed, and because 2 is such a wonderful default, I am not going to
+tell you exactly what it really does. (Besides, I have not yet
+figured out how to describe it.)
+.PP
+There are three options that are normally only useful to people installing
+.I iptex
+which are quickly summarized here:
+.B \-p
+prevents page reversal (useful with the Ricoh engine);
+.B \-X
+and
+.B \-Y
+set an offset to apply to every page (useful with the LBP-10, for
+example, where output starts a few tenths of an inch away from the upper
+left hand corner of the page). The offsets are in tenths of an inch
+and may be negative. Default offsets should be set in the
+.I iptex
+shell script; they will be overridden by explicit
+.B \-X
+and
+.B \-Y
+arguments.
+.SH DIAGNOSTICS
+Most of these should be self explanatory. The message ``unable to
+copy input to temp file'' should only occur when reading standard
+input, and indicates that the temporary file required when reading
+pipes is too large for wherever it is being stored. The environment
+variable ``TMPDIR'' defines which file system is used for this
+temporary file; the default is /tmp. Either put the intermediate DVI
+file in a real disk file, or set TMPDIR, in such cases.
+.SH AUTHOR
+Chris Torek, University of Maryland
+.br
+Mike Urban (TRW) added the \-p, \-X, and \-Y options.
+.SH FILES
+imagen1 - conversion program
+.br
+ipr - Imagen spooler
+.SH "SEE ALSO"
+dvipr(1), dviselect(1), tex(1)
+.SH BUGS
+.I Still
+needs to handle more ``\especial''s.
diff --git a/dviware/umddvi/misc/bcopy.c b/dviware/umddvi/misc/bcopy.c
new file mode 100644
index 0000000000..99a72e2979
--- /dev/null
+++ b/dviware/umddvi/misc/bcopy.c
@@ -0,0 +1,17 @@
+#ifndef lint
+static char rcsid[] = "$Header$";
+#endif
+
+/*
+ * Sample bcopy() routine.
+ * This should be rewritten to be as fast as possible for your
+ * machine.
+ */
+bcopy(from, to, count)
+ register char *from, *to;
+ register int count;
+{
+
+ while (--count >= 0)
+ *to++ = *from++;
+}
diff --git a/dviware/umddvi/misc/bzero.c b/dviware/umddvi/misc/bzero.c
new file mode 100644
index 0000000000..c46eeb4305
--- /dev/null
+++ b/dviware/umddvi/misc/bzero.c
@@ -0,0 +1,17 @@
+#ifndef lint
+static char rcsid[] = "$Header$";
+#endif
+
+/*
+ * Sample bzero() routine.
+ * This should be rewritten to be as fast as possible for your
+ * machine.
+ */
+bzero(addr, count)
+ register char *addr;
+ register int count;
+{
+
+ while (--count >= 0)
+ *addr++ = 0;
+}
diff --git a/dviware/umddvi/misc/check.sh b/dviware/umddvi/misc/check.sh
new file mode 100644
index 0000000000..db0be6513d
--- /dev/null
+++ b/dviware/umddvi/misc/check.sh
@@ -0,0 +1,21 @@
+#! /bin/sh
+#
+# check - check the width tables of all the PXL fonts
+#
+# usage: check directory-name
+
+case $# in
+1) ;;
+*) echo "usage: check directory-name" 1>&2; exit 1;;
+esac
+
+checker=`pwd`/checkw
+
+cd "$1"
+
+for tfm in *.tfm; do
+ base=`basename $tfm .tfm`
+ for pxl in $base.*pxl; do
+ $checker -q $tfm $pxl
+ done
+done
diff --git a/dviware/umddvi/misc/checkw.1 b/dviware/umddvi/misc/checkw.1
new file mode 100644
index 0000000000..821d3a1eae
--- /dev/null
+++ b/dviware/umddvi/misc/checkw.1
@@ -0,0 +1,50 @@
+.TH CHECKW 1
+.SH NAME
+checkw \- check and patch up PXL files whose TFM widths are wrong
+.SH SYNOPSIS
+.B checkw
+[
+.B -f
+] [
+.B -q
+] [
+.B -s
+]
+.I tfmfile
+.I pxlfile
+.SH DESCRIPTION
+.I Checkw
+is a program that ought to be unnecessary, but there is
+a bug in Metafont that produces incorrect TFM widths in PXL
+files for characters that are zero pixels wide.
+.I Checkw
+reads the named TFM and PXL files, which should
+be for the same font, and compares
+the width tables of each. A message is printed indicating whether
+the tables match. If the
+.B -f
+(``fix'') option is given,
+.I checkw
+writes the correct widths back to the PXL file.
+.PP
+The
+.B -s
+(``silent'') option makes
+.I checkw
+operate silently (only exit status is returned). The
+.B -q
+(``quiet'') option makes checkw complain if the TFM and PXL
+files do not match, but otherwise run silently.
+.SH DIAGNOSTICS
+Exit value is 0 if the fonts match or were corrected, 1 if they
+do not, and 2 for any other error. Various messages may be
+printed to the standard error output if things go wrong; they
+are intended to be self explanatory, unless they should ``never happen''.
+If the message does not
+mention a damaged PXL file, the file has not been touched.
+.SH AUTHOR
+Chris Torek, University of Maryland
+\" .SH FILES
+\" .SH "SEE ALSO"
+.SH BUGS
+The bugs are in Metafont. \" :-)
diff --git a/dviware/umddvi/misc/checkw.c b/dviware/umddvi/misc/checkw.c
new file mode 100644
index 0000000000..d318b7e11b
--- /dev/null
+++ b/dviware/umddvi/misc/checkw.c
@@ -0,0 +1,342 @@
+#ifndef lint
+static char rcsid[] = "$Header$";
+#endif
+
+/*
+ * checkw -- check & fix the TFM widths in a PXL file
+ *
+ * Usage: checkw [-f] [-s] tfmfile pxlfile
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "../h/types.h"
+#include "../h/fio.h"
+
+char *ProgName;
+
+struct tfmheader {
+ int th_lf; /* length of the file (words) */
+ int th_lh; /* length of the header data (words) */
+ int th_bc; /* smallest char code in font */
+ int th_ec; /* largest char code in font (inclusive) */
+ int th_nw; /* number of words in width table */
+ int th_nh; /* number of words in height table */
+ int th_nd; /* number of words in depth table */
+ int th_ni; /* number of words in ital. corr. table */
+ int th_nl; /* number of words in lig/kern table */
+ int th_nk; /* number of words in kern table */
+ int th_ne; /* number of words in extensible char table */
+ int th_np; /* number of font param words */
+};
+
+/*
+ * The rest of the TFM file is composed of the following information,
+ * all of which are 32 bit quantities:
+ *
+ * header: array [0..lh-1] of stuff
+ * char_info: array [bc..ec] of char_info_word
+ * width: array [0..nw-1] of fix_word
+ * height: array [0..nh-1] of fix_word
+ * depth: array [0..nd-1] of fix_word
+ * italic: array [0..ni-1] of fix_word
+ * lig_kern: array [0..nl-1] of lig_kern_command
+ * kern: array [0..nk-1] of fix_word
+ * exten: array [0..ne-1] of extensible_recipie
+ * param: array [1..np] of fix_word
+ *
+ * We are interested only in the width information. This can be
+ * found by taking the first byte of each of the char_info_words
+ * and using it as an index in the width table. That is, the
+ * width of character $n$ is width[char_info[$n$-$bc$].width_index].
+ */
+
+struct char_info_word {
+ char width_index;
+ char height_and_depth_index;
+ char italic_index_and_tag;
+ char remainder;
+};
+
+/*
+ * A PXL file ends with 2068 bytes of information which includes the
+ * TFM widths and some other stuff (some of which we don't need, some
+ * of which we do; it's easiest to just read it all).
+ */
+#define PXBUFSIZE 2068
+
+#define PXL_ID 1001
+
+#define PXIDOFF 2064 /* PXL_ID found here */
+#define PXTFMOFF(n) (((n) << 4) + 12)/* TFM width of char $n$ here */
+
+int FFlag; /* -f => fix */
+int SFlag; /* -s => silent */
+int QFlag; /* -q => quiet (like -s if match) */
+char *tfname; /* name of the TFM file */
+FILE *tf; /* the TFM file */
+char *pxname; /* name of the PXL file */
+int px; /* we don't use stdio on the pxl file */
+char pxbuf[PXBUFSIZE]; /* the tail of the PXL file */
+long pxtailoff; /* tells where pxbuf goes */
+struct tfmheader th; /* the TFM file's header information */
+i32 *width; /* the TFM width tables */
+struct char_info_word *char_info;/* the TFM character info tables */
+
+#define WIDTH(c) width[char_info[(c) - th.th_bc].width_index]
+
+extern char *optarg;
+extern int optind;
+extern int errno;
+
+char *malloc ();
+long lseek ();
+
+/*
+ * Exit stati.
+ */
+#define EX_OK 0 /* all is well in fontland */
+#define EX_NOMATCH 1 /* didn't match, didn't update PXL file */
+#define EX_OTHER 2 /* other error (invalid command, etc.) */
+
+main (argc, argv)
+register int argc;
+register char **argv; {
+ register int c;
+
+ ProgName = argv[0];
+ while ((c = getopt (argc, argv, "fqs")) != EOF) {
+ switch (c) {
+ case 'f':
+ FFlag++;
+ break;
+ case 'q':
+ QFlag++;
+ break;
+ case 's':
+ SFlag++;
+ break;
+ case '?':
+usage:
+ error (EX_OTHER, 0, "usage: %s [-f] [-s] tfmfile pxlfile",
+ ProgName);
+ /*NOTREACHED*/
+ }
+ }
+ if (argc - optind != 2)
+ goto usage;
+ tfname = argv[optind];
+ pxname = argv[optind + 1];
+ if ((tf = fopen (tfname, "r")) == NULL)
+ error (EX_OTHER, errno, "can't open %s for reading", tfname);
+ if ((px = open (pxname, FFlag ? 2 : 0)) < 0)
+ error (EX_OTHER, errno, "can't open %s for %s", pxname,
+ FFlag ? "update" : "reading");
+ ReadPXLTail ();
+ ReadTFMHeader ();
+ if (th.th_ec < th.th_bc)
+ error (EX_OTHER, 0, "\
+Are you sure %s is a TFM file? It contains no characters!", tfname);
+ if (th.th_bc < 0 || th.th_ec > 127)
+ error (EX_OTHER, 0, "\
+I don't see how %s can correspond to your PXL file.\n\
+(It has a first character entry of %d, and a last of %d.)",
+ tfname, th.th_bc, th.th_ec);
+ AllocateCharTable (th.th_ec - th.th_bc + 1);
+ AllocateWidthTable (th.th_nw);
+ SkipHeader ();
+ ReadCharInfo (th.th_ec - th.th_bc + 1);
+ ReadWidthTable (th.th_nw);
+ if (WidthsMatch ()) {
+ if (!SFlag && !QFlag)
+ printf ("%s: width tables for %s match %s\n", ProgName,
+ pxname, tfname);
+ exit (EX_OK);
+ }
+ if (!FFlag) {
+ if (!SFlag)
+ printf ("%s: width tables for %s and %s do not match\n", ProgName,
+ pxname, tfname);
+ exit (EX_NOMATCH);
+ }
+ if (!SFlag)
+ printf ("%s: width tables for %s and %s do not match; updating...\n",
+ ProgName, pxname, tfname);
+ FixPXLTail ();
+ WritePXLTail ();
+ if (!SFlag)
+ printf ("%s: width tables in %s updated.\n", ProgName, pxname);
+ exit (EX_OK);
+}
+
+/*
+ * Called if the TFM file seems to be bogus.
+ */
+BadTFMFile () {
+ error (EX_OTHER, 0, "unexpected EOF -- are you sure %s is a TFM file?",
+ tfname);
+ /* NOTREACHED */
+}
+
+/*
+ * Allocate n character info table entries.
+ */
+AllocateCharTable (n)
+register int n; {
+ char_info = (struct char_info_word *)
+ malloc ((unsigned) n * sizeof *char_info);
+ if (char_info == 0)
+ error (EX_OTHER, errno, "unable to allocate %d char table entries", n);
+}
+
+/*
+ * Allocate n width table entries.
+ */
+AllocateWidthTable (n)
+register int n; {
+ width = (i32 *) malloc ((unsigned) n * sizeof *width);
+ if (width == 0)
+ error (EX_OTHER, errno,
+ "unable to allocate %d width table entries", n);
+}
+
+/*
+ * Read the TFM header.
+ */
+ReadTFMHeader () {
+ register int *ip, i;
+
+ for (ip = &th.th_lf; ip <= &th.th_np;) {
+ i = UnSign16 (GetWord (tf));
+ *ip++ = i; /* ``cheating'' */
+ }
+ /* We could do something nice like make sure the actual file size and the
+ reported size (tf.tf_lf * 4?) are the same... naaah. */
+}
+
+/*
+ * Skip over the miscellaneous header info in the TFM file.
+ */
+SkipHeader () {
+ (void) fseek (tf, (long) th.th_lh * sizeof (i32), 1);
+}
+
+/*
+ * Read the character info table from the TFM file. (We get all
+ * of it, even though we're only going to use the width index.)
+ */
+ReadCharInfo (n)
+register int n; {
+ register struct char_info_word *ci;
+
+ for (ci = char_info; --n >= 0; ci++) {
+ ci -> width_index = getc (tf);
+ ci -> height_and_depth_index = getc (tf);
+ ci -> italic_index_and_tag = getc (tf);
+ ci -> remainder = getc (tf);
+ }
+ if (feof (tf))
+ BadTFMFile ();
+}
+
+/*
+ * Read the width table from the TFM file.
+ */
+ReadWidthTable (n)
+register int n; {
+ register i32 *ip;
+
+ for (ip = width; --n >= 0; ip++)
+ fGetLong (tf, *ip);
+
+ if (feof (tf))
+ BadTFMFile ();
+}
+
+/*
+ * Get a 32 bit quantity from the specified offset in the pxl buffer.
+ */
+i32
+GetPXLong (off) {
+ register char *p = pxbuf + off;
+ register i32 rv;
+
+ rv = UnSign8 (*p++) << 24;
+ rv |= UnSign8 (*p++) << 16;
+ rv |= UnSign8 (*p++) << 8;
+ rv |= UnSign8 (*p);
+ return rv;
+}
+
+/*
+ * Put the specified value in the pxl buffer at the given offset.
+ * N.B.: assuming 8 bit bytes (since val >> n might be signed).
+ */
+PutPXLong (off, val)
+int off;
+register i32 val; {
+ register char *p = pxbuf + off;
+
+ *p++ = val >> 24;
+ *p++ = val >> 16;
+ *p++ = val >> 8;
+ *p = val;
+}
+
+/*
+ * Read (and verify) the end part of the pxl file.
+ */
+ReadPXLTail () {
+ struct stat st;
+
+ if (fstat (px, &st))
+ error (EX_OTHER, errno, "fstat(%s)", px, pxname);
+ if (st.st_size & 3 || st.st_size < PXBUFSIZE)
+ error (EX_OTHER, 0, "%s doesn't seem to be a pxl file", pxname);
+ pxtailoff = st.st_size - PXBUFSIZE;
+ if (lseek (px, pxtailoff, 0) != pxtailoff)
+ error (EX_OTHER, errno, "lseek(%s) didn't return %ld", pxname,
+ pxtailoff);
+ if (read (px, pxbuf, PXBUFSIZE) != PXBUFSIZE)
+ error (EX_OTHER, errno, "read(%s)", pxname);
+ if (GetPXLong (PXIDOFF) != PXL_ID)
+ error (EX_OTHER, 0, "%s doesn't seem to be a PXL file.",
+ pxname);
+}
+
+/*
+ * Write the end part of the PXL file back to the original PXL file.
+ */
+WritePXLTail () {
+ if (lseek (px, pxtailoff, 0) != pxtailoff)
+ error (EX_OTHER, errno, "lseek(%s) didn't return %ld", pxname,
+ pxtailoff);
+ if (write (px, pxbuf, PXBUFSIZE) != PXBUFSIZE)
+ error (EX_OTHER, errno, "write(%s) failed---pxl file may be damaged",
+ pxname);
+}
+
+/*
+ * Compare the width values in the PXL tail buffer with those in the
+ * TFM width tables. Return 1 iff they all match.
+ */
+WidthsMatch () {
+ register int i;
+
+ for (i = th.th_bc; i <= th.th_ec; i++)
+ if (GetPXLong (PXTFMOFF (i)) != WIDTH (i))
+ return 0; /* a mismatch */
+ /* perhaps we should make sure the rest are 0... oh well */
+ return 1;
+}
+
+/*
+ * Fix the width values in the PXL file tail buffer.
+ */
+FixPXLTail () {
+ register int i;
+
+ for (i = th.th_bc; i <= th.th_ec; i++)
+ PutPXLong (PXTFMOFF (i), WIDTH (i));
+}
diff --git a/dviware/umddvi/misc/fixfix.c b/dviware/umddvi/misc/fixfix.c
new file mode 100644
index 0000000000..220af31049
--- /dev/null
+++ b/dviware/umddvi/misc/fixfix.c
@@ -0,0 +1,68 @@
+#ifndef lint
+static char rcsid[] = "$Header$";
+#endif
+
+/*
+ * fixfix - fix the number of FIXes for a particular character in
+ * a particular font.
+ *
+ * Compilation:
+ % cc -O -o fixfix fixfix.c
+ */
+
+#include <stdio.h>
+
+main (argc, argv)
+int argc;
+register char **argv;
+{
+ register int i, fd, newn, t;
+ static char buf[4];
+
+ if (argc != 4) {
+ fprintf (stderr, "usage: fixfix font index fixes\n");
+ exit (1);
+ }
+ if ((fd = open (argv[1], 2)) < 0) {
+ perror (argv[1]);
+ exit (1);
+ }
+ i = atoi (argv[2]);
+ if (i < 0 || i > 127) {
+ fprintf (stderr, "%d: invalid char index (<0 || >127)", i);
+ exit (1);
+ }
+ newn = atoi (argv[3]);
+ (void) lseek (fd, 0L, 2);
+ (void) lseek (fd, -2068L + 16L*i + 12L, 1);
+ if (read (fd, buf, 4) != 4) {
+ perror ("read");
+ exit (1);
+ }
+ t = get (buf);
+ printf ("fixfix: char %d: old size = %d\n", i, t);
+ put (newn, buf);
+ (void) lseek (fd, -4L, 1);
+ if (write (fd, buf, 4) != 4) {
+ perror ("write");
+ exit (1);
+ }
+ exit (0);
+}
+
+int
+get (buf)
+register unsigned char *buf;
+{
+ return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
+}
+
+put (n, buf)
+register int n;
+register unsigned char *buf;
+{
+ buf[0] = n >> 24;
+ buf[1] = n >> 16;
+ buf[2] = n >> 8;
+ buf[3] = n;
+}
diff --git a/dviware/umddvi/misc/fontdesc b/dviware/umddvi/misc/fontdesc
new file mode 100644
index 0000000000..e0af700b73
--- /dev/null
+++ b/dviware/umddvi/misc/fontdesc
@@ -0,0 +1,21 @@
+#
+# Sample C-TeX font configuration file.
+#
+# N.B.: choose only one of `box' or `blank' TFM fonts.
+
+# current directory always searched first
+# TYPE SPEC SLOP PATH
+font gf * 3 %f.%mgf
+font pxl * 3 %f.%mpxl
+font pk * 3 %f.%mpk
+# this is not pretty
+font blank * 1 i/%f.tfm
+font box * 1 %f.tfm
+
+# TYPE SPEC SLOP PATH
+font gf * 3 /usr/local/lib/tex/fonts/%f/%f.%mgf
+font pxl * 3 /usr/local/lib/tex/fonts/%f/%f.%mpxl
+font pk * 3 /usr/local/lib/tex/fonts/%f/%f.%mpk
+# SLiTeX invisible fonts can be done with links:
+font blank * 1 /usr/local/lib/tex/slitexfonts/%f.tfm
+font box * 1 /usr/local/lib/tex/fonts/%f.tfm
diff --git a/dviware/umddvi/misc/getdep.sh b/dviware/umddvi/misc/getdep.sh
new file mode 100644
index 0000000000..348df53ffd
--- /dev/null
+++ b/dviware/umddvi/misc/getdep.sh
@@ -0,0 +1,34 @@
+: getdep - get dependency lists.
+
+: change ":" comments to "#" comments if your shell supports those;
+: the result will run faster.
+
+: find cpp
+cpp=unknown
+for where in /lib /usr/lib /bin /usr/bin; do
+ if test -f $where/cpp; then cpp=$where/cpp; break; fi
+done
+if test $cpp = unknown; then
+ echo "I cannot find cpp, sorry" 1>&2; exit 1
+fi
+
+: handle arguments
+incl=
+for i
+do
+ case "$i" in
+ -I*)
+ incl="$incl $i";;
+ *)
+ : assume source file
+ : put '$dep' in front of dependencies
+ dep=`echo "$i" | sed -e 's,/,\\\\/,g' -e 's/\.c$/.o/'`
+ : Find includes, remove leading numerics, remove ./,
+ : remove double quotes, and remove trailing numerics.
+ : Sort that, discarding duplicates, and add '$dep'.
+ $cpp $incl "$i" | grep "^#" |
+ sed -e 's/# [0-9]* //' -e 's,"./,",' -e 's/"\(.*\)"/\1/' \
+ -e 's/ [ 0-9]*$//' |
+ sort -u | sed -e "s/^/$dep: /";;
+ esac
+done
diff --git a/dviware/umddvi/misc/makefile b/dviware/umddvi/misc/makefile
new file mode 100644
index 0000000000..294e24505c
--- /dev/null
+++ b/dviware/umddvi/misc/makefile
@@ -0,0 +1,44 @@
+CFLAGS= -O -R
+LIBS= ../lib/lib.a
+
+STD= fixfix showfont showtfmwidth checkw
+
+all: ${STD}
+
+${STD}: ${LIBS}
+ ${CC} ${CFLAGS} -o $@ $@.c ${LIBS}
+
+install: all
+ @echo "these programs don't get installed..."
+
+clean:
+ rm -f ${STD} *.o a.out core
+
+depend:
+ for i in ${STD}; do \
+ ${CC} -M ${CFLAGS} $$i.c | sed -e 's/\.o:/:/' -e 's, ./, ,' | \
+ awk '{ if ($$1 != prev) { if (rec != "") print rec; \
+ rec = $$0; prev = $$1; } \
+ else { if (length(rec $$2) > 78) { print rec; rec = $$0; } \
+ else rec = rec " " $$2 } } \
+ END { print rec }'; done >makedep
+ echo '/^# DO NOT DELETE THIS LINE/+2,$$d' >eddep
+ echo '$$r makedep' >>eddep
+ echo 'w' >>eddep
+ cp Makefile Makefile.bak
+ ed - Makefile <eddep
+ rm eddep makedep
+ echo '# DEPENDENCIES MUST END AT END OF FILE' >>Makefile
+ echo '# IF YOU PUT STUFF HERE IT WILL GO AWAY' >>Makefile
+ echo '# see make depend above' >>Makefile
+
+# DO NOT DELETE THIS LINE -- make depend uses it
+
+fixfix: fixfix.c /usr/include/stdio.h
+showtfmwidth: showtfmwidth.c /usr/include/stdio.h ../h/types.h ../h/fio.h
+checkw: checkw.c /usr/include/stdio.h /usr/include/sys/types.h
+checkw: /usr/include/sys/stat.h ../h/types.h ../h/fio.h
+showfont.o: showfont.c /usr/include/stdio.h ../h/font.h ../h/types.h ../h/conv.h
+# DEPENDENCIES MUST END AT END OF FILE
+# IF YOU PUT STUFF HERE IT WILL GO AWAY
+# see make depend above
diff --git a/dviware/umddvi/misc/makesubdir.sh b/dviware/umddvi/misc/makesubdir.sh
new file mode 100644
index 0000000000..dd7d74e053
--- /dev/null
+++ b/dviware/umddvi/misc/makesubdir.sh
@@ -0,0 +1,30 @@
+#! /bin/sh
+#
+# makesubdir - make the TeX fonts reside in a subdirectory style system
+#
+# usage:
+# cd /usr/lib/tex/fonts
+# sh makesubdir.sh
+
+if [ -f SUBDIR ]; then
+ echo "$0: SUBDIR file already exists.
+Are you sure you need to do this?
+(If so, remove the SUBDIR file and try again.)" 1>&2
+ exit 1
+fi
+
+>SUBDIR
+
+for font in *.*pxl; do
+ dir=`echo $font | sed -e 's/\..*//'`
+ if [ ! -d $dir ]; then
+ if [ -f $dir ]; then
+echo "$0: \`$dir' exists as a file (renamed to $dir.old)" 1>&2
+ if mv -i $dir $dir.old; then
+ echo "$0: aborting" 1>&2
+ fi
+ fi
+ mkdir $dir
+ fi
+ mv -i $font $dir/$font
+done
diff --git a/dviware/umddvi/misc/makesunfont.c b/dviware/umddvi/misc/makesunfont.c
new file mode 100644
index 0000000000..a90437eb67
--- /dev/null
+++ b/dviware/umddvi/misc/makesunfont.c
@@ -0,0 +1,183 @@
+#ifndef lint
+static char rcsid[] = "$Header$";
+#endif
+
+/*
+ * Convert a TeX format font (pxl, gf, pk) into SUN vfont format
+ * Quick and dirty implementation.
+ *
+ * Lou Salkind
+ * New York University
+ */
+
+#include <stdio.h>
+#include "../h/types.h"
+#include "../h/conv.h"
+#include "../h/font.h"
+
+char *ProgName;
+extern int errno;
+extern char *optarg;
+extern int optind;
+
+#define PTTOSP(x) ((x) << 16) /* points to scaled points */
+
+int dpi;
+int dvimag;
+int dvidsz;
+int globalmag;
+char *devspec;
+int rotation;
+
+main(argc, argv)
+ register int argc;
+ register char **argv;
+{
+ register int c;
+
+ ProgName = *argv;
+ dvimag = PTTOSP(10);
+ dvidsz = PTTOSP(10);
+ globalmag = 1000;
+ dpi = 200;
+ rotation = ROT_NORM;
+ while ((c = getopt(argc, argv, "D:d:m:g:r:s:")) != EOF) {
+ switch (c) {
+
+ case 'D':
+ dpi = atoi(optarg);
+ break;
+
+ case 'd':
+ dvidsz = atoi(optarg);
+ break;
+
+ case 'm':
+ dvimag = atoi(optarg);
+ break;
+
+ case 'g':
+ globalmag = atoi(optarg);
+ break;
+
+ case 'r':
+ rotation = makerot(optarg);
+ break;
+
+ case 's':
+ devspec = optarg;
+ break;
+
+ case '?':
+usage:
+ error(1, 0, "\
+usage: %s [-m dvimag] [-d designsize] [-g globalmag] [-s devspec] font ...",
+ ProgName);
+ /* NOTREACHED */
+
+ default:
+ panic("case %d", c);
+ /* NOTREACHED */
+ }
+ }
+ if (optind >= argc)
+ goto usage;
+ SetConversion(dpi, 1000, 25400000, 473628672, 1000);
+ for (c = optind; c < argc; c++)
+ show(argv[c]);
+ exit(0);
+}
+
+makerot(s)
+ char *s;
+{
+
+ switch (*s) {
+
+ case 'n':
+ return (ROT_NORM);
+
+ case 'l':
+ return (ROT_LEFT);
+
+ case 'd':
+ return (ROT_DOWN);
+
+ case 'r':
+ return (ROT_RIGHT);
+
+ case '0': case '1': case '2': case '3':
+ return (*s - '0');
+
+ default:
+ error(1, 0, "\
+valid rotations are `n'ormal, `l'eft, `right', and `d'own");
+ /* NOTREACHED */
+ }
+}
+
+#include <vfont.h>
+
+struct header header;
+struct dispatch dispatch[NUM_DISPATCH];
+
+show(s)
+ char *s;
+{
+ register struct font *f;
+ register struct glyph *g;
+ register int i;
+ char *fname;
+ int maxx, maxy, offset, rsize;
+ char *rast;
+ char newfile[256];
+
+ f = GetFont(s, dvimag, dvidsz, devspec, &fname);
+ if (f == NULL) {
+ GripeCannotGetFont(s, dvimag, dvidsz, devspec, fname);
+ exit(1);
+ }
+ strcpy(newfile, s);
+ strcat(newfile, ".v");
+ freopen(newfile, "w", stdout);
+ if (fseek(stdout, (long)sizeof(header) + sizeof(dispatch), 0) == -1)
+ exit(1);
+ maxx = 0;
+ maxy = 0;
+ offset = 0;
+ for (i = f->f_lowch; i < f->f_highch; i++) {
+ g = GLYPH(f, i);
+ if (!GVALID(g))
+ continue;
+#ifdef notdef
+ if (fromSP(g->g_tfmwidth) > maxx)
+ maxx = fromSP(g->g_tfmwidth);
+#endif
+ if (!HASRASTER(g))
+ continue;
+ rast = RASTER(g, f, rotation);
+ if (g->g_height > maxy)
+ maxy = g->g_height;
+ if (g->g_width > maxx)
+ maxx = g->g_width;
+ dispatch[i].up = g->g_yorigin;
+ dispatch[i].down = g->g_height - g->g_yorigin;
+ dispatch[i].left = g->g_xorigin;
+ dispatch[i].right = g->g_width - g->g_xorigin;
+ dispatch[i].width = fromSP(g->g_tfmwidth);
+ rsize = ((g->g_width + 7) / 8) * g->g_height;
+ dispatch[i].addr = offset;
+ dispatch[i].nbytes = rsize;
+ fwrite(rast, rsize, 1, stdout);
+ offset += rsize;
+ }
+ header.magic = VFONT_MAGIC;
+ header.size = offset;
+ header.maxx = maxx;
+ header.maxy = maxy;
+ header.xtend = 0;
+ if (fseek(stdout, 0L, 0) == -1)
+ exit(1);
+ fwrite(&header, sizeof(header), 1, stdout);
+ fwrite(dispatch, sizeof(dispatch), 1, stdout);
+}
diff --git a/dviware/umddvi/misc/rot.alg b/dviware/umddvi/misc/rot.alg
new file mode 100644
index 0000000000..76aa85e718
--- /dev/null
+++ b/dviware/umddvi/misc/rot.alg
@@ -0,0 +1,44 @@
+From shulman@topaz.RUTGERS.EDU (Jeff Shulman) Wed Nov 27 09:29:19 1985
+Relay-Version: version B 2.10.1 6/24/83; site umcp-cs.UUCP
+Posting-Version: version B 2.10.3 4.3bsd-beta 6/6/85; site topaz.RUTGERS.EDU
+Path: umcp-cs!seismo!caip!topaz!shulman
+From: shulman@topaz.RUTGERS.EDU (Jeff Shulman)
+Newsgroups: net.graphics
+Subject: Re: bitmap rotation algorithm needed
+Message-ID: <4242@topaz.RUTGERS.EDU>
+Date: Wed, 27-Nov-85 09:29:19 EST
+Date-Received: Wed, 27-Nov-85 22:38:05 EST
+References: <4224@topaz.RUTGERS.EDU> <2809@watcgl.UUCP> <35@brl-tgr.ARPA>
+Reply-To: shulman@topaz.UUCP (Jeff Shulman)
+Organization: Rutgers Univ., New Brunswick, N.J.
+Lines: 26
+
+
+Since noone came up with any more algorithms than I already knew I will
+mention those. They can be found in "ACM Transactions on Graphics" Vol 1
+No. 3, July 1982 Pages 191-214.
+
+The first algorithm, shearing, can work on any N x N matrix and you need
+an extra 2N x 2N temporary bitmap for storage. The gist of this algorithm
+is that individual rows and columns are rotated around themselves in
+stepwise amounts. In the first rotation you rotate the I'th row around
+itself by I bits. You then rotate the J'th column by N - J - 1 bits down.
+You finally rotate back the I'th row by N - I - 1 bits left.
+
+The second algorithm, binary mask (developed by Floyd), works on an N x N
+matrix where N is a power of two. This algorithm works by swapping
+halves and then opposite corners of the bitmap recursively halving the
+size of the pieces being swapped. By cleverly using a mask it is possible
+to accomplish all the recursive swapping in parallel. A better explanation
+of this algorithm can be found in "Smalltalk-80, the language and an
+implementation" (I believe that's the correct title) on pages 408-410.
+
+
+ Jeff
+
+uucp: ...{harvard, seismo, ut-sally, sri-iu, ihnp4!packard}!topaz!shulman
+arpa: SHULMAN@RUTGERS
+CIS: 76136,667
+Delphi: JEFFS
+
+
diff --git a/dviware/umddvi/misc/showfont.c b/dviware/umddvi/misc/showfont.c
new file mode 100644
index 0000000000..870c3d6dcb
--- /dev/null
+++ b/dviware/umddvi/misc/showfont.c
@@ -0,0 +1,173 @@
+#ifndef lint
+static char rcsid[] = "$Header$";
+#endif
+
+/*
+ * Show font things.
+ */
+
+#include <stdio.h>
+#include "../h/types.h"
+#include "../h/conv.h"
+#include "../h/font.h"
+
+char *ProgName;
+extern int errno;
+extern char *optarg;
+extern int optind;
+
+#define PTTOSP(x) ((x) << 16) /* points to scaled points */
+
+int dvimag;
+int dvidsz;
+char *devspec;
+int rotation;
+
+main(argc, argv)
+ register int argc;
+ register char **argv;
+{
+ register int c;
+ int dpi, globalmag;
+
+ ProgName = *argv;
+ dvimag = PTTOSP(10);
+ dvidsz = PTTOSP(10);
+ globalmag = 1000;
+ dpi = 200;
+ rotation = ROT_NORM;
+ while ((c = getopt(argc, argv, "D:d:m:g:r:s:")) != EOF) {
+ switch (c) {
+
+ case 'D':
+ dpi = atoi(optarg);
+ break;
+
+ case 'd':
+ dvidsz = atoi(optarg);
+ break;
+
+ case 'm':
+ dvimag = atoi(optarg);
+ break;
+
+ case 'g':
+ globalmag = atoi(optarg);
+ break;
+
+ case 'r':
+ rotation = makerot(optarg);
+ break;
+
+ case 's':
+ devspec = optarg;
+ break;
+
+ case '?':
+usage:
+ error(1, 0, "\
+usage: %s [-Ddpi] [-mdvimag] [-ddesignsz] [-ggloblmag] [-sdevspec] font ...",
+ ProgName);
+ /* NOTREACHED */
+
+ default:
+ panic("case %d", c);
+ /* NOTREACHED */
+ }
+ }
+ if (optind >= argc)
+ goto usage;
+ SetConversion(dpi, 1000, 25400000, 473628672, globalmag);
+ for (c = optind; c < argc; c++)
+ show(argv[c]);
+ exit(0);
+}
+
+makerot(s)
+ char *s;
+{
+
+ switch (*s) {
+
+ case 'n':
+ return (ROT_NORM);
+
+ case 'l':
+ return (ROT_LEFT);
+
+ case 'd':
+ return (ROT_DOWN);
+
+ case 'r':
+ return (ROT_RIGHT);
+
+ case '0': case '1': case '2': case '3':
+ return (*s - '0');
+
+ default:
+ error(1, 0, "\
+valid rotations are `n'ormal, `l'eft, `right', and `d'own");
+ /* NOTREACHED */
+ }
+}
+
+show(s)
+ char *s;
+{
+ register struct font *f;
+ register struct glyph *g;
+ register int i;
+ char *fname;
+
+ f = GetFont(s, dvimag, dvidsz, devspec, &fname);
+ if (f == NULL) {
+ GripeCannotGetFont(s, dvimag, dvidsz, devspec, fname);
+ exit(1);
+ }
+ printf("[%s]\n", fname);
+ for (i = f->f_lowch; i < f->f_highch; i++) {
+ g = GLYPH(f, i);
+ if (!GVALID(g))
+ continue;
+ printf("glyph ");
+ if (i >= ' ' && i < 127)
+ printf("'%c'", i);
+ else
+ printf("%3d", i);
+ printf(":\n\
+\theight = %5d width = %5d yorigin = %5d xorigin = %5d\n\
+\tTFM width = %6.2fpt (%d pixels)\n",
+ g->g_height, g->g_width, g->g_yorigin, g->g_xorigin,
+ g->g_tfmwidth / 65536.0, fromSP(g->g_tfmwidth));
+ if (!HASRASTER(g))
+ continue;
+ showraster(g, RASTER(g, f, rotation));
+ }
+}
+
+showraster(g, p)
+ struct glyph *g;
+ register char *p;
+{
+ register int c, t, i, j, k, w;
+
+ w = g->g_width;
+ for (i = g->g_height; --i >= 0;) {
+ k = 7;
+ t = 0;
+ for (j = w; --j >= 0;) {
+ if (++k == 8)
+ k = 0, c = *p++;
+ if (c & 0x80) {
+ while (--t >= 0)
+ (void) putchar(' ');
+ t = 0;
+ (void) putchar('*');
+ } else
+ t++;
+ c <<= 1;
+ }
+ (void) putchar('\n');
+ }
+ (void) putchar('\n');
+}
diff --git a/dviware/umddvi/misc/showtfmwidth.c b/dviware/umddvi/misc/showtfmwidth.c
new file mode 100644
index 0000000000..71c2f27cc8
--- /dev/null
+++ b/dviware/umddvi/misc/showtfmwidth.c
@@ -0,0 +1,165 @@
+#ifndef lint
+static char rcsid[] = "$Header$";
+#endif
+
+FIXME (use new tfm library routines)
+
+#include <stdio.h>
+#include "../h/types.h"
+#include "../h/fio.h"
+
+char *ProgName;
+char *getenv ();
+
+struct tfmheader {
+ int th_lf; /* length of the file (words) */
+ int th_lh; /* length of the header data (words) */
+ int th_bc; /* smallest char code in font */
+ int th_ec; /* largest char code in font (inclusive) */
+ int th_nw; /* number of words in width table */
+ int th_nh; /* number of words in height table */
+ int th_nd; /* number of words in depth table */
+ int th_ni; /* number of words in ital. corr. table */
+ int th_nl; /* number of words in lig/kern table */
+ int th_nk; /* number of words in kern table */
+ int th_ne; /* number of words in extensible char table */
+ int th_np; /* number of font param words */
+};
+
+/*
+ * The rest of the TFM file is composed of the following information,
+ * all of which are 32 bit quantities:
+ *
+ * header: array [0..lh-1] of stuff
+ * char_info: array [bc..ec] of char_info_word
+ * width: array [0..nw-1] of fix_word
+ * height: array [0..nh-1] of fix_word
+ * depth: array [0..nd-1] of fix_word
+ * italic: array [0..ni-1] of fix_word
+ * lig_kern: array [0..nl-1] of lig_kern_command
+ * kern: array [0..nk-1] of fix_word
+ * exten: array [0..ne-1] of extensible_recipie
+ * param: array [1..np] of fix_word
+ *
+ * We are interested only in the width information. This can be
+ * found by taking the first byte of each of the char_info_words
+ * and using it as an index in the width table. That is, the
+ * width of character $n$ is width[char_info[$n$-$bc$].width_index].
+ */
+
+struct char_info_word {
+ char width_index;
+ char height_and_depth_index;
+ char italic_index_and_tag;
+ char remainder;
+};
+
+char *tfname;
+FILE *tf;
+struct tfmheader th;
+i32 *width;
+struct char_info_word *char_info;
+
+#ifdef notdef
+extern char *optarg;
+extern int optind;
+#endif
+
+extern int errno;
+
+main (argc, argv)
+int argc;
+char **argv;
+{
+ register int i;
+
+ ProgName = argv[0];
+ if (argc != 2)
+ error (1, 0, "usage: %s tfmfile\n", ProgName);
+ tfname = argv[1];
+ if ((tf = fopen (tfname, "r")) == NULL)
+ error (1, errno, "can't open %s", tfname);
+ ReadTFMHeader ();
+ if (th.th_ec < th.th_bc)
+ error (1, 0, "no characters in %s!?", tfname);
+ if (th.th_bc < 0 || th.th_ec > 127)
+ error (1, 0, "I don't see how %s can correspond to a PXL file.",
+ tfname);
+ AllocateCharTable (th.th_ec - th.th_bc + 1);
+ AllocateWidthTable (th.th_nw);
+ SkipHeader ();
+ ReadCharInfo (th.th_ec - th.th_bc + 1);
+ ReadWidthTable (th.th_nw);
+ for (i = th.th_bc; i <= th.th_ec; i++)
+ show (i);
+ exit (0);
+}
+
+show (c)
+register int c;
+{
+ long w = width[char_info[c - th.th_bc].width_index];
+ char buf[3];
+ char *blanks;
+
+ if (c >= 32 && c < 127)
+ buf[0] = c, buf[1] = 0, blanks = " ";
+ else
+ buf[0] = '^', buf[1] = c ^ 64, buf[2] = 0, blanks = "";
+ printf ("%3d (%s)%s width = %9ld\n", c, buf, blanks, w);
+}
+
+AllocateCharTable (n)
+register int n; {
+ char_info = (struct char_info_word *) malloc (n * sizeof *char_info);
+ if (char_info == 0)
+ error (1, errno, "unable to allocate %d char table entries", n);
+}
+
+AllocateWidthTable (n)
+register int n; {
+ width = (i32 *) malloc (n * sizeof *width);
+ if (width == 0)
+ error (1, errno, "unable to allocate %d width table entries", n);
+}
+
+/* ``cheating'' */
+ReadTFMHeader () {
+ register int *ip, i;
+
+ for (ip = &th.th_lf; ip <= &th.th_np;) {
+ i = UnSign16 (GetWord (tf));
+ *ip++ = i;
+ }
+}
+
+SkipHeader () {
+ fseek (tf, (long) th.th_lh * sizeof (i32), 1);
+}
+
+ReadCharInfo (n)
+register int n; {
+ register struct char_info_word *ci;
+
+ for (ci = char_info; --n >= 0; ci++) {
+ ci -> width_index = getc (tf);
+ ci -> height_and_depth_index = getc (tf);
+ ci -> italic_index_and_tag = getc (tf);
+ ci -> remainder = getc (tf);
+ }
+ if (feof (tf))
+ error (1, 0, "unexpected EOF -- are you sure %s is a tfm file?",
+ tfname);
+}
+
+ReadWidthTable (n)
+register int n; {
+ register i32 *ip;
+
+ for (ip = width; --n >= 0; ip++)
+ fGetLong (tf, *ip);
+
+ if (feof (tf))
+ error (1, 0, "unexpected EOF -- are you sure %s is a tfm file?",
+ tfname);
+}
diff --git a/dviware/umddvi/misc/unmakesubdir.sh b/dviware/umddvi/misc/unmakesubdir.sh
new file mode 100644
index 0000000000..e2d1ee412a
--- /dev/null
+++ b/dviware/umddvi/misc/unmakesubdir.sh
@@ -0,0 +1,22 @@
+#! /bin/sh
+#
+# unmakesubdir - make the TeX fonts reside in a flat style system
+#
+# usage:
+# cd /usr/lib/tex/fonts
+# sh unmakesubdir.sh
+
+if [ ! -f SUBDIR ]; then
+ echo "$0: SUBDIR file already gone.
+Are you sure you need to do this?
+(If so, create a SUBDIR file and try again.)" 1>&2
+ exit 1
+fi
+
+rm SUBDIR
+
+for dir in *; do
+ if [ -d $dir ]; then
+ mv -i $dir/*.*pxl .
+ fi
+done
diff --git a/dviware/umddvi/previewers/dvistuff.c b/dviware/umddvi/previewers/dvistuff.c
new file mode 100644
index 0000000000..669ab55268
--- /dev/null
+++ b/dviware/umddvi/previewers/dvistuff.c
@@ -0,0 +1,978 @@
+/*
+ * This program is Copyright (C) 1987 by the Board of Trustees of the
+ * University of Illinois, and by the author Dirk Grunwald.
+ *
+ * This program may be freely copied, as long as this copyright
+ * message remaines affixed. It may not be sold, altough it may
+ * be distributed with other software which is sold. If the
+ * software is distributed, the source code must be made available.
+ *
+ * No warrenty, expressed or implied, is given with this software.
+ * It is presented in the hope that it will prove useful.
+ */
+#include <stdio.h>
+#include <ctype.h>
+
+#include "dvistuff.h" /* includes types & fonts */
+
+#include "conv.h"
+#include "dvi.h"
+#include "dviclass.h"
+#include "dvicodes.h"
+#include "postamble.h"
+#include "search.h"
+#include "fio.h"
+
+int dviHH = -1; /* current horizontal position, in DEVs */
+int dviVV = -1; /* current vertical position, in DEVs */
+int dviHHMargin = -1; /* horizontal margin (in DEVs) */
+int dviVVMargin = -1; /* vertical margin (in DEVs) */
+int dviTallestPage = -1;
+int dviWidestPage = -1 ;
+int dviCurrentPage = -1;
+int dviTotalPages = -1;
+int dviDPI = -1;
+int dviMaxDrift = -1;
+int dviUserMag = -1; /* user-specified magnification */
+int dviBlackness = -1;
+FILE *dviFile; /* users file */
+char *dviPrintEngine = "canon";
+
+char *ProgName;
+
+/*
+ * Similar to dvi_stack, but includes `dviHH and `dviVV, which are usually
+ * but not always the same as fromSP(h) and fromSP(v):
+ */
+struct localstack {
+ int stack_hh;
+ int stack_vv;
+ struct dvi_stack stack_dvi;
+};
+
+static struct localstack *dvi_stack; /* base of stack */
+static struct localstack *dvi_stackp; /* current place in stack */
+
+/*
+ * DVI preamble and postamble information.
+ */
+
+static long Magnification;
+static long Numerator; /* numerator from DVI file */
+static long Denominator; /* denominator from DVI file */
+
+/*
+ * Font related things.
+ * We keep track of the current font, use the fontfiner
+ * and record errors in the dvi postable in FontErros.
+ * the NoFont is a used when we cant find a font,
+ * to avoid errors.
+ */
+
+struct fontinfo *dviCurrentFont;
+
+static int NextFamilyNumber = 0;
+static int MaxFontFamily = MAX_FONTFAMILY;
+
+static struct search *FontFinder;
+int FontErrors;
+static struct fontinfo NoFont;
+
+/*
+ * We keep a list of pointers to the beginning of pages.
+ * Each page is headed by a DVI_BOP + 44 bytes of information.
+ */
+
+static long *pageOffset;
+
+/*
+ * Correct devpos (the actual device position) to be within dviMaxDrift pixels
+ * of dvipos (the virtual DVI position).
+ */
+#define FIXDRIFT(devpos, dvipos) \
+ if ((devpos) < (dvipos)) \
+ if ((dvipos) - (devpos) <= dviMaxDrift) \
+ /* void */; \
+ else \
+ (devpos) = (dvipos) - dviMaxDrift; \
+ else \
+ if ((devpos) - (dvipos) <= dviMaxDrift) \
+ /* void */; \
+ else \
+ (devpos) = (dvipos) + dviMaxDrift
+
+#define ABS(X) ( (X) < 0 ? -(X) : (X) )
+
+/*
+ * Store the relevant information from the DVI postamble, and set up
+ * various internal things.
+ */
+static void
+PostAmbleHeader(p)
+ register struct PostAmbleInfo *p;
+{
+ int i;
+ int pageSize;
+ int stackSize;
+ long prevPagePointer;
+ long wuzAt;
+
+ Numerator = p->pai_Numerator;
+ Denominator = p->pai_Denominator;
+ Magnification = p->pai_DVIMag;
+
+/*
+ * Set the conversion factor. This must be done before using
+ * any fonts or the fromSP routine.
+ */
+
+ SetConversion(dviDPI, dviUserMag, Numerator, Denominator, Magnification);
+
+ dviTotalPages = p -> pai_NumberOfPages;
+ dviWidestPage = fromSP(p -> pai_WidestPageWidth);
+ dviTallestPage = fromSP(p -> pai_TallestPageHeight);
+
+/*
+ * Set up the DVI stack
+ */
+ stackSize = p -> pai_DVIStackSize * sizeof(*dvi_stack);
+ dvi_stack = (struct localstack *) malloc((unsigned) stackSize);
+
+/*
+ * Set of the table of pointers to pages
+ */
+
+ pageSize = dviTotalPages * sizeof(long);
+ pageOffset = (long *) malloc(pageSize);
+
+ if (pageOffset == NULL) {
+ fprintf(stderr,"xdvi: Can not allocate page directory (%d pages)",
+ dviTotalPages);
+ exit(1);
+ }
+
+/*
+ * Follow back pointers through pages in the DVI file,
+ * storing the offsets in the pageOffset table.
+ */
+
+ prevPagePointer = p->pai_PrevPagePointer;
+ wuzAt = (long) ftell(dviFile);
+
+ if( fseek(dviFile, prevPagePointer, 0) < 0) {
+ perror("fseek");
+ fprintf(stderr,"[postamble] improper seek looking up pages\n");
+ fprintf(stderr,"prevPagePointer = %lx\n",
+ prevPagePointer);
+ }
+
+ for (i = dviTotalPages - 1; i > 0 ; i--) {
+
+ pageOffset[i] = prevPagePointer;
+
+ if (fseek(dviFile, (long) prevPagePointer, 0) < 0) {
+ perror("fseek");
+ fprintf(stderr,"[postamble] improper seek looking up pages\n");
+ fprintf(stderr,"prevPagePointer = %lx\n",
+ prevPagePointer);
+ exit(1);
+ }
+/*
+ * Skip past the other counters at the beginning of the page
+ */
+ if (fseek(dviFile, (long) (1 + 10 * 4), 1) < 0) {
+ perror("fseek");
+ fprintf(stderr,"[postamble] attemping to align to prevPointer\n");
+ exit(1);
+ }
+
+ fGetLong(dviFile, prevPagePointer);
+ }
+
+ pageOffset[0] = prevPagePointer;
+ fseek(dviFile, wuzAt, 0);
+}
+
+static void
+PostAmbleFontDef(p)
+register struct PostAmbleFont *p;
+{
+ register struct fontinfo *fi;
+ register struct font *f;
+
+ char *fname;
+ int def = S_CREATE | S_EXCL;
+
+ fi = (struct fontinfo *) SSearch(FontFinder, p->paf_DVIFontIndex,
+ &def);
+ if (fi == NULL) {
+ if (def & S_COLL)
+ GripeFontAlreadyDefined(p->paf_DVIFontIndex);
+ else {
+ fprintf(stderr, "Can not stash font %ld (out of memory?)\n",
+ p -> paf_DVIFontIndex);
+ exit(1);
+ }
+ }
+
+ if (NextFamilyNumber == MaxFontFamily) {
+ fprintf(stderr,"Out of font family!\n");
+ exit(1);
+ }
+
+ fi->family = NextFamilyNumber;
+ NextFamilyNumber++;
+
+ f = GetFont(p->paf_name, p->paf_DVIMag, p->paf_DVIDesignSize,
+ dviPrintEngine, &fname);
+
+/*
+ * Give the application a chance to bang on this if they want to.
+ */
+
+ f = applicationNewFont(f, fi -> family);
+
+ if ((fi->f = f) == NULL) {
+ GripeCannotGetFont(p->paf_name, p->paf_DVIMag,
+ p->paf_DVIDesignSize, dviPrintEngine, fname);
+ FontErrors++;
+ return;
+ }
+
+ /* match checksums, if not zero */
+ if (p->paf_DVIChecksum && f->f_checksum &&
+ p->paf_DVIChecksum != f->f_checksum)
+ GripeDifferentChecksums(fname, p->paf_DVIChecksum,
+ f->f_checksum);
+
+ fi->pspace = p->paf_DVIMag / 6; /* a three-unit "thin space" */
+ fi->nspace = -4 * fi->pspace;
+ fi->vspace = 5 * fi->pspace;
+}
+
+static void
+ReadPostAmble()
+{
+
+ if ((FontFinder = SCreate(sizeof(struct fontinfo))) == 0) {
+ fprintf(stderr, "can not create FontFinder (out of memory?)");
+ exit(1);
+ }
+
+ ScanPostAmble(dviFile, PostAmbleHeader, PostAmbleFontDef);
+
+ if (FontErrors)
+ GripeMissingFontsPreventOutput(FontErrors);
+}
+
+/*
+ * Read the preamble and do a few sanity checks
+ */
+
+static void
+ReadPreAmble()
+{
+ register int n;
+
+ rewind(dviFile);
+ if (GetByte(dviFile) != Sign8(DVI_PRE))
+ GripeMissingOp("PRE");
+
+ if (GetByte(dviFile) != Sign8(DVI_VERSION))
+ GripeMismatchedValue("version numbers");
+
+ if (GetLong(dviFile) != Numerator)
+ GripeMismatchedValue("numerator");
+
+ if (GetLong(dviFile) != Denominator)
+ GripeMismatchedValue("denominator");
+
+ if (GetLong(dviFile) != Magnification)
+ GripeMismatchedValue("\\magfactor");
+
+ n = UnSign8(GetByte(dviFile));
+ while (--n >= 0)
+ (void) GetByte(dviFile);
+}
+
+void
+dviInit()
+{
+ extern char *ProgName;
+
+ if (dviUserMag == -1) {
+ dviUserMag = 1000;
+ }
+
+ if (dviMaxDrift == -1) {
+ dviMaxDrift = 3;
+ }
+
+ if (dviDPI == -1) {
+ dviDPI = DEFAULT_DPI;
+ }
+
+ if (dviBlackness == -1) {
+ dviBlackness = DEFAULT_BLACKNESS;
+ }
+
+ ReadPostAmble();
+ ReadPreAmble();
+
+ /* Margins -- needs work! */
+
+ if (dviHHMargin == -1) {
+ dviHHMargin = DEFAULT_HHMARGIN;
+ }
+
+ if (dviVVMargin == -1) {
+ dviVVMargin = DEFAULT_VVMARGIN;
+ }
+
+ dviCurrentFont = &NoFont; /* fake font, all zeros */
+
+}
+
+static void
+SelectFont(n)
+i32 n;
+{
+ int x = S_LOOKUP;
+
+ if ((dviCurrentFont = (struct fontinfo *)SSearch(FontFinder, n, &x)) == 0)
+ GripeNoSuchFont(n);
+}
+
+/* Read the postamble. */
+
+/*
+ * Skip a font definition (since we are using those from the postamble)
+ */
+
+/*ARGSUSED*/
+void
+SkipFontDef(font)
+i32 font;
+{
+ register int i;
+
+ (void) GetLong(dviFile);
+ (void) GetLong(dviFile);
+ (void) GetLong(dviFile);
+ i = UnSign8(GetByte(dviFile)) + UnSign8(GetByte(dviFile));
+ while (--i >= 0)
+ (void) GetByte(dviFile);
+}
+
+
+static void
+doDviChar(c, advance)
+int c;
+int advance;
+{
+ register struct glyph *g;
+ register struct font *f;
+ int p;
+
+ f = dviCurrentFont->f;
+
+ if (c < f -> f_lowch || c > f -> f_highch) {
+ fprintf(stderr,"Character out of range: %d\n",
+ c);
+ return;
+ }
+
+ g = GLYPH(f, c);
+ if (!GVALID(g)) {
+ fprintf(stderr, "there is no character %d in %s",
+ c, f->f_path);
+ exit(1);
+ } else {
+
+ if (HASRASTER(g)) { /* workaround for Imagen bug */
+ applicationPutChar(dviHH,dviVV,c);
+ }
+
+ if (advance) {
+ dviHH += g->g_pixwidth;
+ dvi_h += g->g_tfmwidth;
+ p = fromSP(dvi_h);
+ FIXDRIFT(dviHH, p);
+ }
+ }
+}
+
+/*
+ * The next two routines are used to reset all the glyphs.
+ * the dviResetFont routine is called for each font in the font table.
+ * It de-allocates the rasters & glyphs for the shrunken fonts, leaving
+ * the original glyph data untouched.
+ */
+
+
+static void
+dviResetFont(fi, key)
+struct fontinfo *fi;
+int key;
+{
+ if (fi != 0) {
+ applicationResetFont(fi, fi -> family);
+ }
+}
+
+void
+dviResetAll()
+{
+ SEnumerate(FontFinder, dviResetFont);
+}
+
+/*
+ * Process the DVI commands for page #page. If the page number is
+ * out of range, it is cropped to the end.
+ *
+ * Updates dviCurrentPage
+ */
+void
+dviPreparePage(page)
+int page;
+{
+ register int c;
+ register i32 p;
+ int advance;
+
+ if (page < 0) {
+ page = 0;
+ }
+
+ if (page >= dviTotalPages) {
+ page = dviTotalPages - 1;
+ }
+
+ dviCurrentPage = page;
+
+ fseek(dviFile, (long) pageOffset[page], 0);
+
+ dviHH = dviHHMargin;
+ dviVV = dviVVMargin;
+
+ dvi_h = toSP(dviHH);
+ dvi_v = toSP(dviVV);
+
+ dvi_w = 0;
+ dvi_x = 0;
+ dvi_y = 0;
+ dvi_z = 0;
+
+ dvi_stackp = dvi_stack;
+
+ for(;;) {
+/*
+ * Get the DVI byte, and switch on its parameter length and type.
+ * Note that getchar() returns unsigned values.
+ */
+
+ if (feof(dviFile)) {
+ fprintf(stderr,"Unexpected end-of-file\n");
+ exit(1);
+ }
+
+ c = getc(dviFile);
+
+ if (DVI_IsChar(c)) {
+ advance = 1;
+ doDviChar(c, advance);
+ } else {
+
+ switch (DVI_OpLen(c)) {
+
+ case DPL_NONE:
+ break;
+
+ case DPL_SGN1:
+ p = getc(dviFile);
+ p = Sign8(p);
+ break;
+
+ case DPL_SGN2:
+ fGetWord(dviFile, p);
+ p = Sign16(p);
+ break;
+
+ case DPL_SGN3:
+ fGet3Byte(dviFile, p);
+ p = Sign24(p);
+ break;
+
+ case DPL_SGN4:
+ fGetLong(dviFile, p);
+ break;
+
+ case DPL_UNS1:
+ p = UnSign8(getc(dviFile));
+ break;
+
+ case DPL_UNS2:
+ fGetWord(dviFile, p);
+ p = UnSign16(p);
+ break;
+
+ case DPL_UNS3:
+ fGet3Byte(dviFile, p);
+ p = UnSign24(p);
+ break;
+
+ default:
+ panic("DVI_OpLen(%d) = %d", c, DVI_OpLen(c));
+ /* NOTREACHED */
+ }
+
+ switch (DVI_DT(c)) {
+
+ case DT_SET:
+ c = p;
+ doDviChar(c, 1);
+ break;
+
+ case DT_PUT:
+ c = p;
+ doDviChar(c, 0);
+ break;
+
+ case DT_SETRULE:
+ case DT_PUTRULE:
+
+ {
+ i32 h, w, rw;
+
+ fGetLong(dviFile, h);
+ fGetLong(dviFile, rw);
+
+ h = ConvRule(h);
+ w = ConvRule(rw);
+
+ applicationSetRule(dviHH, dviVV, h,w);
+
+ if (DVI_DT(c) == DT_SETRULE) {
+ dviHH += w;
+ dvi_h += rw;
+ w = fromSP(dvi_h);
+ FIXDRIFT(dviHH, w);
+ }
+ }
+ break;
+
+ case DT_NOP:
+ break;
+
+ case DT_BOP:
+/*
+ * Each beginning of page has 11 4-byte words telling us things
+ * about the page. We ignore them.
+ */
+ {
+ fseek(dviFile, (long) (11 * 4), 1);
+ }
+
+ break;
+
+ case DT_EOP:
+ return;
+
+ case DT_PUSH:
+ dvi_stackp->stack_hh = dviHH;
+ dvi_stackp->stack_vv = dviVV;
+ dvi_stackp->stack_dvi = dvi_current;
+ dvi_stackp++;
+ break;
+
+ case DT_POP:
+ dvi_stackp--;
+ dviHH = dvi_stackp->stack_hh;
+ dviVV = dvi_stackp->stack_vv;
+ dvi_current = dvi_stackp->stack_dvi;
+ break;
+
+ case DT_W0: /* there should be a way to make these pretty */
+ p = dvi_w;
+ goto move_right;
+
+ case DT_W:
+ dvi_w = p;
+ goto move_right;
+
+ case DT_X0:
+ p = dvi_x;
+ goto move_right;
+
+ case DT_X:
+ dvi_x = p;
+ goto move_right;
+
+ case DT_RIGHT:
+ move_right:
+ dvi_h += p;
+/*
+ * DVItype tells us that we must round motions in this way:
+ * `When the horizontal motion is small, like a kern, hh
+ * changes by rounding the kern; but when the motion is
+ * large, hh changes by rounding the true position so that
+ * accumulated rounding errors disappear.
+ */
+ if (p >= dviCurrentFont->pspace || p <= dviCurrentFont->nspace)
+ dviHH = fromSP(dvi_h);
+ else {
+ dviHH += fromSP(p);
+ p = fromSP(dvi_h);
+ FIXDRIFT(dviHH, p);
+ }
+ break;
+
+ case DT_Y0:
+ p = dvi_y;
+ goto move_down;
+
+ case DT_Y:
+ dvi_y = p;
+ goto move_down;
+
+ case DT_Z0:
+ p = dvi_z;
+ goto move_down;
+
+ case DT_Z:
+ dvi_z = p;
+ goto move_down;
+
+ case DT_DOWN:
+ move_down:
+ dvi_v += p;
+/*
+ * `Vertical motion is done similarly, but with the threshold
+ * between ``small and ``large increased by a factor of
+ * 5. The idea is to make fractions like $1\over2$ round
+ * consistently, but to absorb accumulated rounding errors in
+ * the baseline-skip moves.
+ */
+ if (ABS(p) >= dviCurrentFont->vspace)
+ dviVV = fromSP(dvi_v);
+ else {
+ dviVV += fromSP(p);
+ p = fromSP(dvi_v);
+ FIXDRIFT(dviVV, p);
+ }
+ break;
+
+ case DT_FNTNUM:
+ SelectFont((i32) (c - DVI_FNTNUM0));
+ break;
+
+ case DT_FNT:
+ SelectFont(p);
+ break;
+
+ case DT_XXX:
+ {
+ char specialBuffer [2048];
+ register char *cp;
+ int sweetp = 0;
+
+ if (p > 2047) {
+ sweetp = p - 2047;
+ p = 2047;
+ }
+
+ for (cp = specialBuffer ; p > 0; p--) {
+ *cp = getc(dviFile);
+ cp++;
+ }
+ *(cp) = 0;
+
+ while(sweetp > 0) {
+ getc(dviFile);
+ }
+
+ applicationDoSpecial(specialBuffer);
+ }
+ break;
+
+ case DT_FNTDEF:
+ SkipFontDef(p);
+ break;
+
+ case DT_PRE:
+ GripeUnexpectedOp("PRE");
+ /* NOTREACHED */
+
+ case DT_POST:
+ GripeUnexpectedOp("POST");
+ /* NOTREACHED */
+
+ case DT_POSTPOST:
+ GripeUnexpectedOp("POSTPOST");
+ /* NOTREACHED */
+
+ case DT_UNDEF:
+ GripeUndefinedOp(c);
+ /* NOTREACHED */
+
+ default:
+ panic("DVI_DT(%d) = %d", c, DVI_DT(c));
+ /* NOTREACHED */
+ }
+ }
+ }
+}
+
+/*
+ * The following routine is used to shrink a glyph by some
+ * shrink factor (in the width & height dimension).
+ *
+ * These shrunken glyphs are more appropriate for previewers.
+ *
+ * To do this, we simple scan the original raster, counting the
+ * number of pixels within a given area. If the number of on pixels is
+ * at least twice the total number of pixels, we turn the pixel in
+ * the shrunken glyph ON, else OFF.
+ *
+ * We use a lookup table to hasten the process of counting pixels.
+ *
+ * The method used should be independent of byte-order (I think).
+ *
+ * You need to define two types. One should be 32-bits long, and
+ * the other 16 bits long.
+ */
+
+typedef unsigned short B16;
+typedef unsigned long B32;
+
+#define LOOKUP_BYTES 256
+#define LOOKUP_BITS 8
+#define LOOKUP_MASK 0xff
+
+static char dviLookUpTable[LOOKUP_BYTES];
+static char tableNotInitialized = 1;
+
+struct glyph *
+dviShrinkGlyph(gly, shrinkH, shrinkW)
+DviGlyph *gly;
+int shrinkH;
+int shrinkW;
+{
+ int shrunkHeight;
+ int shrunkWidth;
+ int glyphWide;
+ int glyphHigh;
+
+ int bytesWide;
+ int shrunkBytesWide;
+
+ struct glyph *ngly;
+
+ B16 *shrunkRaster;
+ int rasterSize;
+
+ int x,y;
+ char *cp;
+ B16 *ptr;
+
+ B32 shrinkMask;
+
+ int sampleSize;
+
+ if (gly == 0 || !HASRASTER(gly)) {
+ return(0);
+ }
+
+ if (gly -> g_raster == 0) {
+ gly-> g_raster = RASTER(gly, dviCurrentFont -> f, ROT_NORM);
+ }
+
+/*
+ * Initialize the lookup table of the number of bits in a given byte
+ */
+
+ if (tableNotInitialized) {
+ register int i;
+ register int j;
+ register int k;
+ register int acc;
+ for (i = 0; i < LOOKUP_BYTES; i++) {
+ j = i;
+ acc = 0;
+ for (k = 0; j != 0 && k < LOOKUP_BITS ; k++) {
+ acc += (j & 1);
+ j >>= 1;
+ }
+ dviLookUpTable[i] = acc;
+ }
+ tableNotInitialized = 0;
+ }
+
+/*
+ * When shrinking the fonts, we convert them from byte alligned
+ * to 16 bit-aligned fonts. I think that this is needed by X,
+ * and also SunWindows. This is done rather than changing the
+ * library routines because some device drivers, i.e. imagen1,
+ * depend on the byte-alligned fonts.
+ */
+ glyphHigh = gly -> g_height;
+ glyphWide = gly -> g_width;
+
+ shrunkHeight = (glyphHigh + shrinkH - 1) / shrinkH;
+ shrunkWidth = (glyphWide + shrinkW - 1) / shrinkW;
+
+ bytesWide = (gly -> g_width + 7) >> 3;
+
+ shrunkBytesWide = ((shrunkWidth + 15) >> 4) * 2;
+
+ rasterSize = (shrunkHeight + 1) * shrunkBytesWide;
+ ptr = shrunkRaster = (B16 *) malloc(rasterSize);
+ bzero(ptr, rasterSize);
+
+ if (ptr == NULL) {
+ fprintf(stderr, "Out of memory!\n");
+ exit(1);
+ }
+
+ for (y = 0; y < glyphHigh; y+= shrinkH) {
+ cp = (char *) ptr;
+ shrinkMask = 0x8000;
+ for (x = 0; x < glyphWide; x += shrinkW) {
+ int i;
+ int samples;
+ char *baseP;
+ int upper;
+ register int thisShrinkW;
+
+ baseP = gly -> g_raster + (y * bytesWide);
+
+/*
+ * Set the upper limit on the height iteration so we dont count
+ * off the end of the raster
+ */
+
+ upper = y + shrinkH;
+ if (upper > glyphHigh) {
+ upper = glyphHigh;
+ }
+
+ if (x + shrinkW > glyphWide) {
+ thisShrinkW = glyphWide - x;
+ } else {
+ thisShrinkW = shrinkW;
+ }
+
+ samples = 0;
+ sampleSize = thisShrinkW * shrinkH;
+
+ for (i = y; i < upper; i++) {
+ register int acc;
+ register char *p;
+ register char *ep;
+/*
+ * Determine how many bytes our shrink window crosses (we might
+ * overlap on byte-edges)
+ */
+
+ p = baseP + (x >> 3);
+ ep = baseP + ( (x + thisShrinkW - 1) >> 3);
+ baseP += bytesWide;
+
+/*
+ * stuff everything in the accumulator
+ */
+
+ acc = 0;
+ while (p <= ep) {
+ acc = ((acc << 8) & 0xff) | *p;
+ p++;
+ }
+
+/*
+ * clean off the right hand-side of extra bits, then clean off
+ * the left hand side of extra bits, and then count them.
+ */
+
+ acc = acc >> ( 7 - ((x + thisShrinkW - 1) & 0x7));
+ acc &= ~(-1 << thisShrinkW);
+ while (acc != 0) {
+ samples += dviLookUpTable[ acc & LOOKUP_MASK ];
+ acc >>= LOOKUP_BITS;
+ }
+ }
+/*
+ * If at least 1/blackness of the bits are on, treat this entire sample as
+ * being on.
+ */
+
+ if ((samples * dviBlackness) >= sampleSize) {
+ *ptr |= shrinkMask;
+ } else {
+ *ptr &= ~ shrinkMask;
+ }
+ shrinkMask >>= 1;
+ if (shrinkMask == 0) {
+ shrinkMask = 0x8000;
+ ptr ++;
+ }
+ }
+ ptr = (B16 *) (cp + shrunkBytesWide);
+ }
+
+/*
+ * Build a new glyph from the shrunken raster
+ */
+
+#ifdef UNDEF
+ printf("Old glyph:\n");
+ seeGlyph(gly -> g_raster, glyphHigh, bytesWide);
+ printf("New glyph:\n");
+ seeGlyph(shrunkRaster, shrunkHeight, shrunkBytesWide);
+#endif UNDEF
+
+ ngly = (struct glyph *) malloc(sizeof(struct glyph));
+ bzero(ngly, sizeof(struct glyph));
+
+ ngly -> g_raster = (char * ) shrunkRaster;
+ ngly -> g_width = shrunkWidth;
+ ngly -> g_height = shrunkHeight;
+
+ ngly -> g_xorigin = gly -> g_xorigin / shrinkH;
+ ngly -> g_yorigin = gly -> g_yorigin / shrinkW;
+
+ ngly -> g_flags |= GF_SHRUNK; /* yes, its been shrunk */
+
+ return(ngly);
+}
+
+#ifdef UNDEF
+
+seeGlyph(c, h, w)
+char *c;
+int h;
+int w;
+{
+ int i,j;
+
+ for (i = 0; i < h; i++ ) {
+ for (j = 0; j < w; j++) {
+ int k;
+ register int ch;
+ register int m;
+ char str[9];
+
+ ch = *(c++);
+ m = 0x80;
+ for (k = 0; k < 8; k++) {
+ str[k] = '0' + ( (ch & m) ? 1 : 0 );
+ m >>= 1;
+ }
+ str[8] = 0;
+ printf("%s", str);
+ }
+ printf("\n");
+ }
+}
+
+
+#endif UNDEF
diff --git a/dviware/umddvi/previewers/dvistuff.h b/dviware/umddvi/previewers/dvistuff.h
new file mode 100644
index 0000000000..b7da1bd3b7
--- /dev/null
+++ b/dviware/umddvi/previewers/dvistuff.h
@@ -0,0 +1,83 @@
+/*
+ * This program is Copyright (C) 1987 by the Board of Trustees of the
+ * University of Illinois, and by the author Dirk Grunwald.
+ *
+ * This program may be freely copied, as long as this copyright
+ * message remaines affixed. It may not be sold, altough it may
+ * be distributed with other software which is sold. If the
+ * software is distributed, the source code must be made available.
+ *
+ * No warrenty, expressed or implied, is given with this software.
+ * It is presented in the hope that it will prove useful.
+ */
+
+/*
+ * Include the following from the CTex distribution
+ */
+
+#include <stdio.h>
+
+#include "types.h"
+#include "font.h"
+
+/*
+ * We use the following flags to keep track of shrunk fonts
+ */
+
+#define GF_SHRUNK GF_USR0
+
+#define GLYPH_SHRUNK(g) ((g) -> g_flags & GF_SHRUNK)
+
+#define SHRUNK_GLYPH_BYTES_WIDE(g) ((((g) -> g_width + 15) >> 4) * 2)
+
+typedef struct font DviFont;
+typedef struct glyph DviGlyph;
+
+#define MAX_GLYPH 128
+#define MAX_FONTFAMILY 128
+
+#define DEFAULT_DPI 300
+#define DEFAULT_HHMARGIN DEFAULT_DPI
+#define DEFAULT_VVMARGIN DEFAULT_DPI
+
+#define DEFAULT_BLACKNESS 3
+
+
+struct fontinfo {
+ struct font *f; /* the font */
+ i32 pspace; /* boundary between `small & `large spaces
+ (for positive horizontal motion) */
+ i32 nspace; /* -4 * pspace, for negative motion */
+ i32 vspace; /* 5 * pspace, for vertical motion */
+ int family; /* Imagen family number (we pick one) */
+};
+
+typedef struct fontinfo DviFontInfo;
+
+extern int dviHH; /* current horizontal position, in DEVs */
+extern int dviVV; /* current vertical position, in DEVs */
+extern int dviHHMargin;
+extern int dviVVMargin;
+extern int dviDPI;
+extern int dviTallestPage;
+extern int dviWidestPage;
+extern int dviTotalPages;
+extern int dviCurrentPage;
+extern int dviMaxDrift;
+extern char *dviPrintEngine;
+extern int dviBlackness;
+
+extern DviFontInfo *dviCurrentFont;
+extern FILE *dviFile; /* user's file */
+extern char *ProgName;
+
+extern void dviInit();
+extern void dviPreparePage( /* int */ );
+extern struct glyph *dviShrinkGlyph();
+
+void applicationLoadGlyph( /* charCode, glyph */ );
+void applicationPutChar( /* hh, vv, charCode */ );
+DviFont *applicationNewFont( /* font structure */);
+void applicationResetFont(/* font info, key */);
+void applicationSetRule( /* hh, vv, height, width : long*/ );
+void applicationDoSpecial();
diff --git a/dviware/umddvi/previewers/makefile b/dviware/umddvi/previewers/makefile
new file mode 100644
index 0000000000..53b3fd7ba9
--- /dev/null
+++ b/dviware/umddvi/previewers/makefile
@@ -0,0 +1,54 @@
+#
+# Makefile for dvi previewer.
+#
+# $Header: Makefile,v 1.3 87/11/30 12:10:21 grunwald Locked $
+# $Source: /mntm/usr.src.local/Iptex/previewers/RCS/Makefile,v $
+#
+BINDIR=/usr/local/bin
+MANDIR=/usr/man
+INCLUDES= -I/usr/include/X -I../h
+CC= cc
+CFLAGS= -O ${INCLUDES}
+XLIBS= ../lib/lib.a -lX
+SUNLIBS= ../lib/lib.a -lsuntool -lsunwindow -lpixrect
+SRCS= texx.c dvistuff.c dvistuff.h
+MANSRC = texx.1 texsun.1
+
+XOBJS= texx.o dvistuff.o
+SUNOBJS = texsun.o dvistuff.o
+
+all: texx texsun
+
+texx: $(OBJS) Makefile
+ $(CC) $(CFLAGS) -o texx $(XOBJS) $(XLIBS)
+
+texsun: $(SUNOBJS) Makefile
+ $(CC) $(CFLAGS) -o texsun $(SUNOBJS) $(SUNLIBS)
+
+dvistuff.o: dvistuff.c dvistuff.h
+texsun.o: texsun.c dvistuff.h
+texx.o: texx.c dvistuff.h
+
+$(SRCS) $(MANSRC):
+ co -q $@
+
+inst-texx: texx texx.1
+ install -s -c -m 775 texx $(BINDIR)/texx
+ install -c -m 664 texx.1 $(MANDIR)/man1/texx.1
+
+inst-texsun: texsun texsun.1
+ install -s -c -m 775 texsun $(BINDIR)/texsun
+ install -c -m 664 texsun.1 $(MANDIR)/man1/texsun.1
+
+depend:
+ makedepend $(CFLAGS) $(SRCS)
+
+install: inst-texsun inst-texx
+
+clean:
+ -rm -f mktable table.c *.o *.BAK *.CKP texx a.out core errs *~
+
+lint:
+ lint $(INCLUDES) texx.c dvistuff.c $(XLIBS)
+ lint $(INCLUDES) texsun.c dvistuff.c $(SUNLIBS)
+
diff --git a/dviware/umddvi/previewers/texsun.1 b/dviware/umddvi/previewers/texsun.1
new file mode 100644
index 0000000000..e1a80e7154
--- /dev/null
+++ b/dviware/umddvi/previewers/texsun.1
@@ -0,0 +1,36 @@
+.TH TEXSUN 1
+.SH NAME
+texsun \- view DVI files on your SunView display
+.SH SYNOPSIS
+.B texsun
+.B [many options]
+.B filename
+.SH DESCRIPTION
+.I Texsun
+takes a DVI file produced by TeX and converts it to a format suitable
+for a SunView window.
+.I filename
+should be the name of a
+.B .dvi
+file.
+The environment and commands for
+.I texsun
+are too complicated to explain in man page.
+Users should consult the Dvi Output Guide.
+.SH DIAGNOSTICS
+Most of these should be self explanatory.
+.SH AUTHOR
+Dirk Grunwald, Univ. of Illinois
+.br
+.I Texsun
+uses a library of routines written by
+Chris Torek, University of Maryland
+.SH FILES
+/usr/local/texsun
+.br
+.SH "SEE ALSO"
+iptex(1), dviselect(1), tex(1)
+.SH BUGS
+.I Still
+needs to handle more ``\especial''s.
+
diff --git a/dviware/umddvi/previewers/texsun.c b/dviware/umddvi/previewers/texsun.c
new file mode 100644
index 0000000000..4eaa87e3e6
--- /dev/null
+++ b/dviware/umddvi/previewers/texsun.c
@@ -0,0 +1,1576 @@
+/*
+ * This program is Copyright (C) 1987 by the Board of Trustees of the
+ * University of Illinois, and by the author Dirk Grunwald.
+ *
+ * This program may be freely copied, as long as this copyright
+ * message remaines affixed. It may not be sold, altough it may
+ * be distributed with other software which is sold. If the
+ * software is distributed, the source code must be made available.
+ *
+ * No warrenty, expressed or implied, is given with this software.
+ * It is presented in the hope that it will prove useful.
+ */
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <suntool/sunview.h>
+#include <suntool/canvas.h>
+#include <sunwindow/defaults.h>
+#include <sys/file.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sun/fbio.h>
+#include "dvistuff.h"
+/*
+ * These constants may need to be changed on your implementation
+ */
+
+/*
+ * Note that ROUNDUP evaluates Y twice.
+ */
+#define ROUNDUP(x,y) (((x)+(y)-1) / (y))
+
+#define DEBUG printf
+
+#define INFORM (Debug > 2)
+#define TALK (Debug > 1)
+#define VERBOSE (Debug > 0)
+
+int Debug = 0;
+static int obscured = 1;
+
+
+/*
+ * SunTools related variables
+ */
+
+static Window tool = 0;
+static Canvas ptubeWindow = 0;
+static Pixwin *ptube = 0;
+
+static int canvasHeight;
+static int canvasWidth;
+static int canvasNormalWidthOffset;
+static int canvasNormalHeightOffset;
+
+typedef int (*intFuncp)();
+intFuncp memPixmapOps;
+
+static int foregroundMode = PIX_SRC | PIX_DST;
+static int clearMode = PIX_CLR;
+static int setMode = PIX_SET;
+static int copyMode = PIX_SRC;
+static int paintMode;
+static int cursorMode;
+
+static int globalArg = 0;
+static int globalNumber = 0;
+static int globalSign = 1;
+static int globalOtherLeaf = 0;
+static int globalLeafX;
+static int globalLeafY;
+static int globalDisplayState;
+static int globalDisplayLeaf;
+
+static int firstPage = 0;
+static char *dviFileName = 0;
+
+static Cursor workingCursor;
+static Cursor readyCursor;
+
+short workingCursorData[] = {
+#include <images/hglass.cursor>;
+};
+mpr_static(workingCursorPixrect, 16, 16, 1, workingCursorData);
+
+short readyCursorData[] = {
+#include <images/bullseye.cursor>;
+};
+mpr_static(readyCursorPixrect, 16, 16, 1, readyCursorData);
+
+/*
+ * TeX-Dvi related variables
+ */
+
+static int rawDviHeight;
+static int rawDviWidth; /* part of X interface, not dvistuff */
+static int maxHeight;
+static int maxWidth;
+static int maxDepth;
+
+static int screenWidth, screenHeight;
+
+#define MAX_LEAVES 2
+#define LEAF_LEFT 0
+#define LEAF_RIGHT 1
+
+#define DEFAULT_LEAVES 2
+
+static int Leaves;
+static int currentLeaf = 0;
+static int pageOnLeaf[MAX_LEAVES] = {-1,-1};
+static int haveLargePage[MAX_LEAVES] = {-1, -1};
+
+#define SHRINK_NORMAL 0
+#define SHRINK_LARGE 1
+#define MAX_SHRINKS 2
+
+static int page_w[MAX_SHRINKS], page_h[MAX_SHRINKS];
+static int leaf_w[MAX_SHRINKS];
+
+static int shrinkFactor[MAX_SHRINKS];
+static int currentShrink;
+static struct glyph **shrunkenGlyphs[MAX_SHRINKS][MAX_FONTFAMILY];
+
+typedef struct mpr_data MprData;
+static Pixrect **shrunkenPixrect[MAX_SHRINKS][MAX_FONTFAMILY];
+
+static int reverse = 0;
+
+static double specialConv;
+
+#define TEXSUN_STATE_NAME "TEXSUN_STATE"
+#define maxStateLines 100
+char *stateFileName;
+
+char **globalArgv;
+int globalArgc;
+
+char *malloc(), *calloc(), *index();
+
+#define MAXFUNC(a,b) ((a) < (b)) ? (b) : (a)
+#define MINFUNC(a,b) ((a) < (b)) ? (a) : (b)
+
+stop_output()
+{
+/*
+ * We must write the state before killing the window
+ */
+ writeState(stateFileName);
+
+ window_set(tool, FRAME_NO_CONFIRM, TRUE, 0);
+ window_destroy (tool);
+ exit (0);
+}
+
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+
+ int xargc=argc;
+ char **xargv=argv;
+
+ char *display = NULL;
+ char option[120];
+ int optionEnd;
+ char *poption;
+
+ int bwidth = 2;
+ char *geometry = NULL, def[32];
+
+ int bdrpix, mouspix;
+ unsigned long xswattrs_mask;
+
+ struct rect tool_rect;
+ int ptubeSelected();
+ int repaintCanvas();
+ int resizeCanvas();
+
+ double atof();
+ char *getenv();
+
+/*
+ * Choose an explicit name so we always find the options.
+ */
+
+ ProgName = "texsun";
+ argv++;
+ argc--;
+ dviFileName = NULL;
+
+ strcpy(option, ProgName);
+ sprintf(option,"/%s/", ProgName);
+ optionEnd = strlen(option);
+ option[optionEnd] = 0;
+ reverse = (int) defaults_get_boolean(strcat(option,"ReverseVideo"), 0, 0);
+
+ option[optionEnd] = 0;
+ shrinkFactor[SHRINK_NORMAL] =
+ defaults_get_integer(strcat(option,"NormalShrink"), 0, 0);
+
+ option[optionEnd] = 0;
+ shrinkFactor[SHRINK_LARGE] =
+ defaults_get_integer(strcat(option,"LargeShrink"), 0, 0);
+
+ option[optionEnd] = 0;
+ dviDPI = defaults_get_integer(strcat(option,"Dpi"), DEFAULT_DPI, 0);
+
+ option[optionEnd] = 0;
+ Leaves = defaults_get_integer(strcat(option,"Leaves"), 0, 0);
+
+ option[optionEnd] = 0;
+ poption = defaults_get_string(strcat(option,"TopMargin"), 0, 0);
+ dviVVMargin = DEFAULT_VVMARGIN * ( (poption == 0) ? 1.0 : atof(poption));
+
+ option[optionEnd] = 0;
+ poption = defaults_get_string(strcat(option,"SideMargin"), 0, 0);
+ dviHHMargin = DEFAULT_HHMARGIN * ( (poption == 0) ? 1.0 : atof(poption));
+
+ option[optionEnd] = 0;
+ dviBlackness = defaults_get_integer(strcat(option,"Blackness"),
+ DEFAULT_BLACKNESS, 0);
+
+ option[optionEnd] = 0;
+ stateFileName = defaults_get_string(strcat(option,"StateFile"), 0, 0);
+
+ if (stateFileName == 0) {
+ stateFileName = getenv(TEXSUN_STATE_NAME);
+ }
+
+ if (argc > 0 && strcmp(argv[0], "-new") == 0) {
+ argv++;
+ argc--;
+ } else {
+ readState(&argc, &argv, stateFileName);
+ }
+
+ globalArgc = argc;
+ globalArgv = argv;
+
+ while (argc) {
+ if (strcmp(*argv, "-rv") == 0) {
+ reverse = !reverse;
+/*
+ * these two are for the state-saver
+ */
+
+ } else if (strcmp(*argv, "-rvOn") == 0 ) {
+ reverse = 1;
+ } else if (strcmp(*argv, "-rvOff") == 0) {
+ reverse = 0;
+ } else if (strcmp(*argv,"-l") == 0 && argc > 1) {
+ argv++;
+ argc--;
+ Leaves = atoi(*argv);
+ if( Leaves < 1 || Leaves > MAX_LEAVES) {
+ fprintf(stderr,"[%s] Bad number of leaves(%d), using %d\n",
+ ProgName, Leaves, MAX_LEAVES);
+ Leaves = MAX_LEAVES;
+ }
+ } else if (strcmp(*argv,"-ns") == 0 && argc > 1) {
+ argv++;
+ argc--;
+ shrinkFactor[SHRINK_NORMAL] = atoi(*argv);
+ } else if (strcmp(*argv,"-ls") == 0 && argc > 1) {
+ argv++;
+ argc--;
+ shrinkFactor[SHRINK_LARGE] = atoi(*argv);
+ } else if (strcmp(*argv,"-dpi") == 0 && argc > 1) {
+ argv++;
+ argc--;
+ dviDPI = atoi(*argv);
+ } else if (strcmp(*argv,"-tm") == 0 && argc > 1) {
+ argv++;
+ argc--;
+ dviVVMargin = dviDPI * atof(*argv);
+ } else if (strcmp(*argv,"-sm") == 0 && argc > 1) {
+ argv++;
+ argc--;
+ dviHHMargin = dviDPI * atof(*argv);
+ } else if (strcmp(*argv, "-bl") == 0 && argc > 1) {
+ argv++;
+ argc--;
+ dviBlackness = atoi(*argv);
+ } else if (strcmp(*argv, "-pg") == 0 && argc > 1) {
+ argv++;
+ argc--;
+ firstPage = atoi(*argv);
+ } else if (strcmp(*argv,"-debug") == 0 && argc > 1) {
+ argv++;
+ argc--;
+ Debug = atoi(*argv);
+ } else if (**argv != '-') {
+ dviFileName = *argv;
+ } else {
+ usage:
+ fprintf(stderr, "Usage: %s [-ns <shrink>] [-ls <shrink>] [-dpi <dots>] \n",
+ ProgName);
+ fprintf(stderr, " [-l <leaves>] [-rv] [-tm <inches>] [-sm <inches>] dviFile\n");
+ exit(1);
+ }
+ argv++;
+ argc--;
+ }
+
+ if (dviFileName == NULL)
+ goto usage;
+
+ if ((dviFile = fopen(dviFileName, "r")) == NULL) {
+ int n = strlen(dviFileName);
+ char *dvi_name;
+
+ if (strcmp(dviFileName + n - sizeof(".dvi") + 1, ".dvi") == 0) {
+ perror(dviFileName);
+ exit(1);
+ }
+ dvi_name = malloc((unsigned) n + sizeof(".dvi"));
+ sprintf(dvi_name, "%s.dvi", dviFileName);
+
+ if ((dviFile = fopen(dvi_name, "r")) == NULL) {
+ perror(dvi_name);
+ exit(1);
+ }
+
+ dviFileName = dvi_name;
+ }
+
+ if (INFORM) {
+ fprintf(stderr, "[texsun] call dviInit();\n");
+ }
+
+ dviInit();
+
+ if (TALK) {
+ fprintf(stderr,"page is %d wide, %d high\n",
+ dviTallestPage, dviWidestPage);
+ }
+
+ if (((double) dviTallestPage * (double) dviWidestPage) > 4.0e7) {
+ fprintf(stderr,"[%s] Warning: Your page size is %d wide and %d tall,\n",
+ ProgName, dviTallestPage, dviWidestPage);
+ fprintf(stderr,"which may be too big to be displayed\n");
+ }
+
+ specialConv = (float) dviDPI / 1000.0;
+
+/*
+ * If no shrink factor was chosen, pick one which will work out nicely
+ * on their display
+ */
+ if (INFORM) {
+ fprintf(stderr, "[texsun] set screenSpecific\n");
+ }
+
+ setScreenSpecifics();
+
+ rawDviHeight = dviTallestPage + 2 * dviVVMargin;
+ rawDviWidth = dviWidestPage + 2 * dviHHMargin;
+
+ if (Leaves == 0) {
+ if (dviTotalPages == 1) {
+ Leaves = 1;
+ } else {
+ Leaves = DEFAULT_LEAVES;
+ }
+ }
+
+ if (INFORM) {
+ fprintf(stderr, "[texsun] choose screenSpecific\n");
+ }
+
+ if (shrinkFactor[SHRINK_NORMAL] == 0) {
+ int sH;
+ int sW;
+ int sH2;
+ int sW2;
+ int shrink2;
+
+ sH = (rawDviHeight + maxHeight - 1) / maxHeight;
+ sW = (Leaves * rawDviWidth + maxWidth - 1) / maxWidth;
+
+ shrinkFactor[SHRINK_NORMAL] = MAXFUNC(sW, sH);
+ shrinkFactor[SHRINK_NORMAL] = MAXFUNC(shrinkFactor[SHRINK_NORMAL], 1);
+
+/*
+ * Check to see if we can get another shrink size bigger display
+ * if we cut the margins.
+ */
+
+ sH2 = (dviTallestPage + (dviHHMargin/32) + maxHeight - 1)
+ / maxHeight;
+ sW2 = ( Leaves * (dviWidestPage + (dviVVMargin/32))
+ + maxHeight - 1) / maxHeight;
+
+ shrink2 = MAXFUNC(sH2, sW2);
+ shrink2 = MAXFUNC(shrink2, 1);
+
+ if (shrink2 < shrinkFactor[SHRINK_NORMAL]) {
+ dviVVMargin /= 32;
+ dviHHMargin /= 32;
+ rawDviHeight = dviTallestPage + 2 * dviVVMargin;
+ rawDviWidth = dviWidestPage + 2 * dviHHMargin;
+ shrinkFactor[SHRINK_NORMAL] = shrink2;
+ }
+ }
+
+ page_h[SHRINK_NORMAL]=(rawDviHeight + shrinkFactor[SHRINK_NORMAL] - 1)
+ / shrinkFactor[SHRINK_NORMAL];
+ leaf_w[SHRINK_NORMAL]=(rawDviWidth + shrinkFactor[SHRINK_NORMAL] - 1)
+ / shrinkFactor[SHRINK_NORMAL];
+
+/*
+ * Based on the shrink factor, choose a shrink factor for the enlarged
+ * display
+ */
+
+ if (shrinkFactor[SHRINK_LARGE] == 0) {
+ shrinkFactor[SHRINK_LARGE] = shrinkFactor[SHRINK_NORMAL] / 2;
+ }
+
+ shrinkFactor[SHRINK_LARGE] = MINFUNC(shrinkFactor[SHRINK_LARGE],
+ shrinkFactor[SHRINK_NORMAL]-1);
+ shrinkFactor[SHRINK_LARGE] = MAXFUNC(shrinkFactor[SHRINK_LARGE], 1);
+
+ page_h[SHRINK_LARGE]=(rawDviHeight + shrinkFactor[SHRINK_LARGE] - 1)
+ / shrinkFactor[SHRINK_LARGE];
+ leaf_w[SHRINK_LARGE]=(rawDviWidth + shrinkFactor[SHRINK_LARGE] - 1)
+ / shrinkFactor[SHRINK_LARGE];
+
+/*
+ * Compute the page size given the number of leaves. We may have
+ * to scale back if everything cant fit.
+ */
+
+ if (leaf_w[SHRINK_NORMAL] * Leaves <= maxWidth) {
+ page_w[SHRINK_NORMAL] = leaf_w[SHRINK_NORMAL] * Leaves;
+ } else {
+ page_w[SHRINK_NORMAL] = leaf_w[SHRINK_NORMAL];
+ Leaves = 1;
+ }
+
+ screenWidth = (page_w[SHRINK_NORMAL] > maxWidth)
+ ? maxWidth : page_w[SHRINK_NORMAL];
+ screenHeight = (page_h[SHRINK_NORMAL] > maxHeight)
+ ? maxHeight : page_h[SHRINK_NORMAL];
+
+ tool_rect.r_left = 0;
+ tool_rect.r_top = 0;
+ tool_rect.r_width = 0;
+ tool_rect.r_height = 0;
+
+ cursorMode = PIX_SRC ^ PIX_DST;
+
+ if (reverse) {
+ paintMode = PIX_NOT(PIX_SRC);
+ } else {
+ paintMode = PIX_SRC;
+ }
+
+ if (INFORM) {
+ fprintf(stderr,"[texsun] create the tool windows\n");
+ }
+
+/* create the tool */
+ tool = window_create (0, FRAME,
+ FRAME_LABEL, "TeXsun",
+ FRAME_OPEN_RECT, &tool_rect,
+ 0);
+ if (tool == 0) {
+ fprintf(stderr,"Unable to create window\n");
+ exit(1);
+ }
+ ptubeWindow = window_create(tool, CANVAS,
+ CANVAS_AUTO_SHRINK, TRUE,
+ CANVAS_AUTO_EXPAND, TRUE,
+ CANVAS_WIDTH, screenWidth,
+ WIN_FIT_WIDTH, screenWidth,
+ CANVAS_HEIGHT, screenHeight,
+ WIN_FIT_HEIGHT, screenHeight,
+ CANVAS_RETAINED, FALSE,
+ CANVAS_REPAINT_PROC, repaintCanvas,
+ CANVAS_RESIZE_PROC, resizeCanvas,
+ WIN_EVENT_PROC, ptubeSelected,
+ WIN_BOTTOM_MARGIN, 0,
+ WIN_LEFT_MARGIN, 0,
+ WIN_TOP_MARGIN, 0,
+ WIN_RIGHT_MARGIN, 0,
+ WIN_X, 0,
+ WIN_Y, 0,
+ 0);
+ if (ptubeWindow == 0) {
+ fprintf(stderr,"Unable to create canvas\n");
+ exit(1);
+ }
+
+ readyCursor = cursor_create(CURSOR_IMAGE, &readyCursorPixrect,
+ CURSOR_OP, cursorMode, 0);
+ workingCursor = cursor_create(CURSOR_IMAGE, &workingCursorPixrect,
+ CURSOR_OP, cursorMode, 0);
+
+ ptubeInit();
+
+ window_set(ptubeWindow, WIN_CONSUME_KBD_EVENT, WIN_ASCII_EVENTS,0);
+
+ signal (SIGINT, stop_output);
+ signal (SIGQUIT, stop_output);
+ signal (SIGIOT, stop_output);
+
+ window_fit(ptubeWindow);
+ window_fit(tool);
+
+ if (INFORM) {
+ fprintf(stderr,"[texsun] enter window loop\n");
+ }
+
+ window_main_loop (tool);
+
+ /* terminate tool */
+ stop_output(0);
+}
+
+/*
+ * State-maintenance routines.
+ *
+ * The state is maintained in a file indicated by the environment
+ * variable TEXSUN_STATE.
+ *
+ * The state is written as a sequence of options, the same options
+ * which can be specified on the command line.
+ *
+ * When the state is used, the saved options are inserted in the
+ * command line before any new options. Thus, new options will
+ * over-ride the saved options, and both saved state and command
+ * line options will over-ride the default options.
+ */
+
+readState(inOutArgc, inOutArgv, stateFileName)
+char ***inOutArgv;
+int *inOutArgc;
+char *stateFileName;
+{
+ if (stateFileName != 0) {
+ FILE *f;
+ char **newArgv;
+ char *p;
+ int newArgc;
+ char buffer[512];
+ char *bufp;
+ int i;
+
+ int argc = *inOutArgc;
+ char **argv = *inOutArgv;
+
+ newArgv = (char **) malloc( sizeof(char *) * (argc + maxStateLines));
+ f = fopen(stateFileName,"r");
+
+/*
+ * The program name has already been removed.
+ */
+
+ newArgc = 0;
+
+ if (f != 0) {
+ while (!feof(f)) {
+ p = fgets(buffer, 512, f);
+ if (p != 0) {
+ int lth;
+ lth = strlen(buffer);
+ p = malloc(lth + 1);
+ strcpy(p, buffer);
+ p[lth-1] = 0; /* kill the newline character */
+ newArgv[newArgc++] = p;
+ }
+ }
+
+ for (i = 0 ; i < argc; i++ ) {
+ newArgv[newArgc++] = argv[i];
+ }
+
+ *inOutArgc = newArgc;
+ *inOutArgv = newArgv;
+ }
+ }
+}
+
+writeState(stateFileName)
+char *stateFileName;
+{
+ if (stateFileName != 0) {
+ FILE *f;
+ char *ptr;
+
+ f = fopen(stateFileName,"w");
+ if (f != 0) {
+ fprintf(f, "-rv%s\n", (reverse) ? "On" : "Off");
+ fprintf(f, "-l\n%d\n", Leaves);
+ fprintf(f, "-ns\n%d\n", shrinkFactor[SHRINK_NORMAL]);
+ fprintf(f, "-ls\n%d\n", shrinkFactor[SHRINK_LARGE]);
+ fprintf(f, "-dpi\n%d\n", dviDPI);
+ fprintf(f, "-tm\n%f\n", (double)
+ ((double) dviVVMargin / (double) dviDPI));
+ fprintf(f, "-sm\n%f\n", (double)
+ ((double) dviHHMargin / (double) dviDPI));
+ fprintf(f, "-bl\n%d\n", dviBlackness);
+ fprintf(f, "-debug\n%d\n", Debug);
+ fprintf(f, "-pg\n%d\n", pageOnLeaf[0]);
+ fprintf(f, "%s\n", dviFileName);
+
+ fclose(f);
+ }
+ }
+}
+
+
+/*
+ * Sun Screen-specific things
+ */
+setScreenSpecifics()
+{
+ struct fbtype FbType;
+ int Fb;
+
+ Fb = open("/dev/fb", O_RDONLY, 0);
+
+ if (Fb < 0) {
+ perror("open");
+ fprintf(stderr,"Unable to open /dev/fb\n");
+ exit(1);
+ }
+ if (ioctl(Fb, FBIOGTYPE, &FbType) == -1) {
+ perror("ioctl");
+ fprintf(stderr,"Unable to determine screen size\n");
+ exit(1);
+ }
+
+ maxWidth = FbType.fb_width;
+ maxHeight = FbType.fb_height;
+ maxDepth = FbType.fb_depth;
+
+ close(Fb);
+}
+
+resizeCanvas(canvas, width, height)
+{
+ canvasWidth = width;
+ canvasHeight = height;
+
+ if (canvasWidth > (Leaves * leaf_w[SHRINK_NORMAL])) {
+ canvasNormalWidthOffset =
+ (canvasWidth - Leaves * leaf_w[SHRINK_NORMAL]);
+ }
+ if (canvasHeight > (Leaves * page_h[SHRINK_NORMAL])) {
+ canvasNormalHeightOffset =
+ (canvasHeight - Leaves * page_h[SHRINK_NORMAL]);
+ }
+}
+
+repaintCanvas(canvas, pixwin, repaint_area)
+Canvas canvas;
+Pixwin *pixwin;
+Rectlist *repaint_area;
+{
+ displayLeaves();
+}
+
+/*
+ * Pixmap manipulation routines
+ */
+
+static Pixrect *pasteUpPixmap[MAX_SHRINKS][MAX_LEAVES];
+static int largePixmapsAllocated = 0;
+
+/*
+ * Ideally, we'd like to paint up a local pixmap & then transmit the
+ * entire pixmap. However, it looks like pixmaps require interaction
+ * with the server.
+ *
+ * So, if the entire page fits on the screen, we'll paint the screen
+ * and when we're done, we'll copy the screen to the pixmap. This
+ * gives the illusion of progress, but allows us to do fast re-paints.
+ *
+ * If we're *not* on the display, we'll just draw to the pixmap and
+ * update it at the end
+ */
+
+static int buildToPixmap = 0;
+
+static void
+clearPixmap(leaf, shrinkSize)
+int leaf;
+int shrinkSize;
+{
+ Pixrect *w;
+
+ if (leaf< 0 || leaf >= Leaves) {
+ fprintf(stderr,"[%s] Reference to bogus leaf in clearPixmap: %d\n",
+ ProgName, leaf);
+ exit(1);
+ }
+
+ if (shrinkSize < 0 || shrinkSize >= MAX_SHRINKS ) {
+ fprintf(stderr,"[%s] reference to bogus shrink %d\n",
+ ProgName, shrinkSize);
+ exit(1);
+ }
+
+ w = pasteUpPixmap[shrinkSize][leaf];
+ pr_rop(w, 0, 0,
+ leaf_w[shrinkSize], page_h[shrinkSize],
+ clearMode,
+ w, 0, 0);
+}
+
+/*
+ * Clear the window. Actually, for a black-on-white display (normal)
+ * this means we need to *set* the entire display using COLOR(1) color.
+ */
+static void
+clearWindow()
+{
+ int localClear = PIX_COLOR(1) | clearMode;
+ if (reverse) {
+ localClear = PIX_NOT(localClear);
+ }
+ pw_writebackground(ptube,
+ 0, 0,
+ canvasWidth, canvasHeight,
+ localClear);
+}
+
+allocatePixmaps()
+{
+ int i;
+
+ for (i = 0; i < Leaves; i++ ) {
+ pasteUpPixmap[SHRINK_NORMAL][i] = (Pixrect *)
+ mem_create(leaf_w[SHRINK_NORMAL], page_h[SHRINK_NORMAL], 1);
+
+ if (pasteUpPixmap[SHRINK_NORMAL][i] == 0) {
+ fprintf(stderr,"[%s] erp! out of PIXMAP memory!\n",
+ ProgName);
+ stop_output();
+ }
+ }
+
+ largePixmapsAllocated = 0;
+
+/*
+ * Clear the pixmap
+ */
+ for (i = 0; i < Leaves; i++) {
+ clearPixmap(i, SHRINK_NORMAL);
+ }
+}
+
+allocateLargePixmaps()
+{
+ int i;
+ for (i = 0; i < Leaves; i++) {
+ pasteUpPixmap[SHRINK_LARGE][i] = (Pixrect *)
+ mem_create(leaf_w[SHRINK_LARGE], page_h[SHRINK_LARGE], 1);
+ clearPixmap(i, SHRINK_LARGE);
+ }
+
+ largePixmapsAllocated = 1;
+}
+
+/*
+ * display the normal sized leaf
+ */
+static int
+displayLeaves()
+{
+ if (globalDisplayState == SHRINK_LARGE) {
+
+/*
+ * globalLeafX and globalLeafY point the part of the display
+ * they want to see, scaled to the large shrink.
+ *
+ */
+ int leafX;
+ int leafY;
+ int leafW;
+ int leafH;
+ int canvasX;
+ int canvasY;
+
+ leafW = MINFUNC(leaf_w[SHRINK_LARGE], canvasWidth);
+ leafH = MINFUNC(page_h[SHRINK_LARGE], canvasHeight);
+
+ leafX = globalLeafX - (leafW / 2); /* find left side */
+ if (leafX < 0) {
+ canvasX = -leafX;
+ leafX = 0;
+ } else {
+ canvasX = 0;
+ }
+
+ if ((leafX + leafW) > leaf_w[SHRINK_LARGE]) {
+ leafW = leaf_w[SHRINK_LARGE] - leafX;
+ }
+
+ leafY = globalLeafY - (leafH / 2); /* gind top side */
+ if (leafY < 0) {
+ canvasY = -leafY;
+ leafY = 0;
+ } else {
+ canvasY = 0;
+ }
+ if ((leafY + leafH) > page_h[SHRINK_LARGE]) {
+ leafH = page_h[SHRINK_LARGE] - leafY;
+ }
+
+#ifdef UNDEF
+ if (leafW < canvasWidth) {
+ leafX += (canvasWidth - leafW) / 2;
+ }
+ if (leafH < canvasHeight) {
+ leafY += (canvasHeight - leafH) / 2;
+ }
+#endif
+
+ clearWindow();
+ pw_write(ptube,
+ canvasX, canvasY,
+ leafW, leafH,
+ paintMode,
+ pasteUpPixmap[SHRINK_LARGE][globalDisplayLeaf],
+ leafX, leafY);
+ } else {
+ clearWindow();
+ pw_write(ptube,
+ 0, 0,
+ leaf_w[SHRINK_NORMAL], page_h[SHRINK_NORMAL],
+ paintMode,
+ pasteUpPixmap[SHRINK_NORMAL][0],
+ 0,0);
+ pw_write(ptube,
+ leaf_w[SHRINK_NORMAL], 0,
+ leaf_w[SHRINK_NORMAL], page_h[SHRINK_NORMAL],
+ paintMode,
+ pasteUpPixmap[SHRINK_NORMAL][1],
+ 0,0);
+ }
+}
+
+static void
+swapLeaf(from, to)
+int from;
+int to;
+{
+ Pixrect *tempPix;
+ int tempNum;
+
+ if (to < 0 || to >= Leaves) {
+ fprintf(stderr,"[%s] bogus to leaf %d in swapLeaf\n",
+ ProgName, to);
+ exit(1);
+ }
+ if (from < 0 || from >= Leaves) {
+ fprintf(stderr,"[%s] bogus from leaf %d in swapLeaf\n",
+ ProgName, from);
+ exit(1);
+ }
+
+ tempPix = pasteUpPixmap[SHRINK_NORMAL][to];
+ pasteUpPixmap[SHRINK_NORMAL][to] = pasteUpPixmap[SHRINK_NORMAL][from];
+ pasteUpPixmap[SHRINK_NORMAL][from] = tempPix;
+
+ tempPix = pasteUpPixmap[SHRINK_LARGE][to];
+ pasteUpPixmap[SHRINK_LARGE][to] = pasteUpPixmap[SHRINK_LARGE][from];
+ pasteUpPixmap[SHRINK_LARGE][from] = tempPix;
+
+ tempNum = pageOnLeaf[to];
+ pageOnLeaf[to] = pageOnLeaf[from];
+ pageOnLeaf[from] = tempNum;
+
+ tempNum = haveLargePage[to];
+ haveLargePage[to] = haveLargePage[from];
+ haveLargePage[from] = tempNum;
+}
+
+static void
+buildLeaf(leaf, page, shrinkSize)
+int leaf;
+int page;
+int shrinkSize;
+{
+
+ if (leaf < 0 || leaf >= Leaves) {
+ fprintf(stderr,"[%s] bogus leaf %d in buildLeaf\n",
+ ProgName, leaf);
+ exit(1);
+ }
+
+ if (shrinkSize < 0 || shrinkSize >= MAX_SHRINKS ) {
+ fprintf(stderr,"[%s] Bogus shrink size %d in buildLeaf\n",
+ ProgName, shrinkSize);
+ exit(1);
+ }
+
+ window_set(ptubeWindow, WIN_CURSOR, workingCursor, 0);
+
+ if (shrinkSize == SHRINK_LARGE && !largePixmapsAllocated) {
+ allocateLargePixmaps();
+ }
+
+/*
+ * If this is a normal size page, kill the information
+ * for the large version.
+ */
+ if (shrinkSize == SHRINK_NORMAL) {
+ haveLargePage[leaf] = -1;
+ }
+
+/*
+ * Determine if this is a valid page. If it's not, we'll just clear
+ * the particular leaf.
+ */
+
+ if (page < 0 || page >= dviTotalPages) {
+ clearPixmap(leaf, shrinkSize);
+
+ if (shrinkSize == SHRINK_NORMAL) {
+ clearWindow(leaf);
+ }
+ } else {
+
+ if (obscured || shrinkSize == SHRINK_LARGE) {
+ buildToPixmap = 1;
+ } else {
+ buildToPixmap = 1;
+ }
+
+ if (buildToPixmap) {
+ clearPixmap(leaf, shrinkSize);
+ } else {
+ clearPixmap(leaf, shrinkSize);
+ if (shrinkSize == SHRINK_NORMAL) {
+ clearWindow(leaf);
+ }
+ }
+
+/*
+ * Note that dviPreparePage may change dviCurrentPage
+ */
+
+ currentLeaf = leaf;
+ currentShrink = shrinkSize;
+
+ dviPreparePage(page);
+
+ page = dviCurrentPage;
+
+/*
+ * Save the constructed page if we were painting it to the screen
+ */
+ put_border(0, 0, leaf_w[currentShrink], page_h[currentShrink], 1);
+
+ if (! buildToPixmap && shrinkSize == SHRINK_NORMAL) {
+ clearPixmap(leaf, SHRINK_NORMAL);
+/*
+ * We save the pixmap from the *retained* image -- the tool may not
+ * actually be up. This isn't optimal, but it saves us a lot of
+ * hacking & having to determine when we're obscured.
+ */
+ pr_rop(pasteUpPixmap[SHRINK_NORMAL][leaf],
+ 0,0,
+ leaf_w[SHRINK_NORMAL], page_h[SHRINK_NORMAL],
+ copyMode,
+ ptube -> pw_prretained,
+ leaf_w[SHRINK_NORMAL] * leaf, 0);
+ } else if (shrinkSize == SHRINK_NORMAL) {
+ /* null */
+ }
+ }
+
+ pageOnLeaf[leaf] = dviCurrentPage;
+ window_set(ptubeWindow, WIN_CURSOR, readyCursor, 0);
+}
+
+/*
+ * interfaces to dvistuff
+ */
+
+/*
+ * Whenever a new font is registers, we create a shrunken Glyph
+ * table for it. However, we don't shrink the glyphs -- that's
+ * done on the fly by the putChar routine.
+ */
+
+DviFont *
+applicationNewFont(f, key)
+struct font *f;
+int key;
+{
+ int shrink;
+
+ if (key < 0 || key > MAX_FONTFAMILY) {
+ fprintf(stderr,"[%s] bogus key in Newfont = %d\n",
+ ProgName, key);
+ exit(1);
+ }
+
+ for (shrink = SHRINK_NORMAL; shrink <= SHRINK_LARGE; shrink++) {
+
+ if (shrunkenGlyphs[shrink][key] == 0) {
+ int lth = sizeof(struct glyph *) * MAX_GLYPH;
+ struct glyph **g;
+
+ g = (struct glyph **) malloc( lth );
+ bzero(g, lth);
+ shrunkenGlyphs[shrink][key] = g;
+ }
+
+ if (shrunkenPixrect[shrink][key] == 0) {
+ int lth = sizeof(Pixrect *) * MAX_GLYPH;
+ Pixrect **g;
+
+ g = (Pixrect **) malloc( lth );
+ bzero(g, lth);
+ shrunkenPixrect[shrink][key] = g;
+ }
+
+ }
+ return(f);
+}
+
+/*
+ * When we reset a font, we only need to free the storage for the
+ * shrunken glyphs. We keep the glyph table available because we're
+ * very likely to fill it in again.
+ */
+
+void
+applicationResetFont(fi, key)
+struct fontinfo *fi;
+int key;
+{
+ int i;
+ struct glyph **theseGlyphs;
+ Pixrect **thesePixrect;
+ int shrink;
+
+
+ for (shrink = SHRINK_NORMAL; shrink <= SHRINK_LARGE; shrink++) {
+ theseGlyphs = shrunkenGlyphs[shrink][key];
+ if (theseGlyphs != 0) {
+ for (i = 0; i < MAX_GLYPH; i++) {
+ struct glyph *g;
+
+ g = theseGlyphs[i];
+
+ if (g != 0) {
+ if ( g -> g_raster != 0) {
+ free(g -> g_raster);
+ }
+ free(g);
+ theseGlyphs[i] = 0;
+ }
+ }
+ }
+
+ thesePixrect = shrunkenPixrect[shrink][key];
+ if (thesePixrect != 0) {
+ for (i = 0; i < MAX_GLYPH; i++) {
+ Pixrect *g;
+
+ g = thesePixrect[i];
+
+ if (g != 0) {
+ free(g -> pr_data);
+ free(g);
+ thesePixrect[i] = 0;
+ }
+ }
+ }
+ }
+}
+
+
+void
+applicationPutChar(hh, vv, charCode)
+int hh;
+int vv;
+int charCode;
+{
+ register struct glyph *g;
+ int x,y;
+ int key;
+ Pixrect *image;
+
+ key = dviCurrentFont -> family;
+
+ g = shrunkenGlyphs[currentShrink][key][charCode];
+
+ if (g == 0) {
+
+ MprData *newMpr = (MprData *) malloc(sizeof(MprData));
+ Pixrect *newPixrect = (Pixrect *) malloc(sizeof(Pixrect));
+ extern struct pixrectops mem_ops;
+
+ g = dviShrinkGlyph(dviCurrentFont -> f -> f_gly[charCode],
+ shrinkFactor[currentShrink],
+ shrinkFactor[currentShrink]);
+ shrunkenGlyphs[currentShrink][key][charCode] = g;
+
+ newMpr -> md_linebytes = SHRUNK_GLYPH_BYTES_WIDE(g);
+ newMpr -> md_image = (short *) g -> g_raster;
+ newMpr -> md_offset.x = 0;
+ newMpr -> md_offset.y = 0;
+ newMpr -> md_primary = 0;
+ newMpr -> md_flags = 0;
+
+ newPixrect -> pr_ops = &mem_ops;
+ newPixrect -> pr_size.x = g -> g_width;
+ newPixrect -> pr_size.y = g -> g_height;
+ newPixrect -> pr_depth =1;
+ newPixrect -> pr_data = (caddr_t) newMpr;
+ shrunkenPixrect[currentShrink][key][charCode] = newPixrect;
+ }
+
+ if (g == 0 || !HASRASTER(g)) return;
+
+ hh /= shrinkFactor[currentShrink];
+ vv /= shrinkFactor[currentShrink];
+
+ x = hh - g -> g_xorigin;
+ y = vv - g -> g_yorigin;
+
+ image = shrunkenPixrect[currentShrink][key][charCode];
+
+ if (buildToPixmap) {
+ pr_rop(pasteUpPixmap[currentShrink][currentLeaf],
+ x,y,
+ g->g_width, g->g_height,
+ foregroundMode,
+ image,
+ 0,0);
+ } else {
+ x += currentLeaf * leaf_w[currentShrink];
+ pw_write(ptube,
+ x, y,
+ g->g_width, g->g_height,
+ foregroundMode,
+ image,
+ 0,0);
+ }
+}
+
+void
+applicationSetRule(hh, vv, h, w)
+int hh, vv;
+int h, w;
+{
+/* (w,h) specifies lower left corner of rule box */
+ int nh, nw;
+
+ hh /= shrinkFactor[currentShrink];
+ vv /= shrinkFactor[currentShrink];
+
+ nh = h / shrinkFactor[currentShrink];
+ nw = w / shrinkFactor[currentShrink];
+
+ if (nh == 0 && h != 0) {
+ nh = 1;
+ }
+ if (nw == 0 && w != 0) {
+ nw = 1 ;
+ }
+
+ put_rectangle(hh, vv - nh, nw, nh, setMode);
+}
+
+/*
+ * This code attempts to support the same set of specials
+ * as imagen1
+ */
+static char *
+skipWhite(c)
+char *c;
+{
+ while (c != 0 && *c != 0 && isspace(*c)) c++;
+ return(c);
+}
+
+static char *
+skipNonWhite(c)
+char *c;
+{
+ while (c != 0 && *c != 0 && ! isspace(*c)) c++;
+ return(c);
+}
+
+#define MAX_POINTS 128
+static int pointListCount = 0;
+static struct pr_pos pointList[MAX_POINTS];
+
+static struct pr_brush specialBrush = {1};
+
+void
+applicationDoSpecial(command)
+char *command;
+{
+ char com[20];
+ int x,y;
+ char *c, *oc;
+
+ c = skipWhite(command);
+ if (*c == 0) return;
+
+ oc = c;
+ c = skipNonWhite(c);
+ x = *c;
+ *c = '\000';
+ strncpy(com, oc, 20);
+ *c = x;
+ c++;
+
+ if (strcmp(com, "pa") == 0) {
+ sscanf(c, " %d %d ", &x, &y);
+ pointList[pointListCount].x =
+ (specialConv * x + dviHH) / shrinkFactor[currentShrink];
+ pointList[pointListCount].y =
+ (specialConv * y + dviVV) / shrinkFactor[currentShrink];
+
+ if (! buildToPixmap) {
+ pointList[pointListCount].x += currentLeaf * leaf_w[currentShrink];
+ }
+
+ pointListCount++;
+
+/*
+ * Make all lines styles come out as a simple line.
+ * Crude, but effective.
+ */
+
+ } else if (strcmp(com, "fp") == 0
+ || strcmp(com,"da") == 0
+ || strcmp(com,"dt") == 0) {
+ if (pointListCount > 0) {
+
+ int fx,fy;
+ int tx,ty;
+ int i;
+
+ fx = pointList[0].x;
+ fy = pointList[0].y;
+
+ for (i = 0; i < pointListCount; i++) {
+ tx = pointList[i].x;
+ ty = pointList[i].y;
+ if (buildToPixmap) {
+ pr_vector(pasteUpPixmap[currentShrink][currentLeaf],
+ fx, fy, tx, ty, foregroundMode, -1);
+ } else {
+ pw_vector(ptube,
+ fx, fy, tx, ty, foregroundMode, -1);
+ }
+ fx = tx;
+ fy = ty;
+ }
+ }
+ pointListCount = 0;
+
+ } else if (strcmp(com, "pn") == 0) {
+ int penSize;
+ sscanf(c," %d ", &penSize);
+ penSize /= (shrinkFactor[currentShrink] * 2); /* looks good */
+ penSize = MAXFUNC(penSize,1);
+ penSize = MINFUNC(penSize,99);
+/*
+ * We dont do anything with this
+ */
+
+ } else {
+
+/*
+ * For now, lets just flush the special
+ */
+ pointListCount = 0;
+ fprintf(stderr, "[%s] special \"%s\" not implemented\n",
+ ProgName, command);
+ }
+}
+
+ptubeInit()
+{
+ struct inputmask mask;
+
+ ptube = canvas_pixwin(ptubeWindow);
+
+ if (ptube == (Pixwin *) NULL) {
+ fprintf(stderr,"Couldn't create ptube pixwin\n");
+ stop_output(0);
+ }
+
+ obscured = 1; /* SunTools does auto-save-unders */
+ globalDisplayState = SHRINK_NORMAL;
+
+ resizeCanvas(ptube,
+ (int) window_get(ptube, CANVAS_WIDTH),
+ (int) window_get(ptube, CANVAS_HEIGHT));
+
+ allocatePixmaps();
+ dviCurrentPage = firstPage;
+ buildLeaf(LEAF_LEFT, dviCurrentPage, SHRINK_NORMAL);
+
+ if (Leaves == 2) {
+ buildLeaf(LEAF_RIGHT, dviCurrentPage + 1, SHRINK_NORMAL);
+ }
+ globalArg = 0;
+ globalNumber = 0;
+}
+
+/* respond to damage to ptube subwindow */
+static int
+ptubeSighandler(sw)
+caddr_t sw;
+{
+ displayLeaves();
+}
+
+static int
+ptubeSelected(win, inputEvent, arg)
+ Window *win;
+ Event *inputEvent;
+ caddr_t arg;
+{
+ int ch;
+
+ int repaint;
+ int rebuild;
+
+#define BOGUSDIR -1
+#define FOREWARD 0
+#define BACKWARD 1
+#define ABSOLUTE 2
+
+ int direction;
+
+ Event *ie;
+
+ repaint = 1;
+ rebuild = 0;
+ direction = BOGUSDIR;
+
+ ie = inputEvent;
+
+ switch(event_id(ie)) {
+
+ case BUT(1) :
+ case BUT(2) :
+ case BUT(3):
+ if (event_is_down(ie)) { /* button going down? */
+ int leaf;
+ int normalLeafW = leaf_w[SHRINK_NORMAL];
+ int leafX;
+ int leafY;
+ int lastLeaf = -1;
+
+ int x = event_x(ie);
+ int y = event_y(ie);
+
+/*
+ * Determine which leaf was pointed to & where we will display it
+ */
+ leaf = x / normalLeafW;
+ if (leaf < 0 || leaf >= Leaves) {
+ leaf = Leaves - 1;
+ }
+
+ lastLeaf = leaf;
+
+ if (Leaves == 1) {
+ globalOtherLeaf = leaf;
+ } else {
+ globalOtherLeaf = 1 - leaf;
+ }
+
+/*
+ * Build the enlarged page if its not already there
+ */
+ if (haveLargePage[leaf] != pageOnLeaf[leaf]) {
+ buildLeaf(leaf, pageOnLeaf[leaf], SHRINK_LARGE);
+ haveLargePage[leaf] = pageOnLeaf[leaf];
+ }
+
+ leafX = (x - (leaf * normalLeafW));
+ leafX = (leafX * shrinkFactor[SHRINK_NORMAL])
+ / shrinkFactor[SHRINK_LARGE];
+
+ leafY = (y * shrinkFactor[SHRINK_NORMAL])
+ / shrinkFactor[SHRINK_LARGE];
+
+ globalLeafX = leafX;
+ globalLeafY = leafY;
+ globalDisplayLeaf = leaf;
+ globalDisplayState = SHRINK_LARGE;
+ displayLeaves();
+ } else {
+ globalDisplayState = SHRINK_NORMAL;
+ displayLeaves();
+ }
+ return;
+
+ case 'q':
+ case '\003': /* control-C */
+ case '\004': /* control-D */
+ stop_output(0);
+ break;
+
+ case 'n':
+ case 'f':
+ case ' ':
+ case '\n' :
+ case '\r' :
+ /* scroll forward */
+ direction = FOREWARD;
+ rebuild = 1;
+ break;
+
+ case 'p':
+ case 'b':
+ case '\b':
+ case 0177 : /* DEL */
+ /* scroll backward */
+ direction = BACKWARD;
+ rebuild = 1;
+ break;
+
+ case '\f':
+ case 'r' :
+ /* repaint current page */
+ repaint = 1;
+ break;
+
+ case 'g':
+ /* go to absolute page */
+ direction = ABSOLUTE; /* may not be, but tough */
+ rebuild = 1;
+ break;
+
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ if (! globalArg) {
+ globalArg = 1;
+ globalSign = 1;
+ globalNumber = 0;
+ }
+ globalNumber = 10*globalNumber + (event_id(ie) - '0');
+ return;
+
+ case '-':
+ if (! globalArg) {
+ globalArg = 1;
+ globalSign = -1;
+ globalNumber = 0;
+ repaint = 0;
+ return;
+ } else
+ goto bad;
+ default:
+ goto bad;
+ }
+
+ if (rebuild && direction != BOGUSDIR) {
+ int newLeft;
+ int newRight;
+/*
+ * canonicalize the request. globalArg is always > 0, were moving in
+ * some direction.
+ */
+
+ if (globalArg == 0 || globalNumber == 0) {
+ globalNumber = 1;
+ }
+
+ globalNumber = globalNumber * globalSign;
+
+ if (globalNumber < 0) {
+ if (direction == FOREWARD) {
+ direction = BACKWARD;
+ } else if (direction == BACKWARD){
+ direction = FOREWARD;
+ }
+ globalNumber = -globalNumber;
+ }
+
+/*
+ * Turn pages
+ */
+ if (direction == BACKWARD) {
+ newLeft = pageOnLeaf[LEAF_LEFT] - globalNumber;
+ } else if (direction == FOREWARD) {
+ newLeft = pageOnLeaf[LEAF_LEFT] + globalNumber;
+ } else {
+ newLeft = globalNumber - 1; /* pages globalNumbered at 0 */
+ }
+
+ newLeft = MINFUNC(newLeft, dviTotalPages-1);
+ newLeft = MAXFUNC(newLeft, 0);
+
+ if (Leaves == 1) {
+ if (newLeft != pageOnLeaf[LEAF_LEFT]) {
+ buildLeaf(LEAF_LEFT, newLeft, SHRINK_NORMAL);
+ }
+ } else {
+ newRight = newLeft + 1;
+
+ if (pageOnLeaf[LEAF_LEFT] != newLeft) {
+ if (newLeft == pageOnLeaf[LEAF_RIGHT]) {
+ swapLeaf(LEAF_RIGHT, LEAF_LEFT);
+ } else if (newRight == pageOnLeaf[LEAF_LEFT]) {
+ swapLeaf(LEAF_LEFT, LEAF_RIGHT);
+ }
+
+ if (pageOnLeaf[LEAF_LEFT] != newLeft) {
+ buildLeaf(LEAF_LEFT, newLeft, SHRINK_NORMAL);
+ }
+
+ if (pageOnLeaf[LEAF_RIGHT] != newRight) {
+ buildLeaf(LEAF_RIGHT, newRight, SHRINK_NORMAL);
+ }
+ }
+ }
+/*
+ * Only repaint it if we need to
+ */
+ }
+
+ displayLeaves();
+
+ globalArg = 0;
+ globalNumber = 0;
+
+ return;
+
+ bad:
+
+ globalArg = 0; /* throw away numeric globalArgument */
+ return;
+
+}
+
+put_border(x, y, w, h, t)
+int x, y, w, h, t;
+{
+ put_rectangle(x, y, w, t, setMode);
+ put_rectangle(x, y, t, h, setMode);
+ put_rectangle(x, y + h - t, w, t, setMode);
+ put_rectangle(x + w - t, y, t, h, setMode);
+}
+
+put_rectangle(x, y, w, h, pix)
+int x, y, w, h;
+int pix;
+{
+ if (buildToPixmap) {
+ pr_rop(pasteUpPixmap[currentShrink][currentLeaf],
+ x,y,
+ w,h,
+ pix,
+ pasteUpPixmap[currentShrink][currentLeaf],
+ 0, 0);
+ } else {
+ pw_write(ptube,
+ x + currentLeaf * leaf_w[currentShrink],y,
+ w,h,
+ pix,
+ ptube, 0, 0);
+ }
+}
+
+
diff --git a/dviware/umddvi/previewers/texx.1 b/dviware/umddvi/previewers/texx.1
new file mode 100644
index 0000000000..a23ef143a1
--- /dev/null
+++ b/dviware/umddvi/previewers/texx.1
@@ -0,0 +1,36 @@
+.TH TEXX 1
+.SH NAME
+texx \- view DVI files on your X-11 window
+.SH SYNOPSIS
+.B texx
+.B [many options]
+.B filename
+.SH DESCRIPTION
+.I Texx
+takes a DVI file produced by TeX and converts it to a format suitable
+an X-11 window.
+.I filename
+should be the name of a
+.B .dvi
+file.
+The environment and commands for
+.I texx
+are too complicated to explain in man page.
+Users should consult the Dvi Output Guide.
+.SH DIAGNOSTICS
+Most of these should be self explanatory.
+.SH AUTHOR
+Dirk Grunwald, Univ. of Illinois
+.br
+.I Texx
+uses a library of routines written by
+Chris Torek, University of Maryland
+.SH FILES
+/usr/local/texx
+.br
+.SH "SEE ALSO"
+iptex(1), dviselect(1), tex(1)
+.SH BUGS
+.I Still
+needs to handle more ``\especial''s.
+
diff --git a/dviware/umddvi/previewers/texx.c b/dviware/umddvi/previewers/texx.c
new file mode 100644
index 0000000000..feaf524b29
--- /dev/null
+++ b/dviware/umddvi/previewers/texx.c
@@ -0,0 +1,1382 @@
+/*
+ * This program is Copyright (C) 1987 by the Board of Trustees of the
+ * University of Illinois, and by the author Dirk Grunwald.
+ *
+ * This program may be freely copied, as long as this copyright
+ * message remaines affixed. It may not be sold, altough it may
+ * be distributed with other software which is sold. If the
+ * software is distributed, the source code must be made available.
+ *
+ * No warrenty, expressed or implied, is given with this software.
+ * It is presented in the hope that it will prove useful.
+ */
+#include <sys/types.h>
+#include <X/Xlib.h>
+#include <X/Xutil.h>
+#include <X/cursorfont.h>
+#include <stdio.h>
+#include <ctype.h>
+
+#include "dvistuff.h"
+/*
+ * These constants may need to be changed on your implementation
+ */
+
+#define BitsPerByte 8
+#define BitsPerShort 16
+#define BytesPerShort (sizeof(short))
+
+#define BitsPerByteMask 0x7
+#define BitsPerByteShift 3
+
+#define BytesPerShot 2
+/*
+ * Note that ROUNDUP evaluates Y twice.
+ */
+#define ROUNDUP(x,y) (((x)+(y)-1) / (y))
+
+
+
+int debug = 0;
+static int obscured = 1;
+
+
+/*
+ * X-11 related variables
+ */
+
+Display *DISP;
+static Window win;
+static int backpix;
+static GC highpix, forepix;
+static GC specialGC;
+static int defaultScreen;
+
+static Cursor workingCursor;
+static Cursor readyCursor;
+
+/*
+ * TeX-Dvi related variables
+ */
+
+static int rawDviHeight;
+static int rawDviWidth; /* part of X interface, not dvistuff */
+static int maxHeight;
+static int maxWidth;
+
+static int screenWidth, screenHeight;
+
+#define MAX_LEAVES 2
+#define LEAF_LEFT 0
+#define LEAF_RIGHT 1
+
+static int Leaves;
+static int currentLeaf = 0;
+static int pageOnLeaf[MAX_LEAVES] = {-1,-1};
+static int haveLargePage[MAX_LEAVES] = {-1, -1};
+
+#define SHRINK_NORMAL 0
+#define SHRINK_LARGE 1
+#define MAX_SHRINKS 2
+
+static int page_w[MAX_SHRINKS], page_h[MAX_SHRINKS];
+static int leaf_w[MAX_SHRINKS];
+
+static int shrinkFactor[MAX_SHRINKS];
+static int currentShrink;
+static struct glyph **shrunkenGlyphs[MAX_SHRINKS][MAX_FONTFAMILY];
+static XImage **shrunkenImages[MAX_SHRINKS][MAX_FONTFAMILY];
+
+static int reverse = 0;
+
+static double specialConv;
+
+char *malloc(), *calloc(), *index();
+
+#define MAX(a,b) ((a) < (b)) ? (b) : (a)
+#define MIN(a,b) ((a) < (b)) ? (a) : (b)
+
+/*
+ * I don't know why this is needed, but our sun seems to thing
+ * and is or & vice versa
+ */
+
+#ifdef mc68000
+#define GXAND GXand
+#define GXOR GXor
+#else
+#define GXAND GXor
+#define GXOR GXand
+#endif
+
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+
+ int xargc=argc;
+ char **xargv=argv;
+
+ char *file;
+ char *display = NULL;
+ char *option;
+
+ int bwidth = 2;
+ char *fore_color;
+ char *back_color;
+ char *high_color;
+ char *brdr_color;
+ char *mous_color;
+ char *geometry = NULL, def[32];
+
+ int bdrpix, mouspix;
+ XColor cdef;
+ XSizeHints hints;
+ XSetWindowAttributes xswattrs;
+ unsigned long xswattrs_mask;
+
+ double atof();
+
+ char *getenv();
+
+ ProgName = *argv;
+ argv++;
+ argc--;
+
+ if ((DISP = XOpenDisplay(display)) == NULL) {
+
+ fprintf(stderr, "[%s] Can't open display '%s'\n",
+ ProgName, XDisplayName(display));
+ exit(1);
+ }
+
+ if ((option = XGetDefault(DISP, ProgName, "ReverseVideo")) &&
+ strcmp(option, "on") == 0)
+ reverse = 1;
+ if (option = XGetDefault(DISP, ProgName, "BorderWidth"))
+ bwidth = atoi(option);
+ fore_color = XGetDefault(DISP, ProgName, "ForeGround");
+ back_color = XGetDefault(DISP, ProgName, "BackGround");
+ high_color = XGetDefault(DISP, ProgName, "Highlight");
+ brdr_color = XGetDefault(DISP, ProgName, "Border");
+ mous_color = XGetDefault(DISP, ProgName, "Mouse");
+
+ option = XGetDefault(DISP, ProgName, "NormalShrink");
+ shrinkFactor[SHRINK_NORMAL] = (option == 0) ? 0 : atoi(option);
+
+ option = XGetDefault(DISP, ProgName, "LargeShrink");
+ shrinkFactor[SHRINK_LARGE] = (option == 0) ? 0 : atoi(option);
+
+ option = XGetDefault(DISP, ProgName, "Blackness");
+ dviBlackness = (option == 0) ? DEFAULT_BLACKNESS : atoi(option);
+
+ option = XGetDefault(DISP, ProgName, "Leaves");
+ Leaves = (option == 0) ? 0 : atoi(option);
+
+ option = XGetDefault(DISP, ProgName, "Dpi");
+ dviDPI = (option == 0) ? DEFAULT_DPI : atoi(option);
+
+ option = XGetDefault(DISP, ProgName, "TopMargin");
+ dviVVMargin = (option == 0) ? DEFAULT_VVMARGIN : atof(option) * dviDPI;
+
+ option = XGetDefault(DISP, ProgName, "SideMargin");
+ dviHHMargin = (option == 0) ? DEFAULT_HHMARGIN : atof(option) * dviDPI;
+
+ file = NULL;
+
+ while (argc) {
+ if (strcmp(*argv, "-p") == 0 && argc > 1) {
+ argv++;
+ argc--;
+ dviDPI = atoi(*argv);
+ if (dviDPI <= 0) goto usage;
+ } else if (strcmp(*argv, "-rv") == 0) {
+ reverse = !reverse;
+ } else if (strcmp(*argv, "-bw") == 0 && argc > 1) {
+ argv++;
+ argc--;
+ bwidth = atoi(*argv);
+ } else if (strcmp(*argv, "-fg") == 0 && argc > 1) {
+ argv++;
+ argc--;
+ fore_color = *argv;
+ } else if (strcmp(*argv, "-bg") == 0 && argc > 1) {
+ argv++;
+ argc--;
+ back_color = *argv;
+ } else if (strcmp(*argv, "-hl") == 0 && argc > 1) {
+ argv++;
+ argc--;
+ high_color = *argv;
+ } else if (strcmp(*argv, "-bd") == 0 && argc > 1) {
+ argv++;
+ argc--;
+ brdr_color = *argv;
+ } else if (strcmp(*argv, "-ms") == 0 && argc > 1) {
+ argv++;
+ argc--;
+ mous_color = *argv;
+ } else if (strcmp(*argv,"-l") == 0 && argc > 1) {
+ argv++;
+ argc--;
+ Leaves = atoi(*argv);
+ if( Leaves < 1 || Leaves > MAX_LEAVES) {
+ fprintf(stderr,"[%s] Bad number of leaves(%d), using %d\n",
+ ProgName, Leaves, MAX_LEAVES);
+ Leaves = MAX_LEAVES;
+ }
+ } else if (strcmp(*argv,"-ns") == 0 && argc > 1) {
+ argv++;
+ argc--;
+ shrinkFactor[SHRINK_NORMAL] = atoi(*argv);
+ } else if (strcmp(*argv,"-ls") == 0 && argc > 1) {
+ argv++;
+ argc--;
+ shrinkFactor[SHRINK_LARGE] = atoi(*argv);
+ } else if (strcmp(*argv,"-bl") == 0 && argc > 1) {
+ argv++;
+ argc--;
+ dviBlackness = atoi(*argv);
+ } else if (strcmp(*argv,"-dpi") == 0 && argc > 1) {
+ argv++;
+ argc--;
+ dviDPI = atoi(*argv);
+ } else if (strcmp(*argv,"-tm") == 0 && argc > 1) {
+ argv++;
+ argc--;
+ dviVVMargin = dviDPI * atof(*argv);
+ } else if (strcmp(*argv,"-sm") == 0 && argc > 1) {
+ argv++;
+ argc--;
+ dviHHMargin = dviDPI * atof(*argv);
+ } else if (**argv == '=') {
+ geometry = *argv;
+ } else if (**argv != '-') {
+ if (index(*argv, ':') != NULL)
+ display = *argv;
+ else
+ file = *argv;
+ } else {
+ usage:
+ fprintf(stderr, "Usage: %s [-s <shrink>] [-l <leaves>] [-rv] [-fg <color>] [-bg <color>] [-hl <color>] [-bd <color>] [-ms <color>] [=<geometry>] [host:display] dviFile\n",
+ ProgName);
+ exit(1);
+ }
+ argv++;
+ argc--;
+ }
+ if (file == NULL)
+ goto usage;
+ if ((dviFile = fopen(file, "r")) == NULL) {
+ int n = strlen(file);
+ char *dvi_name;
+
+ if (strcmp(file + n - sizeof(".dvi") + 1, ".dvi") == 0) {
+ perror(file);
+ exit(1);
+ }
+ dvi_name = malloc((unsigned) n + sizeof(".dvi"));
+ sprintf(dvi_name, "%s.dvi", file);
+ if ((dviFile = fopen(dvi_name, "r")) == NULL) {
+ perror(dvi_name);
+ exit(1);
+ }
+ }
+
+ dviInit();
+
+ specialConv = (float) dviDPI / 1000.0;
+
+/*
+ * If no shrink factor was chosen, pick one which will work out nicely
+ * on their display
+ */
+
+ defaultScreen = XDefaultScreen(DISP);
+
+ maxHeight = XDisplayHeight(DISP, defaultScreen) - 2 * bwidth;
+ maxWidth = XDisplayWidth(DISP, defaultScreen) - 2 * bwidth;
+
+ rawDviHeight = dviTallestPage + 2 * dviVVMargin;
+ rawDviWidth = dviWidestPage + 2 * dviHHMargin;
+
+ if (Leaves == 0) {
+ if (dviTotalPages == 1) {
+ Leaves = 1;
+ } else {
+ Leaves = 2;
+ }
+ }
+
+ if (shrinkFactor[SHRINK_NORMAL] == 0) {
+ int sH;
+ int sW;
+ int sH2;
+ int sW2;
+ int shrink2;
+
+ sH = (rawDviHeight + maxHeight - 1) / maxHeight;
+ sW = (Leaves * rawDviWidth + maxWidth - 1) / maxWidth;
+
+ shrinkFactor[SHRINK_NORMAL] = MAX(sW, sH);
+ shrinkFactor[SHRINK_NORMAL] = MAX(shrinkFactor[SHRINK_NORMAL], 1);
+
+/*
+ * Check to see if we can get another shrink size bigger display
+ * if we cut the margins.
+ */
+
+ sH2 = (dviTallestPage + (dviHHMargin/32) + maxHeight - 1)
+ / maxHeight;
+ sW2 = ( Leaves * (dviWidestPage + (dviVVMargin/32))
+ + maxHeight - 1) / maxHeight;
+
+ shrink2 = MAX(sH2, sW2);
+ shrink2 = MAX(shrink2, 1);
+
+ if (shrink2 < shrinkFactor[SHRINK_NORMAL]) {
+ dviVVMargin /= 32;
+ dviHHMargin /= 32;
+ rawDviHeight = dviTallestPage + 2 * dviVVMargin;
+ rawDviWidth = dviWidestPage + 2 * dviHHMargin;
+ shrinkFactor[SHRINK_NORMAL] = shrink2;
+ }
+ }
+
+ page_h[SHRINK_NORMAL]=(rawDviHeight + shrinkFactor[SHRINK_NORMAL] - 1)
+ / shrinkFactor[SHRINK_NORMAL];
+ leaf_w[SHRINK_NORMAL]=(rawDviWidth + shrinkFactor[SHRINK_NORMAL] - 1)
+ / shrinkFactor[SHRINK_NORMAL];
+
+/*
+ * Based on the shrink factor, choose a shrink factor for the enlarged
+ * display
+ */
+
+ if (shrinkFactor[SHRINK_LARGE] == 0) {
+ shrinkFactor[SHRINK_LARGE] = shrinkFactor[SHRINK_NORMAL] / 2;
+ }
+
+ shrinkFactor[SHRINK_LARGE] = MIN(shrinkFactor[SHRINK_LARGE],
+ shrinkFactor[SHRINK_NORMAL]-1);
+ shrinkFactor[SHRINK_LARGE] = MAX(shrinkFactor[SHRINK_LARGE], 1);
+
+ page_h[SHRINK_LARGE]=(rawDviHeight + shrinkFactor[SHRINK_LARGE] - 1)
+ / shrinkFactor[SHRINK_LARGE];
+ leaf_w[SHRINK_LARGE]=(rawDviWidth + shrinkFactor[SHRINK_LARGE] - 1)
+ / shrinkFactor[SHRINK_LARGE];
+
+/*
+ * Compute the page size given the number of leaves. We may have
+ * to scale back if everything can't fit.
+ */
+
+ if (leaf_w[SHRINK_NORMAL] * Leaves <= maxWidth) {
+ page_w[SHRINK_NORMAL] = leaf_w[SHRINK_NORMAL] * Leaves;
+ } else {
+ page_w[SHRINK_NORMAL] = leaf_w[SHRINK_NORMAL];
+ Leaves = 1;
+ }
+
+ screenWidth = (page_w[SHRINK_NORMAL] > maxWidth)
+ ? maxWidth : page_w[SHRINK_NORMAL];
+ screenHeight = (page_h[SHRINK_NORMAL] > maxHeight)
+ ? maxHeight : page_h[SHRINK_NORMAL];
+
+ highpix = XCreateGC(DISP, RootWindow(DISP, defaultScreen), 0, NULL);
+ forepix = XCreateGC(DISP, RootWindow(DISP, defaultScreen), 0, NULL);
+
+ XCopyGC(DISP, DefaultGC(DISP, 0), (1L<<(GCLastBit+1))-1, highpix);
+ XCopyGC(DISP, highpix, (1L<<(GCLastBit+1))-1, forepix);
+
+ if (reverse) {
+
+ XSetForeground(DISP, forepix, WhitePixel(DISP, defaultScreen));
+ XSetForeground(DISP, highpix, WhitePixel(DISP, defaultScreen));
+ backpix = BlackPixel(DISP, defaultScreen);
+ bdrpix = WhitePixel(DISP, defaultScreen);
+ mouspix = WhitePixel(DISP, defaultScreen);
+ XSetFunction(DISP, forepix, GXAND); /* or */
+ XSetFunction(DISP, highpix, GXAND);
+
+ } else {
+
+ XSetForeground(DISP, forepix, BlackPixel(DISP, defaultScreen));
+ XSetForeground(DISP, highpix, BlackPixel(DISP, defaultScreen));
+ backpix = WhitePixel(DISP, defaultScreen);
+ bdrpix = BlackPixel(DISP, defaultScreen);
+ mouspix = BlackPixel(DISP, defaultScreen);
+ XSetFunction(DISP, forepix, GXOR); /* and */
+ XSetFunction(DISP, highpix, GXOR);
+ }
+
+ if (DisplayCells(DISP, 0) > 2) {
+ Colormap dcm = DefaultColormap(DISP, defaultScreen);
+ if (fore_color
+ && XParseColor(DISP, dcm, fore_color, &cdef)
+ && XAllocColor(DISP, dcm, &cdef)) {
+ XSetForeground(DISP, forepix, cdef.pixel);
+ }
+
+ if (back_color
+ && XParseColor(DISP, dcm, back_color, &cdef)
+ && XAllocColor(DISP, dcm, &cdef)) {
+ backpix = cdef.pixel;
+ }
+
+ if (high_color
+ && XParseColor(DISP, dcm, high_color, &cdef)
+ && XAllocColor(DISP, dcm, &cdef)) {
+ XSetForeground(DISP, highpix, cdef.pixel);
+ }
+
+ if (brdr_color
+ && XParseColor(DISP, dcm, brdr_color, &cdef)
+ && XAllocColor(DISP, dcm, &cdef))
+ {
+ /* null statement? */
+ }
+
+ if (mous_color
+ && XParseColor(DISP, dcm, mous_color, &cdef)
+ && XAllocColor(DISP, dcm, &cdef)) {
+ mouspix = cdef.pixel;
+ }
+ }
+
+ XSetBackground(DISP, forepix, backpix);
+ XSetBackground(DISP, highpix, backpix);
+
+ sprintf(def, "=%dx%d+0+0", screenWidth, screenHeight);
+
+ hints.width = page_w[SHRINK_NORMAL];
+ hints.height = page_h[SHRINK_NORMAL];
+ hints.x = 0; hints.y = 0;
+ hints.flags = (PSize | PPosition);
+
+ xswattrs.border_pixel = bdrpix;
+ xswattrs.background_pixel = backpix;
+ xswattrs_mask = (CWBackPixel|CWBorderPixel);
+
+ win = XCreateWindow(DISP, RootWindow(DISP, defaultScreen),
+ 0, 0,
+ screenWidth, screenHeight,
+ bdrpix,
+ 0, /* depth from parent */
+ InputOutput,
+ CopyFromParent,
+ xswattrs_mask,
+ &xswattrs);
+
+ XSetStandardProperties(DISP, win,
+ ProgName, "DVI Previewer",
+ None,
+ argv, argc, &hints);
+
+ XMapRaised(DISP, win);
+ XSelectInput(DISP, win,
+ KeyPressMask|ButtonPressMask | ButtonReleaseMask
+ |ExposureMask | VisibilityChangeMask);
+
+ workingCursor = XCreateFontCursor(DISP, XC_watch);
+ readyCursor = XCreateFontCursor(DISP, XC_spraycan);
+
+ XDefineCursor(DISP, win, workingCursor);
+ XFlush(DISP);
+
+ specialGC = XCreateGC(DISP, RootWindow(DISP, defaultScreen), 0, NULL);
+ XCopyGC(DISP, forepix, (1L<<(GCLastBit+1))-1, specialGC);
+
+ mainLoop();
+ stop_output(0);
+}
+
+/*
+ * Pixmap manipulation routines
+ */
+
+static Pixmap pasteUpPixmap[MAX_SHRINKS][MAX_LEAVES];
+static GC pasteFillGC;
+static GC pasteCopyGC;
+
+static int largePixmapsAllocated = 0;
+
+/*
+ * Ideally, we'd like to paint up a local pixmap & then transmit the
+ * entire pixmap. However, it looks like pixmaps require interaction
+ * with the server.
+ *
+ * So, if the entire page fits on the screen, we'll paint the screen
+ * and when we're done, we'll copy the screen to the pixmap. This
+ * gives the illusion of progress, but allows us to do fast re-paints.
+ *
+ * If we're *not* on the display, we'll just draw to the pixmap and
+ * update it at the end
+ */
+
+static int buildToPixmap = 1;
+
+static void
+clearPixmap(leaf, shrinkSize)
+int leaf;
+int shrinkSize;
+{
+ if (leaf< 0 || leaf >= Leaves) {
+ fprintf(stderr,"[%s] Reference to bogus leaf in clearPixmap: %d\n",
+ ProgName, leaf);
+ exit(1);
+ }
+
+ if (shrinkSize < 0 || shrinkSize >= MAX_SHRINKS ) {
+ fprintf(stderr,"[%s] reference to bogus shrink %d\n",
+ ProgName, shrinkSize);
+ exit(1);
+ }
+
+ XFillRectangle(DISP, pasteUpPixmap[shrinkSize][leaf], pasteFillGC, 0, 0,
+ leaf_w[shrinkSize], page_h[shrinkSize]);
+}
+
+static void
+clearWindow(leaf)
+int leaf;
+{
+ XFillRectangle(DISP, win, pasteFillGC,
+ leaf * leaf_w[SHRINK_NORMAL], 0,
+ leaf_w[SHRINK_NORMAL], page_h[SHRINK_NORMAL]);
+}
+
+allocatePixmaps()
+{
+ int i;
+
+ for (i = 0; i < Leaves; i++ ) {
+ pasteUpPixmap[SHRINK_NORMAL][i] =
+ XCreatePixmap(DISP, win, leaf_w[SHRINK_NORMAL],
+ page_h[SHRINK_NORMAL], 1);
+
+ if (pasteUpPixmap[SHRINK_NORMAL][i] == 0) {
+ fprintf(stderr,"[%s] erp! out of PIXMAP memory!\n",
+ ProgName);
+ exit(1);
+ }
+ }
+
+ largePixmapsAllocated = 0;
+
+ if (pasteFillGC == 0) {
+ pasteFillGC = XCreateGC(DISP, RootWindow(DISP, defaultScreen),0,NULL);
+ pasteCopyGC = XCreateGC(DISP, RootWindow(DISP, defaultScreen),0,NULL);
+ XCopyGC(DISP, forepix, (1L<<(GCLastBit+1))-1, pasteFillGC);
+ XCopyGC(DISP, forepix, (1L<<(GCLastBit+1))-1, pasteCopyGC);
+ if (reverse) {
+ XSetForeground(DISP, pasteFillGC, BlackPixel(DISP, defaultScreen));
+ } else {
+ XSetForeground(DISP, pasteFillGC, WhitePixel(DISP, defaultScreen));
+ }
+ XSetFunction(DISP, pasteFillGC, GXcopy);
+ XSetFunction(DISP, pasteCopyGC, GXcopy);
+ }
+
+/*
+ * Clear the pixmap
+ */
+ for (i = 0; i < Leaves; i++) {
+ clearPixmap(i, SHRINK_NORMAL);
+ }
+}
+
+allocateLargePixmaps()
+{
+ int i;
+ for (i = 0; i < Leaves; i++) {
+ pasteUpPixmap[SHRINK_LARGE][i] =
+ XCreatePixmap(DISP, win, leaf_w[SHRINK_LARGE],
+ page_h[SHRINK_LARGE], 1);
+
+ clearPixmap(i, SHRINK_LARGE);
+ }
+
+ largePixmapsAllocated = 1;
+}
+
+/*
+ * display the normal sized leaf
+ */
+static void
+displayLeaves()
+{
+ int leaf;
+ XClearWindow(DISP,win);
+ for (leaf = 0; leaf < Leaves; leaf++) {
+ XCopyArea(DISP, pasteUpPixmap[SHRINK_NORMAL][leaf], win, forepix,
+ 0, 0,
+ leaf_w[SHRINK_NORMAL], page_h[SHRINK_NORMAL],
+ leaf_w[SHRINK_NORMAL] * leaf, 0);
+ }
+}
+
+static void displayLeaf(leaf)
+int leaf;
+{
+ clearWindow(leaf);
+ XCopyArea(DISP, pasteUpPixmap[SHRINK_NORMAL][leaf], win, forepix,
+ 0, 0,
+ leaf_w[SHRINK_NORMAL], page_h[SHRINK_NORMAL],
+ leaf_w[SHRINK_NORMAL] * leaf, 0);
+}
+
+static void
+swapLeaf(from, to)
+int from;
+int to;
+{
+ Pixmap tempPix;
+ int tempNum;
+
+ if (to < 0 || to >= Leaves) {
+ fprintf(stderr,"[%s] bogus to leaf %d in swapLeaf\n",
+ ProgName, to);
+ exit(1);
+ }
+ if (from < 0 || from >= Leaves) {
+ fprintf(stderr,"[%s] bogus from leaf %d in swapLeaf\n",
+ ProgName, from);
+ exit(1);
+ }
+
+ tempPix = pasteUpPixmap[SHRINK_NORMAL][to];
+ pasteUpPixmap[SHRINK_NORMAL][to] = pasteUpPixmap[SHRINK_NORMAL][from];
+ pasteUpPixmap[SHRINK_NORMAL][from] = tempPix;
+
+ tempPix = pasteUpPixmap[SHRINK_LARGE][to];
+ pasteUpPixmap[SHRINK_LARGE][to] = pasteUpPixmap[SHRINK_LARGE][from];
+ pasteUpPixmap[SHRINK_LARGE][from] = tempPix;
+
+ tempNum = pageOnLeaf[to];
+ pageOnLeaf[to] = pageOnLeaf[from];
+ pageOnLeaf[from] = tempNum;
+
+ tempNum = haveLargePage[to];
+ haveLargePage[to] = haveLargePage[from];
+ haveLargePage[from] = tempNum;
+}
+
+static void
+buildLeaf(leaf, page, shrinkSize)
+int leaf;
+int page;
+int shrinkSize;
+{
+ XDefineCursor(DISP, win, workingCursor);
+
+ if (leaf < 0 || leaf >= Leaves) {
+ fprintf(stderr,"[%s] bogus leaf %d in buildLeaf\n",
+ ProgName, leaf);
+ exit(1);
+ }
+
+ if (shrinkSize < 0 || shrinkSize >= MAX_SHRINKS ) {
+ fprintf(stderr,"[%s] Bogus shrink size %d in buildLeaf\n",
+ ProgName, shrinkSize);
+ exit(1);
+ }
+
+ if (shrinkSize == SHRINK_LARGE && !largePixmapsAllocated) {
+ allocateLargePixmaps();
+ }
+
+/*
+ * If this is a normal size page, kill the information
+ * for the large version.
+ */
+ if (shrinkSize == SHRINK_NORMAL) {
+ haveLargePage[leaf] = -1;
+ }
+
+/*
+ * Determine if this is a valid page. If it's not, we'll just clear
+ * the particular leaf.
+ */
+
+ if (page < 0 || page >= dviTotalPages) {
+ clearPixmap(leaf, shrinkSize);
+
+ if (shrinkSize == SHRINK_NORMAL) {
+ clearWindow(leaf);
+ }
+ } else {
+
+ if (obscured || shrinkSize == SHRINK_LARGE) {
+ buildToPixmap = 1;
+ } else {
+ buildToPixmap = 0;
+ }
+
+ if (buildToPixmap) {
+ clearPixmap(leaf, shrinkSize);
+ } else {
+ clearPixmap(leaf, shrinkSize);
+ if (shrinkSize == SHRINK_NORMAL) {
+ clearWindow(leaf);
+ }
+ }
+
+/*
+ * Note that dviPreparePage may change dviCurrentPage
+ */
+
+ currentLeaf = leaf;
+ currentShrink = shrinkSize;
+
+ dviPreparePage(page);
+
+ page = dviCurrentPage;
+
+/*
+ * Save the constructed page if we were painting it to the screen
+ */
+ put_border(0, 0, leaf_w[currentShrink], page_h[currentShrink], 1);
+
+ if (! buildToPixmap && shrinkSize == SHRINK_NORMAL) {
+ XCopyArea(DISP, win, pasteUpPixmap[SHRINK_NORMAL][leaf], forepix,
+ leaf * leaf_w[currentShrink], 0,
+ screenWidth, screenHeight, 0,0);
+ } else if (shrinkSize == SHRINK_NORMAL) {
+ displayLeaf(leaf);
+ }
+ }
+
+ pageOnLeaf[leaf] = dviCurrentPage;
+ XDefineCursor(DISP, win, readyCursor);
+
+ XFlush(DISP);
+}
+
+/*
+ * interfaces to dvistuff
+ */
+
+/*
+ * Whenever a new font is registers, we create a shrunken Glyph
+ * table for it. However, we don't shrink the glyphs -- that's
+ * done on the fly by the putChar routine.
+ */
+
+DviFont *
+applicationNewFont(f, key)
+struct font *f;
+int key;
+{
+ int shrink;
+
+ if (key < 0 || key > MAX_FONTFAMILY) {
+ fprintf(stderr,"[%s] bogus key in Newfont = %d\n",
+ ProgName, key);
+ exit(1);
+ }
+
+ for (shrink = SHRINK_NORMAL; shrink <= SHRINK_LARGE; shrink++) {
+
+ if (shrunkenGlyphs[shrink][key] == 0) {
+ int lth = sizeof(struct glyph *) * MAX_GLYPH;
+ struct glyph **g;
+
+ g = (struct glyph **) malloc( lth );
+ bzero(g, lth);
+ shrunkenGlyphs[shrink][key] = g;
+ }
+
+ if (shrunkenImages[shrink][key] == 0) {
+ int lth = sizeof(XImage *) * MAX_GLYPH;
+ XImage **image;
+
+ image = (XImage **) malloc(lth);
+ bzero(image, lth);
+ shrunkenImages[shrink][key] = image;
+ }
+ }
+
+ return(f);
+}
+
+/*
+ * When we reset a font, we only need to free the storage for the
+ * shrunken glyphs. We keep the glyph table available because we're
+ * very likely to fill it in again.
+ */
+
+void
+applicationResetFont(fi, key)
+struct fontinfo *fi;
+int key;
+{
+ int i;
+ struct glyph **theseGlyphs;
+ XImage **theseImages;
+ int shrink;
+
+
+ for (shrink = SHRINK_NORMAL; shrink <= SHRINK_LARGE; shrink++) {
+ theseGlyphs = shrunkenGlyphs[shrink][key];
+ if (theseGlyphs != 0) {
+ for (i = 0; i < MAX_GLYPH; i++) {
+ struct glyph *g;
+
+ g = theseGlyphs[i];
+
+ if (g != 0) {
+ if ( g -> g_raster != 0) {
+ free(g -> g_raster);
+ }
+ free(g);
+ theseGlyphs[i] = 0;
+ }
+ }
+ }
+
+ theseImages = shrunkenImages[shrink][key];
+
+ if (theseImages != 0) {
+ for (i = 0; i < MAX_GLYPH; i++) {
+ if (theseImages[i] != 0) {
+ XDestroyImage(theseImages[i]);
+ }
+ theseImages[i] = 0;
+ }
+ }
+ }
+}
+
+
+void
+applicationPutChar(hh, vv, charCode)
+int hh;
+int vv;
+int charCode;
+{
+ register struct glyph *g;
+ int x,y;
+ XImage *image;
+ int key;
+
+ key = dviCurrentFont -> family;
+
+ g = shrunkenGlyphs[currentShrink][key][charCode];
+
+ if (g == 0) {
+ g = dviShrinkGlyph(dviCurrentFont -> f -> f_gly[charCode],
+ shrinkFactor[currentShrink],
+ shrinkFactor[currentShrink]);
+ shrunkenGlyphs[currentShrink][key][charCode] = g;
+ }
+
+ if (g == 0 || !HASRASTER(g)) return;
+
+ hh /= shrinkFactor[currentShrink];
+ vv /= shrinkFactor[currentShrink];
+
+ x = hh - g -> g_xorigin;
+ y = vv - g -> g_yorigin;
+
+ image = shrunkenImages[currentShrink][key][charCode];
+
+ if (image == 0 ) {
+ image = XCreateImage(DISP, DefaultVisual(DISP, defaultScreen),
+ 1, XYBitmap,
+ 0, g->g_raster,
+ g->g_width, g->g_height,
+ 16, 0);
+
+ shrunkenImages[currentShrink][key][charCode] = image;
+ }
+
+ if (buildToPixmap) {
+ XPutImage(DISP, pasteUpPixmap[currentShrink][currentLeaf],
+ forepix, image,
+ 0, 0,
+ x, y,
+ g->g_width, g->g_height);
+ } else {
+ XPutImage(DISP, win,
+ forepix, image,
+ 0, 0,
+ x + currentLeaf * leaf_w[currentShrink], y,
+ g->g_width, g->g_height);
+ }
+}
+
+void
+applicationSetRule(hh, vv, h, w)
+int hh, vv;
+int h, w;
+{
+/* (w,h) specifies lower left corner of rule box */
+ int nh, nw;
+
+ hh /= shrinkFactor[currentShrink];
+ vv /= shrinkFactor[currentShrink];
+
+ nh = h / shrinkFactor[currentShrink];
+ nw = w / shrinkFactor[currentShrink];
+
+ if (nh == 0 && h != 0) {
+ nh = 1;
+ }
+ if (nw == 0 && w != 0) {
+ nw = 1 ;
+ }
+
+ put_rectangle(hh, vv - nh, nw, nh, forepix);
+}
+
+/*
+ * This code attempts to support the same set of specials
+ * as imagen1
+ */
+static char *
+skipWhite(c)
+char *c;
+{
+ while (c != 0 && *c != 0 && isspace(*c)) c++;
+ return(c);
+}
+
+static char *
+skipNonWhite(c)
+char *c;
+{
+ while (c != 0 && *c != 0 && ! isspace(*c)) c++;
+ return(c);
+}
+
+#define MAX_POINTS 128
+static int pointListCount = 0;
+static XPoint pointList[MAX_POINTS];
+
+void
+applicationDoSpecial(command)
+char *command;
+{
+ char com[20];
+ int x,y;
+ char *c, *oc;
+
+ c = skipWhite(command);
+ if (*c == 0) return;
+
+ oc = c;
+ c = skipNonWhite(c);
+ x = *c;
+ *c = '\000';
+ strncpy(com, oc, 20);
+ *c = x;
+ c++;
+
+ if (strcmp(com, "pa") == 0) {
+ sscanf(c, " %d %d ", &x, &y);
+ pointList[pointListCount].x =
+ (specialConv * x + dviHH) / shrinkFactor[currentShrink];
+ pointList[pointListCount].y =
+ (specialConv * y + dviVV) / shrinkFactor[currentShrink];
+
+ if (! buildToPixmap) {
+ pointList[pointListCount].x += currentLeaf * leaf_w[currentShrink];
+ }
+
+ pointListCount++;
+
+/*
+ * Make all lines styles come out as a simple line.
+ * Crude, but effective.
+ */
+
+ } else if (strcmp(com, "fp") == 0
+ || strcmp(com,"da") == 0
+ || strcmp(com,"dt") == 0) {
+ if (pointListCount > 0) {
+
+ if (buildToPixmap) {
+ XDrawLines(DISP, pasteUpPixmap[currentShrink][currentLeaf],
+ specialGC, pointList, pointListCount,
+ CoordModeOrigin);
+ } else {
+ XDrawLines(DISP, win,
+ specialGC, pointList, pointListCount,
+ CoordModeOrigin);
+ }
+ }
+ pointListCount = 0;
+
+ } else if (strcmp(com, "pn") == 0) {
+ int penSize;
+ sscanf(c," %d ", &penSize);
+ penSize /= (shrinkFactor[currentShrink] * 2); /* looks good */
+ penSize = MAX(penSize,1);
+ penSize = MIN(penSize,99);
+ XSetLineAttributes(DISP, specialGC, penSize,
+ LineSolid, CapButt, JoinMiter);
+ } else {
+
+/*
+ * For now, lets just flush the special
+ */
+ fprintf(stderr, "[%s] special \"%s\" not implemented\n",
+ ProgName, command);
+ }
+}
+
+int
+mainLoop()
+{
+ int ch, arg, sign, number;
+ XEvent event;
+ XWindowAttributes query;
+
+ char trbuf[100];
+ char *string;
+ int nbytes=0;
+
+ int repaint;
+ int rebuild;
+
+#define BOGUSDIR -1
+#define FOREWARD 0
+#define BACKWARD 1
+#define ABSOLUTE 2
+
+ int direction;
+
+/*
+ *
+ * We need to initialized 'obscured'.
+ * Ideally, we would like to know if we are covered at all, but
+ * the best I can come up with is a way to determine if we're
+ * mapped. This works well for wm, uwm & no window manager at all.
+ */
+
+ XClearWindow(DISP,win);
+ XSync(DISP, 0);
+
+ XGetWindowAttributes(DISP, win, &query);
+ obscured = ! (query.map_state == IsViewable);
+
+ allocatePixmaps();
+ dviCurrentPage = 0;
+ buildLeaf(LEAF_LEFT, 0, SHRINK_NORMAL);
+
+ if (Leaves == 2) {
+ XGetWindowAttributes(DISP, win, &query); /* status changed? */
+ obscured = ! (query.map_state == IsViewable);
+ buildLeaf(LEAF_RIGHT, 1, SHRINK_NORMAL);
+ }
+
+ arg = 0;
+ number = 0;
+
+ for (;;) {
+
+ repaint = 1;
+ rebuild = 0;
+ direction = BOGUSDIR;
+
+ XDefineCursor(DISP, win, readyCursor);
+
+ bzero(&event, sizeof(event));
+ XNextEvent (DISP, &event);
+
+ string = "";
+
+ switch (event.type) {
+
+/*
+ * If were painting to the display, and were not completely
+ * visible, wed better really paint to the pixmap, otherwise,
+ * all the stuff painted in an obscured region wont be in the pixmap.
+ */
+
+ case VisibilityNotify:
+ obscured = (event.xvisibility.state != VisibilityUnobscured);
+ continue;
+
+ case Expose:
+ string = "\f";
+ nbytes = 1;
+ break;
+
+
+ case ButtonPress:
+ {
+ int leaf;
+ int otherLeaf;
+ int normalLeafW = leaf_w[SHRINK_NORMAL];
+ int leafX;
+ int leafY;
+ int lastLeaf = -1;
+
+ int x = event.xbutton.x;
+ int y = event.xbutton.y;
+ int lastButton = event.xbutton.button;
+
+/*
+ * Determine which leaf was pointed to & where we will display it
+ */
+ leaf = x / normalLeafW;
+ if (leaf < 0 || leaf >= Leaves) {
+ fprintf(stderr,"[%s] error in button press, leaf = %d\n",
+ ProgName, leaf);
+ exit(1);
+ }
+
+ if (leaf != lastLeaf && lastLeaf != -1) {
+ displayLeaf(lastLeaf);
+ }
+ lastLeaf = leaf;
+
+ if (Leaves == 1) {
+ otherLeaf = leaf;
+ } else {
+ otherLeaf = 1 - leaf;
+ }
+
+/*
+ * Build the enlarged page if its not already there
+*/
+ if (haveLargePage[leaf] != pageOnLeaf[leaf]) {
+ buildLeaf(leaf, pageOnLeaf[leaf], SHRINK_LARGE);
+ haveLargePage[leaf] = pageOnLeaf[leaf];
+ }
+
+/*
+ * Determine where he was looking, build a (x,y) such that
+ * the thing he was pointing at will be on the screen, as close to
+ * center as possible.
+ */
+
+ leafX = (x - (leaf * normalLeafW));
+ leafX = (leafX * shrinkFactor[SHRINK_NORMAL])
+ / shrinkFactor[SHRINK_LARGE];
+
+ leafX -= (leaf_w[SHRINK_NORMAL] / 2);
+ leafX = MAX(leafX, 0);
+ leafX = MIN(leafX, leaf_w[SHRINK_LARGE]);
+
+ leafY = (y * shrinkFactor[SHRINK_NORMAL])
+ / shrinkFactor[SHRINK_LARGE];
+
+ leafY -= (page_h[SHRINK_NORMAL] / 2);
+ leafY = MAX(leafY, 0);
+ leafY = MIN(leafY, page_h[SHRINK_LARGE]);
+
+/*
+ * Display the enlarged image on the leaf, wait for another
+ * button event (the release, we hope)& then restore the image as it was
+ */
+ clearWindow(otherLeaf);
+ XCopyArea(DISP, pasteUpPixmap[SHRINK_LARGE][leaf],
+ win, forepix,
+ leafX, leafY,
+ leaf_w[SHRINK_NORMAL], page_h[SHRINK_NORMAL],
+ leaf_w[SHRINK_NORMAL] * otherLeaf, 0);
+
+ bzero(&event, sizeof(event));
+ for(;;) {
+ XNextEvent(DISP, &event);
+ if (event.type == ButtonRelease
+ && event.xbutton.button == lastButton) {
+ break;
+ }
+ }
+ displayLeaf(otherLeaf);
+ break;
+ }
+
+ case ButtonRelease:
+ break;
+
+ case KeyPress:
+ string = trbuf;
+ nbytes = XLookupString(&event, string, 100, NULL, NULL);
+
+ break;
+ }
+
+ if (nbytes == 0) continue;
+
+ if (nbytes > 1) goto bad;
+
+ switch (ch = *string) {
+ case 'q':
+ case '\003': /* control-C */
+ case '\004': /* control-D */
+ stop_output(0);
+ break;
+
+ case 'n':
+ case 'f':
+ case ' ':
+ case '\n' :
+ case '\r' :
+ /* scroll forward */
+ direction = FOREWARD;
+ rebuild = 1;
+ break;
+
+ case 'p':
+ case 'b':
+ case '\b':
+ case 0177 : /* DEL */
+ /* scroll backward */
+ direction = BACKWARD;
+ rebuild = 1;
+ break;
+
+ case '\f':
+ case 'r' :
+ /* repaint current page */
+ repaint = 1;
+ break;
+
+ case 'g':
+ /* go to absolute page */
+ direction = ABSOLUTE; /* may not be, but tough */
+ rebuild = 1;
+ break;
+
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ if (! arg) {
+ arg = 1;
+ sign = 1;
+ number = 0;
+ }
+ number = 10*number + sign*(ch - '0');
+
+ repaint = 0;
+ continue;
+
+ case '-':
+ if (! arg) {
+ arg = 1;
+ sign = -1;
+ number = 0;
+ repaint = 0;
+ continue;
+ } else
+ goto bad;
+ default:
+ goto bad;
+ }
+
+ if (rebuild && direction != BOGUSDIR) {
+ int newLeft;
+ int newRight;
+/*
+ * canonicalize the request. arg is always > 0, were moving in
+ * some direction.
+ */
+
+ if (!arg || number == 0) {
+ number = 1;
+ }
+
+
+ if (number < 0) {
+ if (direction == FOREWARD) {
+ direction = BACKWARD;
+ } else if (direction == BACKWARD){
+ direction = FOREWARD;
+ }
+ number = -number;
+ }
+
+/*
+ * Turn pages back
+ */
+ if (direction == BACKWARD) {
+ newLeft = pageOnLeaf[LEAF_LEFT] - number;
+ } else if (direction == FOREWARD) {
+ newLeft = pageOnLeaf[LEAF_LEFT] + number;
+ } else {
+ newLeft = number - 1; /* pages numbered at 0 */
+ }
+
+ newLeft = MIN(newLeft, dviTotalPages-1);
+ newLeft = MAX(newLeft, 0);
+
+ if (Leaves == 1) {
+ if (newLeft != pageOnLeaf[LEAF_LEFT]) {
+ buildLeaf(LEAF_LEFT, newLeft, SHRINK_NORMAL);
+ }
+ } else {
+ newRight = newLeft + 1;
+
+ if (pageOnLeaf[LEAF_LEFT] != newLeft) {
+ if (newLeft == pageOnLeaf[LEAF_RIGHT]) {
+ swapLeaf(LEAF_RIGHT, LEAF_LEFT);
+ displayLeaf(LEAF_LEFT);
+ } else if (newRight == pageOnLeaf[LEAF_LEFT]) {
+ swapLeaf(LEAF_LEFT, LEAF_RIGHT);
+ displayLeaf(LEAF_RIGHT);
+ }
+
+ if (pageOnLeaf[LEAF_LEFT] != newLeft) {
+ buildLeaf(LEAF_LEFT, newLeft, SHRINK_NORMAL);
+ }
+
+ if (pageOnLeaf[LEAF_RIGHT] != newRight) {
+ buildLeaf(LEAF_RIGHT, newRight, SHRINK_NORMAL);
+ }
+ }
+ }
+ repaint = 0;
+ rebuild = 0;
+ arg = 0;
+/*
+ * Only repaint it if we need to
+ */
+ }
+
+ if (repaint){
+ displayLeaves();
+ repaint = 0;
+ }
+
+ continue;
+
+ bad:
+
+ arg = 0; /* throw away numeric argument */
+ continue;
+
+ }
+}
+
+stop_output(sig)
+{
+ exit(sig);
+}
+
+put_border(x, y, w, h, t)
+int x, y, w, h, t;
+{
+ put_rectangle(x, y, w, t, highpix);
+ put_rectangle(x, y, t, h, highpix);
+ put_rectangle(x, y + h - t, w, t, highpix);
+ put_rectangle(x + w - t, y, t, h, highpix);
+}
+
+put_rectangle(x, y, w, h, pix)
+int x, y, w, h;
+GC pix;
+{
+ if (buildToPixmap) {
+ XFillRectangle(DISP, pasteUpPixmap[currentShrink][currentLeaf],
+ pix, x, y, w, h);
+ } else {
+ XFillRectangle(DISP, win,
+ pix, x + currentLeaf * leaf_w[currentShrink], y, w, h);
+ }
+}
+
+
diff --git a/dviware/umddvi/previewers/texx2/00readme.tex b/dviware/umddvi/previewers/texx2/00readme.tex
new file mode 100644
index 0000000000..fed4bf42b0
--- /dev/null
+++ b/dviware/umddvi/previewers/texx2/00readme.tex
@@ -0,0 +1,62 @@
+% drivers/umddvi/texx2
+\index{previewers!X11}
+\par\begin{footnotesize}\begin{alltt}
+Contents of README files:\par
+Sorry, this file got let out of the original distribution.
+
+This directory contains several tools to manipulate the DVI files produced
+by TeX and LaTeX. Additionally, it includes a re-distribution of the
+DVI library routines written by Chris Torek at the University of Maryland.
+The utilities included are:
+
+dviselect select specific pages from a DVI file
+iptex print a dvi file on an Imagen
+texx a dvi previewer for X-11 windows
+texsun a dvi previewer for SunView windows
+
+texx2 a much improved dvi previewer for X-11 windows
+
+To install this package, read the documentation in the file
+doc/installation.tex. The short instructions follow.
+
+FOR TEXX2:
+
+ + Change the binary path names in the ./Makefile.
+
+ + Select a location for your ``font description'' file, and copy and
+ modify the file in fontdesc-example to suit your local installation.
+ Change the main makefile to use that path for variable FONTDESC
+
+ The default is /usr/local/lib/tex82/fontdesc
+
+ + cd to texx2; Edit the Imakefile. Note that DEFAULT_TFM_PATH
+ defines the default path for finding .tfm files, just like TeX.
+
+ + Build a Makefile from the Imakefile
+
+ + run ``make texx2'' at the main level
+
+ + texx2 should now be built. You'll need to install some fonts.
+
+ + in run texx2/mftobdf -mag 1000 -scaled 1000 cmr10. If mftobdf
+ can't find your font, you've got a bad fontdesc file or the
+ path to it is wrong.
+
+ + assuming that this works, edit texx2/buildfonts to suite your
+ local X configuration. I keep fonts in /usr/local/lib/X11/fonts/cmr,
+ and have added this to my font path using
+ % xset +fp /usr/local/lib/X11/fonts/cmr
+ % xset fp rehash
+
+ + in texx2, run "buildfonts -mag 500 `cat FONTS` " to build a
+ fair number of standard fonts. Note that the default is
+ 300 dpi. If you want a smaller set too, say ``-mag 333''.
+
+ + You can use other DPI's -- both texx2 & mftobdf have switches
+ for this.
+
+Dirk Grunwald
+Univ. of Illinois
+grunwald@m.cs.uiuc.edu
+
+\end{alltt}\end{footnotesize}\par
diff --git a/dviware/umddvi/previewers/texx2/buildfonts b/dviware/umddvi/previewers/texx2/buildfonts
new file mode 100644
index 0000000000..fa25079e55
--- /dev/null
+++ b/dviware/umddvi/previewers/texx2/buildfonts
@@ -0,0 +1,17 @@
+#!/bin/sh
+MFTOBDF=mftobdf
+FONTDIR=/u/tex/xfonts
+#
+${MFTOBDF} $*
+for file in *.bdf ;
+do
+ base=`echo $file | sed -e 's/.bdf//g'`
+ echo Process $base
+ bdftosnf $base.bdf > ${FONTDIR}/$base.snf
+ rm -f $base.bdf
+done
+#
+cd ${FONTDIR}
+mkfontdir
+xset +fp `pwd`
+xset fp rehash
diff --git a/dviware/umddvi/previewers/texx2/changelog b/dviware/umddvi/previewers/texx2/changelog
new file mode 100644
index 0000000000..a52c3ae90d
--- /dev/null
+++ b/dviware/umddvi/previewers/texx2/changelog
@@ -0,0 +1,123 @@
+Tue Feb 28 18:41:45 1989 Dirk Grunwald (grunwald at flute.cs.uiuc.edu)
+
+ * repackeged as 2.8.5
+
+ * (texx2-font.c) Calculation of mag ignored mag specified in
+ document. Fixed.
+
+ * (texx2-file.c) Made the file name be stuffed into the input box
+
+Sun Feb 26 16:44:46 1989 Dirk Grunwald (grunwald at flute.cs.uiuc.edu)
+
+ * Compensate for scroll-bars. Now, mag=333 on a sun3 gets rid
+ of horiz scroll.
+
+Sat Feb 25 13:19:50 1989 Dirk Grunwald (grunwald at flute.cs.uiuc.edu)
+
+ * texx2-page.c - added TeXPageSlamPages, in case we fail
+ to open a file and need to close exising windows. If we
+ don't, they can move around or redisplay, referencing dead
+ data structures.
+
+ * texx2-page.c - reopening a file now leaves pages at the same
+ page number in the new file. this means you don't have to
+ reposition yourself when you open a file.
+
+ * Released as 2.8
+
+ * texx2-page.c - split TeXPageNewFile into two parts, because
+ value of DviTotalPages changes after an open, causing
+ bogus free().
+
+ * texx2.c - stat the command line file name to make certain
+ it's a regular file before doing a setFile
+
+ * texx2-mark.c - plug last double free? Now explicitly zero variables
+ after *all* frees.
+
+Fri Feb 24 14:47:13 1989 Dirk Grunwald (grunwald at flute.cs.uiuc.edu)
+
+ * Released as 2.7
+
+ * texx2.c - allow single argument to set the file name
+
+ * DviPage.c - fix problem with inlines & optimization. Fontdefs
+ weren't being skipper properly, causing font names to be displayed.
+
+ * texx2-page.c - optimize tied pages for single-page-ahead
+ with foreward travel (avoid freeing next page until it gets it)
+
+ * texx2-page.c - fix double free in TeXPageNewFile (forgot to zero)
+
+ * dvi-simple.c - fix double free for DviCount (forgot to zero)
+
+ * dvi-simple.c - use strncpy
+
+ * texx2-page.c - found out about XtNallowShellResize.
+ remove include of ShellP.h
+
+ * texx2-font.c - reverse order of -mag and -scaled in error
+ message to make cut & paste buildfonts easier
+
+ * Imakefile - remove tabs
+
+ * texx2-error.c - Apply patch from Dana to fix over-write of
+ dialog box.
+
+ * DviPage.c, DviPage2.c - removed setGC, use single globalGC
+ which is rebuilt on each redisplay.
+
+ * DviPageP.h - removed `clearGC', renamed setGC to globalGC
+
+ * texx2-file.c - merged BuildPageLevel into BuildFileLevel.
+
+Fri Feb 24 14:50:36 1989 Dana A. Chee (dana at dino)
+
+ * texx2-error.c - removed unneeded resource XtNresize (not used in
+ text widgets).
+
+ * texx2-file.c - changed strcpy to proper strncpy; created widgets
+ in order used for chaining (Form widget goes through child list
+ once to place children, if the order of their chaining is
+ different from their creation order, the results will not be
+ satisfactory).
+
+ * texx2-widgets.c - let widgets dimension the form; build widgets
+ in correct order for chaining (Page within File now, see above
+ reasons).
+
+ * texx2.c - use proper program and class names for XtInitialize.
+
+Thur Feb 23 17:30:10 1989 Dirk Grunwald (grunwald at flute.cs.uiuc.edu)
+
+ * texx2-page.c - Added `large' and `small' buttons
+ * texx2.c - Added `largeMag' and `smallMag' resources
+
+Sun Feb 19 17:30:10 1989 Dirk Grunwald (grunwald at flute.cs.uiuc.edu)
+
+ * Released as 2.5
+
+ * Added `clear marks' button
+
+ * Fixed error in DviPageWidget - wasn't setting the setGC
+ properly, causing redraws to fail when not using backing store
+
+Fri Feb 17 17:30:10 1989 Dirk Grunwald (grunwald at flute.cs.uiuc.edu)
+
+ * Added ``tied'' pages, Imakefile, man page
+
+Tue Feb 14 11:49:11 1989 Dirk Grunwald (grunwald at flute.cs.uiuc.edu)
+
+ * Changed all args to widgets to be built use XtSetArg instead of
+ automatic aggregate initializations.
+
+ * Changed all callbacks to be built using XtAddCallback instead
+ of automatic aggregate initializations.
+
+ * Changes texx2-error.c to build a temporary _iobuf structure
+ for _doprnt to print erorr messages if vsprintf is unavailable.
+
+ * (texx2-page.c) made pushGotoButton goto the page with a count[0]
+ field matching the selected page number, as opposed to the ordinal
+ page number.
+
diff --git a/dviware/umddvi/previewers/texx2/description b/dviware/umddvi/previewers/texx2/description
new file mode 100644
index 0000000000..2c8009802a
--- /dev/null
+++ b/dviware/umddvi/previewers/texx2/description
@@ -0,0 +1,64 @@
+
+texx2.4 is available for anonymous FTP from
+ a.cs.uiuc.edu: pub/TeX/texx2.4.tar.Z
+or
+ expo.lcs.mit.edu: contrib/texx2.4.tar.Z
+
+texx2, currently at revision 4, is a second generation TeX previewer for
+X11 windowing systems. Unlike texx or xdvi, texx2 uses X11 fonts to display
+TeX output. A companion program, `mftobdf', is used to convert TeX fonts
+(i.e., PXL/GF/PK) fonts to the the formats required for X11.
+
+Consequentially, texx2 is significantly faster than the first release of
+texx or the venerable xdvi. Page display occurs at roughly the same speed
+of displays in `xman'. It's really even faster than texsun.
+
+Features include:
+ + Multiple pages displays at once, each in their own toplevel window.
+
+ + Pages can be `tied' together, such that hitting `foreward'
+ in one page causes the second page to go forward
+
+ + Ability to goto any page (using page numbers stored in \count0)
+
+ + Different mag levels can be set for different page displays
+
+ + Can use any existing fonts (for example, I use 300 dpi fonts,
+ and view the document at mags of 500 and 333 -- this gives
+ good detail & overall views)
+
+ + horiztoial and vertical scroll bars if needed
+
+ + can mark individual pages for printing
+
+ + can print entire document and/or marked pages
+
+ + the main window is designed to be leftup between viewing
+ sessions -- no need to restart the tool each time.
+
+ + handles tpic specials, out-lines bounding box of psfig
+ pictures.
+
+ + Known to work on X servers for Sun 3/60, IBM PC/RT, Vaxstation 3100.
+ Known to run as client on Sun 3/60, IBM PC/RT, Encore Multimax
+ (our vaxstation version of X11 doesn't have all patches applied,
+ so something causes it to die there)
+
+ + It's free.
+
+Downsides:
+ + You need to generate the X11 fonts. While this is simple, it's
+ takes me about 600K to store the fonts we use on a daily basis.
+ However, you *can* compress them, although that slows down
+ page display startup.
+
+ + Can easily expand your server memory size by 450K, because of all
+ the fonts.
+
+ + There is no warrenty, precious little documentation,
+ and I'm not going to be able to answer mail about it
+ because I'm interviewing and trying to finish my thesis.
+ However, if you've ever installed texsun or texx, texx2
+ should be a snap.
+Office: 72 DCL (217) 333-1925
+
diff --git a/dviware/umddvi/previewers/texx2/dvi-simple.c b/dviware/umddvi/previewers/texx2/dvi-simple.c
new file mode 100644
index 0000000000..eea2aca35b
--- /dev/null
+++ b/dviware/umddvi/previewers/texx2/dvi-simple.c
@@ -0,0 +1,508 @@
+/*
+ * This program is Copyright (C) 1987 by the Board of Trustees of the
+ * University of Illinois, and by the author Dirk Grunwald.
+ */
+
+#include <stdio.h>
+#include "dvi-simple.h"
+#include "conv.h"
+#include <assert.h>
+#include <sys/file.h>
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 1
+#endif
+
+#ifdef __STDC__
+ extern void bzero(char *, int);
+ extern char* malloc(int);
+ extern void free(char *);
+ extern char *getenv(char *);
+ extern strcpy(char *, char *);
+ extern strncpy(char *, char *,int);
+ extern strcat(char *, char *);
+ extern FILE *fopen(char *, char *);
+#else
+ extern void bzero();
+ extern char* malloc();
+ extern void free();
+ extern char *getenv();
+ extern strcpy();
+ extern strcat();
+ extern FILE *fopen();
+#endif
+
+struct PostAmbleInfo ThePostAmbleInfo;
+
+int RegisteredFonts = 0;
+
+#define MAX_GLYPHS 256
+DviFontInfo TheFontInfo[ MAX_POSTAMBLE_FONTS ];
+
+long dviPageOffsets;
+
+static long Magnification;
+static long Numerator; /* numerator from DVI file */
+static long Denominator; /* denominator from DVI file */
+
+long *DviCount[DVI_COUNT];
+long *DviPageOffsets = 0;
+
+int DviHHMargin = -1; /* horizontal margin (in DEVs) */
+int DviVVMargin = -1; /* vertical margin (in DEVs) */
+int DviTallestPage = -1;
+int DviWidestPage = -1 ;
+int DviCurrentPage = -1;
+int DviTotalPages = -1;
+int DviDpi = -1;
+int DviMaxDrift = -1;
+int DviUserMag = -1; /* user-specified magnification */
+int DviBlackness = -1;
+FILE *DviFile;
+long DviFileSize;
+char *DviFileName;
+
+static Conv Conversion;
+
+extern int errno;
+
+static int anError;
+
+static void savePostAmblePointer(p)
+struct PostAmbleInfo *p;
+{
+ int i;
+ int page;
+ int pageSize;
+ int stackSize;
+ long prevPagePointer;
+ long wuzAt;
+
+ ThePostAmbleInfo = *p;
+
+ Numerator = p->pai_Numerator;
+ Denominator = p->pai_Denominator;
+ Magnification = p->pai_DVIMag;
+
+ /*
+ * Set the conversion factor. This must be done before using
+ * any fonts or the fromSP routine.
+ */
+
+ CSetConversion(&Conversion,
+ DviDpi, DviUserMag, Numerator, Denominator, Magnification);
+
+ DviTotalPages = p -> pai_NumberOfPages;
+ DviWidestPage = cfromSP(&Conversion, p -> pai_WidestPageWidth);
+ DviTallestPage = cfromSP(&Conversion, p -> pai_TallestPageHeight);
+
+ /*
+ * Set of the table of pointers to pages and room for the
+ * count variables.
+ */
+
+ pageSize = DviTotalPages * sizeof(long);
+ if (DviPageOffsets != 0) {
+ free( (char *) DviPageOffsets);
+ DviPageOffsets = 0;
+ }
+ DviPageOffsets = (long *) malloc(pageSize);
+
+ if (DviPageOffsets == NULL) {
+ error(1,0,"Can not allocate page directory (%d pages)", DviTotalPages);
+ exit(1);
+ }
+
+ for (i = 0; i < DVI_COUNT; i++) {
+ if (DviCount[i] != 0) {
+ free( (char *) DviCount[i]);
+ DviCount[i] = 0;
+ }
+ DviCount[i] = (long *) malloc(pageSize);
+ if (DviCount[i] == NULL) {
+ error(1,0,"Can not allocate count directory (%d pages)", DviTotalPages);
+ exit(1);
+ }
+ }
+
+ /*
+ * Follow back pointers through pages in the DVI file,
+ * storing the offsets in the DviPageOffsets table.
+ */
+
+ prevPagePointer = p->pai_PrevPagePointer;
+ wuzAt = (long) ftell(DviFile);
+
+ fseek(DviFile, 0L, 2);
+ DviFileSize = ftell(DviFile);
+
+ for (page = DviTotalPages - 1; page >= 0 ; page--) {
+
+ /*
+ * Skip to previous page, but skip over BOP marker.
+ */
+ DviPageOffsets[page] = prevPagePointer;
+
+ if( fseek(DviFile, prevPagePointer+1, 0) < 0) {
+ error(1, errno, "Improper seek looking up pages\n");
+ anError |= 1;
+ return;
+ }
+
+ /*
+ * Read the other counters at the beginning of the page
+ */
+
+ for (i = 0; i < DVI_COUNT; i++) {
+ long value;
+ fGetLong(DviFile, value);
+ DviCount[i][page] = value;
+ }
+ fGetLong(DviFile, prevPagePointer);
+ }
+ fseek(DviFile, wuzAt, 0);
+}
+
+#ifndef TEXFONTS
+#define TEXFONTS ".:/u/tex/mftfm:/u/tex/pstfm"
+#endif
+
+static char *EnvFontPath;
+
+static FILE *openTfmFile(name)
+char *name;
+{
+ char *usePath;
+ char path[1024];
+
+ if ( EnvFontPath == 0 ) {
+ extern char *getenv();
+ EnvFontPath = getenv("TEXFONTS");
+ }
+
+ usePath = (EnvFontPath == 0) ? TEXFONTS: EnvFontPath;
+
+ for (;;) {
+ char *p = path;
+
+ if ( usePath == 0 || *usePath == 0 ) {
+ return( 0 );
+ }
+
+ *p = 0;
+
+ while ( *usePath && *usePath != ':' ) {
+ *(p++) = *(usePath++);
+ }
+
+ /* append name */
+
+ *(p++) = '/';
+ strcpy(p, name);
+ strcat(p, ".tfm");
+ if ( access( path, R_OK ) == 0 ) {
+ return( fopen(path, "r") );
+ }
+
+ if ( *usePath == ':' ) {
+ usePath++;
+ }
+ }
+}
+
+static void
+registerFont(f)
+struct PostAmbleFont *f;
+{
+ int thisFont;
+ FILE *tfmFile;
+ char *fontName[1024];
+
+ assert( RegisteredFonts < MAX_POSTAMBLE_FONTS );
+
+ thisFont = RegisteredFonts++;
+/* Attempt to locate the TFM files */
+
+ tfmFile = openTfmFile( f -> paf_name );
+ if ( tfmFile == 0 ) {
+ error(0,0,"Can't find TFM file for %s", f -> paf_name);
+ anError = 1;
+ }
+ else {
+ struct tfmdata t;
+ i32 pspace;
+ int len;
+
+ TheFontInfo[ thisFont ].paf = *f;
+
+ /* make a copy of the name */
+
+ len = strlen( f -> paf_name );
+ TheFontInfo[ thisFont ].paf.paf_name
+ = malloc( sizeof(char) * (len + 1 ));
+ strncpy( TheFontInfo[ thisFont ].paf.paf_name, f -> paf_name, len+1);
+
+ pspace = f -> paf_DVIMag / 6; /* a three-unit "thin space" */
+
+ TheFontInfo[ thisFont ].pspace = pspace;
+ TheFontInfo[ thisFont ].nspace = -4 * pspace;
+ TheFontInfo[ thisFont ].vspace = 5 * pspace;
+
+ bzero((char *) &t, sizeof(t));
+
+ if ( readtfmfile( tfmFile, &t, TRUE ) != 0 ) {
+ error(0,0,"Bogus TFM file: %s", f -> paf_name);
+ }
+ else {
+ int i;
+ int nc = t.t_hdr.th_ec - t.t_hdr.th_bc + 1;
+ int nw;
+ int *p;
+ int s; /* see dvitype */
+ int d;
+
+ if ( TheFontInfo[ thisFont ].widths == 0 ) {
+ TheFontInfo[ thisFont ].widths =
+ (int *) malloc( sizeof(int) * MAX_GLYPHS );
+ }
+
+ /* convert widths */
+ assert( t.t_width[0] == 0 );
+ nw = t.t_hdr.th_nw;
+ s = TheFontInfo[ thisFont ].paf.paf_DVIMag;
+ d = TheFontInfo[ thisFont ].paf.paf_DVIDesignSize;
+
+ for (i = 0; i < nw; i++) {
+
+ int width = t.t_width[i];
+
+ if (width != 0) {
+ width = ScaleOneWidth(width, s);
+ }
+ t.t_width[i] = width;
+
+ }
+
+ p = TheFontInfo[ thisFont ].widths;
+ bzero( (char *) p , sizeof(int) * MAX_GLYPHS );
+
+ p += t.t_hdr.th_bc;
+
+ for (i = 0; i <= nc; i++) {
+ int wi = t.t_ci[i].ci_width;
+ *(p++) = t.t_width[wi];
+ }
+ }
+
+ fclose(tfmFile);
+ }
+}
+
+/*
+ * Returns TRUE if everything is fine
+ */
+
+int
+DviInit( dviFileName, copy )
+char *dviFileName;
+int copy;
+{
+ extern char *ProgName;
+ FILE *dviFile;
+ char *mktemp();
+
+ anError = 0;
+
+ DviFini(); /* clean up the old files */
+
+ DviFile = 0;
+
+ if (dviFileName == 0) {
+ dviFile = stdin;
+ dviFileName = "<stdin>";
+ copy = 1;
+ }
+ else if ((dviFile = fopen(dviFileName, "r")) == NULL) {
+
+ int n = strlen(dviFileName);
+ char *dviName;
+
+ if (strcmp(dviFileName + n - sizeof(".dvi") + 1, ".dvi") == 0) {
+ DviFini();
+ error(0, errno, "[fopen] can't open %s", dviFileName);
+ return(1);
+ }
+
+ dviName = (char *) malloc((unsigned) n + sizeof(".dvi") + 1);
+ sprintf(dviName, "%s.dvi", dviFileName);
+
+ if ((dviFile = fopen(dviName, "r")) == NULL) {
+ DviFini();
+ error(0, errno, "[fopen] can't open %s", dviName);
+ return(1);
+ }
+ dviFileName = dviName;
+ }
+
+ DviFileName = dviFileName;
+
+ if ( copy ) {
+
+ /*
+ * Copy the file to a temporary location if requested.
+ * This lets the person peruse the file while theyre re-texing it.
+ */
+ FILE *tmpFile;
+ char dviTmpFileNameBuffer[256];
+ char *dviTmpFileName;
+
+ sprintf(dviTmpFileNameBuffer,"/tmp/Dvistuff.XXXXXX");
+
+ dviTmpFileName = mktemp(dviTmpFileNameBuffer);
+
+ if (!(tmpFile = fopen(dviTmpFileName,"w+"))) {
+ error(0, errno, "[fopen] Unable to create temporary file");
+ dviTmpFileName = 0;
+ }
+ else {
+ char buffer[BUFSIZ];
+ int b;
+
+ rewind(dviFile);
+ do {
+ b = fread(buffer, 1, BUFSIZ, dviFile);
+ fwrite(buffer, 1, b, tmpFile);
+ } while (! feof(dviFile));
+
+ fclose(dviFile);
+ dviFile = tmpFile;
+ rewind(dviFile);
+
+ /*
+ * Unlink the temporary file. This keeps tmp files from cluddering
+ * up /tmp and it does it in a very application-independent way.
+ * You can't reopen the tmp file, but we don't really allow that
+ * anyway (the tmp file is hidden from the user).
+ */
+
+ if (dviTmpFileName != 0 &&
+ strncmp(dviTmpFileName,"/tmp/",5) == 0) {
+ unlink(dviTmpFileName);
+ }
+ }
+ }
+
+ assert( dviFile != 0 );
+
+ DviFile = dviFile;
+
+ if (DviUserMag == -1) {
+ DviUserMag = 1000;
+ }
+
+ if (DviMaxDrift == -1) {
+ DviMaxDrift = DEFAULT_MAX_DRIFT;
+ }
+
+ if (DviDpi == -1) {
+ DviDpi = DEFAULT_DPI;
+ }
+
+ if (DviBlackness == -1) {
+ DviBlackness = DEFAULT_BLACKNESS;
+ }
+
+ /* Margins -- needs work! */
+
+ if (DviHHMargin == -1) {
+ DviHHMargin = DEFAULT_HHMARGIN;
+ }
+
+ if (DviVVMargin == -1) {
+ DviVVMargin = DEFAULT_VVMARGIN;
+ }
+
+ anError |= ScanPostAmble( DviFile, savePostAmblePointer, registerFont);
+
+ if (anError) {
+ DviFini();
+ }
+
+ return( anError );
+}
+
+void
+DviFini()
+{
+ int font;
+ int c;
+
+ if (DviFile != 0) {
+ fclose(DviFile);
+ }
+
+ DviFile = 0;
+
+ for (font = 0; font < RegisteredFonts; font++) {
+ if ( TheFontInfo[ font ].paf.paf_name ) {
+ free ( (char *) TheFontInfo[ font ].paf.paf_name );
+ TheFontInfo[ font] .paf.paf_name = 0;
+ }
+ if ( TheFontInfo[ font ].widths ) {
+ free ( (char *) TheFontInfo[ font ].widths );
+ TheFontInfo[ font].widths = 0;
+ }
+ }
+ RegisteredFonts = 0;
+
+ for (c = 0; c < DVI_COUNT; c++) {
+ if ( DviCount[ c ] ) {
+ free( (char *) DviCount[ c ] );
+ DviCount[ c ] = 0;
+ }
+ }
+}
+
+
+char *
+DviFetchPage(pageNumber)
+int pageNumber;
+{
+ if ( pageNumber < 0 || pageNumber > DviTotalPages ) {
+ return(0);
+ }
+ else {
+ long start = DviPageOffsets[ pageNumber ];
+ long end = ( pageNumber == (DviTotalPages-1))
+ ? DviFileSize : DviPageOffsets[ pageNumber + 1];
+ long toRead = end - start;
+
+ char *buffer = malloc( toRead );
+
+ if (buffer == 0 ) {
+ return( 0 );
+ }
+ else {
+
+ long loc;
+ long bytes;
+
+ loc = fseek(DviFile, (long) start, 0);
+ if (loc < 0) {
+ error(0,0,"Improper seek: %d", errno);
+ }
+
+ bytes = fread( buffer, 1, toRead, DviFile );
+
+ if (bytes != toRead) {
+ error(0,0,"Tried to read %d, only got %d", toRead, bytes);
+ }
+ return(buffer);
+ }
+ }
+}
+
diff --git a/dviware/umddvi/previewers/texx2/dvi-simple.h b/dviware/umddvi/previewers/texx2/dvi-simple.h
new file mode 100644
index 0000000000..b79e98fb96
--- /dev/null
+++ b/dviware/umddvi/previewers/texx2/dvi-simple.h
@@ -0,0 +1,75 @@
+/*
+ * This program is Copyright (C) 1987 by the Board of Trustees of the
+ * University of Illinois, and by the author Dirk Grunwald.
+ */
+
+#include "types.h"
+#include "dviclass.h"
+#include "dvicodes.h"
+#include "tfm.h"
+#include "fio.h"
+#include "postamble.h"
+
+/*****************************************************************************
+ * Things we read from the DVI file
+ */
+
+extern struct PostAmbleInfo ThePostAmbleInfo;
+
+typedef struct {
+ struct PostAmbleFont paf;
+ int *widths;
+ i32 pspace; /* boundary between `small & `large spaces
+ (for positive horizontal motion) */
+ i32 nspace; /* -4 * pspace, for negative motion */
+ i32 vspace; /* 5 * pspace, for vertical motion */
+} DviFontInfo;
+
+#define MAX_POSTAMBLE_FONTS 256
+extern int RegisteredFonts;
+extern DviFontInfo TheFontInfo[ MAX_POSTAMBLE_FONTS ];
+
+/*****************************************************************************
+/*
+ * Defaults and configuration for dvi-simple
+ */
+
+#define DEFAULT_DPI 300
+#define DEFAULT_HHMARGIN DEFAULT_DPI
+#define DEFAULT_VVMARGIN DEFAULT_DPI
+#define DEFAULT_MAX_DRIFT 3
+
+#define DEFAULT_BLACKNESS 3
+
+#define DVI_COUNT 10 /* count0 .. count9 */
+
+#define SP_PER_INCH(dpi) ( (dpi) * 65536 )
+#define POINTS_PER_INCH 72.27
+
+extern long *DviCount[DVI_COUNT];
+extern long *DviPageOffsets;
+
+extern int DviHHMargin;
+extern int DviVVMargin;
+extern int DviDpi;
+extern int DviTallestPage;
+extern int DviWidestPage;
+extern int DviTotalPages;
+extern int DviCurrentPage;
+extern int DviMaxDrift;
+extern char *DviPrintEngine;
+extern int DviBlackness;
+extern int DviUserMag;
+
+extern FILE *DviFile;
+extern char *DviFileName;
+
+#ifdef __STDC__
+ extern int DviInit( char *, int );
+ extern void DviFini();
+ extern char * DviFetchPage( int );
+#else
+ extern int DviInit();
+ extern void DviFini();
+ extern char * DviFetchPage();
+#endif
diff --git a/dviware/umddvi/previewers/texx2/dvipage.c b/dviware/umddvi/previewers/texx2/dvipage.c
new file mode 100644
index 0000000000..50f3c77a92
--- /dev/null
+++ b/dviware/umddvi/previewers/texx2/dvipage.c
@@ -0,0 +1,915 @@
+/*
+ * This program is Copyright (C) 1987 by the Board of Trustees of the
+ * University of Illinois, and by the author Dirk Grunwald.
+ */
+
+#include <X11/Xos.h>
+#include <X11/IntrinsicP.h>
+#include <X11/StringDefs.h>
+#include <stdio.h>
+#include "dvi-simple.h"
+#include "mio.h"
+#include "conv.h"
+#include <assert.h>
+
+#include "DviPageP.h"
+
+ static XtResource resources[] = {
+
+#define offset(field) XtOffset(DviPageWidget, field)
+
+ /* {name, class, type, size, offset, default_type, default_addr}, */
+
+ {XtNbackground, XtCBackground, XtRPixel, sizeof(Pixel),
+ offset(dviPage.background), XtRString, "XtDefaultBackground"},
+
+ {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
+ offset(dviPage.foreground), XtRString, "XtDefaultForeground"},
+
+ {XtNfont, XtCFont, XtRFontStruct, sizeof(XFontStruct *),
+ offset(dviPage.font), XtRString, "XtDefaultFont"},
+
+ {XtNpage, XtCPage, XtRPointer, sizeof(char *),
+ offset(dviPage.page), XtRPointer, 0},
+
+ {XtNpai, XtCPai, XtRPointer, sizeof(struct PostAmbleInfo *),
+ offset(dviPage.pai), XtRPointer, 0 },
+
+ {XtNdviFonts, XtCDviFonts, XtRPointer, sizeof(DviFontInfo *),
+ offset(dviPage.dviFonts), XtRPointer, 0 },
+
+ {XtNxFonts, XtCXFonts, XtRPointer, sizeof(XFontStruct **),
+ offset(dviPage.xFonts), XtRPointer, 0 },
+
+ {XtNuserMag, XtCUserMag, XtRInt, sizeof(int),
+ offset(dviPage.userMag), XtRString, "500"},
+
+ {XtNdpi, XtCDpi, XtRInt, sizeof(int),
+ offset(dviPage.dpi), XtRString, "300"},
+
+ {XtNreverseVideo, XtCReverseVideo, XtRBool, sizeof(Bool),
+ offset(dviPage.reverseVideo), XtRString, "False"},
+
+ {XtNbackingStore, XtCBackingStore, XtRBackingStore, sizeof (int),
+ offset (dviPage.useBackingStore), XtRString, "default"},
+
+ {XtNpaperWidth, XtCPaperWidth, XtRString, sizeof (char *),
+ offset (dviPage.paperWidthString), XtRString, "8.5"},
+
+ {XtNpaperHeight, XtCPaperHeight, XtRString, sizeof (char *),
+ offset (dviPage.paperHeightString), XtRString, "11"}
+
+#undef offset
+ };
+
+#ifdef __STDC__
+ static void ClassInitialize();
+ static void Initialize(), Destroy(), Redisplay();
+ static void Realize();
+ static Boolean SetValues( );
+ static void SetPageSize( DviPageWidget, Dimension *width, Dimension *heigth);
+ static XtGeometryResult QueryGeometry();
+
+ extern double atof(char *);
+#else
+ static void ClassInitialize();
+ static void Initialize(), Destroy(), Redisplay();
+ static void Realize();
+ static Boolean SetValues();
+ static XtGeometryResult QueryGeometry();
+ static XtGeometryResult QueryGeometry();
+
+ extern double atof();
+#endif
+
+static void DviPageAction(/* Widget, XEvent*, String*, Cardinal* */);
+
+static XtActionsRec actions[] =
+{
+ /* {name, procedure}, */
+ {"dviPage", DviPageAction},
+};
+
+static char translations[] =
+ "<Key>: dviPage() \n\
+";
+
+DviPageClassRec dviPageClassRec = {
+ { /* core fields */
+ /* superclass */
+ (WidgetClass) &widgetClassRec,
+ /* class_name */ "DviPage",
+ /* widget_size */ sizeof(DviPageRec),
+ /* class_initialize */ ClassInitialize,
+ /* class_part_initialize */ NULL,
+ /* class_inited */ FALSE,
+ /* initialize */ Initialize,
+ /* initialize_hook */ NULL,
+ /* realize */ Realize,
+ /* actions */ actions,
+ /* num_actions */ XtNumber(actions),
+ /* resources */ resources,
+ /* num_resources */ XtNumber(resources),
+ /* xrm_class */ NULLQUARK,
+ /* compress_motion */ TRUE,
+ /* compress_exposure */ TRUE,
+ /* compress_enterleave */ TRUE,
+ /* visible_interest */ FALSE,
+ /* destroy */ Destroy,
+ /* resize */ NULL,
+ /* expose */ Redisplay,
+ /* set_values */ SetValues,
+ /* set_values_hook */ NULL,
+ /* set_values_almost */ XtInheritSetValuesAlmost,
+ /* get_values_hook */ NULL,
+ /* accept_focus */ NULL,
+ /* version */ XtVersion,
+ /* callback_private */ NULL,
+ /* tm_table */ translations,
+ /* query_geometry */ QueryGeometry,
+ /* display_accelerator */ XtInheritDisplayAccelerator,
+ /* extension */ NULL
+ },
+ { /* dviPage fields */
+ /* empty */ 0
+ }
+};
+
+WidgetClass dviPageWidgetClass = (WidgetClass)&dviPageClassRec;
+
+/****************************************************************
+ *
+ * Class Procedures
+ *
+ ****************************************************************/
+
+/* Sun cc complains about the following line, but I'll be damned if
+ I know why. It's decld a static void above */
+
+static void ClassInitialize()
+{
+ XtAddConverter( XtRString, XtRBackingStore, XmuCvtStringToBackingStore,
+ NULL, 0 );
+}
+
+/****************************************************************
+ *
+ * Private Procedures
+ *
+ ****************************************************************/
+
+static void DviPageAction(/* Widget, XEvent*, String*, Cardinal* */)
+{
+ fprintf(stderr,"EVENT\n");
+}
+
+void
+SetPageSize(w, wd, ht)
+DviPageWidget w;
+Dimension *wd;
+Dimension *ht;
+{
+ DviPagePart *pi = & (w -> dviPage);
+ struct PostAmbleInfo *pai = pi -> pai;
+
+ long bdr;
+
+ if ( pai != 0 ) {
+ int bdr;
+
+ CSetConversion(&(pi -> Conversion),
+ pi -> dpi,
+ pi -> userMag,
+ pai -> pai_Numerator,
+ pai -> pai_Denominator,
+ pai -> pai_DVIMag);
+ }
+ else {
+ long Numerator = 25400000;
+ long Denominator = 473628272;
+
+ CSetConversion(&(pi -> Conversion),
+ pi -> dpi,
+ pi -> userMag,
+ Numerator,
+ Denominator,
+ 1000);
+ }
+
+ w -> dviPage.fastFromSpValue
+ = (long) ( w -> dviPage.Conversion.c_tosp );
+
+ w -> dviPage.pixelsPerInch
+ = cfromSP(&(pi -> Conversion), SP_PER_INCH( POINTS_PER_INCH ));
+
+ bdr = w -> dviPage.pixelsPerInch;
+
+ w -> dviPage.texPicScale = pi -> userMag * bdr;
+
+ w -> dviPage.pixelsWide = bdr * w -> dviPage.paperWidth;
+ w -> dviPage.pixelsHigh = bdr * w -> dviPage.paperHeight;
+
+ (*wd) = w -> dviPage.pixelsWide;
+ (*ht) = w -> dviPage.pixelsHigh;
+}
+
+static void Initialize (request, new)
+ Widget request, new;
+{
+ DviPageWidget want = (DviPageWidget) request;
+ DviPageWidget w = (DviPageWidget) new;
+
+ XFontStruct *f;
+ int dir, as, ds;
+ XCharStruct os;
+
+ Dimension wd, ht;
+
+ w -> dviPage.page = want -> dviPage.page;
+ w -> dviPage.pai = want -> dviPage.pai ;
+ w -> dviPage.xFonts = want -> dviPage.xFonts ;
+ w -> dviPage.dviFonts = want -> dviPage.dviFonts ;
+
+ w -> dviPage.paperWidth = atof(want -> dviPage.paperWidthString);
+ w -> dviPage.paperHeight = atof(want -> dviPage.paperHeightString);
+
+ w -> dviPage.globalGC = 0;
+
+ w -> dviPage.dviStack = 0;
+ w -> dviPage.dviStackSize = 0;
+ w -> dviPage.pathLen = 0;
+ w -> dviPage.penSize = 1;
+ w -> dviPage.whiten = False;
+ w -> dviPage.shade = False;
+ w -> dviPage.blacken = False;
+
+ SetPageSize(w, &wd, &ht);
+
+#define MaX(x,y) ((x) > (y) ) ? (x) : (y)
+
+ w -> core.width = MaX(wd, want->core.width);
+ w -> core.height = MaX(ht, want->core.height);
+
+#undef MaX
+
+}
+
+static void Realize (gw, valueMask, attrs)
+ Widget gw;
+ XtValueMask *valueMask;
+ XSetWindowAttributes *attrs;
+{
+
+ XWindowAttributes wAttributes;
+
+ DviPageWidget w = (DviPageWidget) gw;
+
+ switch (w->dviPage.useBackingStore) {
+ case Always:
+ case NotUseful:
+ case WhenMapped:
+ *valueMask |=CWBackingStore;
+ attrs->backing_store = w->dviPage.useBackingStore;
+ break;
+ }
+
+ XtCreateWindow( w, InputOutput, (Visual *)CopyFromParent,
+ *valueMask, attrs);
+
+ XGetWindowAttributes( XtDisplay(w), XtWindow(w), &wAttributes );
+
+
+ w -> dviPage.haveBackingStore
+ = ( wAttributes.save_under == Always)
+ || (wAttributes.save_under == WhenMapped);
+
+ w->dviPage.globalGC
+ = XCreateGC( XtDisplay(w), XtWindow(w), 0, NULL);
+}
+
+static void Destroy (gw)
+ Widget gw;
+{
+ DviPageWidget w = (DviPageWidget) gw;
+ XtFree( w -> dviPage.dviStack );
+ w -> dviPage.dviStack = 0;
+
+ if ( w -> dviPage.globalGC ) {
+ XFreeGC( XtDisplay(w), w -> dviPage.globalGC );
+ w -> dviPage.globalGC = 0;
+ }
+}
+
+static Boolean SetValues(current, request, new)
+ DviPageWidget current, request, new;
+{
+
+ DviPagePart *pi = & (request -> dviPage);
+ struct PostAmbleInfo *p = pi -> pai;
+
+ new -> dviPage.page =
+ (request -> dviPage.page)
+ ? (request -> dviPage.page) : current -> dviPage.page ;
+
+ new -> dviPage.xFonts =
+ (request -> dviPage.xFonts)
+ ? (request -> dviPage.xFonts) : current -> dviPage.xFonts;;
+
+ new -> dviPage.pai =
+ (request -> dviPage.pai)
+ ? (request -> dviPage.pai) : current -> dviPage.pai;
+
+ if ( new -> dviPage.pai ) {
+
+ int stackSize = new -> dviPage.pai -> pai_DVIStackSize;
+
+ if (stackSize > new -> dviPage.dviStackSize ) {
+
+ stackSize += 2;
+
+ XtFree( new -> dviPage.dviStack );
+
+ new -> dviPage.dviStack = 0;
+ new -> dviPage.dviStackSize = stackSize;
+
+ if (stackSize > 0 ) {
+ new -> dviPage.dviStack =
+ (LocalDviStack *) (malloc( stackSize * sizeof(LocalDviStack) ));
+ }
+ }
+ }
+
+ new -> dviPage.dviFonts =
+ (request -> dviPage.dviFonts)
+ ? (request -> dviPage.dviFonts) : current -> dviPage.dviFonts;
+
+ new -> dviPage.paperWidth =
+ (request -> dviPage.paperWidthString)
+ ? atof(request -> dviPage.paperWidthString)
+ : current -> dviPage.paperWidth;
+
+ new -> dviPage.paperHeight =
+ (request -> dviPage.paperHeightString)
+ ? atof(request -> dviPage.paperHeightString)
+ : current -> dviPage.paperHeight;
+
+ SetPageSize(new, &(new -> core.width), &(new -> core.height));
+
+ return( True ); /* resize */
+}
+
+static XtGeometryResult QueryGeometry(w, intended, preferred)
+ Widget w;
+ XtWidgetGeometry *intended, *preferred;
+{
+ register DviPageWidget lw = (DviPageWidget) w;
+ Dimension wd, ht;
+
+ SetPageSize((DviPageWidget) w, &wd, &ht);
+
+ preferred -> request_mode = CWWidth | CWHeight;
+
+ preferred -> width = wd ;
+ preferred -> height = ht ;
+
+ if ( ((intended->request_mode & (CWWidth | CWHeight))
+ == (CWWidth | CWHeight)) &&
+ intended->width == preferred->width &&
+ intended->height == preferred->height)
+ return XtGeometryYes;
+ else if (preferred->width == w->core.width &&
+ preferred->height == w->core.height)
+ return XtGeometryNo;
+ else
+ return XtGeometryAlmost;
+}
+
+/*
+ * Some very DVI related things
+ */
+
+#define ABS(X) ( (X) < 0 ? -(X) : (X) )
+
+int
+selectFont(w, ptr, index, font)
+DviPageWidget w;
+DviFontInfo **ptr;
+int *index;
+int font;
+{
+ if ( *ptr != 0 && (*ptr) -> paf.paf_DVIFontIndex == font ) {
+ return 0;
+ }
+ else {
+ int offset;
+ DviFontInfo *fonts = w -> dviPage.dviFonts;
+
+ *ptr = 0;
+ for ( offset = 0; offset < RegisteredFonts; offset++ ) {
+ if ( fonts[offset].paf.paf_DVIFontIndex == font ) {
+ *ptr = &(fonts[offset]);
+ *index = offset;
+ break;
+ }
+ }
+
+ if ( *ptr == 0 ) {
+ error(0,0,"Can't find font %d", font);
+ return 1;
+ }
+ else {
+ return(0);
+ }
+ }
+}
+
+void DviDisplay(widget)
+ DviPageWidget widget;
+{
+ int c;
+ i32 p;
+ int advance;
+ int wuz;
+ int spDrift;
+
+ DviPagePart *page = &( widget -> dviPage);
+
+ struct PostAmbleInfo *pai = page -> pai;
+
+ char *thisPage = page -> page;
+ Conv *conv = &(page -> Conversion);
+
+ DviFontInfo *dviCurrentFont = 0;
+ int dviCurrentFontIndex = 0;
+
+/* following are used to reduce the number of XDrawStrings we do */
+
+#define MAX_DVI_STRING 64
+ char dviString[ MAX_DVI_STRING ];
+ int dviStringLength;
+ int startHH, startVV;
+ int endHH, endVV;
+
+ LocalDviStack *dviStack = page -> dviStack;
+ LocalDviStack *dviStackP; /* current stack item */
+
+ if ( pai == 0 || thisPage == 0 || dviStack == 0) {
+ return;
+ }
+
+ assert( dviStack != 0 );
+
+ dviStackP = dviStack;
+
+ dviStringLength = 0;
+ startHH = startVV = -1;
+ endHH = endVV = -1;
+
+ /* insure that first byte is a BOP mark */
+
+ c = (*thisPage) & 0xff;
+ if ( DVI_DT(c) != DT_BOP ) {
+ error(0,0,"No BOP found");
+ goto cleanup;
+ }
+
+ /* initialize spDrift to be a single pixel width */
+ spDrift = ctoSP( conv, POINTS_PER_INCH / DviDpi );
+
+ for(;;) {
+
+ c = mGetByte(&thisPage);
+
+ if (DVI_IsChar(c)) {
+
+ advance = 1;
+
+ doDviChar:
+ if ( !advance
+ || ABS(endHH - (dviStackP -> h)) > spDrift
+ || ABS(endVV - (dviStackP -> v)) > spDrift
+ || dviStringLength >= MAX_DVI_STRING )
+ {
+
+ if ( dviStringLength > 0 ) {
+ i32 atHH = fastFromSP(widget, startHH);
+ i32 atVV = fastFromSP(widget, startVV);
+ Bool doit = True;
+
+ if ( widget -> dviPage.haveBackingStore ) {
+ i32 width = fastFromSP(widget, endHH);
+ i32 height = fastFromSP(widget, endVV);
+
+ doit =
+ XRectInRegion( widget -> dviPage.updateRegion, atHH, atVV,
+ width, height) != RectangleOut;
+ }
+
+ if (doit) {
+ XDrawString( XtDisplay( widget ), XtWindow( widget ),
+ page -> globalGC, atHH, atVV,
+ dviString, dviStringLength );
+ }
+ }
+ dviStringLength = 0;
+ startHH = dviStackP -> h;
+ startVV = dviStackP -> v ;
+ }
+
+ dviString[ dviStringLength++ ] = c;
+
+ if ( advance && dviCurrentFont && dviCurrentFont -> widths) {
+ dviStackP -> h += (dviCurrentFont -> widths[ c ]) ;
+ }
+
+ endHH = dviStackP -> h;
+ endVV = dviStackP -> v;
+
+ } else {
+
+ switch (DVI_OpLen(c)) {
+
+ case DPL_NONE:
+ break;
+
+ case DPL_SGN1:
+ p = mGetByte(&thisPage);
+ p = Sign8(p);
+ break;
+
+ case DPL_SGN2:
+ mGetWord(&thisPage, &p);
+ p = Sign16(p);
+ break;
+
+ case DPL_SGN3:
+ mGet3Byte(&thisPage, &p);
+ p = Sign24(p);
+ break;
+
+ case DPL_SGN4:
+ mGetLong(&thisPage, &p);
+ break;
+
+ case DPL_UNS1:
+ p = UnSign8(mGetByte(&thisPage));
+ break;
+
+ case DPL_UNS2:
+ mGetWord(&thisPage, &p);
+ p = UnSign16(p);
+ break;
+
+ case DPL_UNS3:
+ mGet3Byte(&thisPage, &p);
+ p = UnSign24(p);
+ break;
+
+ default:
+ panic("DVI_OpLen(%d) = %d", c, DVI_OpLen(c));
+ goto cleanup;
+ /* NOTREACHED */
+ }
+
+ switch (DVI_DT(c)) {
+
+ case DT_SET:
+ c = p;
+ advance = 1;
+ goto doDviChar;
+ break;
+
+ case DT_PUT:
+ c = p;
+ advance = 0;
+ goto doDviChar;
+ break;;
+
+ case DT_SETRULE:
+ case DT_PUTRULE:
+
+ {
+ i32 cHH, cVV;
+ i32 rhh, rvv;
+
+ cHH = fastFromSP(widget, dviStackP -> h);
+ cVV = fastFromSP(widget, dviStackP -> v);
+
+ mGetLong(&thisPage, &rvv);
+ mGetLong(&thisPage, &rhh);
+
+ if (DVI_DT(c) == DT_SETRULE) {
+ dviStackP -> h += rhh;
+ }
+
+ rhh = CConvRule(conv, rhh);
+ rvv = CConvRule(conv, rvv);
+
+ XFillRectangle(XtDisplay(widget), XtWindow(widget),
+ page -> globalGC, cHH, cVV - rvv, rhh, rvv);
+
+ }
+ break;
+
+ case DT_NOP:
+ break;
+
+ case DT_BOP:
+ /*
+ * Each beginning of page has 11 4-byte words telling us things
+ * about the page. We ignore them.
+ */
+ thisPage += (11 * 4);
+
+ dviStackP = dviStack;
+
+ dviStackP -> h = SP_PER_INCH( POINTS_PER_INCH );
+ dviStackP -> v = SP_PER_INCH( POINTS_PER_INCH );
+ startHH = dviStackP -> h;
+ startVV = dviStackP -> v ;
+ endHH = startHH;
+ endVV = startVV;
+ dviStackP -> w = 0;
+ dviStackP -> x = 0;
+ dviStackP -> y = 0;
+ dviStackP -> z = 0;
+
+ break;
+
+ case DT_EOP:
+ goto cleanup;
+ /* NOTREACHED */
+
+ case DT_PUSH:
+ {
+ /* copy the old stack to the new one */
+
+ LocalDviStack *old = dviStackP;
+ dviStackP++;
+ *dviStackP = *old;
+ }
+ break;
+
+ case DT_POP:
+ /* just use the old stack */
+ dviStackP--;
+ break;
+
+ case DT_W0: /* there should be a way to make these pretty */
+ p = dviStackP -> w;
+ goto move_right;
+
+ case DT_W:
+ dviStackP -> w = p;
+ goto move_right;
+
+ case DT_X0:
+ p = dviStackP -> x;
+ goto move_right;
+
+ case DT_X:
+ dviStackP -> x = p;
+ goto move_right;
+
+ case DT_RIGHT:
+ move_right:
+ dviStackP -> h += p;
+ break;
+
+ case DT_Y0:
+ p = dviStackP -> y;
+ goto move_down;
+
+ case DT_Y:
+ dviStackP -> y = p;
+ goto move_down;
+
+ case DT_Z0:
+ p = dviStackP -> z;
+ goto move_down;
+
+ case DT_Z:
+ dviStackP -> z = p;
+ goto move_down;
+
+ case DT_DOWN:
+ move_down:
+ dviStackP -> v += p;
+ break;
+
+ case DT_FNTNUM:
+ case DT_FNT:
+ {
+ int font;
+
+ /* flush existing text */
+
+ if ( dviStringLength > 0 ) {
+ i32 atHH = fastFromSP(widget, startHH);
+ i32 atVV = fastFromSP(widget, startVV);
+ Bool doit = True;
+
+ if ( widget -> dviPage.haveBackingStore ) {
+ i32 width = fastFromSP(widget, endHH);
+ i32 height = fastFromSP(widget, endVV);
+
+ doit =
+ XRectInRegion( widget -> dviPage.updateRegion, atHH, atVV,
+ width, height) != RectangleOut;
+ }
+
+ if (doit) {
+ XDrawString( XtDisplay( widget ), XtWindow( widget ),
+ page -> globalGC, atHH, atVV,
+ dviString, dviStringLength );
+ }
+ dviStringLength = 0;
+ startHH = dviStackP -> h;
+ startVV = dviStackP -> v ;
+ }
+
+ /* switch to new font */
+
+ font = ( DVI_DT(c) == DT_FNTNUM )
+ ? font = (c - DVI_FNTNUM0) : p;
+
+ if ( selectFont(widget,
+ &dviCurrentFont, &dviCurrentFontIndex, font) ) {
+ goto cleanup;
+ }
+ else {
+ /* load the font */
+ XSetFont( XtDisplay(widget), widget -> dviPage.globalGC,
+ (widget -> dviPage.xFonts && widget -> dviPage.xFonts[ dviCurrentFontIndex ])
+ ? (widget->dviPage.xFonts[ dviCurrentFontIndex ]) -> fid
+ : widget -> dviPage.font->fid ) ;
+ }
+ }
+ break;
+
+ case DT_XXX:
+ {
+ char specialBuffer [2048];
+ register char *cp;
+ int sweetp = 0;
+
+ if (p > 2047) {
+ sweetp = p - 2047;
+ p = 2047;
+ }
+
+ for (cp = specialBuffer ; p > 0; p--) {
+ *cp = mGetByte(&thisPage);
+ cp++;
+ }
+ *(cp) = 0;
+
+ while(sweetp > 0) {
+ mGetByte(&thisPage);
+ }
+
+ widget -> dviPage.dviStackPointer = dviStackP;
+ doSpecial(widget, specialBuffer);
+ }
+ break;
+
+ case DT_FNTDEF:
+ {
+ int i;
+ long j;
+ mGetLong(&thisPage, &j);
+ mGetLong(&thisPage, &j);
+ mGetLong(&thisPage, &j);
+ i = UnSign8(mGetByte(&thisPage));
+ i += UnSign8(mGetByte(&thisPage));
+ while (--i >= 0) {
+ (void) mGetByte(&thisPage);
+ }
+ }
+ break;
+
+ case DT_PRE:
+ GripeUnexpectedOp("PRE");
+ goto cleanup;
+ /* NOTREACHED */
+
+ case DT_POST:
+ GripeUnexpectedOp("POST");
+ goto cleanup;
+ /* NOTREACHED */
+
+ case DT_POSTPOST:
+ GripeUnexpectedOp("POSTPOST");
+ goto cleanup;
+ /* NOTREACHED */
+
+ case DT_UNDEF:
+ GripeUndefinedOp(c);
+ goto cleanup;
+ /* NOTREACHED */
+
+ default:
+ panic("DVI_DT(%d) = %d", c, DVI_DT(c));
+ goto cleanup;
+ /* NOTREACHED */
+ }
+ }
+ }
+
+ cleanup:
+ /* clean up laststring if there was one */
+
+ if ( dviStringLength > 0 ) {
+ i32 atHH = fastFromSP(widget, startHH);
+ i32 atVV = fastFromSP(widget, startVV);
+ Bool doit = True;
+
+ if ( widget -> dviPage.haveBackingStore ) {
+ i32 width = fastFromSP(widget, endHH);
+ i32 height = fastFromSP(widget, endVV);
+
+ doit =
+ XRectInRegion( widget -> dviPage.updateRegion, atHH, atVV,
+ width, height) != RectangleOut;
+ }
+
+ if (doit) {
+ XDrawString( XtDisplay( widget ), XtWindow( widget ),
+ page -> globalGC, atHH, atVV,
+ dviString, dviStringLength );
+ }
+ dviStringLength = 0;
+ }
+
+ return;
+
+}
+
+
+/* ARGSUSED */
+static void Redisplay (gw, event, region)
+ Widget gw;
+ XEvent *event; /* unused */
+ Region region; /* unused */
+{
+ DviPageWidget w = (DviPageWidget) gw;
+
+ if (XtIsRealized(w)) {
+
+ XGCValues values;
+ unsigned long fore = w->dviPage.foreground;
+ unsigned long aft = w->dviPage.background;
+
+ if ( w -> dviPage.reverseVideo ) {
+ unsigned long tmp = aft;
+ aft = fore;
+ fore = tmp;
+ }
+
+ /* Prepare to clear the main screen */
+
+ values.function = GXcopy;
+ values.foreground = aft;
+ values.background = fore;
+
+ XChangeGC( XtDisplay(gw), w -> dviPage.globalGC,
+ (unsigned) GCFunction | GCForeground | GCBackground,
+ &values);
+
+ XSetRegion( XtDisplay(w), w -> dviPage.globalGC, region );
+
+ XFillRectangle(XtDisplay(w), XtWindow(w),
+ w -> dviPage.globalGC,
+ 0, 0,
+ w -> core.width, w -> core.height);
+
+ /* Prepare to paint */
+
+ values.foreground = fore;
+ values.background = aft;
+ values.plane_mask = AllPlanes;
+ values.font = w->dviPage.font->fid;
+
+ if ( aft ) {
+ values.function = GXand;
+ }
+ else {
+ values.function = GXor;
+ }
+
+ XChangeGC( XtDisplay(gw), w -> dviPage.globalGC,
+ (unsigned) GCFunction | GCPlaneMask |
+ GCForeground | GCBackground | GCFont,
+ &values);
+
+ XSetRegion( XtDisplay(w), w -> dviPage.globalGC, region );
+
+ if (w -> dviPage.pai && w -> dviPage.page && w -> dviPage.dviFonts ) {
+
+ w -> dviPage.updateRegion = region;
+
+ DviDisplay(w);
+
+ }
+ }
+}
diff --git a/dviware/umddvi/previewers/texx2/dvipage.h b/dviware/umddvi/previewers/texx2/dvipage.h
new file mode 100644
index 0000000000..643ed0a2a3
--- /dev/null
+++ b/dviware/umddvi/previewers/texx2/dvipage.h
@@ -0,0 +1,64 @@
+#include <X11/copyright.h>
+
+#ifndef _DviPage_h
+#define _DviPage_h
+
+/****************************************************************
+*
+* DviPage widget
+*
+****************************************************************/
+
+/* Resources:
+
+Name Class RepType Default Value
+---- ----- ------- -------------
+background Background Pixel XtDefaultBackground
+border BorderColor Pixel XtDefaultForeground
+borderWidth BorderWidth Dimension 1
+destroyCallback Callback Pointer NULL
+height Height Dimension 0
+mappedWhenManaged MappedWhenManaged Boolean True
+sensitive Sensitive Boolean True
+width Width Dimension 0
+x Position Position 0
+y Position Position 0
+
+*/
+
+#include <X11/Xmu.h>
+
+/* define any special resource names here that are not in <X11/StringDefs.h> */
+
+#define XtNbackingStore "backingStore"
+ /* when server should use backing store */
+
+#define XtNpage "page"
+#define XtNpai "pai"
+#define XtNuserMag "userMag"
+#define XtNdpi "dpi"
+#define XtNdviFonts "dviFonts"
+#define XtNxFonts "xFonts"
+#define XtNpaperWidth "paperWidth"
+#define XtNpaperHeight "paperHeight"
+
+#define XtCBackingStore "BackingStore"
+#define XtCPage "Page"
+#define XtCPai "Pai"
+#define XtCUserMag "UserMag"
+#define XtCDpi "Dpi"
+#define XtCDviFonts "DviFonts"
+#define XtCXFonts "XFonts"
+#define XtCPaperWidth "PaperWidth"
+#define XtCPaperHeight "PaperHeight"
+
+/* declare specific DviPageWidget class and instance datatypes */
+
+typedef struct _DviPageClassRec* DviPageWidgetClass;
+typedef struct _DviPageRec* DviPageWidget;
+
+/* declare the class constant */
+
+extern WidgetClass dviPageWidgetClass;
+
+#endif _DviPage_h
diff --git a/dviware/umddvi/previewers/texx2/dvipage2.c b/dviware/umddvi/previewers/texx2/dvipage2.c
new file mode 100644
index 0000000000..0eedd7acca
--- /dev/null
+++ b/dviware/umddvi/previewers/texx2/dvipage2.c
@@ -0,0 +1,522 @@
+/*
+ * This program is Copyright (C) 1987 by the Board of Trustees of the
+ * University of Illinois, and by the author Dirk Grunwald.
+ */
+
+/*
+ * Support drawing routines for TeXsun and TeX
+ *
+ * Copyright, (C) 1987, 1988 Tim Morgan, UC Irvine
+ *
+ * At the time these routines are called, the values of hh and vv should
+ * have been updated to the upper left corner of the graph (the position
+ * the \special appears at in the dvi file). Then the coordinates in the
+ * graphics commands are in terms of a virtual page with axes oriented the
+ * same as the Imagen and the SUN normally have:
+ *
+ * 0,0
+ * +-----------> +x
+ * |
+ * |
+ * |
+ * \ /
+ * +y
+ *
+ * Angles are measured in the conventional way, from +x towards +y.
+ * Unfortunately, that reverses the meaning of "counterclockwise"
+ * from what it's normally thought of.
+ *
+ * A lot of floating point arithmetic has been converted to integer
+ * arithmetic for speed. In some places, this is kind-of kludgy, but
+ * it's worth it.
+ */
+
+
+#include <X11/Xos.h>
+#include <X11/IntrinsicP.h>
+#include <X11/StringDefs.h>
+#include <stdio.h>
+#include "dvi-simple.h"
+#include "conv.h"
+#include <assert.h>
+
+#include "DviPageP.h"
+
+extern char *ProgName;
+
+#include <math.h>
+#include <stdio.h>
+#include <ctype.h>
+
+#define texPicConv(w,x) ( (x * w -> dviPage.pixelsPerInch) / 1000 )
+
+/*
+ * Draw a line from (fx,fy) to (tx,ty).
+ * Right now, we ignore pen_size.
+ */
+static void line_btw(w, fx, fy, tx, ty)
+ DviPageWidget w;
+ int fx, fy, tx, ty;
+{
+ int rx = fastFromSP(w, w -> dviPage.dviStackPointer -> h);
+ int ry = fastFromSP(w, w -> dviPage.dviStackPointer -> v);
+
+ fx = texPicConv(w, fx);
+ fy = texPicConv(w, fy);
+ tx = texPicConv(w, tx);
+ ty = texPicConv(w, ty);
+
+ if ( fx == tx && fy == ty ) {
+ fx += rx;
+ fy += ry;
+
+ if ( XPointInRegion(w -> dviPage.updateRegion, fx, ry) ) {
+ XDrawPoint(XtDisplay(w), XtWindow(w),
+ w -> dviPage.globalGC, fx, fy);
+ }
+ }
+ else {
+ XDrawLine(XtDisplay(w), XtWindow(w),
+ w -> dviPage.globalGC,
+ fx + rx, fy + ry, tx + rx, ty + ry);
+ }
+}
+
+/*
+ * Draw a dot at (x,y)
+ */
+static void dot_at(w, x, y)
+ DviPageWidget w;
+ int x;
+ int y;
+{
+ line_btw(w, x, y, x+1, y);
+}
+
+/*
+ * Apply the requested attributes to the last path (box) drawn.
+ * Attributes are reset.
+ */
+static void
+ do_attribute_path(w, last_min_x, last_max_x, last_min_y, last_max_y)
+DviPageWidget w;
+int last_min_x, last_max_x, last_min_y, last_max_y;
+{
+
+#ifdef UNDEF
+ /*
+ * This is the code as it appears in TeXsun. I dont have the time to
+ * make this do the shading in X-11. If someone does this, please post
+ * diffs to the net.
+ *
+ * Dirk Grunwald
+ */
+
+ static struct pixrect *shade_pr;
+
+ if (last_min_x < last_max_x && last_min_y < last_max_y) {
+ if (whiten) {
+ do_op(last_min_x, last_min_y,
+ xconv(last_max_x) - xconv(last_min_x),
+ yconv(last_max_y) - yconv(last_min_y),
+ PIX_SRC, (struct pixrect *) 0);
+ }
+ else if (blacken) {
+ do_op(last_min_x, last_min_y,
+ xconv(last_max_x) - xconv(last_min_x),
+ yconv(last_max_y) - yconv(last_min_y),
+ PIX_NOT(PIX_SRC), (struct pixrect *) 0);
+ }
+ else if (shade) {
+ if (!shade_pr) {
+ shade_pr = mem_create(3, 3, 1);
+ if (!shade_pr) Fatal("Out of memory -- cannot create pixrect");
+ pr_put(shade_pr, 0, 0, 1);
+ }
+ if (buildToPixmap) {
+ pr_replrop(pasteUpPixmap[currentShrink][currentLeaf],
+ xconv(last_min_x) + pen_size,
+ yconv(last_min_y) + pen_size,
+ xconv(last_max_x) - xconv(last_min_x) - pen_size,
+ yconv(last_max_y) - yconv(last_min_y) - pen_size,
+ PIX_SRC, shade_pr, 0, 0);
+ }
+ else {
+ int offset = currentLeaf*leaf_w[currentShrink]
+ pw_replrop(ptube,
+ xconv(last_min_x) + pen_size + offset,
+ yconv(last_min_y) + pen_size,
+ xconv(last_max_x) - xconv(last_min_x) - pen_size + offset,
+ yconv(last_max_y) - yconv(last_min_y) - pen_size,
+ PIX_SRC, shade_pr, 0, 0);
+ }
+ }
+ }
+ shade = blacken = whiten = FALSE;
+#endif
+}
+
+/*****************************************************************************/
+
+#define TWOPI (3.14159265359*2.0)
+#define MAX_PEN_SIZE 7 /* Max pixels of pen width */
+
+/* Unfortunately, these values also appear in dvisun.c */
+#define xRESOLUTION(w) ( w -> dviPage.pixelsPerInch )
+#define yRESOLUTION(w) ( w -> dviPage.pixelsPerInch )
+
+/*
+ * Set the size of the virtual pen used to draw in milli-inches
+ */
+
+/* ARGSUSED */
+static void set_pen_size(w, cp)
+ DviPageWidget w;
+ char *cp;
+{
+ int ps;
+
+ if (sscanf(cp, " %d ", &ps) != 1) {
+ error(0,0, "illegal .ps command format: %s", cp);
+ return;
+ }
+ w -> dviPage.penSize
+ = (ps*(xRESOLUTION(w)+yRESOLUTION(w)) + 1000) / 2000;
+ if (w -> dviPage.penSize < 1) {
+ w -> dviPage.penSize = 1;
+ }
+ else {
+ if (w -> dviPage.penSize > MAX_PEN_SIZE) {
+ w -> dviPage.penSize = MAX_PEN_SIZE;
+ }
+ }
+}
+
+
+/*
+ * Print the line defined by previous path commands
+ */
+static void flush_path(w)
+ DviPageWidget w;
+{
+ register int i;
+ int last_min_x, last_max_x, last_min_y, last_max_y;
+ int *xx = w -> dviPage.xx;
+ int *yy = w -> dviPage.yy;
+ int path_len = w -> dviPage.pathLen;
+
+ last_min_x = 30000; last_min_y = 30000;
+ last_max_x = -30000; last_max_y = -30000;
+ for (i=1; i< path_len; i++) {
+ if (xx[i] > last_max_x) last_max_x = xx[i];
+ if (xx[i] < last_min_x) last_min_x = xx[i];
+ if (yy[i] > last_max_y) last_max_y = yy[i];
+ if (yy[i] < last_min_y) last_min_y = yy[i];
+ line_btw(w, xx[i], yy[i], xx[i+1], yy[i+1]);
+ }
+ if (xx[path_len] > last_max_x) last_max_x = xx[path_len];
+ if (xx[path_len] < last_min_x) last_min_x = xx[path_len];
+ if (yy[path_len] > last_max_y) last_max_y = yy[path_len];
+ if (yy[path_len] < last_min_y) last_min_y = yy[path_len];
+
+ w -> dviPage.pathLen = 0;
+
+ do_attribute_path(w, last_min_x, last_max_x, last_min_y, last_max_y);
+}
+
+/*
+ * Print a dashed line along the previously defined path, with
+ * the dashes/inch defined.
+ */
+static void flush_dashed(w, cp, dotted)
+ DviPageWidget w;
+ char *cp;
+ int dotted;
+{
+ int i, numdots, x0, y0, x1, y1;
+ int cx0, cy0, cx1, cy1;
+ float inchesperdash;
+ double d, spacesize, a, b, dx, dy, milliperdash;
+
+ int *xx = w -> dviPage.xx;
+ int *yy = w -> dviPage.yy;
+ int path_len = w -> dviPage.pathLen;
+
+ if (sscanf(cp, " %f ", &inchesperdash) != 1) {
+ error(0,0,"illegal format for dotted/dashed line: %s", cp);
+ return;
+ }
+ if (path_len <= 1 || inchesperdash <= 0.0) {
+ error(0,0,"illegal conditions for dotted/dashed line");
+ return;
+ }
+ milliperdash = inchesperdash * 1000.0;
+ x0 = xx[1]; y0 = yy[1];
+ x1 = xx[2]; y1 = yy[2];
+ dx = x1 - x0;
+ dy = y1 - y0;
+ if (dotted) {
+ numdots = sqrt(dx*dx + dy*dy) / milliperdash + 0.5;
+ for (i=0; i <= numdots; i++) {
+ a = (float) i / (float) numdots;
+ cx0 = x0 + a*dx + 0.5;
+ cy0 = y0 + a*dy + 0.5;
+ dot_at(cx0, cy0);
+ }
+ }
+ else {
+ d = sqrt(dx*dx + dy*dy);
+ if (d <= 2.0*milliperdash)
+ line_btw(w, x0, y0, x1, y1);
+ else {
+ numdots = d / (2.0*milliperdash) + 1.0;
+ spacesize = (d - numdots * milliperdash) / (numdots - 1);
+ for (i=0; i<numdots-1; i++) {
+ a = i * (milliperdash + spacesize) / d;
+ b = a + milliperdash / d;
+ cx0 = x0 + a*dx + 0.5;
+ cy0 = y0 + a*dy + 0.5;
+ cx1 = x0 + b*dx + 0.5;
+ cy1 = y0 + b*dy + 0.5;
+ line_btw(w, cx0, cy0, cx1, cy1);
+ b += spacesize / d;
+ }
+ cx0 = x0 + b*dx + 0.5;
+ cy0 = y0 + b*dy + 0.5;
+ line_btw(w, cx0, cy0, x1, y1);
+ }
+ }
+
+ w -> dviPage.pathLen = 0;
+}
+
+
+/*
+ * Add a point to the current path
+ */
+static void add_path(w, cp)
+ DviPageWidget w;
+ char *cp;
+
+{
+ int pathx, pathy;
+
+ if (++( w -> dviPage.pathLen) >= MAXPOINTS) {
+ error(0,0, "Too many points");
+ return;
+ }
+ if (sscanf(cp, " %d %d ", &pathx, &pathy) != 2) {
+ error(0,0,"Malformed path command");
+ return;
+ }
+ w-> dviPage.xx[w -> dviPage.pathLen] = pathx;
+ w-> dviPage.yy[w -> dviPage.pathLen] = pathy;
+}
+
+/*
+ * Draw an arc
+ */
+static void arc(w, cp)
+ DviPageWidget w;
+ char *cp;
+{
+ int xc, yc, xrad, yrad, n;
+ float start_angle, end_angle;
+ int angS, angE;
+ Bool doit = True;
+
+ int rx = fastFromSP(w, w -> dviPage.dviStackPointer -> h);
+ int ry = fastFromSP(w, w -> dviPage.dviStackPointer -> v);
+
+ if (sscanf(cp, " %d %d %d %d %f %f ", &xc, &yc, &xrad, &yrad,
+ &start_angle, &end_angle) != 6) {
+ error(0,0,"illegal arc specification: %s", cp);
+ return;
+ }
+
+ xc = texPicConv(w, xc);
+ yc = texPicConv(w, yc);
+ xrad = texPicConv(w, xrad);
+ yrad = texPicConv(w, yrad);
+
+ angS = (int) ( (start_angle * 360 * 64) / TWOPI);
+ angE = (int) ( ((end_angle - start_angle) * 360 * 64) / TWOPI);
+
+ if ( w -> dviPage.haveBackingStore ) {
+ doit = XRectInRegion( w -> dviPage.updateRegion,
+ xc + rx - xrad, yc + ry - yrad,
+ 2 * xrad, 2 * yrad) != RectangleOut;
+ }
+
+ if (doit) {
+ XDrawArc(XtDisplay(w), XtWindow(w), w -> dviPage.globalGC,
+ xc + rx - xrad, yc + ry - yrad,
+ 2 * xrad, 2 * yrad, -angS, -angE);
+ }
+}
+
+
+/*
+ * APPROXIMATE integer distance between two points
+ */
+#define dist(x0, y0, x1, y1) (abs(x0-x1)+abs(y0-y1))
+
+/*
+ * Draw a spline along the previously defined path
+ */
+static void flush_spline(widget)
+ DviPageWidget widget;
+{
+ int xp, yp, N, lastx=(-1), lasty;
+ int t1, t2, t3, steps, j;
+ register int i, w;
+
+ int *xx = widget -> dviPage.xx;
+ int *yy = widget -> dviPage.yy;
+ int path_len = widget -> dviPage.pathLen;
+
+#ifdef lint
+ lasty = -1;
+#endif
+ N = path_len + 1;
+ xx[0] = xx[1]; yy[0] = yy[1];
+ xx[N] = xx[N-1]; yy[N] = yy[N-1];
+ for (i=0; i<N-1; i++) { /* interval */
+ steps = (dist(xx[i], yy[i], xx[i+1], yy[i+1]) +
+ dist(xx[i+1], yy[i+1], xx[i+2], yy[i+2])) / 80;
+ for (j=0; j<steps; j++) { /* points within */
+ w = (j*1000 + 500) / steps;
+ t1 = w * w / 20;
+ w -= 500;
+ t2 = (750000 - w * w) / 10;
+ w -= 500;
+ t3 = w * w / 20;
+ xp = (t1*xx[i+2] + t2*xx[i+1] + t3*xx[i] + 50000) / 100000;
+ yp = (t1*yy[i+2] + t2*yy[i+1] + t3*yy[i] + 50000) / 100000;
+ if (lastx > -1) line_btw(widget, lastx, lasty, xp, yp);
+ lastx = xp;
+ lasty = yp;
+ }
+ }
+
+ widget -> dviPage.pathLen = 0;
+}
+
+
+/*
+ * Shade the last box, circle, or ellipse
+ */
+static void shade_last(w)
+ DviPageWidget w;
+{
+ w -> dviPage.blacken = False;
+ w -> dviPage.whiten = False;
+ w -> dviPage.shade = True;
+}
+
+
+/*
+ * Make the last box, circle, or ellipse, white inside (shade with white)
+ */
+static void whiten_last(w)
+ DviPageWidget w;
+{
+ w -> dviPage.blacken = False;
+ w -> dviPage.whiten = True;
+ w -> dviPage.shade = False;
+}
+
+
+/*
+ * Make last box, etc, black inside
+ */
+static void blacken_last(w)
+ DviPageWidget w;
+{
+ w -> dviPage.blacken = True;
+ w -> dviPage.whiten = False;
+ w -> dviPage.shade = False;
+}
+
+/*
+ * Draw the bounding box for a \psfig special.
+ *
+ * expected format of the command string is
+ *
+ * width height bbllx bblly bburx bbury
+ *
+ * *ll* means lower-left, *ur* means upper-right.
+ *
+ * We just draw the bounding box.
+ */
+psfigBegin(w,cp)
+DviPageWidget w;
+char *cp;
+{
+ int bbllx, bblly;
+ int bburx, bbury;
+ int width, height;
+
+ int rx = fastFromSP(w, w -> dviPage.dviStackPointer -> h);
+ int ry = fastFromSP(w, w -> dviPage.dviStackPointer -> v);
+
+ sscanf(cp, " %d %d %d %d %d %d ",
+ &width, &height,
+ &bbllx, &bblly, &bburx, &bbury);
+
+ width = fastFromSP(w, width);
+ height = fastFromSP(w, height);
+
+ XDrawLine(XtDisplay(w), XtWindow(w),
+ w -> dviPage.globalGC,
+ rx, ry, rx + width, ry );
+ XDrawLine(XtDisplay(w), XtWindow(w),
+ w -> dviPage.globalGC,
+ rx + width, ry, rx + width, ry + height);
+ XDrawLine(XtDisplay(w), XtWindow(w),
+ w -> dviPage.globalGC,
+ rx + width, ry + height, rx, ry + height);
+ XDrawLine(XtDisplay(w), XtWindow(w),
+ w -> dviPage.globalGC,
+ rx, ry + height, rx, ry);
+}
+
+/*****************************************************************************/
+
+/*
+ * The code to handle the \specials generated by tpic was modified
+ * by Dirk Grunwald using the code Tim Morgan at Univ. of Calif, Irvine
+ * wrote for TeXsun.
+ */
+
+#define COMLEN 64
+
+void doSpecial(w, cp)
+ DviPageWidget w;
+ char *cp;
+{
+ char command[COMLEN], *orig_cp;
+ register int len;
+
+ orig_cp = cp;
+ while (isspace(*cp)) ++cp;
+ len = 0;
+ while (!isspace(*cp) && *cp && len < COMLEN-1) command[len++] = *cp++;
+ command[len] = '\0';
+ if (strcmp(command, "pn") == 0) set_pen_size(w,cp);
+ else if (strcmp(command, "fp") == 0) flush_path(w);
+ else if (strcmp(command, "da") == 0) flush_dashed(w, cp, 0);
+ else if (strcmp(command, "dt") == 0) flush_dashed(w, cp, 1);
+ else if (strcmp(command, "pa") == 0) add_path(w, cp);
+ else if (strcmp(command, "ar") == 0) arc(w, cp);
+ else if (strcmp(command, "sp") == 0) flush_spline(w);
+ else if (strcmp(command, "sh") == 0) shade_last(w);
+ else if (strcmp(command, "wh") == 0) whiten_last(w);
+ else if (strcmp(command, "bk") == 0) blacken_last(w);
+ else if (strcmp(command, "ps::[begin]") == 0) psfigBegin(w, cp);
+ else if (strncmp(command, "ps:",3) == 0) /* do nothing */;
+ else if (strncmp(command, "ln03", 4) == 0) /* do nothing */;
+ else {
+ error(0,0, "special \"%s\" not implemented", orig_cp);
+ }
+}
diff --git a/dviware/umddvi/previewers/texx2/dvipagep.h b/dviware/umddvi/previewers/texx2/dvipagep.h
new file mode 100644
index 0000000000..c81d078bf2
--- /dev/null
+++ b/dviware/umddvi/previewers/texx2/dvipagep.h
@@ -0,0 +1,106 @@
+#include <X11/copyright.h>
+
+/* $XConsortium: DviPageP.h,v 1.2 88/10/25 17:37:59 swick Exp $ */
+/* Copyright Massachusetts Institute of Technology 1987, 1988 */
+
+#ifndef _DviPageP_h
+#define _DviPageP_h
+
+#include "DviPage.h"
+/* include superclass private header file */
+
+#include <X11/CoreP.h>
+
+typedef struct {
+ int empty;
+} DviPageClassPart;
+
+typedef struct _DviPageClassRec {
+ CoreClassPart core_class;
+ DviPageClassPart dviPage_class;
+} DviPageClassRec;
+
+extern DviPageClassRec dviPageClassRec;
+
+typedef struct {
+ i32 stack_hh;
+ i32 stack_vv;
+ i32 h; /* the saved h */
+ i32 v; /* the saved v */
+ i32 w; /* etc */
+ i32 x;
+ i32 y;
+ i32 z;
+} LocalDviStack;
+
+typedef struct {
+ Pixel background;
+ Pixel foreground;
+
+ int useBackingStore; /* backing store type */
+ Bool haveBackingStore;
+
+ Bool reverseVideo;
+
+ XFontStruct *font;
+
+ /* private state */
+
+ GC globalGC;
+
+ char *page;
+ Dimension pixelsWide;
+ Dimension pixelsHigh;
+ Dimension pixelsPerInch;
+
+ char *paperWidthString;
+ char *paperHeightString;
+ float paperWidth;
+ float paperHeight;
+
+ XFontStruct **xFonts;
+
+ struct PostAmbleInfo *pai;
+ DviFontInfo *dviFonts;
+
+ int userMag;
+ int dpi;
+
+ Conv Conversion;
+ int fastFromSpValue;
+
+ Region updateRegion;
+
+ LocalDviStack *dviStack;
+ LocalDviStack *dviStackPointer;
+ int dviStackSize;
+
+ /* for tpic specials */
+#define MAXPOINTS 300 /* Max points in a path */
+ int texPicScale;
+ int xx[MAXPOINTS];
+ int yy[MAXPOINTS];
+ int pathLen;
+ int penSize;
+ Bool whiten;
+ Bool shade;
+ Bool blacken;
+} DviPagePart;
+
+typedef struct _DviPageRec {
+ CorePart core;
+ DviPagePart dviPage;
+} DviPageRec;
+
+#ifdef __STDC__
+static inline long fastFromSP(DviPageWidget w, long x)
+{
+ return( x / ( w -> dviPage.fastFromSpValue ) );
+}
+#else
+
+#define fastFromSP(w, x) ((x) / (w -> dviPage.fastFromSpValue))
+
+#endif
+
+#endif _DviPageP_h
diff --git a/dviware/umddvi/previewers/texx2/fonts b/dviware/umddvi/previewers/texx2/fonts
new file mode 100644
index 0000000000..d28d720595
--- /dev/null
+++ b/dviware/umddvi/previewers/texx2/fonts
@@ -0,0 +1,9 @@
+-scaled 1000
+cmr10 cmex10 cmr17 cmbx12 cmr12 cmtt10 cmbx10 cmti10 cmsy10 cmmi10
+cmbx9 cmsy9 cmmi9 cmr9 cmbx8 cmti8 cmti12 cmsy8 cmmi8 cmr8 cmsy7 cmmi7
+cmr7 cmsy6 cmmi6 cmr6 cmsy5 cmmi5 cmr5 cmsl10 lasy10 cmcsc12 cmbx14
+cmr14 cmr25
+-scaled 1200 cmbx17
+-scaled 1440 cmbx10 cmr10
+-scaled 1728 cmcsc10 cmti10
+-scaled 1200 cmcsc10
diff --git a/dviware/umddvi/previewers/texx2/fonts.distrib b/dviware/umddvi/previewers/texx2/fonts.distrib
new file mode 100644
index 0000000000..d28d720595
--- /dev/null
+++ b/dviware/umddvi/previewers/texx2/fonts.distrib
@@ -0,0 +1,9 @@
+-scaled 1000
+cmr10 cmex10 cmr17 cmbx12 cmr12 cmtt10 cmbx10 cmti10 cmsy10 cmmi10
+cmbx9 cmsy9 cmmi9 cmr9 cmbx8 cmti8 cmti12 cmsy8 cmmi8 cmr8 cmsy7 cmmi7
+cmr7 cmsy6 cmmi6 cmr6 cmsy5 cmmi5 cmr5 cmsl10 lasy10 cmcsc12 cmbx14
+cmr14 cmr25
+-scaled 1200 cmbx17
+-scaled 1440 cmbx10 cmr10
+-scaled 1728 cmcsc10 cmti10
+-scaled 1200 cmcsc10
diff --git a/dviware/umddvi/previewers/texx2/imakefile b/dviware/umddvi/previewers/texx2/imakefile
new file mode 100644
index 0000000000..465c122147
--- /dev/null
+++ b/dviware/umddvi/previewers/texx2/imakefile
@@ -0,0 +1,23 @@
+ DEFINES = -DDEFAULT_TFM_PATH=\".:/usr/local/lib/tex82/fonts\"
+
+ SRCS1 = texx2.c texx2-widgets.c \
+ texx2-file.c texx2-error.c dvi-simple.c \
+ texx2-page.c texx2-font.c texx2-mark.c \
+ DviPage.c DviPage2.c
+ OBJS1 = texx2.o texx2-widgets.o \
+ texx2-file.o texx2-error.o dvi-simple.o \
+ texx2-page.o texx2-font.o texx2-mark.o \
+ DviPage.o DviPage2.o
+ SRCS2 = mftobdf.c
+ OBJS2 = mftobdf.o
+ PROGRAMS = mftobdf texx2
+ INCLUDES = -I../h
+
+SYS_LIBRARIES = -lXaw -lXt -lXmu -lX11
+
+SingleProgramTarget(texx2,$(OBJS1),../lib/lib.a,-lm)
+InstallProgram(texx2, $(BINDIR))
+InstallManPage(texx2, $(MANDIR))
+
+SingleProgramTarget(mftobdf,$(OBJS2),../lib/lib.a,-lm)
+InstallProgram(mftobdf, $(BINDIR) )
diff --git a/dviware/umddvi/previewers/texx2/makefile b/dviware/umddvi/previewers/texx2/makefile
new file mode 100644
index 0000000000..55edaf18d0
--- /dev/null
+++ b/dviware/umddvi/previewers/texx2/makefile
@@ -0,0 +1,26 @@
+CC=gcc
+SRCS1 = texx2.c texx2-widgets.c \
+ texx2-file.c texx2-error.c dvi-simple.c \
+ texx2-page.c texx2-font.c texx2-mark.c \
+ DviPage.c DviPage2.c
+OBJS1 = texx2.o texx2-widgets.o \
+ texx2-file.o texx2-error.o dvi-simple.o \
+ texx2-page.o texx2-font.o texx2-mark.o \
+ DviPage.o DviPage2.o
+SRCS2 = mftobdf.c
+OBJS2 = mftobdf.o
+PROGRAMS = mftobdf texx2
+INCLUDES = -I../h -I~x/include
+SYS_LIBRARIES = -lXaw -lXt -lXmu -lX11
+FONTDESC =/u/tex/config/fontdesc
+
+.c.o:
+ $(CC) -c $< -DTEXFONTS=\".:/u/tex/mftfm:/u/tex/psftm\" $(INCLUDES)
+
+all: texx2 mftobdf
+
+texx2: $(OBJS1)
+ $(CC) -o texx2 $(OBJS1) $(SYS_LIBRARIES) ../lib/lib.a -lm
+
+mftobdf: $(OBJS2)
+ $(CC) -o mftobdf $(OBJS2) ../lib/lib.a -lm
diff --git a/dviware/umddvi/previewers/texx2/manifest b/dviware/umddvi/previewers/texx2/manifest
new file mode 100644
index 0000000000..b98eec15ab
--- /dev/null
+++ b/dviware/umddvi/previewers/texx2/manifest
@@ -0,0 +1,33 @@
+total 264
+-rw-r----- 1 tex 2112 Apr 3 17:49 00readme.tex
+-rw-r----- 1 tex 4097 Mar 17 22:58 ChangeLog
+-rw-r----- 1 tex 2309 Mar 28 11:01 Description
+-rw-r----- 1 tex 20508 Feb 26 02:11 DviPage.c
+-rw-r----- 1 tex 1671 Feb 17 18:03 DviPage.h
+-rw-r----- 1 tex 13451 Feb 25 21:11 DviPage2.c
+-rw-r----- 1 tex 1942 Feb 24 20:49 DviPageP.h
+-rw-r----- 1 tex 326 Mar 28 11:38 FONTS
+-rw-r----- 1 tex 326 Mar 28 12:41 FONTS.distrib
+-rw-r----- 1 tex 840 Mar 15 16:23 Imakefile
+-rw-r----- 1 tex 0 May 14 15:55 MANIFEST
+-rw-r----- 1 tex 790 Mar 30 12:35 Makefile
+-rw-r----- 1 tex 1964 Mar 2 02:07 README
+-rwxr-x--- 1 tex 276 Mar 28 13:02 buildfonts
+-rw-r----- 1 tex 10626 Mar 30 12:36 dvi-simple.c
+-rw-r----- 1 tex 1831 Feb 15 22:33 dvi-simple.h
+-rwxr-x--x 1 tex 114688 Mar 30 12:37 mftobdf
+-rw-r----- 1 tex 13450 Mar 28 13:37 mftobdf.c
+-rw-r----- 1 tex 1175 Feb 15 22:33 mio.h
+-rw-r----- 1 tex 117 Feb 15 22:33 texx2-defs.h
+-rw-r----- 1 tex 4485 Mar 17 22:58 texx2-error.c
+-rw-r----- 1 tex 8720 Mar 1 00:47 texx2-file.c
+-rw-r----- 1 tex 2750 Mar 1 01:04 texx2-font.c
+-rw-r----- 1 tex 172 Feb 17 18:02 texx2-font.h
+-rw-r----- 1 tex 2938 Mar 28 12:57 texx2-mark.c
+-rw-r----- 1 tex 559 Feb 15 22:33 texx2-mark.h
+-rw-r----- 1 tex 20912 Mar 1 00:19 texx2-page.c
+-rw-r----- 1 tex 1467 Feb 26 22:25 texx2-page.h
+-rw-r----- 1 tex 5718 Feb 24 20:15 texx2-widgets.c
+-rw-r----- 1 tex 742 Feb 19 20:47 texx2-widgets.h
+-rw-r----- 1 tex 2511 Mar 28 12:57 texx2.c
+-rw-r----- 1 tex 1040 Mar 1 00:18 texx2.h
diff --git a/dviware/umddvi/previewers/texx2/mftobdf.c b/dviware/umddvi/previewers/texx2/mftobdf.c
new file mode 100644
index 0000000000..ea179ee2f5
--- /dev/null
+++ b/dviware/umddvi/previewers/texx2/mftobdf.c
@@ -0,0 +1,600 @@
+/*
+ * This program is Copyright (C) 1987 by the Board of Trustees of the
+ * University of Illinois, and by the author Dirk Grunwald.
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <ctype.h>
+
+#include "../h/types.h"
+#include "../h/font.h"
+
+#include "../h/conv.h"
+#include "../h/dvi.h"
+#include "../h/dviclass.h"
+#include "../h/dvicodes.h"
+#include "../h/postamble.h"
+#include "../h/search.h"
+#include "../h/fio.h"
+
+/* X11 related files */
+
+int DviBlackness = -1;
+int DviDpi = 300;
+int DviMag = 1000;
+int DviDsz = 1000;
+char *ProgName;
+int ShowSnf = 0;
+int UserMag = 1000;
+
+long Numerator = 25400000;
+long Denomonator = 473628272;
+
+Conv Conversion;
+float DviFontTfmScale;
+
+#define GF_SHRUNK GF_USR0
+#define GLYPH_SHRUNK(g) ((g) -> g_flags & GF_SHRUNK)
+#define SHRUNK_GLYPH_BYTES_WIDE(g) ((((g) -> g_width + 15) >> 4) * 2)
+#define DEFAULT_BLACKNESS 3
+
+#define TWOTO16 0x10000
+#define TWOTO24 16777216
+#define PTPI 72.27
+
+main(argc, argv)
+int argc;
+char **argv;
+{
+ char *name = 0;
+ char *dev = "canon";
+ char *fname = 0;
+ int arg;
+ extern void processFont();
+
+ struct font *theFont;
+
+ ProgName = argv[0];
+
+ for (arg = 1; arg < argc; arg++) {
+ char *str = argv[arg];
+ if ( strcmp(str, "-scaled") == 0 ) {
+ arg++;
+ DviMag = atoi( argv[arg] );
+ }
+ else if ( strcmp(str, "-dpi") == 0 ) {
+ arg++;
+ DviDpi = atoi( argv[arg] );
+ }
+ else if ( strcmp(str, "-size") == 0 ) {
+ arg++;
+ DviDsz = atoi( argv[arg] );
+ }
+ else if ( strcmp(str, "-dev") == 0 ) {
+ arg++;
+ dev = argv[arg];
+ }
+ else if ( strcmp(str, "-show") == 0 ) {
+ ShowSnf = !ShowSnf;
+ }
+ else if ( strcmp(str, "-mag") == 0 ) {
+ arg++;
+ UserMag = atoi(argv[arg]);
+ }
+ else if ( strcmp(str, "-b") == 0 ) {
+ arg++;
+ DviBlackness = atoi(argv[arg]);
+ }
+ else if ( str[0] != '-' ) {
+ name = argv[arg];
+
+ if ( name == 0 ) {
+ fprintf(stderr,"%s: you must specify a font name\n", ProgName);
+ exit(1);
+ }
+
+/* We read the font in at mag and then step it down to user mag, so
+ assume here that usermag is 1000 */
+
+ SetConversion(DviDpi, 1000, Numerator, Denomonator, 1000);
+
+ theFont = GetFont(name, DviMag, DviDsz, dev, &fname);
+ if ( theFont == 0 ) {
+ fprintf(stderr,"Unable to locate ``%s''\n", name);
+ continue;
+ }
+
+ if ( fname != 0 ) {
+ fprintf(stderr,"%s: returned name is %s\n", ProgName, fname);
+ fprintf(stderr,"%s: which lives in %s\n",
+ ProgName, theFont -> f_path);
+ }
+
+/* DviFontTfmScale = fromSP( theFont -> f_design_size); */
+ DviFontTfmScale = ((double)theFont -> f_design_size);
+ DviFontTfmScale *= 1000;
+ DviFontTfmScale /= (double) TWOTO24;
+
+ processFont( theFont, name );
+
+ }
+ else {
+ fprintf(stderr,"%s: don't grok ``%s''\n", ProgName, argv[arg]);
+ exit(1);
+ }
+ }
+ exit(0);
+}
+
+/*
+ * The following routine is used to shrink a glyph by some
+ * shrink factor (in the width & height dimension).
+ *
+ * These shrunken glyphs are more appropriate for previewers.
+ *
+ * To do this, we simple scan the original raster, counting the
+ * number of pixels within a given area. If the number of on pixels is
+ * at least twice the total number of pixels, we turn the pixel in
+ * the shrunken glyph ON, else OFF.
+ *
+ * We use a lookup table to hasten the process of counting pixels.
+ *
+ * The method used should be independent of byte-order (I think).
+ *
+ * You need to define two types. One should be 32-bits long, and
+ * the other 16 bits long.
+ */
+
+typedef unsigned char BITS_8;
+typedef unsigned short BITS_16;
+typedef unsigned long BITS_32;
+
+#define LOOKUP_BYTES 256
+#define LOOKUP_BITS 8
+#define LOOKUP_MASK 0xff
+
+static char dviLookUpTable[LOOKUP_BYTES];
+static char tableNotInitialized = 1;
+
+struct glyph *
+dviShrinkGlyph(gly, font, rotation,shrinkH, shrinkW, blackness, killOld)
+struct glyph *gly;
+struct font *font;
+int rotation;
+int shrinkH;
+int shrinkW;
+int blackness;
+int killOld;
+{
+ int shrunkHeight;
+ int shrunkWidth;
+ int glyphWide;
+ int glyphHigh;
+ int glyphAdvance;
+ int shrunkAdvance;
+
+ int bytesWide;
+ int shrunkBytesWide;
+
+ struct glyph *ngly;
+
+ BITS_16 *shrunkRaster;
+ int rasterSize;
+
+ long width;
+ long dvimag;
+
+ int x,y;
+ BITS_8 *cp;
+ BITS_8 *ptr;
+
+ BITS_32 shrinkMask;
+
+ int sampleSize;
+
+ if (gly == 0 || !HASRASTER(gly) || (gly -> g_width < 0) ) {
+ return(0);
+ }
+
+ if (gly -> g_raster == 0) {
+ gly-> g_raster = RASTER(gly, font, rotation);
+ }
+
+#ifdef UNDEF
+ if ( shrinkH == 1 ) {
+ return( gly );
+ }
+#endif
+
+/*
+ * Initialize the lookup table of the number of bits in a given byte
+ */
+
+ if (tableNotInitialized) {
+ register int i;
+ register int j;
+ register int k;
+ register int acc;
+ for (i = 0; i < LOOKUP_BYTES; i++) {
+ j = i;
+ acc = 0;
+ for (k = 0; j != 0 && k < LOOKUP_BITS ; k++) {
+ acc += (j & 1);
+ j >>= 1;
+ }
+ dviLookUpTable[i] = acc;
+ }
+ tableNotInitialized = 0;
+ }
+
+ glyphHigh = gly -> g_height;
+ glyphWide = gly -> g_width;
+
+/*
+ * The following computes the ``escapement'' or the TFMwidth in
+ * pixels. This converted to the DWIDTH in the bdf files.
+ *
+ * This is a screwy point with Toreks library. He changes
+ * the values of the design_size
+ *
+ */
+ dvimag = font -> f_design_size / 16;
+ dvimag *= font -> f_scaled;
+ dvimag /= 1000;
+ width = ScaleOneWidth( gly -> g_rawtfmwidth, dvimag);
+ gly -> g_pixwidth = fromSP( width );
+ glyphAdvance = (gly -> g_pixwidth);
+
+ shrunkHeight = (glyphHigh + shrinkH - 1) / shrinkH;
+ shrunkWidth = (glyphWide + shrinkW - 1) / shrinkW;
+ shrunkAdvance = (glyphAdvance + shrinkW - 1) / shrinkW;
+
+ bytesWide = (gly -> g_width + 7) >> 3;
+
+ shrunkBytesWide = ((shrunkWidth + 7) >> 3);
+
+ rasterSize = (shrunkHeight + 1) * shrunkBytesWide;
+ shrunkRaster = (BITS_16 *) malloc(rasterSize);
+ bzero(shrunkRaster, rasterSize);
+ ptr = (BITS_8 *) shrunkRaster;
+
+ if (shrunkRaster == NULL) {
+ fprintf(stderr, "Out of memory!\n");
+ exit(1);
+ }
+
+ for (y = 0; y < glyphHigh; y+= shrinkH) {
+ cp = (BITS_8 *) ptr;
+ shrinkMask = 0x80;
+ for (x = 0; x < glyphWide; x += shrinkW) {
+ int i;
+ int samples;
+ BITS_8 *baseP;
+ int upper;
+ register int thisShrinkW;
+
+ baseP = (BITS_8 *) gly -> g_raster + (y * bytesWide);
+
+/*
+ * Set the upper limit on the height iteration so we dont count
+ * off the end of the raster
+ */
+
+ upper = y + shrinkH;
+ if (upper > glyphHigh) {
+ upper = glyphHigh;
+ }
+
+ if (x + shrinkW > glyphWide) {
+ thisShrinkW = glyphWide - x;
+ } else {
+ thisShrinkW = shrinkW;
+ }
+
+ samples = 0;
+ sampleSize = thisShrinkW * shrinkH;
+
+ for (i = y; i < upper; i++) {
+ register int acc;
+ register BITS_8 *p;
+ register BITS_8 *ep;
+/*
+ * Determine how many bytes our shrink window crosses (we might
+ * overlap on byte-edges)
+ */
+
+ p = baseP + (x >> 3);
+ ep = baseP + ( (x + thisShrinkW - 1) >> 3);
+ baseP += bytesWide;
+
+/*
+ * stuff everything in the accumulator
+ */
+
+ acc = 0;
+ while (p <= ep) {
+ acc = ((acc << 8) & 0xff) | *p;
+ p++;
+ }
+
+/*
+ * clean off the right hand-side of extra bits, then clean off
+ * the left hand side of extra bits, and then count them.
+ */
+
+ acc = acc >> ( 7 - ((x + thisShrinkW - 1) & 0x7));
+ acc &= ~(-1 << thisShrinkW);
+ while (acc != 0) {
+ samples += dviLookUpTable[ acc & LOOKUP_MASK ];
+ acc >>= LOOKUP_BITS;
+ }
+ }
+/*
+ * If at least 1/blackness of the bits are on, treat this entire sample as
+ * being on.
+ */
+
+ if ((samples * blackness) >= sampleSize) {
+ *ptr |= shrinkMask;
+ } else {
+ *ptr &= ~ shrinkMask;
+ }
+ shrinkMask >>= 1;
+ if (shrinkMask == 0) {
+ shrinkMask = 0x80;
+ ptr ++;
+ }
+ }
+ ptr = (BITS_8 *) (cp + shrunkBytesWide);
+ }
+
+/*
+ * Build a new glyph from the shrunken raster
+ */
+
+ if (ShowSnf) {
+ printf("Old glyph:\n");
+ seeGlyph(gly -> g_raster, glyphHigh, bytesWide);
+ printf("New glyph:\n");
+ seeGlyph(shrunkRaster, shrunkHeight, shrunkBytesWide);
+ }
+
+ ngly = (struct glyph *) malloc(sizeof(struct glyph));
+ bzero(ngly, sizeof(struct glyph));
+
+ ngly -> g_raster = (char * ) shrunkRaster;
+ ngly -> g_un.g_integer = shrunkBytesWide;
+ ngly -> g_width = shrunkWidth;
+ ngly -> g_pixwidth = shrunkAdvance;
+ ngly -> g_height = shrunkHeight;
+
+ ngly -> g_xorigin = gly -> g_xorigin / shrinkH;
+ ngly -> g_yorigin = gly -> g_yorigin / shrinkW;
+
+ ngly -> g_flags |= GF_SHRUNK; /* yes, its been shrunk */
+
+ if ( killOld && gly -> g_raster ) {
+ free ( gly -> g_raster );
+ gly -> g_raster = 0;
+ }
+
+ return(ngly);
+}
+
+seeGlyph(c, h, w)
+char *c;
+int h;
+int w;
+{
+ int i,j;
+
+ for (i = 0; i < h; i++ ) {
+ for (j = 0; j < w; j++) {
+ int k;
+ register int ch;
+ register int m;
+ char str[9];
+
+ ch = *(c++);
+ m = 0x80;
+ for (k = 0; k < 8; k++) {
+ str[k] = ( (ch & m) ? '#' : '-' );
+ m >>= 1;
+ }
+ str[8] = 0;
+ printf("%s", str);
+ }
+ printf("\n");
+ }
+}
+
+printhex(f,n)
+FILE *f;
+int n;
+{
+ fputc("0123456789abcdef"[(n >> 4) & 0xf], f);
+ fputc("0123456789abcdef"[n & 0xf], f);
+}
+
+/* SNF related junk */
+
+void
+processFont(f, name)
+struct font *f;
+char *name;
+{
+ struct glyph *g;
+ int c;
+ int blackness;
+
+ int maxOverlap;
+ int nnonexistchars;
+
+#define MAX_CHARACTER 127
+
+ int glyphBytes[ MAX_CHARACTER + 1];
+ struct glyph *shrunkGlyphs[ MAX_CHARACTER + 1];
+
+ int totalGlyphs;
+ int pointSize;
+ int shrink;
+
+ int min_width = TWOTO16;
+ int max_width = -TWOTO16;
+
+ int min_height = TWOTO16;
+ int max_height = -TWOTO16;
+
+ int min_xorigin = TWOTO16;
+ int max_xorigin = -TWOTO16;
+
+ int min_yorigin = TWOTO16;
+ int max_yorigin = -TWOTO16;
+
+#define MIN(x,y) ((x < y) ? (x) : (y))
+#define MAX(x,y) ((x < y) ? (y) : (x))
+
+#ifdef __STDC__
+#define MINMAX(x,y) { min_##x = MIN(min_##x,y); max_##x = MAX(max_##x,y); }
+#else
+#define MINMAX(x,y) { min_/**/x = MIN(min_/**/x,y); max_/**/x = MAX(max_/**/x,y); }
+#endif
+
+ char newFileName[256];
+ char newName[256];
+ FILE *fontOut;
+ int i;
+
+ double suffMag = (double) DviMag / (double) DviDsz;
+ int scaled = (suffMag * 1000 + 0.5);
+ int suff = (DviDpi * UserMag * DviMag) / (1000 * 1000);
+
+ if ( f -> f_design_size == 0 ) {
+ return;
+ }
+
+ shrink = 1000 / UserMag ;
+ if (shrink < 1 ) {
+ shrink = 1;
+ }
+ else if ( shrink > 10 ) {
+ shrink = 10;
+ }
+
+ blackness = DviBlackness;
+ blackness = (blackness < 1) ? DEFAULT_BLACKNESS : blackness;
+
+ sprintf(newName, "%s.%d", name, suff);
+ sprintf(newFileName, "%s.bdf", newName);
+
+ fontOut = fopen(newFileName,"w");
+
+ if (! fontOut ) {
+ perror("fopen");
+ exit(1);
+ }
+
+ totalGlyphs = 0;
+
+ for( c = f -> f_lowch; c < f -> f_highch; c++ ) {
+ g = GLYPH(f,c);
+ shrunkGlyphs[c] = 0;
+
+ if (GVALID(g) && HASRASTER(g)) {
+ struct glyph *s;
+
+ s = dviShrinkGlyph( g, f, ROT_NORM, shrink, shrink, blackness, 1);
+ shrunkGlyphs[c] = s;
+
+ if (s == 0 )
+ continue;
+
+ totalGlyphs++;
+
+ MINMAX(width, s->g_width);
+ MINMAX(height, s->g_height);
+ MINMAX(xorigin, s->g_xorigin);
+ MINMAX(yorigin, s->g_yorigin);
+
+ }
+ }
+
+ fprintf(fontOut, "STARTFONT 2.1\n");
+ fprintf(fontOut,
+ "COMMENT This font image translated from Metafont\n");
+ fprintf(fontOut, "COMMENT Input file was ``%s''\n", name);
+ fprintf(fontOut, "COMMENT DPI was ``%d'', usermag ``%d'', blackness ``%d''\n",
+ DviDpi, UserMag, blackness);
+ fprintf(fontOut, "COMMENT shrink was %d\n", shrink);
+
+ fprintf(fontOut, "FONT %s\n", newName);
+
+ pointSize = (f -> f_design_size) / (TWOTO16 * 16);
+ fprintf(fontOut, "SIZE %d %d %d\n", pointSize, suff, suff);
+
+ fprintf(fontOut, "FONTBOUNDINGBOX %d %d %d %d\n",
+ max_width + 1, max_height,
+ -max_xorigin, max_yorigin - max_height + 1);
+
+ /* These follow the X conventions */
+
+ fprintf(fontOut,"STARTPROPERTIES 3\n");
+ fprintf(fontOut,"FONT_ASCENT %d\n",
+ max_height - min_yorigin);
+ fprintf(fontOut,"FONT_DESCENT %d\n",
+ min_yorigin);
+ fprintf(fontOut,"COPYRIGHT \"Public Domain\"\n");
+ fprintf(fontOut,"ENDPROPERTIES\n");
+ fprintf(fontOut,"CHARS %d\n", totalGlyphs);
+
+ for( c = f -> f_lowch; c < f -> f_highch; c++ ) {
+ if ( shrunkGlyphs[c] != 0 ) {
+ int column;
+ int width;
+ float swidth;
+ int bytes;
+ int byte;
+ char *p;
+ struct glyph *s = shrunkGlyphs[c];
+
+ if ( s -> g_raster == 0 ) {
+ continue; /* to next one */
+ }
+
+ fprintf(fontOut, "STARTCHAR C%03d\n",c);
+ fprintf(fontOut, "ENCODING %d\n",c);
+
+ /* I don't know why it's off by one, but it is.. */
+
+ width = s -> g_pixwidth;
+
+ swidth = (double) ( width * 72000 ) / (double) ( pointSize * DviDpi );
+ fprintf(fontOut, "SWIDTH %d %d\n", (int) swidth, 0);
+ fprintf(fontOut, "DWIDTH %d %d\n", width, 0);
+
+ fprintf(fontOut, "BBX %d %d %d %d\n",
+ s -> g_width, /* width, height of bounding box */
+ s -> g_height,
+ -s -> g_xorigin, /* offset of origin w.r.t. lower left corner*/
+ s -> g_yorigin - s -> g_height + 1);
+ fprintf(fontOut, "BITMAP\n");
+
+ column = 0;
+ width = s -> g_un.g_integer;
+ bytes = width * s -> g_height;
+ for( p = s -> g_raster, byte = 0; byte < bytes; byte++, p++, column++ ) {
+ if (column >= width) {
+ fprintf(fontOut,"\n");
+ column = 0;
+ }
+ printhex(fontOut,*p);
+ }
+ if (column == width) {
+ fprintf(fontOut,"\n");
+ }
+ fprintf(fontOut, "ENDCHAR\n");
+ }
+ }
+ fprintf(fontOut, "ENDFONT\n");
+}
diff --git a/dviware/umddvi/previewers/texx2/mio.h b/dviware/umddvi/previewers/texx2/mio.h
new file mode 100644
index 0000000000..cb2b84bfbf
--- /dev/null
+++ b/dviware/umddvi/previewers/texx2/mio.h
@@ -0,0 +1,64 @@
+/*
+ * This program is Copyright (C) 1987 by the Board of Trustees of the
+ * University of Illinois, and by the author Dirk Grunwald.
+ */
+
+/*
+ * Memory I/O: numbers.
+ *
+ */
+
+#ifdef __STDC__
+
+static
+inline int mGetByte(char **m)
+{
+ unsigned char foo = **m;
+ unsigned int retval = foo & 0xff;
+ (*m)++;
+ return retval;
+}
+
+static
+inline void mGetWord( char **m, i32 *r)
+{
+ int x = mGetByte( m ) << 8;
+ x |= mGetByte(m);
+ *r = x;
+}
+
+static
+inline void mGet3Byte( char **m, i32 *r)
+{
+ long x = mGetByte( m ) << 16;
+ x |= ( mGetByte(m ) << 8 );
+ x |= mGetByte(m);
+ *r = x;
+}
+
+static
+inline void mGetLong( char **m, i32 *r)
+{
+ long x = mGetByte( m ) << 24;
+ x |= ( mGetByte(m) << 16 );
+ x |= ( mGetByte(m) << 8 );
+ x |= mGetByte(m);
+ *r = x;
+}
+
+#else
+
+#define mGetByte(m) ( *((*m)++) & 0xff )
+
+#define mGetWord(m, r) {*(r) = mGetByte(m) << 8; *(r) |= mGetByte(m);}
+
+#define mGet3Byte(m,r) {*(r) = mGetByte(m) << 16;\
+ *(r) |= mGetByte(m) << 8;\
+ *(r) |= mGetByte(m);}
+
+#define mGetLong(m, r) {*(r) = mGetByte(m) << 24;\
+ *(r) |= mGetByte(m) << 16;\
+ *(r) |= mGetByte(m) << 8;\
+ *(r) |= mGetByte(m);}
+
+#endif
diff --git a/dviware/umddvi/previewers/texx2/readme b/dviware/umddvi/previewers/texx2/readme
new file mode 100644
index 0000000000..af51b5391c
--- /dev/null
+++ b/dviware/umddvi/previewers/texx2/readme
@@ -0,0 +1,57 @@
+Sorry, this file got let out of the original distribution.
+
+This directory contains several tools to manipulate the DVI files produced
+by TeX and LaTeX. Additionally, it includes a re-distribution of the
+DVI library routines written by Chris Torek at the University of Maryland.
+The utilities included are:
+
+dviselect select specific pages from a DVI file
+iptex print a dvi file on an Imagen
+texx a dvi previewer for X-11 windows
+texsun a dvi previewer for SunView windows
+
+texx2 a much improved dvi previewer for X-11 windows
+
+To install this package, read the documentation in the file
+doc/installation.tex. The short instructions follow.
+
+FOR TEXX2:
+
+ + Change the binary path names in the ./Makefile.
+
+ + Select a location for your ``font description'' file, and copy and
+ modify the file in fontdesc-example to suit your local installation.
+ Change the main makefile to use that path for variable FONTDESC
+
+ The default is /usr/local/lib/tex82/fontdesc
+
+ + cd to texx2; Edit the Imakefile. Note that DEFAULT_TFM_PATH
+ defines the default path for finding .tfm files, just like TeX.
+
+ + Build a Makefile from the Imakefile
+
+ + run ``make texx2'' at the main level
+
+ + texx2 should now be built. You'll need to install some fonts.
+
+ + in run texx2/mftobdf -mag 1000 -scaled 1000 cmr10. If mftobdf
+ can't find your font, you've got a bad fontdesc file or the
+ path to it is wrong.
+
+ + assuming that this works, edit texx2/buildfonts to suite your
+ local X configuration. I keep fonts in /usr/local/lib/X11/fonts/cmr,
+ and have added this to my font path using
+ % xset +fp /usr/local/lib/X11/fonts/cmr
+ % xset fp rehash
+
+ + in texx2, run "buildfonts -mag 500 `cat FONTS` " to build a
+ fair number of standard fonts. Note that the default is
+ 300 dpi. If you want a smaller set too, say ``-mag 333''.
+
+ + You can use other DPI's -- both texx2 & mftobdf have switches
+ for this.
+
+Dirk Grunwald
+Univ. of Illinois
+grunwald@m.cs.uiuc.edu
+
diff --git a/dviware/umddvi/previewers/texx2/texx2-defs.h b/dviware/umddvi/previewers/texx2/texx2-defs.h
new file mode 100644
index 0000000000..5373a96b19
--- /dev/null
+++ b/dviware/umddvi/previewers/texx2/texx2-defs.h
@@ -0,0 +1,4 @@
+
+#define XtIsPoppedUp(widget) ( widget -> shell.popped_up )
+
+#define TOPBOXNAME "topBox" /* Name of the Top Box. */
diff --git a/dviware/umddvi/previewers/texx2/texx2-error.c b/dviware/umddvi/previewers/texx2/texx2-error.c
new file mode 100644
index 0000000000..fdb0854ce5
--- /dev/null
+++ b/dviware/umddvi/previewers/texx2/texx2-error.c
@@ -0,0 +1,224 @@
+/*
+ * This program is Copyright (C) 1987 by the Board of Trustees of the
+ * University of Illinois, and by the author Dirk Grunwald.
+ */
+
+/*
+ * Print an error message with an optional system error number, and
+ * optionally quit.
+ *
+ */
+
+#include <stdio.h>
+#include <varargs.h>
+#include <X11/IntrinsicP.h>
+#include <X11/StringDefs.h>
+#include <X11/ShellP.h>
+#include <X11/AsciiText.h>
+#include "texx2.h"
+#include "texx2-widgets.h"
+
+#ifdef _STDC_
+ extern char* malloc(int);
+ extern char* realloc(char *, int);
+#else
+ extern char* malloc();
+ extern char* realloc();
+#endif
+
+#define ERROR_BUFFER_SIZE 2048
+static char errorMessageBuffer[ ERROR_BUFFER_SIZE ]
+ = {"Welcome to TeXx-2.8.5\nThis is the dialog box\n"};
+static int errorMessageBufferLength=0;
+
+static message(str,quit)
+ char *str;
+ int quit;
+{
+
+ if ( errorText ) {
+ int len = strlen(str);
+ char *p;
+ XtTextPosition start;
+ XtTextPosition end;
+ XtTextBlock tblk;
+
+ tblk.firstPos = 0;
+ tblk.length = len;
+ tblk.ptr = str;
+ tblk.format = FMT8BIT;
+
+ if ( len > 0 && str[len-1] != '\n' ) {
+ str[len] = '\n';
+ str[len+1] = 0;
+ tblk.length = len+1;
+ }
+
+ start = strlen( errorMessageBuffer );
+
+ if ( start + len > ERROR_BUFFER_SIZE ) {
+ start = 0;
+ bzero( errorMessageBuffer, ERROR_BUFFER_SIZE );
+ }
+
+ end = start;
+
+ XtTextDisableRedisplay(errorText);
+
+ XtTextSetInsertionPoint(errorText, start);
+ XtTextSetLastPos( errorText, start );
+
+ XtTextReplace( errorText, start, end, &tblk );
+
+ XtTextEnableRedisplay(errorText);
+
+ }
+}
+
+static void
+pushClearButton(w, clientData, callData)
+Widget w;
+caddr_t clientData; /* unused */
+caddr_t callData; /* unused */
+{
+ bzero( errorMessageBuffer , ERROR_BUFFER_SIZE );
+
+ XtTextDisableRedisplay(errorText);
+ XtTextSetInsertionPoint(errorText, 0);
+ XtTextSetLastPos( errorText, 0 );
+ XtTextEnableRedisplay(errorText);
+}
+
+/*
+ * If you had a real compiler, these would all be
+ * local the next function
+ */
+
+static XtCallbackRec clearButtonCallBacks [] = {
+ {pushClearButton,NULL},
+ {NULL, NULL}
+};
+
+static Arg clearButtonArgs[] = {
+ {XtNcallback, (XtArgVal) clearButtonCallBacks}
+};
+
+static Arg textArgs[] = {
+ {XtNeditType, (XtArgVal) XttextEdit},
+ {XtNstring, (XtArgVal) errorMessageBuffer},
+ {XtNlength, (XtArgVal) ERROR_BUFFER_SIZE},
+ {XtNtextOptions, (XtArgVal) (scrollVertical | scrollOnOverflow | wordBreak )}
+};
+
+void
+BuildErrorBox()
+{
+
+ clearButton =
+ XtCreateManagedWidget("Clear Dialog Box",
+ commandWidgetClass, topPane,
+ clearButtonArgs, XtNumber(clearButtonArgs));
+ errorText =
+ XtCreateManagedWidget("Error-Text",
+ asciiStringWidgetClass, topPane,
+ textArgs, XtNumber(textArgs));
+}
+
+
+#ifdef lint
+
+/* VARARGS3 ARGSUSED */
+error(quit, e, fmt) int quit, e; char *fmt; {;}
+
+/* VARARGS1 ARGSUSED */
+panic(fmt) char *fmt; { exit(1); /* NOTREACHED */ }
+
+#else lint
+
+extern char *ProgName;
+extern int errno;
+extern char *sys_errlist[];
+extern int sys_nerr;
+
+#define ERROR_MSG_LEN 1024
+static char ErrorMsgBuffer[ ERROR_MSG_LEN ];
+
+error(va_alist)
+ va_dcl
+{
+ va_list l;
+ int quit, e;
+ char *fmt;
+ char *p;
+
+ p = ErrorMsgBuffer;
+
+ va_start(l);
+ /* pick up the constant arguments: quit, errno, printf format */
+ quit = va_arg(l, int);
+ e = va_arg(l, int);
+ if (e < 0)
+ e = errno;
+
+ fmt = va_arg(l, char *);
+
+#if defined(sun)
+ (void) vsprintf(p, fmt, l);
+#else
+ /* Does someone know how to do this properly? */
+
+ {
+ struct _iobuf ungodlyhack;
+ ungodlyhack._cnt = ERROR_MSG_LEN;
+ ungodlyhack._ptr = p;
+ ungodlyhack._base = p;
+ ungodlyhack._bufsiz = ERROR_MSG_LEN;
+ ungodlyhack._flag = _IOSTRG;
+ ungodlyhack._file = 255;
+ _doprnt(fmt, l, &ungodlyhack);
+ }
+#endif
+
+ va_end(l);
+
+ message( ErrorMsgBuffer, quit);
+}
+
+panic(va_alist)
+ va_dcl
+{
+ va_list l;
+ char *fmt;
+ char *p;
+
+ p = ErrorMsgBuffer;
+ sprintf(p, "panic: ");
+ p += strlen(p);
+
+ va_start(l);
+ /* pick up the constant arguments: quit, errno, printf format */
+ fmt = va_arg(l, char *);
+
+#if defined(sun)
+ (void) vsprintf(p, fmt, l);
+#else
+ /* Does someone know how to do this properly? */
+
+ {
+ struct _iobuf ungodlyhack;
+ ungodlyhack._cnt = ERROR_MSG_LEN;
+ ungodlyhack._ptr = p;
+ ungodlyhack._base = p;
+ ungodlyhack._bufsiz = ERROR_MSG_LEN;
+ ungodlyhack._flag = _IOSTRG;
+ ungodlyhack._file = 255;
+ _doprnt(fmt, l, &ungodlyhack);
+ }
+#endif
+
+ va_end(l);
+
+ message(ErrorMsgBuffer, 1);
+}
+
+#endif /* lint */
diff --git a/dviware/umddvi/previewers/texx2/texx2-file.c b/dviware/umddvi/previewers/texx2/texx2-file.c
new file mode 100644
index 0000000000..b4fa05310c
--- /dev/null
+++ b/dviware/umddvi/previewers/texx2/texx2-file.c
@@ -0,0 +1,383 @@
+/*
+ * This program is Copyright (C) 1987 by the Board of Trustees of the
+ * University of Illinois, and by the author Dirk Grunwald.
+ */
+
+#include "texx2.h"
+
+#include <errno.h>
+#include <sys/param.h>
+#include <assert.h>
+#include "dvi-simple.h"
+#include "texx2-page.h"
+#include "texx2-mark.h"
+#include "texx2-widgets.h"
+
+char TeXInputFileNameString[MAXPATHLEN+40];
+char *TeXInputFileName;
+
+char TeXInputDirNameString[MAXPATHLEN+40];
+char *TeXInputDirName;
+
+char fileNameInput[MAXPATHLEN];
+
+/*
+ * If it's a file name, set to the directory of that file,
+ * otherwise, set to the directory
+ */
+void
+setDirectory(dir)
+char *dir;
+{
+ Arg argList[20];
+ Cardinal args;
+
+ char pDir[MAXPATHLEN];
+ char *endPDir;
+ int len;
+
+ strncpy(pDir,dir,MAXPATHLEN);
+ len = strlen(pDir);
+ endPDir = &pDir[len];
+
+ while (chdir(pDir) < 0) {
+ /* skip back to last slash */
+ while (endPDir != pDir && *endPDir != '/') endPDir--;
+
+ if (endPDir == pDir) {
+ getwd(pDir);
+ }
+ else {
+ *endPDir = 0;
+ }
+
+ }
+
+ getwd(pDir);
+
+ strcpy(TeXInputDirNameString, "Directory: ");
+ TeXInputDirName = &TeXInputDirNameString[strlen(TeXInputDirNameString)];
+ strncpy(TeXInputDirName, pDir, MAXPATHLEN);
+
+ if ( directoryLabel != NULL ) {
+ args = 0;
+ XtSetArg(argList[args], XtNlabel, TeXInputDirNameString); args++;
+ XtSetArg(argList[args], XtNmaximumLength, MAXPATHLEN); args++;
+
+ XtSetValues( directoryLabel, argList, args);
+ }
+}
+
+void
+ setFileName(fileName)
+char *fileName;
+{
+ if ( fileNameText && XtIsRealized( fileNameText ) ) {
+ XtTextBlock tblk;
+ int len = (fileName == 0) ? 0 : strlen(fileName);
+
+ if ( len > 0 ) {
+ XtTextPosition start = 0;
+ XtTextPosition end = strlen(fileNameInput);;
+
+ tblk.firstPos = 0;
+ tblk.length = len;
+ tblk.ptr = fileName;
+ tblk.format = FMT8BIT;
+
+ XtTextDisableRedisplay(fileNameText);
+
+ XtTextReplace( fileNameText, start, end, &tblk );
+
+ XtTextEnableRedisplay(fileNameText);
+ }
+ }
+ else {
+ int len = (fileName == 0) ? 0 : strlen(fileName);
+ bzero(fileNameInput, MAXPATHLEN);
+ if ( len > 0 ) {
+ strncpy(fileNameInput, fileName, MAXPATHLEN);
+ }
+ }
+}
+
+void
+setFile(fileName, copy)
+char *fileName;
+int copy;
+{
+ DviDpi = TeXxResources.dpi;
+
+ TeXPageCloseFile(); /* close open pages stuff */
+
+ if( DviInit(fileName, copy )) {
+ disablePageLevel();
+ TeXPageSlamPages();
+ error(0, 0,"[fopen] Unable to open ``%s''", fileName);
+ }
+ else {
+ enablePageLevel();
+
+ error(0, 0, "Opened the %d page file ``%s''",
+ DviTotalPages, DviFileName);
+
+ strcpy(TeXInputFileNameString, "File: ");
+ TeXInputFileName = &TeXInputFileNameString[strlen(TeXInputFileNameString)];
+ strcpy(TeXInputFileName, DviFileName, MAXPATHLEN);
+
+ if ( fileLabel != NULL) {
+ Arg argList[20];
+ Cardinal args;
+
+ args = 0;
+ XtSetArg(argList[args], XtNlabel, TeXInputFileNameString); args++;
+ XtSetArg(argList[args], XtNmaximumLength, MAXPATHLEN); args++;
+
+ XtSetValues( fileLabel, argList, args );
+ }
+ }
+ TeXFontNewFile();
+ TeXMarkNewFile();
+ TeXPageOpenFile();
+}
+
+static lastOpenKind = 0;
+
+static void
+pushOpenFileButton(w, clientData, callData)
+Widget w;
+caddr_t clientData; /* unused */
+caddr_t callData; /* unused */
+{
+ char *fileName = fileNameInput;
+
+ if ( fileName == NULL ) {
+ error(0, 0, "No file specified?");
+ }
+ else {
+ if ( w == cdButton ) {
+ setDirectory( fileName );
+ }
+ else if (w == openButton) {
+ lastOpenKind = 0;
+ setFile( fileName, 0);
+ }
+ else if (w == copyButton) {
+ lastOpenKind = 1;
+ setFile( fileName, 1);
+ }
+ }
+}
+
+void
+pushReopenButton(w, clientData, callData)
+Widget w;
+caddr_t clientData; /* unused */
+caddr_t callData; /* unused */
+{
+ char *fileName = fileNameInput;
+
+ if ( fileName == NULL ) {
+ error(0, 0, "No file specified?");
+ }
+ else {
+ setFile( fileName, lastOpenKind); /* open it same way they did */
+ }
+}
+
+static void
+pushCloseFileButton(w, clientData, callData)
+Widget w;
+caddr_t clientData; /* unused */
+caddr_t callData; /* unused */
+{
+ DviFini();
+ TeXFontNewFile();
+ TeXMarkNewFile();
+ TeXPageCloseFile();
+ TeXPageSlamPages();
+ disablePageLevel();
+}
+
+/*
+ * Page related callbacks & routines
+ */
+
+enablePageLevel()
+{
+ Arg argList[20];
+ Cardinal args;
+
+ args = 0;
+ XtSetArg(argList[args], XtNsensitive, True); args++;
+
+ XtSetValues(pageButton, argList, args);
+ XtSetValues(printAllButton, argList, args);
+ XtSetValues(printMarkedButton, argList, args);
+ XtSetValues(printUnmarkedButton, argList, args);
+ XtSetValues(clearMarksButton, argList, args);
+}
+
+disablePageLevel()
+{
+ Arg argList[20];
+ Cardinal args;
+
+ args = 0;
+ XtSetArg(argList[args], XtNsensitive, False); args++;
+
+ XtSetValues(pageButton, argList, args);
+ XtSetValues(printAllButton, argList, args);
+ XtSetValues(printMarkedButton, argList, args);
+ XtSetValues(printUnmarkedButton, argList, args);
+ XtSetValues(clearMarksButton, argList, args);
+}
+
+static void
+pushPageButton(w, clientData, callData)
+Widget w;
+caddr_t clientData; /* unused */
+caddr_t callData; /* unused */
+{
+ if (DviFile != 0 ) {
+ TeXPageBuild();
+ }
+}
+
+static void
+pushPrintButton(w, clientData, callData)
+Widget w;
+caddr_t clientData; /* unused */
+caddr_t callData; /* unused */
+{
+ PrintDirective what = (PrintDirective) clientData;
+ assert( what == printAll || what == printMarked || what == printUnmarked );
+
+ if (DviFile != 0) {
+ TeXMarkPrint( what );
+ }
+
+}
+
+static void
+pushClearMarksButton(w, clientData, callData)
+Widget w;
+caddr_t clientData; /* unused */
+caddr_t callData; /* unused */
+{
+ if (DviFile != 0 ) {
+ TeXMarkNone();
+ }
+}
+
+static void
+pushQuitButton(w, clientData, callData)
+Widget w;
+caddr_t clientData; /* unused */
+caddr_t callData; /* unused */
+{
+ exit(0);
+}
+
+void
+ BuildFileLevel()
+{
+ Arg argList[20];
+ Cardinal args;
+ int len = strlen(fileNameInput);
+
+ args = 0;
+ XtSetArg(argList[args], XtNeditType,XttextEdit); args++;
+ XtSetArg(argList[args], XtNstring, fileNameInput); args++;
+ XtSetArg(argList[args], XtNlength, MAXPATHLEN); args++;
+ XtSetArg(argList[args], XtNtextOptions, (resizeWidth | wordBreak)); args++;
+ fileNameText =
+ XtCreateManagedWidget("fileName",
+ asciiStringWidgetClass, topPane,
+ argList, args);
+
+ quitButton =
+ XtCreateManagedWidget("Quit",
+ commandWidgetClass, topPane,
+ 0,0);
+ XtAddCallback( quitButton, XtNcallback, pushQuitButton, NULL);
+
+ openButton =
+ XtCreateManagedWidget("Open",
+ commandWidgetClass, topPane,
+ 0,0);
+ XtAddCallback( openButton, XtNcallback, pushOpenFileButton, NULL);
+
+ copyButton =
+ XtCreateManagedWidget("Copy",
+ commandWidgetClass, topPane,
+ 0,0);
+ XtAddCallback( copyButton, XtNcallback, pushOpenFileButton, NULL);
+
+ closeButton =
+ XtCreateManagedWidget("Close",
+ commandWidgetClass, topPane,
+ 0,0);
+ XtAddCallback( closeButton, XtNcallback, pushCloseFileButton, NULL);
+
+ cdButton =
+ XtCreateManagedWidget("Cd",
+ commandWidgetClass, topPane,
+ 0,0);
+ XtAddCallback( cdButton, XtNcallback, pushOpenFileButton, NULL);
+
+
+ pageButton
+ = XtCreateManagedWidget("Page",
+ commandWidgetClass, topPane,
+ 0,0);
+ XtAddCallback( pageButton, XtNcallback, pushPageButton, NULL);
+
+ printAllButton
+ = XtCreateManagedWidget("Print All",
+ commandWidgetClass, topPane,
+ 0,0);
+ XtAddCallback( printAllButton, XtNcallback, pushPrintButton, printAll);
+
+ printMarkedButton
+ = XtCreateManagedWidget("Print Marked",
+ commandWidgetClass, topPane,
+ 0,0);
+ XtAddCallback( printMarkedButton, XtNcallback, pushPrintButton, printMarked);
+
+ printUnmarkedButton
+ = XtCreateManagedWidget("Print Unmarked",
+ commandWidgetClass, topPane,
+ 0,0);
+ XtAddCallback( printUnmarkedButton, XtNcallback,
+ pushPrintButton, printUnmarked);
+
+
+ clearMarksButton
+ = XtCreateManagedWidget("Clear Marks",
+ commandWidgetClass, topPane,
+ 0,0);
+ XtAddCallback( clearMarksButton, XtNcallback,
+ pushClearMarksButton, 0);
+
+ disablePageLevel();
+
+ args = 0;
+ XtSetArg(argList[args], XtNlabel, TeXInputDirNameString); args++;
+ XtSetArg(argList[args], XtNmaximumLength, MAXPATHLEN); args++;
+ XtSetArg(argList[args], XtNresize, True); args++;
+ directoryLabel =
+ XtCreateManagedWidget("Cwd",
+ labelWidgetClass, topPane,
+ argList, args);
+
+ args = 0;
+ XtSetArg(argList[args], XtNlabel, TeXInputFileNameString); args++;
+ XtSetArg(argList[args], XtNmaximumLength, MAXPATHLEN); args++;
+ XtSetArg(argList[args], XtNresize, True); args++;
+ fileLabel =
+ XtCreateManagedWidget("FileLabel",
+ labelWidgetClass, topPane,
+ argList, args);
+}
+
diff --git a/dviware/umddvi/previewers/texx2/texx2-font.c b/dviware/umddvi/previewers/texx2/texx2-font.c
new file mode 100644
index 0000000000..ad188ee719
--- /dev/null
+++ b/dviware/umddvi/previewers/texx2/texx2-font.c
@@ -0,0 +1,127 @@
+#include "texx2.h"
+#include "dvi-simple.h"
+#include "texx2-font.h"
+#include <assert.h>
+
+extern Widget TopLevelWidget;
+
+/* font handlers */
+
+int MagAtShrink[] = {-1, 1000, 500, 333, 250, 200, 166, 142, 125, 111, -1};
+
+XFontStruct **FontsAtMag[ MAX_SHRINK + 2 ];
+
+int FontRefCnt[ MAX_SHRINK + 2 ];
+
+XFontStruct **
+TeXFontRef(usermag)
+int usermag;
+{
+ int magSlot;
+
+ for ( magSlot = MIN_SHRINK; magSlot <= MAX_SHRINK; magSlot++ ) {
+ if ( usermag >= MagAtShrink[ magSlot ] )
+ break;
+ }
+
+ assert( magSlot >= MIN_SHRINK && magSlot <= MAX_SHRINK );
+
+ if ( FontsAtMag[ magSlot ] == 0 ) {
+
+ int nameSize;
+ char *name;
+ char *args[128];
+ int argCnt;
+ char tmpStr[128];
+ int lth;
+ int missing;
+
+ int font;
+
+ XFontStruct **thisMag = (XFontStruct **)
+ XtMalloc( sizeof( XFontStruct *) * (RegisteredFonts + 1) );
+
+ for ( font = 0; font <= RegisteredFonts; font++ ) {
+ thisMag[ font ] = 0;
+ }
+
+ /* try to load the fonts */
+
+ missing = 0;
+
+ for (font = 0; font < RegisteredFonts; font++ ) {
+
+ /* get the canonical font name */
+
+ char tmpStr[128];
+ double dvimag = TheFontInfo[font].paf.paf_DVIMag;
+ double dvidsz = TheFontInfo[font].paf.paf_DVIDesignSize;
+ double suffMag = dvimag / dvidsz;
+
+ int mag = usermag;
+ int scaled = (suffMag * ThePostAmbleInfo.pai_DVIMag + 0.5);
+ int suff = (DviDpi * scaled * mag ) / (1000 * 1000);
+
+ sprintf(tmpStr,"%s.%d",
+ TheFontInfo[font].paf.paf_name, (int) suff);
+
+ thisMag[ font ]
+ = XLoadQueryFont( XtDisplay ( TopLevelWidget ), tmpStr );
+ if ( thisMag[ font ] == 0 ) {
+ missing++;
+ error(0,0,"Missing %s ( -mag %d -scaled %d %s )",
+ tmpStr, mag, scaled, TheFontInfo[font].paf.paf_name);
+ }
+ }
+
+ FontsAtMag[ magSlot ] = thisMag;
+ }
+
+ FontRefCnt[ magSlot ] ++;
+
+ return( FontsAtMag[ magSlot ] );
+}
+
+XFontStruct **
+ TeXFontUnref(usermag)
+int usermag;
+{
+ int magSlot;
+
+ for ( magSlot = MIN_SHRINK; magSlot <= MAX_SHRINK; magSlot++ ) {
+ if ( usermag >= MagAtShrink[ magSlot ] )
+ break;
+ }
+
+ assert( magSlot >= MIN_SHRINK && magSlot <= MAX_SHRINK );
+
+ if ( FontsAtMag [ magSlot] ) {
+
+ FontRefCnt[ magSlot ] --;
+
+ if (FontRefCnt[ magSlot ] <= 0 ) {
+ int font;
+ XFontStruct **fonts = FontsAtMag[magSlot];
+
+ /* fonts list is null terminated */
+
+ for (font = 0; fonts[ font ] ; font++ ) {
+ XFreeFont(XtDisplay( TopLevelWidget ), fonts[font] );
+ fonts[ font ] = 0;
+ }
+ XtFree( FontsAtMag[ magSlot ] );
+ FontsAtMag[ magSlot ] = 0;
+ FontRefCnt[ magSlot ] = 0;
+ }
+ }
+}
+
+void
+TeXFontNewFile()
+{
+ int mag;
+
+ for ( mag = 1; mag <= MAX_SHRINK ; mag++ ) {
+ TeXFontUnref( MagAtShrink[ mag ] );
+ }
+}
diff --git a/dviware/umddvi/previewers/texx2/texx2-font.h b/dviware/umddvi/previewers/texx2/texx2-font.h
new file mode 100644
index 0000000000..f0a02a0fd9
--- /dev/null
+++ b/dviware/umddvi/previewers/texx2/texx2-font.h
@@ -0,0 +1,8 @@
+
+#define MIN_SHRINK 1
+#define MAX_SHRINK 9
+
+extern int MagAtShrink[];
+extern void TeXFontNewFile();
+extern XFontStruct **TeXFontRef();
+extern XFontStruct **TeXFontUnref();
diff --git a/dviware/umddvi/previewers/texx2/texx2-mark.c b/dviware/umddvi/previewers/texx2/texx2-mark.c
new file mode 100644
index 0000000000..625c27bf5f
--- /dev/null
+++ b/dviware/umddvi/previewers/texx2/texx2-mark.c
@@ -0,0 +1,163 @@
+/*
+ * This program is Copyright (C) 1987 by the Board of Trustees of the
+ * University of Illinois, and by the author Dirk Grunwald.
+ */
+
+/*
+ * Handle printing of marked pages
+ */
+
+#include <stdio.h>
+#include <X11/Xos.h>
+#include <X11/IntrinsicP.h>
+#include <X11/StringDefs.h>
+
+#include <stdio.h>
+#include <assert.h>
+#include "dvi-simple.h"
+#include "texx2.h"
+#include "texx2-mark.h"
+
+static Bool *markedPages = 0;
+
+void
+TeXMarkNewFile()
+{
+ int page;
+
+ if ( markedPages ) {
+ XtFree( markedPages );
+ markedPages = 0;
+ }
+
+ if ( DviFile != 0 ) {
+ markedPages = (Bool *) malloc( DviTotalPages * sizeof(Bool) );
+ for ( page = 0; page< DviTotalPages; page++ ) {
+ markedPages[ page ] = False;
+ }
+ }
+}
+
+/*
+ * toggle the mark for a given page
+ */
+
+Bool
+TeXMarkToggle(page)
+int page;
+{
+ assert( page >=0 && page < DviTotalPages );
+ markedPages[ page ] = ~markedPages[ page ];
+ return( markedPages[ page ] );
+}
+
+/*
+ * Simply return the state
+ */
+Bool
+TeXMarkState(page)
+int page;
+{
+ assert( page >=0 && page < DviTotalPages );
+ return( markedPages[ page ] );
+}
+
+void
+TeXMarkAll()
+{
+ int page;
+ for (page = 0; page < DviTotalPages; page++) {
+ markedPages[ page ] = True;
+ }
+}
+
+void
+TeXMarkNone()
+{
+ int page;
+ for (page = 0; page < DviTotalPages; page++) {
+ markedPages[ page ] = False;
+ }
+}
+
+/* Print some pages. The Menu selection dictates what pages get printed */
+
+void
+ TeXMarkPrint(pd)
+PrintDirective pd;
+{
+ char *dvips;
+ int cnt;
+ int i;
+ char buf[20];
+ char printCommand[1024];
+
+ char *fileToPrint;
+ int deletePrintedFile;
+
+ if ( pd == printAll ) {
+ fileToPrint = DviFileName;
+ deletePrintedFile = 0;
+ }
+ else {
+
+ int dviSelectBufferLength = 2048;
+ char dviSelectBuffer[ 2048 ];
+
+ fileToPrint = (char *) tmpnam( 0 );
+ deletePrintedFile = 1;
+
+ /* Now run dviselect to extract the pages */
+
+ sprintf(dviSelectBuffer, "dviselect -i %s -o %s ",
+ DviFileName, fileToPrint);
+
+ cnt = 0;
+ for (i = 0; i < DviTotalPages; i++) {
+ if ( (markedPages[ i ] && pd == printMarked )
+ || (!markedPages[ i ] && pd == printUnmarked )) {
+ sprintf(buf, " =%d", i + 1);
+ strcat(dviSelectBuffer, buf);
+ cnt++;
+ }
+ }
+
+ if (cnt != 0) {
+ error(0,0, dviSelectBuffer);
+ system(dviSelectBuffer);
+ }
+ else {
+
+ /* nothing to print? */
+
+ unlink( fileToPrint );
+ return;
+ }
+ }
+
+ /* Now print pages */
+
+ if (TeXxResources.printProgram == 0) {
+ extern char *getenv();
+ dvips = getenv("DVIPRINT");
+ if (dvips == NULL) {
+ dvips = "Dvi "; /* a good guess on BSD systems */
+ }
+ }
+ else {
+ dvips = TeXxResources.printProgram;
+ }
+
+ error(0,0, "Using default ``%s'' to print\n", dvips);
+
+ sprintf(printCommand, "%s %s ", dvips, fileToPrint);
+
+ error(0,0,printCommand);
+
+ system(printCommand);
+
+ if ( deletePrintedFile ) {
+ unlink( fileToPrint );
+ }
+
+}
diff --git a/dviware/umddvi/previewers/texx2/texx2-mark.h b/dviware/umddvi/previewers/texx2/texx2-mark.h
new file mode 100644
index 0000000000..9750e138fa
--- /dev/null
+++ b/dviware/umddvi/previewers/texx2/texx2-mark.h
@@ -0,0 +1,24 @@
+/*
+ * This program is Copyright (C) 1987 by the Board of Trustees of the
+ * University of Illinois, and by the author Dirk Grunwald.
+ */
+
+typedef enum {printAll, printMarked, printUnmarked } PrintDirective;
+
+extern char *printProgram;
+
+#ifdef _STDC_
+ void TeXMarkNewFile();
+ Bool TeXMarkToggle(int);
+ Bool TeXMarkState(int);
+ void TeXMarkAll();
+ void TeXMarkNone();
+ void TeXMarkPrint(PrintDirective);
+#else
+ void TeXMarkNewFile();
+ Bool TeXMarkToggle();
+ Bool TeXMarkState();
+ void TeXMarkAll();
+ void TeXMarkNone();
+ void TeXMarkPrint();
+#endif
diff --git a/dviware/umddvi/previewers/texx2/texx2-page.c b/dviware/umddvi/previewers/texx2/texx2-page.c
new file mode 100644
index 0000000000..dd30349c33
--- /dev/null
+++ b/dviware/umddvi/previewers/texx2/texx2-page.c
@@ -0,0 +1,833 @@
+/*
+ * This program is Copyright (C) 1987 by the Board of Trustees of the
+ * University of Illinois, and by the author Dirk Grunwald.
+ */
+
+/*
+ *
+ * This looks kind of strange because, initially, I had intended to
+ * allow you to `put away' a page without destroying it -- but
+ * I've decided not to do that.
+ *
+ */
+
+#include <stdio.h>
+#include <X11/Xos.h>
+#include <X11/IntrinsicP.h>
+#include <X11/StringDefs.h>
+
+#include <stdio.h>
+#include <assert.h>
+
+#include "dvi-simple.h"
+
+#include "texx2.h"
+
+#include "DviPage.h"
+#include "texx2-page.h"
+#include "texx2-font.h"
+#include <X11/ViewportP.h> /* needed to get scrollbar sizes? */
+
+extern Widget TopLevelWidget;
+
+#ifdef _STCD_
+ void TeXPageRealize(TeXPage *, int);
+ static void showPage(TeXPage *, int);
+#else
+ void TeXPageRealize();
+ static void showPage();
+#endif
+
+int TeXPages;
+TeXPage *TheTeXPages[ MAX_TEX_PAGES ];
+
+typedef struct {
+ char *thePage;
+ int refs;
+} DviPageRef;
+
+DviPageRef *ThePageRefs = 0;
+
+void
+TeXPageCloseFile()
+{
+ int popup;
+
+ /* dispose of existing information */
+
+ for ( popup = 0; popup < TeXPages; popup++ ) {
+ TeXPage *tp = TheTeXPages[popup];
+ if ( tp && tp -> popUpPage) {
+ TeXPageDeref( tp -> pageNumber );
+ TeXFontUnref( tp -> userMag);
+ tp -> pageData = 0;
+ }
+ }
+
+ if ( ThePageRefs ) {
+ int i;
+ for (i = 0; i < DviTotalPages; i++ ) {
+ XtFree( ThePageRefs[i].thePage );
+ ThePageRefs[ i ].thePage = 0;
+ }
+ }
+
+ XtFree( ThePageRefs );
+
+ ThePageRefs = 0;
+}
+
+void
+TeXPageSlamPages()
+{
+ int popup;
+
+ /* take down pages, dispose of existing information */
+
+ for ( popup = 0; popup < TeXPages; popup++ ) {
+ if ( TheTeXPages[popup] && TheTeXPages[ popup ] -> popUpPage) {
+ XtDestroyWidget( TheTeXPages[ popup ] -> popUpPage );
+ }
+ }
+}
+
+void
+TeXPageOpenFile()
+{
+ /* now rebuild it all */
+
+ if ( DviFile != 0 ) {
+ int i;
+ int popup;
+
+ ThePageRefs =
+ (DviPageRef *) XtMalloc( (DviTotalPages+1) * sizeof(DviPageRef) );
+
+ for (i = 0; i < DviTotalPages; i++ ) {
+ ThePageRefs[i].thePage = 0;
+ ThePageRefs[i].refs = 0;
+ }
+
+ for ( popup = 0; popup < TeXPages; popup++ ) {
+ TeXPage *tp = TheTeXPages[ popup ];
+
+ if ( tp && tp -> popUpPage) {
+
+ int pno = tp -> pageNumber;
+
+ if (pno >= 0 && pno < DviTotalPages) {
+ Arg argList[20];
+ int args = 0;
+
+ tp -> pageData = TeXPageRef( tp -> pageNumber );
+
+ XtSetArg(argList[args], XtNpai, &ThePostAmbleInfo); args++;
+ XtSetArg(argList[args], XtNpage, tp -> pageData); args++;
+ XtSetArg(argList[args], XtNdviFonts, TheFontInfo); args++;
+ XtSetArg(argList[args], XtNxFonts,
+ TeXFontRef(tp -> userMag)); args++;
+
+ XtSetValues( tp -> singleDviPage, argList, args);
+
+ showPage( tp, False );
+ }
+ else {
+ XtDestroyWidget( tp -> popUpPage );
+ }
+ }
+ }
+ }
+}
+
+
+/*
+ * Reference and dereference a page structure -- these keep track
+ * of the memory allocated for page buffers & disposes of them
+ * when not in use.
+ */
+
+char *
+TeXPageRef(pageno)
+int pageno;
+{
+ assert( pageno >= 0 || pageno < DviTotalPages );
+
+ ThePageRefs[ pageno ].refs++;
+ if ( ThePageRefs[ pageno ].thePage == 0 ) {
+ ThePageRefs[ pageno ].thePage = DviFetchPage( pageno );
+ }
+
+ return(ThePageRefs[ pageno ].thePage );
+}
+
+void
+TeXPageDeref(pageno)
+int pageno;
+{
+ assert( pageno >= 0 || pageno < DviTotalPages );
+ if ( ThePageRefs && ThePageRefs[ pageno ].refs > 0) {
+ ThePageRefs[ pageno ].refs--;
+ if ( ThePageRefs[ pageno ].refs <= 0 ) {
+ XtFree( ThePageRefs[ pageno ].thePage );
+ ThePageRefs[ pageno ].thePage = 0;
+ }
+ }
+}
+
+/*
+ * Locate a free TeXPage structure. See comment at head.
+ */
+
+TeXPage *
+TeXPageLocate()
+{
+ int i;
+ TeXPage *tp;
+
+ for (i = 0; i < TeXPages; i++ ) {
+ if ( ! TheTeXPages[ i ] -> active ) {
+ return( TheTeXPages[ i ] );
+ }
+ }
+
+ tp = (TeXPage *) XtMalloc(sizeof(TeXPage));
+
+ bzero( tp, sizeof(TeXPage) );
+
+ tp -> realized = False;
+ tp -> tied = 0;
+ tp -> tiedTo = 0;
+
+ /* install the page in the page list */
+
+ if ( TeXPages > MAX_TEX_PAGES ) {
+ error(0,0,"No more pages available");
+ return(0);
+ }
+
+ TheTeXPages[ TeXPages++ ] = tp;
+
+ return( tp );
+}
+
+/*
+ * The callback when pages die.
+ */
+
+static void
+ dviPageDied(w, clientData, callData)
+Widget w;
+caddr_t clientData; /* unused */
+caddr_t callData; /* unused */
+{
+ TeXPage *tp = (TeXPage*) clientData;
+
+ if ( tp != 0 ){
+ tp -> active = False;
+ tp -> realized = False;
+ TeXPageDeref( tp -> pageNumber );
+ TeXFontUnref( tp -> userMag);
+ tp -> popUpPage = 0;
+
+ if ( tp -> tiedTo != 0 && tp -> tiedTo -> active ) {
+ tp -> tiedTo -> tied = 0;
+ }
+
+ if ( tp -> tied != 0 && tp -> tied -> active ) {
+ tp -> tied -> tiedTo = 0;
+ }
+
+ tp -> tiedTo = 0;
+ tp -> tied = 0;
+
+ }
+}
+
+static void
+ pushQuitButton(w, clientData, callData)
+Widget w;
+caddr_t clientData; /* unused */
+caddr_t callData; /* unused */
+{
+ TeXPage *tp = (TeXPage*) clientData;
+ XtDestroyWidget( tp -> popUpPage );
+}
+
+/*
+ * Set all the buttons for this page, possibly also
+ * sending the page information
+ */
+
+static Arg sensArgs[] = {
+ {XtNsensitive, (XtArgVal) True}
+};
+
+static Arg insensArgs[] = {
+ {XtNsensitive, (XtArgVal) False}
+};
+
+static void
+ showPage(tp, displayPage)
+TeXPage *tp;
+Bool displayPage;
+{
+ Arg argList[20];
+ Cardinal args;
+
+ Pixel fore;
+ Pixel back;
+
+ if ( displayPage ) {
+ tp -> pageData = TeXPageRef( tp -> pageNumber );
+ args = 0;
+ XtSetArg(argList[args], XtNpage, tp -> pageData); args++;
+
+ XtSetValues(tp -> singleDviPage, argList, args);
+ }
+
+ if ( tp -> pageNumber == 0 ) {
+ XtSetValues( tp -> backwardButton, insensArgs, XtNumber(insensArgs));
+ }
+ else {
+ XtSetValues( tp -> backwardButton, sensArgs, XtNumber(sensArgs));
+ }
+
+ if ( tp -> pageNumber >= (DviTotalPages-1)) {
+ XtSetValues( tp -> forewardButton, insensArgs, XtNumber(insensArgs));
+ }
+ else {
+ XtSetValues( tp -> forewardButton, sensArgs, XtNumber(sensArgs));
+ }
+
+ /* Take normal values from another button */
+
+ args = 0;
+ XtSetArg(argList[args], XtNforeground, &fore); args++;
+ XtSetArg(argList[args], XtNbackground, &back); args++;
+ XtGetValues( tp -> forewardButton, argList, args);
+
+ if (TeXMarkState( tp -> pageNumber ) ) {
+ Arg argList[20];
+ Cardinal args;
+
+ args = 0;
+ XtSetArg(argList[args], XtNforeground, back); args++;
+ XtSetArg(argList[args], XtNbackground, fore); args++;
+
+ XtSetValues( tp -> markButton, argList, args );
+ }
+ else {
+ Arg argList[20];
+ Cardinal args;
+
+ args = 0;
+ XtSetArg(argList[args], XtNforeground, fore); args++;
+ XtSetArg(argList[args], XtNbackground, back); args++;
+
+ XtSetValues( tp -> markButton, argList, args );
+ }
+}
+
+static void
+ pushForewardButton(w, clientData, callData)
+Widget w;
+caddr_t clientData; /* unused */
+caddr_t callData; /* unused */
+{
+ TeXPage *tp = (TeXPage*) clientData; /* */
+ char *p;
+
+ if (tp -> pageNumber >= DviTotalPages) {
+ return;
+ }
+ else {
+ if ( tp -> pageData != 0 ) {
+ TeXPageDeref( tp -> pageNumber );
+ }
+ tp -> pageNumber++;
+ }
+ showPage(tp, True);
+ if ( tp -> tied ) {
+ pushForewardButton( tp -> tied, tp -> tied, 0 );
+ }
+}
+
+static void
+ pushBackwardButton(w, clientData, callData)
+Widget w;
+caddr_t clientData; /* unused */
+caddr_t callData; /* unused */
+{
+ TeXPage *tp = (TeXPage*) clientData;
+ char *p;
+
+ if ( tp -> tied ) {
+ pushBackwardButton( tp -> tied, tp -> tied, 0 );
+ }
+
+ if ( tp -> pageNumber <= 0 ) {
+ return;
+ }
+ else {
+ if ( tp -> pageData != 0 ) {
+ TeXPageDeref( tp -> pageNumber );
+ }
+
+ tp -> pageNumber--;
+ }
+ showPage(tp, True);
+}
+
+static void
+ pushMarkButton(w, clientData, callData)
+Widget w;
+caddr_t clientData; /* unused */
+caddr_t callData; /* unused */
+{
+ TeXPage *tp = (TeXPage*) clientData;
+
+ TeXMarkToggle( tp -> pageNumber );
+ showPage(tp, False);
+}
+
+static void
+ pushDupButton(w, clientData, callData)
+Widget w;
+caddr_t clientData; /* unused */
+caddr_t callData; /* unused */
+{
+ TeXPage *tp = (TeXPage *) clientData;
+ TeXPage *newtp = TeXPageLocate();
+ TeXPageRealize(newtp, tp -> pageNumber);
+}
+
+static void
+ pushTieButton(w, clientData, callData)
+Widget w;
+caddr_t clientData; /* unused */
+caddr_t callData; /* unused */
+{
+ TeXPage *tp = (TeXPage *) clientData;
+ if ( tp -> tied == 0 ) {
+ TeXPage *newtp = TeXPageLocate();
+ tp -> tied = newtp;
+ newtp -> tiedTo = tp;
+ TeXPageRealize(newtp, tp -> pageNumber);
+ }
+}
+
+/*
+ * The goto button. This scans, starting at the current page number,
+ * until a value of ``DviCount[0]'' meets the goto destination.
+ * This allows us to hit the multiple ``page 1'' refs.
+ */
+static void
+ pushGotoButton(w, clientData, callData)
+Widget w;
+caddr_t clientData; /* unused */
+caddr_t callData; /* unused */
+{
+ TeXPage *tp = (TeXPage*) clientData;
+
+ char *pageNumber = tp -> pageNumberBuffer;
+ if ( pageNumber != 0 && strlen( pageNumber ) > 0 ) {
+
+ int want = atoi( pageNumber );
+ int here = tp -> pageNumber;
+ int page = here;
+
+ for(;;) {
+ page++;
+ if ( page >= DviTotalPages ) {
+ page = 0;
+ }
+ if ( page == here )
+ return;
+
+ if ( DviCount[0][page] == want ) {
+ TeXPageDeref( tp -> pageNumber );
+ tp -> pageNumber = page;
+ TeXPageRef( tp -> pageNumber );
+ showPage(tp, True);
+ return;
+ }
+ }
+ }
+}
+
+void
+changeMag( tp, mag )
+TeXPage *tp;
+int mag;
+{
+ Arg argList[20];
+ Cardinal args;
+
+ if ( mag > 0 && mag != tp -> userMag ) {
+ XFontStruct **x;
+ Dimension maxHt
+ = (int) ((HeightOfScreen(XtScreen(TopLevelWidget))) * 0.90);
+ Dimension maxWd
+ = (int) ((WidthOfScreen(XtScreen(TopLevelWidget))) * 0.95);
+ Dimension dviHt;
+ Dimension dviWd;
+
+ TeXFontUnref( tp -> userMag);
+
+ tp -> userMag = mag; x = TeXFontRef(tp -> userMag);
+
+ args = 0;
+ XtSetArg(argList[args], XtNuserMag, tp -> userMag); args++;
+ XtSetArg(argList[args], XtNxFonts, x); args++;
+ XtSetValues( tp -> singleDviPage, argList, args);
+
+ /* get the size of the dvi page */
+ if ( TeXxResources.autoSize ) {
+ args = 0; XtSetArg(argList[args], XtNwidth, &dviWd); args++;
+ XtSetArg(argList[args], XtNheight, &dviHt); args++;
+ XtGetValues( tp -> singleDviPage, argList, args);
+
+ if ( dviWd <= maxWd ){
+ maxWd = dviWd;
+
+ /* will we need scrollbars? */
+
+ if ( dviHt > maxHt ) {
+ ViewportWidget vp = (ViewportWidget) (tp -> viewPort);
+ maxWd = maxWd
+ + vp -> viewport.vert_bar -> core.width
+ + vp -> viewport.vert_bar -> core.border_width;
+ }
+ }
+ if ( dviHt <= maxHt ) {
+ maxHt = dviHt;
+ if ( dviWd > maxWd ) {
+ ViewportWidget vp = (ViewportWidget) (tp -> viewPort);
+ maxHt = maxHt
+ + vp -> viewport.horiz_bar -> core.width
+ + vp -> viewport.horiz_bar -> core.border_width;
+ }
+ }
+
+ args = 0;
+ XtSetArg(argList[args], XtNwidth, maxWd); args++;
+ XtSetArg(argList[args], XtNheight, maxHt); args++;
+ XtSetValues( tp -> viewPort, argList, args);
+ }
+ }
+}
+
+static void
+ pushMagButton(w, clientData, callData)
+Widget w;
+caddr_t clientData;
+caddr_t callData;
+{
+ TeXPage *tp = (TeXPage *) clientData;
+ int mag;
+
+ mag = atoi( tp -> pageNumberBuffer );
+ changeMag( tp, mag );
+}
+
+static void
+ pushLargeButton(w, clientData, callData)
+Widget w;
+caddr_t clientData; /* unused */
+caddr_t callData; /* unused */
+{
+ TeXPage *tp = (TeXPage *) clientData;
+ changeMag( tp, TeXxResources.largeMag );
+}
+
+static void
+ pushSmallButton(w, clientData, callData)
+Widget w;
+caddr_t clientData; /* unused */
+caddr_t callData; /* unused */
+{
+ TeXPage *tp = (TeXPage *) clientData;
+ changeMag( tp, TeXxResources.smallMag );
+}
+
+/*
+ * Realize the TeXPage structure and pop up the corresponding window
+ */
+void
+TeXPageRealize(tp, pageNumber)
+TeXPage *tp;
+int pageNumber;
+{
+ Arg argList[20];
+ int args;
+
+ Dimension maxHt = (int) ((HeightOfScreen(XtScreen(TopLevelWidget))) * 0.90);
+ Dimension maxWd = (int) ((WidthOfScreen(XtScreen(TopLevelWidget))) * 0.95);
+ Dimension dviHt;
+ Dimension dviWd;
+ extern pushReopenButton(); /* from texx2-file */
+
+ Dimension gap = 30;
+
+ if ( tp == NULL ) {
+ return;
+ }
+
+ assert(TopLevelWidget != 0);
+
+ args = 0;
+ XtSetArg(argList[args], XtNresize, True); args++;
+ XtSetArg(argList[args], XtNallowShellResize, True); args++;
+ tp -> popUpPage =
+ XtCreatePopupShell("TeXx2-Page-Display",
+ topLevelShellWidgetClass, TopLevelWidget,
+ argList,args);
+
+ args = 0;
+ XtSetArg(argList[args], XtNresize, True); args++;
+ tp -> dviPageBox =
+ XtCreateManagedWidget("dviPageBox",
+ formWidgetClass, tp -> popUpPage,
+ argList, args);
+
+ args = 0;
+ XtSetArg(argList[args], XtNresize, True); args++;
+ XtSetArg(argList[args], XtNleft, XtChainLeft); args++;
+ XtSetArg(argList[args], XtNtop, XtChainTop); args++;
+ tp -> quitButton =
+ XtCreateManagedWidget("Quit",
+ commandWidgetClass, tp -> dviPageBox,
+ argList, args);
+ XtAddCallback(tp -> quitButton, XtNcallback, pushQuitButton, tp);
+
+ args = 0;
+ XtSetArg(argList[args], XtNresize, True); args++;
+ XtSetArg(argList[args], XtNtop, XtChainTop); args++;
+ XtSetArg(argList[args], XtNfromHoriz, tp -> quitButton); args++;
+ XtSetArg(argList[args], XtNhorizDistance, gap); args++;
+ tp -> forewardButton =
+ XtCreateManagedWidget("Forward",
+ commandWidgetClass, tp -> dviPageBox,
+ argList, args);
+ XtAddCallback(tp -> forewardButton, XtNcallback, pushForewardButton, tp);
+
+ args = 0;
+ XtSetArg(argList[args], XtNresize, True); args++;
+ XtSetArg(argList[args], XtNtop, XtChainTop); args++;
+ XtSetArg(argList[args], XtNfromHoriz, tp -> forewardButton); args++;
+ tp -> backwardButton =
+ XtCreateManagedWidget("Backward",
+ commandWidgetClass, tp -> dviPageBox,
+ argList, args);
+ XtAddCallback(tp -> backwardButton, XtNcallback, pushBackwardButton, tp);
+
+ args = 0;
+ XtSetArg(argList[args], XtNresize, True); args++;
+ XtSetArg(argList[args], XtNtop, XtChainTop); args++;
+ XtSetArg(argList[args], XtNfromHoriz, tp -> backwardButton); args++;
+ tp -> markButton =
+ XtCreateManagedWidget("Mark",
+ commandWidgetClass, tp -> dviPageBox,
+ argList, args);
+ XtAddCallback(tp -> markButton, XtNcallback, pushMarkButton, tp);
+
+ args = 0;
+ XtSetArg(argList[args], XtNresize, True); args++;
+ XtSetArg(argList[args], XtNtop, XtChainTop); args++;
+ XtSetArg(argList[args], XtNfromHoriz, tp -> markButton); args++;
+ tp -> dupButton =
+ XtCreateManagedWidget("Dup",
+ commandWidgetClass, tp -> dviPageBox,
+ argList, args);
+ XtAddCallback(tp -> dupButton, XtNcallback, pushDupButton, tp);
+
+
+ args = 0;
+ XtSetArg(argList[args], XtNresize, True); args++;
+ XtSetArg(argList[args], XtNtop, XtChainTop); args++;
+ XtSetArg(argList[args], XtNfromHoriz, tp -> dupButton); args++;
+ tp -> tieButton =
+ XtCreateManagedWidget("Tied",
+ commandWidgetClass, tp -> dviPageBox,
+ argList, args);
+ XtAddCallback(tp -> tieButton, XtNcallback, pushTieButton, tp);
+
+ args = 0;
+ XtSetArg(argList[args], XtNresize, True); args++;
+ XtSetArg(argList[args], XtNtop, XtChainTop); args++;
+ XtSetArg(argList[args], XtNfromHoriz, tp -> tieButton); args++;
+ tp -> largeButton =
+ XtCreateManagedWidget("Large",
+ commandWidgetClass, tp -> dviPageBox,
+ argList, args);
+ XtAddCallback(tp -> largeButton, XtNcallback, pushLargeButton, tp);
+
+ args = 0;
+ XtSetArg(argList[args], XtNresize, True); args++;
+ XtSetArg(argList[args], XtNtop, XtChainTop); args++;
+ XtSetArg(argList[args], XtNfromHoriz, tp -> largeButton); args++;
+ tp -> smallButton =
+ XtCreateManagedWidget("Small",
+ commandWidgetClass, tp -> dviPageBox,
+ argList, args);
+ XtAddCallback(tp -> smallButton, XtNcallback, pushSmallButton, tp);
+
+ args = 0;
+ XtSetArg(argList[args], XtNresize, True); args++;
+ XtSetArg(argList[args], XtNtop, XtChainTop); args++;
+ XtSetArg(argList[args], XtNfromHoriz, tp -> smallButton); args++;
+ tp -> reopenButton =
+ XtCreateManagedWidget("Reopen",
+ commandWidgetClass, tp -> dviPageBox,
+ argList, args);
+ XtAddCallback(tp -> reopenButton, XtNcallback, pushReopenButton, tp);
+
+
+ args = 0;
+ XtSetArg(argList[args], XtNresize, True); args++;
+ XtSetArg(argList[args], XtNtop, XtChainTop); args++;
+ XtSetArg(argList[args], XtNfromHoriz, tp -> reopenButton); args++;
+ XtSetArg(argList[args], XtNhorizDistance, gap); args++;
+ XtSetArg(argList[args], XtNeditType, XttextEdit); args++;
+ XtSetArg(argList[args], XtNstring, tp -> pageNumberBuffer); args++;
+ XtSetArg(argList[args], XtNlength, MAXPAGENUMBERBUFFER); args++;
+ XtSetArg(argList[args], XtNtextOptions, resizeWidth); args++;
+ XtSetArg(argList[args], XtNresizable,True); args++;
+ tp -> pageNumberText =
+ XtCreateManagedWidget("",
+ asciiStringWidgetClass, tp -> dviPageBox,
+ argList, args);
+
+ args = 0;
+ XtSetArg(argList[args], XtNresize, True); args++;
+ XtSetArg(argList[args], XtNtop, XtChainTop); args++;
+ XtSetArg(argList[args], XtNfromHoriz, tp -> pageNumberText); args++;
+ tp -> gotoButton =
+ XtCreateManagedWidget("Goto",
+ commandWidgetClass, tp -> dviPageBox,
+ argList, args);
+ XtAddCallback(tp -> gotoButton, XtNcallback, pushGotoButton, tp);
+
+ args = 0;
+ XtSetArg(argList[args], XtNresize, True); args++;
+ XtSetArg(argList[args], XtNtop, XtChainTop); args++;
+ XtSetArg(argList[args], XtNfromHoriz, tp -> gotoButton); args++;
+ tp -> magButton =
+ XtCreateManagedWidget("Mag",
+ commandWidgetClass, tp -> dviPageBox,
+ argList, args);
+ XtAddCallback(tp -> magButton, XtNcallback, pushMagButton, tp);
+
+ args = 0;
+ XtSetArg(argList[args], XtNresize, True); args++;
+ XtSetArg(argList[args], XtNleft, XtChainLeft); args++;
+ XtSetArg(argList[args], XtNfromVert, tp -> pageNumberText); args++;
+ XtSetArg(argList[args], XtNresizable, True); args++;
+ XtSetArg(argList[args], XtNallowHoriz, True); args++;
+ XtSetArg(argList[args], XtNallowVert, True); args++;
+ tp -> viewPort =
+ XtCreateWidget("ViewPort",
+ viewportWidgetClass, tp -> dviPageBox,
+ argList, args);
+
+ bzero(tp -> pageNumberBuffer, MAXPAGENUMBERBUFFER);
+ tp -> realized = True;
+ tp -> pageNumber = pageNumber;
+ tp -> pageData = TeXPageRef( tp -> pageNumber );
+ tp -> userMag = TeXxResources.userMag;
+ tp -> active = True;
+
+ args = 0;
+ XtSetArg(argList[args], XtNresize, True); args++;
+ XtSetArg(argList[args], XtNpai, &ThePostAmbleInfo); args++;
+ XtSetArg(argList[args], XtNdviFonts, TheFontInfo); args++;
+
+ XtSetArg(argList[args], XtNdpi, TeXxResources.dpi ); args++;
+ XtSetArg(argList[args], XtNpaperWidth,
+ TeXxResources.paperWidthString ); args++;
+ XtSetArg(argList[args], XtNpaperHeight,
+ TeXxResources.paperHeightString ); args++;
+
+ XtSetArg(argList[args], XtNpage, tp -> pageData); args++;
+ XtSetArg(argList[args], XtNuserMag, tp -> userMag); args++;
+ XtSetArg(argList[args], XtNxFonts, TeXFontRef(tp -> userMag)); args++;
+
+ tp -> singleDviPage =
+ XtCreateWidget("DviPage",
+ dviPageWidgetClass, tp -> viewPort,
+ argList, args);
+
+ XtAddCallback( tp -> singleDviPage, XtNdestroyCallback, dviPageDied, tp);
+
+ /* get the size of the dvi page. This is an attempt to provide
+ a nice default window size */
+
+ args = 0;
+ XtSetArg(argList[args], XtNwidth, &dviWd); args++;
+ XtSetArg(argList[args], XtNheight, &dviHt); args++;
+ XtGetValues( tp -> singleDviPage, argList, args);
+ if ( dviWd < maxWd ){
+ maxWd = dviWd;
+ }
+ if ( dviHt < maxHt ) {
+ maxHt = dviHt;
+ }
+ args = 0;
+ XtSetArg(argList[args], XtNwidth, maxWd); args++;
+ XtSetArg(argList[args], XtNheight, maxHt); args++;
+ XtSetValues( tp -> viewPort, argList, args);
+
+ /* Now manage the viewport & single page */
+ XtManageChild( tp -> singleDviPage );
+ XtManageChild( tp -> viewPort );
+
+ XtRealizeWidget(tp -> popUpPage);
+
+ /* did we need scrollbars? */
+
+ if ( dviWd <= maxWd ){
+ maxWd = dviWd;
+
+ if ( dviHt > maxHt ) {
+ ViewportWidget vp = (ViewportWidget) (tp -> viewPort);
+ maxWd = maxWd
+ + vp -> viewport.vert_bar -> core.width
+ + vp -> viewport.vert_bar -> core.border_width;
+ }
+ }
+ if ( dviHt <= maxHt ) {
+ maxHt = dviHt;
+ if ( dviWd > maxWd ) {
+ ViewportWidget vp = (ViewportWidget) (tp -> viewPort);
+ maxHt = maxHt
+ + vp -> viewport.horiz_bar -> core.width
+ + vp -> viewport.horiz_bar -> core.border_width;
+ }
+ }
+
+ args = 0;
+ XtSetArg(argList[args], XtNwidth, maxWd); args++;
+ XtSetArg(argList[args], XtNheight, maxHt); args++;
+ XtSetValues( tp -> viewPort, argList, args);
+
+ /* some bug somewhere makes the first page not appear unless I reset page */
+ args = 0;
+ XtSetArg(argList[args], XtNpage, tp -> pageData); args++;
+ XtSetValues(tp -> singleDviPage, argList, args);
+
+ showPage( tp, False ); /* set remaining buttons */
+
+ XtPopup( tp -> popUpPage, XtGrabNone);
+}
+
+void
+ TeXPageBuild()
+{
+ int i;
+
+ TeXPage *tp = TeXPageLocate();
+
+ if ( ! tp -> realized ) {
+ TeXPageRealize(tp, 0);
+ }
+}
diff --git a/dviware/umddvi/previewers/texx2/texx2-page.h b/dviware/umddvi/previewers/texx2/texx2-page.h
new file mode 100644
index 0000000000..00645b8022
--- /dev/null
+++ b/dviware/umddvi/previewers/texx2/texx2-page.h
@@ -0,0 +1,63 @@
+/*
+ * This program is Copyright (C) 1987 by the Board of Trustees of the
+ * University of Illinois, and by the author Dirk Grunwald.
+ */
+
+/* This is everything that's in a TeXPage */
+
+#include "texx2.h"
+
+#include <X11/Shell.h>
+
+typedef struct TeXPageStruct
+{
+ int pageNumber;
+ char * pageData;
+ int userMag;
+ Bool active;
+ Bool realized;
+#define MAXPAGENUMBERBUFFER 10
+ char pageNumberBuffer[MAXPAGENUMBERBUFFER];
+ Widget popUpPage;
+ Widget dviPageBox;
+ Widget singleDviPage;
+ Widget viewPort;
+ Widget buttonBox;
+ Widget forewardButton;
+ Widget backwardButton;
+ Widget markButton;
+ Widget dupButton;
+ struct TeXPageStruct *tied;
+ struct TeXPageStruct *tiedTo;
+ Widget tieButton;
+ Widget largeButton;
+ Widget smallButton;
+ Widget quitButton;
+ Widget pageNumberText;
+ Widget gotoButton;
+ Widget magButton;
+ Widget reopenButton;
+} TeXPage;
+
+extern int TeXPages;
+#define MAX_TEX_PAGES 10
+extern TeXPage *TheTeXPages [ MAX_TEX_PAGES ];
+
+#ifdef _STDC_
+ extern void TeXPageBuild();
+ extern void TeXPageCloseFile();
+ extern void TeXPageSlamPages();
+ extern void TeXPageOpenFile();
+ extern TeXPage *TeXPageLocate();
+ extern char *TeXPageRef(int);
+ extern void TeXPageDeref(int);
+ extern void TeXPageRealize( TeXPage *);
+#else
+ extern void TeXPageBuild();
+ extern void TeXPageCloseFile();
+ extern void TeXPageSlamPages();
+ extern void TeXPageOpenFile();
+ extern TeXPage *TeXPageLocate();
+ extern char *TeXPageRef();
+ extern void TeXPageDeref();
+#endif
diff --git a/dviware/umddvi/previewers/texx2/texx2-widgets.c b/dviware/umddvi/previewers/texx2/texx2-widgets.c
new file mode 100644
index 0000000000..96abbda5fb
--- /dev/null
+++ b/dviware/umddvi/previewers/texx2/texx2-widgets.c
@@ -0,0 +1,174 @@
+#include "texx2.h"
+#include <errno.h>
+#include <sys/param.h>
+#include <assert.h>
+#include "texx2-widgets.h"
+
+Widget topPane;
+Widget topFile;
+Widget topPages;
+Widget topError;
+
+/*
+ * Widgets related to file I/O
+ */
+Widget topFileBox;
+Widget fileNameText;
+Widget openButton;
+Widget copyButton;
+Widget cdButton;
+Widget closeButton;
+Widget quitButton;
+Widget directoryLabel;
+Widget fileLabel;
+
+/*
+ * Widgets related to the pages table
+ */
+Widget pageButton;
+Widget printAllButton;
+Widget printMarkedButton;
+Widget printUnmarkedButton;
+Widget clearMarksButton;
+
+/*
+ * Error dialog widgets
+ */
+
+Widget errorMsgBox;
+Widget errorText;
+Widget clearButton;
+
+void
+ BuildTopLevelWidget(topLevel)
+Widget topLevel;
+{
+
+ Dimension width = 650;
+ Dimension littleGap = 15;
+
+ Arg argList[20];
+ Cardinal args;
+
+ args = 0;
+ XtSetArg(argList[args], XtNresize, True); args++;
+ topPane =
+ XtCreateManagedWidget("texx2-top-pane",
+ formWidgetClass, topLevel,
+ argList, args);
+
+ BuildFileLevel(topPane);
+ BuildErrorBox(topPane);
+
+ args = 0;
+ XtSetArg(argList[args], XtNwidth, width); args++;
+ XtSetArg(argList[args], XtNtop, XtChainTop); args++;
+ XtSetArg(argList[args], XtNleft, XtChainLeft); args++;
+ XtSetArg(argList[args], XtNresizable, True); args++;
+ XtSetValues(fileNameText, argList, args);
+
+ args = 0;
+ XtSetArg(argList[args], XtNfromVert, fileNameText); args++;
+ XtSetArg(argList[args], XtNleft, XtChainLeft); args++;
+ XtSetArg(argList[args], XtNresize, False); args++;
+ XtSetArg(argList[args], XtNresizable, False); args++;
+ XtSetValues(quitButton, argList, args);
+
+ /* Move everything away from the quit button */
+ args = 0;
+ XtSetArg(argList[args], XtNfromVert, fileNameText); args++;
+ XtSetArg(argList[args], XtNfromHoriz, quitButton); args++;
+ XtSetArg(argList[args], XtNhorizDistance, littleGap); args++;
+ XtSetArg(argList[args], XtNresize, False); args++;
+ XtSetArg(argList[args], XtNresizable, False); args++;
+ XtSetValues(openButton, argList, args);
+
+ args = 0;
+ XtSetArg(argList[args], XtNfromVert, fileNameText); args++;
+ XtSetArg(argList[args], XtNfromHoriz, openButton); args++;
+ XtSetArg(argList[args], XtNresize, False); args++;
+ XtSetArg(argList[args], XtNresizable, False); args++;
+ XtSetValues(copyButton, argList, args);
+
+ args = 0;
+ XtSetArg(argList[args], XtNfromVert, fileNameText); args++;
+ XtSetArg(argList[args], XtNfromHoriz, copyButton); args++;
+ XtSetArg(argList[args], XtNresize, False); args++;
+ XtSetArg(argList[args], XtNresizable, False); args++;
+ XtSetValues(closeButton, argList, args);
+
+ args = 0;
+ XtSetArg(argList[args], XtNfromVert, fileNameText); args++;
+ XtSetArg(argList[args], XtNfromHoriz, closeButton); args++;
+ XtSetArg(argList[args], XtNresize, False); args++;
+ XtSetArg(argList[args], XtNresizable, False); args++;
+ XtSetValues(cdButton, argList, args);
+
+ args = 0;
+ XtSetArg(argList[args], XtNfromVert, openButton); args++;
+ XtSetArg(argList[args], XtNfromHoriz, quitButton); args++;
+ XtSetArg(argList[args], XtNhorizDistance, littleGap); args++;
+ XtSetArg(argList[args], XtNresize, False); args++;
+ XtSetArg(argList[args], XtNresizable, False); args++;
+ XtSetValues(pageButton, argList, args);
+
+ args = 0;
+ XtSetArg(argList[args], XtNfromVert, quitButton); args++;
+ XtSetArg(argList[args], XtNfromHoriz, pageButton); args++;
+ XtSetArg(argList[args], XtNresize, False); args++;
+ XtSetArg(argList[args], XtNresizable, False); args++;
+ XtSetValues(printAllButton, argList, args);
+
+ args = 0;
+ XtSetArg(argList[args], XtNfromVert, quitButton); args++;
+ XtSetArg(argList[args], XtNfromHoriz, printAllButton); args++;
+ XtSetArg(argList[args], XtNresizable, True); args++;
+ XtSetArg(argList[args], XtNresize, False); args++;
+ XtSetArg(argList[args], XtNresizable, False); args++;
+ XtSetValues(printMarkedButton, argList, args);
+
+ args = 0;
+ XtSetArg(argList[args], XtNfromVert, quitButton); args++;
+ XtSetArg(argList[args], XtNfromHoriz, printMarkedButton); args++;
+ XtSetArg(argList[args], XtNresize, False); args++;
+ XtSetArg(argList[args], XtNresizable, False); args++;
+ XtSetValues(printUnmarkedButton, argList, args);
+
+ args = 0;
+ XtSetArg(argList[args], XtNfromVert, quitButton); args++;
+ XtSetArg(argList[args], XtNfromHoriz, printUnmarkedButton); args++;
+ XtSetArg(argList[args], XtNresize, False); args++;
+ XtSetArg(argList[args], XtNresizable, False); args++;
+ XtSetValues(clearMarksButton, argList, args);
+
+ args = 0;
+ XtSetArg(argList[args], XtNwidth, width); args++;
+ XtSetArg(argList[args], XtNfromVert, pageButton); args++;
+ XtSetArg(argList[args], XtNleft, XtChainLeft); args++;
+ XtSetArg(argList[args], XtNresizable, True); args++;
+ XtSetArg(argList[args], XtNresize, True); args++;
+ XtSetValues(directoryLabel, argList, args);
+
+ args = 0;
+ XtSetArg(argList[args], XtNwidth, width); args++;
+ XtSetArg(argList[args], XtNfromVert, directoryLabel); args++;
+ XtSetArg(argList[args], XtNleft, XtChainLeft); args++;
+ XtSetArg(argList[args], XtNresizable, True); args++;
+ XtSetArg(argList[args], XtNresize, True); args++;
+ XtSetValues(fileLabel, argList, args);
+
+ args = 0;
+ XtSetArg(argList[args], XtNfromVert, fileLabel); args++;
+ XtSetArg(argList[args], XtNleft, XtChainLeft); args++;
+ XtSetArg(argList[args], XtNresize, False); args++;
+ XtSetArg(argList[args], XtNresizable, False); args++;
+ XtSetValues(clearButton, argList, args);
+
+ args = 0;
+ XtSetArg(argList[args], XtNfromVert, clearButton); args++;
+ XtSetArg(argList[args], XtNleft, XtChainLeft); args++;
+ XtSetArg(argList[args], XtNresizable, True); args++;
+ XtSetArg(argList[args], XtNwidth, width); args++;
+ XtSetArg(argList[args], XtNheight, 150); args++;
+ XtSetValues(errorText, argList, args);
+}
diff --git a/dviware/umddvi/previewers/texx2/texx2-widgets.h b/dviware/umddvi/previewers/texx2/texx2-widgets.h
new file mode 100644
index 0000000000..de0f2c1019
--- /dev/null
+++ b/dviware/umddvi/previewers/texx2/texx2-widgets.h
@@ -0,0 +1,40 @@
+extern Widget topPane;
+
+/*
+ * Widgets related to file I/O
+ */
+extern Widget topFileBox;
+extern Widget fileNameText;
+extern Widget openButton;
+extern Widget closeButton;
+extern Widget copyButton;
+extern Widget cdButton;
+extern Widget quitButton;
+
+extern Widget directoryLabel;
+extern Widget fileLabel;
+
+/*
+ * Widgets related to the pages table
+ */
+extern Widget pageButton;
+extern Widget printAllButton;
+extern Widget printMarkedButton;
+extern Widget printUnmarkedButton;
+extern Widget clearMarksButton;
+
+/*
+ * Error dialog widgets
+ */
+
+extern Widget errorMsgBox;
+extern Widget errorText;
+extern Widget clearButton;
+
+/*
+ * Things that build widgets
+ */
+
+extern void BuildErrorBox();
+extern void BuildFileLevel();
+extern void BuildPageLevel();
diff --git a/dviware/umddvi/previewers/texx2/texx2.c b/dviware/umddvi/previewers/texx2/texx2.c
new file mode 100644
index 0000000000..4b15cc4f51
--- /dev/null
+++ b/dviware/umddvi/previewers/texx2/texx2.c
@@ -0,0 +1,104 @@
+/*
+ * This program is Copyright (C) 1987 by the Board of Trustees of the
+ * University of Illinois, and by the author Dirk Grunwald.
+ */
+
+#include "texx2.h"
+#include "texx2-mark.h"
+
+char *ProgName, *ClassName;
+
+extern void BuildTopLevelWidget();
+
+TeXxResourceStruct TeXxResources;
+
+#define Offset(field) (XtOffset(TeXxResourceStruct *, field))
+
+static XtResource resources[] = {
+ {"print", XtCString, XtRString, sizeof(char *),
+ Offset(printProgram), XtRString, "Dvi "},
+
+ {"mag", XtCString, XtRInt, sizeof(int),
+ Offset(userMag), XtRString, "500"},
+
+ {"paperWidth", XtCString, XtRString, sizeof(char *),
+ Offset(paperWidthString), XtRString, "8.5"},
+
+ {"paperHeight", XtCString, XtRString, sizeof(char *),
+ Offset(paperHeightString), XtRString, "11.5"},
+
+ {"smallMag", XtCString, XtRInt, sizeof(int),
+ Offset(smallMag), XtRString, "333"},
+
+ {"largeMag", XtCString, XtRInt, sizeof(int),
+ Offset(largeMag), XtRString, "500"},
+
+ {"dpi", XtCString, XtRInt, sizeof(int),
+ Offset(dpi), XtRString, "300"},
+
+ {"autoSize", XtCString, XtRBool, sizeof(Bool),
+ Offset(autoSize), XtRString, "True"}
+};
+
+static XrmOptionDescRec Options[] = {
+ {"-print", "*.print", XrmoptionSepArg, (caddr_t) NULL},
+ {"-mag", "*.mag", XrmoptionSepArg, (caddr_t) NULL},
+ {"-paperWidth", "*.paperWidth", XrmoptionSepArg, (caddr_t) NULL},
+ {"-paperHeight", "*.paperHeight", XrmoptionSepArg, (caddr_t) NULL},
+ {"-smallMag", "*.smallMag", XrmoptionSepArg, (caddr_t) NULL},
+ {"-largeMag", "*.largeMag", XrmoptionSepArg, (caddr_t) NULL},
+ {"-dpi", "*.dpi", XrmoptionSepArg, (caddr_t) NULL},
+ {"-autoSize", "*.autoSize", XrmoptionSepArg, (caddr_t) NULL}
+};
+
+int Argc;
+char **Argv;
+
+Widget TopLevelWidget;
+
+void
+main(argc,argv)
+char ** argv;
+int argc;
+{
+
+ Argc = argc;
+ Argv = argv;
+
+ ClassName = "Texx2";
+
+ if( (ProgName = index(argv[0], '/')) == NULL )
+ ProgName = argv[0];
+
+ TopLevelWidget = XtInitialize(ProgName, ClassName,
+ Options, XtNumber(Options),
+ &Argc, Argv);
+
+ XtGetApplicationResources(TopLevelWidget,
+ (caddr_t) &TeXxResources,
+ resources, XtNumber(resources),
+ NULL, (Cardinal) 0);
+
+
+ BuildTopLevelWidget(TopLevelWidget);
+ XtRealizeWidget(TopLevelWidget);
+
+ if ( Argc > 1 ) {
+ struct stat buf;
+
+ /* set file first incase it's a relative path name */
+
+ setFileName( Argv[1] );
+ setDirectory( Argv[1] );
+ }
+ else {
+ setDirectory(".");
+ }
+
+ if ( Argc > 2 ) {
+ error(0,0,"Additional arguments ignored");
+ }
+
+ XtMainLoop();
+}
+
diff --git a/dviware/umddvi/previewers/texx2/texx2.h b/dviware/umddvi/previewers/texx2/texx2.h
new file mode 100644
index 0000000000..c859f091af
--- /dev/null
+++ b/dviware/umddvi/previewers/texx2/texx2.h
@@ -0,0 +1,58 @@
+/*
+ * This program is Copyright (C) 1987 by the Board of Trustees of the
+ * University of Illinois, and by the author Dirk Grunwald.
+ */
+
+/* Std system and C header files */
+
+#ifndef _tex2h_
+#define _tex2h_
+
+#include <stdio.h>
+#include <X11/Xos.h>
+#include <sys/dir.h>
+#include <sys/stat.h>
+
+/* X include files */
+
+#include <X11/X.h>
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+
+/* X toolkit header files */
+
+#include <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+
+/* Widget header files. */
+
+#include <X11/AsciiText.h>
+#include <X11/Box.h>
+#include <X11/Command.h>
+#include <X11/Dialog.h>
+#include <X11/Label.h>
+#include <X11/List.h>
+#include <X11/Scroll.h>
+#include <X11/Shell.h>
+#include <X11/VPaned.h>
+#include <X11/Viewport.h>
+
+#include "texx2-defs.h"
+
+extern char *ProgName;
+
+typedef struct {
+ char *printProgram;
+ int userMag;
+ int dpi;
+ Bool autoSize;
+ int largeMag;
+ int smallMag;
+
+ char *paperWidthString;
+ char *paperHeightString;
+} TeXxResourceStruct;
+
+extern TeXxResourceStruct TeXxResources;
+
+#endif
diff --git a/dviware/umddvi/readme b/dviware/umddvi/readme
new file mode 100644
index 0000000000..559f6877d2
--- /dev/null
+++ b/dviware/umddvi/readme
@@ -0,0 +1,35 @@
+See the file `Installation' for installation notes.
+
+Here is a quick explanation of the C-TeX directory structure.
+
+ctex
+----
+Source for C-TeX. I have not included this one, for it is far from
+complete.
+
+dev
+---
+Device drivers - Imagen and Versatec
+
+doc
+---
+Documentation. (INCOMPLETE)
+
+dvi
+---
+DVI file manipulators. As yet, there is only dviselect, but more
+are planned.
+
+h
+-
+Header files. Some of these are for C-TeX, some for device drivers,
+some for more than one purpose. Ignore the ones that appear unused.
+N.B.: these headers may be rearranged somewhat in the future.
+
+lib
+---
+Library routines, e.g., font file readers, dvi classification tables.
+
+misc
+----
+Miscellaneous stuff.
diff --git a/dviware/umddvi/readme.nyu b/dviware/umddvi/readme.nyu
new file mode 100644
index 0000000000..17a6b20b7c
--- /dev/null
+++ b/dviware/umddvi/readme.nyu
@@ -0,0 +1,8 @@
+This is Chris Torek's ctex distribution enhanced with tpic support
+for the Imagen driver and
+
+ dvidmd device driver for the DMD 5620 display
+ (see also man/dvidmd.1)
+ makefont a program to convert TeX format fonts to
+ vfont(5) (SUN) format (see misc/makefont.c)
+ libcompat a simple compatability library for System V