1*69c7ec87Sslatteng /*	dvar.c	1.12	84/05/24
2f92359bfSslatteng  *
3f92359bfSslatteng  * Varian driver for the new troff
4f92359bfSslatteng  *
5f92359bfSslatteng  * Authors:	BWK(BELL)
6f92359bfSslatteng  *		VCAT(berkley)
7f92359bfSslatteng  *		Richard L. Hyde, Perdue University
84da297a9Sslatteng  *		and David Slattengren, U.C. Berkeley
9f92359bfSslatteng  */
10f92359bfSslatteng 
11f92359bfSslatteng 
12f92359bfSslatteng /*******************************************************************************
13f92359bfSslatteng 
14f92359bfSslatteng     output language from troff:
15f92359bfSslatteng     all numbers are character strings
16f92359bfSslatteng 
17f92359bfSslatteng #..\n	comment
18f92359bfSslatteng sn	size in points
19f92359bfSslatteng fn	font as number from 1 to n
20*69c7ec87Sslatteng in	stipple `font' as number from 1 to n
21f92359bfSslatteng cx	ascii character x
22f92359bfSslatteng Cxyz	funny char \(xyz. terminated by white space
23f92359bfSslatteng Hn	go to absolute horizontal position n
24f92359bfSslatteng Vn	go to absolute vertical position n (down is positive)
25f92359bfSslatteng hn	go n units horizontally (relative)
26f92359bfSslatteng vn	ditto vertically
27f92359bfSslatteng nnc	move right nn, then print c (exactly 2 digits!)
28f92359bfSslatteng 		(this wart is an optimization that shrinks output file size
29f92359bfSslatteng 		 about 35% and run-time about 15% while preserving ascii-ness)
30f92359bfSslatteng p	new page begins -- set v to 0
31f92359bfSslatteng nb a	end of line (information only -- no action needed)
32f92359bfSslatteng 	b = space before line, a = after
33f92359bfSslatteng w	paddable word space -- no action needed
34f92359bfSslatteng 
35f92359bfSslatteng Dt ..\n	draw operation 't':
36*69c7ec87Sslatteng 	Dt d		set line thickness to d
37*69c7ec87Sslatteng 	Ds d		set line style (mask) to d
38f92359bfSslatteng 	Dl x y		line from here by x,y
39f92359bfSslatteng 	Dc d		circle of diameter d with left side here
40f92359bfSslatteng 	De x y		ellipse of axes x,y with left side here
41f92359bfSslatteng 	Da x y r	arc counter-clockwise by x,y of radius r
42f92359bfSslatteng 	D~ x y x y ...	B-spline curve by x,y then x,y ...
43*69c7ec87Sslatteng 	Dg x y x y ...	gremlin spline curve by x,y then x,y ...
44*69c7ec87Sslatteng 	Dp s x y ...	polygon by x,y then ... filled with stipple s
45f92359bfSslatteng 
46f92359bfSslatteng x ..\n	device control functions:
47f92359bfSslatteng      x i	init
48f92359bfSslatteng      x T s	name of device is s
49f92359bfSslatteng      x r n h v	resolution is n/inch h = min horizontal motion, v = min vert
50f92359bfSslatteng      x p	pause (can restart)
51f92359bfSslatteng      x s	stop -- done for ever
52f92359bfSslatteng      x t	generate trailer
53f92359bfSslatteng      x f n s	font position n contains font s
54f92359bfSslatteng      x H n	set character height to n
55f92359bfSslatteng      x S n	set slant to N
56f92359bfSslatteng 
57f92359bfSslatteng 	Subcommands like "i" are often spelled out like "init".
58f92359bfSslatteng 
59f92359bfSslatteng *******************************************************************************/
60f92359bfSslatteng 
61f92359bfSslatteng 
62f92359bfSslatteng #include <stdio.h>
63f92359bfSslatteng #include <ctype.h>
64f92359bfSslatteng #include <sys/vcmd.h>
65f92359bfSslatteng #include "dev.h"
66f92359bfSslatteng 
67f92359bfSslatteng 
681c9df754Sslatteng /* #define DEBUGABLE		/* No, not debugable... */
691c9df754Sslatteng #define DRIVER  		/* Yes, we're driving directly */
701c9df754Sslatteng /* #define FULLPAGE		/* No, don't output full pages */
71*69c7ec87Sslatteng #define	NFONTS	65		/* total number of fonts useable */
72f92359bfSslatteng #define	MAXSTATE 6		/* number of environments rememberable */
73f92359bfSslatteng #define OPENREAD 0		/* mode for openning files */
74f92359bfSslatteng #define RESTART	1		/* upon exit, return either RESTART */
75f92359bfSslatteng #define ABORT	2		/*     or ABORT */
76f92359bfSslatteng #define	FATAL	1		/* type of error */
77f92359bfSslatteng #define	BMASK	0377		/* byte grabber */
7822d5b456Sslatteng #ifndef FONTDIR
794da297a9Sslatteng #define FONTDIR	"/usr/lib/font"	/* default place to find font descriptions */
8022d5b456Sslatteng #endif
814da297a9Sslatteng #define BITDIR "/usr/lib/vfont" /* default place to look for font rasters */
82f92359bfSslatteng #define MAXWRIT 4096		/* max characters allowed to write at once */
83f92359bfSslatteng 
84ebd02298Sslatteng #define  hmot(n)	hgoto(hpos + n)
85f92359bfSslatteng #define  vmot(n)	vgoto(vpos + n)
86f92359bfSslatteng 
87f92359bfSslatteng 
88*69c7ec87Sslatteng char	SccsId[]= "dvar.c	1.12	84/05/24";
89f92359bfSslatteng 
90f92359bfSslatteng int	output	= 0;	/* do we do output at all? */
91f92359bfSslatteng int	nolist	= 0;	/* output page list if > 0 */
92f92359bfSslatteng int	olist[20];	/* pairs of page numbers */
93f92359bfSslatteng int	spage	= 9999;	/* stop every spage pages */
94f92359bfSslatteng int	scount	= 0;
95f92359bfSslatteng struct	dev	dev;
96f92359bfSslatteng struct	font	*fontbase[NFONTS+1];
97f92359bfSslatteng short *	pstab;		/* point size table pointer */
98f92359bfSslatteng int	nsizes;		/* number of sizes device is capable of printing */
99f92359bfSslatteng int	nfonts;		/* number of fonts device is capable of printing */
100*69c7ec87Sslatteng int	nstips;		/* number of stipple fonts device can print */
101f92359bfSslatteng int	nchtab;
102f92359bfSslatteng char *	chname;
103f92359bfSslatteng short *	chtab;
1044da297a9Sslatteng char *	fitab[NFONTS+1];	/* font inclusion table - maps ascii to ch # */
1054da297a9Sslatteng char *	widtab[NFONTS+1];	/* width table for each font */
106f92359bfSslatteng char *	codetab[NFONTS+1];	/* device codes */
1074da297a9Sslatteng char *	fontdir = FONTDIR;	/* place to find devxxx directories */
1084da297a9Sslatteng char *	bitdir = BITDIR;	/* place to find raster fonts and fontmap */
1091c9df754Sslatteng char *	fontname[NFONTS+1];	/* table of what font is on what position */
1104da297a9Sslatteng struct {			/* table of what font */
1114da297a9Sslatteng 	char fname[3];		/*   name maps to what */
1124da297a9Sslatteng 	char *ffile;		/*   filename in bitdirectory */
1134da297a9Sslatteng } fontmap[NFONTS+1];
1144da297a9Sslatteng 
115f92359bfSslatteng 
116f92359bfSslatteng #ifdef DEBUGABLE
117f92359bfSslatteng int	dbg	= 0;
118f92359bfSslatteng #endif
1194da297a9Sslatteng int	size	= -1;	/* current point size (internal pstable index) */
120f92359bfSslatteng int	font	= -1;	/* current font - not using any to start with */
121*69c7ec87Sslatteng int	stip	= -1;	/* current stipple font - not using any to start with */
122*69c7ec87Sslatteng int	stipmem	= 0;	/* current member to use from stipple font */
123f92359bfSslatteng int	hpos;		/* horizontal position we are to be at next; left = 0 */
124f92359bfSslatteng int	vpos;		/* current vertical position (down positive) */
1254da297a9Sslatteng extern	linethickness;	/* thickness (in pixels) of any drawn object */
126ebd02298Sslatteng extern	linmod;		/* line style (a bit mask - dotted, etc.) of objects */
127f92359bfSslatteng int	lastw;		/* width of last character printed */
128f92359bfSslatteng 
129f92359bfSslatteng 
130f92359bfSslatteng #define DISPATCHSIZE	256		/* must be a power of two */
131f92359bfSslatteng #define CHARMASK	(DISPATCHSIZE-1)
132f92359bfSslatteng #define DSIZ		((sizeof *dispatch)*DISPATCHSIZE)
133f92359bfSslatteng #define OUTFILE 	fileno (stdout)
1344da297a9Sslatteng #define	RES		200		/* resolution of the device (dots/in) */
135f92359bfSslatteng 
1361a4ecc79Sslatteng #define RASTER_LENGTH	2112			/* device line length */
137f92359bfSslatteng #define BYTES_PER_LINE	(RASTER_LENGTH/8)
1381c9df754Sslatteng #ifndef FULLPAGE
1391c9df754Sslatteng #	define NLINES	1600			/* page width, 8 inches */
1401c9df754Sslatteng #endif
1411c9df754Sslatteng #ifdef FULLPAGE
142ebd02298Sslatteng #	define NLINES	1700			/* page width, 8.5 inches */
1431c9df754Sslatteng #endif
144f92359bfSslatteng #define BUFFER_SIZE	(NLINES*BYTES_PER_LINE)	/* number of chars in picture */
145f92359bfSslatteng 
146f92359bfSslatteng 
147f92359bfSslatteng int	pltmode[] = { VPLOT };
148f92359bfSslatteng int	prtmode[] = { VPRINT };
149cb97edc8Sslatteng char	buffer1[BUFFER_SIZE];	/* Big line buffers  */
150cb97edc8Sslatteng char	buffer2[BUFFER_SIZE];
151cb97edc8Sslatteng char *	fill = &buffer1[0];	/* Zero origin in filling buffer */
152cb97edc8Sslatteng char *	empty = &buffer2[0];	/* Zero origin in emptying buffer */
153cb97edc8Sslatteng char *	elevel = &buffer2[0];	/* current position in emptying buffer */
154cb97edc8Sslatteng int	emptypos = NLINES;	/* amount of emptying done (initially "done") */
155cb97edc8Sslatteng 
156f92359bfSslatteng 
157f92359bfSslatteng char *	calloc();
158f92359bfSslatteng char *	nalloc();
159f92359bfSslatteng char *	allpanic();
1604dabf413Sslatteng char *	operand();
161f92359bfSslatteng 
162f92359bfSslatteng struct header {
163f92359bfSslatteng 	short	magic;
164f92359bfSslatteng 	unsigned short	size;
165f92359bfSslatteng 	short	maxx;
166f92359bfSslatteng 	short	maxy;
167f92359bfSslatteng 	short	xtnd;
168f92359bfSslatteng } header;
169f92359bfSslatteng 
170f92359bfSslatteng struct	dispatch{
171f92359bfSslatteng 	unsigned short	addr;
172f92359bfSslatteng 	short	nbytes;
173f92359bfSslatteng 	char	up;
174f92359bfSslatteng 	char	down;
175f92359bfSslatteng 	char	left;
176f92359bfSslatteng 	char	right;
177f92359bfSslatteng 	short	width;
178f92359bfSslatteng };
179f92359bfSslatteng 
180f92359bfSslatteng struct	fontdes {
181cb97edc8Sslatteng 	int	fnum;		/* if == -1, then this position is empty */
182f92359bfSslatteng 	int	psize;
183f92359bfSslatteng 	struct	dispatch *disp;
184f92359bfSslatteng 	char	*bits;
185cb97edc8Sslatteng } fontdes[NFONTS+1];		/* initialized at program start */
186f92359bfSslatteng 
187f92359bfSslatteng struct dispatch *dispatch;
188*69c7ec87Sslatteng struct dispatch *stip_disp;
189f92359bfSslatteng int	cfnum = -1;
190f92359bfSslatteng int	cpsize = 10;
191f92359bfSslatteng int	cfont = 1;
192f92359bfSslatteng char	*bits;
193*69c7ec87Sslatteng char	*stip_bits;
194*69c7ec87Sslatteng int	bordered = 1;		/* flag:  "do polygons get bordered?" */
195f92359bfSslatteng int	fontwanted = 1;		/* flag:  "has a new font been requested?" */
196f92359bfSslatteng int	nfontnum = -1;
197f92359bfSslatteng int	npsize = 10;
198f92359bfSslatteng 
199f92359bfSslatteng 
200f92359bfSslatteng 
201f92359bfSslatteng main(argc, argv)
202f92359bfSslatteng char *argv[];
203f92359bfSslatteng {
204cb97edc8Sslatteng 	register FILE *fp;
205cb97edc8Sslatteng 	register int i;
206f92359bfSslatteng 
207cb97edc8Sslatteng 	for (i = 0; i <= NFONTS; fontdes[i++].fnum = -1);
2084dabf413Sslatteng 	while (--argc > 0 && **++argv == '-') {
2094dabf413Sslatteng 		switch ((*argv)[1]) {
210f92359bfSslatteng 		case 'F':
2111c9df754Sslatteng 			bitdir = operand(&argc, &argv);
2124da297a9Sslatteng 			break;
2134da297a9Sslatteng 		case 'f':
2141c9df754Sslatteng 			fontdir = operand(&argc, &argv);
215f92359bfSslatteng 			break;
216f92359bfSslatteng 		case 'o':
2174dabf413Sslatteng 			outlist(operand(&argc, &argv));
218f92359bfSslatteng 			break;
219f92359bfSslatteng #ifdef DEBUGABLE
220f92359bfSslatteng 		case 'd':
2214dabf413Sslatteng 			dbg = atoi(operand(&argc, &argv));
222f92359bfSslatteng 			if (dbg == 0) dbg = 1;
223f92359bfSslatteng 			break;
224f92359bfSslatteng #endif
225f92359bfSslatteng 		case 's':
2264dabf413Sslatteng 			spage = atoi(operand(&argc, &argv));
227f92359bfSslatteng 			if (spage <= 0)
228f92359bfSslatteng 				spage = 9999;
229f92359bfSslatteng 			break;
230f92359bfSslatteng 		}
231f92359bfSslatteng 	}
232f92359bfSslatteng 
2331c9df754Sslatteng #ifdef DRIVER
234f92359bfSslatteng 	ioctl(OUTFILE, VSETSTATE, pltmode);
2351c9df754Sslatteng #endif
236f92359bfSslatteng 
2374dabf413Sslatteng 	if (argc < 1)
238f92359bfSslatteng 		conv(stdin);
239f92359bfSslatteng 	else
2404dabf413Sslatteng 		while (argc--) {
2414dabf413Sslatteng 			if (strcmp(*argv, "-") == 0)
242f92359bfSslatteng 				fp = stdin;
243f92359bfSslatteng 			else if ((fp = fopen(*argv, "r")) == NULL)
244f92359bfSslatteng 				error(FATAL, "can't open %s", *argv);
245f92359bfSslatteng 			conv(fp);
246f92359bfSslatteng 			fclose(fp);
2474dabf413Sslatteng 			argv++;
248f92359bfSslatteng 		}
249f92359bfSslatteng 	exit(0);
250f92359bfSslatteng }
251f92359bfSslatteng 
2524dabf413Sslatteng 
2534dabf413Sslatteng /*----------------------------------------------------------------------------*
2544dabf413Sslatteng  | Routine:	char  * operand (& argc,  & argv)
2554dabf413Sslatteng  |
2564dabf413Sslatteng  | Results:	returns address of the operand given with a command-line
2574dabf413Sslatteng  |		option.  It uses either "-Xoperand" or "-X operand", whichever
2584dabf413Sslatteng  |		is present.  The program is terminated if no option is present.
2594dabf413Sslatteng  |
2604dabf413Sslatteng  | Side Efct:	argc and argv are updated as necessary.
2614dabf413Sslatteng  *----------------------------------------------------------------------------*/
2624dabf413Sslatteng 
2634dabf413Sslatteng char *operand(argcp, argvp)
2644dabf413Sslatteng int * argcp;
2654dabf413Sslatteng char ***argvp;
2664dabf413Sslatteng {
2674dabf413Sslatteng 	if ((**argvp)[2]) return(**argvp + 2); /* operand immediately follows */
2684dabf413Sslatteng 	if ((--*argcp) <= 0)			/* no operand */
2694dabf413Sslatteng 	    error (FATAL, "command-line option operand missing.\n");
2704dabf413Sslatteng 	return(*(++(*argvp)));			/* operand next word */
2714dabf413Sslatteng }
2724dabf413Sslatteng 
2734dabf413Sslatteng 
274f92359bfSslatteng outlist(s)	/* process list of page numbers to be printed */
275f92359bfSslatteng char *s;
276f92359bfSslatteng {
277f92359bfSslatteng 	int n1, n2, i;
278f92359bfSslatteng 
279f92359bfSslatteng 	nolist = 0;
280f92359bfSslatteng 	while (*s) {
281f92359bfSslatteng 		n1 = 0;
282f92359bfSslatteng 		if (isdigit(*s))
283f92359bfSslatteng 			do
284f92359bfSslatteng 				n1 = 10 * n1 + *s++ - '0';
285f92359bfSslatteng 			while (isdigit(*s));
286f92359bfSslatteng 		else
287f92359bfSslatteng 			n1 = -9999;
288f92359bfSslatteng 		n2 = n1;
289f92359bfSslatteng 		if (*s == '-') {
290f92359bfSslatteng 			s++;
291f92359bfSslatteng 			n2 = 0;
292f92359bfSslatteng 			if (isdigit(*s))
293f92359bfSslatteng 				do
294f92359bfSslatteng 					n2 = 10 * n2 + *s++ - '0';
295f92359bfSslatteng 				while (isdigit(*s));
296f92359bfSslatteng 			else
297f92359bfSslatteng 				n2 = 9999;
298f92359bfSslatteng 		}
299f92359bfSslatteng 		olist[nolist++] = n1;
300f92359bfSslatteng 		olist[nolist++] = n2;
301f92359bfSslatteng 		if (*s != '\0')
302f92359bfSslatteng 			s++;
303f92359bfSslatteng 	}
304f92359bfSslatteng 	olist[nolist] = 0;
305f92359bfSslatteng #ifdef DEBUGABLE
306f92359bfSslatteng 	if (dbg)
307f92359bfSslatteng 		for (i=0; i<nolist; i += 2)
308f92359bfSslatteng 			fprintf(stderr,"%3d %3d\n", olist[i], olist[i+1]);
309f92359bfSslatteng #endif
310f92359bfSslatteng }
311f92359bfSslatteng 
312f92359bfSslatteng conv(fp)
313f92359bfSslatteng register FILE *fp;
314f92359bfSslatteng {
315f92359bfSslatteng 	register int c, k;
316f92359bfSslatteng 	int m, n, n1, m1;
317f92359bfSslatteng 	char str[100], buf[300];
318f92359bfSslatteng 
319f92359bfSslatteng 	while ((c = getc(fp)) != EOF) {
320f92359bfSslatteng 		switch (c) {
321f92359bfSslatteng 		case '\n':	/* when input is text */
322f92359bfSslatteng 		case ' ':
323f92359bfSslatteng 		case 0:		/* occasional noise creeps in */
324f92359bfSslatteng 			break;
325f92359bfSslatteng 		case '{':	/* push down current environment */
326f92359bfSslatteng 			t_push();
327f92359bfSslatteng 			break;
328f92359bfSslatteng 		case '}':
329f92359bfSslatteng 			t_pop();
330f92359bfSslatteng 			break;
331f92359bfSslatteng 		case '0': case '1': case '2': case '3': case '4':
332f92359bfSslatteng 		case '5': case '6': case '7': case '8': case '9':
333f92359bfSslatteng 			/* two motion digits plus a character */
334f92359bfSslatteng 			hmot((c-'0')*10 + getc(fp)-'0');
335f92359bfSslatteng 			put1(getc(fp));
336f92359bfSslatteng 			break;
337f92359bfSslatteng 		case 'c':	/* single ascii character */
338f92359bfSslatteng 			put1(getc(fp));
339f92359bfSslatteng 			break;
340f92359bfSslatteng 		case 'C':
341f92359bfSslatteng 			fscanf(fp, "%s", str);
342f92359bfSslatteng 			put1s(str);
343f92359bfSslatteng 			break;
344f92359bfSslatteng 		case 't':	/* straight text */
345f92359bfSslatteng 			fgets(buf, sizeof(buf), fp);
346f92359bfSslatteng 			t_text(buf);
347f92359bfSslatteng 			break;
348f92359bfSslatteng 		case 'D':	/* draw function */
349289ea231Sslatteng 			if (fgets(buf, sizeof(buf), fp) == NULL)
350289ea231Sslatteng 			    error(FATAL, "unexpected end of input");;
351f92359bfSslatteng 			switch (buf[0]) {
352f92359bfSslatteng 			case 'l':	/* draw a line */
353f92359bfSslatteng 			    sscanf(buf+1, "%d %d", &n, &m);
354f92359bfSslatteng 			    drawline(n, m);
355f92359bfSslatteng 			    break;
356f92359bfSslatteng 			case 'c':	/* circle */
357f92359bfSslatteng 			    sscanf(buf+1, "%d", &n);
358f92359bfSslatteng 			    drawcirc(n);
359f92359bfSslatteng 			    break;
360f92359bfSslatteng 			case 'e':	/* ellipse */
361f92359bfSslatteng 			    sscanf(buf+1, "%d %d", &m, &n);
362f92359bfSslatteng 			    drawellip(m, n);
363f92359bfSslatteng 			    break;
364f92359bfSslatteng 			case 'a':	/* arc */
365f92359bfSslatteng 			    sscanf(buf+1, "%d %d %d %d", &n, &m, &n1, &m1);
366f92359bfSslatteng 			    drawarc(n, m, n1, m1);
367f92359bfSslatteng 			    break;
368*69c7ec87Sslatteng 			case 'P':	/* unbordered polygon */
369*69c7ec87Sslatteng 			    bordered = 0;		/* unset border flag */
370*69c7ec87Sslatteng 			case 'p':	/* polygon */
371*69c7ec87Sslatteng 			    sscanf(buf+1, "%d", &m);	/* get stipple */
372*69c7ec87Sslatteng 			    n = 1;			/* number first */
373*69c7ec87Sslatteng 			    while (buf[++n] == ' ');
374*69c7ec87Sslatteng 			    while (isdigit(buf[++n]));
375*69c7ec87Sslatteng 			    setfill(m);			/* set up stipple */
376*69c7ec87Sslatteng 			    drawwig(buf+n, fp, -1);	/* draw polygon */
377*69c7ec87Sslatteng 			    bordered = 1;		/* ALWAYS set after */
378*69c7ec87Sslatteng 			    break;
379f92359bfSslatteng 			case '~':	/* wiggly line */
380*69c7ec87Sslatteng 			    drawwig(buf+1, fp, 1);
381*69c7ec87Sslatteng 			    break;
3821a4ecc79Sslatteng 			case 'g':	/* gremlin spline */
383*69c7ec87Sslatteng 			    drawwig(buf+1, fp, 0);
3841a4ecc79Sslatteng 			    break;
3851a4ecc79Sslatteng 			case 't':	/* line thickness */
3861a4ecc79Sslatteng 			    sscanf(buf+1, "%d", &n);
3871a4ecc79Sslatteng 			    drawthick(n);
3881a4ecc79Sslatteng 			    break;
3891a4ecc79Sslatteng 			case 's':	/* line style */
3901a4ecc79Sslatteng 			    sscanf(buf+1, "%d", &n);
3911a4ecc79Sslatteng 			    drawstyle(n);
392f92359bfSslatteng 			    break;
393f92359bfSslatteng 			default:
394ebd02298Sslatteng 			    error(FATAL, "unknown drawing function %s", buf);
395f92359bfSslatteng 			    break;
396f92359bfSslatteng 			}
397f92359bfSslatteng 			break;
398f92359bfSslatteng 		case 's':
399f92359bfSslatteng 			fscanf(fp, "%d", &n);	/* ignore fractional sizes */
400f92359bfSslatteng 			setsize(t_size(n));
401f92359bfSslatteng 			break;
402f92359bfSslatteng 		case 'f':
403f92359bfSslatteng 			fscanf(fp, "%s", str);
404f92359bfSslatteng 			setfont(t_font(str));
405f92359bfSslatteng 			break;
406*69c7ec87Sslatteng 		case 'i':
407*69c7ec87Sslatteng 			fscanf(fp, "%d", &n);
408*69c7ec87Sslatteng 			setstip(n);
409*69c7ec87Sslatteng 			break;
410f92359bfSslatteng 		case 'H':	/* absolute horizontal motion */
411f92359bfSslatteng 			/* fscanf(fp, "%d", &n); */
412f92359bfSslatteng 			while ((c = getc(fp)) == ' ')
413f92359bfSslatteng 				;
414f92359bfSslatteng 			k = 0;
415f92359bfSslatteng 			do {
416f92359bfSslatteng 				k = 10 * k + c - '0';
417f92359bfSslatteng 			} while (isdigit(c = getc(fp)));
418f92359bfSslatteng 			ungetc(c, fp);
419f92359bfSslatteng 			hgoto(k);
420f92359bfSslatteng 			break;
421f92359bfSslatteng 		case 'h':	/* relative horizontal motion */
422f92359bfSslatteng 			while ((c = getc(fp)) == ' ')
423f92359bfSslatteng 				;
424f92359bfSslatteng 			k = 0;
425f92359bfSslatteng 			do {
426f92359bfSslatteng 				k = 10 * k + c - '0';
427f92359bfSslatteng 			} while (isdigit(c = getc(fp)));
428f92359bfSslatteng 			ungetc(c, fp);
429f92359bfSslatteng 			hmot(k);
430f92359bfSslatteng 			break;
431f92359bfSslatteng 		case 'w':	/* word space */
432f92359bfSslatteng 			break;
433f92359bfSslatteng 		case 'V':
434f92359bfSslatteng 			fscanf(fp, "%d", &n);
435f92359bfSslatteng 			vgoto(n);
436f92359bfSslatteng 			break;
437f92359bfSslatteng 		case 'v':
438f92359bfSslatteng 			fscanf(fp, "%d", &n);
439f92359bfSslatteng 			vmot(n);
440f92359bfSslatteng 			break;
441f92359bfSslatteng 		case 'p':	/* new page */
442f92359bfSslatteng 			fscanf(fp, "%d", &n);
443f92359bfSslatteng 			t_page(n);
444f92359bfSslatteng 			break;
445f92359bfSslatteng 		case 'n':	/* end of line */
446f92359bfSslatteng 			t_newline();
447289ea231Sslatteng 
448f92359bfSslatteng 		case '#':	/* comment */
449289ea231Sslatteng 			do
450289ea231Sslatteng 				c = getc(fp);
451289ea231Sslatteng 			while (c != '\n' && c != EOF);
452f92359bfSslatteng 			break;
453f92359bfSslatteng 		case 'x':	/* device control */
45419de12e6Sslatteng 			if (devcntrl(fp)) return;
455f92359bfSslatteng 			break;
456f92359bfSslatteng 		default:
457ebd02298Sslatteng 			error(FATAL, "unknown input character %o %c", c, c);
458f92359bfSslatteng 		}
459cb97edc8Sslatteng 		if (emptypos < NLINES) {	/* for each input operation */
460cb97edc8Sslatteng 			slop_lines(1);		/* put out an output line */
461cb97edc8Sslatteng #ifdef DRIVER
462cb97edc8Sslatteng 			if (emptypos == NLINES) {
463cb97edc8Sslatteng 				ioctl(OUTFILE, VSETSTATE, prtmode);
464cb97edc8Sslatteng 				if (write(OUTFILE, "\f", 2) != 2)
465cb97edc8Sslatteng 					exit(RESTART);
466cb97edc8Sslatteng 				ioctl(OUTFILE, VSETSTATE, pltmode);
467cb97edc8Sslatteng 			}
468cb97edc8Sslatteng #endif
469cb97edc8Sslatteng 		}
470f92359bfSslatteng 	}
471f92359bfSslatteng }
472f92359bfSslatteng 
47319de12e6Sslatteng int devcntrl(fp)	/* interpret device control functions */
47419de12e6Sslatteng FILE *fp;		/* returns -1 upon "stop" command */
475f92359bfSslatteng {
476f92359bfSslatteng         char str[20], str1[50], buf[50];
477f92359bfSslatteng 	int c, n;
478f92359bfSslatteng 
479f92359bfSslatteng 	fscanf(fp, "%s", str);
480f92359bfSslatteng 	switch (str[0]) {	/* crude for now */
481f92359bfSslatteng 	case 'i':	/* initialize */
482f92359bfSslatteng 		fileinit();
483f92359bfSslatteng 		t_init();
484f92359bfSslatteng 		break;
485f92359bfSslatteng 	case 't':	/* trailer */
486f92359bfSslatteng 		break;
487f92359bfSslatteng 	case 'p':	/* pause -- can restart */
488f92359bfSslatteng 		t_reset('p');
489f92359bfSslatteng 		break;
490f92359bfSslatteng 	case 's':	/* stop */
491f92359bfSslatteng 		t_reset('s');
49219de12e6Sslatteng 		return -1;
493f92359bfSslatteng 	case 'r':	/* resolution assumed when prepared */
4944da297a9Sslatteng 		fscanf(fp, "%d", &n);
495*69c7ec87Sslatteng 		if (n!=RES) error(FATAL,"Input computed for wrong printer");
496f92359bfSslatteng 		break;
497f92359bfSslatteng 	case 'f':	/* font used */
498f92359bfSslatteng 		fscanf(fp, "%d %s", &n, str);
499f92359bfSslatteng 		fgets(buf, sizeof buf, fp);	/* in case there's a filename */
500f92359bfSslatteng 		ungetc('\n', fp);		/* fgets goes too far */
501f92359bfSslatteng 		str1[0] = 0;			/* in case nothing comes in */
502f92359bfSslatteng 		sscanf(buf, "%s", str1);
503f92359bfSslatteng 		loadfont(n, str, str1);
504f92359bfSslatteng 		break;
505f92359bfSslatteng 						/* these don't belong here... */
506f92359bfSslatteng 	case 'H':	/* char height */
507f92359bfSslatteng 		fscanf(fp, "%d", &n);
508f92359bfSslatteng 		t_charht(n);
509f92359bfSslatteng 		break;
510f92359bfSslatteng 	case 'S':	/* slant */
511f92359bfSslatteng 		fscanf(fp, "%d", &n);
512f92359bfSslatteng 		t_slant(n);
513f92359bfSslatteng 		break;
514f92359bfSslatteng 	}
515f92359bfSslatteng 	while ((c = getc(fp)) != '\n')	/* skip rest of input line */
516f92359bfSslatteng 		if (c == EOF)
51719de12e6Sslatteng 			return -1;
51819de12e6Sslatteng 	return 0;
519f92359bfSslatteng }
520f92359bfSslatteng 
521f92359bfSslatteng /* fileinit:	read in font and code files, etc.
522f92359bfSslatteng 		Must open table for device, read in resolution,
5234da297a9Sslatteng 		size info, font info, etc. and set params.
5244da297a9Sslatteng 		Also read in font name mapping.
525f92359bfSslatteng */
5264da297a9Sslatteng 
527f92359bfSslatteng fileinit()
528f92359bfSslatteng {
5294da297a9Sslatteng 	register int i;
5304da297a9Sslatteng 	register int fin;
5314da297a9Sslatteng 	register int nw;
5324da297a9Sslatteng 	register char *filebase;
5334da297a9Sslatteng 	register char *p;
5344da297a9Sslatteng 	register FILE *fp;
5354da297a9Sslatteng 	char	temp[100];
5364da297a9Sslatteng 
5374da297a9Sslatteng 		/* first, read in font map file.  The file must be of Format:
5384da297a9Sslatteng 			XX  FILENAME  (XX = troff font name)
5394da297a9Sslatteng 			with one entry per text line of the file.
5404da297a9Sslatteng 		   Extra stuff after FILENAME is ignored */
5414da297a9Sslatteng 
5424da297a9Sslatteng 	sprintf(temp, "%s/fontmap", bitdir);
5434da297a9Sslatteng 	if ((fp = fopen(temp, "r")) == NULL)
5444da297a9Sslatteng 		error(FATAL, "Can't open %s", temp);
5454da297a9Sslatteng 	for (i = 0; i <= NFONTS && fgets(temp, 100, fp) != NULL; i++) {
5464da297a9Sslatteng 		sscanf(temp, "%2s", fontmap[i].fname);
5474da297a9Sslatteng 		p = &temp[0];
5484da297a9Sslatteng 		while (*p != ' ' && *p != '	') p++;
5494da297a9Sslatteng 		while (*p == ' ' || *p == '	') p++;
5504da297a9Sslatteng 		filebase = p;
5514da297a9Sslatteng 		for (nw = 1; *p != '\n' && *p != ' ' && *p != '\t'; p++) nw++;
5524da297a9Sslatteng 		fontmap[i].ffile = nalloc(1, nw);
5534da297a9Sslatteng 		sscanf(filebase, "%s", fontmap[i].ffile);
5544da297a9Sslatteng 	}
5554da297a9Sslatteng 	fontmap[++i].fname[0] = '0';		/* finish off with zeros */
5564da297a9Sslatteng 	fontmap[i].ffile = (char *) 0;
5574da297a9Sslatteng 	fclose(fp);
5584da297a9Sslatteng #ifdef DEBUGABLE
5594da297a9Sslatteng 	if(dbg) {
5604da297a9Sslatteng 	    fprintf(stderr, "font map:\n");
5614da297a9Sslatteng 	    for (i = 0; fontmap[i].ffile; i++)
5624da297a9Sslatteng 		fprintf(stderr,"%s = %s\n", fontmap[i].fname, fontmap[i].ffile);
5634da297a9Sslatteng 	}
5644da297a9Sslatteng #endif
565f92359bfSslatteng 
566cb97edc8Sslatteng 	sprintf(temp, "%s/devva/DESC.out", fontdir);
567f92359bfSslatteng 	if ((fin = open(temp, 0)) < 0)
568ebd02298Sslatteng 		error(FATAL, "can't open tables for %s", temp);
569f92359bfSslatteng 	read(fin, &dev, sizeof(struct dev));
570f92359bfSslatteng 	nfonts = dev.nfonts;
571*69c7ec87Sslatteng 	nstips = dev.nstips;
572f92359bfSslatteng 	nsizes = dev.nsizes;
573f92359bfSslatteng 	nchtab = dev.nchtab;
574f92359bfSslatteng 	filebase = calloc(1, dev.filesize);	/* enough room for whole file */
575f92359bfSslatteng 	read(fin, filebase, dev.filesize);	/* all at once */
576f92359bfSslatteng 	pstab = (short *) filebase;
577f92359bfSslatteng 	chtab = pstab + nsizes + 1;
578f92359bfSslatteng 	chname = (char *) (chtab + dev.nchtab);
579f92359bfSslatteng 	p = chname + dev.lchname;
580f92359bfSslatteng 	for (i = 1; i <= nfonts; i++) {
581f92359bfSslatteng 		fontbase[i] = (struct font *) p;
582f92359bfSslatteng 		nw = *p & BMASK;		/* 1st thing is width count */
5831c9df754Sslatteng 		p += sizeof(struct font);
584f92359bfSslatteng 		widtab[i] = p;
585f92359bfSslatteng 		codetab[i] = p + 2 * nw;
586f92359bfSslatteng 		fitab[i] = p + 3 * nw;
587f92359bfSslatteng 		p += 3 * nw + dev.nchtab + 128 - 32;
588f92359bfSslatteng 		t_fp(i, fontbase[i]->namefont, fontbase[i]->intname);
589f92359bfSslatteng #ifdef DEBUGABLE
590f92359bfSslatteng 		if (dbg > 1) fontprint(i);
591f92359bfSslatteng #endif
592f92359bfSslatteng 	}
593*69c7ec87Sslatteng 	for (i = 1; i <= nstips; i++) {		/* add in stipple "filenames" */
594*69c7ec87Sslatteng 		if (nfonts + i <= NFONTS)
595*69c7ec87Sslatteng 			t_fp(nfonts + i, p, (char *)0);
596*69c7ec87Sslatteng 		p += strlen(p) + 1;
597*69c7ec87Sslatteng 	}
598f92359bfSslatteng 	fontbase[0] = (struct font *)
599f92359bfSslatteng 		calloc(1,3*255 + dev.nchtab + (128-32) + sizeof (struct font));
600f92359bfSslatteng 	widtab[0] = (char *) fontbase[0] + sizeof (struct font);
601f92359bfSslatteng 	fontbase[0]->nwfont = 255;
602f92359bfSslatteng 	close(fin);
6034da297a9Sslatteng 
604f92359bfSslatteng }
605f92359bfSslatteng 
6064da297a9Sslatteng 
6076dfd4b55Sslatteng #ifdef DEBUGABLE
608f92359bfSslatteng fontprint(i)	/* debugging print of font i (0,...) */
609f92359bfSslatteng {
610f92359bfSslatteng 	int j, n;
611f92359bfSslatteng 	char *p;
612f92359bfSslatteng 
613f92359bfSslatteng 	fprintf(stderr,"font %d:\n", i);
614f92359bfSslatteng 	p = (char *) fontbase[i];
615f92359bfSslatteng 	n = fontbase[i]->nwfont & BMASK;
616f92359bfSslatteng 	fprintf(stderr,
617f92359bfSslatteng 	    "base=0%o, nchars=%d, spec=%d, name=%s, widtab=0%o, fitab=0%o\n",p,
618f92359bfSslatteng 	    n,fontbase[i]->specfont,fontbase[i]->namefont,widtab[i],fitab[i]);
619f92359bfSslatteng 	fprintf(stderr,"widths:\n");
620f92359bfSslatteng 	for (j=0; j <= n; j++) {
621f92359bfSslatteng 		fprintf(stderr," %2d", widtab[i][j] & BMASK);
622f92359bfSslatteng 		if (j % 20 == 19) fprintf(stderr,"\n");
623f92359bfSslatteng 	}
624f92359bfSslatteng 	fprintf(stderr,"\ncodetab:\n");
625f92359bfSslatteng 	for (j=0; j <= n; j++) {
626f92359bfSslatteng 		fprintf(stderr," %2d", codetab[i][j] & BMASK);
627f92359bfSslatteng 		if (j % 20 == 19) fprintf(stderr,"\n");
628f92359bfSslatteng 	}
629f92359bfSslatteng 	fprintf(stderr,"\nfitab:\n");
630f92359bfSslatteng 	for (j=0; j <= dev.nchtab + 128-32; j++) {
631f92359bfSslatteng 		fprintf(stderr," %2d", fitab[i][j] & BMASK);
632f92359bfSslatteng 		if (j % 20 == 19) fprintf(stderr,"\n");
633f92359bfSslatteng 	}
634f92359bfSslatteng 	fprintf(stderr,"\n");
635f92359bfSslatteng }
6366dfd4b55Sslatteng #endif
637f92359bfSslatteng 
63819de12e6Sslatteng 
639f92359bfSslatteng loadfont(n, s, s1)	/* load font info for font s on position n (0...) */
640f92359bfSslatteng int n;
641f92359bfSslatteng char *s, *s1;
642f92359bfSslatteng {
643f92359bfSslatteng 	char temp[60];
64419de12e6Sslatteng 	register int fin;
64519de12e6Sslatteng 	register int nw;
64619de12e6Sslatteng 	register int norig;
6474da297a9Sslatteng 
648f92359bfSslatteng 	if (n < 0 || n > NFONTS)
649f92359bfSslatteng 		error(FATAL, "illegal fp command %d %s", n, s);
650f92359bfSslatteng 	if (strcmp(s, fontbase[n]->namefont) == 0)
651f92359bfSslatteng 		return;
65219de12e6Sslatteng 
65319de12e6Sslatteng 	for (fin = 1; fin <= NFONTS; fin++)	/* first check to see if the */
65419de12e6Sslatteng 	    if (strcmp(s, fontbase[fin]->namefont) == 0) {  /* font is loaded */
65519de12e6Sslatteng 		register char *c;			    /* somewhere else */
65619de12e6Sslatteng 
65719de12e6Sslatteng #define ptrswap(x, y) { c = (char*) (x); x = y; y = c; }
6586dfd4b55Sslatteng #define ptrfswap(x, y) { c = (char*) (x); x = y; y = (struct font *) c; }
65919de12e6Sslatteng 
6606dfd4b55Sslatteng 		ptrfswap(fontbase[n], fontbase[fin]);
66119de12e6Sslatteng 		ptrswap(codetab[n], codetab[fin]);
66219de12e6Sslatteng 		ptrswap(widtab[n], widtab[fin]);
66319de12e6Sslatteng 		ptrswap(fitab[n], fitab[fin]);
66419de12e6Sslatteng 		t_fp(n, fontbase[n]->namefont, fontbase[n]->intname);
66519de12e6Sslatteng 		t_fp(fin, fontbase[fin]->namefont, fontbase[fin]->intname);
66619de12e6Sslatteng 		return;
66719de12e6Sslatteng 	    }
66819de12e6Sslatteng 
669f92359bfSslatteng 	if (s1 == NULL || s1[0] == '\0')
670cb97edc8Sslatteng 		sprintf(temp, "%s/devva/%s.out", fontdir, s);
671f92359bfSslatteng 	else
672f92359bfSslatteng 		sprintf(temp, "%s/%s.out", s1, s);
673f92359bfSslatteng 	if ((fin = open(temp, 0)) < 0)
674f92359bfSslatteng 		error(FATAL, "can't open font table %s", temp);
675f92359bfSslatteng 	norig = fontbase[n]->nwfont & BMASK;
676f92359bfSslatteng 	read(fin, fontbase[n], 3*norig + nchtab+128-32 + sizeof(struct font));
677f92359bfSslatteng 	if ((fontbase[n]->nwfont & BMASK) > norig)
678ebd02298Sslatteng 		error(FATAL, "Font %s too big for position %d", s, n);
679f92359bfSslatteng 	close(fin);
680f92359bfSslatteng 	nw = fontbase[n]->nwfont & BMASK;
681f92359bfSslatteng 	widtab[n] = (char *) fontbase[n] + sizeof(struct font);
682f92359bfSslatteng 	codetab[n] = (char *) widtab[n] + 2 * nw;
683f92359bfSslatteng 	fitab[n] = (char *) widtab[n] + 3 * nw;
684f92359bfSslatteng 	t_fp(n, fontbase[n]->namefont, fontbase[n]->intname);
685f92359bfSslatteng 	fontbase[n]->nwfont = norig;	/* to later use full original size */
686f92359bfSslatteng #ifdef DEBUGABLE
687f92359bfSslatteng 	if (dbg > 1) fontprint(n);
688f92359bfSslatteng #endif
689f92359bfSslatteng }
690f92359bfSslatteng 
691ebd02298Sslatteng 
692f92359bfSslatteng /*VARARGS1*/
693f92359bfSslatteng error(f, s, a1, a2, a3, a4, a5, a6, a7) {
694ebd02298Sslatteng 	fprintf(stderr, "dvar: ");
695f92359bfSslatteng 	fprintf(stderr, s, a1, a2, a3, a4, a5, a6, a7);
696f92359bfSslatteng 	fprintf(stderr, "\n");
6971c9df754Sslatteng 	if (f) exit(ABORT);
698f92359bfSslatteng }
699f92359bfSslatteng 
700f92359bfSslatteng 
701f92359bfSslatteng t_init()	/* initialize device */
702f92359bfSslatteng {
703f92359bfSslatteng 	int i;
704f92359bfSslatteng 
705f92359bfSslatteng 	hpos = vpos = 0;
706f92359bfSslatteng 
707f92359bfSslatteng 	setsize(t_size(10));	/* start somewhere */
708f92359bfSslatteng 	setfont(1);
709f92359bfSslatteng }
710f92359bfSslatteng 
711f92359bfSslatteng 
712f92359bfSslatteng struct state {
713f92359bfSslatteng 	int	ssize;
714f92359bfSslatteng 	int	sfont;
715f92359bfSslatteng 	int	shpos;
716f92359bfSslatteng 	int	svpos;
717ebd02298Sslatteng 	int	sstyle;
718ebd02298Sslatteng 	int	sthick;
719f92359bfSslatteng };
720f92359bfSslatteng struct	state	state[MAXSTATE];
721f92359bfSslatteng struct	state	*statep = state;
722f92359bfSslatteng 
723f92359bfSslatteng t_push()	/* begin a new block */
724f92359bfSslatteng {
725f92359bfSslatteng 	statep->ssize = size;
726f92359bfSslatteng 	statep->sfont = font;
727ebd02298Sslatteng 	statep->sstyle = linmod;
728ebd02298Sslatteng 	statep->sthick = linethickness;
729f92359bfSslatteng 	statep->shpos = hpos;
730f92359bfSslatteng 	statep->svpos = vpos;
731f92359bfSslatteng 	if (statep++ >= state+MAXSTATE)
732f92359bfSslatteng 		error(FATAL, "{ nested too deep");
733f92359bfSslatteng }
734f92359bfSslatteng 
735f92359bfSslatteng t_pop()	/* pop to previous state */
736f92359bfSslatteng {
737f92359bfSslatteng 	if (--statep < state)
738f92359bfSslatteng 		error(FATAL, "extra }");
739f92359bfSslatteng 	size = statep->ssize;
740f92359bfSslatteng 	font = statep->sfont;
741f92359bfSslatteng 	hpos = statep->shpos;
742f92359bfSslatteng 	vpos = statep->svpos;
743ebd02298Sslatteng 	linmod = statep->sstyle;
744ebd02298Sslatteng 	linethickness = statep->sthick;
745f92359bfSslatteng }
746f92359bfSslatteng 
747f92359bfSslatteng t_page(n)	/* do whatever new page functions */
748f92359bfSslatteng {
749f92359bfSslatteng 	int i;
750f92359bfSslatteng 
751f92359bfSslatteng 
752cb97edc8Sslatteng 	if (emptypos < NLINES) {		/* finish off last page, if */
753cb97edc8Sslatteng 		slop_lines(NLINES - emptypos);	/* it's not done yet */
7541c9df754Sslatteng #ifdef DRIVER
755f92359bfSslatteng 		ioctl(OUTFILE, VSETSTATE, prtmode);
756f92359bfSslatteng 		if (write(OUTFILE, "\f", 2) != 2)
757f92359bfSslatteng 			exit(RESTART);
758f92359bfSslatteng 		ioctl(OUTFILE, VSETSTATE, pltmode);
7591c9df754Sslatteng #endif
760f92359bfSslatteng 	}
761cb97edc8Sslatteng 	if (output) {
762cb97edc8Sslatteng 		emptypos = 0;		/* set emptying to be started */
763cb97edc8Sslatteng 		elevel = fill;		/* swap buffer pointers */
764cb97edc8Sslatteng 		fill = empty;
765cb97edc8Sslatteng 		empty = elevel;
766cb97edc8Sslatteng 	}
767f92359bfSslatteng 
768f92359bfSslatteng 	vpos = 0;
769f92359bfSslatteng 	output = 1;
770f92359bfSslatteng 	if (nolist == 0)
771f92359bfSslatteng 		return;		/* no -o specified */
772f92359bfSslatteng 	output = 0;
773f92359bfSslatteng 	for (i = 0; i < nolist; i += 2)
774f92359bfSslatteng 		if (n >= olist[i] && n <= olist[i+1]) {
775f92359bfSslatteng 			output = 1;
776f92359bfSslatteng 			break;
777f92359bfSslatteng 		}
778f92359bfSslatteng }
779f92359bfSslatteng 
780f92359bfSslatteng t_newline()	/* do whatever for the end of a line */
781f92359bfSslatteng {
782f92359bfSslatteng 	hpos = 0;	/* because we're now back at the left margin */
783f92359bfSslatteng }
784f92359bfSslatteng 
785f92359bfSslatteng t_size(n)	/* convert integer to internal size number*/
786f92359bfSslatteng int n;
787f92359bfSslatteng {
788f92359bfSslatteng 	int i;
789f92359bfSslatteng 
790f92359bfSslatteng 	if (n <= pstab[0])
7914da297a9Sslatteng 		return(0);
792f92359bfSslatteng 	else if (n >= pstab[nsizes - 1])
7934da297a9Sslatteng 		return(nsizes - 1);
794f92359bfSslatteng 	for (i = 0; n > pstab[i]; i++)
795f92359bfSslatteng 		;
7964da297a9Sslatteng 	return(i);
797f92359bfSslatteng }
798f92359bfSslatteng 
799f92359bfSslatteng t_charht(n)	/* set character height to n */
800f92359bfSslatteng int n;
801f92359bfSslatteng {
802f92359bfSslatteng #ifdef DEBUGABLE
8034da297a9Sslatteng 	if (dbg) error(!FATAL, "can't set height on varian");
804f92359bfSslatteng #endif
805f92359bfSslatteng }
806f92359bfSslatteng 
807f92359bfSslatteng t_slant(n)	/* set slant to n */
808f92359bfSslatteng int n;
809f92359bfSslatteng {
810f92359bfSslatteng #ifdef DEBUGABLE
8114da297a9Sslatteng 	if (dbg) error(!FATAL, "can't set slant on varian");
812f92359bfSslatteng #endif
813f92359bfSslatteng }
814f92359bfSslatteng 
815f92359bfSslatteng t_font(s)	/* convert string to internal font number */
816f92359bfSslatteng char *s;
817f92359bfSslatteng {
818f92359bfSslatteng 	int n;
819f92359bfSslatteng 
820f92359bfSslatteng 	n = atoi(s);
821f92359bfSslatteng 	if (n < 0 || n > nfonts)
822f92359bfSslatteng 		n = 1;
823f92359bfSslatteng 	return(n);
824f92359bfSslatteng }
825f92359bfSslatteng 
826f92359bfSslatteng t_text(s)	/* print string s as text */
827f92359bfSslatteng char *s;
828f92359bfSslatteng {
829f92359bfSslatteng 	int c;
830f92359bfSslatteng 	char str[100];
831f92359bfSslatteng 
832f92359bfSslatteng 	if (!output)
833f92359bfSslatteng 		return;
834f92359bfSslatteng 	while (c = *s++) {
835f92359bfSslatteng 		if (c == '\\') {
836f92359bfSslatteng 			switch (c = *s++) {
837f92359bfSslatteng 			case '\\':
838f92359bfSslatteng 			case 'e':
839f92359bfSslatteng 				put1('\\');
840f92359bfSslatteng 				break;
841f92359bfSslatteng 			case '(':
842f92359bfSslatteng 				str[0] = *s++;
843f92359bfSslatteng 				str[1] = *s++;
844f92359bfSslatteng 				str[2] = '\0';
845f92359bfSslatteng 				put1s(str);
846f92359bfSslatteng 				break;
847f92359bfSslatteng 			}
848f92359bfSslatteng 		} else {
849f92359bfSslatteng 			put1(c);
850f92359bfSslatteng 		}
851f92359bfSslatteng 		hmot(lastw);
852f92359bfSslatteng #ifdef DEBUGABLE
853f92359bfSslatteng 		if (dbg) fprintf(stderr,"width = %d\n", lastw);
854f92359bfSslatteng #endif
855f92359bfSslatteng 	}
856f92359bfSslatteng }
857f92359bfSslatteng 
858cb97edc8Sslatteng 
859f92359bfSslatteng t_reset(c)
860f92359bfSslatteng {
861cb97edc8Sslatteng 	if (c == 's') {
862cb97edc8Sslatteng 		t_page();
863cb97edc8Sslatteng 		output = 0;
864cb97edc8Sslatteng 		t_page();
8651c9df754Sslatteng #ifdef DRIVER
866f92359bfSslatteng 		ioctl(OUTFILE, VSETSTATE, prtmode);
867f92359bfSslatteng 		if (write(OUTFILE, "\f", 2) != 2)
868f92359bfSslatteng 			exit(RESTART);
8691c9df754Sslatteng #endif
870f92359bfSslatteng 	}
871f92359bfSslatteng }
872f92359bfSslatteng 
873ebd02298Sslatteng 
874ebd02298Sslatteng /*----------------------------------------------------------------------------*
875ebd02298Sslatteng  | Routine:	hgoto (horizontal_spot)
876ebd02298Sslatteng  |
877ebd02298Sslatteng  | Results:	hpos is set to n.  If n overlaps in either direction, it wraps
878ebd02298Sslatteng  |		around to the other end of the page.
879ebd02298Sslatteng  *----------------------------------------------------------------------------*/
880ebd02298Sslatteng 
881ebd02298Sslatteng hgoto(n)
882ebd02298Sslatteng int n;
883f92359bfSslatteng {
884ebd02298Sslatteng     if (n < 0)
885ebd02298Sslatteng 	n += NLINES;
886ebd02298Sslatteng     else if (n >= NLINES)
887ebd02298Sslatteng 	n -= NLINES;
888ebd02298Sslatteng     hpos = n;
889f92359bfSslatteng }
890ebd02298Sslatteng 
891ebd02298Sslatteng 
892ebd02298Sslatteng /*----------------------------------------------------------------------------*
893ebd02298Sslatteng  | Routine:	vgoto (vertical_spot)
894ebd02298Sslatteng  |
895ebd02298Sslatteng  | Results:	vpos is set to n.  If n overlaps in either direction, it wraps
896ebd02298Sslatteng  |		around to the other end of the page.
897ebd02298Sslatteng  *----------------------------------------------------------------------------*/
898ebd02298Sslatteng 
899ebd02298Sslatteng vgoto(n)
900ebd02298Sslatteng int n;
901ebd02298Sslatteng {
902ebd02298Sslatteng     if (n < 0)
903ebd02298Sslatteng 	n += RASTER_LENGTH;
904ebd02298Sslatteng     else if (n > RASTER_LENGTH)
905ebd02298Sslatteng 	n -= RASTER_LENGTH;
906f92359bfSslatteng     vpos = n;
907f92359bfSslatteng }
908f92359bfSslatteng 
909f92359bfSslatteng put1s(s)	/* s is a funny char name */
910f92359bfSslatteng char *s;
911f92359bfSslatteng {
912f92359bfSslatteng 	int i;
913f92359bfSslatteng 
914f92359bfSslatteng 	if (!output)
915f92359bfSslatteng 		return;
916f92359bfSslatteng #ifdef DEBUGABLE
917f92359bfSslatteng 	if (dbg) fprintf(stderr,"%s ", s);
918f92359bfSslatteng #endif
919f92359bfSslatteng 	for (i = 0; i < nchtab; i++)
920f92359bfSslatteng 		if (strcmp(&chname[chtab[i]], s) == 0)
921f92359bfSslatteng 			break;
922f92359bfSslatteng 	if (i < nchtab)
923f92359bfSslatteng 		put1(i + 128);
924f92359bfSslatteng }
925f92359bfSslatteng 
926f92359bfSslatteng put1(c)	/* output char c */
927f92359bfSslatteng int c;
928f92359bfSslatteng {
929f92359bfSslatteng 	char *pw;
930f92359bfSslatteng 	register char *p;
931f92359bfSslatteng 	register int i, k;
932f92359bfSslatteng 	int j, ofont, code;
933f92359bfSslatteng 
934f92359bfSslatteng 	if (!output)
935f92359bfSslatteng 		return;
936f92359bfSslatteng 	c -= 32;
937f92359bfSslatteng 	if (c <= 0) {
938f92359bfSslatteng #ifdef DEBUGABLE
939f92359bfSslatteng 		if (dbg) fprintf(stderr,"non-exist 0%o\n", c + 32);
940f92359bfSslatteng #endif
9414da297a9Sslatteng  		lastw = (widtab[font][0] * pstab[size] + dev.unitwidth/2)
942f92359bfSslatteng 								/ dev.unitwidth;
943f92359bfSslatteng 		return;
944f92359bfSslatteng 	}
945f92359bfSslatteng 	k = ofont = font;
946f92359bfSslatteng 	i = fitab[font][c] & BMASK;
947f92359bfSslatteng 	if (i != 0) {			/* it's on this font */
948f92359bfSslatteng 		p = codetab[font];	/* get the printing value of ch */
949f92359bfSslatteng 		pw = widtab[font];	/* get the width */
9506dfd4b55Sslatteng 	} else {		/* on another font - run down the font list */
9516dfd4b55Sslatteng 		for (j=0; j++ <= nfonts; k = (k+1) % (nfonts+1)) {
952f92359bfSslatteng 			if (fitab[k] == 0)
953f92359bfSslatteng 				continue;
954f92359bfSslatteng 			if ((i=fitab[k][c] & BMASK) != 0) {
955f92359bfSslatteng 				p = codetab[k];
956f92359bfSslatteng 				pw = widtab[k];
957f92359bfSslatteng 				setfont(k);
958f92359bfSslatteng 				break;
959f92359bfSslatteng 			}
960f92359bfSslatteng 		}
9616dfd4b55Sslatteng 	}
9621c9df754Sslatteng 
9636dfd4b55Sslatteng 	if (i == 0) {
964f92359bfSslatteng #ifdef DEBUGABLE
965f92359bfSslatteng 		if (dbg) fprintf(stderr,"not found 0%o\n", c+32);
966f92359bfSslatteng #endif
967f92359bfSslatteng 		return;
968f92359bfSslatteng 	}
9696dfd4b55Sslatteng 	code = p[i] & BMASK;
970f92359bfSslatteng #ifdef DEBUGABLE
971f92359bfSslatteng 	if (dbg) {
972f92359bfSslatteng 		if (isprint(c+32))
973f92359bfSslatteng 			fprintf(stderr,"%c %d\n", c+32, code);
974f92359bfSslatteng 		else
975f92359bfSslatteng 			fprintf(stderr,"%03o %d\n", c+32, code);
976f92359bfSslatteng 	}
977f92359bfSslatteng #endif
978f92359bfSslatteng 	outc(code);	/* character is < 254 */
979f92359bfSslatteng 	if (font != ofont)
980f92359bfSslatteng 		setfont(ofont);
9814da297a9Sslatteng 	lastw = ((pw[i]&077) * pstab[size] + dev.unitwidth/2) / dev.unitwidth;
982f92359bfSslatteng }
983f92359bfSslatteng 
984f92359bfSslatteng 
985f92359bfSslatteng 
986f92359bfSslatteng setsize(n)	/* set point size to n (internal) */
987f92359bfSslatteng int n;
988f92359bfSslatteng {
989f92359bfSslatteng 
990f92359bfSslatteng 	if (n == size)
991f92359bfSslatteng 		return;	/* already there */
9924da297a9Sslatteng 	if (vloadfont(font, pstab[n]) != -1)
993f92359bfSslatteng 		size = n;
994f92359bfSslatteng }
995f92359bfSslatteng 
996f92359bfSslatteng t_fp(n, s, si)	/* font position n now contains font s, intname si */
9971c9df754Sslatteng int n;		/* internal name is ignored */
998f92359bfSslatteng char *s, *si;
999f92359bfSslatteng {
10004da297a9Sslatteng 	register int i;
1001f92359bfSslatteng 
10024da297a9Sslatteng 
10034da297a9Sslatteng 			/* first convert s to filename if possible */
10044da297a9Sslatteng 	for (i = 0; fontmap[i].ffile != (char *) 0; i++) {
10054da297a9Sslatteng #ifdef DEBUGABLE
10064da297a9Sslatteng 		if(dbg>1)fprintf(stderr,"testing :%s:%s:\n",s,fontmap[i].fname);
10074da297a9Sslatteng #endif
10084da297a9Sslatteng 		if (strcmp(s, fontmap[i].fname) == 0) {
10094da297a9Sslatteng 			s = fontmap[i].ffile;
10104da297a9Sslatteng #ifdef DEBUGABLE
10114da297a9Sslatteng 			if(dbg)fprintf(stderr, "found :%s:\n",fontmap[i].ffile);
10124da297a9Sslatteng #endif
10134da297a9Sslatteng 			break;
10144da297a9Sslatteng 		}
10154da297a9Sslatteng 	}
10161c9df754Sslatteng 	fontname[n] = s;
1017cb97edc8Sslatteng 	for(i = 0;i <= NFONTS;i++)	/* free the bits of that font */
1018f92359bfSslatteng 		if (fontdes[i].fnum == n){
1019f92359bfSslatteng 			nfree(fontdes[i].bits);
1020f92359bfSslatteng 			fontdes[i].fnum = -1;
1021f92359bfSslatteng 		}
1022f92359bfSslatteng }
1023f92359bfSslatteng 
10244da297a9Sslatteng 
1025f92359bfSslatteng setfont(n)	/* set font to n */
1026f92359bfSslatteng int n;
1027f92359bfSslatteng {
1028*69c7ec87Sslatteng 	if (n < 0 || n > nfonts)
1029ebd02298Sslatteng 		error(FATAL, "illegal font %d", n);
10304da297a9Sslatteng 	if (vloadfont(n,pstab[size]) != -1)
1031f92359bfSslatteng 		font = n;
1032f92359bfSslatteng }
1033f92359bfSslatteng 
1034*69c7ec87Sslatteng 
1035*69c7ec87Sslatteng setstip(n)	/* set stipple font to n */
1036*69c7ec87Sslatteng int n;
1037*69c7ec87Sslatteng {
1038*69c7ec87Sslatteng 	if (n < 1 || n > nstips)
1039*69c7ec87Sslatteng 		error(FATAL, "illegal stipple %d", n);
1040*69c7ec87Sslatteng 	stip = n;
1041*69c7ec87Sslatteng }
1042*69c7ec87Sslatteng 
1043*69c7ec87Sslatteng 
1044f92359bfSslatteng vloadfont(fnum, fsize)
1045f92359bfSslatteng register int fnum;
1046f92359bfSslatteng register int fsize;
1047f92359bfSslatteng {
1048f92359bfSslatteng 	register int i;
1049f92359bfSslatteng 
1050f92359bfSslatteng 	fontwanted = 0;
1051f92359bfSslatteng 	if (fnum == cfnum && fsize == cpsize)
1052f92359bfSslatteng 		return(0);
1053f92359bfSslatteng 	for (i = 0; i < NFONTS; i++) {
1054f92359bfSslatteng 		if (fontdes[i].fnum == fnum && fontdes[i].psize == fsize) {
1055f92359bfSslatteng 			cfnum = fontdes[i].fnum;
1056f92359bfSslatteng 			cpsize = fontdes[i].psize;
1057f92359bfSslatteng 			dispatch = &fontdes[i].disp[0];
1058f92359bfSslatteng 			bits = fontdes[i].bits;
1059f92359bfSslatteng 			cfont = i;
1060f92359bfSslatteng 			return (0);
1061f92359bfSslatteng 		}
1062f92359bfSslatteng 	}
1063f92359bfSslatteng 		/* this is a new font */
10641c9df754Sslatteng 	if (fnum < 0 || fnum > NFONTS || fontname[fnum] == 0) {
1065f92359bfSslatteng 	    fprintf(stderr, "Internal error: illegal font %d name %s size\n",
10661c9df754Sslatteng 			    fontname[fnum], fnum, fsize);
1067f92359bfSslatteng 	    return(-1);
1068f92359bfSslatteng 	}
1069f92359bfSslatteng 		/* Need to verify the existance of that font/size here*/
1070f92359bfSslatteng 	nfontnum = fnum;
1071f92359bfSslatteng 	npsize = fsize;
1072f92359bfSslatteng 	fontwanted++;
1073f92359bfSslatteng 	return (0);
1074f92359bfSslatteng }
1075f92359bfSslatteng 
1076f92359bfSslatteng 
1077f92359bfSslatteng getfont()
1078f92359bfSslatteng {
10794da297a9Sslatteng 	register int fnum;
10804da297a9Sslatteng 	register int fsize;
10814da297a9Sslatteng 	register int fontd;
10824da297a9Sslatteng 	register int d;
10831c9df754Sslatteng 	register int sizehunt = size;
1084f92359bfSslatteng 	char cbuf[BUFSIZ];
1085f92359bfSslatteng 
1086f92359bfSslatteng 	fnum = nfontnum;
1087f92359bfSslatteng 	fsize = npsize;
10884da297a9Sslatteng 			/* try to open font file - if unsuccessful, hunt for */
10894da297a9Sslatteng 			/* a file of same style, different size to substitute */
10904da297a9Sslatteng 	d = -1;	 /* direction to look in pstab (smaller first) */
10914da297a9Sslatteng 	do {
10921c9df754Sslatteng 	    sprintf(cbuf, "%s/%s.%dr", bitdir, fontname[fnum], fsize);
1093f92359bfSslatteng 	    fontd = open(cbuf, OPENREAD);
10944da297a9Sslatteng 	    if (fontd == -1) {		/* File wasn't found. Try another ps */
10951c9df754Sslatteng 		sizehunt += d;
10961c9df754Sslatteng 		if (sizehunt < 0) {	/* past beginning - look higher */
10974da297a9Sslatteng 		    d = 1;
10981c9df754Sslatteng 		    sizehunt = size + 1;
10994da297a9Sslatteng 		}
11001c9df754Sslatteng 		if (sizehunt > nsizes) {	/* past top - forget it */
11014da297a9Sslatteng 		    d = 0;
11024da297a9Sslatteng 		} else {
11031c9df754Sslatteng 		    fsize = pstab[sizehunt];
11044da297a9Sslatteng 		}
11054da297a9Sslatteng 	    }
11064da297a9Sslatteng 	} while (fontd == -1 && d != 0);
11074da297a9Sslatteng 
11084da297a9Sslatteng 	if (fontd == -1) {		/* completely unsuccessful */
1109f92359bfSslatteng 	    perror(cbuf);
11104da297a9Sslatteng 	    error(!FATAL,"fnum = %d, psize = %d, name = %s",
11111c9df754Sslatteng 		fnum, npsize, fontname[fnum]);
1112f92359bfSslatteng 	    fontwanted = 0;
1113f92359bfSslatteng 	    return (-1);
1114f92359bfSslatteng 	}
1115f92359bfSslatteng 	if (read(fontd, &header, sizeof  (header)) != sizeof (header)
1116f92359bfSslatteng 						|| header.magic != 0436)
1117f92359bfSslatteng 		fprintf(stderr, "%s: Bad font file", cbuf);
1118f92359bfSslatteng 	else {
1119f92359bfSslatteng 		cfont = relfont();
1120f92359bfSslatteng 		if ((bits=nalloc(header.size+DSIZ+1,1))== NULL)
1121f92359bfSslatteng 			if ((bits=allpanic(header.size+DSIZ+1))== NULL) {
11221c9df754Sslatteng 				error(FATAL,"%s: ran out of memory", cbuf);
1123f92359bfSslatteng 			}
1124f92359bfSslatteng 
1125f92359bfSslatteng 			/*
1126f92359bfSslatteng 			 * have allocated one chunk of mem for font, dispatch.
1127f92359bfSslatteng 			 * get the dispatch addr, align to word boundary.
1128f92359bfSslatteng 			 */
1129f92359bfSslatteng 
1130f92359bfSslatteng 		d = (int) bits+header.size;
1131f92359bfSslatteng 		d += 1;
1132f92359bfSslatteng 		d &= ~1;
1133f92359bfSslatteng 		if (read (fontd, d, DSIZ) != DSIZ
1134f92359bfSslatteng 			    || read (fontd, bits, header.size) != header.size)
1135f92359bfSslatteng 			fprintf(stderr, "bad font header");
1136f92359bfSslatteng 		else {
1137f92359bfSslatteng 			close(fontd);
1138f92359bfSslatteng 			cfnum = fontdes[cfont].fnum = fnum;
1139f92359bfSslatteng 			cpsize = fontdes[cfont].psize = fsize;
1140f92359bfSslatteng 			fontdes [cfont].bits = bits;
1141f92359bfSslatteng 			fontdes [cfont].disp = (struct dispatch *) d;
1142f92359bfSslatteng 			dispatch = &fontdes[cfont].disp[0];
1143f92359bfSslatteng 			fontwanted = 0;
1144f92359bfSslatteng 			return (0);
1145f92359bfSslatteng 		}
1146f92359bfSslatteng 	}
1147f92359bfSslatteng 	close(fontd);
1148f92359bfSslatteng 	fontwanted = 0;
1149f92359bfSslatteng 	return(-1);
1150f92359bfSslatteng }
1151f92359bfSslatteng 
1152f92359bfSslatteng /*
1153f92359bfSslatteng  * "release" a font position - find an empty one, if possible
1154f92359bfSslatteng  */
1155f92359bfSslatteng 
1156f92359bfSslatteng relfont()
1157f92359bfSslatteng {
1158f92359bfSslatteng     register int newfont;
1159f92359bfSslatteng 
1160f92359bfSslatteng     for (newfont = 0; newfont < NFONTS; newfont++)
1161cb97edc8Sslatteng 	if (fontdes [newfont].fnum == -1)
1162f92359bfSslatteng 	    break;
1163cb97edc8Sslatteng     if (fontdes [newfont].fnum != -1) {
1164f92359bfSslatteng 	nfree (fontdes [newfont].bits);
1165f92359bfSslatteng #ifdef DEBUGABLE
1166f92359bfSslatteng 	if (dbg) fprintf (stderr, "freeing position %d\n", newfont);
1167f92359bfSslatteng     } else {
1168f92359bfSslatteng 	if (dbg)
1169f92359bfSslatteng 	    fprintf (stderr, "taking, not freeing, position %d\n", newfont);
1170f92359bfSslatteng #endif
1171f92359bfSslatteng     }
1172cb97edc8Sslatteng     fontdes[newfont].fnum = -1;
1173f92359bfSslatteng     return (newfont);
1174f92359bfSslatteng }
1175f92359bfSslatteng 
1176f92359bfSslatteng char *allpanic (nbytes)
1177f92359bfSslatteng int nbytes;
1178f92359bfSslatteng {
1179f92359bfSslatteng 	register int i;
1180f92359bfSslatteng 
1181f92359bfSslatteng 	for (i = 0; i <= NFONTS; i++) {
1182cb97edc8Sslatteng 		if (fontdes[i].fnum != -1) nfree(fontdes[i].bits);
1183cb97edc8Sslatteng 		fontdes[i].fnum = -1;
1184f92359bfSslatteng 		cfnum = cpsize = -1;
1185f92359bfSslatteng 	}
1186f92359bfSslatteng 	return(nalloc(nbytes,1));
1187f92359bfSslatteng }
1188f92359bfSslatteng 
1189f92359bfSslatteng int	M[] = { 0xffffffff, 0xfefefefe, 0xfcfcfcfc, 0xf8f8f8f8,
1190f92359bfSslatteng 		0xf0f0f0f0, 0xe0e0e0e0, 0xc0c0c0c0, 0x80808080, 0x0 };
1191f92359bfSslatteng int	N[] = { 0x00000000, 0x01010101, 0x03030303, 0x07070707,
1192f92359bfSslatteng 		0x0f0f0f0f, 0x1f1f1f1f, 0x3f3f3f3f, 0x7f7f7f7f, 0xffffffff };
1193f92359bfSslatteng int	strim[] = { 0xffffffff, 0xffffff00, 0xffff0000, 0xff000000, 0 };
1194f92359bfSslatteng 
1195f92359bfSslatteng outc(code)
1196f92359bfSslatteng int code;		/* character to print */
1197f92359bfSslatteng {
1198f92359bfSslatteng     register struct dispatch *dis; /* ptr to character font record */
1199f92359bfSslatteng     register char *addr;	/* addr of font data */
1200f92359bfSslatteng     int llen;			/* length of each font line */
1201f92359bfSslatteng     int nlines;			/* number of font lines */
1202f92359bfSslatteng     register char *scanp;	/* ptr to output buffer */
1203f92359bfSslatteng     int scanp_inc;		/* increment to start of next buffer */
1204f92359bfSslatteng     int offset;			/* bit offset to start of font data */
12054da297a9Sslatteng     register int i;		/* loop counter */
1206f92359bfSslatteng     register int count;		/* font data ptr */
1207f92359bfSslatteng     register unsigned fontdata;	/* font data temporary */
1208f92359bfSslatteng     register int off8;		/* offset + 8 */
1209f92359bfSslatteng 
1210f92359bfSslatteng     if (fontwanted)
1211f92359bfSslatteng 	getfont();
1212f92359bfSslatteng     dis = dispatch + code;
1213f92359bfSslatteng     if (dis->nbytes) {
1214f92359bfSslatteng 	addr = bits + dis->addr;
12151a4ecc79Sslatteng 	llen = (dis->up + dis->down + 7) >> 3;
12161a4ecc79Sslatteng 	nlines = dis->right + dis->left;
1217cb97edc8Sslatteng 	scanp = fill + (hpos + 1 - dis->left) * BYTES_PER_LINE
1218cb97edc8Sslatteng 			- (1 + ((dis->down + vpos - 1) >> 3));
1219cb97edc8Sslatteng 	if (scanp < fill)
1220cb97edc8Sslatteng 	    scanp += BUFFER_SIZE;
1221f92359bfSslatteng 	scanp_inc = BYTES_PER_LINE - llen;
1222cb97edc8Sslatteng 	off8 = ((dis->down + vpos - 1) &07);
12231a4ecc79Sslatteng 	offset = off8 - 8;
1224f92359bfSslatteng 	for (i = 0; i < nlines; i++) {
1225cb97edc8Sslatteng 	    if (scanp >= fill + BUFFER_SIZE)
12261c9df754Sslatteng 		scanp -= BUFFER_SIZE;
1227f92359bfSslatteng 	    count = llen;
1228cb97edc8Sslatteng 	    if (scanp + count < fill + BUFFER_SIZE) {
1229f92359bfSslatteng 		do {
1230f92359bfSslatteng 		    fontdata = *(unsigned *)addr;
1231f92359bfSslatteng 		    addr += 4;
1232f92359bfSslatteng 		    if (count < 4)
1233f92359bfSslatteng 			fontdata &= ~strim[count];
1234f92359bfSslatteng 		    *(unsigned*)scanp |=(fontdata << offset) & ~M[off8];
1235f92359bfSslatteng 		    scanp++;
1236f92359bfSslatteng 		    *(unsigned*)scanp |=(fontdata << off8) & ~N[off8];
1237f92359bfSslatteng 		    scanp += 3;
1238f92359bfSslatteng 		    count -= 4;
1239f92359bfSslatteng 		} while (count > 0);
1240f92359bfSslatteng 	    }
1241f92359bfSslatteng 	    scanp += scanp_inc+count;
1242f92359bfSslatteng 	    addr += count;
1243f92359bfSslatteng 	}
1244f92359bfSslatteng 	return;
1245f92359bfSslatteng     }
1246f92359bfSslatteng     return;
1247f92359bfSslatteng }
1248f92359bfSslatteng 
1249*69c7ec87Sslatteng 
1250*69c7ec87Sslatteng /*----------------------------------------------------------------------------*
1251*69c7ec87Sslatteng  | Routine:	setfill(stipple_number)
1252*69c7ec87Sslatteng  |
1253*69c7ec87Sslatteng  | Results:	sets the fill-pattern pointers (stip_disp and
1254*69c7ec87Sslatteng  |		stip_bits) for a particular stipple.  Takes stipple
1255*69c7ec87Sslatteng  |		font from current "stip" number.
1256*69c7ec87Sslatteng  *----------------------------------------------------------------------------*/
1257*69c7ec87Sslatteng 
1258*69c7ec87Sslatteng setfill(number)
1259*69c7ec87Sslatteng int number;
1260*69c7ec87Sslatteng {
1261*69c7ec87Sslatteng 	int curfont;		/* places to save current text font */
1262*69c7ec87Sslatteng 	int cursize;
1263*69c7ec87Sslatteng 
1264*69c7ec87Sslatteng 					/* set global stipmem for polygon */
1265*69c7ec87Sslatteng 	if (number < 0 || number >= DISPATCHSIZE)
1266*69c7ec87Sslatteng 		stipmem = 0;
1267*69c7ec87Sslatteng 	else
1268*69c7ec87Sslatteng 		stipmem = number;
1269*69c7ec87Sslatteng 
1270*69c7ec87Sslatteng 	curfont = cfnum;		/* get pointers to */
1271*69c7ec87Sslatteng 	cursize = cpsize;		/* the inuse font */
1272*69c7ec87Sslatteng 	if (vloadfont(nfonts + stip, 0)) {
1273*69c7ec87Sslatteng 	    stip_disp = (struct dispatch *) NULL;	/* stipple not here */
1274*69c7ec87Sslatteng 	} else {
1275*69c7ec87Sslatteng 	    if (fontwanted) {
1276*69c7ec87Sslatteng 		if (getfont()) {
1277*69c7ec87Sslatteng 		    stip_disp = (struct dispatch *) NULL;
1278*69c7ec87Sslatteng 		} else {
1279*69c7ec87Sslatteng 		    stip_disp = dispatch;	/* save for polygon routine */
1280*69c7ec87Sslatteng 		    stip_bits = bits;
1281*69c7ec87Sslatteng 		}
1282*69c7ec87Sslatteng 	    } else {
1283*69c7ec87Sslatteng 		stip_disp = dispatch;	/* save for polygon routine */
1284*69c7ec87Sslatteng 		stip_bits = bits;
1285*69c7ec87Sslatteng 	    }
1286*69c7ec87Sslatteng 	}
1287*69c7ec87Sslatteng 	vloadfont(curfont, cursize);
1288*69c7ec87Sslatteng }
1289*69c7ec87Sslatteng 
1290*69c7ec87Sslatteng 
1291f92359bfSslatteng slop_lines(nlines)
1292f92359bfSslatteng int nlines;
1293f92359bfSslatteng 
1294f92359bfSslatteng /* Output "nlines" lines from the buffer, and clear that section of the  */
1295cb97edc8Sslatteng /* buffer.	Also updates the pointers to the emptying buffer */
1296f92359bfSslatteng 
1297f92359bfSslatteng {
1298f92359bfSslatteng 	unsigned usize;
1299f92359bfSslatteng 
1300f92359bfSslatteng 	usize = BYTES_PER_LINE * nlines;
1301cb97edc8Sslatteng 	vwrite(elevel, usize);
1302cb97edc8Sslatteng 	vclear(elevel, usize);
1303cb97edc8Sslatteng 	elevel += usize;
1304cb97edc8Sslatteng 	emptypos += nlines;
1305f92359bfSslatteng }
1306f92359bfSslatteng 
13074da297a9Sslatteng vwrite(buf,usize)
1308f92359bfSslatteng char *buf;
1309f92359bfSslatteng unsigned usize;
1310f92359bfSslatteng {
1311f92359bfSslatteng 	register int tsize = 0;
1312f92359bfSslatteng 
1313f92359bfSslatteng 	while (usize){
1314f92359bfSslatteng 		buf += tsize;
1315f92359bfSslatteng 		tsize = usize > MAXWRIT ? MAXWRIT : usize;
1316f92359bfSslatteng #ifdef DEBUGABLE
1317f92359bfSslatteng 		if (dbg)fprintf(stderr,"buf = %d size = %d\n",buf,tsize);
1318f92359bfSslatteng #endif
1319f92359bfSslatteng 		if ((tsize = write(OUTFILE, buf, tsize)) < 0) {
1320ebd02298Sslatteng 			perror("dvar: write failed");
1321f92359bfSslatteng 			exit(RESTART);
1322f92359bfSslatteng 		}
1323f92359bfSslatteng 		usize -= tsize;
1324f92359bfSslatteng 	}
1325f92359bfSslatteng }
1326f92359bfSslatteng 
1327f92359bfSslatteng vclear (ptr, nbytes)
1328f92359bfSslatteng char	*ptr;
1329f92359bfSslatteng unsigned nbytes;
1330f92359bfSslatteng {
1331f92359bfSslatteng     register tsize = 0;
1332f92359bfSslatteng 
1333f92359bfSslatteng     while (nbytes){
1334f92359bfSslatteng 	if ((unsigned)(16*1024) < nbytes) {
1335f92359bfSslatteng 	    tsize = 16 * 1024;
1336f92359bfSslatteng 	} else
1337f92359bfSslatteng 	    tsize = nbytes;
1338f92359bfSslatteng 	nbytes -= tsize;
1339f92359bfSslatteng #ifdef DEBUGABLE
1340f92359bfSslatteng 	if (dbg) fprintf(stderr,"clearing ptr = %d size = %d\n",ptr,tsize);
1341f92359bfSslatteng #endif
1342f92359bfSslatteng 	clear(ptr,tsize);
1343f92359bfSslatteng 	ptr += tsize;
1344f92359bfSslatteng     }
1345f92359bfSslatteng }
1346f92359bfSslatteng 
1347f92359bfSslatteng /*ARGSUSED*/
1348f92359bfSslatteng clear(lp, nbytes)
1349f92359bfSslatteng int *lp;
1350f92359bfSslatteng int nbytes;
1351f92359bfSslatteng {
1352f92359bfSslatteng 	asm("movc5 $0,(sp),$0,8(ap),*4(ap)");
1353f92359bfSslatteng }
1354f92359bfSslatteng 
1355f92359bfSslatteng char *
1356f92359bfSslatteng nalloc(i, j)
1357f92359bfSslatteng int i, j;
1358f92359bfSslatteng {
1359f92359bfSslatteng 	register char *cp;
1360f92359bfSslatteng 
1361f92359bfSslatteng 	cp = calloc(i, j);
1362f92359bfSslatteng #ifdef DEBUGABLE
1363f92359bfSslatteng 	if (dbg) fprintf(stderr, "allocated %d bytes at %x\n", i * j, cp);
1364f92359bfSslatteng #endif
1365f92359bfSslatteng 	return(cp);
1366f92359bfSslatteng }
1367f92359bfSslatteng 
1368f92359bfSslatteng nfree(cp)
1369f92359bfSslatteng char *cp;
1370f92359bfSslatteng {
1371f92359bfSslatteng #ifdef DEBUGABLE
1372f92359bfSslatteng 	if (dbg) fprintf(stderr, "freeing at %x\n", cp);
1373f92359bfSslatteng #endif
1374f92359bfSslatteng 	free(cp);
1375f92359bfSslatteng }
1376f92359bfSslatteng 
1377f92359bfSslatteng 
1378f92359bfSslatteng /*
1379f92359bfSslatteng  * Points should be in the range 0 <= x < RASTER_LENGTH, 0 <= y < NLINES.
1380f92359bfSslatteng  * The origin is the top left-hand corner with increasing x towards the
13814da297a9Sslatteng  * right and increasing y going down.  X and Y should be sent as (0,0) being
13824da297a9Sslatteng  * at the bottom left.  The output array is NLINES x BYTES_PER_LINE pixels.
1383f92359bfSslatteng  */
1384f92359bfSslatteng point(x, y)
13851a4ecc79Sslatteng register int x;
13861a4ecc79Sslatteng register int y;
1387f92359bfSslatteng {
1388*69c7ec87Sslatteng     if ((unsigned)(y=(RASTER_LENGTH-1)-y)<RASTER_LENGTH && (unsigned)x<NLINES) {
1389cb97edc8Sslatteng 	*(fill + x * BYTES_PER_LINE + (y >> 3)) |= 1 << (7 - (y & 07));
1390f92359bfSslatteng     }
1391f92359bfSslatteng }
1392*69c7ec87Sslatteng 
1393*69c7ec87Sslatteng 
1394*69c7ec87Sslatteng #define pv(x)	((polyvector *)x)
1395*69c7ec87Sslatteng 
1396*69c7ec87Sslatteng typedef struct poly {
1397*69c7ec87Sslatteng 	struct poly *next;	/* doublely-linked lists of vectors */
1398*69c7ec87Sslatteng 	struct poly *prev;
1399*69c7ec87Sslatteng 	int param;	/* bressenham line algorithm parameter */
1400*69c7ec87Sslatteng 	short dy;	/* delta-y for calculating line */
1401*69c7ec87Sslatteng 	short dx;	/* delta-x for calculating line */
1402*69c7ec87Sslatteng 	short curry;	/* current y in this vector */
1403*69c7ec87Sslatteng 	short endx;	/* where vector ends */
1404*69c7ec87Sslatteng } polyvector;
1405*69c7ec87Sslatteng 
1406*69c7ec87Sslatteng 
1407*69c7ec87Sslatteng /*----------------------------------------------------------------------------*
1408*69c7ec87Sslatteng  | Routine:	polygon ( x_coordinates, y_coordinates, num_of_points )
1409*69c7ec87Sslatteng  |
1410*69c7ec87Sslatteng  | Results:	draws a polygon starting at (x[1], y[1]) going through
1411*69c7ec87Sslatteng  |		each of (x_coordinates, y_coordinates), and fills it
1412*69c7ec87Sslatteng  |		with a stipple pattern from stip_disp and stip_bits,
1413*69c7ec87Sslatteng  |		which point to the stipple font.  The pattern is defined
1414*69c7ec87Sslatteng  |		by "stip" and "stipmem".
1415*69c7ec87Sslatteng  |
1416*69c7ec87Sslatteng  |		The scan-line algorithm implemented scans from left to
1417*69c7ec87Sslatteng  |		right (low x to high x).  It also scans, within a line,
1418*69c7ec87Sslatteng  |		from bottom to top (high y to low y).
1419*69c7ec87Sslatteng  |
1420*69c7ec87Sslatteng  |		polygons are clipped to page boundary.
1421*69c7ec87Sslatteng  |
1422*69c7ec87Sslatteng  | Bugs:	stipple pattern MUST be a power of two bytes "wide" and
1423*69c7ec87Sslatteng  |		square.  The square restriction comes from the fact that
1424*69c7ec87Sslatteng  |		the varian and versatec are respectively rotated.
1425*69c7ec87Sslatteng  *----------------------------------------------------------------------------*/
1426*69c7ec87Sslatteng 
1427*69c7ec87Sslatteng polygon(x, y, npts)
1428*69c7ec87Sslatteng int x[];
1429*69c7ec87Sslatteng int y[];
1430*69c7ec87Sslatteng int npts;
1431*69c7ec87Sslatteng {
1432*69c7ec87Sslatteng     int nextx;			/* at what x value the next vector starts */
1433*69c7ec87Sslatteng     int maxx, minx, maxy, miny;		/* finds bounds of polygon */
1434*69c7ec87Sslatteng     polyvector *activehead;		/* doing fill, is active edge list */
1435*69c7ec87Sslatteng     polyvector *waitinghead;		/* edges waiting to be active */
1436*69c7ec87Sslatteng     register polyvector *vectptr;	/* random vector */
1437*69c7ec87Sslatteng     register int i;			/* random register */
1438*69c7ec87Sslatteng 
1439*69c7ec87Sslatteng     char *topstipple;		/* points to beginning of stipple glyph */
1440*69c7ec87Sslatteng     char *leftstipple;		/* points to beginning of line of stipple */
1441*69c7ec87Sslatteng     char *bottompage;		/* points to the edge of a raster line */
1442*69c7ec87Sslatteng     int bytewidth;		/* glyph width in bytes */
1443*69c7ec87Sslatteng     int mask;			/* mask to pick off pixel index into stipple */
1444*69c7ec87Sslatteng     int bytemask;		/* mask to pick off byte index into stipple */
1445*69c7ec87Sslatteng 
1446*69c7ec87Sslatteng 
1447*69c7ec87Sslatteng     if (bordered) {
1448*69c7ec87Sslatteng 	for (i = 1; i < npts; i++)		/* first draw outlines */
1449*69c7ec87Sslatteng 	    HGtline(x[i], y[i], x[i+1], y[i+1]);
1450*69c7ec87Sslatteng     }
1451*69c7ec87Sslatteng 
1452*69c7ec87Sslatteng 						/* if no stipple, don't fill */
1453*69c7ec87Sslatteng     if (stip_disp == (struct dispatch *) NULL || stip_bits == (char *) NULL)
1454*69c7ec87Sslatteng 	return;
1455*69c7ec87Sslatteng 
1456*69c7ec87Sslatteng     stip_disp += stipmem;			/* set up parameters for */
1457*69c7ec87Sslatteng     if (!stip_disp->nbytes) {			/* tiling with the stipple */
1458*69c7ec87Sslatteng #ifdef DEBUGABLE
1459*69c7ec87Sslatteng 	error(!FATAL, "member not found: member %d, stipple %d", stipmem, stip);
1460*69c7ec87Sslatteng #endif
1461*69c7ec87Sslatteng 	return;
1462*69c7ec87Sslatteng     }
1463*69c7ec87Sslatteng     topstipple = stip_bits + stip_disp->addr;
1464*69c7ec87Sslatteng     bytewidth = stip_disp->up + stip_disp->down;
1465*69c7ec87Sslatteng     for (i = 1 << 30; i && i != bytewidth; i = i >> 1)
1466*69c7ec87Sslatteng 	;
1467*69c7ec87Sslatteng     if (i==0 || bytewidth<8 || bytewidth != stip_disp->right+stip_disp->left) {
1468*69c7ec87Sslatteng 	error(!FATAL, "invalid stipple: number %d, member %d", stip, stipmem);
1469*69c7ec87Sslatteng 	return;
1470*69c7ec87Sslatteng     }
1471*69c7ec87Sslatteng     mask = bytewidth - 1;
1472*69c7ec87Sslatteng     bytewidth = bytewidth >> 3;
1473*69c7ec87Sslatteng     bytemask = bytewidth - 1;
1474*69c7ec87Sslatteng 
1475*69c7ec87Sslatteng 				/* allocate space for raster-fill algorithm*/
1476*69c7ec87Sslatteng     if ((vectptr = pv( nalloc(sizeof(polyvector), npts + 6) )) == NULL) {
1477*69c7ec87Sslatteng 	error(!FATAL, "unable to allocate space for polygon");
1478*69c7ec87Sslatteng 	return;
1479*69c7ec87Sslatteng     }
1480*69c7ec87Sslatteng #ifdef DEBUGABLE
1481*69c7ec87Sslatteng     if (dbg) fprintf(stderr, "polygon, %d points\n", npts);
1482*69c7ec87Sslatteng #endif
1483*69c7ec87Sslatteng 
1484*69c7ec87Sslatteng     waitinghead = vectptr;
1485*69c7ec87Sslatteng     minx = maxx = x[1];
1486*69c7ec87Sslatteng     miny = maxy = y[1];
1487*69c7ec87Sslatteng     (vectptr++)->prev = pv( NULL );	/* put dummy entry at start */
1488*69c7ec87Sslatteng     waitinghead->next = vectptr;
1489*69c7ec87Sslatteng     vectptr->prev = waitinghead;
1490*69c7ec87Sslatteng     i = 1;					/* starting point of coords */
1491*69c7ec87Sslatteng     if (y[1] != y[npts] || x[1] != x[npts]) {
1492*69c7ec87Sslatteng 	y[0] = y[npts];				/* close polygon if it's not */
1493*69c7ec87Sslatteng 	x[0] = x[npts];
1494*69c7ec87Sslatteng 	i = 0;
1495*69c7ec87Sslatteng     }
1496*69c7ec87Sslatteng     while (i < npts) {		/* set up the vectors */
1497*69c7ec87Sslatteng 	register int j;			/* indexes to work off of */
1498*69c7ec87Sslatteng 	register int k;
1499*69c7ec87Sslatteng 
1500*69c7ec87Sslatteng 	if (miny > y[i]) miny = y[i];		/* remember limits */
1501*69c7ec87Sslatteng 	else if (maxy < y[i]) maxy = y[i];
1502*69c7ec87Sslatteng 	if (maxx < x[i]) maxx = x[i];
1503*69c7ec87Sslatteng 	else if (minx > x[i]) minx = x[i];
1504*69c7ec87Sslatteng 
1505*69c7ec87Sslatteng 	j = i;			/* j "points" to the higher (lesser) point */
1506*69c7ec87Sslatteng 	k = ++i;
1507*69c7ec87Sslatteng 	if (x[j] == x[k])		/* ignore vertical lines */
1508*69c7ec87Sslatteng 	    continue;
1509*69c7ec87Sslatteng 
1510*69c7ec87Sslatteng 	if (x[j] > x[k]) {
1511*69c7ec87Sslatteng 	    j++;
1512*69c7ec87Sslatteng 	    k--;
1513*69c7ec87Sslatteng 	}
1514*69c7ec87Sslatteng 	vectptr->next = vectptr + 1;
1515*69c7ec87Sslatteng 	vectptr->param = x[j];		/* starting point of vector */
1516*69c7ec87Sslatteng 	vectptr->dy = y[k] - y[j];	/* line-calculating parameters */
1517*69c7ec87Sslatteng 	vectptr->dx = x[k] - x[j];
1518*69c7ec87Sslatteng 	vectptr->curry = y[j];		/* starting point */
1519*69c7ec87Sslatteng 	(vectptr++)->endx = x[k];	/* ending point */
1520*69c7ec87Sslatteng 	vectptr->prev = vectptr - 1;
1521*69c7ec87Sslatteng     }
1522*69c7ec87Sslatteng 				/* set now because we didn't know minx before */
1523*69c7ec87Sslatteng     leftstipple = topstipple + (minx & mask) * bytewidth;
1524*69c7ec87Sslatteng     bottompage = fill + minx * BYTES_PER_LINE;
1525*69c7ec87Sslatteng     waitinghead->param = minx - 1;
1526*69c7ec87Sslatteng 					/* if no useable vectors, quit */
1527*69c7ec87Sslatteng     if (vectptr == waitinghead + 1)
1528*69c7ec87Sslatteng 	goto leavepoly;
1529*69c7ec87Sslatteng 
1530*69c7ec87Sslatteng     vectptr->param = maxx + 1;		/* dummy entry at end, too */
1531*69c7ec87Sslatteng     vectptr->next = pv( NULL );
1532*69c7ec87Sslatteng 
1533*69c7ec87Sslatteng     activehead = ++vectptr;		/* two dummy entries for active list */
1534*69c7ec87Sslatteng     vectptr->curry = maxy + 1;		/* head */
1535*69c7ec87Sslatteng     vectptr->endx = maxx + 1;
1536*69c7ec87Sslatteng     vectptr->param = vectptr->dx = vectptr->dy = 0;
1537*69c7ec87Sslatteng     activehead->next = ++vectptr;
1538*69c7ec87Sslatteng     activehead->prev = vectptr;
1539*69c7ec87Sslatteng 
1540*69c7ec87Sslatteng     vectptr->prev = activehead;		/* tail */
1541*69c7ec87Sslatteng     vectptr->next = activehead;
1542*69c7ec87Sslatteng     vectptr->curry = miny - 1;
1543*69c7ec87Sslatteng     vectptr->endx = maxx + 1;
1544*69c7ec87Sslatteng     vectptr->param = vectptr->dx = vectptr->dy = 0;
1545*69c7ec87Sslatteng 
1546*69c7ec87Sslatteng 
1547*69c7ec87Sslatteng 			/* main loop -- gets vectors off the waiting list, */
1548*69c7ec87Sslatteng 			/* then displays spans while updating the vectors in */
1549*69c7ec87Sslatteng 			/* the active list */
1550*69c7ec87Sslatteng     while (minx <= maxx) {
1551*69c7ec87Sslatteng 	i = maxx + 1;		/* this is the NEXT time to get a new vector */
1552*69c7ec87Sslatteng 	for (vectptr = waitinghead->next; vectptr != pv( NULL ); ) {
1553*69c7ec87Sslatteng 	    if (minx == vectptr->param) {
1554*69c7ec87Sslatteng 				/* the entry in waiting list (vectptr) is */
1555*69c7ec87Sslatteng 				/*   ready to go into active list.  Need to */
1556*69c7ec87Sslatteng 				/*   convert some vector stuff and sort the */
1557*69c7ec87Sslatteng 				/*   entry into the list. */
1558*69c7ec87Sslatteng 		register polyvector *p;	/* random vector pointers */
1559*69c7ec87Sslatteng 		register polyvector *v;
1560*69c7ec87Sslatteng 
1561*69c7ec87Sslatteng 							/* convert this */
1562*69c7ec87Sslatteng 		if (vectptr->dy < 0)			/* entry to active */
1563*69c7ec87Sslatteng 		    vectptr->param = (vectptr->dy >> 1) - (vectptr->dx >> 1);
1564*69c7ec87Sslatteng 		else
1565*69c7ec87Sslatteng 		    vectptr->param = -((vectptr->dx >> 1) + (vectptr->dy >> 1));
1566*69c7ec87Sslatteng 
1567*69c7ec87Sslatteng 		p = vectptr;			/* remove from the */
1568*69c7ec87Sslatteng 		vectptr = vectptr->next;	/* waiting list */
1569*69c7ec87Sslatteng 		vectptr->prev = p->prev;
1570*69c7ec87Sslatteng 		p->prev->next = vectptr;
1571*69c7ec87Sslatteng 						/* find where it goes */
1572*69c7ec87Sslatteng 						/* in the active list */
1573*69c7ec87Sslatteng 						/* (sorted greatest first) */
1574*69c7ec87Sslatteng 		for (v = activehead->next; v->curry > p->curry; v = v->next)
1575*69c7ec87Sslatteng 		    ;
1576*69c7ec87Sslatteng 		p->next = v;		/* insert into active list */
1577*69c7ec87Sslatteng 		p->prev = v->prev;	/* before the one it stopped on */
1578*69c7ec87Sslatteng 		v->prev = p;
1579*69c7ec87Sslatteng 		p->prev->next = p;
1580*69c7ec87Sslatteng 	    } else {
1581*69c7ec87Sslatteng 		if (i > vectptr->param) {
1582*69c7ec87Sslatteng 		    i = vectptr->param;
1583*69c7ec87Sslatteng 		}
1584*69c7ec87Sslatteng 		vectptr = vectptr->next;
1585*69c7ec87Sslatteng 	    }
1586*69c7ec87Sslatteng 	}
1587*69c7ec87Sslatteng 	nextx = i;
1588*69c7ec87Sslatteng 
1589*69c7ec87Sslatteng 					/* print the polygon while there */
1590*69c7ec87Sslatteng 					/* are no more vectors to add */
1591*69c7ec87Sslatteng 	while (minx < nextx) {
1592*69c7ec87Sslatteng 					/* remove any finished vectors */
1593*69c7ec87Sslatteng 	    vectptr = activehead->next;
1594*69c7ec87Sslatteng 	    do {
1595*69c7ec87Sslatteng 		if (vectptr->endx <= minx) {
1596*69c7ec87Sslatteng 		    vectptr->prev->next = vectptr->next;
1597*69c7ec87Sslatteng 		    vectptr->next->prev = vectptr->prev;
1598*69c7ec87Sslatteng 		}
1599*69c7ec87Sslatteng 	    } while ((vectptr = vectptr->next) != activehead);
1600*69c7ec87Sslatteng 
1601*69c7ec87Sslatteng 					/* draw the span */
1602*69c7ec87Sslatteng 	    if (((unsigned) minx) < NLINES) {
1603*69c7ec87Sslatteng 	      vectptr = activehead->next;
1604*69c7ec87Sslatteng 	      while (vectptr->next != activehead) {
1605*69c7ec87Sslatteng 		register int start;	/* get the beginning */
1606*69c7ec87Sslatteng 		register int length;	/*   and the end of span */
1607*69c7ec87Sslatteng 		register char *glyph;
1608*69c7ec87Sslatteng 		register char *raster;
1609*69c7ec87Sslatteng 
1610*69c7ec87Sslatteng 		start = (RASTER_LENGTH - 1) - vectptr->curry;
1611*69c7ec87Sslatteng 		vectptr = vectptr->next;
1612*69c7ec87Sslatteng 		length = RASTER_LENGTH - vectptr->curry;
1613*69c7ec87Sslatteng 		vectptr = vectptr->next;
1614*69c7ec87Sslatteng 
1615*69c7ec87Sslatteng 					/* bound the polygon to the page */
1616*69c7ec87Sslatteng 		if (start >= RASTER_LENGTH)
1617*69c7ec87Sslatteng 		    break;
1618*69c7ec87Sslatteng 		if (start < 0) start = 0;
1619*69c7ec87Sslatteng 		if (length > RASTER_LENGTH) length = RASTER_LENGTH;
1620*69c7ec87Sslatteng 		length -= start;		/* length is in pixels */
1621*69c7ec87Sslatteng 
1622*69c7ec87Sslatteng 		i = start & 7;
1623*69c7ec87Sslatteng 		start = start >> 3;		/* start is in bytes */
1624*69c7ec87Sslatteng 		raster = bottompage + start;
1625*69c7ec87Sslatteng 		glyph = leftstipple + (start & bytemask);
1626*69c7ec87Sslatteng 
1627*69c7ec87Sslatteng 		if (i) {			/* do any piece of byte */
1628*69c7ec87Sslatteng 		    register char data;		/* that hangs on the front */
1629*69c7ec87Sslatteng 
1630*69c7ec87Sslatteng 		    data = (*(glyph++)) & (0x7f >> --i);
1631*69c7ec87Sslatteng 		    length -= 7 - i;
1632*69c7ec87Sslatteng 		    if (length < 0) {		/* less than one byte wide? */
1633*69c7ec87Sslatteng 			data &= 0xff << -length;
1634*69c7ec87Sslatteng 			length = 0;	/* force clean stoppage */
1635*69c7ec87Sslatteng 		    }
1636*69c7ec87Sslatteng 		    *(raster++) |= data;
1637*69c7ec87Sslatteng 					/* update glyph ptr after first byte */
1638*69c7ec87Sslatteng 		    if (!(++start & bytemask))
1639*69c7ec87Sslatteng 			glyph = leftstipple;
1640*69c7ec87Sslatteng 		}
1641*69c7ec87Sslatteng 						/* fill the line of raster */
1642*69c7ec87Sslatteng 		while ((length -= 8) >= 0) {
1643*69c7ec87Sslatteng 		    *(raster++) |= *(glyph++);
1644*69c7ec87Sslatteng 		    if (!(++start & bytemask))
1645*69c7ec87Sslatteng 			glyph = leftstipple;
1646*69c7ec87Sslatteng 		}
1647*69c7ec87Sslatteng 		if (length & 7) {	/* add any part hanging off the end */
1648*69c7ec87Sslatteng 		    *raster |= (*glyph) & (0xff << -length);
1649*69c7ec87Sslatteng 		}
1650*69c7ec87Sslatteng 	      }
1651*69c7ec87Sslatteng 	    }
1652*69c7ec87Sslatteng 
1653*69c7ec87Sslatteng #ifdef DEBUGABLE
1654*69c7ec87Sslatteng 	    if (dbg) {
1655*69c7ec87Sslatteng 		vectptr = activehead;
1656*69c7ec87Sslatteng 		do {
1657*69c7ec87Sslatteng 		    fprintf (stderr, "%d ", vectptr->curry);
1658*69c7ec87Sslatteng 		    vectptr = vectptr->next;
1659*69c7ec87Sslatteng 		} while (vectptr != activehead);
1660*69c7ec87Sslatteng 	    }
1661*69c7ec87Sslatteng #endif
1662*69c7ec87Sslatteng 					/* update the vectors */
1663*69c7ec87Sslatteng 	    vectptr = activehead->next;
1664*69c7ec87Sslatteng 	    do {
1665*69c7ec87Sslatteng 		if (vectptr->dy > 0) {
1666*69c7ec87Sslatteng 		    while (vectptr->param >= 0) {
1667*69c7ec87Sslatteng 			vectptr->param -= vectptr->dx;
1668*69c7ec87Sslatteng 			vectptr->curry++;
1669*69c7ec87Sslatteng 		    }
1670*69c7ec87Sslatteng 		    vectptr->param += vectptr->dy;
1671*69c7ec87Sslatteng 		} else if (vectptr->dy < 0) {
1672*69c7ec87Sslatteng 		    while (vectptr->param >= 0) {
1673*69c7ec87Sslatteng 			vectptr->param -= vectptr->dx;
1674*69c7ec87Sslatteng 			vectptr->curry--;
1675*69c7ec87Sslatteng 		    }
1676*69c7ec87Sslatteng 		    vectptr->param -= vectptr->dy;
1677*69c7ec87Sslatteng 		}
1678*69c7ec87Sslatteng 					/* must sort the vectors if updates */
1679*69c7ec87Sslatteng 					/* caused them to cross */
1680*69c7ec87Sslatteng 					/* also move to next vector here */
1681*69c7ec87Sslatteng 		if (vectptr->curry > vectptr->prev->curry) {
1682*69c7ec87Sslatteng 		    register polyvector *v;		/* vector to move */
1683*69c7ec87Sslatteng 		    register polyvector *p;	/* vector to put it after */
1684*69c7ec87Sslatteng 
1685*69c7ec87Sslatteng 		    v = vectptr;
1686*69c7ec87Sslatteng 		    p = v->prev;
1687*69c7ec87Sslatteng 		    while (v->curry > p->curry)	/* find the */
1688*69c7ec87Sslatteng 			p = p->prev;		/* right vector */
1689*69c7ec87Sslatteng 
1690*69c7ec87Sslatteng 		    vectptr = vectptr->next;	/* remove from spot */
1691*69c7ec87Sslatteng 		    vectptr->prev = v->prev;
1692*69c7ec87Sslatteng 		    v->prev->next = vectptr;
1693*69c7ec87Sslatteng 
1694*69c7ec87Sslatteng 		    v->prev = p;		/* put in new spot */
1695*69c7ec87Sslatteng 		    v->next = p->next;
1696*69c7ec87Sslatteng 		    p->next = v;
1697*69c7ec87Sslatteng 		    v->next->prev = v;
1698*69c7ec87Sslatteng 		} else {
1699*69c7ec87Sslatteng 		    vectptr = vectptr->next;
1700*69c7ec87Sslatteng 		}
1701*69c7ec87Sslatteng 	    } while (vectptr != activehead);
1702*69c7ec87Sslatteng #ifdef DEBUGABLE
1703*69c7ec87Sslatteng 	    if (dbg) fprintf(stderr, "line done\n");
1704*69c7ec87Sslatteng #endif
1705*69c7ec87Sslatteng 
1706*69c7ec87Sslatteng 	    if (++minx & mask) {
1707*69c7ec87Sslatteng 		leftstipple += bytewidth;
1708*69c7ec87Sslatteng 	    } else {
1709*69c7ec87Sslatteng 		leftstipple = topstipple;
1710*69c7ec87Sslatteng 	    }
1711*69c7ec87Sslatteng 	    bottompage += BYTES_PER_LINE;
1712*69c7ec87Sslatteng 	} /* while (minx < nextx) */
1713*69c7ec87Sslatteng     } /* while (minx <= maxx) */
1714*69c7ec87Sslatteng 
1715*69c7ec87Sslatteng leavepoly:
1716*69c7ec87Sslatteng     nfree(waitinghead);
1717*69c7ec87Sslatteng }  /* polygon function */
1718