summaryrefslogtreecommitdiff
path: root/dviware/dvibook/libtex/dvistate.c
blob: b11f3f10ccd55a44d921c6e8e011b7860eaa2b93 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
/*
 * Copyright (c) 1987, 1989 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: /usr/src/local/tex/local/mctex/lib/RCS/dvistate.c,v 1.1 89/08/22 21:49:03 chris Exp $";
#endif

/*
 * dvistate - basic DVI machine interpreter
 */

#include <stdio.h>
#include "types.h"
#include "conv.h"
#include "dvicodes.h"
#include "error.h"
#include "fio.h"
#include "font.h"
#include "gripes.h"
#include "postamble.h"
#include "search.h"
#include "seek.h"
#include "dvistate.h"

struct dvi_state ds;

/* yech, statics! */
static struct font *(*s_deffnt)();
static int s_dpi;
static int s_errs;

static void pre(), post(), fntdef();

char *malloc();

/*
 * Read through the postamble and the preamble and set up the
 * global DVI state.  Each font is passed to (*fontfn)().
 * Upon return, the input file (fp) is positioned at the beginning
 * of the first page.
 *
 * dpi is the resolution of the printer in pixels (dots) per inch,
 * and xoffset and yoffset are the values from the -X and -Y flags
 * (default zero).  We add 1000 to each offset (since the offsets
 * are in 1/1000ths of an inch), and then multiply by dpi and divide
 * by 1000, to get the actual offset.
 *
 * If a device introduces a constant offset, e.g., of .25 inch
 * horizontally and .31 inch vertically, the caller can compensate
 * by passing (xflag - 2500) and (yflag - 3100).
 */
void
DVISetState(fp, fontfn, dpi, xoffset, yoffset)
	FILE *fp;
	struct font *(*fontfn)();
	int dpi, xoffset, yoffset;
{

	/* make sure fseek() will work */
	if ((ds.ds_fp = SeekFile(fp)) == NULL)
		error(1, -1, "unable to copy input to temp file (disk full?)");

	/* h and v must be deferred until we have a conversion */
	ds.ds_fresh.hh = ((1000 + (i32)xoffset) * dpi) / 1000;
	ds.ds_fresh.vv = ((1000 + (i32)yoffset) * dpi) / 1000;

	ds.ds_fonts = SCreate(sizeof(struct font *));
	if (ds.ds_fonts == NULL)
		error(1, 0, "cannot create font table (out of memory?)");
	s_errs = 0;
	s_dpi = dpi;
	s_deffnt = fontfn;
	ScanPostAmble(ds.ds_fp, post, fntdef);
	if (s_errs)
		GripeMissingFontsPreventOutput(s_errs);
	pre();
}

/*
 * Read the preamble and apply sanity checks.
 * The presence of a preamble is virtually certain,
 * since we have already found and read a postamble.
 */
static void
pre()
{
	register int n;
	register FILE *fp = ds.ds_fp;

	rewind(fp);
	if (GetByte(fp) != Sign8(DVI_PRE))
		GripeMissingOp("PRE");
	if (GetByte(fp) != Sign8(DVI_VERSION))
		GripeMismatchedValue("version number");
	if (GetLong(fp) != ds.ds_num)
		GripeMismatchedValue("numerator");
	if (GetLong(fp) != ds.ds_denom)
		GripeMismatchedValue("denominator");
	if (GetLong(fp) != ds.ds_dvimag)
		GripeMismatchedValue("\\magnification");
	n = UnSign8(GetByte(fp));
	while (--n >= 0)
		(void) GetByte(fp);
}

/*
 * Store the relevant information from the DVI postamble.
 */
static void
post(p)
	register struct PostAmbleInfo *p;
{
	register int n;

	ds.ds_prevpage = p->pai_PrevPagePointer;
	ds.ds_num = p->pai_Numerator;
	ds.ds_denom = p->pai_Denominator;
	ds.ds_dvimag = p->pai_DVIMag;
	ds.ds_maxheight = p->pai_TallestPageHeight;
	ds.ds_maxwidth = p->pai_WidestPageWidth;
	ds.ds_npages = p->pai_NumberOfPages;

	/* set the global conversion factor */
	SetConversion(s_dpi,
	    ds.ds_usermag, ds.ds_num, ds.ds_denom, ds.ds_dvimag);

	ds.ds_fresh.h = toSP(ds.ds_fresh.hh);
	ds.ds_fresh.v = toSP(ds.ds_fresh.vv);
#ifdef unneeded			/* counting on init-to-zero ... */
	ds.ds_fresh.w = 0;
	ds.ds_fresh.x = 0;
	ds.ds_fresh.y = 0;
	ds.ds_fresh.z = 0;
#endif
	/* make the stack */
	n = p->pai_DVIStackSize * sizeof(DviStack);
	if ((ds.ds_stack = (struct dvi_stack *)malloc((unsigned)n)) == NULL)
		GripeOutOfMemory(n, "DVI stack");
	ds.ds_sp = ds.ds_stack;
}

/*
 * Handle a font definition from the postamble.
 */
static void
fntdef(p)
	register struct PostAmbleFont *p;
{
	register struct font *f, **fp;
	int def = S_CREATE | S_EXCL;

	fp = (struct font **)SSearch(ds.ds_fonts, p->paf_DVIFontIndex, &def);
	if (fp == NULL) {
		if (def & S_COLL)
			GripeFontAlreadyDefined(p->paf_DVIFontIndex);
		else
			error(1, 0, "cannot stash font %ld (out of memory?)",
			    (long)p->paf_DVIFontIndex);
		/* NOTREACHED */
	}

	/* apply driver function to get font */
	f = (*s_deffnt)(p->paf_name, p->paf_DVIMag, p->paf_DVIDesignSize);
	if (f == NULL) {
		s_errs++;
		return;
	}
	*fp = f;

	/* match checksums, unless one is (or both are) zero */
	if (p->paf_DVIChecksum && f->f_checksum &&
	    p->paf_DVIChecksum != f->f_checksum)
		GripeDifferentChecksums(f->f_path, p->paf_DVIChecksum,
		    f->f_checksum);
}

/*
 * Given a font index, return the corresponding pointer.
 */
struct font *
DVIFindFont(n)
	i32 n;
{
	int x = S_LOOKUP;
	char *p;

	if ((p = SSearch(ds.ds_fonts, n, &x)) == NULL) {
		GripeNoSuchFont(n);
		/* NOTREACHED */
	}
	return (*(struct font **)p);
}

/*
 * Handle a rule: read width and height, then call the given function.
 * If `advance', move dvi position afterwards.
 */
void
DVIRule(fn, advance)
	void (*fn)();
	int advance;
{
	register i32 h, w, ww;
	register FILE *fp = ds.ds_fp;

	fGetLong(fp, h);
	fGetLong(fp, ww);
	h = ConvRule(h);
	w = ConvRule(ww);
	(*fn)(h, w);
	if (advance) {
		dvi_hh += w;
		dvi_h += ww;
		w = fromSP(dvi_h);
		FIXDRIFT(dvi_hh, w);
	}
}

/*
 * Handle a BOP: read the ten \count values and the previous page pointer,
 * reset DVI position, and call the given function.
 */
void
DVIBeginPage(fn)
	void (*fn)();
{
	register int i;
	i32 count[10];

	for (i = 0; i < 10; i++)
		count[i] = GetLong(ds.ds_fp);
	ds.ds_prevpage = GetLong(ds.ds_fp);

	/* reset DVI page position and stack pointer, then call driver */
	ds.ds_cur = ds.ds_fresh;
	ds.ds_sp = ds.ds_stack;

	(*fn)(count);
}