1*25330Sslatteng /*	dip.c	1.12	(Berkeley)	85/10/29
214396Sslatteng  *	dip
314396Sslatteng  *	driver for impress/imagen canon laser printer
414396Sslatteng  */
514396Sslatteng 
614396Sslatteng /*
714396Sslatteng output language from troff:
814396Sslatteng all numbers are character strings
914396Sslatteng 
1014396Sslatteng sn	size in points
1114396Sslatteng fn	font as number from 1-n
1216406Sslatteng in	stipple `font' as number from 1-n
1314396Sslatteng cx	ascii character x
1414396Sslatteng Cxyz	funny char xyz. terminated by white space
1514396Sslatteng Hn	go to absolute horizontal position n
1614396Sslatteng Vn	go to absolute vertical position n (down is positive)
1714396Sslatteng hn	go n units horizontally (relative)
1814396Sslatteng vn	ditto vertically
1914396Sslatteng nnc	move right nn, then print c (exactly 2 digits!)
2014396Sslatteng 		(this wart is an optimization that shrinks output file size
2114396Sslatteng 		 about 35% and run-time about 15% while preserving ascii-ness)
2214396Sslatteng Dt ...\n	draw operation 't':
2316406Sslatteng 	Dt d		line thickness set to d
2416406Sslatteng 	Ds d		line style (coordinate bit map) set to d
2514396Sslatteng 	Dl x y		line from here by x,y
2614396Sslatteng 	Dc d		circle of diameter d with left side here
2714396Sslatteng 	De x y		ellipse of axes x,y with left side here
2814396Sslatteng 	Da x y r	arc counter-clockwise by x,y of radius r
2914396Sslatteng 	D~ x y x y ...	wiggly line by x,y then x,y ...
3016406Sslatteng 	Dg x y x y ...	gremlin spline by x,y then x,y ...
3116406Sslatteng 	Dp s x y ...	polygon filled with s by x,y then ...
3216503Sslatteng 	DP s x y ...	unbordered polygon filled with s by x,y then ...
3314396Sslatteng nb a	end of line (information only -- no action needed)
3414396Sslatteng 	b = space before line, a = after
3514967Sslatteng pn	new page begins -- set v to 0
3614396Sslatteng #...\n	comment
3714396Sslatteng x ...\n	device control functions:
3814396Sslatteng 	x i	init
3914396Sslatteng 	x T s	name of device is s
4014396Sslatteng 	x r n h v	resolution is n/inch
4114396Sslatteng 		h = min horizontal motion, v = min vert
4214396Sslatteng 	x p	pause (can restart)
4314396Sslatteng 	x s	stop -- done for ever
4414396Sslatteng 	x t	generate trailer
4514396Sslatteng 	x f n s	font position n contains font s
4614396Sslatteng 	x H n	set character height to n
4714396Sslatteng 	x S n	set slant to N
4814396Sslatteng 
4914396Sslatteng 	Subcommands like "i" are often spelled out like "init".
5014396Sslatteng */
5114396Sslatteng 
5214396Sslatteng #include	<stdio.h>
5314396Sslatteng #include	<signal.h>
5414396Sslatteng #include	<math.h>
5514396Sslatteng #include	<ctype.h>
5614396Sslatteng #include	"dev.h"
5714396Sslatteng #include	"canon.h"
5814967Sslatteng #include	"rst.h"
5914396Sslatteng 
6014396Sslatteng 
6114967Sslatteng /* #define  DEBUGABLE	/* whether or not it'll accept the -d option */
6214967Sslatteng #define  abs(n)		((n) >= 0 ? (n) : -(n))
6314967Sslatteng #define  hmot(n)	hpos += n
6414967Sslatteng #define  hgoto(n)	hpos = n
6514967Sslatteng #define  vmot(n)	vpos += n
6614967Sslatteng #define  vgoto(n)	vpos = n
6714396Sslatteng 
6814967Sslatteng #define	FATAL	1
6914967Sslatteng #define	BMASK	0377
7016406Sslatteng #define	NFONT	35		/* maximum forever */
7114396Sslatteng 
7215736Sslatteng #ifndef FONTDIR
7314967Sslatteng #define FONTDIR	"/usr/lib/font";
7415736Sslatteng #endif
7514967Sslatteng #define BITDIR	"/usr/local/lib/ifontt";
7614967Sslatteng 
7714967Sslatteng 				/* BOTTOMTHRESH and DELTATHRESH are used to */
7814967Sslatteng 				/* search through the glyphs downloaded to */
7914967Sslatteng 				/* determine which ones to keep and which to */
8014967Sslatteng 				/* dump.  They're tested against BOTTOMTHRESH */
8114967Sslatteng 				/* first, then if THAT doesn't release enough */
8214967Sslatteng 				/* space, DELTATHRESH is added until it is. */
8314967Sslatteng #define BOTTOMTHRESH	16
8414967Sslatteng #define DELTATHRESH	16
8514967Sslatteng #define MEMSIZE	70000		/* amount of memory inside imagen */
8614967Sslatteng #define BUFFER	20000		/* imagen memory set aside for page buffer */
8714967Sslatteng #define CHARRAY	128		/* size of character use count array */
8814967Sslatteng 
8914967Sslatteng int	MAXX = (RES*8+RES/3);	/* size of the page... (not 8-1/2" x 11", */
9014967Sslatteng int	MAXY = (RES*10+RES/2+RES/4);		/*  but 8-1/3" x 10-3/4") */
9114967Sslatteng 
9214967Sslatteng int	output	= 0;		/* do we do output at all? */
9314967Sslatteng int	pageno	= -1;		/* output page number */
9414967Sslatteng int	nolist	= 0;		/* output page list if > 0 */
9514967Sslatteng int	olist[20];		/* pairs of page numbers */
9614967Sslatteng 
9714396Sslatteng struct dev dev;
9814396Sslatteng struct font *fontbase[NFONT+1];
9914967Sslatteng short *	pstab;
10014967Sslatteng int	nsizes = 1;
10114396Sslatteng int	nfonts;
10216406Sslatteng int	nstips;
10314396Sslatteng int	nchtab;
10414967Sslatteng char *	chname;
10514967Sslatteng short *	chtab;
10614967Sslatteng unsigned char *	fitab[NFONT+1];		/* legal characters for each font */
10714967Sslatteng unsigned char *	widtab[NFONT+1];	/* width table for each font */
10814967Sslatteng unsigned char *	codetab[NFONT+1];	/* device code translation */
10914967Sslatteng char *	fontname[NFONT+1];		/* what font is on what position? */
11014396Sslatteng 
11114967Sslatteng #ifdef DEBUGABLE
11214396Sslatteng int	dbg	= 0;
11314967Sslatteng #endif
11414396Sslatteng 
11514967Sslatteng FILE *	tf = stdout;		/* output file pointer */
11614967Sslatteng char *	fontdir = FONTDIR;
11714967Sslatteng char *	bitdir = BITDIR;
11814967Sslatteng FILE *	fp = stdin;		/* input file pointer */
11914396Sslatteng 
12014967Sslatteng int	totglyph= 0;		/* total space used by glyphs sent down */
12114967Sslatteng int	maxglyph= MEMSIZE - BUFFER;		/* maximum space for glyphs */
12214967Sslatteng 
12314967Sslatteng int	size = 1;
12414967Sslatteng int	font = 1;
12516406Sslatteng int	stip = 1;
12614967Sslatteng int	family;
12714967Sslatteng int	hpos;		/* current horizontal position (left = 0) */
12814967Sslatteng int	vpos;		/* current vertical position (down positive) */
12914967Sslatteng int	lastw	= 0;	/* width of last input character */
13016503Sslatteng extern int polyborder;		/* flag to turn off borders around a polygon */
13114967Sslatteng 
13214967Sslatteng typedef struct {
13314967Sslatteng 	int	font;
13414967Sslatteng 	int	size;
13516406Sslatteng 	short	first;
13616406Sslatteng 	short	last;
13714967Sslatteng 	unsigned char chused[CHARRAY];	/* test array - character downloaded? */
13814967Sslatteng 	glyph_dir *glyph;		/* array of character descriptions */
13914967Sslatteng 	unsigned char *cdp;		/* char data pointer */
14014967Sslatteng } fontset;
14114967Sslatteng 
14214967Sslatteng fontset	*fs;			/* A global pointer to the current family */
14314967Sslatteng fontset fontdata[NFONT+1];	/* table of family data descripters */
14414967Sslatteng 
14514967Sslatteng int	lastsize	= -1;
14614967Sslatteng int	lastfont	= -1;
14714967Sslatteng int	lastx		= -1;
14814967Sslatteng int	lasty		= -1;
14914967Sslatteng int	lastfam		= -1;
15016406Sslatteng int	laststip	= -1;
15116406Sslatteng int	laststipmem	= -1;
15214967Sslatteng 
15314967Sslatteng 
15414967Sslatteng 
main(argc,argv)15514396Sslatteng main(argc, argv)
15614396Sslatteng char *argv[];
15714396Sslatteng {
15814967Sslatteng 	int i;
15914396Sslatteng 	char *mktemp();
16014967Sslatteng 	char *operand();
16114396Sslatteng 
16214967Sslatteng 	while (--argc > 0 && **++argv == '-') {
16314967Sslatteng 		switch ((*argv)[1]) {
16415278Sslatteng 		case 'X':
16515278Sslatteng 			MAXX = atoi(operand(&argc, &argv));
16615278Sslatteng 			break;
16715278Sslatteng 		case 'Y':
16815278Sslatteng 			MAXY = atoi(operand(&argc, &argv));
16915278Sslatteng 			break;
17014967Sslatteng 		case 'F':
17114967Sslatteng 			fontdir = operand(&argc, &argv);
17214396Sslatteng 			break;
17314396Sslatteng 		case 'f':
17414967Sslatteng 			bitdir = operand(&argc, &argv);
17514396Sslatteng 			break;
17614396Sslatteng 		case 'o':
17714967Sslatteng 			outlist(operand(&argc, &argv));
17814396Sslatteng 			break;
17914396Sslatteng 		case 'b':
18014967Sslatteng 			if ((i = atoi(operand(&argc, &argv))) < 1000) i = 1000;
18114967Sslatteng 			else if (i > MEMSIZE - 1000) i = MEMSIZE - 1000;
18214967Sslatteng 			maxglyph = MEMSIZE - i;
18314396Sslatteng 			break;
18414967Sslatteng #ifdef DEBUGABLE
18514396Sslatteng 		case 'd':
18614967Sslatteng 			dbg = atoi(operand(&argc, &argv));
18714967Sslatteng 			if (dbg == 0) error (FATAL, "no debug value");
18814396Sslatteng 			break;
18914967Sslatteng #endif
19014396Sslatteng 		}
19114396Sslatteng 	}
19214396Sslatteng 
19314967Sslatteng 	if (argc < 1)
19414396Sslatteng 		conv(stdin);
19514396Sslatteng 	else
19614967Sslatteng 		while (argc-- > 0) {
19714967Sslatteng 			if (strcmp(*argv, "-") == 0)
19814396Sslatteng 				fp = stdin;
19914396Sslatteng 			else if ((fp = fopen(*argv, "r")) == NULL)
20014396Sslatteng 				error(FATAL, "can't open %s", *argv);
20114396Sslatteng 			conv(fp);
20214396Sslatteng 			fclose(fp);
20314967Sslatteng 			argv++;
20414396Sslatteng 		}
20514967Sslatteng 
20614396Sslatteng 	t_wrapup();
20714967Sslatteng 	exit(0);
20814967Sslatteng }
20914967Sslatteng 
21014967Sslatteng 
21114967Sslatteng /*----------------------------------------------------------------------------*
21214967Sslatteng  | Routine:	char  * operand (& argc,  & argv)
21314967Sslatteng  |
21414967Sslatteng  | Results:	returns address of the operand given with a command-line
21514967Sslatteng  |		option.  It uses either "-Xoperand" or "-X operand", whichever
21614967Sslatteng  |		is present.  The program is terminated if no option is present.
21714967Sslatteng  |
21814967Sslatteng  | Side Efct:	argc and argv are updated as necessary.
21914967Sslatteng  *----------------------------------------------------------------------------*/
22014967Sslatteng 
operand(argcp,argvp)22114967Sslatteng char *operand(argcp, argvp)
22214967Sslatteng int * argcp;
22314967Sslatteng char ***argvp;
22414967Sslatteng {
22514967Sslatteng 	if ((**argvp)[2]) return(**argvp + 2); /* operand immediately follows */
22614967Sslatteng 	if ((--*argcp) <= 0) {			/* no operand */
22715278Sslatteng 	    error (FATAL, "command-line option operand missing.");
22814396Sslatteng 	}
22914967Sslatteng 	return(*(++(*argvp)));			/* operand next word */
23014396Sslatteng }
23114396Sslatteng 
23214967Sslatteng 
outlist(s)23314396Sslatteng outlist(s)	/* process list of page numbers to be printed */
23415617Sslatteng register char *s;
23514396Sslatteng {
23615617Sslatteng 	register int n1, n2;
23714396Sslatteng 
23814396Sslatteng 	nolist = 0;
23914396Sslatteng 	while (*s) {
24014396Sslatteng 		n1 = 0;
24114396Sslatteng 		if (isdigit(*s))
24214396Sslatteng 			do
24314396Sslatteng 				n1 = 10 * n1 + *s++ - '0';
24414396Sslatteng 			while (isdigit(*s));
24514396Sslatteng 		else
24614396Sslatteng 			n1 = -9999;
24714396Sslatteng 		n2 = n1;
24814396Sslatteng 		if (*s == '-') {
24914396Sslatteng 			s++;
25014396Sslatteng 			n2 = 0;
25114396Sslatteng 			if (isdigit(*s))
25214396Sslatteng 				do
25314396Sslatteng 					n2 = 10 * n2 + *s++ - '0';
25414396Sslatteng 				while (isdigit(*s));
25514396Sslatteng 			else
25614396Sslatteng 				n2 = 9999;
25714396Sslatteng 		}
25814396Sslatteng 		olist[nolist++] = n1;
25914396Sslatteng 		olist[nolist++] = n2;
26014396Sslatteng 		if (*s != '\0')
26114396Sslatteng 			s++;
26214396Sslatteng 	}
26314396Sslatteng 	olist[nolist] = 0;
26414967Sslatteng #ifdef DEBUGABLE
26514396Sslatteng 	if (dbg)
26614396Sslatteng 		for (i=0; i<nolist; i += 2)
26714396Sslatteng 			printf("%3d %3d\n", olist[i], olist[i+1]);
26814967Sslatteng #endif
26914396Sslatteng }
27014396Sslatteng 
27114967Sslatteng 
in_olist(n)27214396Sslatteng in_olist(n)	/* is n in olist? */
27314396Sslatteng int n;
27414396Sslatteng {
27514396Sslatteng 	int i;
27614396Sslatteng 
27714396Sslatteng 	if (nolist == 0)
27814396Sslatteng 		return(1);	/* everything is included */
27914396Sslatteng 	for (i = 0; i < nolist; i += 2)
28014396Sslatteng 		if (n >= olist[i] && n <= olist[i+1])
28114396Sslatteng 			return(1);
28214396Sslatteng 	return(0);
28314396Sslatteng }
28414396Sslatteng 
28514967Sslatteng 
conv(fp)28614396Sslatteng conv(fp)
28714396Sslatteng register FILE *fp;
28814396Sslatteng {
28914967Sslatteng 	register int c;
29014967Sslatteng 	register int k;
29114967Sslatteng 	int m, n, n1, m1;
29214396Sslatteng 	char str[100], buf[300];
29314396Sslatteng 
29414396Sslatteng 	while ((c = getc(fp)) != EOF) {
29514396Sslatteng 		switch (c) {
29614396Sslatteng 		case '\n':	/* when input is text */
29714396Sslatteng 		case ' ':
29814396Sslatteng 		case 0:		/* occasional noise creeps in */
29914396Sslatteng 			break;
30014396Sslatteng 		case '0': case '1': case '2': case '3': case '4':
30114396Sslatteng 		case '5': case '6': case '7': case '8': case '9':
30214396Sslatteng 			/* two motion digits plus a character */
30314396Sslatteng 			hmot((c-'0')*10 + getc(fp)-'0');
30414396Sslatteng 			put1(getc(fp));
30514396Sslatteng 			break;
30614396Sslatteng 		case 'c':	/* single ascii character */
30714396Sslatteng 			put1(getc(fp));
30814396Sslatteng 			break;
30914396Sslatteng 		case 'C':
31014396Sslatteng 			fscanf(fp, "%s", str);
31114396Sslatteng 			put1s(str);
31214396Sslatteng 			break;
31314396Sslatteng 		case 'D':	/* draw function */
31416184Sslatteng 			if (fgets(buf, sizeof(buf), fp) == NULL)
31516184Sslatteng 			    error(FATAL, "unexpected end of input");
31614396Sslatteng 			switch (buf[0]) {
31714396Sslatteng 			case 'l':	/* draw a line */
31814396Sslatteng 				sscanf(buf+1, "%d %d", &n, &m);
31914967Sslatteng 				drawline(n, m, ".");
32014396Sslatteng 				break;
32114396Sslatteng 			case 'c':	/* circle */
32214396Sslatteng 				sscanf(buf+1, "%d", &n);
32314396Sslatteng 				drawcirc(n);
32414396Sslatteng 				break;
32514396Sslatteng 			case 'e':	/* ellipse */
32614396Sslatteng 				sscanf(buf+1, "%d %d", &m, &n);
32714396Sslatteng 				drawellip(m, n);
32814396Sslatteng 				break;
32914396Sslatteng 			case 'a':	/* arc */
33014396Sslatteng 				sscanf(buf+1, "%d %d %d %d", &n, &m, &n1, &m1);
33114396Sslatteng 				drawarc(n, m, n1, m1);
33214396Sslatteng 				break;
33316503Sslatteng 			case 'P':
33416503Sslatteng 				polyborder = 0;		/* borderless polygon */
33516406Sslatteng 			case 'p':	/* polygon */
33616406Sslatteng 				sscanf(buf+1, "%d", &m);/* get stipple */
33716406Sslatteng 				n = 1;			/* number first */
33816406Sslatteng 				while (buf[++n] == ' ');
33916406Sslatteng 				while (isdigit(buf[n])) n++;
34016406Sslatteng 				setfill(m);		/* set up stipple */
34116406Sslatteng 				drawwig(buf+n, fp, -1);	/* draw polygon */
34216503Sslatteng 				polyborder = 1;		/* assume polygons */
34316503Sslatteng 				break;			/*   all have borders */
34416503Sslatteng 
34514396Sslatteng 			case 'g':	/* gremlin curve */
34615617Sslatteng 				drawwig(buf+1, fp, 0);
34715617Sslatteng 				break;
34814396Sslatteng 			case '~':	/* wiggly line */
34915617Sslatteng 				drawwig(buf+1, fp, 1);
35014967Sslatteng 				break;
35115617Sslatteng 			case 't':	/* line-thickness */
35214967Sslatteng 				sscanf(buf+1, "%d", &n);
35314967Sslatteng 				drawthick(n);
35414967Sslatteng 				break;
35515617Sslatteng 			case 's':	/* line-style */
35614967Sslatteng 				sscanf(buf+1, "%d", &n);
35714967Sslatteng 				drawstyle(n);
35814396Sslatteng 				break;
35914396Sslatteng 			default:
36014967Sslatteng 				error(FATAL, "unknown drawing function %s",buf);
36114396Sslatteng 				break;
36214396Sslatteng 			}
36314396Sslatteng 			break;
36414396Sslatteng 		case 's':
36514396Sslatteng 			fscanf(fp, "%d", &n);	/* ignore fractional sizes */
36614396Sslatteng 			setsize(t_size(n));
36714396Sslatteng 			break;
36814396Sslatteng 		case 'f':
36914396Sslatteng 			fscanf(fp, "%s", str);
37014396Sslatteng 			setfont(t_font(str));
37114396Sslatteng 			break;
37216406Sslatteng 		case 'i':
37316406Sslatteng 			fscanf(fp, "%d", &n);
37416406Sslatteng 			setstip(n);
37516406Sslatteng 			break;
37614396Sslatteng 		case 'H':	/* absolute horizontal motion */
37714396Sslatteng 			/* fscanf(fp, "%d", &n); */
37814396Sslatteng 			while ((c = getc(fp)) == ' ')
37914396Sslatteng 				;
38014396Sslatteng 			k = 0;
38114396Sslatteng 			do {
38214396Sslatteng 				k = 10 * k + c - '0';
38314396Sslatteng 			} while (isdigit(c = getc(fp)));
38414396Sslatteng 			ungetc(c, fp);
38514396Sslatteng 			hgoto(k);
38614396Sslatteng 			break;
38714396Sslatteng 		case 'h':	/* relative horizontal motion */
38814396Sslatteng 			/* fscanf(fp, "%d", &n); */
38914396Sslatteng 			while ((c = getc(fp)) == ' ')
39014396Sslatteng 				;
39114396Sslatteng 			k = 0;
39214396Sslatteng 			do {
39314396Sslatteng 				k = 10 * k + c - '0';
39414396Sslatteng 			} while (isdigit(c = getc(fp)));
39514396Sslatteng 			ungetc(c, fp);
39614396Sslatteng 			hmot(k);
39714396Sslatteng 			break;
39814396Sslatteng 		case 'w':	/* word space */
39914396Sslatteng 			break;
40014396Sslatteng 		case 'V':
40114396Sslatteng 			fscanf(fp, "%d", &n);
40214396Sslatteng 			vgoto(n);
40314396Sslatteng 			break;
40414396Sslatteng 		case 'v':
40514396Sslatteng 			fscanf(fp, "%d", &n);
40614396Sslatteng 			vmot(n);
40714396Sslatteng 			break;
40814396Sslatteng 		case 'p':	/* new page */
40914396Sslatteng 			fscanf(fp, "%d", &n);
41014396Sslatteng 			t_page(n);
41114396Sslatteng 			break;
41214396Sslatteng 		case 'n':	/* end of line */
41314967Sslatteng 			hpos = 0;
41416184Sslatteng 
41514396Sslatteng 		case '#':	/* comment */
41616184Sslatteng 			do
41716184Sslatteng 				c = getc(fp);
41816184Sslatteng 			while (c != '\n' && c != EOF);
41914396Sslatteng 			break;
42014396Sslatteng 		case 'x':	/* device control */
42115617Sslatteng 			if (devcntrl(fp)) return;
42214396Sslatteng 			break;
42314396Sslatteng 		default:
42415278Sslatteng 			error(FATAL, "unknown input character %o %c", c, c);
42514396Sslatteng 		}
42614396Sslatteng 	}
42714396Sslatteng }
42814396Sslatteng 
42914967Sslatteng 
devcntrl(fp)43015617Sslatteng int devcntrl(fp)	/* interpret device control functions */
43115617Sslatteng FILE *fp;		/* returns -1 upon "stop" command */
43214396Sslatteng {
43314396Sslatteng         char str[20], str1[50], buf[50];
43414396Sslatteng 	int c, n;
43514396Sslatteng 
43614396Sslatteng 	fscanf(fp, "%s", str);
43714396Sslatteng 	switch (str[0]) {	/* crude for now */
43814396Sslatteng 	case 'i':	/* initialize */
43914396Sslatteng 		fileinit();
44016406Sslatteng 		t_init();
44114396Sslatteng 		break;
44214396Sslatteng 	case 'T':	/* device name */
44314396Sslatteng 	case 't':	/* trailer */
44414396Sslatteng 	case 'p':	/* pause -- can restart */
44515617Sslatteng 		break;
44614396Sslatteng 	case 's':	/* stop */
44715617Sslatteng 		return -1;
44814396Sslatteng 	case 'r':	/* resolution assumed when prepared */
44914967Sslatteng 		fscanf(fp, "%d", &n);
45016503Sslatteng 		if (n!=RES) error(FATAL,"Input computed for wrong printer");
45114396Sslatteng 		break;
45214396Sslatteng 	case 'f':	/* font used */
45314396Sslatteng 		fscanf(fp, "%d %s", &n, str);
45414396Sslatteng 		fgets(buf, sizeof buf, fp);	/* in case there's a filename */
45514396Sslatteng 		ungetc('\n', fp);	/* fgets goes too far */
45614396Sslatteng 		str1[0] = 0;	/* in case there's nothing to come in */
45714396Sslatteng 		sscanf(buf, "%s", str1);
45814396Sslatteng 		loadfont(n, str, str1);
45914396Sslatteng 		break;
46014396Sslatteng 	case 'H':	/* char height */
46114396Sslatteng 		fscanf(fp, "%d", &n);
46214396Sslatteng 		t_charht(n);
46314396Sslatteng 		break;
46414396Sslatteng 	case 'S':	/* slant */
46514396Sslatteng 		fscanf(fp, "%d", &n);
46614396Sslatteng 		t_slant(n);
46714396Sslatteng 		break;
46814396Sslatteng 	}
46914396Sslatteng 	while ((c = getc(fp)) != '\n')	/* skip rest of input line */
47014396Sslatteng 		if (c == EOF)
47115617Sslatteng 			return -1;
47215617Sslatteng 	return 0;
47314396Sslatteng }
47414396Sslatteng 
47514967Sslatteng 
fileinit()47614396Sslatteng fileinit()	/* read in font and code files, etc. */
47714396Sslatteng {
47814967Sslatteng 	register int i;
47914967Sslatteng 	register int fin;
48014967Sslatteng 	register int nw;
48114967Sslatteng 	register unsigned char *filebase;
48214967Sslatteng 	register unsigned char *p;
48314967Sslatteng 	unsigned char *malloc();
48414967Sslatteng 	char temp[100];
48514396Sslatteng 
48614967Sslatteng 		/* open table for device,
48714967Sslatteng 		 * read in resolution, size info, font info, etc.
48814967Sslatteng 		 * and set params
48914967Sslatteng 		 */
49014396Sslatteng 
49114967Sslatteng 	sprintf(temp, "%s/devip/DESC.out", fontdir);
49214396Sslatteng 	if ((fin = open(temp, 0)) < 0)
49314396Sslatteng 		error(FATAL, "can't open tables for %s", temp);
49414396Sslatteng 	read(fin, &dev, sizeof(struct dev));
49514396Sslatteng 	nfonts = dev.nfonts;
49616406Sslatteng 	nstips = dev.nstips;
49714396Sslatteng 	nsizes = dev.nsizes;
49814396Sslatteng 	nchtab = dev.nchtab;
49914396Sslatteng 	filebase = malloc(dev.filesize);	/* enough room for whole file */
50014396Sslatteng 	read(fin, filebase, dev.filesize);	/* all at once */
50114396Sslatteng 	pstab = (short *) filebase;
50214396Sslatteng 	chtab = pstab + nsizes + 1;
50314396Sslatteng 	chname = (char *) (chtab + dev.nchtab);
50414967Sslatteng 	p = (unsigned char *) chname + dev.lchname;
50514967Sslatteng 	for (i = 1; i <= nfonts; i++) {
50614967Sslatteng 		fontbase[i] = (struct font *) p;
50714967Sslatteng 		nw = *p & BMASK;		/* 1st thing is width count */
50814967Sslatteng 		p += sizeof(struct font);
50914967Sslatteng 		widtab[i] = p;			/* then width table */
51014967Sslatteng 		codetab[i] = p + 2 * nw;	/* then code conversion table */
51114967Sslatteng 		fitab[i] = p + 3 * nw;		/* then font inclusion table */
51214967Sslatteng 		p += 3 * nw + dev.nchtab + 128 - 32;
51314967Sslatteng 		t_fp(i, fontbase[i]->namefont, fontbase[i]->intname);
51414967Sslatteng #ifdef DEBUGABLE
51514967Sslatteng 		if (dbg > 1) fontprint(i);
51614967Sslatteng #endif
51714396Sslatteng 	}
51816406Sslatteng 	for (i = 1; i <= nstips; i++) {		/* add in Stipple "filenames" */
51916406Sslatteng 		if (nfonts + i <= NFONT)
52016406Sslatteng 		    t_fp(nfonts + i, p, (char *)0);
52116406Sslatteng 		p += strlen(p) + 1;
52216406Sslatteng 	}
52314967Sslatteng 	fontbase[0] = NULL;
52414967Sslatteng 	close(fin);				/* no fonts loaded yet */
52514967Sslatteng 	for (i = 0; i <= NFONT; i++) fontdata[i].font = fontdata[i].size = -1;
52614396Sslatteng }
52714396Sslatteng 
52814967Sslatteng 
52914967Sslatteng #ifdef DEBUGABLE
fontprint(i)53014396Sslatteng fontprint(i)	/* debugging print of font i (0,...) */
53114396Sslatteng {
53214967Sslatteng 	int j, n;
53314396Sslatteng 	char *p;
53414396Sslatteng 
53514396Sslatteng 	printf("font %d:\n", i);
53614396Sslatteng 	p = (char *) fontbase[i];
53714396Sslatteng 	n = fontbase[i]->nwfont & BMASK;
53814396Sslatteng 	printf("base=0%o, nchars=%d, spec=%d, name=%s, widtab=0%o, fitab=0%o\n",
53914967Sslatteng 		p, n, fontbase[i]->specfont, fontbase[i]->namefont, widtab[i], fitab[i]);
54014396Sslatteng 	printf("widths:\n");
54114396Sslatteng 	for (j=0; j <= n; j++) {
54214967Sslatteng 		printf(" %2d", widtab[i][j] & BMASK);
54314396Sslatteng 		if (j % 20 == 19) printf("\n");
54414396Sslatteng 	}
54514396Sslatteng 	printf("\ncodetab:\n");
54614396Sslatteng 	for (j=0; j <= n; j++) {
54714396Sslatteng 		printf(" %2d", codetab[i][j] & BMASK);
54814396Sslatteng 		if (j % 20 == 19) printf("\n");
54914396Sslatteng 	}
55014396Sslatteng 	printf("\nfitab:\n");
55114396Sslatteng 	for (j=0; j <= dev.nchtab + 128-32; j++) {
55214396Sslatteng 		printf(" %2d", fitab[i][j] & BMASK);
55314396Sslatteng 		if (j % 20 == 19) printf("\n");
55414396Sslatteng 	}
55514396Sslatteng 	printf("\n");
55614396Sslatteng }
55714967Sslatteng #endif
55814396Sslatteng 
55914967Sslatteng 
loadfont(n,s,s1)56014396Sslatteng loadfont(n, s, s1)	/* load font info for font s on position n (0...) */
56114396Sslatteng int n;
56214396Sslatteng char *s, *s1;
56314396Sslatteng {
56414396Sslatteng 	char temp[60];
56514967Sslatteng 	int fin, nw;
56614396Sslatteng 
56714396Sslatteng 	if (n < 0 || n > NFONT)
56814396Sslatteng 		error(FATAL, "illegal fp command %d %s", n, s);
56914396Sslatteng 	if (fontbase[n] != NULL && strcmp(s, fontbase[n]->namefont) == 0)
57014396Sslatteng 		return;
57116428Sslatteng 
57216428Sslatteng 	for (fin = 1; fin <= NFONT; fin++)	/* first check to see if the */
57316428Sslatteng 	    if (strcmp(s, fontbase[fin]->namefont) == 0) {  /* font is loaded */
57416428Sslatteng 		register unsigned char *c;		    /* somewhere else */
57516428Sslatteng 
57616428Sslatteng #define ptrswap(x, y) { c = (unsigned char*) (x); x = y; y = c; }
57716428Sslatteng #define ptrfswap(x, y) { c=(unsigned char*)(x); x = y; y = (struct font *) c; }
57816428Sslatteng 
57916428Sslatteng 		ptrfswap(fontbase[n], fontbase[fin]);
58016428Sslatteng 		ptrswap(codetab[n], codetab[fin]);
58116428Sslatteng 		ptrswap(widtab[n], widtab[fin]);
58216428Sslatteng 		ptrswap(fitab[n], fitab[fin]);
58316428Sslatteng 		t_fp(n, fontbase[n]->namefont, fontbase[n]->intname);
58416428Sslatteng 		t_fp(fin, fontbase[fin]->namefont, fontbase[fin]->intname);
58516428Sslatteng 		return;
58616428Sslatteng 	    }
58716428Sslatteng 
58814396Sslatteng 	if (s1 == NULL || s1[0] == '\0')
58914967Sslatteng 		sprintf(temp, "%s/devip/%s.out", fontdir, s);
59014396Sslatteng 	else
59114396Sslatteng 		sprintf(temp, "%s/%s.out", s1, s);
59214396Sslatteng 	if ((fin = open(temp, 0)) < 0) {
59314396Sslatteng 		error(!FATAL, "can't open font table %s", temp);
59414396Sslatteng 		return;
59514396Sslatteng 	}
59614396Sslatteng 	if (fontbase[n] != NULL)
59714396Sslatteng 		free(fontbase[n]);
59814396Sslatteng 	fontbase[n] = (struct font *) malloc(3*255 + dev.nchtab +
59914396Sslatteng 				(128-32) + sizeof(struct font));
60014396Sslatteng 	if (fontbase[n] == NULL)
60114396Sslatteng 		error(FATAL, "Out of space in loadfont %s", s);
60214396Sslatteng 	read(fin, fontbase[n], 3*255 + nchtab+128-32 + sizeof(struct font));
60314396Sslatteng 	close(fin);
60414396Sslatteng 	nw = fontbase[n]->nwfont & BMASK;
60514967Sslatteng 	widtab[n] = (unsigned char *) fontbase[n] + sizeof(struct font);
60614967Sslatteng 	codetab[n] = (unsigned char *) widtab[n] + 2 * nw;
60714967Sslatteng 	fitab[n] = (unsigned char *) widtab[n] + 3 * nw;
60814396Sslatteng 	t_fp(n, fontbase[n]->namefont, fontbase[n]->intname);
60914967Sslatteng #ifdef DEBUGABLE
61014396Sslatteng 	if (dbg > 1) fontprint(n);
61114967Sslatteng #endif
61214396Sslatteng }
61314396Sslatteng 
61414967Sslatteng 
61514967Sslatteng /*VARARGS2*/
error(f,s,a1,a2,a3,a4,a5,a6,a7)61614967Sslatteng error(f, s, a1, a2, a3, a4, a5, a6, a7)
61714967Sslatteng int f;
61814967Sslatteng char *s;
61914396Sslatteng {
62014396Sslatteng 	fprintf(stderr, "dip: ");
62114396Sslatteng 	fprintf(stderr, s, a1, a2, a3, a4, a5, a6, a7);
62214396Sslatteng 	fprintf(stderr, "\n");
62314396Sslatteng 	if (f)
62415278Sslatteng 		exit(2);
62514396Sslatteng }
62614396Sslatteng 
62714396Sslatteng 
t_init()62816406Sslatteng t_init()	/* initialize device */
62914396Sslatteng {
63016406Sslatteng 	drawthick(3);		/* set the line thickness parameter */
63114396Sslatteng 	hpos = vpos = 0;
63214396Sslatteng 	setsize(t_size(10));	/* start somewhere */
63314396Sslatteng }
63414396Sslatteng 
63514396Sslatteng 
63614967Sslatteng /*----------------------------------------------------------------------------*
63714967Sslatteng  | Routine:	t_page ( page_number )
63814967Sslatteng  |
63914967Sslatteng  | Results:	mark this page done for printing.  If we think we've filled
64014967Sslatteng  |		the imagen too much, delete some of the info in the glyph cache.
64114967Sslatteng  |		This is a good time to do this since it's at the end of a page
64214967Sslatteng  |		and will get done every so often.
64314967Sslatteng  *----------------------------------------------------------------------------*/
64414967Sslatteng 
t_page(pg)64514396Sslatteng t_page(pg)	/* do whatever new page functions */
64614396Sslatteng {
64714967Sslatteng 	register int i;
64814967Sslatteng 	register int threshold;
64914396Sslatteng 
65014396Sslatteng 	pageno = pg;
65114967Sslatteng #ifdef DEBUGABLE
65214396Sslatteng 	if(dbg)fprintf(stderr, "t_page %d, output=%d\n", pg, output);
65314967Sslatteng #endif
65414967Sslatteng 	if (output != 0)
65514396Sslatteng 		putc(AEND, tf);
65614396Sslatteng 	output = in_olist(pg);
65714967Sslatteng 
65814396Sslatteng 	if (output) {
65914967Sslatteng 	    threshold = BOTTOMTHRESH;
66014967Sslatteng 	    while (totglyph >= maxglyph) {
66114967Sslatteng 		for (i = 0; i < NFONT; i++) {
66214967Sslatteng 		    if (fontdata[i].font != -1)
66314967Sslatteng 			clearglyphs(i, threshold);
66414396Sslatteng 		}
66514967Sslatteng 		threshold += DELTATHRESH;
66614967Sslatteng 	    }
66714396Sslatteng 	}
66814396Sslatteng 	lastx = lasty = -1;
66916406Sslatteng 	hpos = vpos = 0;
67014396Sslatteng }
67114396Sslatteng 
67214396Sslatteng 
t_size(n)67314396Sslatteng t_size(n)	/* convert integer to internal size number*/
67414396Sslatteng int n;
67514396Sslatteng {
67614396Sslatteng 	int i;
67714396Sslatteng 
67814396Sslatteng 	if (n <= pstab[0])
67916406Sslatteng 		return(0);
68014396Sslatteng 	else if (n >= pstab[nsizes-1])
68114967Sslatteng 		return(nsizes-1);
68214396Sslatteng 	for (i = 0; n > pstab[i]; i++)
68314396Sslatteng 		;
68414967Sslatteng 	return(i);
68514396Sslatteng }
68614396Sslatteng 
68714967Sslatteng 
t_charht(n)68814396Sslatteng t_charht(n)	/* set character height to n */
68914396Sslatteng int n;
69014396Sslatteng {
69114396Sslatteng 	/* punt for now */
69214396Sslatteng }
69314396Sslatteng 
69414967Sslatteng 
t_slant(n)69514396Sslatteng t_slant(n)	/* set slant to n */
69614396Sslatteng int n;
69714396Sslatteng {
69814396Sslatteng 	/* punt for now */
69914396Sslatteng }
70014396Sslatteng 
70114967Sslatteng 
t_font(s)70214396Sslatteng t_font(s)	/* convert string to internal font number */
70314396Sslatteng char *s;
70414396Sslatteng {
70514396Sslatteng 	int n;
70614396Sslatteng 
70714396Sslatteng 	n = atoi(s);
70814396Sslatteng 	if (n < 0 || n > nfonts)
70914396Sslatteng 		n = 1;
71014396Sslatteng 	return(n);
71114396Sslatteng }
71214396Sslatteng 
71314396Sslatteng 
t_wrapup()71414396Sslatteng t_wrapup()
71514396Sslatteng {
71614396Sslatteng 	putc(AEND, tf);
71714396Sslatteng 	putc(AEOF, tf);
71814396Sslatteng }
71914396Sslatteng 
72014396Sslatteng 
put1s(s)72114396Sslatteng put1s(s)	/* s is a funny char name */
72214967Sslatteng register char *s;
72314396Sslatteng {
72414396Sslatteng 	static int i = 0;
72514396Sslatteng 
72614396Sslatteng 	if (!output)
72714396Sslatteng 		return;
72814967Sslatteng #ifdef DEBUGABLE
72914396Sslatteng 	if (dbg) printf("%s ", s);
73014967Sslatteng #endif
73114396Sslatteng 	if (strcmp(s, &chname[chtab[i]]) != 0)
73214396Sslatteng 		for (i = 0; i < nchtab; i++)
73314396Sslatteng 			if (strcmp(&chname[chtab[i]], s) == 0)
73414396Sslatteng 				break;
73514396Sslatteng 	if (i < nchtab)
73614396Sslatteng 		put1(i + 128);
73714396Sslatteng 	else
73814396Sslatteng 		i = 0;
73914396Sslatteng }
74014396Sslatteng 
74114967Sslatteng 
put1(c)74214396Sslatteng put1(c)	/* output char c */
74314967Sslatteng register int c;
74414396Sslatteng {
74514967Sslatteng 	register unsigned char *pw;
74614967Sslatteng 	register unsigned char *p;
74714967Sslatteng 	register int i;
74814967Sslatteng 	register int j;
74914967Sslatteng 	register int k;
75014967Sslatteng 	int ofont, code;
75114396Sslatteng 
75214396Sslatteng 	if (!output)
75314396Sslatteng 		return;
75414396Sslatteng 	c -= 32;
75514396Sslatteng 	if (c <= 0) {
75614967Sslatteng #ifdef DEBUGABLE
75714396Sslatteng 		if (dbg) printf("non-exist 0%o\n", c+32);
75814967Sslatteng #endif
75914396Sslatteng 		return;
76014396Sslatteng 	}
76114967Sslatteng 	ofont = font;
76214967Sslatteng 	i = fitab[font][c];
76314396Sslatteng 	if (i != 0) {	/* it's on this font */
76414396Sslatteng 		p = codetab[font];
76514967Sslatteng 		pw = widtab[font];
76614967Sslatteng 	} else {		/* on another font */
76715278Sslatteng 		k = font;	/* start with current, then run down the list */
76814967Sslatteng 		for (j=0; j++ <= nfonts; k = (k+1) % (nfonts+1))
76914967Sslatteng 			if (fontbase[k] != NULL && (i = fitab[k][c]) != 0) {
77014396Sslatteng 				p = codetab[k];
77114967Sslatteng 				pw = widtab[k];
77214396Sslatteng 				setfont(k);
77314396Sslatteng 				break;
77414396Sslatteng 			}
77514396Sslatteng 	}
77614967Sslatteng 	code = p[i] & BMASK;
77714967Sslatteng 	if (i == 0) {
77814967Sslatteng #ifdef DEBUGABLE
77914396Sslatteng 		if (dbg) printf("not found 0%o\n", c+32);
78014967Sslatteng #endif
78114396Sslatteng 		return;
78214396Sslatteng 	}
78314967Sslatteng 	lastw = (pw[i] * pstab[size] + dev.unitwidth/2) / dev.unitwidth;
78414967Sslatteng #ifdef DEBUGABLE
78514396Sslatteng 	if (dbg) {
78614396Sslatteng 		if (isprint(c+32))
78714396Sslatteng 			printf("%c %d\n", c+32, code);
78814396Sslatteng 		else
78914396Sslatteng 			printf("%03o %d\n", c+32, code);
79014396Sslatteng 	} else
79114967Sslatteng #endif
79214967Sslatteng 		if (output) xychar(code);
79314396Sslatteng 	if (font != ofont)
79414396Sslatteng 		setfont(ofont);
79514396Sslatteng }
79614396Sslatteng 
79714967Sslatteng 
setsize(n)79814396Sslatteng setsize(n)	/* set point size to n (internal) */
79914396Sslatteng int n;
80014396Sslatteng {
80114396Sslatteng 	size = n;
80214396Sslatteng }
80314396Sslatteng 
80414396Sslatteng 
80514967Sslatteng /*----------------------------------------------------------------------------*
80614967Sslatteng  | Routine:	t_fp ( number, string, string_internal )
80714967Sslatteng  |
80814967Sslatteng  | Results:	font position number now contains font 'string', internal
80914967Sslatteng  |		font name (number) is ignored.
81014967Sslatteng  |
81114967Sslatteng  | Side Efct:	any fonts loaded into fontdata with this font number are
81214967Sslatteng  |		removed.  And, to make sure they're not accessed, if lastfont
81314967Sslatteng  |		equals number, it is "disabled" by setting lastfont to -1.
81414967Sslatteng  *----------------------------------------------------------------------------*/
81514396Sslatteng 
t_fp(n,s,si)81614967Sslatteng t_fp(n, s, si)
81714396Sslatteng int n;
81814396Sslatteng char *s, *si;
81914396Sslatteng {
82014967Sslatteng 	register int i;
82114967Sslatteng 
82214967Sslatteng 	fontname[n] = s;
82314967Sslatteng 	for (i = 0; i <= NFONT; i++)		/* release any font files */
82414967Sslatteng 		if (fontdata[i].font == n) {	/* for this font */
82514967Sslatteng 			clearglyphs (i, 1000);
82614967Sslatteng 			putc(AFORCE, tf);
82714967Sslatteng 			free (fontdata[i].cdp);
82814967Sslatteng 			free (fontdata[i].glyph);
82914967Sslatteng 			fontdata[i].font = -1;
83014967Sslatteng 		}
83114967Sslatteng 	if (n == lastfont) lastfont = -1;
83214396Sslatteng }
83314396Sslatteng 
83414967Sslatteng 
setfont(n)83514396Sslatteng setfont(n)	/* set font to n */
83614396Sslatteng int n;
83714396Sslatteng {
83814396Sslatteng 	if (!output)
83914396Sslatteng 		return;
84016406Sslatteng 	if (n < 0 || n > nfonts)
84114396Sslatteng 		error(FATAL, "illegal font %d", n);
84214396Sslatteng 	font = n;
84314396Sslatteng }
84414396Sslatteng 
84514967Sslatteng 
setstip(n)84616406Sslatteng setstip(n)	/* set stipple "font" to n */
84716406Sslatteng int n;
84816406Sslatteng {
84916406Sslatteng 	if (!output)
85016406Sslatteng 		return;
85116406Sslatteng 	if (n < 1 || n > nstips)
85216406Sslatteng 		error(FATAL, "illegal stipple %d", n);
85316406Sslatteng 	stip = n;
85416406Sslatteng }
85516406Sslatteng 
85616406Sslatteng 
85714967Sslatteng /*----------------------------------------------------------------------------*
85814967Sslatteng  | Routine:	rd1, rd2, rd3, rd4 ( file_pointer )
85914967Sslatteng  |
86014967Sslatteng  | Results:	gets one, two three or four bytes from a file and interprets
86114967Sslatteng  |		them as integers.  Most significant bytes come first.
86214967Sslatteng  *----------------------------------------------------------------------------*/
86314967Sslatteng 
rd1(fp)86414967Sslatteng int rd1(fp)
86514967Sslatteng FILE *fp;
86614396Sslatteng {
86714967Sslatteng     register int i;
86814967Sslatteng 
86914967Sslatteng     if((i = getc(fp)) == EOF) error(FATAL, "font file read error");
87014967Sslatteng     return i;
87114396Sslatteng }
87214396Sslatteng 
rd2(fp)87314967Sslatteng int rd2(fp)
87414967Sslatteng FILE *fp;
87514967Sslatteng {
87614967Sslatteng     register short i = rd1(fp) << 8;
87714396Sslatteng 
87814967Sslatteng     return i | rd1(fp);
87914967Sslatteng }
88014396Sslatteng 
rd3(fp)88114967Sslatteng int rd3(fp)
88214967Sslatteng FILE *fp;
88314967Sslatteng {
88414967Sslatteng     register int i = rd2(fp) << 8;
88514396Sslatteng 
88614967Sslatteng     return i | rd1(fp);
88714967Sslatteng }
88814396Sslatteng 
rd4(fp)88914967Sslatteng int rd4(fp)
89014967Sslatteng FILE *fp;
89114396Sslatteng {
89214967Sslatteng     register int i = rd2(fp) << 16;
89314396Sslatteng 
89414967Sslatteng     return i | rd2(fp);
89514396Sslatteng }
89614396Sslatteng 
89714967Sslatteng 
89814967Sslatteng /*----------------------------------------------------------------------------*
89914967Sslatteng  | Routine:	getfontdata ( font, size )
90014967Sslatteng  |
901*25330Sslatteng  | Results:	returns the family number of the font/size found.  If the
902*25330Sslatteng  |		particular point size requested is not found, other sizes are
903*25330Sslatteng  |		searched for.  The font information pointer, fs, is set to
904*25330Sslatteng  |		point to data for "font" at point size "size".  If no infor-
905*25330Sslatteng  |		mation for that font is available, the info is read in from
906*25330Sslatteng  |		the appropriate font file.  The table "fontdata" holds all the
907*25330Sslatteng  |		fonts, and it is cleared of a random font/size if necessary.
90814967Sslatteng  *----------------------------------------------------------------------------*/
90914967Sslatteng 
getfontdata(f,s)91014967Sslatteng int getfontdata(f, s)
91114967Sslatteng int f;
91214967Sslatteng int s;
91314396Sslatteng {
91414396Sslatteng 	char name[100];
91514967Sslatteng 	register FILE *fd;
91614967Sslatteng 	register int i;
91714967Sslatteng 	register int fam;
91814967Sslatteng 	register int bitbase;
91914967Sslatteng 	register glyph_dir *maxgp;
92014967Sslatteng 	register glyph_dir *gp;
92114967Sslatteng 	preamble p;
92214396Sslatteng 
92314967Sslatteng 				/* first check if it's here already */
92414967Sslatteng 	for (fam = 0; fam <= NFONT; fam++)
92514967Sslatteng 	    if (fontdata[fam].font == f && fontdata[fam].size == s) {
92614967Sslatteng 		fs = &fontdata[fam];
92714967Sslatteng 		return (fam);
92814967Sslatteng 	    }
92914967Sslatteng 						/* find an empty slot */
93014967Sslatteng 	for (fam = 0; fam < NFONT && fontdata[fam].font != -1; fam++);
93114967Sslatteng 	fs = &fontdata[fam];
93214967Sslatteng 	if (fs->font != -1) {		/* clear a slot if not empty */
93314967Sslatteng 		clearglyphs(fam, 1000);		/* dumb version - always take */
93414967Sslatteng 		putc(AFORCE, tf);		/* the last one to replace */
93514967Sslatteng 		free(fs->glyph);
93614967Sslatteng 		free(fs->cdp);
93714396Sslatteng 	}
938*25330Sslatteng 
939*25330Sslatteng 	bitbase = s;
940*25330Sslatteng 			/* try to open font file - if unsuccessful, hunt for */
941*25330Sslatteng 			/* a file of same style, different size to substitute */
942*25330Sslatteng 	i = -1;	 /* direction to look in pstab (smaller first) */
943*25330Sslatteng 	do {
944*25330Sslatteng 	    sprintf(name, "%s/%s.%d", bitdir, fontname[f], pstab[bitbase]);
945*25330Sslatteng 	    fd = fopen(name, "r");
946*25330Sslatteng 	    if (fd == NULL) {		/* File wasn't found. Try another ps */
947*25330Sslatteng 		bitbase += i;
948*25330Sslatteng 		if (bitbase < 0) {	/* past beginning - look higher */
949*25330Sslatteng 		    i = 1;
950*25330Sslatteng 		    bitbase = s + i;
951*25330Sslatteng 		}
952*25330Sslatteng 		if (bitbase > nsizes)	/* past top - forget it */
953*25330Sslatteng 		    i = 0;
954*25330Sslatteng 	    }
955*25330Sslatteng 	} while (fd == NULL && i != 0);
956*25330Sslatteng 
957*25330Sslatteng 	if (fd == NULL)			/* completely unsuccessful */
958*25330Sslatteng 		error(FATAL,"can't open %s/%s.%d",bitdir,fontname[f],pstab[s]);
95914967Sslatteng 						/* check for proper file mark */
96015278Sslatteng 	for(i = 0; i < FMARK; filemark[i++] = getc(fd));
96115278Sslatteng 	if (strncmp(filemark, "Rast", 4))
96214967Sslatteng 		error(FATAL, "bad File Mark in %s.", name);
96314967Sslatteng 					/* get preamble */
96414967Sslatteng 	p.p_size = rd2(fd);
96514967Sslatteng 	p.p_version = rd1(fd);
96614967Sslatteng 	if (p.p_version)
96714967Sslatteng 		error(FATAL, "wrong version of Font file: %s.", name);
96814967Sslatteng 	p.p_glyph = rd3(fd);
96916406Sslatteng 	fs->first = p.p_first = rd2(fd);
97016406Sslatteng 	fs->last = p.p_last = rd2(fd);
97114967Sslatteng 				/* skip rest of preamble */
97214967Sslatteng 	i = p.p_glyph - 18;
97314967Sslatteng 	while (i--) getc(fd);
97414967Sslatteng 	fs->glyph = (glyph_dir *)	/* allocate first */
97514967Sslatteng 		((char *) malloc((p.p_last - p.p_first + 1) * sizeof(glyph_dir))
97614967Sslatteng 		- (char *) (p.p_first * sizeof(glyph_dir)));
97716406Sslatteng 	maxgp = gp = &(fs->glyph[p.p_first]);
97816406Sslatteng 	bitbase = maxgp->g_bitp;
97914967Sslatteng 	for (i = p.p_first; i++ <= p.p_last; gp++) {
98014967Sslatteng 	    gp->g_height = rd2(fd);
98114967Sslatteng 	    gp->g_width = rd2(fd);
98214967Sslatteng 	    gp->g_up = rd2(fd);
98314967Sslatteng 	    gp->g_left = rd2(fd);
98414967Sslatteng 	    gp->g_pwidth = rd4(fd);
98514967Sslatteng 	    if ((gp->g_bitp = rd3(fd)) > maxgp->g_bitp)	/* find the glyphs */
98616406Sslatteng 		maxgp = gp;				/* farthest from and */
98716406Sslatteng 	    else if(gp->g_bitp < bitbase)		/* nearest to the */
98816406Sslatteng 		bitbase = gp->g_bitp;			/* start of the file */
98914967Sslatteng 	}
99016406Sslatteng 					/* remove file offset in bit pointers */
99114967Sslatteng 	for (gp = fs->glyph, i = p.p_first; i++ <= p.p_last; gp++)
99214967Sslatteng 	    gp->g_bitp -= bitbase;
99314396Sslatteng 
99414967Sslatteng 	i = maxgp->g_bitp + maxgp->g_height * ((maxgp->g_width + 7) / 8);
99514967Sslatteng 	fs->cdp = (unsigned char *) malloc(i);
99614967Sslatteng 	lseek(fileno(fd), (long) bitbase, 0);
99714967Sslatteng 	if (read(fileno (fd), fs->cdp, i) != i)
99814967Sslatteng 		error(FATAL, "can't read in %s", name);
99914967Sslatteng 	fclose(fd);
100014396Sslatteng 
100114967Sslatteng 	fs->size = s;
100214967Sslatteng 	fs->font = f;
100314967Sslatteng 	for (i = 0; i < CHARRAY; fs->chused[i++] = 0);
100414967Sslatteng 	return (fam);
100514396Sslatteng }
100614396Sslatteng 
100714967Sslatteng 
100816406Sslatteng /*----------------------------------------------------------------------------*
100916406Sslatteng  | Routine:	setfill(stipple_number)
101016406Sslatteng  |
101116406Sslatteng  | Results:	sends the appropriate command to set the fill-pattern
101216406Sslatteng  |		for a particular stipple.  Sends the glyph if necessary,
101316406Sslatteng  |		and does nothing if the pattern is the same.  Takes stipple
101416406Sslatteng  |		font from current "stip" number.
101516406Sslatteng  *----------------------------------------------------------------------------*/
101616406Sslatteng 
setfill(number)101716406Sslatteng setfill(number)
101816406Sslatteng register int number;
101916406Sslatteng {
102016406Sslatteng 	register int fam;
102116406Sslatteng 	register int gsize;
102216406Sslatteng 	register glyph_dir *par;
102316406Sslatteng 	register unsigned char *p;
102416406Sslatteng 	register fontset *savefs;
102516406Sslatteng 
102616406Sslatteng 	if (stip == laststip && number == laststipmem)
102716406Sslatteng 		return;
102816406Sslatteng 
102916406Sslatteng 	savefs = fs;			/* getfontdata sets fs, so we have to */
103016406Sslatteng 					/* save it before calling getfontdata */
103116406Sslatteng 	fam = getfontdata(nfonts + stip, nsizes);
103216406Sslatteng 	laststip = stip;
103316406Sslatteng 	laststipmem = number;		/* must be set before call to polygon */
103416406Sslatteng 
103516406Sslatteng 	if (!number || number < fs->first || number > fs->last) {
103616555Sslatteng nostipbits:
103716406Sslatteng 		fs = savefs;		/* forget it if it's out of range */
103816406Sslatteng 		laststipmem = 0;	/* force NO stipple */
103916406Sslatteng 		return;
104016406Sslatteng 	}
104116406Sslatteng 	if (fs->chused[number] == 0) {		/* stipple not down-loaded */
104216555Sslatteng 		par = &(fs->glyph[number]);
104316555Sslatteng 		if (!par->g_bitp)
104416555Sslatteng 		    goto nostipbits;
104516555Sslatteng 		totglyph += glspace(par);
104616406Sslatteng 		putc(ABGLY, tf);
104716406Sslatteng 		putint((fam << 7) | number, tf);
104816406Sslatteng  		putint(par->g_pwidth, tf);
104916406Sslatteng 		putint(par->g_width, tf);
105016406Sslatteng 		putint(par->g_left, tf);
105116406Sslatteng 		putint(par->g_height, tf);
105216406Sslatteng 		putint(par->g_up, tf);
105316406Sslatteng 		gsize = ((par->g_width + 7)/8) * par->g_height;
105416406Sslatteng 		p = fs->cdp + par->g_bitp;
105516406Sslatteng 		while (gsize--)
105616406Sslatteng 			putc(*p++, tf);
105716406Sslatteng 	}
105816406Sslatteng 						/* mark that it's been used */
105916406Sslatteng 	if (fs->chused[number] != BMASK)
106016406Sslatteng 		fs->chused[number]++;
106116406Sslatteng 	putc(ASTEXTURE, tf);			/* set the texture */
106216406Sslatteng 	putint((fam << 7) | number, tf);
106316406Sslatteng 	fs = savefs;				/* return fs to proper spot */
106416406Sslatteng }
106516406Sslatteng 
106616406Sslatteng 
xychar(c)106714396Sslatteng xychar(c)
106814967Sslatteng register int c;
106914396Sslatteng {
107014396Sslatteng 	register unsigned char *p;
107114967Sslatteng 	register glyph_dir *par;
107214967Sslatteng 	register int gsize;
107314396Sslatteng 
107414396Sslatteng 
107514967Sslatteng 	if (c >= CHARRAY) {
107614967Sslatteng #ifdef DEBUGABLE
107714967Sslatteng 		if (dbg) error(!FATAL, "character out of range: %d 0%o", c, c);
107814967Sslatteng #endif
107914967Sslatteng 		return;
108014967Sslatteng 	}
108114396Sslatteng 	if (font != lastfont || size != lastsize) {
108214967Sslatteng 		family = getfontdata(font, size);
108314396Sslatteng 		lastsize = size;
108414396Sslatteng 		lastfont = font;
108514396Sslatteng 	}
108614967Sslatteng 	par = &(fs->glyph[c]);
108714967Sslatteng 	p = fs->cdp + par->g_bitp;
108814967Sslatteng 	if (family != lastfam) {
108914396Sslatteng 		putc(AF, tf);
109014967Sslatteng 		putc(lastfam = family ,tf);
109114396Sslatteng 	}
109214396Sslatteng 
109314967Sslatteng 	if (fs->chused[c] == 0) {	/* 1st use of this character */
109414396Sslatteng 		totglyph += glspace(par);
109514967Sslatteng 		putc(ABGLY, tf);
109614967Sslatteng 		putint((family << 7) | c, tf);
109714967Sslatteng  		putint(lastw, tf);		/* use troff's width, not */
109814967Sslatteng 		putint(par->g_width, tf);	/* the RST character width */
109914967Sslatteng 		putint(par->g_left, tf);
110014967Sslatteng 		putint(par->g_height, tf);
110114967Sslatteng 		putint(par->g_up, tf);
110214967Sslatteng 		gsize = ((par->g_width + 7)/8) * par->g_height;
110314967Sslatteng 		while (gsize--)
110414396Sslatteng 			putc(*p++, tf);
110514396Sslatteng 	}
110616406Sslatteng 					/* note that character's been used */
110716406Sslatteng 	if (fs->chused[c] != BMASK)
110816406Sslatteng 		fs->chused[c]++;
110914967Sslatteng 	hvflush();
111014967Sslatteng 	putc(c, tf);		/* guaranteed to be in range */
111114967Sslatteng 	lastx += lastw;		/* take account of the automatic advance */
111214967Sslatteng }
111314396Sslatteng 
111414396Sslatteng 
111514967Sslatteng /*----------------------------------------------------------------------------*
111614967Sslatteng  | Routine:	hvflush ( )
111714967Sslatteng  |
111814967Sslatteng  | Results:	force current position (hpos, vpos) on the imagen
111914967Sslatteng  *----------------------------------------------------------------------------*/
112014396Sslatteng 
hvflush()112114967Sslatteng hvflush()
112214396Sslatteng {
112314967Sslatteng 	if (vpos != lasty) {
112414967Sslatteng 		putc(ASETV, tf);
112514967Sslatteng 		putint(lasty = vpos, tf);
112614396Sslatteng 	}
112714967Sslatteng 	if (hpos != lastx) {
112814967Sslatteng 		putc(ASETH, tf);
112914967Sslatteng 		putint(lastx = hpos, tf);
113014396Sslatteng 	}
113114396Sslatteng }
113214396Sslatteng 
113314967Sslatteng 
113414967Sslatteng /*----------------------------------------------------------------------------*
113514967Sslatteng  | Routine:	glspace ( glyph )
113614967Sslatteng  |
113714967Sslatteng  | Results:	returns how much space the glyph (defined by the glyph_dir
113814967Sslatteng  |		entry) will take in the imagen's memory.
113914967Sslatteng  *----------------------------------------------------------------------------*/
114014967Sslatteng 
glspace(par)114114396Sslatteng glspace(par)
114214967Sslatteng glyph_dir *par;
114314396Sslatteng {
114414967Sslatteng 	return 19 + ((par->g_width + 15) / 16 ) * (par->g_height);
114514967Sslatteng }
114614396Sslatteng 
114714396Sslatteng 
114814967Sslatteng /*----------------------------------------------------------------------------*
114914967Sslatteng  | Routine:	clearglyphs ( index, limit )
115014967Sslatteng  |
115114967Sslatteng  | Results:	any glyphs downloaded into the imagen with a "chused" entry
115214967Sslatteng  |		less than "limit" (and > 0) are marked for deletion and their
115314967Sslatteng  |		space is "unrecorded" in totglyph.
115414967Sslatteng  |
115514967Sslatteng  | Bugs:	clearglyphs does NOT check index to make sure the family exists
115614967Sslatteng  *----------------------------------------------------------------------------*/
115714396Sslatteng 
clearglyphs(index,limit)115814967Sslatteng clearglyphs(index, limit)
115914967Sslatteng int index;
116014967Sslatteng int limit;
116114396Sslatteng {
116214967Sslatteng 	register fontset *f = &fontdata[index];
116314967Sslatteng 	register int j;
116414396Sslatteng 
116514967Sslatteng #ifdef DEBUGABLE
116614967Sslatteng 	if (dbg) fprintf(stderr, "clear %d family of %d (%d/%d) on page %d\n",
116714967Sslatteng 			index, limit, totglyph, maxglyph, pageno);
116814967Sslatteng #endif
116914967Sslatteng 	for (j = 0; j < CHARRAY; j++) {
117014967Sslatteng 		if (f->chused[j] && f->chused[j] < limit) {
117114967Sslatteng 			putc(ADELG, tf);
117214967Sslatteng 			putint(index<<7 | j, tf);
117314967Sslatteng 			totglyph -= glspace (&(f->glyph[j]));
117414967Sslatteng 			f->chused[j] = 0;
117514396Sslatteng 		}
117614967Sslatteng 	}
117714396Sslatteng }
117814396Sslatteng 
117914396Sslatteng 
putint(n,f)118014396Sslatteng putint(n, f)
118114396Sslatteng int n;
118214396Sslatteng FILE *f;
118314396Sslatteng {
118414396Sslatteng 	putc(n >> 8, f);
118514396Sslatteng 	putc(n & 0377, f);
118614396Sslatteng }
1187