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