1 /* dver.c	1.7	83/07/29
2  *
3  * Versatec driver for the new troff
4  *
5  * Authors:	BWK(BELL)
6  *		VCAT(berkley)
7  *		Richard L. Hyde, Perdue University
8  *		and David Slattengren, Berkeley
9  */
10 
11 
12 /*******************************************************************************
13 
14     output language from troff:
15     all numbers are character strings
16 
17 #..\n	comment
18 sn	size in points
19 fn	font as number from 1 to n
20 cx	ascii character x
21 Cxyz	funny char \(xyz. terminated by white space
22 Hn	go to absolute horizontal position n
23 Vn	go to absolute vertical position n (down is positive)
24 hn	go n units horizontally (relative)
25 vn	ditto vertically
26 nnc	move right nn, then print c (exactly 2 digits!)
27 		(this wart is an optimization that shrinks output file size
28 		 about 35% and run-time about 15% while preserving ascii-ness)
29 p	new page begins -- set v to 0
30 nb a	end of line (information only -- no action needed)
31 	b = space before line, a = after
32 w	paddable word space -- no action needed
33 
34 Dt ..\n	draw operation 't':
35 	Dl x y		line from here by x,y
36 	Dc d		circle of diameter d with left side here
37 	De x y		ellipse of axes x,y with left side here
38 	Da x y r	arc counter-clockwise by x,y of radius r
39 	D~ x y x y ...	B-spline curve by x,y then x,y ...
40 
41 x ..\n	device control functions:
42      x i	init
43      x T s	name of device is s
44      x r n h v	resolution is n/inch h = min horizontal motion, v = min vert
45      x p	pause (can restart)
46      x s	stop -- done for ever
47      x t	generate trailer
48      x f n s	font position n contains font s
49      x H n	set character height to n
50      x S n	set slant to N
51 
52 	Subcommands like "i" are often spelled out like "init".
53 
54 *******************************************************************************/
55 
56 
57 #include <stdio.h>
58 #include <ctype.h>
59 #include <sys/vcmd.h>
60 #include "dev.h"
61 
62 
63 #define DEBUGABLE		/* Yes, debugable... */
64 #define	NFONTS	25		/* total number of fonts useable */
65 #define	MAXSTATE 6		/* number of environments rememberable */
66 #define OPENREAD 0		/* mode for openning files */
67 #define RESTART	1		/* upon exit, return either RESTART */
68 #define ABORT	2		/*     or ABORT */
69 #define	FATAL	1		/* type of error */
70 #define	BMASK	0377		/* byte grabber */
71 #define FONTDIR	"/usr/lib/font"	/* default place to look for fonts */
72 #define MAXWRIT 4096		/* max characters allowed to write at once */
73 
74 #define  hmot(n)	hpos += n
75 #define  hgoto(n)	hpos = n
76 #define  vmot(n)	vgoto(vpos + n)
77 
78 
79 char	SccsId[]= "dver.c	1.7	83/07/29";
80 
81 int	output	= 0;	/* do we do output at all? */
82 int	nolist	= 0;	/* output page list if > 0 */
83 int	olist[20];	/* pairs of page numbers */
84 int	spage	= 9999;	/* stop every spage pages */
85 int	scount	= 0;
86 struct	dev	dev;
87 struct	font	*fontbase[NFONTS+1];
88 short	*pstab;		/* point size table pointer */
89 int	res;		/* input was computed according to this resolution */
90 int	nsizes;		/* number of sizes device is capable of printing */
91 int	nfonts;		/* number of fonts device is capable of printing */
92 int	smnt;		/* index of first special font */
93 int	nchtab;
94 char	*chname;
95 short	*chtab;
96 char	*fitab[NFONTS+1];
97 char	*widtab[NFONTS+1];
98 char	*codetab[NFONTS+1];	/* device codes */
99 char	*fontdir = FONTDIR;
100 struct {			/* table of what font */
101 	char *name;		/*   name is on what */
102 	int number;		/*   position in font tables */
103 } fontname[NFONTS+1];
104 
105 #ifdef DEBUGABLE
106 int	dbg	= 0;
107 #endif
108 int	maxH;		/* farthest down we've been on the current page */
109 int	size	= -1;	/* current point size being use */
110 int	font	= -1;	/* current font - not using any to start with */
111 int	hpos;		/* horizontal position we are to be at next; left = 0 */
112 int	vpos;		/* current vertical position (down positive) */
113 extern	linethickness;	/* thickness (in pixels) of any drawn objects */
114 extern	linmod;		/* line style (a bit mask - dotted, etc.) of objects */
115 int	lastw;		/* width of last character printed */
116 
117 
118 #define DISPATCHSIZE	256		/* must be a power of two */
119 #define CHARMASK	(DISPATCHSIZE-1)
120 #define DSIZ		((sizeof *dispatch)*DISPATCHSIZE)
121 #define OUTFILE 	fileno (stdout)
122 #define	RES		200		/* resolution of the device */
123 #define	TRAILER		(10 * RES)	/* position of trailer */
124 
125 #define RASTER_LENGTH	2048			/* device line length */
126 #define BYTES_PER_LINE	(RASTER_LENGTH/8)
127 #define NLINES		(11 * RES)		/* 11" long paper */
128 #define BUFFER_SIZE	(NLINES*BYTES_PER_LINE)	/* number of chars in picture */
129 
130 
131 int	pltmode[] = { VPLOT };
132 int	prtmode[] = { VPRINT };
133 char	buffer[BUFFER_SIZE];	/* Big line buffers  */
134 char	*buf0p = &buffer[0];	/* Zero origin in circular buffer  */
135 
136 char	*calloc();
137 char	*nalloc();
138 char	*allpanic();
139 
140 struct header {
141 	short	magic;
142 	unsigned short	size;
143 	short	maxx;
144 	short	maxy;
145 	short	xtnd;
146 } header;
147 
148 struct	dispatch{
149 	unsigned short	addr;
150 	short	nbytes;
151 	char	up;
152 	char	down;
153 	char	left;
154 	char	right;
155 	short	width;
156 };
157 
158 struct	fontdes {
159 	int	fnum;
160 	int	psize;
161 	struct	dispatch *disp;
162 	char	*bits;
163 } fontdes[NFONTS] = {
164 	-1,
165 	-1
166 };
167 
168 struct dispatch *dispatch;
169 int	cfnum = -1;
170 int	cpsize = 10;
171 int	cfont = 1;
172 char	*bits;
173 int	fontwanted = 1;		/* flag:  "has a new font been requested?" */
174 int	nfontnum = -1;
175 int	npsize = 10;
176 
177 
178 
179 main(argc, argv)
180 char *argv[];
181 {
182 	FILE *fp;
183 	int done();
184 
185 	while (argc > 1 && argv[1][0] == '-') {
186 		switch (argv[1][1]) {
187 		case 'f':
188 		case 'F':
189 			fontdir = argv[2];
190 			argv++;
191 			argc--;
192 			break;
193 		case 'o':
194 			outlist(&argv[1][2]);
195 			break;
196 #ifdef DEBUGABLE
197 		case 'd':
198 			dbg = atoi(&argv[1][2]);
199 			if (dbg == 0) dbg = 1;
200 			break;
201 #endif
202 		case 's':
203 			spage = atoi(&argv[1][2]);
204 			if (spage <= 0)
205 				spage = 9999;
206 			break;
207 		}
208 		argc--;
209 		argv++;
210 	}
211 
212 /* noversatec
213 	ioctl(OUTFILE, VSETSTATE, pltmode);
214 noversatec */
215 
216 	if (argc <= 1)
217 		conv(stdin);
218 	else
219 		while (--argc > 0) {
220 			if (strcmp(*++argv, "-") == 0)
221 				fp = stdin;
222 			else if ((fp = fopen(*argv, "r")) == NULL)
223 				error(FATAL, "can't open %s", *argv);
224 			conv(fp);
225 			fclose(fp);
226 		}
227 	done();
228 	exit(0);
229 }
230 
231 outlist(s)	/* process list of page numbers to be printed */
232 char *s;
233 {
234 	int n1, n2, i;
235 
236 	nolist = 0;
237 	while (*s) {
238 		n1 = 0;
239 		if (isdigit(*s))
240 			do
241 				n1 = 10 * n1 + *s++ - '0';
242 			while (isdigit(*s));
243 		else
244 			n1 = -9999;
245 		n2 = n1;
246 		if (*s == '-') {
247 			s++;
248 			n2 = 0;
249 			if (isdigit(*s))
250 				do
251 					n2 = 10 * n2 + *s++ - '0';
252 				while (isdigit(*s));
253 			else
254 				n2 = 9999;
255 		}
256 		olist[nolist++] = n1;
257 		olist[nolist++] = n2;
258 		if (*s != '\0')
259 			s++;
260 	}
261 	olist[nolist] = 0;
262 #ifdef DEBUGABLE
263 	if (dbg)
264 		for (i=0; i<nolist; i += 2)
265 			fprintf(stderr,"%3d %3d\n", olist[i], olist[i+1]);
266 #endif
267 }
268 
269 conv(fp)
270 register FILE *fp;
271 {
272 	register int c, k;
273 	int m, n, n1, m1;
274 	char str[100], buf[300];
275 
276 	while ((c = getc(fp)) != EOF) {
277 		switch (c) {
278 		case '\n':	/* when input is text */
279 		case ' ':
280 		case 0:		/* occasional noise creeps in */
281 			break;
282 		case '{':	/* push down current environment */
283 			t_push();
284 			break;
285 		case '}':
286 			t_pop();
287 			break;
288 		case '0': case '1': case '2': case '3': case '4':
289 		case '5': case '6': case '7': case '8': case '9':
290 			/* two motion digits plus a character */
291 			hmot((c-'0')*10 + getc(fp)-'0');
292 			put1(getc(fp));
293 			break;
294 		case 'c':	/* single ascii character */
295 			put1(getc(fp));
296 			break;
297 		case 'C':
298 			fscanf(fp, "%s", str);
299 			put1s(str);
300 			break;
301 		case 't':	/* straight text */
302 			fgets(buf, sizeof(buf), fp);
303 			t_text(buf);
304 			break;
305 		case 'D':	/* draw function */
306 			fgets(buf, sizeof(buf), fp);
307 			switch (buf[0]) {
308 			case 'l':	/* draw a line */
309 			    sscanf(buf+1, "%d %d", &n, &m);
310 			    drawline(n, m);
311 			    break;
312 			case 'c':	/* circle */
313 			    sscanf(buf+1, "%d", &n);
314 			    drawcirc(n);
315 			    break;
316 			case 'e':	/* ellipse */
317 			    sscanf(buf+1, "%d %d", &m, &n);
318 			    drawellip(m, n);
319 			    break;
320 			case 'a':	/* arc */
321 			    sscanf(buf+1, "%d %d %d %d", &n, &m, &n1, &m1);
322 			    drawarc(n, m, n1, m1);
323 			    break;
324 			case '~':	/* wiggly line */
325 			case 'g':	/* gremlin spline */
326 			    drawwig(buf+1, fp, buf[0] == '~');
327 			    break;
328 			case 't':	/* line thickness */
329 			    sscanf(buf+1, "%d", &n);
330 			    drawthick(n);
331 			    break;
332 			case 's':	/* line style */
333 			    sscanf(buf+1, "%d", &n);
334 			    drawstyle(n);
335 			    break;
336 			default:
337 			    error(FATAL, "unknown drawing function %s\n", buf);
338 			    break;
339 			}
340 			break;
341 		case 's':
342 			fscanf(fp, "%d", &n);	/* ignore fractional sizes */
343 			setsize(t_size(n));
344 			break;
345 		case 'f':
346 			fscanf(fp, "%s", str);
347 			setfont(t_font(str));
348 			break;
349 		case 'H':	/* absolute horizontal motion */
350 			/* fscanf(fp, "%d", &n); */
351 			while ((c = getc(fp)) == ' ')
352 				;
353 			k = 0;
354 			do {
355 				k = 10 * k + c - '0';
356 			} while (isdigit(c = getc(fp)));
357 			ungetc(c, fp);
358 			hgoto(k);
359 			break;
360 		case 'h':	/* relative horizontal motion */
361 			while ((c = getc(fp)) == ' ')
362 				;
363 			k = 0;
364 			do {
365 				k = 10 * k + c - '0';
366 			} while (isdigit(c = getc(fp)));
367 			ungetc(c, fp);
368 			hmot(k);
369 			break;
370 		case 'w':	/* word space */
371 			break;
372 		case 'V':
373 			fscanf(fp, "%d", &n);
374 			vgoto(n);
375 			break;
376 		case 'v':
377 			fscanf(fp, "%d", &n);
378 			vmot(n);
379 			break;
380 		case 'p':	/* new page */
381 			fscanf(fp, "%d", &n);
382 			t_page(n);
383 			break;
384 		case 'n':	/* end of line */
385 			while (getc(fp) != '\n')
386 				;
387 			t_newline();
388 			break;
389 		case '#':	/* comment */
390 			while (getc(fp) != '\n')
391 				;
392 			break;
393 		case 'x':	/* device control */
394 			devcntrl(fp);
395 			break;
396 		default:
397 			error(!FATAL, "unknown input character %o %c\n", c, c);
398 			done();
399 		}
400 	}
401 }
402 
403 devcntrl(fp)	/* interpret device control functions */
404 FILE *fp;
405 {
406         char str[20], str1[50], buf[50];
407 	int c, n;
408 
409 	fscanf(fp, "%s", str);
410 	switch (str[0]) {	/* crude for now */
411 	case 'i':	/* initialize */
412 		fileinit();
413 		t_init();
414 		break;
415 	case 't':	/* trailer */
416 		t_trailer();
417 		break;
418 	case 'p':	/* pause -- can restart */
419 		t_reset('p');
420 		break;
421 	case 's':	/* stop */
422 		t_reset('s');
423 		break;
424 	case 'r':	/* resolution assumed when prepared */
425 		fscanf(fp, "%d", &res);
426 		break;
427 	case 'f':	/* font used */
428 		fscanf(fp, "%d %s", &n, str);
429 		fgets(buf, sizeof buf, fp);	/* in case there's a filename */
430 		ungetc('\n', fp);		/* fgets goes too far */
431 		str1[0] = 0;			/* in case nothing comes in */
432 		sscanf(buf, "%s", str1);
433 		loadfont(n, str, str1);
434 		break;
435 						/* these don't belong here... */
436 	case 'H':	/* char height */
437 		fscanf(fp, "%d", &n);
438 		t_charht(n);
439 		break;
440 	case 'S':	/* slant */
441 		fscanf(fp, "%d", &n);
442 		t_slant(n);
443 		break;
444 	}
445 	while ((c = getc(fp)) != '\n')	/* skip rest of input line */
446 		if (c == EOF)
447 			break;
448 }
449 
450 /* fileinit:	read in font and code files, etc.
451 		Must open table for device, read in resolution,
452 		size info, font info, etc. and set params
453 */
454 fileinit()
455 {
456 	int i, fin, nw;
457 	char	*filebase, *p;
458 	char	temp[60];
459 
460 	sprintf(temp, "%s/devver/DESC.out", fontdir);
461 	if ((fin = open(temp, 0)) < 0)
462 		error(FATAL, "can't open tables for %s\n", temp);
463 	read(fin, &dev, sizeof(struct dev));
464 	nfonts = dev.nfonts;
465 	nsizes = dev.nsizes;
466 	nchtab = dev.nchtab;
467 	filebase = calloc(1,dev.filesize);	/* enough room for whole file */
468 	read(fin, filebase, dev.filesize);	/* all at once */
469 	pstab = (short *) filebase;
470 	chtab = pstab + nsizes + 1;
471 	chname = (char *) (chtab + dev.nchtab);
472 	p = chname + dev.lchname;
473 	for (i = 1; i <= nfonts; i++) {
474 		fontbase[i] = (struct font *) p;
475 		nw = *p & BMASK;		/* 1st thing is width count */
476 		if (smnt == 0 && fontbase[i]->specfont == 1)
477 			smnt = i;		/* first special font */
478 		p += sizeof(struct font);	/* that is on the beginning */
479 		widtab[i] = p;
480 		codetab[i] = p + 2 * nw;
481 		fitab[i] = p + 3 * nw;
482 		p += 3 * nw + dev.nchtab + 128 - 32;
483 		t_fp(i, fontbase[i]->namefont, fontbase[i]->intname);
484 #ifdef DEBUGABLE
485 		if (dbg > 1) fontprint(i);
486 #endif
487 	}
488 	fontbase[0] = (struct font *)
489 		calloc(1,3*255 + dev.nchtab + (128-32) + sizeof (struct font));
490 	widtab[0] = (char *) fontbase[0] + sizeof (struct font);
491 	fontbase[0]->nwfont = 255;
492 	close(fin);
493 }
494 
495 fontprint(i)	/* debugging print of font i (0,...) */
496 {
497 	int j, n;
498 	char *p;
499 
500 	fprintf(stderr,"font %d:\n", i);
501 	p = (char *) fontbase[i];
502 	n = fontbase[i]->nwfont & BMASK;
503 	fprintf(stderr,
504 	    "base=0%o, nchars=%d, spec=%d, name=%s, widtab=0%o, fitab=0%o\n",p,
505 	    n,fontbase[i]->specfont,fontbase[i]->namefont,widtab[i],fitab[i]);
506 	fprintf(stderr,"widths:\n");
507 	for (j=0; j <= n; j++) {
508 		fprintf(stderr," %2d", widtab[i][j] & BMASK);
509 		if (j % 20 == 19) fprintf(stderr,"\n");
510 	}
511 	fprintf(stderr,"\ncodetab:\n");
512 	for (j=0; j <= n; j++) {
513 		fprintf(stderr," %2d", codetab[i][j] & BMASK);
514 		if (j % 20 == 19) fprintf(stderr,"\n");
515 	}
516 	fprintf(stderr,"\nfitab:\n");
517 	for (j=0; j <= dev.nchtab + 128-32; j++) {
518 		fprintf(stderr," %2d", fitab[i][j] & BMASK);
519 		if (j % 20 == 19) fprintf(stderr,"\n");
520 	}
521 	fprintf(stderr,"\n");
522 }
523 
524 loadfont(n, s, s1)	/* load font info for font s on position n (0...) */
525 int n;
526 char *s, *s1;
527 {
528 	char temp[60];
529 	int fin, nw, norig;
530 
531 	if (n < 0 || n > NFONTS)
532 		error(FATAL, "illegal fp command %d %s", n, s);
533 	if (strcmp(s, fontbase[n]->namefont) == 0)
534 		return;
535 	if (s1 == NULL || s1[0] == '\0')
536 		sprintf(temp, "%s/devver/%s.out", fontdir, s);
537 	else
538 		sprintf(temp, "%s/%s.out", s1, s);
539 	if ((fin = open(temp, 0)) < 0)
540 		error(FATAL, "can't open font table %s", temp);
541 	norig = fontbase[n]->nwfont & BMASK;
542 	read(fin, fontbase[n], 3*norig + nchtab+128-32 + sizeof(struct font));
543 	if ((fontbase[n]->nwfont & BMASK) > norig)
544 		error(FATAL, "Font %s too big for position %d\n", s, n);
545 	close(fin);
546 	nw = fontbase[n]->nwfont & BMASK;
547 	widtab[n] = (char *) fontbase[n] + sizeof(struct font);
548 	codetab[n] = (char *) widtab[n] + 2 * nw;
549 	fitab[n] = (char *) widtab[n] + 3 * nw;
550 	t_fp(n, fontbase[n]->namefont, fontbase[n]->intname);
551 	fontbase[n]->nwfont = norig;	/* to later use full original size */
552 #ifdef DEBUGABLE
553 	if (dbg > 1) fontprint(n);
554 #endif
555 }
556 
557 done()
558 {
559 	t_reset('s');
560 	exit(0);
561 }
562 /*VARARGS1*/
563 error(f, s, a1, a2, a3, a4, a5, a6, a7) {
564 	fprintf(stderr, "dver: ");
565 	fprintf(stderr, s, a1, a2, a3, a4, a5, a6, a7);
566 	fprintf(stderr, "\n");
567 	if (f)
568 		done();
569 }
570 
571 
572 /*******************************************************************************
573  * Routine:
574  * Results:
575  * Side Efct:
576  ******************************************************************************/
577 
578 t_init()	/* initialize device */
579 {
580 	int i;
581 
582 	hpos = vpos = 0;
583 
584 	setsize(t_size(10));	/* start somewhere */
585 	setfont(1);
586 }
587 
588 
589 struct state {
590 	int	ssize;
591 	int	sfont;
592 	int	shpos;
593 	int	svpos;
594 	int	sstyle;
595 	int	sthick;
596 };
597 struct	state	state[MAXSTATE];
598 struct	state	*statep = state;
599 
600 t_push()	/* begin a new block */
601 {
602 	statep->ssize = size;
603 	statep->sfont = font;
604 	statep->sstyle = linmod;
605 	statep->sthick = linethickness;
606 	statep->shpos = hpos;
607 	statep->svpos = vpos;
608 	if (statep++ >= state+MAXSTATE)
609 		error(FATAL, "{ nested too deep");
610 }
611 
612 t_pop()	/* pop to previous state */
613 {
614 	if (--statep < state)
615 		error(FATAL, "extra }");
616 	size = statep->ssize;
617 	font = statep->sfont;
618 	hpos = statep->shpos;
619 	vpos = statep->svpos;
620 	linmod = statep->sstyle;
621 	linethickness = statep->sthick;
622 }
623 
624 t_page(n)	/* do whatever new page functions */
625 {
626 	int i;
627 
628 
629 	if (output) {
630 		if (++scount >= spage) {
631 			t_reset('p');
632 			scount = 0;
633 		}
634 		slop_lines(maxH);
635 /* noversatec
636 		ioctl(OUTFILE, VSETSTATE, prtmode);
637 		if (write(OUTFILE, "\f", 2) != 2)
638 			exit(RESTART);
639 		ioctl(OUTFILE, VSETSTATE, pltmode);
640 noversatec */
641 		size = BYTES_PER_LINE * maxH;
642 		vclear(buf0p, size);
643 		buf0p = buffer;
644 	}
645 
646 	maxH = 0;
647 
648 	vpos = 0;
649 	output = 1;
650 	if (nolist == 0)
651 		return;	/* no -o specified */
652 	output = 0;
653 	for (i = 0; i < nolist; i += 2)
654 		if (n >= olist[i] && n <= olist[i+1]) {
655 			output = 1;
656 			break;
657 		}
658 }
659 
660 t_newline()	/* do whatever for the end of a line */
661 {
662 	hpos = 0;	/* because we're now back at the left margin */
663 }
664 
665 t_size(n)	/* convert integer to internal size number*/
666 int n;
667 {
668 	int i;
669 
670 	if (n <= pstab[0])
671 		return(1);
672 	else if (n >= pstab[nsizes-1])
673 		return(nsizes);
674 	for (i = 0; n > pstab[i]; i++)
675 		;
676 	return(i+1);
677 }
678 
679 t_charht(n)	/* set character height to n */
680 int n;
681 {
682 #ifdef DEBUGABLE
683 	if (dbg)fprintf(stderr,"can't set height on versatec yet\n");
684 #endif
685 }
686 
687 t_slant(n)	/* set slant to n */
688 int n;
689 {
690 #ifdef DEBUGABLE
691 	if (dbg)fprintf(stderr,"can't set slant on versatec yet\n");
692 #endif
693 }
694 
695 t_font(s)	/* convert string to internal font number */
696 char *s;
697 {
698 	int n;
699 
700 	n = atoi(s);
701 	if (n < 0 || n > nfonts)
702 		n = 1;
703 	return(n);
704 }
705 
706 t_text(s)	/* print string s as text */
707 char *s;
708 {
709 	int c;
710 	char str[100];
711 
712 	if (!output)
713 		return;
714 	while (c = *s++) {
715 		if (c == '\\') {
716 			switch (c = *s++) {
717 			case '\\':
718 			case 'e':
719 				put1('\\');
720 				break;
721 			case '(':
722 				str[0] = *s++;
723 				str[1] = *s++;
724 				str[2] = '\0';
725 				put1s(str);
726 				break;
727 			}
728 		} else {
729 			put1(c);
730 		}
731 		hmot(lastw);
732 #ifdef DEBUGABLE
733 		if (dbg) fprintf(stderr,"width = %d\n", lastw);
734 #endif
735 	}
736 }
737 
738 t_reset(c)
739 {
740 
741 
742 	output = 1;
743 	switch(c){
744 	case 'p':
745 		slop_lines(maxH);
746 		maxH = 0;
747 		buf0p = buffer;
748 		break;
749 	case 's':
750 		slop_lines(maxH);
751 		t_done();
752 		break; /* no Return */
753 	}
754 }
755 
756 t_done()	/* clean up and get ready to die */
757 {
758 /* noversatec
759 	ioctl(OUTFILE, VSETSTATE, prtmode);
760 	if (write(OUTFILE, "\f", 2) != 2)
761 		exit(RESTART);
762 noversatec */
763 }
764 
765 t_trailer()
766 {
767 	vpos = 0;
768 	vgoto(TRAILER);
769 	vpos = 0;
770 }
771 
772 vgoto(n)
773 {
774 			/* check to see if n would move use past buf0p */
775     if (n < 0) {
776 	fprintf (stderr, "ERROR vgoto past the beginning");
777 	done();
778     }
779 					/* check for end of page */
780     if (n > RES * 11) n -= RES * 11;	/* wrap around on to the top */
781     vpos = n;
782 }
783 
784 put1s(s)	/* s is a funny char name */
785 char *s;
786 {
787 	int i;
788 
789 	if (!output)
790 		return;
791 #ifdef DEBUGABLE
792 	if (dbg) fprintf(stderr,"%s ", s);
793 #endif
794 	for (i = 0; i < nchtab; i++)
795 		if (strcmp(&chname[chtab[i]], s) == 0)
796 			break;
797 	if (i < nchtab)
798 		put1(i + 128);
799 }
800 
801 put1(c)	/* output char c */
802 int c;
803 {
804 	char *pw;
805 	register char *p;
806 	register int i, k;
807 	int j, ofont, code;
808 
809 	if (!output)
810 		return;
811 	c -= 32;
812 	if (c <= 0) {
813 #ifdef DEBUGABLE
814 		if (dbg) fprintf(stderr,"non-exist 0%o\n", c + 32);
815 #endif
816  		lastw = (widtab[font][0] * pstab[size-1] + dev.unitwidth/2)
817 								/ dev.unitwidth;
818 		return;
819 	}
820 	k = ofont = font;
821 	i = fitab[font][c] & BMASK;
822 	if (i != 0) {			/* it's on this font */
823 		p = codetab[font];	/* get the printing value of ch */
824 		pw = widtab[font];	/* get the width */
825 	} else if (smnt > 0) {		/* on special (we hope) */
826 		for (k=smnt, j=0; j <= nfonts; j++, k = (k+1) % (nfonts+1)){
827 			if (fitab[k] == 0)
828 				continue;
829 			if ((i = fitab[k][c] & BMASK) != 0) {
830 				p = codetab[k];
831 				pw = widtab[k];
832 				setfont(k);
833 				break;
834 			}
835 		}
836 	}
837 	if (i == 0 || (code = p[i] & BMASK) == 0 || k > nfonts) {
838 #ifdef DEBUGABLE
839 		if (dbg) fprintf(stderr,"not found 0%o\n", c+32);
840 #endif
841 		return;
842 	}
843 #ifdef DEBUGABLE
844 	if (dbg) {
845 		if (isprint(c+32))
846 			fprintf(stderr,"%c %d\n", c+32, code);
847 		else
848 			fprintf(stderr,"%03o %d\n", c+32, code);
849 	}
850 #endif
851 	outc(code);	/* character is < 254 */
852 	if (font != ofont)
853 		setfont(ofont);
854 	lastw = ((pw[i]&077) * pstab[size-1] + dev.unitwidth/2) / dev.unitwidth;
855 }
856 
857 
858 
859 setsize(n)	/* set point size to n (internal) */
860 int n;
861 {
862 
863 	if (n == size)
864 		return;	/* already there */
865 	if (vloadfont(font,pstab[n-1]) != -1)
866 		size = n;
867 }
868 
869 t_fp(n, s, si)	/* font position n now contains font s, intname si */
870 int n;
871 char *s, *si;
872 {
873 	register	i;
874 
875 	fontname[n].name = s;
876 	fontname[n].number = atoi(si);
877 	for(i = 0;i < NFONTS;i++)/* free the bits of that font */
878 		if (fontdes[i].fnum == n){
879 			nfree(fontdes[i].bits);
880 			fontdes[i].bits = 0;
881 			fontdes[i].fnum = -1;
882 		}
883 }
884 
885 setfont(n)	/* set font to n */
886 int n;
887 {
888 	if (n < 0 || n > NFONTS)
889 		error(FATAL, "illegal font %d\n", n);
890 	if (vloadfont(n,pstab[size - 1]) != -1)
891 		font = n;
892 }
893 
894 vloadfont(fnum, fsize)
895 register int fnum;
896 register int fsize;
897 {
898 	register int i;
899 
900 	fontwanted = 0;
901 	if (fnum == cfnum && fsize == cpsize)
902 		return(0);
903 	for (i = 0; i < NFONTS; i++) {
904 		if (fontdes[i].fnum == fnum && fontdes[i].psize == fsize) {
905 			cfnum = fontdes[i].fnum;
906 			cpsize = fontdes[i].psize;
907 			dispatch = &fontdes[i].disp[0];
908 			bits = fontdes[i].bits;
909 			cfont = i;
910 			return (0);
911 		}
912 	}
913 		/* this is a new font */
914 	if (fnum < 0 || fnum > NFONTS || fontname[fnum].name == 0) {
915 	    fprintf(stderr, "Internal error: illegal font %d name %s size\n",
916 			    fontname[fnum].name,fnum,fsize);
917 	    return(-1);
918 	}
919 		/* Need to verify the existance of that font/size here*/
920 	nfontnum = fnum;
921 	npsize = fsize;
922 	fontwanted++;
923 	return (0);
924 }
925 
926 
927 getfont()
928 {
929 	register int fnum, fsize, fontd;
930 	int d;
931 	char cbuf[BUFSIZ];
932 
933 	fnum = nfontnum;
934 	fsize = npsize;
935 	sprintf(cbuf, "/usr/lib/vfont/%s.%d",fontname[fnum].name, fsize);
936 	fontd = open(cbuf, OPENREAD);
937 	if (fontd == -1) {
938 		perror(cbuf);
939 		error(0,"fnum = %d size = %d name = %s\n",
940 			fnum,fsize,fontname[fnum]);
941 		fontwanted = 0;
942 		return (-1);
943 	}
944 	if (read(fontd, &header, sizeof  (header)) != sizeof (header)
945 						|| header.magic != 0436)
946 		fprintf(stderr, "%s: Bad font file", cbuf);
947 	else {
948 		cfont = relfont();
949 		if ((bits=nalloc(header.size+DSIZ+1,1))== NULL)
950 			if ((bits=allpanic(header.size+DSIZ+1))== NULL) {
951 				fprintf(stderr,"%s: ran out of memory\n", cbuf);
952 				exit(ABORT);
953 			}
954 
955 			/*
956 			 * have allocated one chunk of mem for font, dispatch.
957 			 * get the dispatch addr, align to word boundary.
958 			 */
959 
960 		d = (int) bits+header.size;
961 		d += 1;
962 		d &= ~1;
963 		if (read (fontd, d, DSIZ) != DSIZ
964 			    || read (fontd, bits, header.size) != header.size)
965 			fprintf(stderr, "bad font header");
966 		else {
967 			close(fontd);
968 			cfnum = fontdes[cfont].fnum = fnum;
969 			cpsize = fontdes[cfont].psize = fsize;
970 			fontdes [cfont].bits = bits;
971 			fontdes [cfont].disp = (struct dispatch *) d;
972 			dispatch = &fontdes[cfont].disp[0];
973 			fontwanted = 0;
974 			return (0);
975 		}
976 	}
977 	close(fontd);
978 	fontwanted = 0;
979 	return(-1);
980 }
981 
982 /*
983  * "release" a font position - find an empty one, if possible
984  */
985 
986 relfont()
987 {
988     register int newfont;
989 
990     for (newfont = 0; newfont < NFONTS; newfont++)
991 	if (fontdes [newfont].bits == (char *) -1  ||  !fontdes [newfont].bits)
992 	    break;
993     if (fontdes [newfont].bits != (char *) -1  &&  fontdes [newfont].bits) {
994 	nfree (fontdes [newfont].bits);
995 	fontdes [newfont].bits = (char *)0;
996 #ifdef DEBUGABLE
997 	if (dbg) fprintf (stderr, "freeing position %d\n", newfont);
998     } else {
999 	if (dbg)
1000 	    fprintf (stderr, "taking, not freeing, position %d\n", newfont);
1001 #endif
1002     }
1003     fontdes[newfont].bits = 0;
1004     return (newfont);
1005 }
1006 
1007 char *allpanic (nbytes)
1008 int nbytes;
1009 {
1010 	register int i;
1011 
1012 	for (i = 0; i <= NFONTS; i++)
1013 	    if (fontdes[i].bits != (char *)-1 && fontdes[i].bits != (char *)0)
1014 		nfree(fontdes[i].bits);
1015 	for (i = 0; i <= NFONTS; i++) {
1016 		fontdes[i].fnum = fontdes[i].psize = -1;
1017 		fontdes[i].bits = 0;
1018 		cfnum = cpsize = -1;
1019 	}
1020 	return(nalloc(nbytes,1));
1021 }
1022 
1023 int	M[] = { 0xffffffff, 0xfefefefe, 0xfcfcfcfc, 0xf8f8f8f8,
1024 		0xf0f0f0f0, 0xe0e0e0e0, 0xc0c0c0c0, 0x80808080, 0x0 };
1025 int	N[] = { 0x00000000, 0x01010101, 0x03030303, 0x07070707,
1026 		0x0f0f0f0f, 0x1f1f1f1f, 0x3f3f3f3f, 0x7f7f7f7f, 0xffffffff };
1027 int	strim[] = { 0xffffffff, 0xffffff00, 0xffff0000, 0xff000000, 0 };
1028 
1029 outc(code)
1030 int code;		/* character to print */
1031 {
1032     register struct dispatch *dis; /* ptr to character font record */
1033     register char *addr;	/* addr of font data */
1034     int llen;			/* length of each font line */
1035     int nlines;			/* number of font lines */
1036     register char *scanp;	/* ptr to output buffer */
1037     int scanp_inc;		/* increment to start of next buffer */
1038     int offset;			/* bit offset to start of font data */
1039     int i;			/* loop counter */
1040     register int count;		/* font data ptr */
1041     register unsigned fontdata;	/* font data temporary */
1042     register int off8;		/* offset + 8 */
1043 
1044     if (fontwanted)
1045 	getfont();
1046     dis = dispatch + code;
1047     if (dis->nbytes) {
1048 	addr = bits + dis->addr;
1049 	llen = (dis->left + dis->right + 7) / 8;
1050 	nlines = dis->up + dis->down;
1051 	if ((i = vpos + dis->down) > maxH) maxH = i;	/* remember page len */
1052 	scanp = buf0p + (((vpos - dis->up) - 1) * BYTES_PER_LINE
1053 			+ (hpos - dis->left) / 8);
1054 	if (scanp < &buffer[0])
1055 	    scanp += sizeof buffer;
1056 	scanp_inc = BYTES_PER_LINE - llen;
1057 	offset = - ((hpos - dis->left) &07);
1058 	off8 = offset + 8;
1059 	for (i = 0; i < nlines; i++) {
1060 	    if (scanp >= &buffer[BUFFER_SIZE])
1061 		scanp -= sizeof buffer;
1062 	    count = llen;
1063 	    if (scanp + count <= &buffer[BUFFER_SIZE]) {
1064 		do {
1065 		    fontdata = *(unsigned *)addr;
1066 		    addr += 4;
1067 		    if (count < 4)
1068 			fontdata &= ~strim[count];
1069 		    *(unsigned*)scanp |=(fontdata << offset) & ~M[off8];
1070 		    scanp++;
1071 		    *(unsigned*)scanp |=(fontdata << off8) & ~N[off8];
1072 		    scanp += 3;
1073 		    count -= 4;
1074 		} while (count > 0);
1075 	    }
1076 	    scanp += scanp_inc+count;
1077 	    addr += count;
1078 	}
1079 	return;
1080     }
1081     return;
1082 }
1083 
1084 slop_lines(nlines)
1085 int nlines;
1086 
1087 /* Output "nlines" lines from the buffer, and clear that section of the  */
1088 /* buffer.	*/
1089 
1090 {
1091 	unsigned usize;
1092 
1093 	usize = BYTES_PER_LINE * nlines;
1094 	writev(buf0p,usize);
1095 	vclear(buf0p, usize);
1096 /* noversatec
1097 	ioctl(OUTFILE, VSETSTATE, pltmode);
1098 noversatec */
1099 }
1100 
1101 writev(buf,usize)
1102 char *buf;
1103 unsigned usize;
1104 {
1105 	register int tsize = 0;
1106 
1107 	while (usize){
1108 		buf += tsize;
1109 		tsize = usize > MAXWRIT ? MAXWRIT : usize;
1110 #ifdef DEBUGABLE
1111 		if (dbg)fprintf(stderr,"buf = %d size = %d\n",buf,tsize);
1112 #endif
1113 		if ((tsize = write(OUTFILE, buf, tsize)) < 0) {
1114 			perror("dver: write failed");
1115 			exit(RESTART);
1116 		}
1117 		usize -= tsize;
1118 	}
1119 }
1120 
1121 vclear (ptr, nbytes)
1122 char	*ptr;
1123 unsigned nbytes;
1124 {
1125     register tsize = 0;
1126 
1127     while (nbytes){
1128 	if ((unsigned)(16*1024) < nbytes) {
1129 	    tsize = 16 * 1024;
1130 	} else
1131 	    tsize = nbytes;
1132 	nbytes -= tsize;
1133 #ifdef DEBUGABLE
1134 	if (dbg) fprintf(stderr,"clearing ptr = %d size = %d\n",ptr,tsize);
1135 #endif
1136 	clear(ptr,tsize);
1137 	ptr += tsize;
1138     }
1139 }
1140 
1141 /*ARGSUSED*/
1142 clear(lp, nbytes)
1143 int *lp;
1144 int nbytes;
1145 {
1146 	asm("movc5 $0,(sp),$0,8(ap),*4(ap)");
1147 }
1148 
1149 char *
1150 nalloc(i, j)
1151 int i, j;
1152 {
1153 	register char *cp;
1154 
1155 	cp = calloc(i, j);
1156 #ifdef DEBUGABLE
1157 	if (dbg) fprintf(stderr, "allocated %d bytes at %x\n", i * j, cp);
1158 #endif
1159 	return(cp);
1160 }
1161 
1162 nfree(cp)
1163 char *cp;
1164 {
1165 #ifdef DEBUGABLE
1166 	if (dbg) fprintf(stderr, "freeing at %x\n", cp);
1167 #endif
1168 	free(cp);
1169 }
1170 
1171 
1172 /*
1173  * Points should be in the range 0 <= x < RASTER_LENGTH, 0 <= y < NLINES.
1174  * The origin is the top left-hand corner with increasing x towards the
1175  * right and increasing y going down.
1176  * The output array is NLINES x BYTES_PER_LINE pixels.
1177  */
1178 point(x, y)
1179 register int x, y;
1180 {
1181     if ((unsigned) x < RASTER_LENGTH && (unsigned) y < NLINES) {
1182 	buffer [y * BYTES_PER_LINE + (x >> 3)] |= 1 << (7 - (x & 07));
1183     }
1184 }
1185