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