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