diff options
author | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
commit | e0c6872cf40896c7be36b11dcc744620f10adf1d (patch) | |
tree | 60335e10d2f4354b0674ec22d7b53f0f8abee672 /dviware/umddvi |
Initial commit
Diffstat (limited to 'dviware/umddvi')
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 |