1*24162Sslatteng /*	dver.c	1.17	85/08/05
212593Sslatteng  *
316099Sslatteng  * VAX Versatec driver for the new troff
412587Sslatteng  *
513857Sslatteng  * Authors:	BWK(BELL)
613857Sslatteng  *		VCAT(berkley)
713857Sslatteng  *		Richard L. Hyde, Perdue University
814759Sslatteng  *		and David Slattengren, U.C. Berkeley
912587Sslatteng  */
1012587Sslatteng 
1112587Sslatteng 
1212593Sslatteng /*******************************************************************************
1312587Sslatteng 
1412593Sslatteng     output language from troff:
1512593Sslatteng     all numbers are character strings
1612593Sslatteng 
1713275Sslatteng #..\n	comment
1812587Sslatteng sn	size in points
1913275Sslatteng fn	font as number from 1 to n
2016538Sslatteng in	stipple as number from 1 to n
2112587Sslatteng cx	ascii character x
2213275Sslatteng Cxyz	funny char \(xyz. terminated by white space
2312587Sslatteng Hn	go to absolute horizontal position n
2412587Sslatteng Vn	go to absolute vertical position n (down is positive)
2512587Sslatteng hn	go n units horizontally (relative)
2612587Sslatteng vn	ditto vertically
2712587Sslatteng nnc	move right nn, then print c (exactly 2 digits!)
2812587Sslatteng 		(this wart is an optimization that shrinks output file size
2912587Sslatteng 		 about 35% and run-time about 15% while preserving ascii-ness)
3014759Sslatteng pn	new page begins (number n) -- set v to 0
3114759Sslatteng P	spread ends -- output it.
3213275Sslatteng nb a	end of line (information only -- no action needed)
3313275Sslatteng 	b = space before line, a = after
3413275Sslatteng w	paddable word space -- no action needed
3513275Sslatteng 
3612593Sslatteng Dt ..\n	draw operation 't':
3716538Sslatteng 	Dt d		set line thickness to d pixels
3816538Sslatteng 	Ds d		set line style mask to d
3912587Sslatteng 	Dl x y		line from here by x,y
4012587Sslatteng 	Dc d		circle of diameter d with left side here
4112587Sslatteng 	De x y		ellipse of axes x,y with left side here
4212587Sslatteng 	Da x y r	arc counter-clockwise by x,y of radius r
4313275Sslatteng 	D~ x y x y ...	B-spline curve by x,y then x,y ...
4416538Sslatteng 	Dg x y x y ...	gremlin spline curve by x,y then x,y ...
4516538Sslatteng 	Dq d n miny maxy [p dx dy curx endy]	polygon filled with d, has n
4616538Sslatteng 			vectors, with extents from miny to maxy (no border)
4713275Sslatteng 
4812593Sslatteng x ..\n	device control functions:
4913275Sslatteng      x i	init
5013275Sslatteng      x T s	name of device is s
5113275Sslatteng      x r n h v	resolution is n/inch h = min horizontal motion, v = min vert
5213275Sslatteng      x p	pause (can restart)
5313275Sslatteng      x s	stop -- done for ever
5413275Sslatteng      x t	generate trailer
5513275Sslatteng      x f n s	font position n contains font s
5613275Sslatteng      x H n	set character height to n
5713275Sslatteng      x S n	set slant to N
5812587Sslatteng 
5912587Sslatteng 	Subcommands like "i" are often spelled out like "init".
6012587Sslatteng 
6112593Sslatteng *******************************************************************************/
6212593Sslatteng 
6312593Sslatteng 
6412593Sslatteng #include <stdio.h>
6512593Sslatteng #include <ctype.h>
6613275Sslatteng #include <sys/vcmd.h>
6712587Sslatteng #include "dev.h"
6812587Sslatteng 
6912587Sslatteng 
7015282Sslatteng /* #define DEBUGABLE		/* No, not debugable... */
7115282Sslatteng #define DRIVER			/* Yes, we're driving directly */
7216538Sslatteng #define	NFONTS	65		/* total number of fonts useable */
7313787Sslatteng #define	MAXSTATE 6		/* number of environments rememberable */
7413275Sslatteng #define OPENREAD 0		/* mode for openning files */
7513275Sslatteng #define RESTART	1		/* upon exit, return either RESTART */
7613275Sslatteng #define ABORT	2		/*     or ABORT */
7713275Sslatteng #define	FATAL	1		/* type of error */
7813275Sslatteng #define	BMASK	0377		/* byte grabber */
7915735Sslatteng #ifndef FONTDIR
8014759Sslatteng #define FONTDIR	"/usr/lib/font"	/* default place to find font descriptions */
8115735Sslatteng #endif
8219068Sslatteng #ifndef BITDIR
8314759Sslatteng #define BITDIR "/usr/lib/vfont" /* default place to look for font rasters */
8419068Sslatteng #endif
8513787Sslatteng #define MAXWRIT 4096		/* max characters allowed to write at once */
8612587Sslatteng 
8713275Sslatteng #define  hmot(n)	hpos += n
8813275Sslatteng #define  hgoto(n)	hpos = n
8914759Sslatteng #define  vmot(n)	vgoto(vpos + (n))
9012593Sslatteng 
9113275Sslatteng 
92*24162Sslatteng char	SccsId[]= "dver.c	1.17	85/08/05";
9313275Sslatteng 
9412587Sslatteng int	output	= 0;	/* do we do output at all? */
9512587Sslatteng int	nolist	= 0;	/* output page list if > 0 */
9612587Sslatteng int	olist[20];	/* pairs of page numbers */
9712587Sslatteng struct	dev	dev;
9813275Sslatteng struct	font	*fontbase[NFONTS+1];
9914759Sslatteng short *	pstab;		/* point size table pointer */
10013787Sslatteng int	nsizes;		/* number of sizes device is capable of printing */
10116538Sslatteng int	nfonts = 1;	/* number of fonts device is capable of printing */
10216538Sslatteng int	nstips = 1;	/* number of stipple fonts device can print */
10312587Sslatteng int	nchtab;
10414759Sslatteng char *	chname;
10514759Sslatteng short *	chtab;
10614759Sslatteng char *	fitab[NFONTS+1];	/* font inclusion table - maps ascii to ch # */
10714759Sslatteng char *	widtab[NFONTS+1];	/* width table for each font */
10814759Sslatteng char *	codetab[NFONTS+1];	/* device codes */
10914759Sslatteng char *	fontdir = FONTDIR;	/* place to find devxxx directories */
11014759Sslatteng char *	bitdir = BITDIR;	/* place to find raster fonts and fontmap */
11115282Sslatteng char *	fontname[NFONTS+1];	/* list of what font is on what position */
11213787Sslatteng struct {			/* table of what font */
11314759Sslatteng 	char fname[3];		/*   name maps to what */
11414759Sslatteng 	char *ffile;		/*   filename in bitdirectory */
11514759Sslatteng } fontmap[NFONTS+1];
11612587Sslatteng 
11713275Sslatteng #ifdef DEBUGABLE
11812587Sslatteng int	dbg	= 0;
11913275Sslatteng #endif
12014759Sslatteng int	size	= 1;	/* current point size (internal pstable index) */
12114759Sslatteng int	font	= 1;	/* current font - assume reasonable starting font */
12216538Sslatteng int	stip	= -1;	/* current stipple font - none to start with */
12316538Sslatteng int	stipmem	= 0;	/* current member from stipple font to use */
12412593Sslatteng int	hpos;		/* horizontal position we are to be at next; left = 0 */
12512587Sslatteng int	vpos;		/* current vertical position (down positive) */
12614759Sslatteng int	maxv;		/* farthest down the page we've been */
12714759Sslatteng extern	linethickness;	/* thickness (in pixels) of any drawn object */
12814283Sslatteng extern	linmod;		/* line style (a bit mask - dotted, etc.) of objects */
12913787Sslatteng int	lastw;		/* width of last character printed */
13012587Sslatteng 
13112587Sslatteng 
13213275Sslatteng #define DISPATCHSIZE	256		/* must be a power of two */
13313275Sslatteng #define CHARMASK	(DISPATCHSIZE-1)
13413275Sslatteng #define DSIZ		((sizeof *dispatch)*DISPATCHSIZE)
13513275Sslatteng #define OUTFILE 	fileno (stdout)
13612587Sslatteng 
13714759Sslatteng #define	RES		200		/* resolution of the device (dots/in) */
13814759Sslatteng #define RASTER_LENGTH	7040		/* device line length */
13913275Sslatteng #define BYTES_PER_LINE	(RASTER_LENGTH/8)
14015619Sslatteng #define BAND		1			/* length of a band in inches */
14115282Sslatteng #define NLINES		(int)(BAND * RES)	/* BAND" long bands */
14213787Sslatteng #define BUFFER_SIZE	(NLINES*BYTES_PER_LINE)	/* number of chars in picture */
14312587Sslatteng 
14414759Sslatteng #define BUFTOP		(&buffer[0])
14514759Sslatteng #define BUFBOTTOM	(&buffer[BUFFER_SIZE] - 1)
14615282Sslatteng #define buf0p		BUFTOP			/* vorigin in circular buffer */
14714759Sslatteng #define PAGEEND		1			/* flags to "outband" to tell */
14814759Sslatteng #define OVERBAND	0			/* whether to fill out a page */
14913275Sslatteng 
15014759Sslatteng 
15113275Sslatteng int	pltmode[] = { VPLOT };
15213275Sslatteng int	prtmode[] = { VPRINT };
15314759Sslatteng char	buffer[BUFFER_SIZE];	/* versatec-wide NLINES buffer */
15414759Sslatteng int	vorigin = 0;		/* where on the page startbuf maps to */
15514759Sslatteng int	pagelen = 0;		/* how long the current "page" has printed */
15612587Sslatteng 
15714759Sslatteng char *	calloc();
15814759Sslatteng char *	nalloc();
15914759Sslatteng char *	allpanic();
16015282Sslatteng char *	operand();
16112587Sslatteng 
16213275Sslatteng struct header {
16312587Sslatteng 	short	magic;
16412587Sslatteng 	unsigned short	size;
16512587Sslatteng 	short	maxx;
16612587Sslatteng 	short	maxy;
16712587Sslatteng 	short	xtnd;
16812587Sslatteng } header;
16912587Sslatteng 
17012587Sslatteng struct	dispatch{
17112587Sslatteng 	unsigned short	addr;
17212587Sslatteng 	short	nbytes;
17312587Sslatteng 	char	up;
17412587Sslatteng 	char	down;
17512587Sslatteng 	char	left;
17612587Sslatteng 	char	right;
17712587Sslatteng 	short	width;
17812587Sslatteng };
17912587Sslatteng 
18012587Sslatteng struct	fontdes {
18115282Sslatteng 	int	fnum;			/* if == -1, this position unused */
18212587Sslatteng 	int	psize;
18312587Sslatteng 	struct	dispatch *disp;
18412587Sslatteng 	char	*bits;
18515282Sslatteng } fontdes[NFONTS+1];			/* is initialized at start of main */
18612587Sslatteng 
18712587Sslatteng struct dispatch *dispatch;
18816538Sslatteng struct dispatch *stip_disp;
18912587Sslatteng int	cfnum = -1;
19012587Sslatteng int	cpsize = 10;
19112587Sslatteng int	cfont = 1;
19212587Sslatteng char	*bits;
19316538Sslatteng char	*stip_bits;
19413275Sslatteng int	fontwanted = 1;		/* flag:  "has a new font been requested?" */
19512587Sslatteng int	nfontnum = -1;
19612587Sslatteng int	npsize = 10;
19712587Sslatteng 
19813275Sslatteng 
19912587Sslatteng 
main(argc,argv)20012587Sslatteng main(argc, argv)
20112587Sslatteng char *argv[];
20212587Sslatteng {
20315282Sslatteng 	register FILE *fp;
20415282Sslatteng 	register int i;
20512587Sslatteng 
20615282Sslatteng 	for (i = 0; i <= NFONTS; fontdes[i++].fnum = -1);
20715282Sslatteng 	while (--argc > 0 && **++argv == '-') {
20815282Sslatteng 		switch ((*argv)[1]) {
20912587Sslatteng 		case 'F':
21015282Sslatteng 			bitdir = operand(&argc, &argv);
21112587Sslatteng 			break;
21214759Sslatteng 		case 'f':
21315282Sslatteng 			fontdir = operand(&argc, &argv);
21414759Sslatteng 			break;
21512587Sslatteng 		case 'o':
21615282Sslatteng 			outlist(operand(&argc, &argv));
21712587Sslatteng 			break;
21813275Sslatteng #ifdef DEBUGABLE
21912587Sslatteng 		case 'd':
22015282Sslatteng 			dbg = atoi(operand(&argc, &argv));
22112587Sslatteng 			if (dbg == 0) dbg = 1;
22212587Sslatteng 			break;
22313275Sslatteng #endif
22412587Sslatteng 		}
22512587Sslatteng 	}
22615282Sslatteng #ifdef DRIVER
22715282Sslatteng 	ioctl(OUTFILE, VSETSTATE, pltmode);
22815282Sslatteng #endif
22912587Sslatteng 
23015282Sslatteng 	if (argc < 1)
23112587Sslatteng 		conv(stdin);
23212587Sslatteng 	else
23315282Sslatteng 		while (argc-- > 0) {
23415282Sslatteng 			if (strcmp(*argv, "-") == 0)
23512587Sslatteng 				fp = stdin;
23612587Sslatteng 			else if ((fp = fopen(*argv, "r")) == NULL)
23712587Sslatteng 				error(FATAL, "can't open %s", *argv);
23812587Sslatteng 			conv(fp);
23912587Sslatteng 			fclose(fp);
24015282Sslatteng 			argv++;
24112587Sslatteng 		}
24212587Sslatteng 	exit(0);
24312587Sslatteng }
24412587Sslatteng 
24515282Sslatteng 
24615282Sslatteng /*----------------------------------------------------------------------------*
24715282Sslatteng  | Routine:	char  * operand (& argc,  & argv)
24815282Sslatteng  |
24915282Sslatteng  | Results:	returns address of the operand given with a command-line
25015282Sslatteng  |		option.  It uses either "-Xoperand" or "-X operand", whichever
25115282Sslatteng  |		is present.  The program is terminated if no option is present.
25215282Sslatteng  |
25315282Sslatteng  | Side Efct:	argc and argv are updated as necessary.
25415282Sslatteng  *----------------------------------------------------------------------------*/
25515282Sslatteng 
operand(argcp,argvp)25615282Sslatteng char *operand(argcp, argvp)
25715282Sslatteng int * argcp;
25815282Sslatteng char ***argvp;
25915282Sslatteng {
26015282Sslatteng 	if ((**argvp)[2]) return(**argvp + 2); /* operand immediately follows */
26115282Sslatteng 	if ((--*argcp) <= 0) {			/* no operand */
26215282Sslatteng 	    error (FATAL, "command-line option operand missing.");
26315282Sslatteng 	}
26415282Sslatteng 	return(*(++(*argvp)));			/* operand next word */
26515282Sslatteng }
26615282Sslatteng 
26715282Sslatteng 
outlist(s)26812587Sslatteng outlist(s)	/* process list of page numbers to be printed */
26912587Sslatteng char *s;
27012587Sslatteng {
27115282Sslatteng 	int n1, n2;
27215282Sslatteng #ifdef DEBUGABLE
27315282Sslatteng 	int i;
27415282Sslatteng #endif
27512587Sslatteng 
27612587Sslatteng 	nolist = 0;
27712587Sslatteng 	while (*s) {
27812587Sslatteng 		n1 = 0;
27912587Sslatteng 		if (isdigit(*s))
28012587Sslatteng 			do
28112587Sslatteng 				n1 = 10 * n1 + *s++ - '0';
28212587Sslatteng 			while (isdigit(*s));
28312587Sslatteng 		else
28412587Sslatteng 			n1 = -9999;
28512587Sslatteng 		n2 = n1;
28612587Sslatteng 		if (*s == '-') {
28712587Sslatteng 			s++;
28812587Sslatteng 			n2 = 0;
28912587Sslatteng 			if (isdigit(*s))
29012587Sslatteng 				do
29112587Sslatteng 					n2 = 10 * n2 + *s++ - '0';
29212587Sslatteng 				while (isdigit(*s));
29312587Sslatteng 			else
29412587Sslatteng 				n2 = 9999;
29512587Sslatteng 		}
29612587Sslatteng 		olist[nolist++] = n1;
29712587Sslatteng 		olist[nolist++] = n2;
29812587Sslatteng 		if (*s != '\0')
29912587Sslatteng 			s++;
30012587Sslatteng 	}
30112587Sslatteng 	olist[nolist] = 0;
30213275Sslatteng #ifdef DEBUGABLE
30312587Sslatteng 	if (dbg)
30412587Sslatteng 		for (i=0; i<nolist; i += 2)
30512587Sslatteng 			fprintf(stderr,"%3d %3d\n", olist[i], olist[i+1]);
30613275Sslatteng #endif
30712587Sslatteng }
30812587Sslatteng 
conv(fp)30912587Sslatteng conv(fp)
31012587Sslatteng register FILE *fp;
31112587Sslatteng {
31212587Sslatteng 	register int c, k;
31312587Sslatteng 	int m, n, n1, m1;
31412587Sslatteng 	char str[100], buf[300];
31512587Sslatteng 
31612587Sslatteng 	while ((c = getc(fp)) != EOF) {
31712587Sslatteng 		switch (c) {
31812587Sslatteng 		case '\n':	/* when input is text */
31916196Sslatteng 		case 0:		/* occasional noise creeps in */
32016196Sslatteng 		case '\t':
32112587Sslatteng 		case ' ':
32212587Sslatteng 			break;
32312587Sslatteng 		case '{':	/* push down current environment */
32412587Sslatteng 			t_push();
32512587Sslatteng 			break;
32612587Sslatteng 		case '}':
32712587Sslatteng 			t_pop();
32812587Sslatteng 			break;
32912587Sslatteng 		case '0': case '1': case '2': case '3': case '4':
33012587Sslatteng 		case '5': case '6': case '7': case '8': case '9':
33112587Sslatteng 			/* two motion digits plus a character */
33212587Sslatteng 			hmot((c-'0')*10 + getc(fp)-'0');
33312587Sslatteng 			put1(getc(fp));
33412587Sslatteng 			break;
33512587Sslatteng 		case 'c':	/* single ascii character */
33612587Sslatteng 			put1(getc(fp));
33712587Sslatteng 			break;
33812587Sslatteng 		case 'C':
33912587Sslatteng 			fscanf(fp, "%s", str);
34012587Sslatteng 			put1s(str);
34112587Sslatteng 			break;
34212587Sslatteng 		case 't':	/* straight text */
34316196Sslatteng 			if (fgets(buf, sizeof(buf), fp) == NULL)
34416196Sslatteng 			    error(FATAL, "unexpected end of input");
34512587Sslatteng 			t_text(buf);
34612587Sslatteng 			break;
34712587Sslatteng 		case 'D':	/* draw function */
34816196Sslatteng 			if (fgets(buf, sizeof(buf), fp) == NULL)
34916196Sslatteng 			    error(FATAL, "unexpected end of input");
35012587Sslatteng 			switch (buf[0]) {
35112587Sslatteng 			case 'l':	/* draw a line */
35212593Sslatteng 			    sscanf(buf+1, "%d %d", &n, &m);
35313787Sslatteng 			    drawline(n, m);
35412593Sslatteng 			    break;
35512587Sslatteng 			case 'c':	/* circle */
35612593Sslatteng 			    sscanf(buf+1, "%d", &n);
35712593Sslatteng 			    drawcirc(n);
35812593Sslatteng 			    break;
35912587Sslatteng 			case 'e':	/* ellipse */
36012593Sslatteng 			    sscanf(buf+1, "%d %d", &m, &n);
36112593Sslatteng 			    drawellip(m, n);
36212593Sslatteng 			    break;
36312587Sslatteng 			case 'a':	/* arc */
36412593Sslatteng 			    sscanf(buf+1, "%d %d %d %d", &n, &m, &n1, &m1);
36512593Sslatteng 			    drawarc(n, m, n1, m1);
36612593Sslatteng 			    break;
36716538Sslatteng                         case 'q':	/* polygon */
36816538Sslatteng 			    n = 1;			/* get stipple */
36916538Sslatteng 			    while (isspace(buf[++n]));	/* number first */
37016538Sslatteng 			    setfill(atoi(&(buf[n])));	/* set up stipple */
37116538Sslatteng 			    while (isdigit(buf[++n]));
37216538Sslatteng 			    polygon(&(buf[n]), fp);	/* draw polygon */
37316538Sslatteng                             break;
37412587Sslatteng 			case '~':	/* wiggly line */
37513889Sslatteng 			case 'g':	/* gremlin spline */
37613889Sslatteng 			    drawwig(buf+1, fp, buf[0] == '~');
37712593Sslatteng 			    break;
37813889Sslatteng 			case 't':	/* line thickness */
37913889Sslatteng 			    sscanf(buf+1, "%d", &n);
38013889Sslatteng 			    drawthick(n);
38113889Sslatteng 			    break;
38213889Sslatteng 			case 's':	/* line style */
38313889Sslatteng 			    sscanf(buf+1, "%d", &n);
38413889Sslatteng 			    drawstyle(n);
38513889Sslatteng 			    break;
38612587Sslatteng 			default:
38714759Sslatteng 			    error(FATAL, "unknown drawing function %s", buf);
38812593Sslatteng 			    break;
38912587Sslatteng 			}
39012587Sslatteng 			break;
39112587Sslatteng 		case 's':
39216196Sslatteng 			fscanf(fp, "%d", &n);
39312587Sslatteng 			setsize(t_size(n));
39412587Sslatteng 			break;
39516538Sslatteng 		case 'i':
39616538Sslatteng 			fscanf(fp, "%d", &n);
39716538Sslatteng 			setstip(n);
39816538Sslatteng 			break;
39912587Sslatteng 		case 'f':
40012587Sslatteng 			fscanf(fp, "%s", str);
40112587Sslatteng 			setfont(t_font(str));
40212587Sslatteng 			break;
40312587Sslatteng 		case 'H':	/* absolute horizontal motion */
40412587Sslatteng 			while ((c = getc(fp)) == ' ')
40512587Sslatteng 				;
40612587Sslatteng 			k = 0;
40712587Sslatteng 			do {
40812587Sslatteng 				k = 10 * k + c - '0';
40912587Sslatteng 			} while (isdigit(c = getc(fp)));
41012587Sslatteng 			ungetc(c, fp);
41112587Sslatteng 			hgoto(k);
41212587Sslatteng 			break;
41312587Sslatteng 		case 'h':	/* relative horizontal motion */
41412587Sslatteng 			while ((c = getc(fp)) == ' ')
41512587Sslatteng 				;
41612587Sslatteng 			k = 0;
41712587Sslatteng 			do {
41812587Sslatteng 				k = 10 * k + c - '0';
41912587Sslatteng 			} while (isdigit(c = getc(fp)));
42012587Sslatteng 			ungetc(c, fp);
42112587Sslatteng 			hmot(k);
42212587Sslatteng 			break;
42312587Sslatteng 		case 'w':	/* word space */
42412587Sslatteng 			break;
42512587Sslatteng 		case 'V':
42612587Sslatteng 			fscanf(fp, "%d", &n);
42712587Sslatteng 			vgoto(n);
42812587Sslatteng 			break;
42912587Sslatteng 		case 'v':
43012587Sslatteng 			fscanf(fp, "%d", &n);
43112587Sslatteng 			vmot(n);
43212587Sslatteng 			break;
43314759Sslatteng 		case 'P':	/* new spread */
43415282Sslatteng 			if (output) outband(OVERBAND);
43514759Sslatteng 			break;
43612587Sslatteng 		case 'p':	/* new page */
43712587Sslatteng 			fscanf(fp, "%d", &n);
43812587Sslatteng 			t_page(n);
43912587Sslatteng 			break;
44012587Sslatteng 		case 'n':	/* end of line */
44112587Sslatteng 			t_newline();
44216196Sslatteng 
44312587Sslatteng 		case '#':	/* comment */
44416196Sslatteng 			do
44516196Sslatteng 				c = getc(fp);
44616196Sslatteng 			while (c != '\n' && c != EOF);
44712587Sslatteng 			break;
44812587Sslatteng 		case 'x':	/* device control */
44915619Sslatteng 			if (devcntrl(fp)) return;
45012587Sslatteng 			break;
45112587Sslatteng 		default:
45214759Sslatteng 			error(FATAL, "unknown input character %o %c", c, c);
45312587Sslatteng 		}
45412587Sslatteng 	}
45512587Sslatteng }
45612587Sslatteng 
devcntrl(fp)45715619Sslatteng int devcntrl(fp)	/* interpret device control functions */
45815619Sslatteng FILE *fp;		/* returns -1 apon recieving "stop" command */
45912587Sslatteng {
46012587Sslatteng         char str[20], str1[50], buf[50];
46112587Sslatteng 	int c, n;
46212587Sslatteng 
46312587Sslatteng 	fscanf(fp, "%s", str);
46412587Sslatteng 	switch (str[0]) {	/* crude for now */
46512587Sslatteng 	case 'i':	/* initialize */
46612587Sslatteng 		fileinit();
46713787Sslatteng 		t_init();
46812587Sslatteng 		break;
46912587Sslatteng 	case 't':	/* trailer */
47012587Sslatteng 		break;
47112587Sslatteng 	case 'p':	/* pause -- can restart */
47212587Sslatteng 		t_reset('p');
47312587Sslatteng 		break;
47412587Sslatteng 	case 's':	/* stop */
47512587Sslatteng 		t_reset('s');
47615619Sslatteng 		return -1;
47712587Sslatteng 	case 'r':	/* resolution assumed when prepared */
47814759Sslatteng 		fscanf(fp, "%d", &n);
47916538Sslatteng 		if (n!=RES) error(FATAL,"Input computed for wrong printer");
48012587Sslatteng 		break;
48112587Sslatteng 	case 'f':	/* font used */
48212587Sslatteng 		fscanf(fp, "%d %s", &n, str);
48315282Sslatteng 		(void) fgets(buf, sizeof buf, fp);   /* in case of filename */
48412593Sslatteng 		ungetc('\n', fp);		/* fgets goes too far */
48512593Sslatteng 		str1[0] = 0;			/* in case nothing comes in */
48612587Sslatteng 		sscanf(buf, "%s", str1);
48712587Sslatteng 		loadfont(n, str, str1);
48812587Sslatteng 		break;
48912593Sslatteng 						/* these don't belong here... */
49012587Sslatteng 	case 'H':	/* char height */
49112587Sslatteng 		fscanf(fp, "%d", &n);
49212587Sslatteng 		t_charht(n);
49312587Sslatteng 		break;
49412587Sslatteng 	case 'S':	/* slant */
49512587Sslatteng 		fscanf(fp, "%d", &n);
49612587Sslatteng 		t_slant(n);
49712587Sslatteng 		break;
49812587Sslatteng 	}
49912587Sslatteng 	while ((c = getc(fp)) != '\n')	/* skip rest of input line */
50012587Sslatteng 		if (c == EOF)
50115619Sslatteng 			return -1;
50215619Sslatteng 	return 0;
50312587Sslatteng }
50412587Sslatteng 
50512593Sslatteng /* fileinit:	read in font and code files, etc.
50612593Sslatteng 		Must open table for device, read in resolution,
50714759Sslatteng 		size info, font info, etc. and set params.
50814759Sslatteng 		Also read in font name mapping.
50912593Sslatteng */
fileinit()51012593Sslatteng fileinit()
51112587Sslatteng {
51214759Sslatteng 	register int i;
51314759Sslatteng 	register int fin;
51414759Sslatteng 	register int nw;
51514759Sslatteng 	register char *filebase;
51614759Sslatteng 	register char *p;
51714759Sslatteng 	register FILE *fp;
51814759Sslatteng 	char	temp[100];
51912587Sslatteng 
52014759Sslatteng 
52114759Sslatteng 		/* first, read in font map file.  The file must be of Format:
52214759Sslatteng 			XX  FILENAME  (XX = troff font name)
52314759Sslatteng 			with one entry per text line of the file.
52414759Sslatteng 		   Extra stuff after FILENAME is ignored */
52514759Sslatteng 
52614759Sslatteng 	sprintf(temp, "%s/fontmap", bitdir);
52714759Sslatteng 	if ((fp = fopen(temp, "r")) == NULL)
52814759Sslatteng 		error(FATAL, "Can't open %s", temp);
52914759Sslatteng 	for (i = 0; i <= NFONTS && fgets(temp, 100, fp) != NULL; i++) {
53014759Sslatteng 		sscanf(temp, "%2s", fontmap[i].fname);
53114759Sslatteng 		p = &temp[0];
53214759Sslatteng 		while (*p != ' ' && *p != '	') p++;
53314759Sslatteng 		while (*p == ' ' || *p == '	') p++;
53414759Sslatteng 		filebase = p;
53514759Sslatteng 		for (nw = 1; *p != '\n' && *p != ' ' && *p != '\t'; p++) nw++;
53614759Sslatteng 		fontmap[i].ffile = nalloc(1, nw);
53714759Sslatteng 		sscanf(filebase, "%s", fontmap[i].ffile);
53814759Sslatteng 	}
53914759Sslatteng 	fontmap[++i].fname[0] = '0';		/* finish off with zeros */
54014759Sslatteng 	fontmap[i].ffile = (char *) 0;
54114759Sslatteng 	fclose(fp);
54214759Sslatteng #ifdef DEBUGABLE
54314759Sslatteng 	if(dbg) {
54414759Sslatteng 	    fprintf(stderr, "font map:\n");
54514759Sslatteng 	    for (i = 0; fontmap[i].ffile; i++)
54614759Sslatteng 		fprintf(stderr,"%s = %s\n", fontmap[i].fname, fontmap[i].ffile);
54714759Sslatteng 	}
54814759Sslatteng #endif
54914759Sslatteng 
55014759Sslatteng 
55115282Sslatteng 	sprintf(temp, "%s/devvp/DESC.out", fontdir);
55212587Sslatteng 	if ((fin = open(temp, 0)) < 0)
55314759Sslatteng 		error(FATAL, "can't open tables for %s", temp);
55415282Sslatteng 	if (read(fin, &dev, sizeof(struct dev)) != sizeof(struct dev))
55515282Sslatteng 		error(FATAL, "can't read header for %s", temp);
55612587Sslatteng 	nfonts = dev.nfonts;
55712587Sslatteng 	nsizes = dev.nsizes;
55816538Sslatteng 	nstips = dev.nstips;
55912587Sslatteng 	nchtab = dev.nchtab;
56014759Sslatteng 	filebase = calloc(1, dev.filesize);	/* enough room for whole file */
56115282Sslatteng 	if (read(fin, filebase, dev.filesize) != dev.filesize)	/* at once */
56215282Sslatteng 		error(FATAL, "can't read width table for %s", temp);
56312587Sslatteng 	pstab = (short *) filebase;
56412587Sslatteng 	chtab = pstab + nsizes + 1;
56512587Sslatteng 	chname = (char *) (chtab + dev.nchtab);
56612587Sslatteng 	p = chname + dev.lchname;
56712587Sslatteng 	for (i = 1; i <= nfonts; i++) {
56812587Sslatteng 		fontbase[i] = (struct font *) p;
56912593Sslatteng 		nw = *p & BMASK;		/* 1st thing is width count */
57015282Sslatteng 		p += sizeof(struct font);
57113275Sslatteng 		widtab[i] = p;
57212587Sslatteng 		codetab[i] = p + 2 * nw;
57312587Sslatteng 		fitab[i] = p + 3 * nw;
57412587Sslatteng 		p += 3 * nw + dev.nchtab + 128 - 32;
57512587Sslatteng 		t_fp(i, fontbase[i]->namefont, fontbase[i]->intname);
57613275Sslatteng #ifdef DEBUGABLE
57713275Sslatteng 		if (dbg > 1) fontprint(i);
57813275Sslatteng #endif
57912587Sslatteng 	}
58016538Sslatteng 	for (i = 1; i <= nstips; i++) {		/* add in stipple "filenames" */
58116538Sslatteng 		if (nfonts + i <= NFONTS)
58216538Sslatteng 			t_fp(nfonts + i, p, (char *)0);
58316538Sslatteng 		p += strlen(p) + 1;
58416538Sslatteng 	}
58512593Sslatteng 	fontbase[0] = (struct font *)
58612593Sslatteng 		calloc(1,3*255 + dev.nchtab + (128-32) + sizeof (struct font));
58713275Sslatteng 	widtab[0] = (char *) fontbase[0] + sizeof (struct font);
58812587Sslatteng 	fontbase[0]->nwfont = 255;
58912587Sslatteng 	close(fin);
59012587Sslatteng }
59112587Sslatteng 
59215282Sslatteng #ifdef DEBUGABLE
fontprint(i)59312587Sslatteng fontprint(i)	/* debugging print of font i (0,...) */
59412587Sslatteng {
59512587Sslatteng 	int j, n;
59612587Sslatteng 	char *p;
59712587Sslatteng 
59812587Sslatteng 	fprintf(stderr,"font %d:\n", i);
59912587Sslatteng 	p = (char *) fontbase[i];
60012587Sslatteng 	n = fontbase[i]->nwfont & BMASK;
60112593Sslatteng 	fprintf(stderr,
60212593Sslatteng 	    "base=0%o, nchars=%d, spec=%d, name=%s, widtab=0%o, fitab=0%o\n",p,
60313275Sslatteng 	    n,fontbase[i]->specfont,fontbase[i]->namefont,widtab[i],fitab[i]);
60412587Sslatteng 	fprintf(stderr,"widths:\n");
60512587Sslatteng 	for (j=0; j <= n; j++) {
60613275Sslatteng 		fprintf(stderr," %2d", widtab[i][j] & BMASK);
60712587Sslatteng 		if (j % 20 == 19) fprintf(stderr,"\n");
60812587Sslatteng 	}
60912587Sslatteng 	fprintf(stderr,"\ncodetab:\n");
61012587Sslatteng 	for (j=0; j <= n; j++) {
61112587Sslatteng 		fprintf(stderr," %2d", codetab[i][j] & BMASK);
61212587Sslatteng 		if (j % 20 == 19) fprintf(stderr,"\n");
61312587Sslatteng 	}
61412587Sslatteng 	fprintf(stderr,"\nfitab:\n");
61512587Sslatteng 	for (j=0; j <= dev.nchtab + 128-32; j++) {
61612587Sslatteng 		fprintf(stderr," %2d", fitab[i][j] & BMASK);
61712587Sslatteng 		if (j % 20 == 19) fprintf(stderr,"\n");
61812587Sslatteng 	}
61912587Sslatteng 	fprintf(stderr,"\n");
62012587Sslatteng }
62115282Sslatteng #endif
62212587Sslatteng 
62314759Sslatteng 
loadfont(n,s,s1)62412587Sslatteng loadfont(n, s, s1)	/* load font info for font s on position n (0...) */
62512587Sslatteng int n;
62612587Sslatteng char *s, *s1;
62712587Sslatteng {
62812587Sslatteng 	char temp[60];
62915619Sslatteng 	register int fin;
63015619Sslatteng 	register int nw;
63115619Sslatteng 	register int norig;
63212587Sslatteng 
63313275Sslatteng 	if (n < 0 || n > NFONTS)
63412587Sslatteng 		error(FATAL, "illegal fp command %d %s", n, s);
63512587Sslatteng 	if (strcmp(s, fontbase[n]->namefont) == 0)
63612587Sslatteng 		return;
63715619Sslatteng 
63815619Sslatteng 	for (fin = 1; fin <= NFONTS; fin++)	/* first check to see if the */
63915619Sslatteng 	    if (strcmp(s, fontbase[fin]->namefont) == 0) {  /* font is loaded */
64015619Sslatteng 		register char *c;			    /* somewhere else */
64115619Sslatteng 
64215619Sslatteng #define ptrswap(x, y) { c = (char*) (x); x = y; y = c; }
64316099Sslatteng #define ptrfswap(x, y) { c = (char*) (x); x = y; y = (struct font *)c; }
64415619Sslatteng 
64516099Sslatteng 		ptrfswap(fontbase[n], fontbase[fin]);
64615619Sslatteng 		ptrswap(codetab[n], codetab[fin]);
64715619Sslatteng 		ptrswap(widtab[n], widtab[fin]);
64815619Sslatteng 		ptrswap(fitab[n], fitab[fin]);
64915619Sslatteng 		t_fp(n, fontbase[n]->namefont, fontbase[n]->intname);
65015619Sslatteng 		t_fp(fin, fontbase[fin]->namefont, fontbase[fin]->intname);
65115619Sslatteng 		return;
65215619Sslatteng 	    }
65315619Sslatteng 
65412587Sslatteng 	if (s1 == NULL || s1[0] == '\0')
65515282Sslatteng 		sprintf(temp, "%s/devvp/%s.out", fontdir, s);
65612587Sslatteng 	else
65712587Sslatteng 		sprintf(temp, "%s/%s.out", s1, s);
65812587Sslatteng 	if ((fin = open(temp, 0)) < 0)
65912587Sslatteng 		error(FATAL, "can't open font table %s", temp);
66012587Sslatteng 	norig = fontbase[n]->nwfont & BMASK;
66115282Sslatteng 	if (read(fin,fontbase[n],3*norig+nchtab+128-32+sizeof(struct font)) < 0)
66215282Sslatteng 		error(FATAL, "Can't read in font %s on position %d", s, n);
66312587Sslatteng 	if ((fontbase[n]->nwfont & BMASK) > norig)
66414759Sslatteng 		error(FATAL, "Font %s too big for position %d", s, n);
66512587Sslatteng 	close(fin);
66612587Sslatteng 	nw = fontbase[n]->nwfont & BMASK;
66713275Sslatteng 	widtab[n] = (char *) fontbase[n] + sizeof(struct font);
66813275Sslatteng 	codetab[n] = (char *) widtab[n] + 2 * nw;
66913275Sslatteng 	fitab[n] = (char *) widtab[n] + 3 * nw;
67012587Sslatteng 	t_fp(n, fontbase[n]->namefont, fontbase[n]->intname);
67112593Sslatteng 	fontbase[n]->nwfont = norig;	/* to later use full original size */
67213275Sslatteng #ifdef DEBUGABLE
67312587Sslatteng 	if (dbg > 1) fontprint(n);
67413275Sslatteng #endif
67512587Sslatteng }
67612587Sslatteng 
67714759Sslatteng 
67812587Sslatteng /*VARARGS1*/
error(f,s,a1,a2,a3,a4,a5,a6,a7)67912587Sslatteng error(f, s, a1, a2, a3, a4, a5, a6, a7) {
68012587Sslatteng 	fprintf(stderr, "dver: ");
68112587Sslatteng 	fprintf(stderr, s, a1, a2, a3, a4, a5, a6, a7);
68212587Sslatteng 	fprintf(stderr, "\n");
68315282Sslatteng 	if (f) exit(ABORT);
68412587Sslatteng }
68512587Sslatteng 
68612587Sslatteng 
t_init()68713787Sslatteng t_init()	/* initialize device */
68812587Sslatteng {
68915282Sslatteng 	vorigin = pagelen = maxv = hpos = vpos = 0;
69012587Sslatteng 
69115282Sslatteng 	output = 0;		/* don't output anything yet */
69212587Sslatteng 	setsize(t_size(10));	/* start somewhere */
69312587Sslatteng 	setfont(1);
69412587Sslatteng }
69512587Sslatteng 
69612587Sslatteng 
69712587Sslatteng struct state {
69812587Sslatteng 	int	ssize;
69912587Sslatteng 	int	sfont;
70012587Sslatteng 	int	shpos;
70112587Sslatteng 	int	svpos;
70214283Sslatteng 	int	sstyle;
70314283Sslatteng 	int	sthick;
70412587Sslatteng };
70512587Sslatteng struct	state	state[MAXSTATE];
70612587Sslatteng struct	state	*statep = state;
70712587Sslatteng 
t_push()70812587Sslatteng t_push()	/* begin a new block */
70912587Sslatteng {
71012587Sslatteng 	statep->ssize = size;
71112587Sslatteng 	statep->sfont = font;
71214283Sslatteng 	statep->sstyle = linmod;
71314283Sslatteng 	statep->sthick = linethickness;
71412587Sslatteng 	statep->shpos = hpos;
71512587Sslatteng 	statep->svpos = vpos;
71612587Sslatteng 	if (statep++ >= state+MAXSTATE)
71712587Sslatteng 		error(FATAL, "{ nested too deep");
71812587Sslatteng }
71912587Sslatteng 
t_pop()72012587Sslatteng t_pop()	/* pop to previous state */
72112587Sslatteng {
72212587Sslatteng 	if (--statep < state)
72312587Sslatteng 		error(FATAL, "extra }");
72412587Sslatteng 	size = statep->ssize;
72512587Sslatteng 	font = statep->sfont;
72612587Sslatteng 	hpos = statep->shpos;
72712587Sslatteng 	vpos = statep->svpos;
72814283Sslatteng 	linmod = statep->sstyle;
72914283Sslatteng 	linethickness = statep->sthick;
73012587Sslatteng }
73112587Sslatteng 
73214759Sslatteng 
t_page(n)73312587Sslatteng t_page(n)	/* do whatever new page functions */
73412587Sslatteng {
73512587Sslatteng 	int i;
73612587Sslatteng 
73712587Sslatteng 
73815282Sslatteng 	if (output) outband(PAGEEND);
73915282Sslatteng 
74014759Sslatteng 	maxv = vpos = 0;
74112587Sslatteng 
74212587Sslatteng 	output = 1;
74312587Sslatteng 	if (nolist == 0)
74414759Sslatteng 		return;		/* no -o specified */
74512587Sslatteng 	output = 0;
74612587Sslatteng 	for (i = 0; i < nolist; i += 2)
74712587Sslatteng 		if (n >= olist[i] && n <= olist[i+1]) {
74812587Sslatteng 			output = 1;
74912587Sslatteng 			break;
75012587Sslatteng 		}
75112587Sslatteng }
75212587Sslatteng 
75314759Sslatteng 
outband(page)75414759Sslatteng outband(page)
75514759Sslatteng int page;
75614759Sslatteng {
75714759Sslatteng     register int outsize;
75814759Sslatteng 
75915282Sslatteng     if (page == PAGEEND) {		/* set outsize to inch boundary */
76016196Sslatteng 	outsize = (maxv + (RES - 2) - pagelen) / RES;
76115619Sslatteng 	vorigin = pagelen = 0;		/* reset for new page */
76215282Sslatteng 	if (outsize < 1) return;	/* if outsize <= zero, forget it */
76315282Sslatteng 
76416196Sslatteng 	outsize *= RES * BYTES_PER_LINE;
76516196Sslatteng 	vwrite(buf0p, outsize > BUFFER_SIZE ? BUFFER_SIZE : outsize);
76616196Sslatteng 	vclear(buf0p, BUFFER_SIZE);
76716196Sslatteng 	while ((outsize -= BUFFER_SIZE) > 0)
76816196Sslatteng 	    vwrite(buf0p, outsize > BUFFER_SIZE ? BUFFER_SIZE : outsize);
76916196Sslatteng     } else {
77014759Sslatteng 	vorigin += NLINES;
77114759Sslatteng 	pagelen += NLINES;
77214759Sslatteng 	vwrite(buf0p, BUFFER_SIZE);
77314759Sslatteng 	vclear(buf0p, BUFFER_SIZE);
77414759Sslatteng     }
77514759Sslatteng }
77614759Sslatteng 
77714759Sslatteng 
t_newline()77812587Sslatteng t_newline()	/* do whatever for the end of a line */
77912587Sslatteng {
78012587Sslatteng 	hpos = 0;	/* because we're now back at the left margin */
78112587Sslatteng }
78212587Sslatteng 
t_size(n)78312587Sslatteng t_size(n)	/* convert integer to internal size number*/
78412587Sslatteng int n;
78512587Sslatteng {
78612587Sslatteng 	int i;
78712587Sslatteng 
78812587Sslatteng 	if (n <= pstab[0])
78914759Sslatteng 		return(0);
79014759Sslatteng 	else if (n >= pstab[nsizes - 1])
79114759Sslatteng 		return(nsizes - 1);
79212587Sslatteng 	for (i = 0; n > pstab[i]; i++)
79312587Sslatteng 		;
79414759Sslatteng 	return(i);
79512587Sslatteng }
79612587Sslatteng 
79715282Sslatteng /*ARGSUSED*/
t_charht(n)79812587Sslatteng t_charht(n)	/* set character height to n */
79912587Sslatteng int n;
80012587Sslatteng {
80113275Sslatteng #ifdef DEBUGABLE
80214759Sslatteng 	if (dbg) error(!FATAL, "can't set height on versatec");
80313275Sslatteng #endif
80412587Sslatteng }
80512587Sslatteng 
80615282Sslatteng /*ARGSUSED*/
t_slant(n)80712587Sslatteng t_slant(n)	/* set slant to n */
80812587Sslatteng int n;
80912587Sslatteng {
81013275Sslatteng #ifdef DEBUGABLE
81114759Sslatteng 	if (dbg) error(!FATAL, "can't set slant on versatec");
81213275Sslatteng #endif
81312587Sslatteng }
81412587Sslatteng 
t_font(s)81512587Sslatteng t_font(s)	/* convert string to internal font number */
81612587Sslatteng char *s;
81712587Sslatteng {
81812587Sslatteng 	int n;
81912587Sslatteng 
82012587Sslatteng 	n = atoi(s);
82112587Sslatteng 	if (n < 0 || n > nfonts)
82212587Sslatteng 		n = 1;
82312587Sslatteng 	return(n);
82412587Sslatteng }
82512587Sslatteng 
t_text(s)82612587Sslatteng t_text(s)	/* print string s as text */
82712587Sslatteng char *s;
82812587Sslatteng {
82912587Sslatteng 	int c;
83012587Sslatteng 	char str[100];
83112587Sslatteng 
83212587Sslatteng 	if (!output)
83312587Sslatteng 		return;
83412587Sslatteng 	while (c = *s++) {
83512587Sslatteng 		if (c == '\\') {
83612587Sslatteng 			switch (c = *s++) {
83712587Sslatteng 			case '\\':
83812587Sslatteng 			case 'e':
83912587Sslatteng 				put1('\\');
84012587Sslatteng 				break;
84112587Sslatteng 			case '(':
84212587Sslatteng 				str[0] = *s++;
84312587Sslatteng 				str[1] = *s++;
84412587Sslatteng 				str[2] = '\0';
84512587Sslatteng 				put1s(str);
84612587Sslatteng 				break;
84712587Sslatteng 			}
84812587Sslatteng 		} else {
84912587Sslatteng 			put1(c);
85012587Sslatteng 		}
85112587Sslatteng 		hmot(lastw);
85213275Sslatteng #ifdef DEBUGABLE
85312587Sslatteng 		if (dbg) fprintf(stderr,"width = %d\n", lastw);
85413275Sslatteng #endif
85512587Sslatteng 	}
85612587Sslatteng }
85712587Sslatteng 
85814759Sslatteng 
t_reset(c)85912587Sslatteng t_reset(c)
86012587Sslatteng {
86112587Sslatteng 	switch(c){
86212587Sslatteng 	case 's':
86315282Sslatteng 		t_page(0);
86415282Sslatteng #ifdef DRIVER
86515282Sslatteng 		ioctl(OUTFILE, VSETSTATE, prtmode);
86615282Sslatteng #endif
86714759Sslatteng 		break;
86812587Sslatteng 	}
86912587Sslatteng }
87012587Sslatteng 
87112587Sslatteng 
vgoto(n)87214759Sslatteng vgoto (n)
87314759Sslatteng int n;
87412587Sslatteng {
87514759Sslatteng 	vpos = n;
87612587Sslatteng }
87712587Sslatteng 
87812587Sslatteng 
put1s(s)87912587Sslatteng put1s(s)	/* s is a funny char name */
88012587Sslatteng char *s;
88112587Sslatteng {
88212587Sslatteng 	int i;
88312587Sslatteng 
88412587Sslatteng 	if (!output)
88512587Sslatteng 		return;
88613275Sslatteng #ifdef DEBUGABLE
88712587Sslatteng 	if (dbg) fprintf(stderr,"%s ", s);
88813275Sslatteng #endif
88912587Sslatteng 	for (i = 0; i < nchtab; i++)
89012587Sslatteng 		if (strcmp(&chname[chtab[i]], s) == 0)
89112587Sslatteng 			break;
89212587Sslatteng 	if (i < nchtab)
89312587Sslatteng 		put1(i + 128);
89412587Sslatteng }
89512587Sslatteng 
put1(c)89612587Sslatteng put1(c)	/* output char c */
89712587Sslatteng int c;
89812587Sslatteng {
89912587Sslatteng 	char *pw;
90012587Sslatteng 	register char *p;
90112587Sslatteng 	register int i, k;
90212587Sslatteng 	int j, ofont, code;
90312587Sslatteng 
90412587Sslatteng 	if (!output)
90512587Sslatteng 		return;
90612587Sslatteng 	c -= 32;
90712587Sslatteng 	if (c <= 0) {
90813275Sslatteng #ifdef DEBUGABLE
90912587Sslatteng 		if (dbg) fprintf(stderr,"non-exist 0%o\n", c + 32);
91013275Sslatteng #endif
91114759Sslatteng  		lastw = (widtab[font][0] * pstab[size] + dev.unitwidth/2)
91213787Sslatteng 								/ dev.unitwidth;
91312587Sslatteng 		return;
91412587Sslatteng 	}
91512587Sslatteng 	k = ofont = font;
91612587Sslatteng 	i = fitab[font][c] & BMASK;
91713787Sslatteng 	if (i != 0) {			/* it's on this font */
91813787Sslatteng 		p = codetab[font];	/* get the printing value of ch */
91913787Sslatteng 		pw = widtab[font];	/* get the width */
92015282Sslatteng 	} else		/* on another font (we hope) */
92116099Sslatteng 		for (j=0; j <= nfonts; j++, k = (k+1) % (nfonts+1)){
92213275Sslatteng 			if (fitab[k] == 0)
92312587Sslatteng 				continue;
92412587Sslatteng 			if ((i = fitab[k][c] & BMASK) != 0) {
92512587Sslatteng 				p = codetab[k];
92613275Sslatteng 				pw = widtab[k];
92712587Sslatteng 				setfont(k);
92812587Sslatteng 				break;
92912587Sslatteng 			}
93012587Sslatteng 		}
93115282Sslatteng 
93216099Sslatteng 	if (i == 0) {
93313275Sslatteng #ifdef DEBUGABLE
93412587Sslatteng 		if (dbg) fprintf(stderr,"not found 0%o\n", c+32);
93513275Sslatteng #endif
93612587Sslatteng 		return;
93712587Sslatteng 	}
93816099Sslatteng 	code = p[i] & BMASK;
93913275Sslatteng #ifdef DEBUGABLE
94012587Sslatteng 	if (dbg) {
94112587Sslatteng 		if (isprint(c+32))
94212587Sslatteng 			fprintf(stderr,"%c %d\n", c+32, code);
94312587Sslatteng 		else
94412587Sslatteng 			fprintf(stderr,"%03o %d\n", c+32, code);
94513275Sslatteng 	}
94613275Sslatteng #endif
94713275Sslatteng 	outc(code);	/* character is < 254 */
94812587Sslatteng 	if (font != ofont)
94912587Sslatteng 		setfont(ofont);
95014759Sslatteng 	lastw = ((pw[i]&077) * pstab[size] + dev.unitwidth/2) / dev.unitwidth;
95112587Sslatteng }
95212587Sslatteng 
95312587Sslatteng 
95412587Sslatteng 
setsize(n)95512587Sslatteng setsize(n)	/* set point size to n (internal) */
95612587Sslatteng int n;
95712587Sslatteng {
95812587Sslatteng 
95912587Sslatteng 	if (n == size)
96012587Sslatteng 		return;	/* already there */
96114759Sslatteng 	if (vloadfont(font, pstab[n]) != -1)
96212587Sslatteng 		size = n;
96312587Sslatteng }
96412587Sslatteng 
96515282Sslatteng /*ARGSUSED*/
t_fp(n,s,si)96612587Sslatteng t_fp(n, s, si)	/* font position n now contains font s, intname si */
96715282Sslatteng int n;		/* internal name is ignored */
96812587Sslatteng char *s, *si;
96912587Sslatteng {
97014759Sslatteng 	register int i;
97112587Sslatteng 
97214759Sslatteng 			/* first convert s to filename if possible */
97314759Sslatteng 	for (i = 0; fontmap[i].ffile != (char *) 0; i++) {
97414759Sslatteng #ifdef DEBUGABLE
97514759Sslatteng 		if(dbg>1)fprintf(stderr,"testing :%s:%s:\n",s,fontmap[i].fname);
97614759Sslatteng #endif
97714759Sslatteng 		if (strcmp(s, fontmap[i].fname) == 0) {
97814759Sslatteng 			s = fontmap[i].ffile;
97914759Sslatteng #ifdef DEBUGABLE
98014759Sslatteng 			if(dbg)fprintf(stderr, "found :%s:\n",fontmap[i].ffile);
98114759Sslatteng #endif
98214759Sslatteng 			break;
98314759Sslatteng 		}
98414759Sslatteng 	}
98514759Sslatteng 
98615282Sslatteng 	fontname[n] = s;
98715282Sslatteng 	for(i = 0;i <= NFONTS;i++)	/* free the bits of that font */
98813275Sslatteng 		if (fontdes[i].fnum == n){
98912587Sslatteng 			nfree(fontdes[i].bits);
99012587Sslatteng 			fontdes[i].fnum = -1;
99112587Sslatteng 		}
99212587Sslatteng }
99312587Sslatteng 
setfont(n)99412587Sslatteng setfont(n)	/* set font to n */
99512587Sslatteng int n;
99612587Sslatteng {
99716538Sslatteng 	if (n < 0 || n > nfonts)
99814759Sslatteng 		error(FATAL, "illegal font %d", n);
99914759Sslatteng 	if (vloadfont(n,pstab[size]) != -1)
100012587Sslatteng 		font = n;
100112587Sslatteng }
100212587Sslatteng 
setstip(n)100316538Sslatteng setstip(n)	/* set stipple font to n */
100416538Sslatteng int n;
100516538Sslatteng {
100616538Sslatteng 	if (n < 1 || n > nstips)
100716538Sslatteng 		error(FATAL, "illegal stipple %d", n);
100816538Sslatteng 	stip = n;
100916538Sslatteng }
101016538Sslatteng 
101116538Sslatteng 
101216538Sslatteng /*----------------------------------------------------------------------------*
101316538Sslatteng  | Routine:	setfill(stipple_number)
101416538Sslatteng  |
101516538Sslatteng  | Results:	sets the fill-pattern pointers (stip_disp and
101616538Sslatteng  |		stip_bits) for a particular stipple.  Takes stipple
101716538Sslatteng  |		font from current "stip" number.
101816538Sslatteng  *----------------------------------------------------------------------------*/
101916538Sslatteng 
setfill(number)102016538Sslatteng setfill(number)
102116538Sslatteng int number;
102216538Sslatteng {
102316538Sslatteng 	int curfont;		/* places to save current text font */
102416538Sslatteng 	int cursize;
102516538Sslatteng 
102616538Sslatteng 					/* set global stipmem for polygon */
102716538Sslatteng 	if (number < 0 || number >= DISPATCHSIZE)
102816538Sslatteng 		stipmem = 0;
102916538Sslatteng 	else
103016538Sslatteng 		stipmem = number;
103116538Sslatteng 
103216538Sslatteng 	curfont = cfnum;		/* get pointers to */
103316538Sslatteng 	cursize = cpsize;		/* the inuse font */
103416538Sslatteng 	if (vloadfont(nfonts + stip, 0)) {
103516538Sslatteng 	    stip_disp = (struct dispatch *) NULL;	/* stipple not here */
103616538Sslatteng 	} else {
103716538Sslatteng 	    if (fontwanted) {
103816538Sslatteng 		if (getfont()) {
103916538Sslatteng 		    stip_disp = (struct dispatch *) NULL;
104016538Sslatteng 		} else {
104116538Sslatteng 		    stip_disp = dispatch;	/* save for polygon routine */
104216538Sslatteng 		    stip_bits = bits;
104316538Sslatteng 		}
104416538Sslatteng 	    } else {
104516538Sslatteng 		stip_disp = dispatch;	/* save for polygon routine */
104616538Sslatteng 		stip_bits = bits;
104716538Sslatteng 	    }
104816538Sslatteng 	}
104916538Sslatteng 	vloadfont(curfont, cursize);
105016538Sslatteng }
105116538Sslatteng 
105216538Sslatteng 
vloadfont(fnum,fsize)105312587Sslatteng vloadfont(fnum, fsize)
105412587Sslatteng register int fnum;
105512587Sslatteng register int fsize;
105612587Sslatteng {
105712587Sslatteng 	register int i;
105812587Sslatteng 
105912587Sslatteng 	fontwanted = 0;
106012587Sslatteng 	if (fnum == cfnum && fsize == cpsize)
106112587Sslatteng 		return(0);
106215282Sslatteng 	for (i = 0; i <= NFONTS; i++) {
106312587Sslatteng 		if (fontdes[i].fnum == fnum && fontdes[i].psize == fsize) {
106412587Sslatteng 			cfnum = fontdes[i].fnum;
106512587Sslatteng 			cpsize = fontdes[i].psize;
106612587Sslatteng 			dispatch = &fontdes[i].disp[0];
106712587Sslatteng 			bits = fontdes[i].bits;
106812587Sslatteng 			cfont = i;
106912587Sslatteng 			return (0);
107012587Sslatteng 		}
107112593Sslatteng 	}
107212587Sslatteng 		/* this is a new font */
107315282Sslatteng 	if (fnum < 0 || fnum > NFONTS || fontname[fnum] == 0) {
107414759Sslatteng #ifdef DEBUGABLE
107514759Sslatteng 	    if (dbg) error(!FATAL, "illegal font %d size %d", fnum, fsize);
107614759Sslatteng #endif
107713275Sslatteng 	    return(-1);
107812587Sslatteng 	}
107912593Sslatteng 		/* Need to verify the existance of that font/size here*/
108012587Sslatteng 	nfontnum = fnum;
108112587Sslatteng 	npsize = fsize;
108212587Sslatteng 	fontwanted++;
108312587Sslatteng 	return (0);
108412587Sslatteng }
108512587Sslatteng 
108612587Sslatteng 
getfont()108712587Sslatteng getfont()
108812587Sslatteng {
108914759Sslatteng 	register int fnum;
109014759Sslatteng 	register int fsize;
109114759Sslatteng 	register int fontd;
109214759Sslatteng 	register int d;
109315282Sslatteng 	register int sizehunt = size;
109412587Sslatteng 	char cbuf[BUFSIZ];
109512587Sslatteng 
109614759Sslatteng 
109712587Sslatteng 	fnum = nfontnum;
109812587Sslatteng 	fsize = npsize;
109914759Sslatteng 			/* try to open font file - if unsuccessful, hunt for */
110014759Sslatteng 			/* a file of same style, different size to substitute */
110114759Sslatteng 	d = -1;	/* direction to look in pstab (smaller first) */
110214759Sslatteng 	do {
110315282Sslatteng 	    sprintf(cbuf, "%s/%s.%d", bitdir, fontname[fnum], fsize);
110414759Sslatteng 	    fontd = open(cbuf, OPENREAD);
110514759Sslatteng 	    if (fontd == -1) {		/* File wasn't found. Try another ps */
110615282Sslatteng 		sizehunt += d;
110715282Sslatteng 		if (sizehunt < 0) {	/* past beginning - look higher */
110814759Sslatteng 		    d = 1;
110915282Sslatteng 		    sizehunt = size + 1;
111014759Sslatteng 		}
111115282Sslatteng 		if (sizehunt > nsizes) {	/* past top - forget it */
111214759Sslatteng 		    d = 0;
111314759Sslatteng 		} else {
111415282Sslatteng 		    fsize = pstab[sizehunt];
111514759Sslatteng 		}
111614759Sslatteng 	    }
111714759Sslatteng 	} while (fontd == -1 && d != 0);
111814759Sslatteng 
111914759Sslatteng 	if (fontd == -1) {		/* completely unsuccessful */
112014759Sslatteng 	    perror(cbuf);
112114759Sslatteng 	    error(!FATAL,"fnum = %d, psize = %d, name = %s",
112215282Sslatteng 		fnum, npsize, fontname[fnum]);
112314759Sslatteng 	    fontwanted = 0;
112414759Sslatteng 	    return (-1);
112512587Sslatteng 	}
112612593Sslatteng 	if (read(fontd, &header, sizeof  (header)) != sizeof (header)
112712593Sslatteng 						|| header.magic != 0436)
112812587Sslatteng 		fprintf(stderr, "%s: Bad font file", cbuf);
112912587Sslatteng 	else {
113012587Sslatteng 		cfont = relfont();
113113275Sslatteng 		if ((bits=nalloc(header.size+DSIZ+1,1))== NULL)
113213275Sslatteng 			if ((bits=allpanic(header.size+DSIZ+1))== NULL) {
113315282Sslatteng 				error(FATAL, "%s: ran out of memory", cbuf);
113413275Sslatteng 			}
113513275Sslatteng 
113612587Sslatteng 			/*
113712587Sslatteng 			 * have allocated one chunk of mem for font, dispatch.
113812587Sslatteng 			 * get the dispatch addr, align to word boundary.
113912587Sslatteng 			 */
114013275Sslatteng 
114113275Sslatteng 		d = (int) bits+header.size;
114213275Sslatteng 		d += 1;
114313275Sslatteng 		d &= ~1;
114413275Sslatteng 		if (read (fontd, d, DSIZ) != DSIZ
114513275Sslatteng 			    || read (fontd, bits, header.size) != header.size)
114613275Sslatteng 			fprintf(stderr, "bad font header");
114713275Sslatteng 		else {
114813275Sslatteng 			close(fontd);
114913275Sslatteng 			cfnum = fontdes[cfont].fnum = fnum;
115013275Sslatteng 			cpsize = fontdes[cfont].psize = fsize;
115113275Sslatteng 			fontdes [cfont].bits = bits;
115213275Sslatteng 			fontdes [cfont].disp = (struct dispatch *) d;
115313275Sslatteng 			dispatch = &fontdes[cfont].disp[0];
115413275Sslatteng 			fontwanted = 0;
115513275Sslatteng 			return (0);
115612587Sslatteng 		}
115712587Sslatteng 	}
115812587Sslatteng 	close(fontd);
115912587Sslatteng 	fontwanted = 0;
116012587Sslatteng 	return(-1);
116112587Sslatteng }
116212587Sslatteng 
116313275Sslatteng /*
116413275Sslatteng  * "release" a font position - find an empty one, if possible
116513275Sslatteng  */
116612587Sslatteng 
relfont()116712587Sslatteng relfont()
116812587Sslatteng {
116913275Sslatteng     register int newfont;
117012587Sslatteng 
117113275Sslatteng     for (newfont = 0; newfont < NFONTS; newfont++)
117215282Sslatteng 	if (fontdes [newfont].fnum == -1)
117313275Sslatteng 	    break;
117415282Sslatteng     if (fontdes [newfont].fnum != -1) {
117513275Sslatteng 	nfree (fontdes [newfont].bits);
117613275Sslatteng #ifdef DEBUGABLE
117713275Sslatteng 	if (dbg) fprintf (stderr, "freeing position %d\n", newfont);
117813275Sslatteng     } else {
117913275Sslatteng 	if (dbg)
118013275Sslatteng 	    fprintf (stderr, "taking, not freeing, position %d\n", newfont);
118113275Sslatteng #endif
118213275Sslatteng     }
118315282Sslatteng     fontdes[newfont].fnum = -1;
118413275Sslatteng     return (newfont);
118512587Sslatteng }
118612587Sslatteng 
allpanic(nbytes)118712593Sslatteng char *allpanic (nbytes)
118812593Sslatteng int nbytes;
118912587Sslatteng {
119012587Sslatteng 	register int i;
119112587Sslatteng 
119212587Sslatteng 	for (i = 0; i <= NFONTS; i++) {
119315282Sslatteng 		if (fontdes[i].fnum != -1) nfree(fontdes[i].bits);
119412587Sslatteng 		fontdes[i].fnum = fontdes[i].psize = -1;
119512587Sslatteng 		cfnum = cpsize = -1;
119612587Sslatteng 	}
119712587Sslatteng 	return(nalloc(nbytes,1));
119812587Sslatteng }
119912587Sslatteng 
120012587Sslatteng int	M[] = { 0xffffffff, 0xfefefefe, 0xfcfcfcfc, 0xf8f8f8f8,
120112587Sslatteng 		0xf0f0f0f0, 0xe0e0e0e0, 0xc0c0c0c0, 0x80808080, 0x0 };
120212587Sslatteng int	N[] = { 0x00000000, 0x01010101, 0x03030303, 0x07070707,
120312587Sslatteng 		0x0f0f0f0f, 0x1f1f1f1f, 0x3f3f3f3f, 0x7f7f7f7f, 0xffffffff };
120412587Sslatteng int	strim[] = { 0xffffffff, 0xffffff00, 0xffff0000, 0xff000000, 0 };
120512587Sslatteng 
outc(code)120612587Sslatteng outc(code)
120713787Sslatteng int code;		/* character to print */
120812587Sslatteng {
120913787Sslatteng     register struct dispatch *dis; /* ptr to character font record */
121013787Sslatteng     register char *addr;	/* addr of font data */
121113787Sslatteng     int llen;			/* length of each font line */
121213787Sslatteng     int nlines;			/* number of font lines */
121313787Sslatteng     register char *scanp;	/* ptr to output buffer */
121413787Sslatteng     int scanp_inc;		/* increment to start of next buffer */
121513787Sslatteng     int offset;			/* bit offset to start of font data */
121614759Sslatteng     register int i;		/* loop counter */
121713787Sslatteng     register int count;		/* font data ptr */
121813787Sslatteng     register unsigned fontdata;	/* font data temporary */
121916196Sslatteng     register int off8;		/* reverse of offset */
122012587Sslatteng 
122113787Sslatteng     if (fontwanted)
122215282Sslatteng 	if (getfont()) return;
122313787Sslatteng     dis = dispatch + code;
122413787Sslatteng     if (dis->nbytes) {
122516214Sslatteng #ifdef DEBUGABLE
122616214Sslatteng 	if (dbg) fprintf(stderr, "char %d at (%d,%d)", code, hpos, vpos);
122716214Sslatteng #endif
122813787Sslatteng 	addr = bits + dis->addr;
122913787Sslatteng 	llen = (dis->left + dis->right + 7) / 8;
123013787Sslatteng 	nlines = dis->up + dis->down;
123114759Sslatteng 	if ((i = vpos + dis->down) > maxv) maxv = i;
123215282Sslatteng 	scanp = buf0p + (vpos - (vorigin + dis->up)) * BYTES_PER_LINE
123314759Sslatteng 			+ (hpos - dis->left) / 8;
123413787Sslatteng 	scanp_inc = BYTES_PER_LINE - llen;
123516196Sslatteng 	offset = (hpos - dis->left) &07;
123616196Sslatteng 	off8 = 8 - offset;
123713787Sslatteng 	for (i = 0; i < nlines; i++) {
123816214Sslatteng 	    if (scanp + (count = llen) > BUFBOTTOM) {
123916214Sslatteng #ifdef DEBUGABLE
124016214Sslatteng 		if (dbg) fprintf(stderr, " scrapped\n");
124116214Sslatteng #endif
124215282Sslatteng 		return;
124316214Sslatteng 	    }
124416214Sslatteng #ifdef DEBUGABLE
124516214Sslatteng 	    if (dbg) fprintf(stderr, "-");
124616214Sslatteng #endif
124714759Sslatteng 	    if (scanp >= BUFTOP) {
124813787Sslatteng 		do {
124913787Sslatteng 		    fontdata = *(unsigned *)addr;
125013787Sslatteng 		    addr += 4;
125113787Sslatteng 		    if (count < 4)
125213787Sslatteng 			fontdata &= ~strim[count];
125316196Sslatteng 		    *(unsigned*)scanp |=(fontdata >> offset) & ~M[off8];
125413787Sslatteng 		    scanp++;
125513787Sslatteng 		    *(unsigned*)scanp |=(fontdata << off8) & ~N[off8];
125613787Sslatteng 		    scanp += 3;
125713787Sslatteng 		    count -= 4;
125813787Sslatteng 		} while (count > 0);
125913787Sslatteng 	    }
126013787Sslatteng 	    scanp += scanp_inc+count;
126113787Sslatteng 	    addr += count;
126212587Sslatteng 	}
126316214Sslatteng #ifdef DEBUGABLE
126416214Sslatteng 	if (dbg) fprintf(stderr, "\n");
126516214Sslatteng #endif
126613787Sslatteng     }
126712587Sslatteng }
126812587Sslatteng 
126912587Sslatteng 
vwrite(buf,usize)127014759Sslatteng vwrite(buf,usize)
127112587Sslatteng char *buf;
127215282Sslatteng int usize;
127312587Sslatteng {
127413275Sslatteng 	register int tsize = 0;
127513275Sslatteng 
127615282Sslatteng 	while (usize) {
127712587Sslatteng 		buf += tsize;
127813787Sslatteng 		tsize = usize > MAXWRIT ? MAXWRIT : usize;
127913275Sslatteng #ifdef DEBUGABLE
128013275Sslatteng 		if (dbg)fprintf(stderr,"buf = %d size = %d\n",buf,tsize);
128116214Sslatteng 	    if (!dbg)
128213275Sslatteng #endif
128313275Sslatteng 		if ((tsize = write(OUTFILE, buf, tsize)) < 0) {
128412587Sslatteng 			perror("dver: write failed");
128512587Sslatteng 			exit(RESTART);
128612587Sslatteng 		}
128713275Sslatteng 		usize -= tsize;
128812587Sslatteng 	}
128912587Sslatteng }
129012587Sslatteng 
vclear(ptr,nbytes)129112593Sslatteng vclear (ptr, nbytes)
129212587Sslatteng char	*ptr;
129315282Sslatteng int nbytes;
129412587Sslatteng {
129512593Sslatteng     register tsize = 0;
129612593Sslatteng 
129713275Sslatteng     while (nbytes){
129812593Sslatteng 	if ((unsigned)(16*1024) < nbytes) {
129912593Sslatteng 	    tsize = 16 * 1024;
130012593Sslatteng 	} else
130112593Sslatteng 	    tsize = nbytes;
130212593Sslatteng 	nbytes -= tsize;
130313275Sslatteng #ifdef DEBUGABLE
130412593Sslatteng 	if (dbg) fprintf(stderr,"clearing ptr = %d size = %d\n",ptr,tsize);
130513275Sslatteng #endif
130612593Sslatteng 	clear(ptr,tsize);
130712593Sslatteng 	ptr += tsize;
130812593Sslatteng     }
130912587Sslatteng }
131012587Sslatteng 
131112587Sslatteng /*ARGSUSED*/
clear(lp,nbytes)131212587Sslatteng clear(lp, nbytes)
131315282Sslatteng char *lp;
131412593Sslatteng int nbytes;
131512587Sslatteng {
1316*24162Sslatteng #ifdef vax
131712587Sslatteng 	asm("movc5 $0,(sp),$0,8(ap),*4(ap)");
1318*24162Sslatteng #else
1319*24162Sslatteng 	register int i = nbytes;
1320*24162Sslatteng 	register char *cp = lp;
1321*24162Sslatteng 
1322*24162Sslatteng 	while(i-- > 0)
1323*24162Sslatteng 		*(cp++) = 0;
1324*24162Sslatteng #endif
132512587Sslatteng }
132612587Sslatteng 
132712587Sslatteng char *
nalloc(i,j)132812587Sslatteng nalloc(i, j)
132912593Sslatteng int i, j;
133012587Sslatteng {
133112587Sslatteng 	register char *cp;
133212587Sslatteng 
133312587Sslatteng 	cp = calloc(i, j);
133413275Sslatteng #ifdef DEBUGABLE
133513275Sslatteng 	if (dbg) fprintf(stderr, "allocated %d bytes at %x\n", i * j, cp);
133613275Sslatteng #endif
133712587Sslatteng 	return(cp);
133812587Sslatteng }
133912587Sslatteng 
nfree(cp)134012587Sslatteng nfree(cp)
134112593Sslatteng char *cp;
134212587Sslatteng {
134313275Sslatteng #ifdef DEBUGABLE
134413275Sslatteng 	if (dbg) fprintf(stderr, "freeing at %x\n", cp);
134513275Sslatteng #endif
134612587Sslatteng 	free(cp);
134712587Sslatteng }
134812593Sslatteng 
134912593Sslatteng 
135013787Sslatteng /*
135114759Sslatteng  * Plot a dot at (x, y).  Points should be in the range 0 <= x < RASTER_LENGTH,
135214759Sslatteng  * vorigin <= y < vorigin + NLINES.  If the point will not fit on the buffer,
135314759Sslatteng  * it is left out.  Things outside the x boundary are wrapped around the end.
135413787Sslatteng  */
point(x,y)135513787Sslatteng point(x, y)
135616196Sslatteng register int x;
135716196Sslatteng register int y;
135813787Sslatteng {
135914759Sslatteng     register char *ptr = buf0p + (y - vorigin) * BYTES_PER_LINE + (x >> 3);
136014759Sslatteng 
136116196Sslatteng     if (ptr > BUFBOTTOM || ptr < BUFTOP)	/* ignore if it's off buffer */
136216196Sslatteng 	return;
136316196Sslatteng 
136416196Sslatteng     *ptr |= 1 << (7 - (x & 07));
136516196Sslatteng     if (y > maxv) maxv = y;
136613787Sslatteng }
136716538Sslatteng 
136816538Sslatteng 
136916538Sslatteng #define MAXX	0x7fff		/* largest positive int */
137016538Sslatteng #define MINX	0x8000		/* smallest negative int */
137116538Sslatteng #define MAXVECT	75
137216538Sslatteng 
137316538Sslatteng typedef struct poly {
137416538Sslatteng 	struct poly *next;	/* doublely-linked lists of vectors */
137516538Sslatteng 	struct poly *prev;
137616538Sslatteng 	int param;	/* bressenham line algorithm parameter */
137716538Sslatteng 	short dy;	/* delta-y for calculating line */
137816538Sslatteng 	short dx;	/* delta-x for calculating line */
137916538Sslatteng 	short currx;	/* current x in this vector */
138016538Sslatteng 	short endy;	/* where vector ends */
138116538Sslatteng } polyvector;
138216538Sslatteng 
138316538Sslatteng int	rp_len;		/* length of the string in "buf" */
138416538Sslatteng char *	rp_ptr;		/* "walking" pointer into buf */
138516538Sslatteng 
138616538Sslatteng 
138716538Sslatteng /*----------------------------------------------------------------------------*
138816538Sslatteng  | Routine:	read_poly (input_buffer, file_pointer)
138916538Sslatteng  |
139016538Sslatteng  | Results:	gets an integer from buffer pointed to by rp_ptr,
139116538Sslatteng  |		and advances in the file.  If there is nothing left,
139216538Sslatteng  |		more can be read in from the file.  rp_ptr and rp_len
139316538Sslatteng  |		are set in "polygon".
139416538Sslatteng  *----------------------------------------------------------------------------*/
139516538Sslatteng 
read_poly(buf,fp)139616538Sslatteng read_poly(buf, fp)
139716538Sslatteng char *buf;
139816538Sslatteng FILE *fp;
139916538Sslatteng {
140016538Sslatteng 	register int i;
140116538Sslatteng 
140216538Sslatteng 
140316538Sslatteng 	if (*rp_ptr == '\n')
140416538Sslatteng 	    return 0;
140516538Sslatteng 
140616538Sslatteng 	while (isspace(*++rp_ptr));	/* skip any leading spaces */
140716538Sslatteng 	i = atoi(rp_ptr);		/* convert motion to curve points */
140816538Sslatteng 	while (isdigit(*++rp_ptr));	/* skip number*/
140916538Sslatteng 					/* if the amount we read wasn't the */
141016538Sslatteng 					/*    whole thing, read some more in */
141116538Sslatteng 	if (rp_len - (rp_ptr - buf) < 10 && *(buf + rp_len - 1) != '\n') {
141216538Sslatteng 	    register char *cop = buf;
141316538Sslatteng 
141416538Sslatteng 	    while (*(cop++) = *(rp_ptr++));	/* what's left to beginning */
141516538Sslatteng 	    if (fgets ((cop - 1), rp_len - (cop - buf), fp) == NULL)
141616538Sslatteng 		error(FATAL, "unexpected end of input");
141716538Sslatteng 	    rp_ptr = buf;
141816538Sslatteng 	}
141916538Sslatteng 
142016538Sslatteng 	return i;
142116538Sslatteng }
142216538Sslatteng 
142316538Sslatteng 
142416538Sslatteng /*----------------------------------------------------------------------------*
142516538Sslatteng  | Routine:	polygon ( string, file )
142616538Sslatteng  |
142716538Sslatteng  | Results:	draws a polygon specified by the parameters encoded into the
142816538Sslatteng  |		string (and from the file, if necessary).  The parameters are
142916538Sslatteng  |		broken up into separate vectors.  The vectors are encoded as
143016538Sslatteng  |		follows:  (p dx dy curx endy); endy is the bottom of vector,
143116538Sslatteng  |		curx is where x starts;  dx, dy are the deltas for the line;
143216538Sslatteng  |		if dy is negative, p is the Bresenham line algorithm parameter,
143316538Sslatteng  |		otherwise p is the starting y.  All the active vectors must be
143416538Sslatteng  |		put first.
143516538Sslatteng  |
143616538Sslatteng  |		The polygon is filled with a stipple pattern from stip_disp
143716538Sslatteng  |		and stip_bits, which point to the stipple font.  The pattern
143816538Sslatteng  |		is defined by "stip" and "stipmem".
143916538Sslatteng  |
144016538Sslatteng  |		The scan-line algorithm implemented scans from top to
144116538Sslatteng  |		bottom (low y to high y).  It also scans, within a line,
144216538Sslatteng  |		from left to right (low x to high x).
144316538Sslatteng  |
144416538Sslatteng  | Bugs:	stipple pattern MUST be a power of two bytes "wide" and
144516538Sslatteng  |		square.  The square restriction comes from the fact that
144616538Sslatteng  |		the varian and versatec are respectively rotated.
144716538Sslatteng  *----------------------------------------------------------------------------*/
144816538Sslatteng 
polygon(buf,fp)144916538Sslatteng polygon(buf, fp)
145016538Sslatteng char *buf;
145116538Sslatteng FILE *fp;
145216538Sslatteng {
145316538Sslatteng     int nexty;			/* at what y value the next vector starts */
145416538Sslatteng     int maxy, miny;		/* finds bounds of polygon */
145516538Sslatteng     polyvector *activehead;		/* doing fill, is active edge list */
145616538Sslatteng     polyvector *waitinghead;		/* edges waiting to be active */
145716538Sslatteng     register polyvector *vectptr;	/* random vector */
145816538Sslatteng     register int i;			/* random register */
145916538Sslatteng 
146016538Sslatteng     char *topstipple;		/* points to beginning of stipple glyph */
146116538Sslatteng     char *leftstipple;		/* points to beginning of line of stipple */
146216538Sslatteng     char *leftpage;		/* points to the edge of a raster line */
146316538Sslatteng     int bytewidth;		/* glyph width in bytes */
146416538Sslatteng     int mask;			/* mask to pick off pixel index into stipple */
146516538Sslatteng     int bytemask;		/* mask to pick off byte index into stipple */
146616538Sslatteng 
146716538Sslatteng 
146816538Sslatteng     rp_len = strlen(buf);	/* length of the string in "buf" */
146916538Sslatteng     rp_ptr = buf;		/* "walking" pointer into buf */
147016538Sslatteng 						/* if no stipple, don't fill */
147116538Sslatteng     if (stip_disp == (struct dispatch *) NULL || stip_bits == (char *) NULL)
147216538Sslatteng 	goto leavepoly;
147316538Sslatteng 
147416538Sslatteng     stip_disp += stipmem;			/* set up parameters for */
147516538Sslatteng     if (!stip_disp->nbytes) {			/* tiling with the stipple */
147616538Sslatteng #ifdef DEBUGABLE
147716538Sslatteng 	error(!FATAL, "member not found: member %d, stipple %d", stipmem, stip);
147816538Sslatteng #endif
147916538Sslatteng 	goto leavepoly;
148016538Sslatteng     }
148116538Sslatteng     topstipple = stip_bits + stip_disp->addr;
148216538Sslatteng     bytewidth = stip_disp->up + stip_disp->down;
148316538Sslatteng     for (i = 1 << 30; i && i != bytewidth; i = i >> 1)
148416538Sslatteng 	;
148516538Sslatteng     if (i==0 || bytewidth<8 || bytewidth != stip_disp->right+stip_disp->left) {
148616538Sslatteng 	error(!FATAL, "invalid stipple: number %d, member %d", stip, stipmem);
148716538Sslatteng 	goto leavepoly;
148816538Sslatteng     }
148916538Sslatteng     mask = bytewidth - 1;
149016538Sslatteng     bytewidth = bytewidth >> 3;
149116538Sslatteng     bytemask = bytewidth - 1;
149216538Sslatteng 
149316538Sslatteng     if ((i = read_poly(buf, fp)) < 2)	/* # of vects command holds */
149416538Sslatteng 	goto leavepoly;
149516538Sslatteng     miny = read_poly(buf, fp);		/* get limits from command */
149616538Sslatteng     maxy = read_poly(buf, fp);
149716538Sslatteng 
149816538Sslatteng     leftstipple = topstipple + (miny & mask) * bytewidth;
149916538Sslatteng     leftpage = buf0p + (miny - vorigin) * BYTES_PER_LINE;
150016538Sslatteng 
150116538Sslatteng 				/* allocate space for raster-fill algorithm*/
150216538Sslatteng     vectptr = (polyvector *) nalloc(sizeof(polyvector), i + 4);
150316538Sslatteng     if (vectptr == (polyvector *) NULL) {
150416538Sslatteng 	error(!FATAL, "unable to allocate space for polygon");
150516538Sslatteng 	return;
150616538Sslatteng     }
150716538Sslatteng 
150816538Sslatteng     waitinghead = vectptr;
150916538Sslatteng     vectptr->param = miny - 1;		/* put dummy entry at start */
151016538Sslatteng     (vectptr++)->prev = NULL;
151116538Sslatteng     waitinghead->next = vectptr;
151216538Sslatteng     vectptr->prev = waitinghead;
151316538Sslatteng 
151416538Sslatteng     while (i--) {
151516538Sslatteng 	vectptr->next = vectptr + 1;
151616538Sslatteng 	vectptr->param = read_poly(buf, fp);
151716538Sslatteng 	vectptr->dx = read_poly(buf,fp);
151816538Sslatteng 	vectptr->dy = read_poly(buf,fp);
151916538Sslatteng 	vectptr->currx = read_poly(buf,fp);
152016538Sslatteng 	(vectptr++)->endy = read_poly(buf,fp);
152116538Sslatteng 	vectptr->prev = vectptr - 1;
152216538Sslatteng     }
152316538Sslatteng 
152416538Sslatteng     vectptr->param = maxy + 1;		/* dummy entry at end, too */
152516538Sslatteng     vectptr->currx = vectptr->dx = vectptr->dy = 0;
152616538Sslatteng     vectptr->next = NULL;
152716538Sslatteng 
152816538Sslatteng     activehead = ++vectptr;		/* two dummy entries for active list */
152916538Sslatteng     vectptr->currx = MINX;		/* head */
153016538Sslatteng     vectptr->endy = maxy + 1;
153116538Sslatteng     vectptr->param = vectptr->dx = vectptr->dy = 0;
153216538Sslatteng     activehead->next = ++vectptr;
153316538Sslatteng     activehead->prev = vectptr;
153416538Sslatteng     vectptr->prev = activehead;		/* tail */
153516538Sslatteng     vectptr->next = activehead;
153616538Sslatteng     vectptr->currx = MAXX;
153716538Sslatteng     vectptr->endy = maxy + 1;
153816538Sslatteng     vectptr->param = vectptr->dx = vectptr->dy = 0;
153916538Sslatteng 
154016538Sslatteng     vectptr = waitinghead->next;	/* if anything is active already */
154116538Sslatteng     if (vectptr->dy < 0) {		/*   put them into the active list */
154216538Sslatteng 	register polyvector *p;		/* random useful register pointer */
154316538Sslatteng 
154416538Sslatteng 	p = vectptr;
154516538Sslatteng 	do {
154616538Sslatteng 	    vectptr->dy = -vectptr->dy;
154716538Sslatteng 	} while ((++vectptr)->dy < 0);
154816538Sslatteng 
154916538Sslatteng 	waitinghead->next = vectptr;	/* first, remove list from waiting */
155016538Sslatteng 	(vectptr--)->prev = waitinghead;
155116538Sslatteng 
155216538Sslatteng 	activehead->next->prev = vectptr;	/* link in end */
155316538Sslatteng 	vectptr->next = activehead->next;
155416538Sslatteng 	activehead->next = p;			/* link in start */
155516538Sslatteng 	p->prev = activehead;
155616538Sslatteng     }
155716538Sslatteng 
155816538Sslatteng 			/* main loop -- gets vectors off the waiting list, */
155916538Sslatteng 			/* then displays spans while updating the vectors in */
156016538Sslatteng 			/* the active list */
156116538Sslatteng     while (miny <= maxy) {
156216538Sslatteng 	i = maxy + 1;		/* this is the NEXT time to get a new vector */
156316538Sslatteng 	for (vectptr = waitinghead->next; vectptr != NULL; ) {
156416538Sslatteng 	    if (miny == vectptr->param) {
156516538Sslatteng 				/* the entry in waiting list (vectptr) is */
156616538Sslatteng 				/*   ready to go into active list.  Need to */
156716538Sslatteng 				/*   convert some vector stuff and sort the */
156816538Sslatteng 				/*   entry into the list. */
156916538Sslatteng 		register polyvector *p;	/* random vector pointers */
157016538Sslatteng 		register polyvector *v;
157116538Sslatteng 
157216538Sslatteng 							/* convert this */
157316538Sslatteng 		if (vectptr->dx < 0)			/* entry to active */
157416538Sslatteng 		    vectptr->param = -((vectptr->dx >> 1) + (vectptr->dy >> 1));
157516538Sslatteng 		else
157616538Sslatteng 		    vectptr->param = (vectptr->dx >> 1) - (vectptr->dy >> 1);
157716538Sslatteng 
157816538Sslatteng 		p = vectptr;			/* remove from the */
157916538Sslatteng 		vectptr = vectptr->next;	/* waiting list */
158016538Sslatteng 		vectptr->prev = p->prev;
158116538Sslatteng 		p->prev->next = vectptr;
158216538Sslatteng 						/* find where it goes */
158316538Sslatteng 						/* in the active list */
158416538Sslatteng 						/* (sorted smallest first) */
158516538Sslatteng 		for (v = activehead->next; v->currx < p->currx; v = v->next)
158616538Sslatteng 		    ;
158716538Sslatteng 		p->next = v;		/* insert into active list */
158816538Sslatteng 		p->prev = v->prev;	/* before the one it stopped on */
158916538Sslatteng 		v->prev = p;
159016538Sslatteng 		p->prev->next = p;
159116538Sslatteng 	    } else {
159216538Sslatteng 		if (i > vectptr->param) {
159316538Sslatteng 		    i = vectptr->param;
159416538Sslatteng 		}
159516538Sslatteng 		vectptr = vectptr->next;
159616538Sslatteng 	    }
159716538Sslatteng 	}
159816538Sslatteng 	nexty = i;
159916538Sslatteng 
160016538Sslatteng 					/* print the polygon while there */
160116538Sslatteng 					/* are no more vectors to add */
160216538Sslatteng 	while (miny < nexty) {
160316538Sslatteng 					/* remove any finished vectors */
160416538Sslatteng 	    vectptr = activehead->next;
160516538Sslatteng 	    do {
160616538Sslatteng 		if (vectptr->endy <= miny) {
160716538Sslatteng 		    vectptr->prev->next = vectptr->next;
160816538Sslatteng 		    vectptr->next->prev = vectptr->prev;
160916538Sslatteng 		}
161016538Sslatteng 	    } while ((vectptr = vectptr->next) != activehead);
161116538Sslatteng 
161216538Sslatteng 					/* draw the span */
161316538Sslatteng 	    vectptr = activehead->next;
161416538Sslatteng 	    while (vectptr->next != activehead) {
161516538Sslatteng 		register int start;	/* get the beginning */
161616538Sslatteng 		register int length;	/*   and the end of span */
161716538Sslatteng 		register char *glyph;
161816538Sslatteng 		register char *raster;
161916538Sslatteng 
162016538Sslatteng 		start = vectptr->currx;
162116538Sslatteng 		vectptr = vectptr->next;
162216538Sslatteng 		length = vectptr->currx + 1;
162316538Sslatteng 		vectptr = vectptr->next;
162416538Sslatteng 
162516538Sslatteng 					/* bound the polygon to the page */
162616538Sslatteng 		if (start >= RASTER_LENGTH)
162716538Sslatteng 		    break;
162816538Sslatteng 		if (start < 0) start = 0;
162916538Sslatteng 		if (length > RASTER_LENGTH) length = RASTER_LENGTH;
163016538Sslatteng 		length -= start;		/* length is in pixels */
163116538Sslatteng 
163216538Sslatteng 		i = start & 7;
163316538Sslatteng 		start = start >> 3;		/* start is in bytes */
163416538Sslatteng 		raster = leftpage + start;
163516538Sslatteng 		glyph = leftstipple + (start & bytemask);
163616538Sslatteng 
163716538Sslatteng 		if (i) {			/* do any piece of byte */
163816538Sslatteng 		    register char data;		/* that hangs on the front */
163916538Sslatteng 
164016538Sslatteng 		    data = (*(glyph++)) & (0x7f >> --i);
164116538Sslatteng 		    length -= 7 - i;
164216538Sslatteng 		    if (length < 0) {		/* less than one byte wide? */
164316538Sslatteng 			data &= 0xff << -length;
164416538Sslatteng 			length = 0;	/* force clean stoppage */
164516538Sslatteng 		    }
164616538Sslatteng 		    *(raster++) |= data;
164716538Sslatteng 					/* update glyph ptr after first byte */
164816538Sslatteng 		    if (!(++start & bytemask))
164916538Sslatteng 			glyph = leftstipple;
165016538Sslatteng 		}
165116538Sslatteng 						/* fill the line of raster */
165216538Sslatteng 		while ((length -= 8) >= 0) {
165316538Sslatteng 		    *(raster++) |= *(glyph++);
165416538Sslatteng 		    if (!(++start & bytemask))
165516538Sslatteng 			glyph = leftstipple;
165616538Sslatteng 		}
165716538Sslatteng 		if (length & 7) {	/* add any part hanging off the end */
165816538Sslatteng 		    *raster |= (*glyph) & (0xff << -length);
165916538Sslatteng 		}
166016538Sslatteng 	    }
166116538Sslatteng 
166216538Sslatteng #ifdef DEBUGABLE
166316538Sslatteng 	    if (dbg) {
166416538Sslatteng 		vectptr = activehead;
166516538Sslatteng 		do {
166616538Sslatteng 		    fprintf (stderr, "%d ", vectptr->currx);
166716538Sslatteng 		    vectptr = vectptr->next;
166816538Sslatteng 		} while (vectptr != activehead);
166916538Sslatteng 	    }
167016538Sslatteng #endif
167116538Sslatteng 					/* update the vectors */
167216538Sslatteng 	    vectptr = activehead->next;
167316538Sslatteng 	    do {
167416538Sslatteng 		if (vectptr->dx > 0) {
167516538Sslatteng 		    while (vectptr->param >= 0) {
167616538Sslatteng 			vectptr->param -= vectptr->dy;
167716538Sslatteng 			vectptr->currx++;
167816538Sslatteng 		    }
167916538Sslatteng 		    vectptr->param += vectptr->dx;
168016538Sslatteng 		} else if (vectptr->dx < 0) {
168116538Sslatteng 		    while (vectptr->param >= 0) {
168216538Sslatteng 			vectptr->param -= vectptr->dy;
168316538Sslatteng 			vectptr->currx--;
168416538Sslatteng 		    }
168516538Sslatteng 		    vectptr->param -= vectptr->dx;
168616538Sslatteng 		}
168716538Sslatteng 					/* must sort the vectors if updates */
168816538Sslatteng 					/* caused them to cross */
168916538Sslatteng 					/* also move to next vector here */
169016538Sslatteng 		if (vectptr->currx < vectptr->prev->currx) {
169116538Sslatteng 		    register polyvector *v;		/* vector to move */
169216538Sslatteng 		    register polyvector *p;	/* vector to put it after */
169316538Sslatteng 
169416538Sslatteng 		    v = vectptr;
169516538Sslatteng 		    p = v->prev;
169616538Sslatteng 		    while (v->currx < p->currx)	/* find the */
169716538Sslatteng 			p = p->prev;		/* right vector */
169816538Sslatteng 
169916538Sslatteng 		    vectptr = vectptr->next;	/* remove from spot */
170016538Sslatteng 		    vectptr->prev = v->prev;
170116538Sslatteng 		    v->prev->next = vectptr;
170216538Sslatteng 
170316538Sslatteng 		    v->prev = p;		/* put in new spot */
170416538Sslatteng 		    v->next = p->next;
170516538Sslatteng 		    p->next = v;
170616538Sslatteng 		    v->next->prev = v;
170716538Sslatteng 		} else {
170816538Sslatteng 		    vectptr = vectptr->next;
170916538Sslatteng 		}
171016538Sslatteng 	    } while (vectptr != activehead);
171116538Sslatteng #ifdef DEBUGABLE
171216538Sslatteng 	    if (dbg) fprintf(stderr, "line done\n");
171316538Sslatteng #endif
171416538Sslatteng 
171516538Sslatteng 	    if (++miny & mask) {
171616538Sslatteng 		leftstipple += bytewidth;
171716538Sslatteng 	    } else {
171816538Sslatteng 		leftstipple = topstipple;
171916538Sslatteng 	    }
172016538Sslatteng 	    leftpage += BYTES_PER_LINE;
172116538Sslatteng 	} /* while (miny < nexty) */
172216538Sslatteng     } /* while (miny <= maxy) */
172316538Sslatteng 
172416538Sslatteng     nfree(waitinghead);		/* dump the space allocated for polygon */
172516538Sslatteng 
172616538Sslatteng leavepoly:
172716538Sslatteng     while (*rp_ptr != '\n')
172816538Sslatteng 	i = read_poly(buf, fp);
172916538Sslatteng }  /* polygon function */
1730