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