|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T v
Length: 24084 (0x5e14)
Types: TextFile
Names: »verser1.c«
└─⟦060c9c824⟧ Bits:30007080 DKUUG TeX 2/12/89
└─⟦this⟧ »./DVIware/laser-setters/umd-dvi/dev/verser1.c«
/*
* 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;
}