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