1*24165Sslatteng /*	dvar.c	1.15	85/08/05
213858Sslatteng  *
313858Sslatteng  * Varian driver for the new troff
413858Sslatteng  *
513858Sslatteng  * Authors:	BWK(BELL)
613858Sslatteng  *		VCAT(berkley)
713858Sslatteng  *		Richard L. Hyde, Perdue University
814582Sslatteng  *		and David Slattengren, U.C. Berkeley
913858Sslatteng  */
1013858Sslatteng 
1113858Sslatteng 
1213858Sslatteng /*******************************************************************************
1313858Sslatteng 
1413858Sslatteng     output language from troff:
1513858Sslatteng     all numbers are character strings
1613858Sslatteng 
1713858Sslatteng #..\n	comment
1813858Sslatteng sn	size in points
1913858Sslatteng fn	font as number from 1 to n
2016539Sslatteng in	stipple `font' as number from 1 to n
2113858Sslatteng cx	ascii character x
2213858Sslatteng Cxyz	funny char \(xyz. terminated by white space
2313858Sslatteng Hn	go to absolute horizontal position n
2413858Sslatteng Vn	go to absolute vertical position n (down is positive)
2513858Sslatteng hn	go n units horizontally (relative)
2613858Sslatteng vn	ditto vertically
2713858Sslatteng nnc	move right nn, then print c (exactly 2 digits!)
2813858Sslatteng 		(this wart is an optimization that shrinks output file size
2913858Sslatteng 		 about 35% and run-time about 15% while preserving ascii-ness)
3013858Sslatteng p	new page begins -- set v to 0
3113858Sslatteng nb a	end of line (information only -- no action needed)
3213858Sslatteng 	b = space before line, a = after
3313858Sslatteng w	paddable word space -- no action needed
3413858Sslatteng 
3513858Sslatteng Dt ..\n	draw operation 't':
3616539Sslatteng 	Dt d		set line thickness to d
3716539Sslatteng 	Ds d		set line style (mask) to d
3813858Sslatteng 	Dl x y		line from here by x,y
3913858Sslatteng 	Dc d		circle of diameter d with left side here
4013858Sslatteng 	De x y		ellipse of axes x,y with left side here
4113858Sslatteng 	Da x y r	arc counter-clockwise by x,y of radius r
4213858Sslatteng 	D~ x y x y ...	B-spline curve by x,y then x,y ...
4316539Sslatteng 	Dg x y x y ...	gremlin spline curve by x,y then x,y ...
4416539Sslatteng 	Dp s x y ...	polygon by x,y then ... filled with stipple s
4513858Sslatteng 
4613858Sslatteng x ..\n	device control functions:
4713858Sslatteng      x i	init
4813858Sslatteng      x T s	name of device is s
4913858Sslatteng      x r n h v	resolution is n/inch h = min horizontal motion, v = min vert
5013858Sslatteng      x p	pause (can restart)
5113858Sslatteng      x s	stop -- done for ever
5213858Sslatteng      x t	generate trailer
5313858Sslatteng      x f n s	font position n contains font s
5413858Sslatteng      x H n	set character height to n
5513858Sslatteng      x S n	set slant to N
5613858Sslatteng 
5713858Sslatteng 	Subcommands like "i" are often spelled out like "init".
5813858Sslatteng 
5913858Sslatteng *******************************************************************************/
6013858Sslatteng 
6113858Sslatteng 
6213858Sslatteng #include <stdio.h>
6313858Sslatteng #include <ctype.h>
6413858Sslatteng #include <sys/vcmd.h>
6513858Sslatteng #include "dev.h"
6613858Sslatteng 
6713858Sslatteng 
6815176Sslatteng /* #define DEBUGABLE		/* No, not debugable... */
6915176Sslatteng #define DRIVER  		/* Yes, we're driving directly */
7015176Sslatteng /* #define FULLPAGE		/* No, don't output full pages */
7116539Sslatteng #define	NFONTS	65		/* total number of fonts useable */
7213858Sslatteng #define	MAXSTATE 6		/* number of environments rememberable */
7313858Sslatteng #define OPENREAD 0		/* mode for openning files */
7413858Sslatteng #define RESTART	1		/* upon exit, return either RESTART */
7513858Sslatteng #define ABORT	2		/*     or ABORT */
7613858Sslatteng #define	FATAL	1		/* type of error */
7713858Sslatteng #define	BMASK	0377		/* byte grabber */
7815734Sslatteng #ifndef FONTDIR
7914582Sslatteng #define FONTDIR	"/usr/lib/font"	/* default place to find font descriptions */
8015734Sslatteng #endif
8119066Sslatteng #ifndef BITDIR
8214582Sslatteng #define BITDIR "/usr/lib/vfont" /* default place to look for font rasters */
8319066Sslatteng #endif
8413858Sslatteng #define MAXWRIT 4096		/* max characters allowed to write at once */
8513858Sslatteng 
8614284Sslatteng #define  hmot(n)	hgoto(hpos + n)
8713858Sslatteng #define  vmot(n)	vgoto(vpos + n)
8813858Sslatteng 
8913858Sslatteng 
90*24165Sslatteng char	SccsId[]= "dvar.c	1.15	85/08/05";
9113858Sslatteng 
9213858Sslatteng int	output	= 0;	/* do we do output at all? */
9313858Sslatteng int	nolist	= 0;	/* output page list if > 0 */
9413858Sslatteng int	olist[20];	/* pairs of page numbers */
9513858Sslatteng int	spage	= 9999;	/* stop every spage pages */
9613858Sslatteng int	scount	= 0;
9713858Sslatteng struct	dev	dev;
9813858Sslatteng struct	font	*fontbase[NFONTS+1];
9914582Sslatteng short *	pstab;		/* point size table pointer */
10013858Sslatteng int	nsizes;		/* number of sizes device is capable of printing */
10113858Sslatteng int	nfonts;		/* number of fonts device is capable of printing */
10216539Sslatteng int	nstips;		/* number of stipple fonts device can print */
10313858Sslatteng int	nchtab;
10414582Sslatteng char *	chname;
10514582Sslatteng short *	chtab;
10614582Sslatteng char *	fitab[NFONTS+1];	/* font inclusion table - maps ascii to ch # */
10714582Sslatteng char *	widtab[NFONTS+1];	/* width table for each font */
10814582Sslatteng char *	codetab[NFONTS+1];	/* device codes */
10914582Sslatteng char *	fontdir = FONTDIR;	/* place to find devxxx directories */
11014582Sslatteng char *	bitdir = BITDIR;	/* place to find raster fonts and fontmap */
11115176Sslatteng char *	fontname[NFONTS+1];	/* table of what font is on what position */
11213858Sslatteng struct {			/* table of what font */
11314582Sslatteng 	char fname[3];		/*   name maps to what */
11414582Sslatteng 	char *ffile;		/*   filename in bitdirectory */
11514582Sslatteng } fontmap[NFONTS+1];
11613858Sslatteng 
11714582Sslatteng 
11813858Sslatteng #ifdef DEBUGABLE
11913858Sslatteng int	dbg	= 0;
12013858Sslatteng #endif
12114582Sslatteng int	size	= -1;	/* current point size (internal pstable index) */
12213858Sslatteng int	font	= -1;	/* current font - not using any to start with */
12316539Sslatteng int	stip	= -1;	/* current stipple font - not using any to start with */
12416539Sslatteng int	stipmem	= 0;	/* current member to use from stipple font */
12513858Sslatteng int	hpos;		/* horizontal position we are to be at next; left = 0 */
12613858Sslatteng int	vpos;		/* current vertical position (down positive) */
12714582Sslatteng extern	linethickness;	/* thickness (in pixels) of any drawn object */
12814284Sslatteng extern	linmod;		/* line style (a bit mask - dotted, etc.) of objects */
12913858Sslatteng int	lastw;		/* width of last character printed */
13013858Sslatteng 
13113858Sslatteng 
13213858Sslatteng #define DISPATCHSIZE	256		/* must be a power of two */
13313858Sslatteng #define CHARMASK	(DISPATCHSIZE-1)
13413858Sslatteng #define DSIZ		((sizeof *dispatch)*DISPATCHSIZE)
13513858Sslatteng #define OUTFILE 	fileno (stdout)
13614582Sslatteng #define	RES		200		/* resolution of the device (dots/in) */
13713858Sslatteng 
13813890Sslatteng #define RASTER_LENGTH	2112			/* device line length */
13913858Sslatteng #define BYTES_PER_LINE	(RASTER_LENGTH/8)
14015176Sslatteng #ifndef FULLPAGE
14115176Sslatteng #	define NLINES	1600			/* page width, 8 inches */
14215176Sslatteng #endif
14315176Sslatteng #ifdef FULLPAGE
14415176Sslatteng #	define NLINES	1700			/* page width, 8.5 inches */
14515176Sslatteng #endif
14613858Sslatteng #define BUFFER_SIZE	(NLINES*BYTES_PER_LINE)	/* number of chars in picture */
14713858Sslatteng 
14813858Sslatteng 
14913858Sslatteng int	pltmode[] = { VPLOT };
15013858Sslatteng int	prtmode[] = { VPRINT };
15115283Sslatteng char	buffer1[BUFFER_SIZE];	/* Big line buffers  */
15215283Sslatteng char	buffer2[BUFFER_SIZE];
15315283Sslatteng char *	fill = &buffer1[0];	/* Zero origin in filling buffer */
15415283Sslatteng char *	empty = &buffer2[0];	/* Zero origin in emptying buffer */
15515283Sslatteng char *	elevel = &buffer2[0];	/* current position in emptying buffer */
15615283Sslatteng int	emptypos = NLINES;	/* amount of emptying done (initially "done") */
15713858Sslatteng 
15815283Sslatteng 
15914582Sslatteng char *	calloc();
16014582Sslatteng char *	nalloc();
16114582Sslatteng char *	allpanic();
16214823Sslatteng char *	operand();
16313858Sslatteng 
16413858Sslatteng struct header {
16513858Sslatteng 	short	magic;
16613858Sslatteng 	unsigned short	size;
16713858Sslatteng 	short	maxx;
16813858Sslatteng 	short	maxy;
16913858Sslatteng 	short	xtnd;
17013858Sslatteng } header;
17113858Sslatteng 
17213858Sslatteng struct	dispatch{
17313858Sslatteng 	unsigned short	addr;
17413858Sslatteng 	short	nbytes;
17513858Sslatteng 	char	up;
17613858Sslatteng 	char	down;
17713858Sslatteng 	char	left;
17813858Sslatteng 	char	right;
17913858Sslatteng 	short	width;
18013858Sslatteng };
18113858Sslatteng 
18213858Sslatteng struct	fontdes {
18315283Sslatteng 	int	fnum;		/* if == -1, then this position is empty */
18413858Sslatteng 	int	psize;
18513858Sslatteng 	struct	dispatch *disp;
18613858Sslatteng 	char	*bits;
18715283Sslatteng } fontdes[NFONTS+1];		/* initialized at program start */
18813858Sslatteng 
18913858Sslatteng struct dispatch *dispatch;
19016539Sslatteng struct dispatch *stip_disp;
19113858Sslatteng int	cfnum = -1;
19213858Sslatteng int	cpsize = 10;
19313858Sslatteng int	cfont = 1;
19413858Sslatteng char	*bits;
19516539Sslatteng char	*stip_bits;
19616539Sslatteng int	bordered = 1;		/* flag:  "do polygons get bordered?" */
19713858Sslatteng int	fontwanted = 1;		/* flag:  "has a new font been requested?" */
19813858Sslatteng int	nfontnum = -1;
19913858Sslatteng int	npsize = 10;
20013858Sslatteng 
20113858Sslatteng 
20213858Sslatteng 
main(argc,argv)20313858Sslatteng main(argc, argv)
20413858Sslatteng char *argv[];
20513858Sslatteng {
20615283Sslatteng 	register FILE *fp;
20715283Sslatteng 	register int i;
20813858Sslatteng 
20915283Sslatteng 	for (i = 0; i <= NFONTS; fontdes[i++].fnum = -1);
21014823Sslatteng 	while (--argc > 0 && **++argv == '-') {
21114823Sslatteng 		switch ((*argv)[1]) {
21214582Sslatteng 		case 'F':
21315176Sslatteng 			bitdir = operand(&argc, &argv);
21414582Sslatteng 			break;
21513858Sslatteng 		case 'f':
21615176Sslatteng 			fontdir = operand(&argc, &argv);
21713858Sslatteng 			break;
21813858Sslatteng 		case 'o':
21914823Sslatteng 			outlist(operand(&argc, &argv));
22013858Sslatteng 			break;
22113858Sslatteng #ifdef DEBUGABLE
22213858Sslatteng 		case 'd':
22314823Sslatteng 			dbg = atoi(operand(&argc, &argv));
22413858Sslatteng 			if (dbg == 0) dbg = 1;
22513858Sslatteng 			break;
22613858Sslatteng #endif
22713858Sslatteng 		case 's':
22814823Sslatteng 			spage = atoi(operand(&argc, &argv));
22913858Sslatteng 			if (spage <= 0)
23013858Sslatteng 				spage = 9999;
23113858Sslatteng 			break;
23213858Sslatteng 		}
23313858Sslatteng 	}
23413858Sslatteng 
23515176Sslatteng #ifdef DRIVER
23613858Sslatteng 	ioctl(OUTFILE, VSETSTATE, pltmode);
23715176Sslatteng #endif
23813858Sslatteng 
23914823Sslatteng 	if (argc < 1)
24013858Sslatteng 		conv(stdin);
24113858Sslatteng 	else
24214823Sslatteng 		while (argc--) {
24314823Sslatteng 			if (strcmp(*argv, "-") == 0)
24413858Sslatteng 				fp = stdin;
24513858Sslatteng 			else if ((fp = fopen(*argv, "r")) == NULL)
24613858Sslatteng 				error(FATAL, "can't open %s", *argv);
24713858Sslatteng 			conv(fp);
24813858Sslatteng 			fclose(fp);
24914823Sslatteng 			argv++;
25013858Sslatteng 		}
25113858Sslatteng 	exit(0);
25213858Sslatteng }
25313858Sslatteng 
25414823Sslatteng 
25514823Sslatteng /*----------------------------------------------------------------------------*
25614823Sslatteng  | Routine:	char  * operand (& argc,  & argv)
25714823Sslatteng  |
25814823Sslatteng  | Results:	returns address of the operand given with a command-line
25914823Sslatteng  |		option.  It uses either "-Xoperand" or "-X operand", whichever
26014823Sslatteng  |		is present.  The program is terminated if no option is present.
26114823Sslatteng  |
26214823Sslatteng  | Side Efct:	argc and argv are updated as necessary.
26314823Sslatteng  *----------------------------------------------------------------------------*/
26414823Sslatteng 
operand(argcp,argvp)26514823Sslatteng char *operand(argcp, argvp)
26614823Sslatteng int * argcp;
26714823Sslatteng char ***argvp;
26814823Sslatteng {
26914823Sslatteng 	if ((**argvp)[2]) return(**argvp + 2); /* operand immediately follows */
27014823Sslatteng 	if ((--*argcp) <= 0)			/* no operand */
27114823Sslatteng 	    error (FATAL, "command-line option operand missing.\n");
27214823Sslatteng 	return(*(++(*argvp)));			/* operand next word */
27314823Sslatteng }
27414823Sslatteng 
27514823Sslatteng 
outlist(s)27613858Sslatteng outlist(s)	/* process list of page numbers to be printed */
27713858Sslatteng char *s;
27813858Sslatteng {
27913858Sslatteng 	int n1, n2, i;
28013858Sslatteng 
28113858Sslatteng 	nolist = 0;
28213858Sslatteng 	while (*s) {
28313858Sslatteng 		n1 = 0;
28413858Sslatteng 		if (isdigit(*s))
28513858Sslatteng 			do
28613858Sslatteng 				n1 = 10 * n1 + *s++ - '0';
28713858Sslatteng 			while (isdigit(*s));
28813858Sslatteng 		else
28913858Sslatteng 			n1 = -9999;
29013858Sslatteng 		n2 = n1;
29113858Sslatteng 		if (*s == '-') {
29213858Sslatteng 			s++;
29313858Sslatteng 			n2 = 0;
29413858Sslatteng 			if (isdigit(*s))
29513858Sslatteng 				do
29613858Sslatteng 					n2 = 10 * n2 + *s++ - '0';
29713858Sslatteng 				while (isdigit(*s));
29813858Sslatteng 			else
29913858Sslatteng 				n2 = 9999;
30013858Sslatteng 		}
30113858Sslatteng 		olist[nolist++] = n1;
30213858Sslatteng 		olist[nolist++] = n2;
30313858Sslatteng 		if (*s != '\0')
30413858Sslatteng 			s++;
30513858Sslatteng 	}
30613858Sslatteng 	olist[nolist] = 0;
30713858Sslatteng #ifdef DEBUGABLE
30813858Sslatteng 	if (dbg)
30913858Sslatteng 		for (i=0; i<nolist; i += 2)
31013858Sslatteng 			fprintf(stderr,"%3d %3d\n", olist[i], olist[i+1]);
31113858Sslatteng #endif
31213858Sslatteng }
31313858Sslatteng 
conv(fp)31413858Sslatteng conv(fp)
31513858Sslatteng register FILE *fp;
31613858Sslatteng {
31713858Sslatteng 	register int c, k;
31813858Sslatteng 	int m, n, n1, m1;
31913858Sslatteng 	char str[100], buf[300];
32013858Sslatteng 
32113858Sslatteng 	while ((c = getc(fp)) != EOF) {
32213858Sslatteng 		switch (c) {
32313858Sslatteng 		case '\n':	/* when input is text */
32413858Sslatteng 		case ' ':
32513858Sslatteng 		case 0:		/* occasional noise creeps in */
32613858Sslatteng 			break;
32713858Sslatteng 		case '{':	/* push down current environment */
32813858Sslatteng 			t_push();
32913858Sslatteng 			break;
33013858Sslatteng 		case '}':
33113858Sslatteng 			t_pop();
33213858Sslatteng 			break;
33313858Sslatteng 		case '0': case '1': case '2': case '3': case '4':
33413858Sslatteng 		case '5': case '6': case '7': case '8': case '9':
33513858Sslatteng 			/* two motion digits plus a character */
33613858Sslatteng 			hmot((c-'0')*10 + getc(fp)-'0');
33713858Sslatteng 			put1(getc(fp));
33813858Sslatteng 			break;
33913858Sslatteng 		case 'c':	/* single ascii character */
34013858Sslatteng 			put1(getc(fp));
34113858Sslatteng 			break;
34213858Sslatteng 		case 'C':
34313858Sslatteng 			fscanf(fp, "%s", str);
34413858Sslatteng 			put1s(str);
34513858Sslatteng 			break;
34613858Sslatteng 		case 't':	/* straight text */
34713858Sslatteng 			fgets(buf, sizeof(buf), fp);
34813858Sslatteng 			t_text(buf);
34913858Sslatteng 			break;
35013858Sslatteng 		case 'D':	/* draw function */
35116186Sslatteng 			if (fgets(buf, sizeof(buf), fp) == NULL)
35216186Sslatteng 			    error(FATAL, "unexpected end of input");;
35313858Sslatteng 			switch (buf[0]) {
35413858Sslatteng 			case 'l':	/* draw a line */
35513858Sslatteng 			    sscanf(buf+1, "%d %d", &n, &m);
35613858Sslatteng 			    drawline(n, m);
35713858Sslatteng 			    break;
35813858Sslatteng 			case 'c':	/* circle */
35913858Sslatteng 			    sscanf(buf+1, "%d", &n);
36013858Sslatteng 			    drawcirc(n);
36113858Sslatteng 			    break;
36213858Sslatteng 			case 'e':	/* ellipse */
36313858Sslatteng 			    sscanf(buf+1, "%d %d", &m, &n);
36413858Sslatteng 			    drawellip(m, n);
36513858Sslatteng 			    break;
36613858Sslatteng 			case 'a':	/* arc */
36713858Sslatteng 			    sscanf(buf+1, "%d %d %d %d", &n, &m, &n1, &m1);
36813858Sslatteng 			    drawarc(n, m, n1, m1);
36913858Sslatteng 			    break;
37016539Sslatteng 			case 'P':	/* unbordered polygon */
37116539Sslatteng 			    bordered = 0;		/* unset border flag */
37216539Sslatteng 			case 'p':	/* polygon */
37316539Sslatteng 			    sscanf(buf+1, "%d", &m);	/* get stipple */
37416539Sslatteng 			    n = 1;			/* number first */
37516539Sslatteng 			    while (buf[++n] == ' ');
37616539Sslatteng 			    while (isdigit(buf[++n]));
37716539Sslatteng 			    setfill(m);			/* set up stipple */
37816539Sslatteng 			    drawwig(buf+n, fp, -1);	/* draw polygon */
37916539Sslatteng 			    bordered = 1;		/* ALWAYS set after */
38016539Sslatteng 			    break;
38113858Sslatteng 			case '~':	/* wiggly line */
38216539Sslatteng 			    drawwig(buf+1, fp, 1);
38316539Sslatteng 			    break;
38413890Sslatteng 			case 'g':	/* gremlin spline */
38516539Sslatteng 			    drawwig(buf+1, fp, 0);
38613858Sslatteng 			    break;
38713890Sslatteng 			case 't':	/* line thickness */
38813890Sslatteng 			    sscanf(buf+1, "%d", &n);
38913890Sslatteng 			    drawthick(n);
39013890Sslatteng 			    break;
39113890Sslatteng 			case 's':	/* line style */
39213890Sslatteng 			    sscanf(buf+1, "%d", &n);
39313890Sslatteng 			    drawstyle(n);
39413890Sslatteng 			    break;
39513858Sslatteng 			default:
39614284Sslatteng 			    error(FATAL, "unknown drawing function %s", buf);
39713858Sslatteng 			    break;
39813858Sslatteng 			}
39913858Sslatteng 			break;
40013858Sslatteng 		case 's':
40113858Sslatteng 			fscanf(fp, "%d", &n);	/* ignore fractional sizes */
40213858Sslatteng 			setsize(t_size(n));
40313858Sslatteng 			break;
40413858Sslatteng 		case 'f':
40513858Sslatteng 			fscanf(fp, "%s", str);
40613858Sslatteng 			setfont(t_font(str));
40713858Sslatteng 			break;
40816539Sslatteng 		case 'i':
40916539Sslatteng 			fscanf(fp, "%d", &n);
41016539Sslatteng 			setstip(n);
41116539Sslatteng 			break;
41213858Sslatteng 		case 'H':	/* absolute horizontal motion */
41313858Sslatteng 			/* fscanf(fp, "%d", &n); */
41413858Sslatteng 			while ((c = getc(fp)) == ' ')
41513858Sslatteng 				;
41613858Sslatteng 			k = 0;
41713858Sslatteng 			do {
41813858Sslatteng 				k = 10 * k + c - '0';
41913858Sslatteng 			} while (isdigit(c = getc(fp)));
42013858Sslatteng 			ungetc(c, fp);
42113858Sslatteng 			hgoto(k);
42213858Sslatteng 			break;
42313858Sslatteng 		case 'h':	/* relative horizontal motion */
42413858Sslatteng 			while ((c = getc(fp)) == ' ')
42513858Sslatteng 				;
42613858Sslatteng 			k = 0;
42713858Sslatteng 			do {
42813858Sslatteng 				k = 10 * k + c - '0';
42913858Sslatteng 			} while (isdigit(c = getc(fp)));
43013858Sslatteng 			ungetc(c, fp);
43113858Sslatteng 			hmot(k);
43213858Sslatteng 			break;
43313858Sslatteng 		case 'w':	/* word space */
43413858Sslatteng 			break;
43513858Sslatteng 		case 'V':
43613858Sslatteng 			fscanf(fp, "%d", &n);
43713858Sslatteng 			vgoto(n);
43813858Sslatteng 			break;
43913858Sslatteng 		case 'v':
44013858Sslatteng 			fscanf(fp, "%d", &n);
44113858Sslatteng 			vmot(n);
44213858Sslatteng 			break;
44313858Sslatteng 		case 'p':	/* new page */
44413858Sslatteng 			fscanf(fp, "%d", &n);
44513858Sslatteng 			t_page(n);
44613858Sslatteng 			break;
44713858Sslatteng 		case 'n':	/* end of line */
44813858Sslatteng 			t_newline();
44916186Sslatteng 
45013858Sslatteng 		case '#':	/* comment */
45116186Sslatteng 			do
45216186Sslatteng 				c = getc(fp);
45316186Sslatteng 			while (c != '\n' && c != EOF);
45413858Sslatteng 			break;
45513858Sslatteng 		case 'x':	/* device control */
45615618Sslatteng 			if (devcntrl(fp)) return;
45713858Sslatteng 			break;
45813858Sslatteng 		default:
45914284Sslatteng 			error(FATAL, "unknown input character %o %c", c, c);
46013858Sslatteng 		}
46115283Sslatteng 		if (emptypos < NLINES) {	/* for each input operation */
46215283Sslatteng 			slop_lines(1);		/* put out an output line */
46315283Sslatteng #ifdef DRIVER
46415283Sslatteng 			if (emptypos == NLINES) {
46515283Sslatteng 				ioctl(OUTFILE, VSETSTATE, prtmode);
46615283Sslatteng 				if (write(OUTFILE, "\f", 2) != 2)
46715283Sslatteng 					exit(RESTART);
46815283Sslatteng 				ioctl(OUTFILE, VSETSTATE, pltmode);
46915283Sslatteng 			}
47015283Sslatteng #endif
47115283Sslatteng 		}
47213858Sslatteng 	}
47313858Sslatteng }
47413858Sslatteng 
devcntrl(fp)47515618Sslatteng int devcntrl(fp)	/* interpret device control functions */
47615618Sslatteng FILE *fp;		/* returns -1 upon "stop" command */
47713858Sslatteng {
47813858Sslatteng         char str[20], str1[50], buf[50];
47913858Sslatteng 	int c, n;
48013858Sslatteng 
48113858Sslatteng 	fscanf(fp, "%s", str);
48213858Sslatteng 	switch (str[0]) {	/* crude for now */
48313858Sslatteng 	case 'i':	/* initialize */
48413858Sslatteng 		fileinit();
48513858Sslatteng 		t_init();
48613858Sslatteng 		break;
48713858Sslatteng 	case 't':	/* trailer */
48813858Sslatteng 		break;
48913858Sslatteng 	case 'p':	/* pause -- can restart */
49013858Sslatteng 		t_reset('p');
49113858Sslatteng 		break;
49213858Sslatteng 	case 's':	/* stop */
49313858Sslatteng 		t_reset('s');
49415618Sslatteng 		return -1;
49513858Sslatteng 	case 'r':	/* resolution assumed when prepared */
49614582Sslatteng 		fscanf(fp, "%d", &n);
49716539Sslatteng 		if (n!=RES) error(FATAL,"Input computed for wrong printer");
49813858Sslatteng 		break;
49913858Sslatteng 	case 'f':	/* font used */
50013858Sslatteng 		fscanf(fp, "%d %s", &n, str);
50113858Sslatteng 		fgets(buf, sizeof buf, fp);	/* in case there's a filename */
50213858Sslatteng 		ungetc('\n', fp);		/* fgets goes too far */
50313858Sslatteng 		str1[0] = 0;			/* in case nothing comes in */
50413858Sslatteng 		sscanf(buf, "%s", str1);
50513858Sslatteng 		loadfont(n, str, str1);
50613858Sslatteng 		break;
50713858Sslatteng 						/* these don't belong here... */
50813858Sslatteng 	case 'H':	/* char height */
50913858Sslatteng 		fscanf(fp, "%d", &n);
51013858Sslatteng 		t_charht(n);
51113858Sslatteng 		break;
51213858Sslatteng 	case 'S':	/* slant */
51313858Sslatteng 		fscanf(fp, "%d", &n);
51413858Sslatteng 		t_slant(n);
51513858Sslatteng 		break;
51613858Sslatteng 	}
51713858Sslatteng 	while ((c = getc(fp)) != '\n')	/* skip rest of input line */
51813858Sslatteng 		if (c == EOF)
51915618Sslatteng 			return -1;
52015618Sslatteng 	return 0;
52113858Sslatteng }
52213858Sslatteng 
52313858Sslatteng /* fileinit:	read in font and code files, etc.
52413858Sslatteng 		Must open table for device, read in resolution,
52514582Sslatteng 		size info, font info, etc. and set params.
52614582Sslatteng 		Also read in font name mapping.
52713858Sslatteng */
52814582Sslatteng 
fileinit()52913858Sslatteng fileinit()
53013858Sslatteng {
53114582Sslatteng 	register int i;
53214582Sslatteng 	register int fin;
53314582Sslatteng 	register int nw;
53414582Sslatteng 	register char *filebase;
53514582Sslatteng 	register char *p;
53614582Sslatteng 	register FILE *fp;
53714582Sslatteng 	char	temp[100];
53813858Sslatteng 
53914582Sslatteng 		/* first, read in font map file.  The file must be of Format:
54014582Sslatteng 			XX  FILENAME  (XX = troff font name)
54114582Sslatteng 			with one entry per text line of the file.
54214582Sslatteng 		   Extra stuff after FILENAME is ignored */
54314582Sslatteng 
54414582Sslatteng 	sprintf(temp, "%s/fontmap", bitdir);
54514582Sslatteng 	if ((fp = fopen(temp, "r")) == NULL)
54614582Sslatteng 		error(FATAL, "Can't open %s", temp);
54714582Sslatteng 	for (i = 0; i <= NFONTS && fgets(temp, 100, fp) != NULL; i++) {
54814582Sslatteng 		sscanf(temp, "%2s", fontmap[i].fname);
54914582Sslatteng 		p = &temp[0];
55014582Sslatteng 		while (*p != ' ' && *p != '	') p++;
55114582Sslatteng 		while (*p == ' ' || *p == '	') p++;
55214582Sslatteng 		filebase = p;
55314582Sslatteng 		for (nw = 1; *p != '\n' && *p != ' ' && *p != '\t'; p++) nw++;
55414582Sslatteng 		fontmap[i].ffile = nalloc(1, nw);
55514582Sslatteng 		sscanf(filebase, "%s", fontmap[i].ffile);
55614582Sslatteng 	}
55714582Sslatteng 	fontmap[++i].fname[0] = '0';		/* finish off with zeros */
55814582Sslatteng 	fontmap[i].ffile = (char *) 0;
55914582Sslatteng 	fclose(fp);
56014582Sslatteng #ifdef DEBUGABLE
56114582Sslatteng 	if(dbg) {
56214582Sslatteng 	    fprintf(stderr, "font map:\n");
56314582Sslatteng 	    for (i = 0; fontmap[i].ffile; i++)
56414582Sslatteng 		fprintf(stderr,"%s = %s\n", fontmap[i].fname, fontmap[i].ffile);
56514582Sslatteng 	}
56614582Sslatteng #endif
56714582Sslatteng 
56815283Sslatteng 	sprintf(temp, "%s/devva/DESC.out", fontdir);
56913858Sslatteng 	if ((fin = open(temp, 0)) < 0)
57014284Sslatteng 		error(FATAL, "can't open tables for %s", temp);
57113858Sslatteng 	read(fin, &dev, sizeof(struct dev));
57213858Sslatteng 	nfonts = dev.nfonts;
57316539Sslatteng 	nstips = dev.nstips;
57413858Sslatteng 	nsizes = dev.nsizes;
57513858Sslatteng 	nchtab = dev.nchtab;
57614582Sslatteng 	filebase = calloc(1, dev.filesize);	/* enough room for whole file */
57713858Sslatteng 	read(fin, filebase, dev.filesize);	/* all at once */
57813858Sslatteng 	pstab = (short *) filebase;
57913858Sslatteng 	chtab = pstab + nsizes + 1;
58013858Sslatteng 	chname = (char *) (chtab + dev.nchtab);
58113858Sslatteng 	p = chname + dev.lchname;
58213858Sslatteng 	for (i = 1; i <= nfonts; i++) {
58313858Sslatteng 		fontbase[i] = (struct font *) p;
58413858Sslatteng 		nw = *p & BMASK;		/* 1st thing is width count */
58515176Sslatteng 		p += sizeof(struct font);
58613858Sslatteng 		widtab[i] = p;
58713858Sslatteng 		codetab[i] = p + 2 * nw;
58813858Sslatteng 		fitab[i] = p + 3 * nw;
58913858Sslatteng 		p += 3 * nw + dev.nchtab + 128 - 32;
59013858Sslatteng 		t_fp(i, fontbase[i]->namefont, fontbase[i]->intname);
59113858Sslatteng #ifdef DEBUGABLE
59213858Sslatteng 		if (dbg > 1) fontprint(i);
59313858Sslatteng #endif
59413858Sslatteng 	}
59516539Sslatteng 	for (i = 1; i <= nstips; i++) {		/* add in stipple "filenames" */
59616539Sslatteng 		if (nfonts + i <= NFONTS)
59716539Sslatteng 			t_fp(nfonts + i, p, (char *)0);
59816539Sslatteng 		p += strlen(p) + 1;
59916539Sslatteng 	}
60013858Sslatteng 	fontbase[0] = (struct font *)
60113858Sslatteng 		calloc(1,3*255 + dev.nchtab + (128-32) + sizeof (struct font));
60213858Sslatteng 	widtab[0] = (char *) fontbase[0] + sizeof (struct font);
60313858Sslatteng 	fontbase[0]->nwfont = 255;
60413858Sslatteng 	close(fin);
60514582Sslatteng 
60613858Sslatteng }
60713858Sslatteng 
60814582Sslatteng 
60916098Sslatteng #ifdef DEBUGABLE
fontprint(i)61013858Sslatteng fontprint(i)	/* debugging print of font i (0,...) */
61113858Sslatteng {
61213858Sslatteng 	int j, n;
61313858Sslatteng 	char *p;
61413858Sslatteng 
61513858Sslatteng 	fprintf(stderr,"font %d:\n", i);
61613858Sslatteng 	p = (char *) fontbase[i];
61713858Sslatteng 	n = fontbase[i]->nwfont & BMASK;
61813858Sslatteng 	fprintf(stderr,
61913858Sslatteng 	    "base=0%o, nchars=%d, spec=%d, name=%s, widtab=0%o, fitab=0%o\n",p,
62013858Sslatteng 	    n,fontbase[i]->specfont,fontbase[i]->namefont,widtab[i],fitab[i]);
62113858Sslatteng 	fprintf(stderr,"widths:\n");
62213858Sslatteng 	for (j=0; j <= n; j++) {
62313858Sslatteng 		fprintf(stderr," %2d", widtab[i][j] & BMASK);
62413858Sslatteng 		if (j % 20 == 19) fprintf(stderr,"\n");
62513858Sslatteng 	}
62613858Sslatteng 	fprintf(stderr,"\ncodetab:\n");
62713858Sslatteng 	for (j=0; j <= n; j++) {
62813858Sslatteng 		fprintf(stderr," %2d", codetab[i][j] & BMASK);
62913858Sslatteng 		if (j % 20 == 19) fprintf(stderr,"\n");
63013858Sslatteng 	}
63113858Sslatteng 	fprintf(stderr,"\nfitab:\n");
63213858Sslatteng 	for (j=0; j <= dev.nchtab + 128-32; j++) {
63313858Sslatteng 		fprintf(stderr," %2d", fitab[i][j] & BMASK);
63413858Sslatteng 		if (j % 20 == 19) fprintf(stderr,"\n");
63513858Sslatteng 	}
63613858Sslatteng 	fprintf(stderr,"\n");
63713858Sslatteng }
63816098Sslatteng #endif
63913858Sslatteng 
64015618Sslatteng 
loadfont(n,s,s1)64113858Sslatteng loadfont(n, s, s1)	/* load font info for font s on position n (0...) */
64213858Sslatteng int n;
64313858Sslatteng char *s, *s1;
64413858Sslatteng {
64513858Sslatteng 	char temp[60];
64615618Sslatteng 	register int fin;
64715618Sslatteng 	register int nw;
64815618Sslatteng 	register int norig;
64913858Sslatteng 
65013858Sslatteng 	if (n < 0 || n > NFONTS)
65113858Sslatteng 		error(FATAL, "illegal fp command %d %s", n, s);
65213858Sslatteng 	if (strcmp(s, fontbase[n]->namefont) == 0)
65313858Sslatteng 		return;
65415618Sslatteng 
65515618Sslatteng 	for (fin = 1; fin <= NFONTS; fin++)	/* first check to see if the */
65615618Sslatteng 	    if (strcmp(s, fontbase[fin]->namefont) == 0) {  /* font is loaded */
65715618Sslatteng 		register char *c;			    /* somewhere else */
65815618Sslatteng 
65915618Sslatteng #define ptrswap(x, y) { c = (char*) (x); x = y; y = c; }
66016098Sslatteng #define ptrfswap(x, y) { c = (char*) (x); x = y; y = (struct font *) c; }
66115618Sslatteng 
66216098Sslatteng 		ptrfswap(fontbase[n], fontbase[fin]);
66315618Sslatteng 		ptrswap(codetab[n], codetab[fin]);
66415618Sslatteng 		ptrswap(widtab[n], widtab[fin]);
66515618Sslatteng 		ptrswap(fitab[n], fitab[fin]);
66615618Sslatteng 		t_fp(n, fontbase[n]->namefont, fontbase[n]->intname);
66715618Sslatteng 		t_fp(fin, fontbase[fin]->namefont, fontbase[fin]->intname);
66815618Sslatteng 		return;
66915618Sslatteng 	    }
67015618Sslatteng 
67113858Sslatteng 	if (s1 == NULL || s1[0] == '\0')
67215283Sslatteng 		sprintf(temp, "%s/devva/%s.out", fontdir, s);
67313858Sslatteng 	else
67413858Sslatteng 		sprintf(temp, "%s/%s.out", s1, s);
67513858Sslatteng 	if ((fin = open(temp, 0)) < 0)
67613858Sslatteng 		error(FATAL, "can't open font table %s", temp);
67713858Sslatteng 	norig = fontbase[n]->nwfont & BMASK;
67813858Sslatteng 	read(fin, fontbase[n], 3*norig + nchtab+128-32 + sizeof(struct font));
67913858Sslatteng 	if ((fontbase[n]->nwfont & BMASK) > norig)
68014284Sslatteng 		error(FATAL, "Font %s too big for position %d", s, n);
68113858Sslatteng 	close(fin);
68213858Sslatteng 	nw = fontbase[n]->nwfont & BMASK;
68313858Sslatteng 	widtab[n] = (char *) fontbase[n] + sizeof(struct font);
68413858Sslatteng 	codetab[n] = (char *) widtab[n] + 2 * nw;
68513858Sslatteng 	fitab[n] = (char *) widtab[n] + 3 * nw;
68613858Sslatteng 	t_fp(n, fontbase[n]->namefont, fontbase[n]->intname);
68713858Sslatteng 	fontbase[n]->nwfont = norig;	/* to later use full original size */
68813858Sslatteng #ifdef DEBUGABLE
68913858Sslatteng 	if (dbg > 1) fontprint(n);
69013858Sslatteng #endif
69113858Sslatteng }
69213858Sslatteng 
69314284Sslatteng 
69413858Sslatteng /*VARARGS1*/
error(f,s,a1,a2,a3,a4,a5,a6,a7)69513858Sslatteng error(f, s, a1, a2, a3, a4, a5, a6, a7) {
69614284Sslatteng 	fprintf(stderr, "dvar: ");
69713858Sslatteng 	fprintf(stderr, s, a1, a2, a3, a4, a5, a6, a7);
69813858Sslatteng 	fprintf(stderr, "\n");
69915176Sslatteng 	if (f) exit(ABORT);
70013858Sslatteng }
70113858Sslatteng 
70213858Sslatteng 
t_init()70313858Sslatteng t_init()	/* initialize device */
70413858Sslatteng {
70513858Sslatteng 	int i;
70613858Sslatteng 
70713858Sslatteng 	hpos = vpos = 0;
70813858Sslatteng 
70913858Sslatteng 	setsize(t_size(10));	/* start somewhere */
71013858Sslatteng 	setfont(1);
71113858Sslatteng }
71213858Sslatteng 
71313858Sslatteng 
71413858Sslatteng struct state {
71513858Sslatteng 	int	ssize;
71613858Sslatteng 	int	sfont;
71713858Sslatteng 	int	shpos;
71813858Sslatteng 	int	svpos;
71914284Sslatteng 	int	sstyle;
72014284Sslatteng 	int	sthick;
72113858Sslatteng };
72213858Sslatteng struct	state	state[MAXSTATE];
72313858Sslatteng struct	state	*statep = state;
72413858Sslatteng 
t_push()72513858Sslatteng t_push()	/* begin a new block */
72613858Sslatteng {
72713858Sslatteng 	statep->ssize = size;
72813858Sslatteng 	statep->sfont = font;
72914284Sslatteng 	statep->sstyle = linmod;
73014284Sslatteng 	statep->sthick = linethickness;
73113858Sslatteng 	statep->shpos = hpos;
73213858Sslatteng 	statep->svpos = vpos;
73313858Sslatteng 	if (statep++ >= state+MAXSTATE)
73413858Sslatteng 		error(FATAL, "{ nested too deep");
73513858Sslatteng }
73613858Sslatteng 
t_pop()73713858Sslatteng t_pop()	/* pop to previous state */
73813858Sslatteng {
73913858Sslatteng 	if (--statep < state)
74013858Sslatteng 		error(FATAL, "extra }");
74113858Sslatteng 	size = statep->ssize;
74213858Sslatteng 	font = statep->sfont;
74313858Sslatteng 	hpos = statep->shpos;
74413858Sslatteng 	vpos = statep->svpos;
74514284Sslatteng 	linmod = statep->sstyle;
74614284Sslatteng 	linethickness = statep->sthick;
74713858Sslatteng }
74813858Sslatteng 
t_page(n)74913858Sslatteng t_page(n)	/* do whatever new page functions */
75013858Sslatteng {
75113858Sslatteng 	int i;
75213858Sslatteng 
75313858Sslatteng 
75415283Sslatteng 	if (emptypos < NLINES) {		/* finish off last page, if */
75515283Sslatteng 		slop_lines(NLINES - emptypos);	/* it's not done yet */
75615176Sslatteng #ifdef DRIVER
75713858Sslatteng 		ioctl(OUTFILE, VSETSTATE, prtmode);
75813858Sslatteng 		if (write(OUTFILE, "\f", 2) != 2)
75913858Sslatteng 			exit(RESTART);
76013858Sslatteng 		ioctl(OUTFILE, VSETSTATE, pltmode);
76115176Sslatteng #endif
76213858Sslatteng 	}
76315283Sslatteng 	if (output) {
76415283Sslatteng 		emptypos = 0;		/* set emptying to be started */
76515283Sslatteng 		elevel = fill;		/* swap buffer pointers */
76615283Sslatteng 		fill = empty;
76715283Sslatteng 		empty = elevel;
76815283Sslatteng 	}
76913858Sslatteng 
77013858Sslatteng 	vpos = 0;
77113858Sslatteng 	output = 1;
77213858Sslatteng 	if (nolist == 0)
77314582Sslatteng 		return;		/* no -o specified */
77413858Sslatteng 	output = 0;
77513858Sslatteng 	for (i = 0; i < nolist; i += 2)
77613858Sslatteng 		if (n >= olist[i] && n <= olist[i+1]) {
77713858Sslatteng 			output = 1;
77813858Sslatteng 			break;
77913858Sslatteng 		}
78013858Sslatteng }
78113858Sslatteng 
t_newline()78213858Sslatteng t_newline()	/* do whatever for the end of a line */
78313858Sslatteng {
78413858Sslatteng 	hpos = 0;	/* because we're now back at the left margin */
78513858Sslatteng }
78613858Sslatteng 
t_size(n)78713858Sslatteng t_size(n)	/* convert integer to internal size number*/
78813858Sslatteng int n;
78913858Sslatteng {
79013858Sslatteng 	int i;
79113858Sslatteng 
79213858Sslatteng 	if (n <= pstab[0])
79314582Sslatteng 		return(0);
79414582Sslatteng 	else if (n >= pstab[nsizes - 1])
79514582Sslatteng 		return(nsizes - 1);
79613858Sslatteng 	for (i = 0; n > pstab[i]; i++)
79713858Sslatteng 		;
79814582Sslatteng 	return(i);
79913858Sslatteng }
80013858Sslatteng 
t_charht(n)80113858Sslatteng t_charht(n)	/* set character height to n */
80213858Sslatteng int n;
80313858Sslatteng {
80413858Sslatteng #ifdef DEBUGABLE
80514582Sslatteng 	if (dbg) error(!FATAL, "can't set height on varian");
80613858Sslatteng #endif
80713858Sslatteng }
80813858Sslatteng 
t_slant(n)80913858Sslatteng t_slant(n)	/* set slant to n */
81013858Sslatteng int n;
81113858Sslatteng {
81213858Sslatteng #ifdef DEBUGABLE
81314582Sslatteng 	if (dbg) error(!FATAL, "can't set slant on varian");
81413858Sslatteng #endif
81513858Sslatteng }
81613858Sslatteng 
t_font(s)81713858Sslatteng t_font(s)	/* convert string to internal font number */
81813858Sslatteng char *s;
81913858Sslatteng {
82013858Sslatteng 	int n;
82113858Sslatteng 
82213858Sslatteng 	n = atoi(s);
82313858Sslatteng 	if (n < 0 || n > nfonts)
82413858Sslatteng 		n = 1;
82513858Sslatteng 	return(n);
82613858Sslatteng }
82713858Sslatteng 
t_text(s)82813858Sslatteng t_text(s)	/* print string s as text */
82913858Sslatteng char *s;
83013858Sslatteng {
83113858Sslatteng 	int c;
83213858Sslatteng 	char str[100];
83313858Sslatteng 
83413858Sslatteng 	if (!output)
83513858Sslatteng 		return;
83613858Sslatteng 	while (c = *s++) {
83713858Sslatteng 		if (c == '\\') {
83813858Sslatteng 			switch (c = *s++) {
83913858Sslatteng 			case '\\':
84013858Sslatteng 			case 'e':
84113858Sslatteng 				put1('\\');
84213858Sslatteng 				break;
84313858Sslatteng 			case '(':
84413858Sslatteng 				str[0] = *s++;
84513858Sslatteng 				str[1] = *s++;
84613858Sslatteng 				str[2] = '\0';
84713858Sslatteng 				put1s(str);
84813858Sslatteng 				break;
84913858Sslatteng 			}
85013858Sslatteng 		} else {
85113858Sslatteng 			put1(c);
85213858Sslatteng 		}
85313858Sslatteng 		hmot(lastw);
85413858Sslatteng #ifdef DEBUGABLE
85513858Sslatteng 		if (dbg) fprintf(stderr,"width = %d\n", lastw);
85613858Sslatteng #endif
85713858Sslatteng 	}
85813858Sslatteng }
85913858Sslatteng 
86015283Sslatteng 
t_reset(c)86113858Sslatteng t_reset(c)
86213858Sslatteng {
86315283Sslatteng 	if (c == 's') {
86415283Sslatteng 		t_page();
86515283Sslatteng 		output = 0;
86615283Sslatteng 		t_page();
86715176Sslatteng #ifdef DRIVER
86814582Sslatteng 		ioctl(OUTFILE, VSETSTATE, prtmode);
86914582Sslatteng 		if (write(OUTFILE, "\f", 2) != 2)
87014582Sslatteng 			exit(RESTART);
87115176Sslatteng #endif
87213858Sslatteng 	}
87313858Sslatteng }
87413858Sslatteng 
87513858Sslatteng 
87614284Sslatteng /*----------------------------------------------------------------------------*
87714284Sslatteng  | Routine:	hgoto (horizontal_spot)
87814284Sslatteng  |
87914284Sslatteng  | Results:	hpos is set to n.  If n overlaps in either direction, it wraps
88014284Sslatteng  |		around to the other end of the page.
88114284Sslatteng  *----------------------------------------------------------------------------*/
88214284Sslatteng 
hgoto(n)88314284Sslatteng hgoto(n)
88414284Sslatteng int n;
88514284Sslatteng {
88614284Sslatteng     if (n < 0)
88714284Sslatteng 	n += NLINES;
88814284Sslatteng     else if (n >= NLINES)
88914284Sslatteng 	n -= NLINES;
89014284Sslatteng     hpos = n;
89114284Sslatteng }
89214284Sslatteng 
89314284Sslatteng 
89414284Sslatteng /*----------------------------------------------------------------------------*
89514284Sslatteng  | Routine:	vgoto (vertical_spot)
89614284Sslatteng  |
89714284Sslatteng  | Results:	vpos is set to n.  If n overlaps in either direction, it wraps
89814284Sslatteng  |		around to the other end of the page.
89914284Sslatteng  *----------------------------------------------------------------------------*/
90014284Sslatteng 
vgoto(n)90113858Sslatteng vgoto(n)
90214284Sslatteng int n;
90313858Sslatteng {
90414284Sslatteng     if (n < 0)
90514284Sslatteng 	n += RASTER_LENGTH;
90614284Sslatteng     else if (n > RASTER_LENGTH)
90714284Sslatteng 	n -= RASTER_LENGTH;
90813858Sslatteng     vpos = n;
90913858Sslatteng }
91013858Sslatteng 
put1s(s)91113858Sslatteng put1s(s)	/* s is a funny char name */
91213858Sslatteng char *s;
91313858Sslatteng {
91413858Sslatteng 	int i;
91513858Sslatteng 
91613858Sslatteng 	if (!output)
91713858Sslatteng 		return;
91813858Sslatteng #ifdef DEBUGABLE
91913858Sslatteng 	if (dbg) fprintf(stderr,"%s ", s);
92013858Sslatteng #endif
92113858Sslatteng 	for (i = 0; i < nchtab; i++)
92213858Sslatteng 		if (strcmp(&chname[chtab[i]], s) == 0)
92313858Sslatteng 			break;
92413858Sslatteng 	if (i < nchtab)
92513858Sslatteng 		put1(i + 128);
92613858Sslatteng }
92713858Sslatteng 
put1(c)92813858Sslatteng put1(c)	/* output char c */
92913858Sslatteng int c;
93013858Sslatteng {
93113858Sslatteng 	char *pw;
93213858Sslatteng 	register char *p;
93313858Sslatteng 	register int i, k;
93413858Sslatteng 	int j, ofont, code;
93513858Sslatteng 
93613858Sslatteng 	if (!output)
93713858Sslatteng 		return;
93813858Sslatteng 	c -= 32;
93913858Sslatteng 	if (c <= 0) {
94013858Sslatteng #ifdef DEBUGABLE
94113858Sslatteng 		if (dbg) fprintf(stderr,"non-exist 0%o\n", c + 32);
94213858Sslatteng #endif
94314582Sslatteng  		lastw = (widtab[font][0] * pstab[size] + dev.unitwidth/2)
94413858Sslatteng 								/ dev.unitwidth;
94513858Sslatteng 		return;
94613858Sslatteng 	}
94713858Sslatteng 	k = ofont = font;
94813858Sslatteng 	i = fitab[font][c] & BMASK;
94913858Sslatteng 	if (i != 0) {			/* it's on this font */
95013858Sslatteng 		p = codetab[font];	/* get the printing value of ch */
95113858Sslatteng 		pw = widtab[font];	/* get the width */
95216098Sslatteng 	} else {		/* on another font - run down the font list */
95316098Sslatteng 		for (j=0; j++ <= nfonts; k = (k+1) % (nfonts+1)) {
95413858Sslatteng 			if (fitab[k] == 0)
95513858Sslatteng 				continue;
95616098Sslatteng 			if ((i=fitab[k][c] & BMASK) != 0) {
95713858Sslatteng 				p = codetab[k];
95813858Sslatteng 				pw = widtab[k];
95913858Sslatteng 				setfont(k);
96013858Sslatteng 				break;
96113858Sslatteng 			}
96213858Sslatteng 		}
96316098Sslatteng 	}
96415176Sslatteng 
96516098Sslatteng 	if (i == 0) {
96613858Sslatteng #ifdef DEBUGABLE
96713858Sslatteng 		if (dbg) fprintf(stderr,"not found 0%o\n", c+32);
96813858Sslatteng #endif
96913858Sslatteng 		return;
97013858Sslatteng 	}
97116098Sslatteng 	code = p[i] & BMASK;
97213858Sslatteng #ifdef DEBUGABLE
97313858Sslatteng 	if (dbg) {
97413858Sslatteng 		if (isprint(c+32))
97513858Sslatteng 			fprintf(stderr,"%c %d\n", c+32, code);
97613858Sslatteng 		else
97713858Sslatteng 			fprintf(stderr,"%03o %d\n", c+32, code);
97813858Sslatteng 	}
97913858Sslatteng #endif
98013858Sslatteng 	outc(code);	/* character is < 254 */
98113858Sslatteng 	if (font != ofont)
98213858Sslatteng 		setfont(ofont);
98314582Sslatteng 	lastw = ((pw[i]&077) * pstab[size] + dev.unitwidth/2) / dev.unitwidth;
98413858Sslatteng }
98513858Sslatteng 
98613858Sslatteng 
98713858Sslatteng 
setsize(n)98813858Sslatteng setsize(n)	/* set point size to n (internal) */
98913858Sslatteng int n;
99013858Sslatteng {
99113858Sslatteng 
99213858Sslatteng 	if (n == size)
99313858Sslatteng 		return;	/* already there */
99414582Sslatteng 	if (vloadfont(font, pstab[n]) != -1)
99513858Sslatteng 		size = n;
99613858Sslatteng }
99713858Sslatteng 
t_fp(n,s,si)99813858Sslatteng t_fp(n, s, si)	/* font position n now contains font s, intname si */
99915176Sslatteng int n;		/* internal name is ignored */
100013858Sslatteng char *s, *si;
100113858Sslatteng {
100214582Sslatteng 	register int i;
100313858Sslatteng 
100414582Sslatteng 
100514582Sslatteng 			/* first convert s to filename if possible */
100614582Sslatteng 	for (i = 0; fontmap[i].ffile != (char *) 0; i++) {
100714582Sslatteng #ifdef DEBUGABLE
100814582Sslatteng 		if(dbg>1)fprintf(stderr,"testing :%s:%s:\n",s,fontmap[i].fname);
100914582Sslatteng #endif
101014582Sslatteng 		if (strcmp(s, fontmap[i].fname) == 0) {
101114582Sslatteng 			s = fontmap[i].ffile;
101214582Sslatteng #ifdef DEBUGABLE
101314582Sslatteng 			if(dbg)fprintf(stderr, "found :%s:\n",fontmap[i].ffile);
101414582Sslatteng #endif
101514582Sslatteng 			break;
101614582Sslatteng 		}
101714582Sslatteng 	}
101815176Sslatteng 	fontname[n] = s;
101915283Sslatteng 	for(i = 0;i <= NFONTS;i++)	/* free the bits of that font */
102013858Sslatteng 		if (fontdes[i].fnum == n){
102113858Sslatteng 			nfree(fontdes[i].bits);
102213858Sslatteng 			fontdes[i].fnum = -1;
102313858Sslatteng 		}
102413858Sslatteng }
102513858Sslatteng 
102614582Sslatteng 
setfont(n)102713858Sslatteng setfont(n)	/* set font to n */
102813858Sslatteng int n;
102913858Sslatteng {
103016539Sslatteng 	if (n < 0 || n > nfonts)
103114284Sslatteng 		error(FATAL, "illegal font %d", n);
103214582Sslatteng 	if (vloadfont(n,pstab[size]) != -1)
103313858Sslatteng 		font = n;
103413858Sslatteng }
103513858Sslatteng 
103616539Sslatteng 
setstip(n)103716539Sslatteng setstip(n)	/* set stipple font to n */
103816539Sslatteng int n;
103916539Sslatteng {
104016539Sslatteng 	if (n < 1 || n > nstips)
104116539Sslatteng 		error(FATAL, "illegal stipple %d", n);
104216539Sslatteng 	stip = n;
104316539Sslatteng }
104416539Sslatteng 
104516539Sslatteng 
vloadfont(fnum,fsize)104613858Sslatteng vloadfont(fnum, fsize)
104713858Sslatteng register int fnum;
104813858Sslatteng register int fsize;
104913858Sslatteng {
105013858Sslatteng 	register int i;
105113858Sslatteng 
105213858Sslatteng 	fontwanted = 0;
105313858Sslatteng 	if (fnum == cfnum && fsize == cpsize)
105413858Sslatteng 		return(0);
105513858Sslatteng 	for (i = 0; i < NFONTS; i++) {
105613858Sslatteng 		if (fontdes[i].fnum == fnum && fontdes[i].psize == fsize) {
105713858Sslatteng 			cfnum = fontdes[i].fnum;
105813858Sslatteng 			cpsize = fontdes[i].psize;
105913858Sslatteng 			dispatch = &fontdes[i].disp[0];
106013858Sslatteng 			bits = fontdes[i].bits;
106113858Sslatteng 			cfont = i;
106213858Sslatteng 			return (0);
106313858Sslatteng 		}
106413858Sslatteng 	}
106513858Sslatteng 		/* this is a new font */
106615176Sslatteng 	if (fnum < 0 || fnum > NFONTS || fontname[fnum] == 0) {
106717226Sslatteng 	    error(!FATAL,"error: illegal font %d, size %d\n", fnum, fsize);
106813858Sslatteng 	    return(-1);
106913858Sslatteng 	}
107013858Sslatteng 		/* Need to verify the existance of that font/size here*/
107113858Sslatteng 	nfontnum = fnum;
107213858Sslatteng 	npsize = fsize;
107313858Sslatteng 	fontwanted++;
107413858Sslatteng 	return (0);
107513858Sslatteng }
107613858Sslatteng 
107713858Sslatteng 
getfont()107813858Sslatteng getfont()
107913858Sslatteng {
108014582Sslatteng 	register int fnum;
108114582Sslatteng 	register int fsize;
108214582Sslatteng 	register int fontd;
108314582Sslatteng 	register int d;
108415176Sslatteng 	register int sizehunt = size;
108513858Sslatteng 	char cbuf[BUFSIZ];
108613858Sslatteng 
108713858Sslatteng 	fnum = nfontnum;
108813858Sslatteng 	fsize = npsize;
108914582Sslatteng 			/* try to open font file - if unsuccessful, hunt for */
109014582Sslatteng 			/* a file of same style, different size to substitute */
109115176Sslatteng 	d = -1;	 /* direction to look in pstab (smaller first) */
109214582Sslatteng 	do {
109315176Sslatteng 	    sprintf(cbuf, "%s/%s.%dr", bitdir, fontname[fnum], fsize);
109414582Sslatteng 	    fontd = open(cbuf, OPENREAD);
109514582Sslatteng 	    if (fontd == -1) {		/* File wasn't found. Try another ps */
109615176Sslatteng 		sizehunt += d;
109715176Sslatteng 		if (sizehunt < 0) {	/* past beginning - look higher */
109814582Sslatteng 		    d = 1;
109915176Sslatteng 		    sizehunt = size + 1;
110014582Sslatteng 		}
110115176Sslatteng 		if (sizehunt > nsizes) {	/* past top - forget it */
110214582Sslatteng 		    d = 0;
110314582Sslatteng 		} else {
110415176Sslatteng 		    fsize = pstab[sizehunt];
110514582Sslatteng 		}
110614582Sslatteng 	    }
110714582Sslatteng 	} while (fontd == -1 && d != 0);
110814582Sslatteng 
110914582Sslatteng 	if (fontd == -1) {		/* completely unsuccessful */
111014582Sslatteng 	    perror(cbuf);
111114582Sslatteng 	    error(!FATAL,"fnum = %d, psize = %d, name = %s",
111215176Sslatteng 		fnum, npsize, fontname[fnum]);
111314582Sslatteng 	    fontwanted = 0;
111414582Sslatteng 	    return (-1);
111513858Sslatteng 	}
111613858Sslatteng 	if (read(fontd, &header, sizeof  (header)) != sizeof (header)
111713858Sslatteng 						|| header.magic != 0436)
111813858Sslatteng 		fprintf(stderr, "%s: Bad font file", cbuf);
111913858Sslatteng 	else {
112013858Sslatteng 		cfont = relfont();
112113858Sslatteng 		if ((bits=nalloc(header.size+DSIZ+1,1))== NULL)
112213858Sslatteng 			if ((bits=allpanic(header.size+DSIZ+1))== NULL) {
112315176Sslatteng 				error(FATAL,"%s: ran out of memory", cbuf);
112413858Sslatteng 			}
112513858Sslatteng 
112613858Sslatteng 			/*
112713858Sslatteng 			 * have allocated one chunk of mem for font, dispatch.
112813858Sslatteng 			 * get the dispatch addr, align to word boundary.
112913858Sslatteng 			 */
113013858Sslatteng 
113113858Sslatteng 		d = (int) bits+header.size;
113213858Sslatteng 		d += 1;
113313858Sslatteng 		d &= ~1;
113413858Sslatteng 		if (read (fontd, d, DSIZ) != DSIZ
113513858Sslatteng 			    || read (fontd, bits, header.size) != header.size)
113613858Sslatteng 			fprintf(stderr, "bad font header");
113713858Sslatteng 		else {
113813858Sslatteng 			close(fontd);
113913858Sslatteng 			cfnum = fontdes[cfont].fnum = fnum;
114013858Sslatteng 			cpsize = fontdes[cfont].psize = fsize;
114113858Sslatteng 			fontdes [cfont].bits = bits;
114213858Sslatteng 			fontdes [cfont].disp = (struct dispatch *) d;
114313858Sslatteng 			dispatch = &fontdes[cfont].disp[0];
114413858Sslatteng 			fontwanted = 0;
114513858Sslatteng 			return (0);
114613858Sslatteng 		}
114713858Sslatteng 	}
114813858Sslatteng 	close(fontd);
114913858Sslatteng 	fontwanted = 0;
115013858Sslatteng 	return(-1);
115113858Sslatteng }
115213858Sslatteng 
115313858Sslatteng /*
115413858Sslatteng  * "release" a font position - find an empty one, if possible
115513858Sslatteng  */
115613858Sslatteng 
relfont()115713858Sslatteng relfont()
115813858Sslatteng {
115913858Sslatteng     register int newfont;
116013858Sslatteng 
116113858Sslatteng     for (newfont = 0; newfont < NFONTS; newfont++)
116215283Sslatteng 	if (fontdes [newfont].fnum == -1)
116313858Sslatteng 	    break;
116415283Sslatteng     if (fontdes [newfont].fnum != -1) {
116513858Sslatteng 	nfree (fontdes [newfont].bits);
116613858Sslatteng #ifdef DEBUGABLE
116713858Sslatteng 	if (dbg) fprintf (stderr, "freeing position %d\n", newfont);
116813858Sslatteng     } else {
116913858Sslatteng 	if (dbg)
117013858Sslatteng 	    fprintf (stderr, "taking, not freeing, position %d\n", newfont);
117113858Sslatteng #endif
117213858Sslatteng     }
117315283Sslatteng     fontdes[newfont].fnum = -1;
117413858Sslatteng     return (newfont);
117513858Sslatteng }
117613858Sslatteng 
allpanic(nbytes)117713858Sslatteng char *allpanic (nbytes)
117813858Sslatteng int nbytes;
117913858Sslatteng {
118013858Sslatteng 	register int i;
118113858Sslatteng 
118213858Sslatteng 	for (i = 0; i <= NFONTS; i++) {
118315283Sslatteng 		if (fontdes[i].fnum != -1) nfree(fontdes[i].bits);
118415283Sslatteng 		fontdes[i].fnum = -1;
118513858Sslatteng 		cfnum = cpsize = -1;
118613858Sslatteng 	}
118713858Sslatteng 	return(nalloc(nbytes,1));
118813858Sslatteng }
118913858Sslatteng 
119013858Sslatteng int	M[] = { 0xffffffff, 0xfefefefe, 0xfcfcfcfc, 0xf8f8f8f8,
119113858Sslatteng 		0xf0f0f0f0, 0xe0e0e0e0, 0xc0c0c0c0, 0x80808080, 0x0 };
119213858Sslatteng int	N[] = { 0x00000000, 0x01010101, 0x03030303, 0x07070707,
119313858Sslatteng 		0x0f0f0f0f, 0x1f1f1f1f, 0x3f3f3f3f, 0x7f7f7f7f, 0xffffffff };
119413858Sslatteng int	strim[] = { 0xffffffff, 0xffffff00, 0xffff0000, 0xff000000, 0 };
119513858Sslatteng 
outc(code)119613858Sslatteng outc(code)
119713858Sslatteng int code;		/* character to print */
119813858Sslatteng {
119913858Sslatteng     register struct dispatch *dis; /* ptr to character font record */
120013858Sslatteng     register char *addr;	/* addr of font data */
120113858Sslatteng     int llen;			/* length of each font line */
120213858Sslatteng     int nlines;			/* number of font lines */
120313858Sslatteng     register char *scanp;	/* ptr to output buffer */
120413858Sslatteng     int scanp_inc;		/* increment to start of next buffer */
120513858Sslatteng     int offset;			/* bit offset to start of font data */
120614582Sslatteng     register int i;		/* loop counter */
120713858Sslatteng     register int count;		/* font data ptr */
120813858Sslatteng     register unsigned fontdata;	/* font data temporary */
120913858Sslatteng     register int off8;		/* offset + 8 */
121013858Sslatteng 
121113858Sslatteng     if (fontwanted)
121213858Sslatteng 	getfont();
121313858Sslatteng     dis = dispatch + code;
121413858Sslatteng     if (dis->nbytes) {
121513858Sslatteng 	addr = bits + dis->addr;
121613890Sslatteng 	llen = (dis->up + dis->down + 7) >> 3;
121713890Sslatteng 	nlines = dis->right + dis->left;
121815283Sslatteng 	scanp = fill + (hpos + 1 - dis->left) * BYTES_PER_LINE
121915283Sslatteng 			- (1 + ((dis->down + vpos - 1) >> 3));
122015283Sslatteng 	if (scanp < fill)
122115283Sslatteng 	    scanp += BUFFER_SIZE;
122213858Sslatteng 	scanp_inc = BYTES_PER_LINE - llen;
122315283Sslatteng 	off8 = ((dis->down + vpos - 1) &07);
122413890Sslatteng 	offset = off8 - 8;
122513858Sslatteng 	for (i = 0; i < nlines; i++) {
122615283Sslatteng 	    if (scanp >= fill + BUFFER_SIZE)
122715176Sslatteng 		scanp -= BUFFER_SIZE;
122813858Sslatteng 	    count = llen;
122915283Sslatteng 	    if (scanp + count < fill + BUFFER_SIZE) {
123013858Sslatteng 		do {
123113858Sslatteng 		    fontdata = *(unsigned *)addr;
123213858Sslatteng 		    addr += 4;
123313858Sslatteng 		    if (count < 4)
123413858Sslatteng 			fontdata &= ~strim[count];
123513858Sslatteng 		    *(unsigned*)scanp |=(fontdata << offset) & ~M[off8];
123613858Sslatteng 		    scanp++;
123713858Sslatteng 		    *(unsigned*)scanp |=(fontdata << off8) & ~N[off8];
123813858Sslatteng 		    scanp += 3;
123913858Sslatteng 		    count -= 4;
124013858Sslatteng 		} while (count > 0);
124113858Sslatteng 	    }
124213858Sslatteng 	    scanp += scanp_inc+count;
124313858Sslatteng 	    addr += count;
124413858Sslatteng 	}
124513858Sslatteng 	return;
124613858Sslatteng     }
124713858Sslatteng     return;
124813858Sslatteng }
124913858Sslatteng 
125016539Sslatteng 
125116539Sslatteng /*----------------------------------------------------------------------------*
125216539Sslatteng  | Routine:	setfill(stipple_number)
125316539Sslatteng  |
125416539Sslatteng  | Results:	sets the fill-pattern pointers (stip_disp and
125516539Sslatteng  |		stip_bits) for a particular stipple.  Takes stipple
125616539Sslatteng  |		font from current "stip" number.
125716539Sslatteng  *----------------------------------------------------------------------------*/
125816539Sslatteng 
setfill(number)125916539Sslatteng setfill(number)
126016539Sslatteng int number;
126116539Sslatteng {
126216539Sslatteng 	int curfont;		/* places to save current text font */
126316539Sslatteng 	int cursize;
126416539Sslatteng 
126516539Sslatteng 					/* set global stipmem for polygon */
126616539Sslatteng 	if (number < 0 || number >= DISPATCHSIZE)
126716539Sslatteng 		stipmem = 0;
126816539Sslatteng 	else
126916539Sslatteng 		stipmem = number;
127016539Sslatteng 
127116539Sslatteng 	curfont = cfnum;		/* get pointers to */
127216539Sslatteng 	cursize = cpsize;		/* the inuse font */
127316539Sslatteng 	if (vloadfont(nfonts + stip, 0)) {
127416539Sslatteng 	    stip_disp = (struct dispatch *) NULL;	/* stipple not here */
127516539Sslatteng 	} else {
127616539Sslatteng 	    if (fontwanted) {
127716539Sslatteng 		if (getfont()) {
127816539Sslatteng 		    stip_disp = (struct dispatch *) NULL;
127916539Sslatteng 		} else {
128016539Sslatteng 		    stip_disp = dispatch;	/* save for polygon routine */
128116539Sslatteng 		    stip_bits = bits;
128216539Sslatteng 		}
128316539Sslatteng 	    } else {
128416539Sslatteng 		stip_disp = dispatch;	/* save for polygon routine */
128516539Sslatteng 		stip_bits = bits;
128616539Sslatteng 	    }
128716539Sslatteng 	}
128817226Sslatteng 	if (curfont >= 0) vloadfont(curfont, cursize);
128916539Sslatteng }
129016539Sslatteng 
129116539Sslatteng 
slop_lines(nlines)129213858Sslatteng slop_lines(nlines)
129313858Sslatteng int nlines;
129413858Sslatteng 
129513858Sslatteng /* Output "nlines" lines from the buffer, and clear that section of the  */
129615283Sslatteng /* buffer.	Also updates the pointers to the emptying buffer */
129713858Sslatteng 
129813858Sslatteng {
129913858Sslatteng 	unsigned usize;
130013858Sslatteng 
130113858Sslatteng 	usize = BYTES_PER_LINE * nlines;
130215283Sslatteng 	vwrite(elevel, usize);
130315283Sslatteng 	vclear(elevel, usize);
130415283Sslatteng 	elevel += usize;
130515283Sslatteng 	emptypos += nlines;
130613858Sslatteng }
130713858Sslatteng 
vwrite(buf,usize)130814582Sslatteng vwrite(buf,usize)
130913858Sslatteng char *buf;
131013858Sslatteng unsigned usize;
131113858Sslatteng {
131213858Sslatteng 	register int tsize = 0;
131313858Sslatteng 
131413858Sslatteng 	while (usize){
131513858Sslatteng 		buf += tsize;
131613858Sslatteng 		tsize = usize > MAXWRIT ? MAXWRIT : usize;
131713858Sslatteng #ifdef DEBUGABLE
131813858Sslatteng 		if (dbg)fprintf(stderr,"buf = %d size = %d\n",buf,tsize);
131913858Sslatteng #endif
132013858Sslatteng 		if ((tsize = write(OUTFILE, buf, tsize)) < 0) {
132114284Sslatteng 			perror("dvar: write failed");
132213858Sslatteng 			exit(RESTART);
132313858Sslatteng 		}
132413858Sslatteng 		usize -= tsize;
132513858Sslatteng 	}
132613858Sslatteng }
132713858Sslatteng 
vclear(ptr,nbytes)132813858Sslatteng vclear (ptr, nbytes)
132913858Sslatteng char	*ptr;
133013858Sslatteng unsigned nbytes;
133113858Sslatteng {
133213858Sslatteng     register tsize = 0;
133313858Sslatteng 
133413858Sslatteng     while (nbytes){
133513858Sslatteng 	if ((unsigned)(16*1024) < nbytes) {
133613858Sslatteng 	    tsize = 16 * 1024;
133713858Sslatteng 	} else
133813858Sslatteng 	    tsize = nbytes;
133913858Sslatteng 	nbytes -= tsize;
134013858Sslatteng #ifdef DEBUGABLE
134113858Sslatteng 	if (dbg) fprintf(stderr,"clearing ptr = %d size = %d\n",ptr,tsize);
134213858Sslatteng #endif
134313858Sslatteng 	clear(ptr,tsize);
134413858Sslatteng 	ptr += tsize;
134513858Sslatteng     }
134613858Sslatteng }
134713858Sslatteng 
134813858Sslatteng /*ARGSUSED*/
clear(lp,nbytes)134913858Sslatteng clear(lp, nbytes)
135013858Sslatteng int *lp;
135113858Sslatteng int nbytes;
135213858Sslatteng {
1353*24165Sslatteng #ifdef vax
135413858Sslatteng 	asm("movc5 $0,(sp),$0,8(ap),*4(ap)");
1355*24165Sslatteng #else
1356*24165Sslatteng 	register int i = nbytes;
1357*24165Sslatteng 	register int *cp = lp;
1358*24165Sslatteng 
1359*24165Sslatteng 	while (i-- > 0)
1360*24165Sslatteng 		*(cp++) = 0;
1361*24165Sslatteng #endif
136213858Sslatteng }
136313858Sslatteng 
136413858Sslatteng char *
nalloc(i,j)136513858Sslatteng nalloc(i, j)
136613858Sslatteng int i, j;
136713858Sslatteng {
136813858Sslatteng 	register char *cp;
136913858Sslatteng 
137013858Sslatteng 	cp = calloc(i, j);
137113858Sslatteng #ifdef DEBUGABLE
137213858Sslatteng 	if (dbg) fprintf(stderr, "allocated %d bytes at %x\n", i * j, cp);
137313858Sslatteng #endif
137413858Sslatteng 	return(cp);
137513858Sslatteng }
137613858Sslatteng 
nfree(cp)137713858Sslatteng nfree(cp)
137813858Sslatteng char *cp;
137913858Sslatteng {
138013858Sslatteng #ifdef DEBUGABLE
138113858Sslatteng 	if (dbg) fprintf(stderr, "freeing at %x\n", cp);
138213858Sslatteng #endif
138313858Sslatteng 	free(cp);
138413858Sslatteng }
138513858Sslatteng 
138613858Sslatteng 
138713858Sslatteng /*
138813858Sslatteng  * Points should be in the range 0 <= x < RASTER_LENGTH, 0 <= y < NLINES.
138913858Sslatteng  * The origin is the top left-hand corner with increasing x towards the
139014582Sslatteng  * right and increasing y going down.  X and Y should be sent as (0,0) being
139114582Sslatteng  * at the bottom left.  The output array is NLINES x BYTES_PER_LINE pixels.
139213858Sslatteng  */
point(x,y)139313858Sslatteng point(x, y)
139413890Sslatteng register int x;
139513890Sslatteng register int y;
139613858Sslatteng {
139716539Sslatteng     if ((unsigned)(y=(RASTER_LENGTH-1)-y)<RASTER_LENGTH && (unsigned)x<NLINES) {
139815283Sslatteng 	*(fill + x * BYTES_PER_LINE + (y >> 3)) |= 1 << (7 - (y & 07));
139913858Sslatteng     }
140013858Sslatteng }
140116539Sslatteng 
140216539Sslatteng 
140316539Sslatteng #define pv(x)	((polyvector *)x)
140416539Sslatteng 
140516539Sslatteng typedef struct poly {
140616539Sslatteng 	struct poly *next;	/* doublely-linked lists of vectors */
140716539Sslatteng 	struct poly *prev;
140816539Sslatteng 	int param;	/* bressenham line algorithm parameter */
140916539Sslatteng 	short dy;	/* delta-y for calculating line */
141016539Sslatteng 	short dx;	/* delta-x for calculating line */
141116539Sslatteng 	short curry;	/* current y in this vector */
141216539Sslatteng 	short endx;	/* where vector ends */
141316539Sslatteng } polyvector;
141416539Sslatteng 
141516539Sslatteng 
141616539Sslatteng /*----------------------------------------------------------------------------*
141716539Sslatteng  | Routine:	polygon ( x_coordinates, y_coordinates, num_of_points )
141816539Sslatteng  |
141916539Sslatteng  | Results:	draws a polygon starting at (x[1], y[1]) going through
142016539Sslatteng  |		each of (x_coordinates, y_coordinates), and fills it
142116539Sslatteng  |		with a stipple pattern from stip_disp and stip_bits,
142216539Sslatteng  |		which point to the stipple font.  The pattern is defined
142316539Sslatteng  |		by "stip" and "stipmem".
142416539Sslatteng  |
142516539Sslatteng  |		The scan-line algorithm implemented scans from left to
142616539Sslatteng  |		right (low x to high x).  It also scans, within a line,
142716539Sslatteng  |		from bottom to top (high y to low y).
142816539Sslatteng  |
142916539Sslatteng  |		polygons are clipped to page boundary.
143016539Sslatteng  |
143116539Sslatteng  | Bugs:	stipple pattern MUST be a power of two bytes "wide" and
143216539Sslatteng  |		square.  The square restriction comes from the fact that
143316539Sslatteng  |		the varian and versatec are respectively rotated.
143416539Sslatteng  *----------------------------------------------------------------------------*/
143516539Sslatteng 
polygon(x,y,npts)143616539Sslatteng polygon(x, y, npts)
143716539Sslatteng int x[];
143816539Sslatteng int y[];
143916539Sslatteng int npts;
144016539Sslatteng {
144116539Sslatteng     int nextx;			/* at what x value the next vector starts */
144216539Sslatteng     int maxx, minx, maxy, miny;		/* finds bounds of polygon */
144316539Sslatteng     polyvector *activehead;		/* doing fill, is active edge list */
144416539Sslatteng     polyvector *waitinghead;		/* edges waiting to be active */
144516539Sslatteng     register polyvector *vectptr;	/* random vector */
144616539Sslatteng     register int i;			/* random register */
144716539Sslatteng 
144816539Sslatteng     char *topstipple;		/* points to beginning of stipple glyph */
144916539Sslatteng     char *leftstipple;		/* points to beginning of line of stipple */
145016539Sslatteng     char *bottompage;		/* points to the edge of a raster line */
145116539Sslatteng     int bytewidth;		/* glyph width in bytes */
145216539Sslatteng     int mask;			/* mask to pick off pixel index into stipple */
145316539Sslatteng     int bytemask;		/* mask to pick off byte index into stipple */
145416539Sslatteng 
145516539Sslatteng 
145616539Sslatteng     if (bordered) {
145716539Sslatteng 	for (i = 1; i < npts; i++)		/* first draw outlines */
145816539Sslatteng 	    HGtline(x[i], y[i], x[i+1], y[i+1]);
145916539Sslatteng     }
146016539Sslatteng 
146116539Sslatteng 						/* if no stipple, don't fill */
146216539Sslatteng     if (stip_disp == (struct dispatch *) NULL || stip_bits == (char *) NULL)
146316539Sslatteng 	return;
146416539Sslatteng 
146516539Sslatteng     stip_disp += stipmem;			/* set up parameters for */
146616539Sslatteng     if (!stip_disp->nbytes) {			/* tiling with the stipple */
146716539Sslatteng #ifdef DEBUGABLE
146816539Sslatteng 	error(!FATAL, "member not found: member %d, stipple %d", stipmem, stip);
146916539Sslatteng #endif
147016539Sslatteng 	return;
147116539Sslatteng     }
147216539Sslatteng     topstipple = stip_bits + stip_disp->addr;
147316539Sslatteng     bytewidth = stip_disp->up + stip_disp->down;
147416539Sslatteng     for (i = 1 << 30; i && i != bytewidth; i = i >> 1)
147516539Sslatteng 	;
147616539Sslatteng     if (i==0 || bytewidth<8 || bytewidth != stip_disp->right+stip_disp->left) {
147716539Sslatteng 	error(!FATAL, "invalid stipple: number %d, member %d", stip, stipmem);
147816539Sslatteng 	return;
147916539Sslatteng     }
148016539Sslatteng     mask = bytewidth - 1;
148116539Sslatteng     bytewidth = bytewidth >> 3;
148216539Sslatteng     bytemask = bytewidth - 1;
148316539Sslatteng 
148416539Sslatteng 				/* allocate space for raster-fill algorithm*/
148516539Sslatteng     if ((vectptr = pv( nalloc(sizeof(polyvector), npts + 6) )) == NULL) {
148616539Sslatteng 	error(!FATAL, "unable to allocate space for polygon");
148716539Sslatteng 	return;
148816539Sslatteng     }
148916539Sslatteng #ifdef DEBUGABLE
149016539Sslatteng     if (dbg) fprintf(stderr, "polygon, %d points\n", npts);
149116539Sslatteng #endif
149216539Sslatteng 
149316539Sslatteng     waitinghead = vectptr;
149416539Sslatteng     minx = maxx = x[1];
149516539Sslatteng     miny = maxy = y[1];
149616539Sslatteng     (vectptr++)->prev = pv( NULL );	/* put dummy entry at start */
149716539Sslatteng     waitinghead->next = vectptr;
149816539Sslatteng     vectptr->prev = waitinghead;
149916539Sslatteng     i = 1;					/* starting point of coords */
150016539Sslatteng     if (y[1] != y[npts] || x[1] != x[npts]) {
150116539Sslatteng 	y[0] = y[npts];				/* close polygon if it's not */
150216539Sslatteng 	x[0] = x[npts];
150316539Sslatteng 	i = 0;
150416539Sslatteng     }
150516539Sslatteng     while (i < npts) {		/* set up the vectors */
150616539Sslatteng 	register int j;			/* indexes to work off of */
150716539Sslatteng 	register int k;
150816539Sslatteng 
150916539Sslatteng 	if (miny > y[i]) miny = y[i];		/* remember limits */
151016539Sslatteng 	else if (maxy < y[i]) maxy = y[i];
151116539Sslatteng 	if (maxx < x[i]) maxx = x[i];
151216539Sslatteng 	else if (minx > x[i]) minx = x[i];
151316539Sslatteng 
151416539Sslatteng 	j = i;			/* j "points" to the higher (lesser) point */
151516539Sslatteng 	k = ++i;
151616539Sslatteng 	if (x[j] == x[k])		/* ignore vertical lines */
151716539Sslatteng 	    continue;
151816539Sslatteng 
151916539Sslatteng 	if (x[j] > x[k]) {
152016539Sslatteng 	    j++;
152116539Sslatteng 	    k--;
152216539Sslatteng 	}
152316539Sslatteng 	vectptr->next = vectptr + 1;
152416539Sslatteng 	vectptr->param = x[j];		/* starting point of vector */
152516539Sslatteng 	vectptr->dy = y[k] - y[j];	/* line-calculating parameters */
152616539Sslatteng 	vectptr->dx = x[k] - x[j];
152716539Sslatteng 	vectptr->curry = y[j];		/* starting point */
152816539Sslatteng 	(vectptr++)->endx = x[k];	/* ending point */
152916539Sslatteng 	vectptr->prev = vectptr - 1;
153016539Sslatteng     }
153116539Sslatteng 				/* set now because we didn't know minx before */
153216539Sslatteng     leftstipple = topstipple + (minx & mask) * bytewidth;
153316539Sslatteng     bottompage = fill + minx * BYTES_PER_LINE;
153416539Sslatteng     waitinghead->param = minx - 1;
153516539Sslatteng 					/* if no useable vectors, quit */
153616539Sslatteng     if (vectptr == waitinghead + 1)
153716539Sslatteng 	goto leavepoly;
153816539Sslatteng 
153916539Sslatteng     vectptr->param = maxx + 1;		/* dummy entry at end, too */
154016539Sslatteng     vectptr->next = pv( NULL );
154116539Sslatteng 
154216539Sslatteng     activehead = ++vectptr;		/* two dummy entries for active list */
154316539Sslatteng     vectptr->curry = maxy + 1;		/* head */
154416539Sslatteng     vectptr->endx = maxx + 1;
154516539Sslatteng     vectptr->param = vectptr->dx = vectptr->dy = 0;
154616539Sslatteng     activehead->next = ++vectptr;
154716539Sslatteng     activehead->prev = vectptr;
154816539Sslatteng 
154916539Sslatteng     vectptr->prev = activehead;		/* tail */
155016539Sslatteng     vectptr->next = activehead;
155116539Sslatteng     vectptr->curry = miny - 1;
155216539Sslatteng     vectptr->endx = maxx + 1;
155316539Sslatteng     vectptr->param = vectptr->dx = vectptr->dy = 0;
155416539Sslatteng 
155516539Sslatteng 
155616539Sslatteng 			/* main loop -- gets vectors off the waiting list, */
155716539Sslatteng 			/* then displays spans while updating the vectors in */
155816539Sslatteng 			/* the active list */
155916539Sslatteng     while (minx <= maxx) {
156016539Sslatteng 	i = maxx + 1;		/* this is the NEXT time to get a new vector */
156116539Sslatteng 	for (vectptr = waitinghead->next; vectptr != pv( NULL ); ) {
156216539Sslatteng 	    if (minx == vectptr->param) {
156316539Sslatteng 				/* the entry in waiting list (vectptr) is */
156416539Sslatteng 				/*   ready to go into active list.  Need to */
156516539Sslatteng 				/*   convert some vector stuff and sort the */
156616539Sslatteng 				/*   entry into the list. */
156716539Sslatteng 		register polyvector *p;	/* random vector pointers */
156816539Sslatteng 		register polyvector *v;
156916539Sslatteng 
157016539Sslatteng 							/* convert this */
157116539Sslatteng 		if (vectptr->dy < 0)			/* entry to active */
157216539Sslatteng 		    vectptr->param = (vectptr->dy >> 1) - (vectptr->dx >> 1);
157316539Sslatteng 		else
157416539Sslatteng 		    vectptr->param = -((vectptr->dx >> 1) + (vectptr->dy >> 1));
157516539Sslatteng 
157616539Sslatteng 		p = vectptr;			/* remove from the */
157716539Sslatteng 		vectptr = vectptr->next;	/* waiting list */
157816539Sslatteng 		vectptr->prev = p->prev;
157916539Sslatteng 		p->prev->next = vectptr;
158016539Sslatteng 						/* find where it goes */
158116539Sslatteng 						/* in the active list */
158216539Sslatteng 						/* (sorted greatest first) */
158316539Sslatteng 		for (v = activehead->next; v->curry > p->curry; v = v->next)
158416539Sslatteng 		    ;
158516539Sslatteng 		p->next = v;		/* insert into active list */
158616539Sslatteng 		p->prev = v->prev;	/* before the one it stopped on */
158716539Sslatteng 		v->prev = p;
158816539Sslatteng 		p->prev->next = p;
158916539Sslatteng 	    } else {
159016539Sslatteng 		if (i > vectptr->param) {
159116539Sslatteng 		    i = vectptr->param;
159216539Sslatteng 		}
159316539Sslatteng 		vectptr = vectptr->next;
159416539Sslatteng 	    }
159516539Sslatteng 	}
159616539Sslatteng 	nextx = i;
159716539Sslatteng 
159816539Sslatteng 					/* print the polygon while there */
159916539Sslatteng 					/* are no more vectors to add */
160016539Sslatteng 	while (minx < nextx) {
160116539Sslatteng 					/* remove any finished vectors */
160216539Sslatteng 	    vectptr = activehead->next;
160316539Sslatteng 	    do {
160416539Sslatteng 		if (vectptr->endx <= minx) {
160516539Sslatteng 		    vectptr->prev->next = vectptr->next;
160616539Sslatteng 		    vectptr->next->prev = vectptr->prev;
160716539Sslatteng 		}
160816539Sslatteng 	    } while ((vectptr = vectptr->next) != activehead);
160916539Sslatteng 
161016539Sslatteng 					/* draw the span */
161116539Sslatteng 	    if (((unsigned) minx) < NLINES) {
161216539Sslatteng 	      vectptr = activehead->next;
161316539Sslatteng 	      while (vectptr->next != activehead) {
161416539Sslatteng 		register int start;	/* get the beginning */
161516539Sslatteng 		register int length;	/*   and the end of span */
161616539Sslatteng 		register char *glyph;
161716539Sslatteng 		register char *raster;
161816539Sslatteng 
161916539Sslatteng 		start = (RASTER_LENGTH - 1) - vectptr->curry;
162016539Sslatteng 		vectptr = vectptr->next;
162116539Sslatteng 		length = RASTER_LENGTH - vectptr->curry;
162216539Sslatteng 		vectptr = vectptr->next;
162316539Sslatteng 
162416539Sslatteng 					/* bound the polygon to the page */
162516539Sslatteng 		if (start >= RASTER_LENGTH)
162616539Sslatteng 		    break;
162716539Sslatteng 		if (start < 0) start = 0;
162816539Sslatteng 		if (length > RASTER_LENGTH) length = RASTER_LENGTH;
162916539Sslatteng 		length -= start;		/* length is in pixels */
163016539Sslatteng 
163116539Sslatteng 		i = start & 7;
163216539Sslatteng 		start = start >> 3;		/* start is in bytes */
163316539Sslatteng 		raster = bottompage + start;
163416539Sslatteng 		glyph = leftstipple + (start & bytemask);
163516539Sslatteng 
163616539Sslatteng 		if (i) {			/* do any piece of byte */
163716539Sslatteng 		    register char data;		/* that hangs on the front */
163816539Sslatteng 
163916539Sslatteng 		    data = (*(glyph++)) & (0x7f >> --i);
164016539Sslatteng 		    length -= 7 - i;
164116539Sslatteng 		    if (length < 0) {		/* less than one byte wide? */
164216539Sslatteng 			data &= 0xff << -length;
164316539Sslatteng 			length = 0;	/* force clean stoppage */
164416539Sslatteng 		    }
164516539Sslatteng 		    *(raster++) |= data;
164616539Sslatteng 					/* update glyph ptr after first byte */
164716539Sslatteng 		    if (!(++start & bytemask))
164816539Sslatteng 			glyph = leftstipple;
164916539Sslatteng 		}
165016539Sslatteng 						/* fill the line of raster */
165116539Sslatteng 		while ((length -= 8) >= 0) {
165216539Sslatteng 		    *(raster++) |= *(glyph++);
165316539Sslatteng 		    if (!(++start & bytemask))
165416539Sslatteng 			glyph = leftstipple;
165516539Sslatteng 		}
165616539Sslatteng 		if (length & 7) {	/* add any part hanging off the end */
165716539Sslatteng 		    *raster |= (*glyph) & (0xff << -length);
165816539Sslatteng 		}
165916539Sslatteng 	      }
166016539Sslatteng 	    }
166116539Sslatteng 
166216539Sslatteng #ifdef DEBUGABLE
166316539Sslatteng 	    if (dbg) {
166416539Sslatteng 		vectptr = activehead;
166516539Sslatteng 		do {
166616539Sslatteng 		    fprintf (stderr, "%d ", vectptr->curry);
166716539Sslatteng 		    vectptr = vectptr->next;
166816539Sslatteng 		} while (vectptr != activehead);
166916539Sslatteng 	    }
167016539Sslatteng #endif
167116539Sslatteng 					/* update the vectors */
167216539Sslatteng 	    vectptr = activehead->next;
167316539Sslatteng 	    do {
167416539Sslatteng 		if (vectptr->dy > 0) {
167516539Sslatteng 		    while (vectptr->param >= 0) {
167616539Sslatteng 			vectptr->param -= vectptr->dx;
167716539Sslatteng 			vectptr->curry++;
167816539Sslatteng 		    }
167916539Sslatteng 		    vectptr->param += vectptr->dy;
168016539Sslatteng 		} else if (vectptr->dy < 0) {
168116539Sslatteng 		    while (vectptr->param >= 0) {
168216539Sslatteng 			vectptr->param -= vectptr->dx;
168316539Sslatteng 			vectptr->curry--;
168416539Sslatteng 		    }
168516539Sslatteng 		    vectptr->param -= vectptr->dy;
168616539Sslatteng 		}
168716539Sslatteng 					/* must sort the vectors if updates */
168816539Sslatteng 					/* caused them to cross */
168916539Sslatteng 					/* also move to next vector here */
169016539Sslatteng 		if (vectptr->curry > vectptr->prev->curry) {
169116539Sslatteng 		    register polyvector *v;		/* vector to move */
169216539Sslatteng 		    register polyvector *p;	/* vector to put it after */
169316539Sslatteng 
169416539Sslatteng 		    v = vectptr;
169516539Sslatteng 		    p = v->prev;
169616539Sslatteng 		    while (v->curry > p->curry)	/* find the */
169716539Sslatteng 			p = p->prev;		/* right vector */
169816539Sslatteng 
169916539Sslatteng 		    vectptr = vectptr->next;	/* remove from spot */
170016539Sslatteng 		    vectptr->prev = v->prev;
170116539Sslatteng 		    v->prev->next = vectptr;
170216539Sslatteng 
170316539Sslatteng 		    v->prev = p;		/* put in new spot */
170416539Sslatteng 		    v->next = p->next;
170516539Sslatteng 		    p->next = v;
170616539Sslatteng 		    v->next->prev = v;
170716539Sslatteng 		} else {
170816539Sslatteng 		    vectptr = vectptr->next;
170916539Sslatteng 		}
171016539Sslatteng 	    } while (vectptr != activehead);
171116539Sslatteng #ifdef DEBUGABLE
171216539Sslatteng 	    if (dbg) fprintf(stderr, "line done\n");
171316539Sslatteng #endif
171416539Sslatteng 
171516539Sslatteng 	    if (++minx & mask) {
171616539Sslatteng 		leftstipple += bytewidth;
171716539Sslatteng 	    } else {
171816539Sslatteng 		leftstipple = topstipple;
171916539Sslatteng 	    }
172016539Sslatteng 	    bottompage += BYTES_PER_LINE;
172116539Sslatteng 	} /* while (minx < nextx) */
172216539Sslatteng     } /* while (minx <= maxx) */
172316539Sslatteng 
172416539Sslatteng leavepoly:
172516539Sslatteng     nfree(waitinghead);
172616539Sslatteng }  /* polygon function */
1727