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