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