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