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