1*92970570Sslatteng /*	dvar.c	1.15	85/08/05
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
2069c7ec87Sslatteng 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':
3669c7ec87Sslatteng 	Dt d		set line thickness to d
3769c7ec87Sslatteng 	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 ...
4369c7ec87Sslatteng 	Dg x y x y ...	gremlin spline curve by x,y then x,y ...
4469c7ec87Sslatteng 	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 */
7169c7ec87Sslatteng #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
815b07345cSslatteng #ifndef BITDIR
824da297a9Sslatteng #define BITDIR "/usr/lib/vfont" /* default place to look for font rasters */
835b07345cSslatteng #endif
84f92359bfSslatteng #define MAXWRIT 4096		/* max characters allowed to write at once */
85f92359bfSslatteng 
86ebd02298Sslatteng #define  hmot(n)	hgoto(hpos + n)
87f92359bfSslatteng #define  vmot(n)	vgoto(vpos + n)
88f92359bfSslatteng 
89f92359bfSslatteng 
90*92970570Sslatteng char	SccsId[]= "dvar.c	1.15	85/08/05";
91f92359bfSslatteng 
92f92359bfSslatteng int	output	= 0;	/* do we do output at all? */
93f92359bfSslatteng int	nolist	= 0;	/* output page list if > 0 */
94f92359bfSslatteng int	olist[20];	/* pairs of page numbers */
95f92359bfSslatteng int	spage	= 9999;	/* stop every spage pages */
96f92359bfSslatteng int	scount	= 0;
97f92359bfSslatteng struct	dev	dev;
98f92359bfSslatteng struct	font	*fontbase[NFONTS+1];
99f92359bfSslatteng short *	pstab;		/* point size table pointer */
100f92359bfSslatteng int	nsizes;		/* number of sizes device is capable of printing */
101f92359bfSslatteng int	nfonts;		/* number of fonts device is capable of printing */
10269c7ec87Sslatteng int	nstips;		/* number of stipple fonts device can print */
103f92359bfSslatteng int	nchtab;
104f92359bfSslatteng char *	chname;
105f92359bfSslatteng short *	chtab;
1064da297a9Sslatteng char *	fitab[NFONTS+1];	/* font inclusion table - maps ascii to ch # */
1074da297a9Sslatteng char *	widtab[NFONTS+1];	/* width table for each font */
108f92359bfSslatteng char *	codetab[NFONTS+1];	/* device codes */
1094da297a9Sslatteng char *	fontdir = FONTDIR;	/* place to find devxxx directories */
1104da297a9Sslatteng char *	bitdir = BITDIR;	/* place to find raster fonts and fontmap */
1111c9df754Sslatteng char *	fontname[NFONTS+1];	/* table of what font is on what position */
1124da297a9Sslatteng struct {			/* table of what font */
1134da297a9Sslatteng 	char fname[3];		/*   name maps to what */
1144da297a9Sslatteng 	char *ffile;		/*   filename in bitdirectory */
1154da297a9Sslatteng } fontmap[NFONTS+1];
1164da297a9Sslatteng 
117f92359bfSslatteng 
118f92359bfSslatteng #ifdef DEBUGABLE
119f92359bfSslatteng int	dbg	= 0;
120f92359bfSslatteng #endif
1214da297a9Sslatteng int	size	= -1;	/* current point size (internal pstable index) */
122f92359bfSslatteng int	font	= -1;	/* current font - not using any to start with */
12369c7ec87Sslatteng int	stip	= -1;	/* current stipple font - not using any to start with */
12469c7ec87Sslatteng int	stipmem	= 0;	/* current member to use from stipple font */
125f92359bfSslatteng int	hpos;		/* horizontal position we are to be at next; left = 0 */
126f92359bfSslatteng int	vpos;		/* current vertical position (down positive) */
1274da297a9Sslatteng extern	linethickness;	/* thickness (in pixels) of any drawn object */
128ebd02298Sslatteng extern	linmod;		/* line style (a bit mask - dotted, etc.) of objects */
129f92359bfSslatteng int	lastw;		/* width of last character printed */
130f92359bfSslatteng 
131f92359bfSslatteng 
132f92359bfSslatteng #define DISPATCHSIZE	256		/* must be a power of two */
133f92359bfSslatteng #define CHARMASK	(DISPATCHSIZE-1)
134f92359bfSslatteng #define DSIZ		((sizeof *dispatch)*DISPATCHSIZE)
135f92359bfSslatteng #define OUTFILE 	fileno (stdout)
1364da297a9Sslatteng #define	RES		200		/* resolution of the device (dots/in) */
137f92359bfSslatteng 
1381a4ecc79Sslatteng #define RASTER_LENGTH	2112			/* device line length */
139f92359bfSslatteng #define BYTES_PER_LINE	(RASTER_LENGTH/8)
1401c9df754Sslatteng #ifndef FULLPAGE
1411c9df754Sslatteng #	define NLINES	1600			/* page width, 8 inches */
1421c9df754Sslatteng #endif
1431c9df754Sslatteng #ifdef FULLPAGE
144ebd02298Sslatteng #	define NLINES	1700			/* page width, 8.5 inches */
1451c9df754Sslatteng #endif
146f92359bfSslatteng #define BUFFER_SIZE	(NLINES*BYTES_PER_LINE)	/* number of chars in picture */
147f92359bfSslatteng 
148f92359bfSslatteng 
149f92359bfSslatteng int	pltmode[] = { VPLOT };
150f92359bfSslatteng int	prtmode[] = { VPRINT };
151cb97edc8Sslatteng char	buffer1[BUFFER_SIZE];	/* Big line buffers  */
152cb97edc8Sslatteng char	buffer2[BUFFER_SIZE];
153cb97edc8Sslatteng char *	fill = &buffer1[0];	/* Zero origin in filling buffer */
154cb97edc8Sslatteng char *	empty = &buffer2[0];	/* Zero origin in emptying buffer */
155cb97edc8Sslatteng char *	elevel = &buffer2[0];	/* current position in emptying buffer */
156cb97edc8Sslatteng int	emptypos = NLINES;	/* amount of emptying done (initially "done") */
157cb97edc8Sslatteng 
158f92359bfSslatteng 
159f92359bfSslatteng char *	calloc();
160f92359bfSslatteng char *	nalloc();
161f92359bfSslatteng char *	allpanic();
1624dabf413Sslatteng char *	operand();
163f92359bfSslatteng 
164f92359bfSslatteng struct header {
165f92359bfSslatteng 	short	magic;
166f92359bfSslatteng 	unsigned short	size;
167f92359bfSslatteng 	short	maxx;
168f92359bfSslatteng 	short	maxy;
169f92359bfSslatteng 	short	xtnd;
170f92359bfSslatteng } header;
171f92359bfSslatteng 
172f92359bfSslatteng struct	dispatch{
173f92359bfSslatteng 	unsigned short	addr;
174f92359bfSslatteng 	short	nbytes;
175f92359bfSslatteng 	char	up;
176f92359bfSslatteng 	char	down;
177f92359bfSslatteng 	char	left;
178f92359bfSslatteng 	char	right;
179f92359bfSslatteng 	short	width;
180f92359bfSslatteng };
181f92359bfSslatteng 
182f92359bfSslatteng struct	fontdes {
183cb97edc8Sslatteng 	int	fnum;		/* if == -1, then this position is empty */
184f92359bfSslatteng 	int	psize;
185f92359bfSslatteng 	struct	dispatch *disp;
186f92359bfSslatteng 	char	*bits;
187cb97edc8Sslatteng } fontdes[NFONTS+1];		/* initialized at program start */
188f92359bfSslatteng 
189f92359bfSslatteng struct dispatch *dispatch;
19069c7ec87Sslatteng struct dispatch *stip_disp;
191f92359bfSslatteng int	cfnum = -1;
192f92359bfSslatteng int	cpsize = 10;
193f92359bfSslatteng int	cfont = 1;
194f92359bfSslatteng char	*bits;
19569c7ec87Sslatteng char	*stip_bits;
19669c7ec87Sslatteng int	bordered = 1;		/* flag:  "do polygons get bordered?" */
197f92359bfSslatteng int	fontwanted = 1;		/* flag:  "has a new font been requested?" */
198f92359bfSslatteng int	nfontnum = -1;
199f92359bfSslatteng int	npsize = 10;
200f92359bfSslatteng 
201f92359bfSslatteng 
202f92359bfSslatteng 
main(argc,argv)203f92359bfSslatteng main(argc, argv)
204f92359bfSslatteng char *argv[];
205f92359bfSslatteng {
206cb97edc8Sslatteng 	register FILE *fp;
207cb97edc8Sslatteng 	register int i;
208f92359bfSslatteng 
209cb97edc8Sslatteng 	for (i = 0; i <= NFONTS; fontdes[i++].fnum = -1);
2104dabf413Sslatteng 	while (--argc > 0 && **++argv == '-') {
2114dabf413Sslatteng 		switch ((*argv)[1]) {
212f92359bfSslatteng 		case 'F':
2131c9df754Sslatteng 			bitdir = operand(&argc, &argv);
2144da297a9Sslatteng 			break;
2154da297a9Sslatteng 		case 'f':
2161c9df754Sslatteng 			fontdir = operand(&argc, &argv);
217f92359bfSslatteng 			break;
218f92359bfSslatteng 		case 'o':
2194dabf413Sslatteng 			outlist(operand(&argc, &argv));
220f92359bfSslatteng 			break;
221f92359bfSslatteng #ifdef DEBUGABLE
222f92359bfSslatteng 		case 'd':
2234dabf413Sslatteng 			dbg = atoi(operand(&argc, &argv));
224f92359bfSslatteng 			if (dbg == 0) dbg = 1;
225f92359bfSslatteng 			break;
226f92359bfSslatteng #endif
227f92359bfSslatteng 		case 's':
2284dabf413Sslatteng 			spage = atoi(operand(&argc, &argv));
229f92359bfSslatteng 			if (spage <= 0)
230f92359bfSslatteng 				spage = 9999;
231f92359bfSslatteng 			break;
232f92359bfSslatteng 		}
233f92359bfSslatteng 	}
234f92359bfSslatteng 
2351c9df754Sslatteng #ifdef DRIVER
236f92359bfSslatteng 	ioctl(OUTFILE, VSETSTATE, pltmode);
2371c9df754Sslatteng #endif
238f92359bfSslatteng 
2394dabf413Sslatteng 	if (argc < 1)
240f92359bfSslatteng 		conv(stdin);
241f92359bfSslatteng 	else
2424dabf413Sslatteng 		while (argc--) {
2434dabf413Sslatteng 			if (strcmp(*argv, "-") == 0)
244f92359bfSslatteng 				fp = stdin;
245f92359bfSslatteng 			else if ((fp = fopen(*argv, "r")) == NULL)
246f92359bfSslatteng 				error(FATAL, "can't open %s", *argv);
247f92359bfSslatteng 			conv(fp);
248f92359bfSslatteng 			fclose(fp);
2494dabf413Sslatteng 			argv++;
250f92359bfSslatteng 		}
251f92359bfSslatteng 	exit(0);
252f92359bfSslatteng }
253f92359bfSslatteng 
2544dabf413Sslatteng 
2554dabf413Sslatteng /*----------------------------------------------------------------------------*
2564dabf413Sslatteng  | Routine:	char  * operand (& argc,  & argv)
2574dabf413Sslatteng  |
2584dabf413Sslatteng  | Results:	returns address of the operand given with a command-line
2594dabf413Sslatteng  |		option.  It uses either "-Xoperand" or "-X operand", whichever
2604dabf413Sslatteng  |		is present.  The program is terminated if no option is present.
2614dabf413Sslatteng  |
2624dabf413Sslatteng  | Side Efct:	argc and argv are updated as necessary.
2634dabf413Sslatteng  *----------------------------------------------------------------------------*/
2644dabf413Sslatteng 
operand(argcp,argvp)2654dabf413Sslatteng char *operand(argcp, argvp)
2664dabf413Sslatteng int * argcp;
2674dabf413Sslatteng char ***argvp;
2684dabf413Sslatteng {
2694dabf413Sslatteng 	if ((**argvp)[2]) return(**argvp + 2); /* operand immediately follows */
2704dabf413Sslatteng 	if ((--*argcp) <= 0)			/* no operand */
2714dabf413Sslatteng 	    error (FATAL, "command-line option operand missing.\n");
2724dabf413Sslatteng 	return(*(++(*argvp)));			/* operand next word */
2734dabf413Sslatteng }
2744dabf413Sslatteng 
2754dabf413Sslatteng 
outlist(s)276f92359bfSslatteng outlist(s)	/* process list of page numbers to be printed */
277f92359bfSslatteng char *s;
278f92359bfSslatteng {
279f92359bfSslatteng 	int n1, n2, i;
280f92359bfSslatteng 
281f92359bfSslatteng 	nolist = 0;
282f92359bfSslatteng 	while (*s) {
283f92359bfSslatteng 		n1 = 0;
284f92359bfSslatteng 		if (isdigit(*s))
285f92359bfSslatteng 			do
286f92359bfSslatteng 				n1 = 10 * n1 + *s++ - '0';
287f92359bfSslatteng 			while (isdigit(*s));
288f92359bfSslatteng 		else
289f92359bfSslatteng 			n1 = -9999;
290f92359bfSslatteng 		n2 = n1;
291f92359bfSslatteng 		if (*s == '-') {
292f92359bfSslatteng 			s++;
293f92359bfSslatteng 			n2 = 0;
294f92359bfSslatteng 			if (isdigit(*s))
295f92359bfSslatteng 				do
296f92359bfSslatteng 					n2 = 10 * n2 + *s++ - '0';
297f92359bfSslatteng 				while (isdigit(*s));
298f92359bfSslatteng 			else
299f92359bfSslatteng 				n2 = 9999;
300f92359bfSslatteng 		}
301f92359bfSslatteng 		olist[nolist++] = n1;
302f92359bfSslatteng 		olist[nolist++] = n2;
303f92359bfSslatteng 		if (*s != '\0')
304f92359bfSslatteng 			s++;
305f92359bfSslatteng 	}
306f92359bfSslatteng 	olist[nolist] = 0;
307f92359bfSslatteng #ifdef DEBUGABLE
308f92359bfSslatteng 	if (dbg)
309f92359bfSslatteng 		for (i=0; i<nolist; i += 2)
310f92359bfSslatteng 			fprintf(stderr,"%3d %3d\n", olist[i], olist[i+1]);
311f92359bfSslatteng #endif
312f92359bfSslatteng }
313f92359bfSslatteng 
conv(fp)314f92359bfSslatteng conv(fp)
315f92359bfSslatteng register FILE *fp;
316f92359bfSslatteng {
317f92359bfSslatteng 	register int c, k;
318f92359bfSslatteng 	int m, n, n1, m1;
319f92359bfSslatteng 	char str[100], buf[300];
320f92359bfSslatteng 
321f92359bfSslatteng 	while ((c = getc(fp)) != EOF) {
322f92359bfSslatteng 		switch (c) {
323f92359bfSslatteng 		case '\n':	/* when input is text */
324f92359bfSslatteng 		case ' ':
325f92359bfSslatteng 		case 0:		/* occasional noise creeps in */
326f92359bfSslatteng 			break;
327f92359bfSslatteng 		case '{':	/* push down current environment */
328f92359bfSslatteng 			t_push();
329f92359bfSslatteng 			break;
330f92359bfSslatteng 		case '}':
331f92359bfSslatteng 			t_pop();
332f92359bfSslatteng 			break;
333f92359bfSslatteng 		case '0': case '1': case '2': case '3': case '4':
334f92359bfSslatteng 		case '5': case '6': case '7': case '8': case '9':
335f92359bfSslatteng 			/* two motion digits plus a character */
336f92359bfSslatteng 			hmot((c-'0')*10 + getc(fp)-'0');
337f92359bfSslatteng 			put1(getc(fp));
338f92359bfSslatteng 			break;
339f92359bfSslatteng 		case 'c':	/* single ascii character */
340f92359bfSslatteng 			put1(getc(fp));
341f92359bfSslatteng 			break;
342f92359bfSslatteng 		case 'C':
343f92359bfSslatteng 			fscanf(fp, "%s", str);
344f92359bfSslatteng 			put1s(str);
345f92359bfSslatteng 			break;
346f92359bfSslatteng 		case 't':	/* straight text */
347f92359bfSslatteng 			fgets(buf, sizeof(buf), fp);
348f92359bfSslatteng 			t_text(buf);
349f92359bfSslatteng 			break;
350f92359bfSslatteng 		case 'D':	/* draw function */
351289ea231Sslatteng 			if (fgets(buf, sizeof(buf), fp) == NULL)
352289ea231Sslatteng 			    error(FATAL, "unexpected end of input");;
353f92359bfSslatteng 			switch (buf[0]) {
354f92359bfSslatteng 			case 'l':	/* draw a line */
355f92359bfSslatteng 			    sscanf(buf+1, "%d %d", &n, &m);
356f92359bfSslatteng 			    drawline(n, m);
357f92359bfSslatteng 			    break;
358f92359bfSslatteng 			case 'c':	/* circle */
359f92359bfSslatteng 			    sscanf(buf+1, "%d", &n);
360f92359bfSslatteng 			    drawcirc(n);
361f92359bfSslatteng 			    break;
362f92359bfSslatteng 			case 'e':	/* ellipse */
363f92359bfSslatteng 			    sscanf(buf+1, "%d %d", &m, &n);
364f92359bfSslatteng 			    drawellip(m, n);
365f92359bfSslatteng 			    break;
366f92359bfSslatteng 			case 'a':	/* arc */
367f92359bfSslatteng 			    sscanf(buf+1, "%d %d %d %d", &n, &m, &n1, &m1);
368f92359bfSslatteng 			    drawarc(n, m, n1, m1);
369f92359bfSslatteng 			    break;
37069c7ec87Sslatteng 			case 'P':	/* unbordered polygon */
37169c7ec87Sslatteng 			    bordered = 0;		/* unset border flag */
37269c7ec87Sslatteng 			case 'p':	/* polygon */
37369c7ec87Sslatteng 			    sscanf(buf+1, "%d", &m);	/* get stipple */
37469c7ec87Sslatteng 			    n = 1;			/* number first */
37569c7ec87Sslatteng 			    while (buf[++n] == ' ');
37669c7ec87Sslatteng 			    while (isdigit(buf[++n]));
37769c7ec87Sslatteng 			    setfill(m);			/* set up stipple */
37869c7ec87Sslatteng 			    drawwig(buf+n, fp, -1);	/* draw polygon */
37969c7ec87Sslatteng 			    bordered = 1;		/* ALWAYS set after */
38069c7ec87Sslatteng 			    break;
381f92359bfSslatteng 			case '~':	/* wiggly line */
38269c7ec87Sslatteng 			    drawwig(buf+1, fp, 1);
38369c7ec87Sslatteng 			    break;
3841a4ecc79Sslatteng 			case 'g':	/* gremlin spline */
38569c7ec87Sslatteng 			    drawwig(buf+1, fp, 0);
3861a4ecc79Sslatteng 			    break;
3871a4ecc79Sslatteng 			case 't':	/* line thickness */
3881a4ecc79Sslatteng 			    sscanf(buf+1, "%d", &n);
3891a4ecc79Sslatteng 			    drawthick(n);
3901a4ecc79Sslatteng 			    break;
3911a4ecc79Sslatteng 			case 's':	/* line style */
3921a4ecc79Sslatteng 			    sscanf(buf+1, "%d", &n);
3931a4ecc79Sslatteng 			    drawstyle(n);
394f92359bfSslatteng 			    break;
395f92359bfSslatteng 			default:
396ebd02298Sslatteng 			    error(FATAL, "unknown drawing function %s", buf);
397f92359bfSslatteng 			    break;
398f92359bfSslatteng 			}
399f92359bfSslatteng 			break;
400f92359bfSslatteng 		case 's':
401f92359bfSslatteng 			fscanf(fp, "%d", &n);	/* ignore fractional sizes */
402f92359bfSslatteng 			setsize(t_size(n));
403f92359bfSslatteng 			break;
404f92359bfSslatteng 		case 'f':
405f92359bfSslatteng 			fscanf(fp, "%s", str);
406f92359bfSslatteng 			setfont(t_font(str));
407f92359bfSslatteng 			break;
40869c7ec87Sslatteng 		case 'i':
40969c7ec87Sslatteng 			fscanf(fp, "%d", &n);
41069c7ec87Sslatteng 			setstip(n);
41169c7ec87Sslatteng 			break;
412f92359bfSslatteng 		case 'H':	/* absolute horizontal motion */
413f92359bfSslatteng 			/* fscanf(fp, "%d", &n); */
414f92359bfSslatteng 			while ((c = getc(fp)) == ' ')
415f92359bfSslatteng 				;
416f92359bfSslatteng 			k = 0;
417f92359bfSslatteng 			do {
418f92359bfSslatteng 				k = 10 * k + c - '0';
419f92359bfSslatteng 			} while (isdigit(c = getc(fp)));
420f92359bfSslatteng 			ungetc(c, fp);
421f92359bfSslatteng 			hgoto(k);
422f92359bfSslatteng 			break;
423f92359bfSslatteng 		case 'h':	/* relative horizontal motion */
424f92359bfSslatteng 			while ((c = getc(fp)) == ' ')
425f92359bfSslatteng 				;
426f92359bfSslatteng 			k = 0;
427f92359bfSslatteng 			do {
428f92359bfSslatteng 				k = 10 * k + c - '0';
429f92359bfSslatteng 			} while (isdigit(c = getc(fp)));
430f92359bfSslatteng 			ungetc(c, fp);
431f92359bfSslatteng 			hmot(k);
432f92359bfSslatteng 			break;
433f92359bfSslatteng 		case 'w':	/* word space */
434f92359bfSslatteng 			break;
435f92359bfSslatteng 		case 'V':
436f92359bfSslatteng 			fscanf(fp, "%d", &n);
437f92359bfSslatteng 			vgoto(n);
438f92359bfSslatteng 			break;
439f92359bfSslatteng 		case 'v':
440f92359bfSslatteng 			fscanf(fp, "%d", &n);
441f92359bfSslatteng 			vmot(n);
442f92359bfSslatteng 			break;
443f92359bfSslatteng 		case 'p':	/* new page */
444f92359bfSslatteng 			fscanf(fp, "%d", &n);
445f92359bfSslatteng 			t_page(n);
446f92359bfSslatteng 			break;
447f92359bfSslatteng 		case 'n':	/* end of line */
448f92359bfSslatteng 			t_newline();
449289ea231Sslatteng 
450f92359bfSslatteng 		case '#':	/* comment */
451289ea231Sslatteng 			do
452289ea231Sslatteng 				c = getc(fp);
453289ea231Sslatteng 			while (c != '\n' && c != EOF);
454f92359bfSslatteng 			break;
455f92359bfSslatteng 		case 'x':	/* device control */
45619de12e6Sslatteng 			if (devcntrl(fp)) return;
457f92359bfSslatteng 			break;
458f92359bfSslatteng 		default:
459ebd02298Sslatteng 			error(FATAL, "unknown input character %o %c", c, c);
460f92359bfSslatteng 		}
461cb97edc8Sslatteng 		if (emptypos < NLINES) {	/* for each input operation */
462cb97edc8Sslatteng 			slop_lines(1);		/* put out an output line */
463cb97edc8Sslatteng #ifdef DRIVER
464cb97edc8Sslatteng 			if (emptypos == NLINES) {
465cb97edc8Sslatteng 				ioctl(OUTFILE, VSETSTATE, prtmode);
466cb97edc8Sslatteng 				if (write(OUTFILE, "\f", 2) != 2)
467cb97edc8Sslatteng 					exit(RESTART);
468cb97edc8Sslatteng 				ioctl(OUTFILE, VSETSTATE, pltmode);
469cb97edc8Sslatteng 			}
470cb97edc8Sslatteng #endif
471cb97edc8Sslatteng 		}
472f92359bfSslatteng 	}
473f92359bfSslatteng }
474f92359bfSslatteng 
devcntrl(fp)47519de12e6Sslatteng int devcntrl(fp)	/* interpret device control functions */
47619de12e6Sslatteng FILE *fp;		/* returns -1 upon "stop" command */
477f92359bfSslatteng {
478f92359bfSslatteng         char str[20], str1[50], buf[50];
479f92359bfSslatteng 	int c, n;
480f92359bfSslatteng 
481f92359bfSslatteng 	fscanf(fp, "%s", str);
482f92359bfSslatteng 	switch (str[0]) {	/* crude for now */
483f92359bfSslatteng 	case 'i':	/* initialize */
484f92359bfSslatteng 		fileinit();
485f92359bfSslatteng 		t_init();
486f92359bfSslatteng 		break;
487f92359bfSslatteng 	case 't':	/* trailer */
488f92359bfSslatteng 		break;
489f92359bfSslatteng 	case 'p':	/* pause -- can restart */
490f92359bfSslatteng 		t_reset('p');
491f92359bfSslatteng 		break;
492f92359bfSslatteng 	case 's':	/* stop */
493f92359bfSslatteng 		t_reset('s');
49419de12e6Sslatteng 		return -1;
495f92359bfSslatteng 	case 'r':	/* resolution assumed when prepared */
4964da297a9Sslatteng 		fscanf(fp, "%d", &n);
49769c7ec87Sslatteng 		if (n!=RES) error(FATAL,"Input computed for wrong printer");
498f92359bfSslatteng 		break;
499f92359bfSslatteng 	case 'f':	/* font used */
500f92359bfSslatteng 		fscanf(fp, "%d %s", &n, str);
501f92359bfSslatteng 		fgets(buf, sizeof buf, fp);	/* in case there's a filename */
502f92359bfSslatteng 		ungetc('\n', fp);		/* fgets goes too far */
503f92359bfSslatteng 		str1[0] = 0;			/* in case nothing comes in */
504f92359bfSslatteng 		sscanf(buf, "%s", str1);
505f92359bfSslatteng 		loadfont(n, str, str1);
506f92359bfSslatteng 		break;
507f92359bfSslatteng 						/* these don't belong here... */
508f92359bfSslatteng 	case 'H':	/* char height */
509f92359bfSslatteng 		fscanf(fp, "%d", &n);
510f92359bfSslatteng 		t_charht(n);
511f92359bfSslatteng 		break;
512f92359bfSslatteng 	case 'S':	/* slant */
513f92359bfSslatteng 		fscanf(fp, "%d", &n);
514f92359bfSslatteng 		t_slant(n);
515f92359bfSslatteng 		break;
516f92359bfSslatteng 	}
517f92359bfSslatteng 	while ((c = getc(fp)) != '\n')	/* skip rest of input line */
518f92359bfSslatteng 		if (c == EOF)
51919de12e6Sslatteng 			return -1;
52019de12e6Sslatteng 	return 0;
521f92359bfSslatteng }
522f92359bfSslatteng 
523f92359bfSslatteng /* fileinit:	read in font and code files, etc.
524f92359bfSslatteng 		Must open table for device, read in resolution,
5254da297a9Sslatteng 		size info, font info, etc. and set params.
5264da297a9Sslatteng 		Also read in font name mapping.
527f92359bfSslatteng */
5284da297a9Sslatteng 
fileinit()529f92359bfSslatteng fileinit()
530f92359bfSslatteng {
5314da297a9Sslatteng 	register int i;
5324da297a9Sslatteng 	register int fin;
5334da297a9Sslatteng 	register int nw;
5344da297a9Sslatteng 	register char *filebase;
5354da297a9Sslatteng 	register char *p;
5364da297a9Sslatteng 	register FILE *fp;
5374da297a9Sslatteng 	char	temp[100];
5384da297a9Sslatteng 
5394da297a9Sslatteng 		/* first, read in font map file.  The file must be of Format:
5404da297a9Sslatteng 			XX  FILENAME  (XX = troff font name)
5414da297a9Sslatteng 			with one entry per text line of the file.
5424da297a9Sslatteng 		   Extra stuff after FILENAME is ignored */
5434da297a9Sslatteng 
5444da297a9Sslatteng 	sprintf(temp, "%s/fontmap", bitdir);
5454da297a9Sslatteng 	if ((fp = fopen(temp, "r")) == NULL)
5464da297a9Sslatteng 		error(FATAL, "Can't open %s", temp);
5474da297a9Sslatteng 	for (i = 0; i <= NFONTS && fgets(temp, 100, fp) != NULL; i++) {
5484da297a9Sslatteng 		sscanf(temp, "%2s", fontmap[i].fname);
5494da297a9Sslatteng 		p = &temp[0];
5504da297a9Sslatteng 		while (*p != ' ' && *p != '	') p++;
5514da297a9Sslatteng 		while (*p == ' ' || *p == '	') p++;
5524da297a9Sslatteng 		filebase = p;
5534da297a9Sslatteng 		for (nw = 1; *p != '\n' && *p != ' ' && *p != '\t'; p++) nw++;
5544da297a9Sslatteng 		fontmap[i].ffile = nalloc(1, nw);
5554da297a9Sslatteng 		sscanf(filebase, "%s", fontmap[i].ffile);
5564da297a9Sslatteng 	}
5574da297a9Sslatteng 	fontmap[++i].fname[0] = '0';		/* finish off with zeros */
5584da297a9Sslatteng 	fontmap[i].ffile = (char *) 0;
5594da297a9Sslatteng 	fclose(fp);
5604da297a9Sslatteng #ifdef DEBUGABLE
5614da297a9Sslatteng 	if(dbg) {
5624da297a9Sslatteng 	    fprintf(stderr, "font map:\n");
5634da297a9Sslatteng 	    for (i = 0; fontmap[i].ffile; i++)
5644da297a9Sslatteng 		fprintf(stderr,"%s = %s\n", fontmap[i].fname, fontmap[i].ffile);
5654da297a9Sslatteng 	}
5664da297a9Sslatteng #endif
567f92359bfSslatteng 
568cb97edc8Sslatteng 	sprintf(temp, "%s/devva/DESC.out", fontdir);
569f92359bfSslatteng 	if ((fin = open(temp, 0)) < 0)
570ebd02298Sslatteng 		error(FATAL, "can't open tables for %s", temp);
571f92359bfSslatteng 	read(fin, &dev, sizeof(struct dev));
572f92359bfSslatteng 	nfonts = dev.nfonts;
57369c7ec87Sslatteng 	nstips = dev.nstips;
574f92359bfSslatteng 	nsizes = dev.nsizes;
575f92359bfSslatteng 	nchtab = dev.nchtab;
576f92359bfSslatteng 	filebase = calloc(1, dev.filesize);	/* enough room for whole file */
577f92359bfSslatteng 	read(fin, filebase, dev.filesize);	/* all at once */
578f92359bfSslatteng 	pstab = (short *) filebase;
579f92359bfSslatteng 	chtab = pstab + nsizes + 1;
580f92359bfSslatteng 	chname = (char *) (chtab + dev.nchtab);
581f92359bfSslatteng 	p = chname + dev.lchname;
582f92359bfSslatteng 	for (i = 1; i <= nfonts; i++) {
583f92359bfSslatteng 		fontbase[i] = (struct font *) p;
584f92359bfSslatteng 		nw = *p & BMASK;		/* 1st thing is width count */
5851c9df754Sslatteng 		p += sizeof(struct font);
586f92359bfSslatteng 		widtab[i] = p;
587f92359bfSslatteng 		codetab[i] = p + 2 * nw;
588f92359bfSslatteng 		fitab[i] = p + 3 * nw;
589f92359bfSslatteng 		p += 3 * nw + dev.nchtab + 128 - 32;
590f92359bfSslatteng 		t_fp(i, fontbase[i]->namefont, fontbase[i]->intname);
591f92359bfSslatteng #ifdef DEBUGABLE
592f92359bfSslatteng 		if (dbg > 1) fontprint(i);
593f92359bfSslatteng #endif
594f92359bfSslatteng 	}
59569c7ec87Sslatteng 	for (i = 1; i <= nstips; i++) {		/* add in stipple "filenames" */
59669c7ec87Sslatteng 		if (nfonts + i <= NFONTS)
59769c7ec87Sslatteng 			t_fp(nfonts + i, p, (char *)0);
59869c7ec87Sslatteng 		p += strlen(p) + 1;
59969c7ec87Sslatteng 	}
600f92359bfSslatteng 	fontbase[0] = (struct font *)
601f92359bfSslatteng 		calloc(1,3*255 + dev.nchtab + (128-32) + sizeof (struct font));
602f92359bfSslatteng 	widtab[0] = (char *) fontbase[0] + sizeof (struct font);
603f92359bfSslatteng 	fontbase[0]->nwfont = 255;
604f92359bfSslatteng 	close(fin);
6054da297a9Sslatteng 
606f92359bfSslatteng }
607f92359bfSslatteng 
6084da297a9Sslatteng 
6096dfd4b55Sslatteng #ifdef DEBUGABLE
fontprint(i)610f92359bfSslatteng fontprint(i)	/* debugging print of font i (0,...) */
611f92359bfSslatteng {
612f92359bfSslatteng 	int j, n;
613f92359bfSslatteng 	char *p;
614f92359bfSslatteng 
615f92359bfSslatteng 	fprintf(stderr,"font %d:\n", i);
616f92359bfSslatteng 	p = (char *) fontbase[i];
617f92359bfSslatteng 	n = fontbase[i]->nwfont & BMASK;
618f92359bfSslatteng 	fprintf(stderr,
619f92359bfSslatteng 	    "base=0%o, nchars=%d, spec=%d, name=%s, widtab=0%o, fitab=0%o\n",p,
620f92359bfSslatteng 	    n,fontbase[i]->specfont,fontbase[i]->namefont,widtab[i],fitab[i]);
621f92359bfSslatteng 	fprintf(stderr,"widths:\n");
622f92359bfSslatteng 	for (j=0; j <= n; j++) {
623f92359bfSslatteng 		fprintf(stderr," %2d", widtab[i][j] & BMASK);
624f92359bfSslatteng 		if (j % 20 == 19) fprintf(stderr,"\n");
625f92359bfSslatteng 	}
626f92359bfSslatteng 	fprintf(stderr,"\ncodetab:\n");
627f92359bfSslatteng 	for (j=0; j <= n; j++) {
628f92359bfSslatteng 		fprintf(stderr," %2d", codetab[i][j] & BMASK);
629f92359bfSslatteng 		if (j % 20 == 19) fprintf(stderr,"\n");
630f92359bfSslatteng 	}
631f92359bfSslatteng 	fprintf(stderr,"\nfitab:\n");
632f92359bfSslatteng 	for (j=0; j <= dev.nchtab + 128-32; j++) {
633f92359bfSslatteng 		fprintf(stderr," %2d", fitab[i][j] & BMASK);
634f92359bfSslatteng 		if (j % 20 == 19) fprintf(stderr,"\n");
635f92359bfSslatteng 	}
636f92359bfSslatteng 	fprintf(stderr,"\n");
637f92359bfSslatteng }
6386dfd4b55Sslatteng #endif
639f92359bfSslatteng 
64019de12e6Sslatteng 
loadfont(n,s,s1)641f92359bfSslatteng loadfont(n, s, s1)	/* load font info for font s on position n (0...) */
642f92359bfSslatteng int n;
643f92359bfSslatteng char *s, *s1;
644f92359bfSslatteng {
645f92359bfSslatteng 	char temp[60];
64619de12e6Sslatteng 	register int fin;
64719de12e6Sslatteng 	register int nw;
64819de12e6Sslatteng 	register int norig;
6494da297a9Sslatteng 
650f92359bfSslatteng 	if (n < 0 || n > NFONTS)
651f92359bfSslatteng 		error(FATAL, "illegal fp command %d %s", n, s);
652f92359bfSslatteng 	if (strcmp(s, fontbase[n]->namefont) == 0)
653f92359bfSslatteng 		return;
65419de12e6Sslatteng 
65519de12e6Sslatteng 	for (fin = 1; fin <= NFONTS; fin++)	/* first check to see if the */
65619de12e6Sslatteng 	    if (strcmp(s, fontbase[fin]->namefont) == 0) {  /* font is loaded */
65719de12e6Sslatteng 		register char *c;			    /* somewhere else */
65819de12e6Sslatteng 
65919de12e6Sslatteng #define ptrswap(x, y) { c = (char*) (x); x = y; y = c; }
6606dfd4b55Sslatteng #define ptrfswap(x, y) { c = (char*) (x); x = y; y = (struct font *) c; }
66119de12e6Sslatteng 
6626dfd4b55Sslatteng 		ptrfswap(fontbase[n], fontbase[fin]);
66319de12e6Sslatteng 		ptrswap(codetab[n], codetab[fin]);
66419de12e6Sslatteng 		ptrswap(widtab[n], widtab[fin]);
66519de12e6Sslatteng 		ptrswap(fitab[n], fitab[fin]);
66619de12e6Sslatteng 		t_fp(n, fontbase[n]->namefont, fontbase[n]->intname);
66719de12e6Sslatteng 		t_fp(fin, fontbase[fin]->namefont, fontbase[fin]->intname);
66819de12e6Sslatteng 		return;
66919de12e6Sslatteng 	    }
67019de12e6Sslatteng 
671f92359bfSslatteng 	if (s1 == NULL || s1[0] == '\0')
672cb97edc8Sslatteng 		sprintf(temp, "%s/devva/%s.out", fontdir, s);
673f92359bfSslatteng 	else
674f92359bfSslatteng 		sprintf(temp, "%s/%s.out", s1, s);
675f92359bfSslatteng 	if ((fin = open(temp, 0)) < 0)
676f92359bfSslatteng 		error(FATAL, "can't open font table %s", temp);
677f92359bfSslatteng 	norig = fontbase[n]->nwfont & BMASK;
678f92359bfSslatteng 	read(fin, fontbase[n], 3*norig + nchtab+128-32 + sizeof(struct font));
679f92359bfSslatteng 	if ((fontbase[n]->nwfont & BMASK) > norig)
680ebd02298Sslatteng 		error(FATAL, "Font %s too big for position %d", s, n);
681f92359bfSslatteng 	close(fin);
682f92359bfSslatteng 	nw = fontbase[n]->nwfont & BMASK;
683f92359bfSslatteng 	widtab[n] = (char *) fontbase[n] + sizeof(struct font);
684f92359bfSslatteng 	codetab[n] = (char *) widtab[n] + 2 * nw;
685f92359bfSslatteng 	fitab[n] = (char *) widtab[n] + 3 * nw;
686f92359bfSslatteng 	t_fp(n, fontbase[n]->namefont, fontbase[n]->intname);
687f92359bfSslatteng 	fontbase[n]->nwfont = norig;	/* to later use full original size */
688f92359bfSslatteng #ifdef DEBUGABLE
689f92359bfSslatteng 	if (dbg > 1) fontprint(n);
690f92359bfSslatteng #endif
691f92359bfSslatteng }
692f92359bfSslatteng 
693ebd02298Sslatteng 
694f92359bfSslatteng /*VARARGS1*/
error(f,s,a1,a2,a3,a4,a5,a6,a7)695f92359bfSslatteng error(f, s, a1, a2, a3, a4, a5, a6, a7) {
696ebd02298Sslatteng 	fprintf(stderr, "dvar: ");
697f92359bfSslatteng 	fprintf(stderr, s, a1, a2, a3, a4, a5, a6, a7);
698f92359bfSslatteng 	fprintf(stderr, "\n");
6991c9df754Sslatteng 	if (f) exit(ABORT);
700f92359bfSslatteng }
701f92359bfSslatteng 
702f92359bfSslatteng 
t_init()703f92359bfSslatteng t_init()	/* initialize device */
704f92359bfSslatteng {
705f92359bfSslatteng 	int i;
706f92359bfSslatteng 
707f92359bfSslatteng 	hpos = vpos = 0;
708f92359bfSslatteng 
709f92359bfSslatteng 	setsize(t_size(10));	/* start somewhere */
710f92359bfSslatteng 	setfont(1);
711f92359bfSslatteng }
712f92359bfSslatteng 
713f92359bfSslatteng 
714f92359bfSslatteng struct state {
715f92359bfSslatteng 	int	ssize;
716f92359bfSslatteng 	int	sfont;
717f92359bfSslatteng 	int	shpos;
718f92359bfSslatteng 	int	svpos;
719ebd02298Sslatteng 	int	sstyle;
720ebd02298Sslatteng 	int	sthick;
721f92359bfSslatteng };
722f92359bfSslatteng struct	state	state[MAXSTATE];
723f92359bfSslatteng struct	state	*statep = state;
724f92359bfSslatteng 
t_push()725f92359bfSslatteng t_push()	/* begin a new block */
726f92359bfSslatteng {
727f92359bfSslatteng 	statep->ssize = size;
728f92359bfSslatteng 	statep->sfont = font;
729ebd02298Sslatteng 	statep->sstyle = linmod;
730ebd02298Sslatteng 	statep->sthick = linethickness;
731f92359bfSslatteng 	statep->shpos = hpos;
732f92359bfSslatteng 	statep->svpos = vpos;
733f92359bfSslatteng 	if (statep++ >= state+MAXSTATE)
734f92359bfSslatteng 		error(FATAL, "{ nested too deep");
735f92359bfSslatteng }
736f92359bfSslatteng 
t_pop()737f92359bfSslatteng t_pop()	/* pop to previous state */
738f92359bfSslatteng {
739f92359bfSslatteng 	if (--statep < state)
740f92359bfSslatteng 		error(FATAL, "extra }");
741f92359bfSslatteng 	size = statep->ssize;
742f92359bfSslatteng 	font = statep->sfont;
743f92359bfSslatteng 	hpos = statep->shpos;
744f92359bfSslatteng 	vpos = statep->svpos;
745ebd02298Sslatteng 	linmod = statep->sstyle;
746ebd02298Sslatteng 	linethickness = statep->sthick;
747f92359bfSslatteng }
748f92359bfSslatteng 
t_page(n)749f92359bfSslatteng t_page(n)	/* do whatever new page functions */
750f92359bfSslatteng {
751f92359bfSslatteng 	int i;
752f92359bfSslatteng 
753f92359bfSslatteng 
754cb97edc8Sslatteng 	if (emptypos < NLINES) {		/* finish off last page, if */
755cb97edc8Sslatteng 		slop_lines(NLINES - emptypos);	/* it's not done yet */
7561c9df754Sslatteng #ifdef DRIVER
757f92359bfSslatteng 		ioctl(OUTFILE, VSETSTATE, prtmode);
758f92359bfSslatteng 		if (write(OUTFILE, "\f", 2) != 2)
759f92359bfSslatteng 			exit(RESTART);
760f92359bfSslatteng 		ioctl(OUTFILE, VSETSTATE, pltmode);
7611c9df754Sslatteng #endif
762f92359bfSslatteng 	}
763cb97edc8Sslatteng 	if (output) {
764cb97edc8Sslatteng 		emptypos = 0;		/* set emptying to be started */
765cb97edc8Sslatteng 		elevel = fill;		/* swap buffer pointers */
766cb97edc8Sslatteng 		fill = empty;
767cb97edc8Sslatteng 		empty = elevel;
768cb97edc8Sslatteng 	}
769f92359bfSslatteng 
770f92359bfSslatteng 	vpos = 0;
771f92359bfSslatteng 	output = 1;
772f92359bfSslatteng 	if (nolist == 0)
773f92359bfSslatteng 		return;		/* no -o specified */
774f92359bfSslatteng 	output = 0;
775f92359bfSslatteng 	for (i = 0; i < nolist; i += 2)
776f92359bfSslatteng 		if (n >= olist[i] && n <= olist[i+1]) {
777f92359bfSslatteng 			output = 1;
778f92359bfSslatteng 			break;
779f92359bfSslatteng 		}
780f92359bfSslatteng }
781f92359bfSslatteng 
t_newline()782f92359bfSslatteng t_newline()	/* do whatever for the end of a line */
783f92359bfSslatteng {
784f92359bfSslatteng 	hpos = 0;	/* because we're now back at the left margin */
785f92359bfSslatteng }
786f92359bfSslatteng 
t_size(n)787f92359bfSslatteng t_size(n)	/* convert integer to internal size number*/
788f92359bfSslatteng int n;
789f92359bfSslatteng {
790f92359bfSslatteng 	int i;
791f92359bfSslatteng 
792f92359bfSslatteng 	if (n <= pstab[0])
7934da297a9Sslatteng 		return(0);
794f92359bfSslatteng 	else if (n >= pstab[nsizes - 1])
7954da297a9Sslatteng 		return(nsizes - 1);
796f92359bfSslatteng 	for (i = 0; n > pstab[i]; i++)
797f92359bfSslatteng 		;
7984da297a9Sslatteng 	return(i);
799f92359bfSslatteng }
800f92359bfSslatteng 
t_charht(n)801f92359bfSslatteng t_charht(n)	/* set character height to n */
802f92359bfSslatteng int n;
803f92359bfSslatteng {
804f92359bfSslatteng #ifdef DEBUGABLE
8054da297a9Sslatteng 	if (dbg) error(!FATAL, "can't set height on varian");
806f92359bfSslatteng #endif
807f92359bfSslatteng }
808f92359bfSslatteng 
t_slant(n)809f92359bfSslatteng t_slant(n)	/* set slant to n */
810f92359bfSslatteng int n;
811f92359bfSslatteng {
812f92359bfSslatteng #ifdef DEBUGABLE
8134da297a9Sslatteng 	if (dbg) error(!FATAL, "can't set slant on varian");
814f92359bfSslatteng #endif
815f92359bfSslatteng }
816f92359bfSslatteng 
t_font(s)817f92359bfSslatteng t_font(s)	/* convert string to internal font number */
818f92359bfSslatteng char *s;
819f92359bfSslatteng {
820f92359bfSslatteng 	int n;
821f92359bfSslatteng 
822f92359bfSslatteng 	n = atoi(s);
823f92359bfSslatteng 	if (n < 0 || n > nfonts)
824f92359bfSslatteng 		n = 1;
825f92359bfSslatteng 	return(n);
826f92359bfSslatteng }
827f92359bfSslatteng 
t_text(s)828f92359bfSslatteng t_text(s)	/* print string s as text */
829f92359bfSslatteng char *s;
830f92359bfSslatteng {
831f92359bfSslatteng 	int c;
832f92359bfSslatteng 	char str[100];
833f92359bfSslatteng 
834f92359bfSslatteng 	if (!output)
835f92359bfSslatteng 		return;
836f92359bfSslatteng 	while (c = *s++) {
837f92359bfSslatteng 		if (c == '\\') {
838f92359bfSslatteng 			switch (c = *s++) {
839f92359bfSslatteng 			case '\\':
840f92359bfSslatteng 			case 'e':
841f92359bfSslatteng 				put1('\\');
842f92359bfSslatteng 				break;
843f92359bfSslatteng 			case '(':
844f92359bfSslatteng 				str[0] = *s++;
845f92359bfSslatteng 				str[1] = *s++;
846f92359bfSslatteng 				str[2] = '\0';
847f92359bfSslatteng 				put1s(str);
848f92359bfSslatteng 				break;
849f92359bfSslatteng 			}
850f92359bfSslatteng 		} else {
851f92359bfSslatteng 			put1(c);
852f92359bfSslatteng 		}
853f92359bfSslatteng 		hmot(lastw);
854f92359bfSslatteng #ifdef DEBUGABLE
855f92359bfSslatteng 		if (dbg) fprintf(stderr,"width = %d\n", lastw);
856f92359bfSslatteng #endif
857f92359bfSslatteng 	}
858f92359bfSslatteng }
859f92359bfSslatteng 
860cb97edc8Sslatteng 
t_reset(c)861f92359bfSslatteng t_reset(c)
862f92359bfSslatteng {
863cb97edc8Sslatteng 	if (c == 's') {
864cb97edc8Sslatteng 		t_page();
865cb97edc8Sslatteng 		output = 0;
866cb97edc8Sslatteng 		t_page();
8671c9df754Sslatteng #ifdef DRIVER
868f92359bfSslatteng 		ioctl(OUTFILE, VSETSTATE, prtmode);
869f92359bfSslatteng 		if (write(OUTFILE, "\f", 2) != 2)
870f92359bfSslatteng 			exit(RESTART);
8711c9df754Sslatteng #endif
872f92359bfSslatteng 	}
873f92359bfSslatteng }
874f92359bfSslatteng 
875ebd02298Sslatteng 
876ebd02298Sslatteng /*----------------------------------------------------------------------------*
877ebd02298Sslatteng  | Routine:	hgoto (horizontal_spot)
878ebd02298Sslatteng  |
879ebd02298Sslatteng  | Results:	hpos is set to n.  If n overlaps in either direction, it wraps
880ebd02298Sslatteng  |		around to the other end of the page.
881ebd02298Sslatteng  *----------------------------------------------------------------------------*/
882ebd02298Sslatteng 
hgoto(n)883ebd02298Sslatteng hgoto(n)
884ebd02298Sslatteng int n;
885f92359bfSslatteng {
886ebd02298Sslatteng     if (n < 0)
887ebd02298Sslatteng 	n += NLINES;
888ebd02298Sslatteng     else if (n >= NLINES)
889ebd02298Sslatteng 	n -= NLINES;
890ebd02298Sslatteng     hpos = n;
891f92359bfSslatteng }
892ebd02298Sslatteng 
893ebd02298Sslatteng 
894ebd02298Sslatteng /*----------------------------------------------------------------------------*
895ebd02298Sslatteng  | Routine:	vgoto (vertical_spot)
896ebd02298Sslatteng  |
897ebd02298Sslatteng  | Results:	vpos is set to n.  If n overlaps in either direction, it wraps
898ebd02298Sslatteng  |		around to the other end of the page.
899ebd02298Sslatteng  *----------------------------------------------------------------------------*/
900ebd02298Sslatteng 
vgoto(n)901ebd02298Sslatteng vgoto(n)
902ebd02298Sslatteng int n;
903ebd02298Sslatteng {
904ebd02298Sslatteng     if (n < 0)
905ebd02298Sslatteng 	n += RASTER_LENGTH;
906ebd02298Sslatteng     else if (n > RASTER_LENGTH)
907ebd02298Sslatteng 	n -= RASTER_LENGTH;
908f92359bfSslatteng     vpos = n;
909f92359bfSslatteng }
910f92359bfSslatteng 
put1s(s)911f92359bfSslatteng put1s(s)	/* s is a funny char name */
912f92359bfSslatteng char *s;
913f92359bfSslatteng {
914f92359bfSslatteng 	int i;
915f92359bfSslatteng 
916f92359bfSslatteng 	if (!output)
917f92359bfSslatteng 		return;
918f92359bfSslatteng #ifdef DEBUGABLE
919f92359bfSslatteng 	if (dbg) fprintf(stderr,"%s ", s);
920f92359bfSslatteng #endif
921f92359bfSslatteng 	for (i = 0; i < nchtab; i++)
922f92359bfSslatteng 		if (strcmp(&chname[chtab[i]], s) == 0)
923f92359bfSslatteng 			break;
924f92359bfSslatteng 	if (i < nchtab)
925f92359bfSslatteng 		put1(i + 128);
926f92359bfSslatteng }
927f92359bfSslatteng 
put1(c)928f92359bfSslatteng put1(c)	/* output char c */
929f92359bfSslatteng int c;
930f92359bfSslatteng {
931f92359bfSslatteng 	char *pw;
932f92359bfSslatteng 	register char *p;
933f92359bfSslatteng 	register int i, k;
934f92359bfSslatteng 	int j, ofont, code;
935f92359bfSslatteng 
936f92359bfSslatteng 	if (!output)
937f92359bfSslatteng 		return;
938f92359bfSslatteng 	c -= 32;
939f92359bfSslatteng 	if (c <= 0) {
940f92359bfSslatteng #ifdef DEBUGABLE
941f92359bfSslatteng 		if (dbg) fprintf(stderr,"non-exist 0%o\n", c + 32);
942f92359bfSslatteng #endif
9434da297a9Sslatteng  		lastw = (widtab[font][0] * pstab[size] + dev.unitwidth/2)
944f92359bfSslatteng 								/ dev.unitwidth;
945f92359bfSslatteng 		return;
946f92359bfSslatteng 	}
947f92359bfSslatteng 	k = ofont = font;
948f92359bfSslatteng 	i = fitab[font][c] & BMASK;
949f92359bfSslatteng 	if (i != 0) {			/* it's on this font */
950f92359bfSslatteng 		p = codetab[font];	/* get the printing value of ch */
951f92359bfSslatteng 		pw = widtab[font];	/* get the width */
9526dfd4b55Sslatteng 	} else {		/* on another font - run down the font list */
9536dfd4b55Sslatteng 		for (j=0; j++ <= nfonts; k = (k+1) % (nfonts+1)) {
954f92359bfSslatteng 			if (fitab[k] == 0)
955f92359bfSslatteng 				continue;
956f92359bfSslatteng 			if ((i=fitab[k][c] & BMASK) != 0) {
957f92359bfSslatteng 				p = codetab[k];
958f92359bfSslatteng 				pw = widtab[k];
959f92359bfSslatteng 				setfont(k);
960f92359bfSslatteng 				break;
961f92359bfSslatteng 			}
962f92359bfSslatteng 		}
9636dfd4b55Sslatteng 	}
9641c9df754Sslatteng 
9656dfd4b55Sslatteng 	if (i == 0) {
966f92359bfSslatteng #ifdef DEBUGABLE
967f92359bfSslatteng 		if (dbg) fprintf(stderr,"not found 0%o\n", c+32);
968f92359bfSslatteng #endif
969f92359bfSslatteng 		return;
970f92359bfSslatteng 	}
9716dfd4b55Sslatteng 	code = p[i] & BMASK;
972f92359bfSslatteng #ifdef DEBUGABLE
973f92359bfSslatteng 	if (dbg) {
974f92359bfSslatteng 		if (isprint(c+32))
975f92359bfSslatteng 			fprintf(stderr,"%c %d\n", c+32, code);
976f92359bfSslatteng 		else
977f92359bfSslatteng 			fprintf(stderr,"%03o %d\n", c+32, code);
978f92359bfSslatteng 	}
979f92359bfSslatteng #endif
980f92359bfSslatteng 	outc(code);	/* character is < 254 */
981f92359bfSslatteng 	if (font != ofont)
982f92359bfSslatteng 		setfont(ofont);
9834da297a9Sslatteng 	lastw = ((pw[i]&077) * pstab[size] + dev.unitwidth/2) / dev.unitwidth;
984f92359bfSslatteng }
985f92359bfSslatteng 
986f92359bfSslatteng 
987f92359bfSslatteng 
setsize(n)988f92359bfSslatteng setsize(n)	/* set point size to n (internal) */
989f92359bfSslatteng int n;
990f92359bfSslatteng {
991f92359bfSslatteng 
992f92359bfSslatteng 	if (n == size)
993f92359bfSslatteng 		return;	/* already there */
9944da297a9Sslatteng 	if (vloadfont(font, pstab[n]) != -1)
995f92359bfSslatteng 		size = n;
996f92359bfSslatteng }
997f92359bfSslatteng 
t_fp(n,s,si)998f92359bfSslatteng t_fp(n, s, si)	/* font position n now contains font s, intname si */
9991c9df754Sslatteng int n;		/* internal name is ignored */
1000f92359bfSslatteng char *s, *si;
1001f92359bfSslatteng {
10024da297a9Sslatteng 	register int i;
1003f92359bfSslatteng 
10044da297a9Sslatteng 
10054da297a9Sslatteng 			/* first convert s to filename if possible */
10064da297a9Sslatteng 	for (i = 0; fontmap[i].ffile != (char *) 0; i++) {
10074da297a9Sslatteng #ifdef DEBUGABLE
10084da297a9Sslatteng 		if(dbg>1)fprintf(stderr,"testing :%s:%s:\n",s,fontmap[i].fname);
10094da297a9Sslatteng #endif
10104da297a9Sslatteng 		if (strcmp(s, fontmap[i].fname) == 0) {
10114da297a9Sslatteng 			s = fontmap[i].ffile;
10124da297a9Sslatteng #ifdef DEBUGABLE
10134da297a9Sslatteng 			if(dbg)fprintf(stderr, "found :%s:\n",fontmap[i].ffile);
10144da297a9Sslatteng #endif
10154da297a9Sslatteng 			break;
10164da297a9Sslatteng 		}
10174da297a9Sslatteng 	}
10181c9df754Sslatteng 	fontname[n] = s;
1019cb97edc8Sslatteng 	for(i = 0;i <= NFONTS;i++)	/* free the bits of that font */
1020f92359bfSslatteng 		if (fontdes[i].fnum == n){
1021f92359bfSslatteng 			nfree(fontdes[i].bits);
1022f92359bfSslatteng 			fontdes[i].fnum = -1;
1023f92359bfSslatteng 		}
1024f92359bfSslatteng }
1025f92359bfSslatteng 
10264da297a9Sslatteng 
setfont(n)1027f92359bfSslatteng setfont(n)	/* set font to n */
1028f92359bfSslatteng int n;
1029f92359bfSslatteng {
103069c7ec87Sslatteng 	if (n < 0 || n > nfonts)
1031ebd02298Sslatteng 		error(FATAL, "illegal font %d", n);
10324da297a9Sslatteng 	if (vloadfont(n,pstab[size]) != -1)
1033f92359bfSslatteng 		font = n;
1034f92359bfSslatteng }
1035f92359bfSslatteng 
103669c7ec87Sslatteng 
setstip(n)103769c7ec87Sslatteng setstip(n)	/* set stipple font to n */
103869c7ec87Sslatteng int n;
103969c7ec87Sslatteng {
104069c7ec87Sslatteng 	if (n < 1 || n > nstips)
104169c7ec87Sslatteng 		error(FATAL, "illegal stipple %d", n);
104269c7ec87Sslatteng 	stip = n;
104369c7ec87Sslatteng }
104469c7ec87Sslatteng 
104569c7ec87Sslatteng 
vloadfont(fnum,fsize)1046f92359bfSslatteng vloadfont(fnum, fsize)
1047f92359bfSslatteng register int fnum;
1048f92359bfSslatteng register int fsize;
1049f92359bfSslatteng {
1050f92359bfSslatteng 	register int i;
1051f92359bfSslatteng 
1052f92359bfSslatteng 	fontwanted = 0;
1053f92359bfSslatteng 	if (fnum == cfnum && fsize == cpsize)
1054f92359bfSslatteng 		return(0);
1055f92359bfSslatteng 	for (i = 0; i < NFONTS; i++) {
1056f92359bfSslatteng 		if (fontdes[i].fnum == fnum && fontdes[i].psize == fsize) {
1057f92359bfSslatteng 			cfnum = fontdes[i].fnum;
1058f92359bfSslatteng 			cpsize = fontdes[i].psize;
1059f92359bfSslatteng 			dispatch = &fontdes[i].disp[0];
1060f92359bfSslatteng 			bits = fontdes[i].bits;
1061f92359bfSslatteng 			cfont = i;
1062f92359bfSslatteng 			return (0);
1063f92359bfSslatteng 		}
1064f92359bfSslatteng 	}
1065f92359bfSslatteng 		/* this is a new font */
10661c9df754Sslatteng 	if (fnum < 0 || fnum > NFONTS || fontname[fnum] == 0) {
1067a2d3d00eSslatteng 	    error(!FATAL,"error: illegal font %d, size %d\n", fnum, fsize);
1068f92359bfSslatteng 	    return(-1);
1069f92359bfSslatteng 	}
1070f92359bfSslatteng 		/* Need to verify the existance of that font/size here*/
1071f92359bfSslatteng 	nfontnum = fnum;
1072f92359bfSslatteng 	npsize = fsize;
1073f92359bfSslatteng 	fontwanted++;
1074f92359bfSslatteng 	return (0);
1075f92359bfSslatteng }
1076f92359bfSslatteng 
1077f92359bfSslatteng 
getfont()1078f92359bfSslatteng getfont()
1079f92359bfSslatteng {
10804da297a9Sslatteng 	register int fnum;
10814da297a9Sslatteng 	register int fsize;
10824da297a9Sslatteng 	register int fontd;
10834da297a9Sslatteng 	register int d;
10841c9df754Sslatteng 	register int sizehunt = size;
1085f92359bfSslatteng 	char cbuf[BUFSIZ];
1086f92359bfSslatteng 
1087f92359bfSslatteng 	fnum = nfontnum;
1088f92359bfSslatteng 	fsize = npsize;
10894da297a9Sslatteng 			/* try to open font file - if unsuccessful, hunt for */
10904da297a9Sslatteng 			/* a file of same style, different size to substitute */
10914da297a9Sslatteng 	d = -1;	 /* direction to look in pstab (smaller first) */
10924da297a9Sslatteng 	do {
10931c9df754Sslatteng 	    sprintf(cbuf, "%s/%s.%dr", bitdir, fontname[fnum], fsize);
1094f92359bfSslatteng 	    fontd = open(cbuf, OPENREAD);
10954da297a9Sslatteng 	    if (fontd == -1) {		/* File wasn't found. Try another ps */
10961c9df754Sslatteng 		sizehunt += d;
10971c9df754Sslatteng 		if (sizehunt < 0) {	/* past beginning - look higher */
10984da297a9Sslatteng 		    d = 1;
10991c9df754Sslatteng 		    sizehunt = size + 1;
11004da297a9Sslatteng 		}
11011c9df754Sslatteng 		if (sizehunt > nsizes) {	/* past top - forget it */
11024da297a9Sslatteng 		    d = 0;
11034da297a9Sslatteng 		} else {
11041c9df754Sslatteng 		    fsize = pstab[sizehunt];
11054da297a9Sslatteng 		}
11064da297a9Sslatteng 	    }
11074da297a9Sslatteng 	} while (fontd == -1 && d != 0);
11084da297a9Sslatteng 
11094da297a9Sslatteng 	if (fontd == -1) {		/* completely unsuccessful */
1110f92359bfSslatteng 	    perror(cbuf);
11114da297a9Sslatteng 	    error(!FATAL,"fnum = %d, psize = %d, name = %s",
11121c9df754Sslatteng 		fnum, npsize, fontname[fnum]);
1113f92359bfSslatteng 	    fontwanted = 0;
1114f92359bfSslatteng 	    return (-1);
1115f92359bfSslatteng 	}
1116f92359bfSslatteng 	if (read(fontd, &header, sizeof  (header)) != sizeof (header)
1117f92359bfSslatteng 						|| header.magic != 0436)
1118f92359bfSslatteng 		fprintf(stderr, "%s: Bad font file", cbuf);
1119f92359bfSslatteng 	else {
1120f92359bfSslatteng 		cfont = relfont();
1121f92359bfSslatteng 		if ((bits=nalloc(header.size+DSIZ+1,1))== NULL)
1122f92359bfSslatteng 			if ((bits=allpanic(header.size+DSIZ+1))== NULL) {
11231c9df754Sslatteng 				error(FATAL,"%s: ran out of memory", cbuf);
1124f92359bfSslatteng 			}
1125f92359bfSslatteng 
1126f92359bfSslatteng 			/*
1127f92359bfSslatteng 			 * have allocated one chunk of mem for font, dispatch.
1128f92359bfSslatteng 			 * get the dispatch addr, align to word boundary.
1129f92359bfSslatteng 			 */
1130f92359bfSslatteng 
1131f92359bfSslatteng 		d = (int) bits+header.size;
1132f92359bfSslatteng 		d += 1;
1133f92359bfSslatteng 		d &= ~1;
1134f92359bfSslatteng 		if (read (fontd, d, DSIZ) != DSIZ
1135f92359bfSslatteng 			    || read (fontd, bits, header.size) != header.size)
1136f92359bfSslatteng 			fprintf(stderr, "bad font header");
1137f92359bfSslatteng 		else {
1138f92359bfSslatteng 			close(fontd);
1139f92359bfSslatteng 			cfnum = fontdes[cfont].fnum = fnum;
1140f92359bfSslatteng 			cpsize = fontdes[cfont].psize = fsize;
1141f92359bfSslatteng 			fontdes [cfont].bits = bits;
1142f92359bfSslatteng 			fontdes [cfont].disp = (struct dispatch *) d;
1143f92359bfSslatteng 			dispatch = &fontdes[cfont].disp[0];
1144f92359bfSslatteng 			fontwanted = 0;
1145f92359bfSslatteng 			return (0);
1146f92359bfSslatteng 		}
1147f92359bfSslatteng 	}
1148f92359bfSslatteng 	close(fontd);
1149f92359bfSslatteng 	fontwanted = 0;
1150f92359bfSslatteng 	return(-1);
1151f92359bfSslatteng }
1152f92359bfSslatteng 
1153f92359bfSslatteng /*
1154f92359bfSslatteng  * "release" a font position - find an empty one, if possible
1155f92359bfSslatteng  */
1156f92359bfSslatteng 
relfont()1157f92359bfSslatteng relfont()
1158f92359bfSslatteng {
1159f92359bfSslatteng     register int newfont;
1160f92359bfSslatteng 
1161f92359bfSslatteng     for (newfont = 0; newfont < NFONTS; newfont++)
1162cb97edc8Sslatteng 	if (fontdes [newfont].fnum == -1)
1163f92359bfSslatteng 	    break;
1164cb97edc8Sslatteng     if (fontdes [newfont].fnum != -1) {
1165f92359bfSslatteng 	nfree (fontdes [newfont].bits);
1166f92359bfSslatteng #ifdef DEBUGABLE
1167f92359bfSslatteng 	if (dbg) fprintf (stderr, "freeing position %d\n", newfont);
1168f92359bfSslatteng     } else {
1169f92359bfSslatteng 	if (dbg)
1170f92359bfSslatteng 	    fprintf (stderr, "taking, not freeing, position %d\n", newfont);
1171f92359bfSslatteng #endif
1172f92359bfSslatteng     }
1173cb97edc8Sslatteng     fontdes[newfont].fnum = -1;
1174f92359bfSslatteng     return (newfont);
1175f92359bfSslatteng }
1176f92359bfSslatteng 
allpanic(nbytes)1177f92359bfSslatteng char *allpanic (nbytes)
1178f92359bfSslatteng int nbytes;
1179f92359bfSslatteng {
1180f92359bfSslatteng 	register int i;
1181f92359bfSslatteng 
1182f92359bfSslatteng 	for (i = 0; i <= NFONTS; i++) {
1183cb97edc8Sslatteng 		if (fontdes[i].fnum != -1) nfree(fontdes[i].bits);
1184cb97edc8Sslatteng 		fontdes[i].fnum = -1;
1185f92359bfSslatteng 		cfnum = cpsize = -1;
1186f92359bfSslatteng 	}
1187f92359bfSslatteng 	return(nalloc(nbytes,1));
1188f92359bfSslatteng }
1189f92359bfSslatteng 
1190f92359bfSslatteng int	M[] = { 0xffffffff, 0xfefefefe, 0xfcfcfcfc, 0xf8f8f8f8,
1191f92359bfSslatteng 		0xf0f0f0f0, 0xe0e0e0e0, 0xc0c0c0c0, 0x80808080, 0x0 };
1192f92359bfSslatteng int	N[] = { 0x00000000, 0x01010101, 0x03030303, 0x07070707,
1193f92359bfSslatteng 		0x0f0f0f0f, 0x1f1f1f1f, 0x3f3f3f3f, 0x7f7f7f7f, 0xffffffff };
1194f92359bfSslatteng int	strim[] = { 0xffffffff, 0xffffff00, 0xffff0000, 0xff000000, 0 };
1195f92359bfSslatteng 
outc(code)1196f92359bfSslatteng outc(code)
1197f92359bfSslatteng int code;		/* character to print */
1198f92359bfSslatteng {
1199f92359bfSslatteng     register struct dispatch *dis; /* ptr to character font record */
1200f92359bfSslatteng     register char *addr;	/* addr of font data */
1201f92359bfSslatteng     int llen;			/* length of each font line */
1202f92359bfSslatteng     int nlines;			/* number of font lines */
1203f92359bfSslatteng     register char *scanp;	/* ptr to output buffer */
1204f92359bfSslatteng     int scanp_inc;		/* increment to start of next buffer */
1205f92359bfSslatteng     int offset;			/* bit offset to start of font data */
12064da297a9Sslatteng     register int i;		/* loop counter */
1207f92359bfSslatteng     register int count;		/* font data ptr */
1208f92359bfSslatteng     register unsigned fontdata;	/* font data temporary */
1209f92359bfSslatteng     register int off8;		/* offset + 8 */
1210f92359bfSslatteng 
1211f92359bfSslatteng     if (fontwanted)
1212f92359bfSslatteng 	getfont();
1213f92359bfSslatteng     dis = dispatch + code;
1214f92359bfSslatteng     if (dis->nbytes) {
1215f92359bfSslatteng 	addr = bits + dis->addr;
12161a4ecc79Sslatteng 	llen = (dis->up + dis->down + 7) >> 3;
12171a4ecc79Sslatteng 	nlines = dis->right + dis->left;
1218cb97edc8Sslatteng 	scanp = fill + (hpos + 1 - dis->left) * BYTES_PER_LINE
1219cb97edc8Sslatteng 			- (1 + ((dis->down + vpos - 1) >> 3));
1220cb97edc8Sslatteng 	if (scanp < fill)
1221cb97edc8Sslatteng 	    scanp += BUFFER_SIZE;
1222f92359bfSslatteng 	scanp_inc = BYTES_PER_LINE - llen;
1223cb97edc8Sslatteng 	off8 = ((dis->down + vpos - 1) &07);
12241a4ecc79Sslatteng 	offset = off8 - 8;
1225f92359bfSslatteng 	for (i = 0; i < nlines; i++) {
1226cb97edc8Sslatteng 	    if (scanp >= fill + BUFFER_SIZE)
12271c9df754Sslatteng 		scanp -= BUFFER_SIZE;
1228f92359bfSslatteng 	    count = llen;
1229cb97edc8Sslatteng 	    if (scanp + count < fill + BUFFER_SIZE) {
1230f92359bfSslatteng 		do {
1231f92359bfSslatteng 		    fontdata = *(unsigned *)addr;
1232f92359bfSslatteng 		    addr += 4;
1233f92359bfSslatteng 		    if (count < 4)
1234f92359bfSslatteng 			fontdata &= ~strim[count];
1235f92359bfSslatteng 		    *(unsigned*)scanp |=(fontdata << offset) & ~M[off8];
1236f92359bfSslatteng 		    scanp++;
1237f92359bfSslatteng 		    *(unsigned*)scanp |=(fontdata << off8) & ~N[off8];
1238f92359bfSslatteng 		    scanp += 3;
1239f92359bfSslatteng 		    count -= 4;
1240f92359bfSslatteng 		} while (count > 0);
1241f92359bfSslatteng 	    }
1242f92359bfSslatteng 	    scanp += scanp_inc+count;
1243f92359bfSslatteng 	    addr += count;
1244f92359bfSslatteng 	}
1245f92359bfSslatteng 	return;
1246f92359bfSslatteng     }
1247f92359bfSslatteng     return;
1248f92359bfSslatteng }
1249f92359bfSslatteng 
125069c7ec87Sslatteng 
125169c7ec87Sslatteng /*----------------------------------------------------------------------------*
125269c7ec87Sslatteng  | Routine:	setfill(stipple_number)
125369c7ec87Sslatteng  |
125469c7ec87Sslatteng  | Results:	sets the fill-pattern pointers (stip_disp and
125569c7ec87Sslatteng  |		stip_bits) for a particular stipple.  Takes stipple
125669c7ec87Sslatteng  |		font from current "stip" number.
125769c7ec87Sslatteng  *----------------------------------------------------------------------------*/
125869c7ec87Sslatteng 
setfill(number)125969c7ec87Sslatteng setfill(number)
126069c7ec87Sslatteng int number;
126169c7ec87Sslatteng {
126269c7ec87Sslatteng 	int curfont;		/* places to save current text font */
126369c7ec87Sslatteng 	int cursize;
126469c7ec87Sslatteng 
126569c7ec87Sslatteng 					/* set global stipmem for polygon */
126669c7ec87Sslatteng 	if (number < 0 || number >= DISPATCHSIZE)
126769c7ec87Sslatteng 		stipmem = 0;
126869c7ec87Sslatteng 	else
126969c7ec87Sslatteng 		stipmem = number;
127069c7ec87Sslatteng 
127169c7ec87Sslatteng 	curfont = cfnum;		/* get pointers to */
127269c7ec87Sslatteng 	cursize = cpsize;		/* the inuse font */
127369c7ec87Sslatteng 	if (vloadfont(nfonts + stip, 0)) {
127469c7ec87Sslatteng 	    stip_disp = (struct dispatch *) NULL;	/* stipple not here */
127569c7ec87Sslatteng 	} else {
127669c7ec87Sslatteng 	    if (fontwanted) {
127769c7ec87Sslatteng 		if (getfont()) {
127869c7ec87Sslatteng 		    stip_disp = (struct dispatch *) NULL;
127969c7ec87Sslatteng 		} else {
128069c7ec87Sslatteng 		    stip_disp = dispatch;	/* save for polygon routine */
128169c7ec87Sslatteng 		    stip_bits = bits;
128269c7ec87Sslatteng 		}
128369c7ec87Sslatteng 	    } else {
128469c7ec87Sslatteng 		stip_disp = dispatch;	/* save for polygon routine */
128569c7ec87Sslatteng 		stip_bits = bits;
128669c7ec87Sslatteng 	    }
128769c7ec87Sslatteng 	}
1288a2d3d00eSslatteng 	if (curfont >= 0) vloadfont(curfont, cursize);
128969c7ec87Sslatteng }
129069c7ec87Sslatteng 
129169c7ec87Sslatteng 
slop_lines(nlines)1292f92359bfSslatteng slop_lines(nlines)
1293f92359bfSslatteng int nlines;
1294f92359bfSslatteng 
1295f92359bfSslatteng /* Output "nlines" lines from the buffer, and clear that section of the  */
1296cb97edc8Sslatteng /* buffer.	Also updates the pointers to the emptying buffer */
1297f92359bfSslatteng 
1298f92359bfSslatteng {
1299f92359bfSslatteng 	unsigned usize;
1300f92359bfSslatteng 
1301f92359bfSslatteng 	usize = BYTES_PER_LINE * nlines;
1302cb97edc8Sslatteng 	vwrite(elevel, usize);
1303cb97edc8Sslatteng 	vclear(elevel, usize);
1304cb97edc8Sslatteng 	elevel += usize;
1305cb97edc8Sslatteng 	emptypos += nlines;
1306f92359bfSslatteng }
1307f92359bfSslatteng 
vwrite(buf,usize)13084da297a9Sslatteng vwrite(buf,usize)
1309f92359bfSslatteng char *buf;
1310f92359bfSslatteng unsigned usize;
1311f92359bfSslatteng {
1312f92359bfSslatteng 	register int tsize = 0;
1313f92359bfSslatteng 
1314f92359bfSslatteng 	while (usize){
1315f92359bfSslatteng 		buf += tsize;
1316f92359bfSslatteng 		tsize = usize > MAXWRIT ? MAXWRIT : usize;
1317f92359bfSslatteng #ifdef DEBUGABLE
1318f92359bfSslatteng 		if (dbg)fprintf(stderr,"buf = %d size = %d\n",buf,tsize);
1319f92359bfSslatteng #endif
1320f92359bfSslatteng 		if ((tsize = write(OUTFILE, buf, tsize)) < 0) {
1321ebd02298Sslatteng 			perror("dvar: write failed");
1322f92359bfSslatteng 			exit(RESTART);
1323f92359bfSslatteng 		}
1324f92359bfSslatteng 		usize -= tsize;
1325f92359bfSslatteng 	}
1326f92359bfSslatteng }
1327f92359bfSslatteng 
vclear(ptr,nbytes)1328f92359bfSslatteng vclear (ptr, nbytes)
1329f92359bfSslatteng char	*ptr;
1330f92359bfSslatteng unsigned nbytes;
1331f92359bfSslatteng {
1332f92359bfSslatteng     register tsize = 0;
1333f92359bfSslatteng 
1334f92359bfSslatteng     while (nbytes){
1335f92359bfSslatteng 	if ((unsigned)(16*1024) < nbytes) {
1336f92359bfSslatteng 	    tsize = 16 * 1024;
1337f92359bfSslatteng 	} else
1338f92359bfSslatteng 	    tsize = nbytes;
1339f92359bfSslatteng 	nbytes -= tsize;
1340f92359bfSslatteng #ifdef DEBUGABLE
1341f92359bfSslatteng 	if (dbg) fprintf(stderr,"clearing ptr = %d size = %d\n",ptr,tsize);
1342f92359bfSslatteng #endif
1343f92359bfSslatteng 	clear(ptr,tsize);
1344f92359bfSslatteng 	ptr += tsize;
1345f92359bfSslatteng     }
1346f92359bfSslatteng }
1347f92359bfSslatteng 
1348f92359bfSslatteng /*ARGSUSED*/
clear(lp,nbytes)1349f92359bfSslatteng clear(lp, nbytes)
1350f92359bfSslatteng int *lp;
1351f92359bfSslatteng int nbytes;
1352f92359bfSslatteng {
1353*92970570Sslatteng #ifdef vax
1354f92359bfSslatteng 	asm("movc5 $0,(sp),$0,8(ap),*4(ap)");
1355*92970570Sslatteng #else
1356*92970570Sslatteng 	register int i = nbytes;
1357*92970570Sslatteng 	register int *cp = lp;
1358*92970570Sslatteng 
1359*92970570Sslatteng 	while (i-- > 0)
1360*92970570Sslatteng 		*(cp++) = 0;
1361*92970570Sslatteng #endif
1362f92359bfSslatteng }
1363f92359bfSslatteng 
1364f92359bfSslatteng char *
nalloc(i,j)1365f92359bfSslatteng nalloc(i, j)
1366f92359bfSslatteng int i, j;
1367f92359bfSslatteng {
1368f92359bfSslatteng 	register char *cp;
1369f92359bfSslatteng 
1370f92359bfSslatteng 	cp = calloc(i, j);
1371f92359bfSslatteng #ifdef DEBUGABLE
1372f92359bfSslatteng 	if (dbg) fprintf(stderr, "allocated %d bytes at %x\n", i * j, cp);
1373f92359bfSslatteng #endif
1374f92359bfSslatteng 	return(cp);
1375f92359bfSslatteng }
1376f92359bfSslatteng 
nfree(cp)1377f92359bfSslatteng nfree(cp)
1378f92359bfSslatteng char *cp;
1379f92359bfSslatteng {
1380f92359bfSslatteng #ifdef DEBUGABLE
1381f92359bfSslatteng 	if (dbg) fprintf(stderr, "freeing at %x\n", cp);
1382f92359bfSslatteng #endif
1383f92359bfSslatteng 	free(cp);
1384f92359bfSslatteng }
1385f92359bfSslatteng 
1386f92359bfSslatteng 
1387f92359bfSslatteng /*
1388f92359bfSslatteng  * Points should be in the range 0 <= x < RASTER_LENGTH, 0 <= y < NLINES.
1389f92359bfSslatteng  * The origin is the top left-hand corner with increasing x towards the
13904da297a9Sslatteng  * right and increasing y going down.  X and Y should be sent as (0,0) being
13914da297a9Sslatteng  * at the bottom left.  The output array is NLINES x BYTES_PER_LINE pixels.
1392f92359bfSslatteng  */
point(x,y)1393f92359bfSslatteng point(x, y)
13941a4ecc79Sslatteng register int x;
13951a4ecc79Sslatteng register int y;
1396f92359bfSslatteng {
139769c7ec87Sslatteng     if ((unsigned)(y=(RASTER_LENGTH-1)-y)<RASTER_LENGTH && (unsigned)x<NLINES) {
1398cb97edc8Sslatteng 	*(fill + x * BYTES_PER_LINE + (y >> 3)) |= 1 << (7 - (y & 07));
1399f92359bfSslatteng     }
1400f92359bfSslatteng }
140169c7ec87Sslatteng 
140269c7ec87Sslatteng 
140369c7ec87Sslatteng #define pv(x)	((polyvector *)x)
140469c7ec87Sslatteng 
140569c7ec87Sslatteng typedef struct poly {
140669c7ec87Sslatteng 	struct poly *next;	/* doublely-linked lists of vectors */
140769c7ec87Sslatteng 	struct poly *prev;
140869c7ec87Sslatteng 	int param;	/* bressenham line algorithm parameter */
140969c7ec87Sslatteng 	short dy;	/* delta-y for calculating line */
141069c7ec87Sslatteng 	short dx;	/* delta-x for calculating line */
141169c7ec87Sslatteng 	short curry;	/* current y in this vector */
141269c7ec87Sslatteng 	short endx;	/* where vector ends */
141369c7ec87Sslatteng } polyvector;
141469c7ec87Sslatteng 
141569c7ec87Sslatteng 
141669c7ec87Sslatteng /*----------------------------------------------------------------------------*
141769c7ec87Sslatteng  | Routine:	polygon ( x_coordinates, y_coordinates, num_of_points )
141869c7ec87Sslatteng  |
141969c7ec87Sslatteng  | Results:	draws a polygon starting at (x[1], y[1]) going through
142069c7ec87Sslatteng  |		each of (x_coordinates, y_coordinates), and fills it
142169c7ec87Sslatteng  |		with a stipple pattern from stip_disp and stip_bits,
142269c7ec87Sslatteng  |		which point to the stipple font.  The pattern is defined
142369c7ec87Sslatteng  |		by "stip" and "stipmem".
142469c7ec87Sslatteng  |
142569c7ec87Sslatteng  |		The scan-line algorithm implemented scans from left to
142669c7ec87Sslatteng  |		right (low x to high x).  It also scans, within a line,
142769c7ec87Sslatteng  |		from bottom to top (high y to low y).
142869c7ec87Sslatteng  |
142969c7ec87Sslatteng  |		polygons are clipped to page boundary.
143069c7ec87Sslatteng  |
143169c7ec87Sslatteng  | Bugs:	stipple pattern MUST be a power of two bytes "wide" and
143269c7ec87Sslatteng  |		square.  The square restriction comes from the fact that
143369c7ec87Sslatteng  |		the varian and versatec are respectively rotated.
143469c7ec87Sslatteng  *----------------------------------------------------------------------------*/
143569c7ec87Sslatteng 
polygon(x,y,npts)143669c7ec87Sslatteng polygon(x, y, npts)
143769c7ec87Sslatteng int x[];
143869c7ec87Sslatteng int y[];
143969c7ec87Sslatteng int npts;
144069c7ec87Sslatteng {
144169c7ec87Sslatteng     int nextx;			/* at what x value the next vector starts */
144269c7ec87Sslatteng     int maxx, minx, maxy, miny;		/* finds bounds of polygon */
144369c7ec87Sslatteng     polyvector *activehead;		/* doing fill, is active edge list */
144469c7ec87Sslatteng     polyvector *waitinghead;		/* edges waiting to be active */
144569c7ec87Sslatteng     register polyvector *vectptr;	/* random vector */
144669c7ec87Sslatteng     register int i;			/* random register */
144769c7ec87Sslatteng 
144869c7ec87Sslatteng     char *topstipple;		/* points to beginning of stipple glyph */
144969c7ec87Sslatteng     char *leftstipple;		/* points to beginning of line of stipple */
145069c7ec87Sslatteng     char *bottompage;		/* points to the edge of a raster line */
145169c7ec87Sslatteng     int bytewidth;		/* glyph width in bytes */
145269c7ec87Sslatteng     int mask;			/* mask to pick off pixel index into stipple */
145369c7ec87Sslatteng     int bytemask;		/* mask to pick off byte index into stipple */
145469c7ec87Sslatteng 
145569c7ec87Sslatteng 
145669c7ec87Sslatteng     if (bordered) {
145769c7ec87Sslatteng 	for (i = 1; i < npts; i++)		/* first draw outlines */
145869c7ec87Sslatteng 	    HGtline(x[i], y[i], x[i+1], y[i+1]);
145969c7ec87Sslatteng     }
146069c7ec87Sslatteng 
146169c7ec87Sslatteng 						/* if no stipple, don't fill */
146269c7ec87Sslatteng     if (stip_disp == (struct dispatch *) NULL || stip_bits == (char *) NULL)
146369c7ec87Sslatteng 	return;
146469c7ec87Sslatteng 
146569c7ec87Sslatteng     stip_disp += stipmem;			/* set up parameters for */
146669c7ec87Sslatteng     if (!stip_disp->nbytes) {			/* tiling with the stipple */
146769c7ec87Sslatteng #ifdef DEBUGABLE
146869c7ec87Sslatteng 	error(!FATAL, "member not found: member %d, stipple %d", stipmem, stip);
146969c7ec87Sslatteng #endif
147069c7ec87Sslatteng 	return;
147169c7ec87Sslatteng     }
147269c7ec87Sslatteng     topstipple = stip_bits + stip_disp->addr;
147369c7ec87Sslatteng     bytewidth = stip_disp->up + stip_disp->down;
147469c7ec87Sslatteng     for (i = 1 << 30; i && i != bytewidth; i = i >> 1)
147569c7ec87Sslatteng 	;
147669c7ec87Sslatteng     if (i==0 || bytewidth<8 || bytewidth != stip_disp->right+stip_disp->left) {
147769c7ec87Sslatteng 	error(!FATAL, "invalid stipple: number %d, member %d", stip, stipmem);
147869c7ec87Sslatteng 	return;
147969c7ec87Sslatteng     }
148069c7ec87Sslatteng     mask = bytewidth - 1;
148169c7ec87Sslatteng     bytewidth = bytewidth >> 3;
148269c7ec87Sslatteng     bytemask = bytewidth - 1;
148369c7ec87Sslatteng 
148469c7ec87Sslatteng 				/* allocate space for raster-fill algorithm*/
148569c7ec87Sslatteng     if ((vectptr = pv( nalloc(sizeof(polyvector), npts + 6) )) == NULL) {
148669c7ec87Sslatteng 	error(!FATAL, "unable to allocate space for polygon");
148769c7ec87Sslatteng 	return;
148869c7ec87Sslatteng     }
148969c7ec87Sslatteng #ifdef DEBUGABLE
149069c7ec87Sslatteng     if (dbg) fprintf(stderr, "polygon, %d points\n", npts);
149169c7ec87Sslatteng #endif
149269c7ec87Sslatteng 
149369c7ec87Sslatteng     waitinghead = vectptr;
149469c7ec87Sslatteng     minx = maxx = x[1];
149569c7ec87Sslatteng     miny = maxy = y[1];
149669c7ec87Sslatteng     (vectptr++)->prev = pv( NULL );	/* put dummy entry at start */
149769c7ec87Sslatteng     waitinghead->next = vectptr;
149869c7ec87Sslatteng     vectptr->prev = waitinghead;
149969c7ec87Sslatteng     i = 1;					/* starting point of coords */
150069c7ec87Sslatteng     if (y[1] != y[npts] || x[1] != x[npts]) {
150169c7ec87Sslatteng 	y[0] = y[npts];				/* close polygon if it's not */
150269c7ec87Sslatteng 	x[0] = x[npts];
150369c7ec87Sslatteng 	i = 0;
150469c7ec87Sslatteng     }
150569c7ec87Sslatteng     while (i < npts) {		/* set up the vectors */
150669c7ec87Sslatteng 	register int j;			/* indexes to work off of */
150769c7ec87Sslatteng 	register int k;
150869c7ec87Sslatteng 
150969c7ec87Sslatteng 	if (miny > y[i]) miny = y[i];		/* remember limits */
151069c7ec87Sslatteng 	else if (maxy < y[i]) maxy = y[i];
151169c7ec87Sslatteng 	if (maxx < x[i]) maxx = x[i];
151269c7ec87Sslatteng 	else if (minx > x[i]) minx = x[i];
151369c7ec87Sslatteng 
151469c7ec87Sslatteng 	j = i;			/* j "points" to the higher (lesser) point */
151569c7ec87Sslatteng 	k = ++i;
151669c7ec87Sslatteng 	if (x[j] == x[k])		/* ignore vertical lines */
151769c7ec87Sslatteng 	    continue;
151869c7ec87Sslatteng 
151969c7ec87Sslatteng 	if (x[j] > x[k]) {
152069c7ec87Sslatteng 	    j++;
152169c7ec87Sslatteng 	    k--;
152269c7ec87Sslatteng 	}
152369c7ec87Sslatteng 	vectptr->next = vectptr + 1;
152469c7ec87Sslatteng 	vectptr->param = x[j];		/* starting point of vector */
152569c7ec87Sslatteng 	vectptr->dy = y[k] - y[j];	/* line-calculating parameters */
152669c7ec87Sslatteng 	vectptr->dx = x[k] - x[j];
152769c7ec87Sslatteng 	vectptr->curry = y[j];		/* starting point */
152869c7ec87Sslatteng 	(vectptr++)->endx = x[k];	/* ending point */
152969c7ec87Sslatteng 	vectptr->prev = vectptr - 1;
153069c7ec87Sslatteng     }
153169c7ec87Sslatteng 				/* set now because we didn't know minx before */
153269c7ec87Sslatteng     leftstipple = topstipple + (minx & mask) * bytewidth;
153369c7ec87Sslatteng     bottompage = fill + minx * BYTES_PER_LINE;
153469c7ec87Sslatteng     waitinghead->param = minx - 1;
153569c7ec87Sslatteng 					/* if no useable vectors, quit */
153669c7ec87Sslatteng     if (vectptr == waitinghead + 1)
153769c7ec87Sslatteng 	goto leavepoly;
153869c7ec87Sslatteng 
153969c7ec87Sslatteng     vectptr->param = maxx + 1;		/* dummy entry at end, too */
154069c7ec87Sslatteng     vectptr->next = pv( NULL );
154169c7ec87Sslatteng 
154269c7ec87Sslatteng     activehead = ++vectptr;		/* two dummy entries for active list */
154369c7ec87Sslatteng     vectptr->curry = maxy + 1;		/* head */
154469c7ec87Sslatteng     vectptr->endx = maxx + 1;
154569c7ec87Sslatteng     vectptr->param = vectptr->dx = vectptr->dy = 0;
154669c7ec87Sslatteng     activehead->next = ++vectptr;
154769c7ec87Sslatteng     activehead->prev = vectptr;
154869c7ec87Sslatteng 
154969c7ec87Sslatteng     vectptr->prev = activehead;		/* tail */
155069c7ec87Sslatteng     vectptr->next = activehead;
155169c7ec87Sslatteng     vectptr->curry = miny - 1;
155269c7ec87Sslatteng     vectptr->endx = maxx + 1;
155369c7ec87Sslatteng     vectptr->param = vectptr->dx = vectptr->dy = 0;
155469c7ec87Sslatteng 
155569c7ec87Sslatteng 
155669c7ec87Sslatteng 			/* main loop -- gets vectors off the waiting list, */
155769c7ec87Sslatteng 			/* then displays spans while updating the vectors in */
155869c7ec87Sslatteng 			/* the active list */
155969c7ec87Sslatteng     while (minx <= maxx) {
156069c7ec87Sslatteng 	i = maxx + 1;		/* this is the NEXT time to get a new vector */
156169c7ec87Sslatteng 	for (vectptr = waitinghead->next; vectptr != pv( NULL ); ) {
156269c7ec87Sslatteng 	    if (minx == vectptr->param) {
156369c7ec87Sslatteng 				/* the entry in waiting list (vectptr) is */
156469c7ec87Sslatteng 				/*   ready to go into active list.  Need to */
156569c7ec87Sslatteng 				/*   convert some vector stuff and sort the */
156669c7ec87Sslatteng 				/*   entry into the list. */
156769c7ec87Sslatteng 		register polyvector *p;	/* random vector pointers */
156869c7ec87Sslatteng 		register polyvector *v;
156969c7ec87Sslatteng 
157069c7ec87Sslatteng 							/* convert this */
157169c7ec87Sslatteng 		if (vectptr->dy < 0)			/* entry to active */
157269c7ec87Sslatteng 		    vectptr->param = (vectptr->dy >> 1) - (vectptr->dx >> 1);
157369c7ec87Sslatteng 		else
157469c7ec87Sslatteng 		    vectptr->param = -((vectptr->dx >> 1) + (vectptr->dy >> 1));
157569c7ec87Sslatteng 
157669c7ec87Sslatteng 		p = vectptr;			/* remove from the */
157769c7ec87Sslatteng 		vectptr = vectptr->next;	/* waiting list */
157869c7ec87Sslatteng 		vectptr->prev = p->prev;
157969c7ec87Sslatteng 		p->prev->next = vectptr;
158069c7ec87Sslatteng 						/* find where it goes */
158169c7ec87Sslatteng 						/* in the active list */
158269c7ec87Sslatteng 						/* (sorted greatest first) */
158369c7ec87Sslatteng 		for (v = activehead->next; v->curry > p->curry; v = v->next)
158469c7ec87Sslatteng 		    ;
158569c7ec87Sslatteng 		p->next = v;		/* insert into active list */
158669c7ec87Sslatteng 		p->prev = v->prev;	/* before the one it stopped on */
158769c7ec87Sslatteng 		v->prev = p;
158869c7ec87Sslatteng 		p->prev->next = p;
158969c7ec87Sslatteng 	    } else {
159069c7ec87Sslatteng 		if (i > vectptr->param) {
159169c7ec87Sslatteng 		    i = vectptr->param;
159269c7ec87Sslatteng 		}
159369c7ec87Sslatteng 		vectptr = vectptr->next;
159469c7ec87Sslatteng 	    }
159569c7ec87Sslatteng 	}
159669c7ec87Sslatteng 	nextx = i;
159769c7ec87Sslatteng 
159869c7ec87Sslatteng 					/* print the polygon while there */
159969c7ec87Sslatteng 					/* are no more vectors to add */
160069c7ec87Sslatteng 	while (minx < nextx) {
160169c7ec87Sslatteng 					/* remove any finished vectors */
160269c7ec87Sslatteng 	    vectptr = activehead->next;
160369c7ec87Sslatteng 	    do {
160469c7ec87Sslatteng 		if (vectptr->endx <= minx) {
160569c7ec87Sslatteng 		    vectptr->prev->next = vectptr->next;
160669c7ec87Sslatteng 		    vectptr->next->prev = vectptr->prev;
160769c7ec87Sslatteng 		}
160869c7ec87Sslatteng 	    } while ((vectptr = vectptr->next) != activehead);
160969c7ec87Sslatteng 
161069c7ec87Sslatteng 					/* draw the span */
161169c7ec87Sslatteng 	    if (((unsigned) minx) < NLINES) {
161269c7ec87Sslatteng 	      vectptr = activehead->next;
161369c7ec87Sslatteng 	      while (vectptr->next != activehead) {
161469c7ec87Sslatteng 		register int start;	/* get the beginning */
161569c7ec87Sslatteng 		register int length;	/*   and the end of span */
161669c7ec87Sslatteng 		register char *glyph;
161769c7ec87Sslatteng 		register char *raster;
161869c7ec87Sslatteng 
161969c7ec87Sslatteng 		start = (RASTER_LENGTH - 1) - vectptr->curry;
162069c7ec87Sslatteng 		vectptr = vectptr->next;
162169c7ec87Sslatteng 		length = RASTER_LENGTH - vectptr->curry;
162269c7ec87Sslatteng 		vectptr = vectptr->next;
162369c7ec87Sslatteng 
162469c7ec87Sslatteng 					/* bound the polygon to the page */
162569c7ec87Sslatteng 		if (start >= RASTER_LENGTH)
162669c7ec87Sslatteng 		    break;
162769c7ec87Sslatteng 		if (start < 0) start = 0;
162869c7ec87Sslatteng 		if (length > RASTER_LENGTH) length = RASTER_LENGTH;
162969c7ec87Sslatteng 		length -= start;		/* length is in pixels */
163069c7ec87Sslatteng 
163169c7ec87Sslatteng 		i = start & 7;
163269c7ec87Sslatteng 		start = start >> 3;		/* start is in bytes */
163369c7ec87Sslatteng 		raster = bottompage + start;
163469c7ec87Sslatteng 		glyph = leftstipple + (start & bytemask);
163569c7ec87Sslatteng 
163669c7ec87Sslatteng 		if (i) {			/* do any piece of byte */
163769c7ec87Sslatteng 		    register char data;		/* that hangs on the front */
163869c7ec87Sslatteng 
163969c7ec87Sslatteng 		    data = (*(glyph++)) & (0x7f >> --i);
164069c7ec87Sslatteng 		    length -= 7 - i;
164169c7ec87Sslatteng 		    if (length < 0) {		/* less than one byte wide? */
164269c7ec87Sslatteng 			data &= 0xff << -length;
164369c7ec87Sslatteng 			length = 0;	/* force clean stoppage */
164469c7ec87Sslatteng 		    }
164569c7ec87Sslatteng 		    *(raster++) |= data;
164669c7ec87Sslatteng 					/* update glyph ptr after first byte */
164769c7ec87Sslatteng 		    if (!(++start & bytemask))
164869c7ec87Sslatteng 			glyph = leftstipple;
164969c7ec87Sslatteng 		}
165069c7ec87Sslatteng 						/* fill the line of raster */
165169c7ec87Sslatteng 		while ((length -= 8) >= 0) {
165269c7ec87Sslatteng 		    *(raster++) |= *(glyph++);
165369c7ec87Sslatteng 		    if (!(++start & bytemask))
165469c7ec87Sslatteng 			glyph = leftstipple;
165569c7ec87Sslatteng 		}
165669c7ec87Sslatteng 		if (length & 7) {	/* add any part hanging off the end */
165769c7ec87Sslatteng 		    *raster |= (*glyph) & (0xff << -length);
165869c7ec87Sslatteng 		}
165969c7ec87Sslatteng 	      }
166069c7ec87Sslatteng 	    }
166169c7ec87Sslatteng 
166269c7ec87Sslatteng #ifdef DEBUGABLE
166369c7ec87Sslatteng 	    if (dbg) {
166469c7ec87Sslatteng 		vectptr = activehead;
166569c7ec87Sslatteng 		do {
166669c7ec87Sslatteng 		    fprintf (stderr, "%d ", vectptr->curry);
166769c7ec87Sslatteng 		    vectptr = vectptr->next;
166869c7ec87Sslatteng 		} while (vectptr != activehead);
166969c7ec87Sslatteng 	    }
167069c7ec87Sslatteng #endif
167169c7ec87Sslatteng 					/* update the vectors */
167269c7ec87Sslatteng 	    vectptr = activehead->next;
167369c7ec87Sslatteng 	    do {
167469c7ec87Sslatteng 		if (vectptr->dy > 0) {
167569c7ec87Sslatteng 		    while (vectptr->param >= 0) {
167669c7ec87Sslatteng 			vectptr->param -= vectptr->dx;
167769c7ec87Sslatteng 			vectptr->curry++;
167869c7ec87Sslatteng 		    }
167969c7ec87Sslatteng 		    vectptr->param += vectptr->dy;
168069c7ec87Sslatteng 		} else if (vectptr->dy < 0) {
168169c7ec87Sslatteng 		    while (vectptr->param >= 0) {
168269c7ec87Sslatteng 			vectptr->param -= vectptr->dx;
168369c7ec87Sslatteng 			vectptr->curry--;
168469c7ec87Sslatteng 		    }
168569c7ec87Sslatteng 		    vectptr->param -= vectptr->dy;
168669c7ec87Sslatteng 		}
168769c7ec87Sslatteng 					/* must sort the vectors if updates */
168869c7ec87Sslatteng 					/* caused them to cross */
168969c7ec87Sslatteng 					/* also move to next vector here */
169069c7ec87Sslatteng 		if (vectptr->curry > vectptr->prev->curry) {
169169c7ec87Sslatteng 		    register polyvector *v;		/* vector to move */
169269c7ec87Sslatteng 		    register polyvector *p;	/* vector to put it after */
169369c7ec87Sslatteng 
169469c7ec87Sslatteng 		    v = vectptr;
169569c7ec87Sslatteng 		    p = v->prev;
169669c7ec87Sslatteng 		    while (v->curry > p->curry)	/* find the */
169769c7ec87Sslatteng 			p = p->prev;		/* right vector */
169869c7ec87Sslatteng 
169969c7ec87Sslatteng 		    vectptr = vectptr->next;	/* remove from spot */
170069c7ec87Sslatteng 		    vectptr->prev = v->prev;
170169c7ec87Sslatteng 		    v->prev->next = vectptr;
170269c7ec87Sslatteng 
170369c7ec87Sslatteng 		    v->prev = p;		/* put in new spot */
170469c7ec87Sslatteng 		    v->next = p->next;
170569c7ec87Sslatteng 		    p->next = v;
170669c7ec87Sslatteng 		    v->next->prev = v;
170769c7ec87Sslatteng 		} else {
170869c7ec87Sslatteng 		    vectptr = vectptr->next;
170969c7ec87Sslatteng 		}
171069c7ec87Sslatteng 	    } while (vectptr != activehead);
171169c7ec87Sslatteng #ifdef DEBUGABLE
171269c7ec87Sslatteng 	    if (dbg) fprintf(stderr, "line done\n");
171369c7ec87Sslatteng #endif
171469c7ec87Sslatteng 
171569c7ec87Sslatteng 	    if (++minx & mask) {
171669c7ec87Sslatteng 		leftstipple += bytewidth;
171769c7ec87Sslatteng 	    } else {
171869c7ec87Sslatteng 		leftstipple = topstipple;
171969c7ec87Sslatteng 	    }
172069c7ec87Sslatteng 	    bottompage += BYTES_PER_LINE;
172169c7ec87Sslatteng 	} /* while (minx < nextx) */
172269c7ec87Sslatteng     } /* while (minx <= maxx) */
172369c7ec87Sslatteng 
172469c7ec87Sslatteng leavepoly:
172569c7ec87Sslatteng     nfree(waitinghead);
172669c7ec87Sslatteng }  /* polygon function */
1727