xref: /original-bsd/old/vfilters/rvcat/rvcat.c (revision 73949c1b)
1 /*
2  * Copyright (c) 1983 Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #ifndef lint
9 char copyright[] =
10 "@(#) Copyright (c) 1983 Regents of the University of California.\n\
11  All rights reserved.\n";
12 #endif /* not lint */
13 
14 #ifndef lint
15 static char sccsid[] = "@(#)rvcat.c	5.6 (Berkeley) 02/15/91";
16 #endif /* not lint */
17 
18 /*
19  * Cat Simulator for Versatec and Varian
20  * Modified for Varian with rotated fonts: wnj 5/30/80.
21  *
22  * Takes two extra special codes defined by rvsort:
23  *	0115 - break for new page, goto (0,0)
24  *	0116 - lead 64* following byte
25  */
26 
27 #include <stdio.h>
28 #include <sys/vcmd.h>
29 #include <vfont.h>
30 
31 int	prtmode[] = {VPRINT};
32 int	pltmode[] = {VPLOT};
33 
34 #define DISPATCHSIZE		256	/* must be a power of two */
35 #define CHARMASK		(DISPATCHSIZE-1)
36 #define NFONTS			25
37 #define SPECIALFONT		3
38 #define DSIZ			((sizeof *dispatch)*DISPATCHSIZE)
39 #define MAXF			4
40 
41 #define LOCAL_RAILMAG		".railmag"
42 #define GLOBAL_RAILMAG		"/usr/lib/vfont/railmag"
43 
44 /*
45  * Here we make up for the fact that we only have 2112
46  * bits vertically when we need 2200 (11''*200/in), by
47  * a 4% vertical size squashing.
48  */
49 #define CONVERT(n)		((n*(200./432.))*(2112./2200.))
50 #define RECONVERT(n)		((n*(432./200.))*(2200./2112.))
51 
52 #define NLINES			110
53 
54 #define	FF_LINES		1600	/* Scan lines to output before formfeeding. */
55 
56 #define	min(a,b)		(a<b ? a : b)
57 
58 char	buffer[NLINES * 264];	/* Big enough for varain */
59 char	*buf0p = &buffer[0];	/* Zero origin in circular buffer */
60 
61 char	*calloc();
62 char	*nalloc();
63 char	*allpanic();
64 
65 struct	header	header;
66 struct dispatch *dispatch;
67 
68 struct	fontdes {
69 	int	fnum;
70 	int	psize;
71 	struct	dispatch *disp;
72 	char	*bits;
73 } fontdes[NFONTS] = {
74 	-1,
75 	-1
76 };
77 
78 struct point_sizes {
79 	int	stupid_code;
80 	int	real_code;
81 } point_sizes[] = {
82 	010, 6,
83 	0, 7,
84 	01, 8,
85 	07, 9,
86 	02, 10,
87 	03, 11,
88 	04, 12,
89 	05, 14,
90 	0211, 16,
91 	06, 18,
92 	0212, 20,
93 	0213, 22,
94 	0214, 24,
95 	0215, 28,
96 	0216, 36,
97 	0, 0
98 };
99 
100 int	lines;
101 
102 int	vc = 1;			/* varian/versatec output file descriptor */
103 int	varian = 1;		/* 0 for versatec, 1 for varian. */
104 int	BYTES_PER_LINE = 264;	/* number of bytes per raster line. */
105 int	PAGE_LINES = 1700;	/* number of raster lines per page. */
106 int	BUFFER_SIZE = NLINES * 264;	/* buffer size. */
107 int	cfnum = -1;
108 int	cpsize = 10;
109 int	cfont = 1;
110 char	*bits;
111 int	nfontnum = -1;
112 int	fontwanted = 1;
113 int	npsize = 10;
114 int	last_ssize = 02;
115 int	xpos, ypos;
116 int	esc, lead, back, verd, mcase, railmag;
117 double	row, col;
118 char	*fontname[MAXF];
119 char	fnbuf[120];
120 char	*scanline;
121 int	linecount;
122 
123 char	asctab[128] = {
124 	'\0',	/*blank*/
125 	'h',	/*h*/
126 	't',	/*t*/
127 	'n',	/*n*/
128 	'm',	/*m*/
129 	'l',	/*l*/
130 	'i',	/*i*/
131 	'z',	/*z*/
132 	's',	/*s*/
133 	'd',	/*d*/
134 	'b',	/*b*/
135 	'x',	/*x*/
136 	'f',	/*f*/
137 	'j',	/*j*/
138 	'u',	/*u*/
139 	'k',	/*k*/
140 	'\0',	/*blank*/
141 	'p',	/*p*/
142 	'\06',	/*_ 3/4 em dash*/
143 	';',	/*;*/
144 	'\0',	/*blank*/
145 	'a',	/*a*/
146 	'\05',	/*rule*/
147 	'c',	/*c*/
148 	'`',	/*` open*/
149 	'e',	/*e*/
150 	'\'',	/*' close*/
151 	'o',	/*o*/
152 	'\021',	/*1/4*/
153 	'r',	/*r*/
154 	'\022',	/*1/2*/
155 	'v',	/*v*/
156 	'-',	/*- hyphen*/
157 	'w',	/*w*/
158 	'q',	/*q*/
159 	'/',	/*/*/
160 	'.',	/*.*/
161 	'g',	/*g*/
162 	'\023',	/*3/4*/
163 	',',	/*,*/
164 	'&',	/*&*/
165 	'y',	/*y*/
166 	'\0',	/*blank*/
167 	'%',	/*%*/
168 	'\0',	/*blank*/
169 	'Q',	/*Q*/
170 	'T',	/*T*/
171 	'O',	/*O*/
172 	'H',	/*H*/
173 	'N',	/*N*/
174 	'M',	/*M*/
175 	'L',	/*L*/
176 	'R',	/*R*/
177 	'G',	/*G*/
178 	'I',	/*I*/
179 	'P',	/*P*/
180 	'C',	/*C*/
181 	'V',	/*V*/
182 	'E',	/*E*/
183 	'Z',	/*Z*/
184 	'D',	/*D*/
185 	'B',	/*B*/
186 	'S',	/*S*/
187 	'Y',	/*Y*/
188 	'\0',	/*blank*/
189 	'F',	/*F*/
190 	'X',	/*X*/
191 	'A',	/*A*/
192 	'W',	/*W*/
193 	'J',	/*J*/
194 	'U',	/*U*/
195 	'K',	/*K*/
196 	'0',	/*0*/
197 	'1',	/*1*/
198 	'2',	/*2*/
199 	'3',	/*3*/
200 	'4',	/*4*/
201 	'5',	/*5*/
202 	'6',	/*6*/
203 	'7',	/*7*/
204 	'8',	/*8*/
205 	'9',	/*9*/
206 	'*',	/***/
207 	'\04',	/*minus*/
208 	'\01',	/*fi*/
209 	'\02',	/*fl*/
210 	'\03',	/*ff*/
211 	'\020',	/* cent sign */
212 	'\012',	/*ffl*/
213 	'\011',	/*ffi*/
214 	'(',	/*(*/
215 	')',	/*)*/
216 	'[',	/*[*/
217 	']',	/*]*/
218 	'\013',	/* degree */
219 	'\014',	/* dagger */
220 	'=',	/*=*/
221 	'\017',	/* registered */
222 	':',	/*:*/
223 	'+',	/*+*/
224 	'\0',	/*blank*/
225 	'!',	/*!*/
226 	'\07',	/* bullet */
227 	'?',	/*?*/
228 	'\015',	/*foot mark*/
229 	'|',	/*|*/
230 	'\0',	/*blank*/
231 	'\016',	/* copyright */
232 	'\010',	/* square */
233 	'$',	/*$*/
234 	'\0',
235 	'\0',
236 	'"',	/*"*/
237 	'#',	/*#*/
238 	'<',	/*<*/
239 	'>',	/*>*/
240 	'@',	/*@*/
241 	'\\',	/*\\*/
242 	'^',	/*^*/
243 	'{',	/*{*/
244 	'}',	/*}*/
245 	'~'	/*~*/
246 };
247 
248 char spectab[128] = {
249 	'\0',	/*blank*/
250 	'w',	/*psi*/
251 	'h',	/*theta*/
252 	'm',	/*nu*/
253 	'l',	/*mu*/
254 	'k',	/*lambda*/
255 	'i',	/*iota*/
256 	'f',	/*zeta*/
257 	'r',	/*sigma*/
258 	'd',	/*delta*/
259 	'b',	/*beta*/
260 	'n',	/*xi*/
261 	'g',	/*eta*/
262 	'u',	/*phi*/
263 	't',	/*upsilon*/
264 	'j',	/*kappa*/
265 	'\0',	/*blank*/
266 	'p',	/*pi*/
267 	'@',	/*at-sign*/
268 	'7',	/*down arrow*/
269 	'\0',	/*blank*/
270 	'a',	/*alpha*/
271 	'|',	/*or*/
272 	'v',	/*chi*/
273 	'"',	/*"*/
274 	'e',	/*epsilon*/
275 	'=',	/*=*/
276 	'o',	/*omicron*/
277 	'4',	/*left arrow*/
278 	'q',	/*rho*/
279 	'6',	/*up arrow*/
280 	's',	/*tau*/
281 	'_',	/*underrule*/
282 	'\\',	/*\*/
283 	'W',	/*Psi*/
284 	'\07',	/*bell system sign*/
285 	'\001',	/*infinity*/
286 	'c',	/*gamma*/
287 	'\002',	/*improper superset*/
288 	'\003',	/*proportional to*/
289 	'\004',	/*right hand*/
290 	'x',	/*omega*/
291 	'\0',	/*blank*/
292 	'(',	/*gradient*/
293 	'\0',	/*blank*/
294 	'U',	/*Phi*/
295 	'H',	/*Theta*/
296 	'X',	/*Omega*/
297 	'\005',	/*cup (union)*/
298 	'\006',	/*root en*/
299 	'\014',	/*terminal sigma*/
300 	'K',	/*Lambda*/
301 	'-',	/*minus*/
302 	'C',	/*Gamma*/
303 	'\015',	/*integral sign*/
304 	'P',	/*Pi*/
305 	'\032',	/*subset of*/
306 	'\033',	/*superset of*/
307 	'2',	/*approximates*/
308 	'y',	/*partial derivative*/
309 	'D',	/*Delta*/
310 	'\013',	/*square root*/
311 	'R',	/*Sigma*/
312 	'1',	/*approx =*/
313 	'\0',	/*blank*/
314 	'>',	/*>*/
315 	'N',	/*Xi*/
316 	'<',	/*<*/
317 	'\016',	/*slash (longer)*/
318 	'\034',	/*cap (intersection)*/
319 	'T',	/*Upsilon*/
320 	'\035',	/*not*/
321 	'\023',	/*right ceiling (rt of ")*/
322 	'\024',	/*left top (of big curly)*/
323 	'\017',	/*bold vertical*/
324 	'\030',	/*left center of big curly bracket*/
325 	'\025',	/*left bottom*/
326 	'\026',	/*right top*/
327 	'\031',	/*right center of big curly bracket*/
328 	'\027',	/*right bot*/
329 	'\021',	/*right floor (rb of ")*/
330 	'\020',	/*left floor (left bot of big sq bract)*/
331 	'\022',	/*left ceiling (lt of ")*/
332 	'*',	/*multiply*/
333 	'/',	/*divide*/
334 	'\010',	/*plus-minus*/
335 	'\011',	/*<=*/
336 	'\012',	/*>=*/
337 	'0',	/*identically equal*/
338 	'3',	/*not equal*/
339 	'{',	/*{*/
340 	'}',	/*}*/
341 	'\'',	/*' acute accent*/
342 	'`',	/*` grave accent*/
343 	'^',	/*^*/
344 	'#',	/*sharp*/
345 	'\036',	/*left hand*/
346 	'\037',	/*member of*/
347 	'~',	/*~*/
348 	'z',	/*empty set*/
349 	'\0',	/*blank*/
350 	'Y',	/*dbl dagger*/
351 	'Z',	/*box rule*/
352 	'9',	/*asterisk*/
353 	'[',	/*improper subset*/
354 	']',	/*circle*/
355 	'\0',	/*blank*/
356 	'+',	/*eqn plus*/
357 	'5',	/*right arrow*/
358 	'8'	/*section mark*/
359 };
360 
361 main(argc, argv)
362 	int argc;
363 	char *argv[];
364 {
365 	char *namearg = NULL;
366 	char *hostarg = NULL;
367 	char *acctfile = NULL;
368 
369 	while (--argc) {
370 		if (*(*++argv) == '-')
371 			switch (argv[0][1]) {
372 			case 'x':
373 				BYTES_PER_LINE = atoi(&argv[0][2]) / 8;
374 				BUFFER_SIZE = NLINES * BYTES_PER_LINE;
375 				break;
376 
377 			case 'y':
378 				PAGE_LINES = atoi(&argv[0][2]);
379 				break;
380 
381 			case 'n':
382 				if (argc > 1) {
383 					argc--;
384 					namearg = *++argv;
385 				}
386 				break;
387 
388 			case 'h':
389 				if (argc > 1) {
390 					argc--;
391 					hostarg = *++argv;
392 				}
393 				break;
394 			}
395 		else
396 			acctfile = *argv;
397 	}
398 	ioctl(vc, VSETSTATE, pltmode);
399 	readrm();
400 	ofile();
401 	ioctl(vc, VSETSTATE, prtmode);
402 	if (varian)
403 		write(vc, "\f", 2);
404 	else
405 		write(vc, "\n\n\n\n\n", 6);
406 	account(namearg, hostarg, acctfile);
407 	exit(0);
408 }
409 
410 readrm()
411 {
412 	register int i;
413 	register char *cp;
414 	register int rmfd;
415 	char c;
416 
417 	if ((rmfd = open(LOCAL_RAILMAG, 0)) < 0)
418 		if ((rmfd = open(GLOBAL_RAILMAG, 0)) < 0) {
419 			fprintf(stderr, "rvcat: No railmag file\n");
420 			exit(2);
421 		}
422 	cp = fnbuf;
423 	for (i = 0; i < MAXF; i++) {
424 		fontname[i] = cp;
425 		while (read(rmfd, &c, 1) == 1 && c != '\n')
426 			*cp++ = c;
427 		*cp++ = '\0';
428 	}
429 	close(rmfd);
430 }
431 
432 ofile()
433 {
434 	register int c;
435 	register int i;
436 	double scol;
437 	static int initialized;
438 
439 	lines = 0;
440 	while ((c = getchar()) != EOF) {
441 		if (!c)
442 			continue;
443 		if (c & 0200) {
444 			esc += (~c) & 0177;
445 			continue;
446 		}
447 		if (esc) {
448 			if (back)
449 				esc = -esc;
450 			col += esc;
451 			esc = 0;
452 			i = CONVERT(col);
453 			while (i >= NLINES) {
454 				slop_lines(15);
455 				i = CONVERT(col);
456 			}
457 			ypos = i;
458 		}
459 		if ((c & 0377) < 0100)	/*  Purely for efficiency  */
460 			goto normal_char;
461 		switch (c) {
462 
463 		case 0100:
464 			esc = 0;
465 			lead = 0;
466 			linecount = 0;
467 			verd = 0;
468 			back = 0;
469 			mcase = 0;
470 			railmag = 0;
471 			if (loadfont(railmag, cpsize) < 0)
472 				fprintf(stderr, "rvcat: Can't load initial font\n");
473 			if (initialized)
474 				goto reset;
475 			initialized = 1;
476 			row = 0;
477 			xpos = CONVERT(row);
478 			for (c = 0; c < BUFFER_SIZE; c++)
479 				buffer[c] = 0;
480 			col = 0;
481 			ypos = 0;
482 			break;
483 
484 		case 0101:	/* lower rail */
485 			crail(railmag &= ~01);
486 			break;
487 
488 		case 0102:	/* upper rail */
489 			crail(railmag |= 01);
490 			break;
491 
492 		case 0103:	/* upper mag */
493 			crail(railmag |= 02);
494 			break;
495 
496 		case 0104:	/* lower mag */
497 			crail(railmag &= ~02);
498 			break;
499 
500 		case 0105:	/* lower case */
501 			mcase = 0;
502 			break;
503 
504 		case 0106:	/* upper case */
505 			mcase = 0100;
506 			break;
507 
508 		case 0107:	/* escape forward */
509 			back = 0;
510 			break;
511 
512 		case 0110:	/* escape backwards */
513 			back = 1;
514 			break;
515 
516 		case 0111:	/* stop */
517 			break;
518 
519 		case 0112:	/* lead forward */
520 			verd = 0;
521 			break;
522 
523 		case 0113:	/* undefined */
524 			break;
525 
526 		case 0114:	/* lead backward */
527 			verd = 1;
528 			break;
529 
530 		case 0115:	/* undefined */
531 reset:
532 			c = lines % PAGE_LINES;
533 			while (c < FF_LINES) {
534 				slop_lines(min(FF_LINES - c, NLINES));
535 				c = lines % PAGE_LINES;
536 			}
537 			new_page(PAGE_LINES - c);
538 			break;
539 
540 		case 0116:
541 			lead = (getchar() & 0377) * 64;
542 			goto leadin;
543 
544 		case 0117:
545 			break;
546 
547 		default:
548 			if ((c & 0340) == 0140)	/* leading */ {
549 				lead = (~c) & 037;
550 leadin:
551 				if (verd)
552 					lead = -lead;
553 				row += lead*3;	/*  Lead is 3 units  */
554 				xpos = CONVERT(row);
555 				continue;
556 			}
557 			if ((c & 0360) == 0120)	/* size change */ {
558 				loadfont(railmag, findsize(c & 017));
559 				continue;
560 			}
561 			if (c & 0300)
562 				continue;
563 
564 normal_char:
565 			if (row < 0 || CONVERT(row) >= BYTES_PER_LINE * 8)
566 				continue;
567 			c = (c & 077) | mcase;
568 			outc(c);
569 		}
570 	}
571 out:
572 	slop_lines(NLINES);
573 }
574 
575 findsize(code)
576 	register int code;
577 {
578 	register struct point_sizes *psp;
579 
580 	psp = point_sizes;
581 	while (psp->real_code != 0) {
582 		if ((psp->stupid_code & 017) == code)
583 			break;
584 		psp++;
585 	}
586 	code = 0;
587 	if (!(last_ssize & 0200) && (psp->stupid_code & 0200))
588 		code = -55;
589 	else if ((last_ssize & 0200) && !(psp->stupid_code & 0200))
590 		code = 55;
591 	if (back)
592 		code = -code;
593 	esc += code;
594 	last_ssize = psp->stupid_code;
595 	return(psp->real_code);
596 }
597 
598 account(who, from, acctfile)
599 	char *who, *from, *acctfile;
600 {
601 	register FILE *a;
602 
603 	if (who == NULL || acctfile == NULL)
604 		return;
605 	if (access(acctfile, 02) || (a = fopen(acctfile, "a")) == NULL)
606 		return;
607 	/*
608 	 * Varian accounting is done by 8.5 inch pages;
609 	 * Versatec accounting is by the (12 inch) foot.
610 	 */
611 	fprintf(a, "t%6.2f\t", (double)lines / (double)PAGE_LINES);
612 	if (from != NULL)
613 		fprintf(a, "%s:", from);
614 	fprintf(a, "%s\n", who);
615 	fclose(a);
616 }
617 
618 crail(nrail)
619 	register int nrail;
620 {
621 	register int psize;
622 
623 	psize = cpsize;
624 	if (fontwanted && psize != npsize)
625 		psize = npsize;
626 	loadfont(nrail, psize);
627 }
628 
629 
630 loadfont(fnum, size)
631 	register int fnum;
632 	register int size;
633 {
634 	register int i;
635 	char cbuf[80];
636 
637 	fontwanted = 0;
638 	if (fnum == cfnum && size == cpsize)
639 		return(0);
640 	for (i = 0; i < NFONTS; i++)
641 		if (fontdes[i].fnum == fnum && fontdes[i].psize == size) {
642 			cfnum = fontdes[i].fnum;
643 			cpsize = fontdes[i].psize;
644 			dispatch = &fontdes[i].disp[0];
645 			bits = fontdes[i].bits;
646 			cfont = i;
647 			return(0);
648 		}
649 	if (fnum < 0 || fnum >= MAXF) {
650 		fprintf(stderr, "rvcat: Internal error: illegal font\n");
651 		return(-1);
652 	}
653 	nfontnum = fnum;
654 	npsize = size;
655 	fontwanted++;
656 	return(0);
657 }
658 
659 
660 getfont()
661 {
662 	register int fnum, size, font;
663 	int d;
664 	char cbuf[BUFSIZ];
665 	char *cp = cbuf;
666 	char *dp;
667 
668 	if (!fontwanted)
669 		return(0);
670 	fnum = nfontnum;
671 	size = npsize;
672 	sprintf(cbuf, "%s.%dr", fontname[fnum], size);
673 	font = open(cbuf, 0);
674 	if (font == -1) {
675 		fprintf(stderr, "rvcat: ");
676 		perror(cbuf);
677 		fontwanted = 0;
678 		return(-1);
679 	}
680 	if (read(font, &header, sizeof header)!=sizeof header || header.magic!=0436)
681 		fprintf(stderr, "rvcat: %s: Bad font file", cbuf);
682 	else {
683 		cfont = relfont();
684 		if (((bits=nalloc(header.size+DSIZ+1,1))== NULL)
685 			&& ((bits=allpanic(header.size+DSIZ+1))== NULL)) {
686 				fprintf(stderr, "rvcat: %s: ran out of memory\n", cbuf);
687 				exit(2);
688 		} else {
689 			/*
690 			 * have allocated one chunk of mem for font, dispatch.
691 			 * get the dispatch addr, align to word boundary.
692 			 */
693 			d = (int) bits+header.size;
694 			d += 1;
695 			d &= ~1;
696 			if (read(font, d, DSIZ)!=DSIZ
697 			  || read(font, bits, header.size)!=header.size)
698 				fprintf(stderr, "rvcat: bad font header");
699 			else {
700 				close(font);
701 				cfnum = fontdes[cfont].fnum = fnum;
702 				cpsize = fontdes[cfont].psize = size;
703 				fontdes[cfont].bits = bits;
704 				fontdes[cfont].disp = (struct dispatch *) d;
705 				dispatch = &fontdes[cfont].disp[0];
706 				fontwanted = 0;
707 				return(0);
708 			}
709 		}
710 	}
711 	close(font);
712 	fontwanted = 0;
713 	return(-1);
714 }
715 
716 int lastloaded = -1;
717 
718 relfont()
719 {
720 	register int newfont;
721 
722 	newfont = lastloaded;
723 	/*
724 	 * optimization for special font.  since we think that usually
725 	 * there is only one character at a time from any special math
726 	 * font, make it the candidate for removal.
727 	 */
728 	if (fontdes[cfont].fnum != SPECIALFONT || fontdes[cfont].bits==0)
729 		if (++newfont>=NFONTS)
730 			newfont = 0;
731 	lastloaded = newfont;
732 	if ((int)fontdes[newfont].bits != -1 && fontdes[newfont].bits != 0)
733 		nfree(fontdes[newfont].bits);
734 	fontdes[newfont].bits = 0;
735 	return(newfont);
736 }
737 
738 char *
739 allpanic(nbytes)
740 	int nbytes;
741 {
742 	register int i;
743 
744 	for (i = 0; i <= NFONTS; i++)
745 		if (fontdes[i].bits != (char *)-1 && fontdes[i].bits != (char *)0)
746 			nfree(fontdes[i].bits);
747 	lastloaded = cfont;
748 	for (i = 0; i <= NFONTS; i++) {
749 		fontdes[i].fnum = fontdes[i].psize = -1;
750 		fontdes[i].bits = 0;
751 		cfnum = cpsize = -1;
752 	}
753 	return(nalloc(nbytes,1));
754 }
755 
756 int	M[] = { 0xffffffff, 0xfefefefe, 0xfcfcfcfc, 0xf8f8f8f8,
757 		0xf0f0f0f0, 0xe0e0e0e0, 0xc0c0c0c0, 0x80808080, 0x0 };
758 int	N[] = { 0x00000000, 0x01010101, 0x03030303, 0x07070707,
759 		0x0f0f0f0f, 0x1f1f1f1f, 0x3f3f3f3f, 0x7f7f7f7f, 0xffffffff };
760 int	strim[] = { 0xffffffff, 0xffffff00, 0xffff0000, 0xff000000, 0 };
761 
762 outc(code)
763 	int code;
764 {
765 	char c;				/* character to print */
766 	register struct dispatch *d;	/* ptr to character font record */
767 	register char *addr;		/* addr of font data */
768 	int llen;			/* length of each font line */
769 	int nlines;			/* number of font lines */
770 	register char *scanp;		/* ptr to output buffer */
771 	int scanp_inc;			/* increment to start of next buffer */
772 	int offset;			/* bit offset to start of font data */
773 	int i;				/* loop counter */
774 	register int count;		/* font data ptr */
775 	register unsigned fontdata;	/* font data temporary */
776 	register int off8;		/* offset + 8 */
777 	int b0poff;			/* bit offset back towards buf0p */
778 
779 	if (fontwanted)
780 		getfont();
781 	if (railmag == SPECIALFONT) {
782 		if ((c = spectab[code]) < 0)
783 			return(0);
784 	} else if ((c = asctab[code]) < 0)
785 		return(0);
786 	d = dispatch+c;
787 	if (d->nbytes) {
788 		addr = bits+d->addr;
789 		llen = (d->down+d->up+7)/8;
790 		nlines = d->left+d->right;
791 		if (ypos+d->right >= NLINES)
792 			slop_lines(ypos+d->right-NLINES+6);
793 		b0poff = BYTES_PER_LINE*8 - 1 - (xpos+d->down);
794 		scanp = ((ypos-d->left-1)*BYTES_PER_LINE+b0poff/8)+buf0p;
795 		if (scanp < &buffer[0])
796 			scanp += BUFFER_SIZE;
797 		scanp_inc = BYTES_PER_LINE-llen;
798 		offset = -(b0poff&07);
799 		off8 = offset+8;
800 		for (i = 0; i < nlines; i++) {
801 			if (scanp >= &buffer[BUFFER_SIZE])
802 				scanp -= BUFFER_SIZE;
803 			count = llen;
804 			if (scanp + count <= &buffer[BUFFER_SIZE])
805 				do {
806 					fontdata = *(unsigned *)addr;
807 					addr += 4;
808 					if (count < 4)
809 						fontdata &= ~strim[count];
810 					*(unsigned *)scanp |= (fontdata << offset) &~ M[off8];
811 					scanp++;
812 					*(unsigned *)scanp |= (fontdata << off8) &~ N[off8];
813 					scanp += 3;
814 					count -= 4;
815 				} while (count > 0);
816 			scanp += scanp_inc+count;
817 			addr += count;
818 		}
819 		return(1);
820 	}
821 	return(0);
822 }
823 
824 slop_lines(ncols)
825 	int ncols;
826 {
827 	register int i, rcols;
828 
829 	lines += ncols;
830 	rcols = (&buffer[BUFFER_SIZE] - buf0p) / BYTES_PER_LINE;
831 	if (rcols < ncols) {
832 		if (write(vc, buf0p, BYTES_PER_LINE * rcols) < 0)
833 			exit(1);
834 		bzero(buf0p, rcols * BYTES_PER_LINE);
835 		buf0p = buffer;
836 		ncols -= rcols;
837 		ypos -= rcols;
838 		col -= RECONVERT(rcols);
839 	}
840 	if (write(vc, buf0p, BYTES_PER_LINE * ncols) < 0)
841 		exit(1);
842 	bzero(buf0p, BYTES_PER_LINE * ncols);
843 	buf0p += BYTES_PER_LINE * ncols;
844 	if (buf0p >= &buffer[BUFFER_SIZE])
845 		buf0p -= BUFFER_SIZE;
846 	ypos -= ncols;
847 	col -= RECONVERT(ncols);
848 }
849 
850 /* Start a new page by formfeeding, resetting buffer and column counters. */
851 new_page(lines_left)
852 	int lines_left;		/* ... on page. */
853 {
854 	lines += lines_left;
855 	buf0p = buffer;		/* Clear out buffer and reset pointers. */
856 	bzero(buf0p, BYTES_PER_LINE * NLINES);
857 	row = 0;
858 	col = 0;
859 	xpos = CONVERT(row);
860 	ypos = 0;
861 	ioctl(vc, VSETSTATE, prtmode);
862 	write (vc, "\f", 2);
863 	ioctl(vc, VSETSTATE, pltmode);
864 }
865 
866 char *
867 nalloc(i, j)
868 	int i, j;
869 {
870 	register char *cp;
871 
872 	cp = calloc(i, j);
873 	return(cp);
874 }
875 
876 nfree(cp)
877 	char *cp;
878 {
879 	free(cp);
880 }
881