|
|
1.1 root 1: /*
2: * drive 202 typesetter
3: */
4:
5: /*
6: output language from troff:
7: all numbers are character strings
8:
9: sn size in points
10: fn font as number from 1-n
11: cx ascii character x
12: Cxyz funny char xyz. terminated by white space
13: Nn absolute character number n on this font. ditto
14: Hn go to absolute horizontal position n
15: Vn go to absolute vertical position n (down is positive)
16: hn go n units horizontally (relative)
17: vn ditto vertically
18: nnc move right nn, then print c (exactly 2 digits!)
19: (this wart is an optimization that shrinks output file size
20: about 35% and run-time about 15% while preserving ascii-ness)
21: Dt ...\n draw operation 't':
22: Dl x y line from here by x,y
23: Dc d circle of diameter d with left side here
24: De x y ellipse of axes x,y with left side here
25: Da dx dy dx dy arc counter-clockwise, center at dx,dx, end at dx,dy
26: D~ x y x y ... wiggly line by x,y then x,y ...
27: nb a end of line (information only -- no action needed)
28: w paddable word space -- no action needed
29: b = space before line, a = after
30: p new page begins -- set v to 0
31: #...\n comment
32: x ...\n device control functions:
33: x i init
34: x T s name of device is s
35: x r n h v resolution is n/inch
36: h = min horizontal motion, v = min vert
37: x p pause (can restart)
38: x s stop -- done for ever
39: x t generate trailer
40: x f n s font position n contains font s
41: x H n set character height to n
42: x S n set slant to N
43:
44: Subcommands like "i" are often spelled out like "init".
45: */
46:
47: #include <stdio.h>
48: #include <ctype.h>
49: #include <signal.h>
50:
51: #include "dev.h"
52: #define NFONT 10
53:
54: int output = 0; /* do we do output at all? */
55: int nolist = 0; /* output page list if > 0 */
56: #define N_OLIST 100
57: int olist[N_OLIST]; /* pairs of page numbers */
58: int spage = 9999; /* stop every spage pages */
59: int scount = 0;
60: int xoffset = 0; /* units are typesetter goobies! */
61:
62: struct dev dev;
63: struct Font *fontbase[NFONT+1];
64: short *pstab;
65: int nsizes;
66: int nfonts;
67: int smnt; /* index of first special font */
68: int nchtab;
69: char *chname;
70: short *chtab;
71: char *fitab[NFONT+1];
72: char *widthtab[NFONT+1]; /* widtab would be a better name */
73: char *codetab[NFONT+1]; /* device codes */
74:
75: #define FATAL 1
76: #define BYTEMASK 0377
77: int dbg = 0;
78: int windowht = 250; /* resettable logical height of d202 faceplate */
79: int res; /* input assumed computed according to this resolution */
80:
81: char *typesetter = "/dev/202";
82: FILE *tf = NULL; /* output file */
83: char *fontdir = "/usr/lib/font";
84: extern char devname[];
85:
86: #define hmot(n) hpos += n
87: #define hgoto(n) hpos = n
88: #define vmot(n) vgoto(vpos + n)
89:
90: int size = -1; /* this is invalid */
91: int font = -1; /* current font */
92: int hpos; /* horizontal position where we are supposed to be next (left = 0) */
93: int oldh; /* previous H position */
94: int vpos; /* current vertical position (down positive) */
95: int oldv; /* current pos in 1/4 point units */
96: int horig; /* h origin of current block; hpos rel to this */
97: int vorig;
98: int DX = 2; /* step size in x for drawing */
99: int DY = 2; /* step size in y for drawing */
100: int drawdot = 0; /* draw with this character */
101: int drawsize = 1; /* shrink by this factor when drawing */
102:
103: main(argc, argv)
104: char *argv[];
105: {
106: FILE *fp;
107: int i;
108: int busyflag = 0;
109: int waitflag = 0;
110: int done();
111:
112: while (argc > 1 && argv[1][0] == '-') {
113: switch (argv[1][1]) {
114: case 'f':
115: case 'F':
116: fontdir = argv[2];
117: argv++;
118: argc--;
119: break;
120: case 't':
121: tf = stdout;
122: break;
123: case 'o':
124: outlist(&argv[1][2]);
125: break;
126: case 'd':
127: dbg = atoi(&argv[1][2]);
128: if (dbg == 0) dbg = 1;
129: tf = stdout;
130: break;
131: case 'b':
132: busyflag = 1;
133: break;
134: case 'w':
135: waitflag = 1;
136: break;
137: case 's':
138: spage = atoi(&argv[1][2]);
139: if (spage <= 0)
140: spage = 9999;
141: break;
142: case 'x': /* x offset */
143: xoffset = atoi(&argv[1][2]);
144: break;
145: case 'i':
146: windowht = atoi(&argv[1][2]);
147: break;
148: case 'D':
149: if (argv[1][2] == 'X') DX = atoi(&argv[1][3]);
150: else if (argv[1][2] == 'Y') DY = atoi(&argv[1][3]);
151: else DX = DY = atoi(&argv[1][2]);
152: break;
153: case '.':
154: drawdot = argv[1][2];
155: break;
156: }
157: argc--;
158: argv++;
159: }
160: tryagain:
161: if (tf != stdout)
162: tf = fopen(typesetter, "w");
163: if (busyflag) {
164: printf(tf==NULL? "Busy.\n": "Available.\n");
165: exit(0);
166: }
167: if (tf == NULL) {
168: if (waitflag == 0) {
169: error(!FATAL, "can't open typesetter\n");
170: exit(1);
171: } else {
172: sleep(60);
173: goto tryagain;
174: }
175: }
176:
177: if (signal(SIGINT, done) == SIG_IGN) {
178: signal(SIGINT, SIG_IGN);
179: signal(SIGQUIT, SIG_IGN);
180: signal(SIGHUP, SIG_IGN);
181: } else {
182: signal(SIGQUIT, done);
183: signal(SIGHUP, done);
184: }
185: signal(SIGTERM, done);
186:
187: if (argc <= 1)
188: conv(stdin);
189: else
190: while (--argc > 0) {
191: if (strcmp(*++argv, "-") == 0)
192: fp = stdin;
193: else if ((fp = fopen(*argv, "r")) == NULL)
194: error(FATAL, "can't open %s", *argv);
195: conv(fp);
196: fclose(fp);
197: }
198: account();
199: done();
200: }
201:
202: int maxolist = 9999; /* largest page number in -o */
203:
204: outlist(s) /* process list of page numbers to be printed */
205: char *s;
206: {
207: int n1, n2, i;
208:
209: nolist = 0;
210: while (*s) {
211: n1 = 0;
212: if (isdigit(*s))
213: do
214: n1 = 10 * n1 + *s++ - '0';
215: while (isdigit(*s));
216: else
217: n1 = -9999;
218: n2 = n1;
219: if (*s == '-') {
220: s++;
221: n2 = 0;
222: if (isdigit(*s))
223: do
224: n2 = 10 * n2 + *s++ - '0';
225: while (isdigit(*s));
226: else
227: n2 = 9999;
228: }
229: if (nolist > N_OLIST-2)
230: error(FATAL, "too many items in -o");
231: olist[nolist++] = n1;
232: olist[nolist++] = n2;
233: if (n2 > maxolist)
234: maxolist = n2;
235: if (*s != '\0')
236: s++;
237: }
238: olist[nolist] = 0;
239: if (dbg)
240: for (i=0; i<nolist; i += 2)
241: printf("%3d %3d\n", olist[i], olist[i+1]);
242: }
243:
244: conv(fp)
245: register FILE *fp;
246: {
247: register int c, k, sign;
248: int m, n, i, n1, m1;
249: char str[100], buf[300];
250:
251: while ((c = getc(fp)) != EOF) {
252: switch (c) {
253: case '\n': /* when input is text */
254: case ' ':
255: case 0: /* occasional noise creeps in */
256: break;
257: case '{': /* push down current environment */
258: t_push();
259: break;
260: case '}':
261: t_pop();
262: break;
263: case '0': case '1': case '2': case '3': case '4':
264: case '5': case '6': case '7': case '8': case '9':
265: /* two motion digits plus a character */
266: hmot((c-'0')*10 + getc(fp)-'0');
267: put1(getc(fp));
268: break;
269: case 'c': /* single ascii character */
270: put1(getc(fp));
271: break;
272: case 'C':
273: fscanf(fp, "%s", str);
274: put1s(str);
275: break;
276: case 'N': /* absolute character number */
277: fscanf(fp, "%d", &n);
278: put1a(n);
279: break;
280: case 't': /* straight text */
281: fgets(buf, sizeof(buf), fp);
282: t_text(buf);
283: break;
284: case 'D': /* draw function */
285: fgets(buf, sizeof(buf), fp);
286: switch (buf[0]) {
287: case 'l': /* draw a line */
288: sscanf(buf+1, "%d %d", &n, &m);
289: drawline(n, m, ".");
290: break;
291: case 'c': /* circle */
292: sscanf(buf+1, "%d", &n);
293: drawcirc(n);
294: break;
295: case 'e': /* ellipse */
296: sscanf(buf+1, "%d %d", &m, &n);
297: drawellip(m, n);
298: break;
299: case 'a': /* arc */
300: sscanf(buf+1, "%d %d %d %d", &n, &m, &n1, &m1);
301: drawarc(n, m, n1, m1);
302: break;
303: case '~': /* wiggly line */
304: drawwig(buf+1);
305: break;
306: default:
307: error(FATAL, "unknown drawing function %s\n", buf);
308: break;
309: }
310: break;
311: case 's':
312: fscanf(fp, "%d", &n); /* ignore fractional sizes */
313: setsize(t_size(n));
314: break;
315: case 'f':
316: fscanf(fp, "%s", str);
317: setfont(t_font(str));
318: break;
319: case 'H': /* absolute horizontal motion */
320: /* fscanf(fp, "%d", &n); */
321: while ((c = getc(fp)) == ' ')
322: ;
323: k = 0;
324: do {
325: k = 10 * k + c - '0';
326: } while (isdigit(c = getc(fp)));
327: ungetc(c, fp);
328: hgoto(k);
329: break;
330: case 'h': /* relative horizontal motion */
331: /* fscanf(fp, "%d", &n); */
332: while ((c = getc(fp)) == ' ')
333: ;
334: k = 0;
335: sign = 1;
336: if (c == '-') {
337: sign = -1;
338: c = getc(fp);
339: }
340: do {
341: k = 10 * k + c - '0';
342: } while (isdigit(c = getc(fp)));
343: ungetc(c, fp);
344: hmot(sign * k);
345: break;
346: case 'w': /* word space */
347: break;
348: case 'V':
349: fscanf(fp, "%d", &n);
350: vgoto(n);
351: break;
352: case 'v':
353: fscanf(fp, "%d", &n);
354: vmot(n);
355: break;
356: case 'p': /* new page */
357: fscanf(fp, "%d", &n);
358: t_page(n);
359: break;
360: case 'n': /* end of line */
361: while (getc(fp) != '\n')
362: ;
363: t_newline();
364: break;
365: case '#': /* comment */
366: while (getc(fp) != '\n')
367: ;
368: break;
369: case 'x': /* device control */
370: devcntrl(fp);
371: break;
372: default:
373: error(!FATAL, "unknown input character %o %c\n", c, c);
374: fprintf(stderr, "input context is:\n%c", c);
375: for (i = 0; i < 10; i++) {
376: if (fgets(buf, sizeof(buf), fp) == NULL)
377: break;
378: fprintf(stderr, "%s", buf);
379: }
380: done();
381: }
382: }
383: }
384:
385: devcntrl(fp) /* interpret device control functions */
386: FILE *fp;
387: {
388: char str[20], str1[50], buf[50];
389: int c, n;
390:
391: fscanf(fp, "%s", str);
392: switch (str[0]) { /* crude for now */
393: case 'i': /* initialize */
394: fileinit();
395: t_init(0);
396: break;
397: case 'T': /* device name */
398: fscanf(fp, "%s", devname);
399: if (strcmp(devname, "202") != 0) {
400: error(FATAL, "input file for %s, not 202", devname);
401: exit(1);
402: }
403: break;
404: case 't': /* trailer */
405: t_trailer();
406: break;
407: case 'p': /* pause -- can restart */
408: t_reset('p');
409: break;
410: case 's': /* stop */
411: t_reset('s');
412: break;
413: case 'r': /* resolution assumed when prepared */
414: fscanf(fp, "%d", &res);
415: break;
416: case 'f': /* font used */
417: fscanf(fp, "%d %s", &n, str);
418: fgets(buf, sizeof buf, fp); /* in case there's a filename */
419: ungetc('\n', fp); /* fgets goes too far */
420: str1[0] = 0; /* in case there's nothing to come in */
421: sscanf(buf, "%s", str1);
422: loadfont(n, str, str1);
423: break;
424: /* these don't belong here... */
425: case 'H': /* char height */
426: fscanf(fp, "%d", &n);
427: t_charht(n);
428: break;
429: case 'S': /* slant */
430: fscanf(fp, "%d", &n);
431: t_slant(n);
432: break;
433: }
434: while ((c = getc(fp)) != '\n') /* skip rest of input line */
435: if (c == EOF)
436: break;
437: }
438:
439: fileinit() /* read in font and code files, etc. */
440: {
441: int i, fin, nw;
442: char *malloc(), *filebase, *p;
443: char temp[60];
444:
445: /* open table for device,
446: /* read in resolution, size info, font info, etc.
447: /* and set params
448: */
449: sprintf(temp, "%s/dev%s/DESC.out", fontdir, devname);
450: if ((fin = open(temp, 0)) < 0)
451: error(FATAL, "can't open tables for %s\n", temp);
452: read(fin, &dev, sizeof(struct dev));
453: nfonts = dev.nfonts;
454: nsizes = dev.nsizes;
455: nchtab = dev.nchtab;
456: filebase = malloc(dev.filesize); /* enough room for whole file */
457: read(fin, filebase, dev.filesize); /* all at once */
458: pstab = (short *) filebase;
459: chtab = pstab + nsizes + 1;
460: chname = (char *) (chtab + dev.nchtab);
461: p = chname + dev.lchname;
462: for (i = 1; i <= nfonts; i++) {
463: fontbase[i] = (struct Font *) p;
464: nw = *p & BYTEMASK; /* 1st thing is width count */
465: if (smnt == 0 && fontbase[i]->specfont == 1)
466: smnt = i; /* first special font */
467: p += sizeof(struct Font); /* that's what's on the beginning */
468: widthtab[i] = p;
469: codetab[i] = p + 2 * nw;
470: fitab[i] = p + 3 * nw;
471: p += 3 * nw + dev.nchtab + 128 - 32;
472: t_fp(i, fontbase[i]->namefont, fontbase[i]->intname);
473: if(dbg > 1) fontprint(i);
474: }
475: fontbase[0] = (struct Font *) malloc(3*255 + dev.nchtab + (128-32) + sizeof (struct Font));
476: widthtab[0] = (char *) fontbase[0] + sizeof (struct Font);
477: fontbase[0]->nwfont = 255;
478: close(fin);
479: }
480:
481: fontprint(i) /* debugging print of font i (0,...) */
482: {
483: int j, k, n;
484: char *p;
485:
486: printf("font %d:\n", i);
487: p = (char *) fontbase[i];
488: n = fontbase[i]->nwfont & BYTEMASK;
489: printf("base=0%o, nchars=%d, spec=%d, name=%s, widtab=0%o, fitab=0%o\n",
490: p, n, fontbase[i]->specfont, fontbase[i]->namefont, widthtab[i], fitab[i]);
491: printf("widths:\n");
492: for (j=0; j <= n; j++) {
493: printf(" %2d", widthtab[i][j] & BYTEMASK);
494: if (j % 20 == 19) printf("\n");
495: }
496: printf("\ncodetab:\n");
497: for (j=0; j <= n; j++) {
498: printf(" %2d", codetab[i][j] & BYTEMASK);
499: if (j % 20 == 19) printf("\n");
500: }
501: printf("\nfitab:\n");
502: for (j=0; j <= dev.nchtab + 128-32; j++) {
503: printf(" %2d", fitab[i][j] & BYTEMASK);
504: if (j % 20 == 19) printf("\n");
505: }
506: printf("\n");
507: }
508:
509: loadfont(n, s, s1) /* load font info for font s on position n (0...) */
510: int n;
511: char *s, *s1;
512: {
513: char temp[60];
514: int fin, nw, norig;
515:
516: if (n < 0 || n > NFONT)
517: error(FATAL, "illegal fp command %d %s", n, s);
518: if (strcmp(s, fontbase[n]->namefont) == 0)
519: return;
520: if (s1 && s1[0])
521: s = s1;
522: sprintf(temp, "%s/dev%s/%s.out", fontdir, devname, s);
523: if ((fin = open(temp, 0)) < 0)
524: error(FATAL, "can't open font table %s", temp);
525: norig = fontbase[n]->nwfont & BYTEMASK;
526: read(fin, fontbase[n], 3*norig + nchtab+128-32 + sizeof(struct Font));
527: if ((fontbase[n]->nwfont & BYTEMASK) > norig)
528: error(FATAL, "Font %s too big for position %d\n", s, n);
529: close(fin);
530: nw = fontbase[n]->nwfont & BYTEMASK;
531: widthtab[n] = (char *) fontbase[n] + sizeof(struct Font);
532: codetab[n] = (char *) widthtab[n] + 2 * nw;
533: fitab[n] = (char *) widthtab[n] + 3 * nw;
534: t_fp(n, fontbase[n]->namefont, fontbase[n]->intname);
535: fontbase[n]->nwfont = norig; /* so can later use full original size */
536: if (dbg > 1) fontprint(n);
537: }
538:
539: done()
540: {
541: if (tf == NULL)
542: exit(1);
543: putint(0); /* some no-ops */
544: putint(0);
545: t_reset('s');
546: exit(0);
547: }
548:
549: error(f, s, a1, a2, a3, a4, a5, a6, a7) {
550: fprintf(stderr, "d202: ");
551: fprintf(stderr, s, a1, a2, a3, a4, a5, a6, a7);
552: fprintf(stderr, "\n");
553: if (f)
554: done();
555: }
556:
557:
558: /*
559: Here beginneth all the stuff that really depends
560: on the 202 (we hope).
561: */
562:
563:
564: char devname[20] = "202";
565:
566: #define RES 972 /* 202 is 288 goobies per inch vertically */
567: /* but 972 horizontally! */
568: /* can get 486 vertically by using electronic baseline jump */
569: #define TRAILER (14 * res)
570: #define LMARGIN 0 /* left margin offset */
571: #define HMAX (48 * (res/6)) /* maximum horizontal size = 48 picas */
572: #define VMAX (15 * res) /* 15 inch page */
573:
574: #define HOR 254 /* next int is horizontal motion */
575: #define ESCAPE 255 /* general-purpose escape for all others */
576: #define BASEINIT -162 /* initial baseline for 202 */
577:
578:
579:
580: int lastc, lastw; /* last character and width (not used) */
581: int lastfont = -2; /* last real font sent to 202 */
582:
583: long paper; /* paper used */
584:
585: int refscr = 0;
586:
587: t_init(reinit) /* initialize device */
588: int reinit;
589: {
590: int i;
591:
592: hpos = vpos = oldv = oldh = 0;
593: refscr = 0;
594: /* the above are not true until the code below happens*/
595: setsize(t_size(10)); /* start somewhere */
596: setfont(font = 1);
597: sendfont();
598: putesc("v");
599: putint(72); /* 1/4 inch initial lead */
600: putesc("j");
601: putint(BASEINIT);
602: putesc("H");
603: putint(0); /* make sure at left */
604:
605: if (drawdot) { /* -. flag was given */
606: drawsize = 2;
607: } else {
608: for (i = 0; i < nchtab; i++)
609: if (strcmp(&chname[chtab[i]], "l.") == 0)
610: break;
611: if (i < nchtab) {
612: drawdot = i + 128;
613: drawsize = 1;
614: } else {
615: drawdot = '.';
616: drawsize = 2; /* half size */
617: }
618: }
619: }
620:
621: #define MAXSTATE 5
622:
623: struct state {
624: int ssize;
625: int sfont;
626: int shpos;
627: int svpos;
628: int shorig;
629: int svorig;
630: };
631: struct state state[MAXSTATE];
632: struct state *statep = state;
633:
634: t_push() /* begin a new block */
635: {
636: hflush();
637: statep->ssize = size;
638: statep->sfont = font;
639: statep->shorig = horig;
640: statep->svorig = vorig;
641: statep->shpos = hpos;
642: statep->svpos = vpos;
643: horig = hpos;
644: vorig = vpos;
645: hpos = vpos = 0;
646: if (statep++ >= state+MAXSTATE)
647: error(FATAL, "{ nested too deep");
648: hpos = vpos = 0;
649: }
650:
651: t_pop() /* pop to previous state */
652: {
653: if (--statep < state)
654: error(FATAL, "extra }");
655: size = statep->ssize;
656: font = statep->sfont;
657: hpos = statep->shpos;
658: vpos = statep->svpos;
659: horig = statep->shorig;
660: vorig = statep->svorig;
661: }
662:
663: t_page(n) /* do whatever new page functions */
664: {
665: int i;
666:
667: if (output) {
668: if (tf != stdout)
669: paper += vpos;
670: if (++scount >= spage) {
671: t_reset('p');
672: scount = 0;
673: }
674: }
675: refscr -= vpos;
676: vpos = 0;
677: oldv = 0;
678: output = 1;
679: putesc("p");
680: putint(n);
681: putesc("H");
682: putint(0);
683: putflush();
684: if (nolist == 0)
685: return; /* no -o specified */
686: if (n > maxolist) /* we've gone past the end */
687: done();
688: output = 0;
689: for (i = 0; i < nolist; i += 2)
690: if (n >= olist[i] && n <= olist[i+1]) {
691: output = 1;
692: break;
693: }
694: }
695:
696: t_newline() /* do whatever for the end of a line */
697: {
698: hpos = 0; /* because we're now back at the left margin */
699: if (output)
700: putesc("n");
701: }
702:
703: t_size(n) /* convert integer to internal size number*/
704: int n;
705: {
706: int i;
707:
708: if (n <= pstab[0])
709: return(1);
710: else if (n >= pstab[nsizes-1])
711: return(nsizes);
712: for (i = 0; n > pstab[i]; i++)
713: ;
714: return(i+1);
715: }
716:
717: t_charht(n) /* set character height to n */
718: int n;
719: {
720: putesc("xH");
721: putint(n);
722: putc('\n', tf);
723: }
724:
725: t_slant(n) /* set slant to n */
726: int n;
727: {
728: putesc("xS");
729: putint(n);
730: putc('\n', tf);
731: }
732:
733: t_font(s) /* convert string to internal font number */
734: char *s;
735: {
736: int n;
737:
738: n = atoi(s);
739: if (n < 0 || n > nfonts)
740: n = 1;
741: return(n);
742: }
743:
744: t_text(s) /* print string s as text. not used */
745: char *s;
746: {
747: int c, w;
748: char str[100];
749:
750: if (!output)
751: return;
752: while (c = *s++) {
753: if (c == '\\') {
754: switch (c = *s++) {
755: case '\\':
756: case 'e':
757: put1('\\');
758: break;
759: case '(':
760: str[0] = *s++;
761: str[1] = *s++;
762: str[2] = '\0';
763: put1s(str);
764: break;
765: }
766: } else {
767: put1(c);
768: }
769: hmot(lastw);
770: if (dbg) printf("width = %d\n", lastw);
771: }
772: }
773:
774: t_reset(c)
775: {
776: int n;
777:
778: if (output)
779: paper += vpos;
780: output = 1; /* by God */
781: if (c == 'p')
782: putesc("xp\n");
783: else
784: putesc("xs\n");
785: fflush(tf);
786: }
787:
788: char *tracct = "/usr/adm/tracct";
789:
790: account() /* record paper use */
791: {
792: FILE *f = NULL;
793: char *name, *getlogin();
794:
795: if (tf == stdout)
796: return;
797: f = fopen(tracct, "a");
798: if(f != NULL) {
799: name = getlogin();
800: if (name == NULL)
801: name = "???";
802: fprintf(f, "%4d %s\n", (int)(paper/res + 20+6)/12, name);
803: }
804: }
805:
806: t_trailer()
807: {
808: /* vpos = oldv = 0;
809: /* vgoto(TRAILER);
810: /* vpos = oldv = 0;
811: */
812: }
813:
814: hflush() /* actual horizontal output occurs here */
815: {
816: register int dh;
817: int htrue;
818:
819: if (!output)
820: return;
821: htrue = hpos + horig;
822: dh = htrue - oldh;
823: if (dh > 0 && dh < 256) {
824: if (dbg)
825: printf(" h%d\n", dh & BYTEMASK);
826: else {
827: putc(HOR, tf);
828: putc(dh, tf);
829: }
830: } else if (dh != 0) {
831: if (dbg)
832: printf(" esc H %d\n", htrue+xoffset);
833: else {
834: putesc("H");
835: putint(htrue+xoffset);
836: }
837: }
838: oldh = htrue + horig;
839: }
840:
841: vgoto(n)
842: {
843: int deltav, nelec, ps, vtrue, ntrue;
844:
845: /* To understand this function, you need to know the
846: /* following characteristics of the 202:
847: /* one unit of electronic baseline jump = 1/486 inch;
848: /* one unit of mechanical motion = 1/288 inch;
849: /* further, mechanical motion accumulates and persists,
850: /* while electronic baseline jump persists but doesn't accumulate.
851: /* The window is 1296 units high, and we leave a margin on top of
852: /* 14*(current point size) and on the bottom of 4*(curr pt sz).
853: /* Our inductive assertion on entering this function
854: /* is that the current vertical position is within the margins.
855: /* If we want to move to a point between the margins, we
856: /* perform this motion with a pure electronic baseline jump.
857: /* Otherwise, we move the paper mechanically so that the desired
858: /* point is close to the top of the screen, subject to the margin
859: /* constraints.
860: */
861:
862: if (!output)
863: return;
864: if (dbg) printf(" vgoto %d to %d\n", vpos, n);
865: ps = (pstab[size]-1)>72?72:pstab[size-1];
866: vtrue = vpos + vorig;
867: ntrue = n + vorig;
868: if (refscr < ntrue || refscr - windowht - 14*ps > ntrue) {
869: /* mechanical motion */
870: deltav = ntrue - refscr;
871: if (deltav < 0 && deltav > -54)
872: deltav -= 54;
873: if (deltav > 0 && deltav < 54)
874: deltav += 54;
875: deltav = (deltav > 0) ? ((deltav/54)*54) : -((-(deltav-53)/54)*54);
876: if (deltav) {
877: putesc ("v");
878: if (deltav > 0)
879: putint(deltav/54*16);
880: else
881: putint(-(-deltav/54)*16);
882: refscr += deltav;
883: vtrue += deltav;
884: }
885: }
886: if (ntrue - vtrue) {
887: nelec = -(324 - (refscr - ntrue));
888: if (nelec > 0)
889: nelec /= 2;
890: else
891: nelec = -((-nelec) / 2);
892: putesc("j");
893: putint(nelec);
894: }
895: vpos = n;
896: }
897:
898:
899: put1s(s) /* s is a funny char name */
900: char *s;
901: {
902: int i;
903: static char lasti = 0; /* cache last hit */
904:
905: if (!output)
906: return;
907: if (dbg) printf("%s ", s);
908: if (strcmp(&chname[chtab[lasti]], s) != 0)
909: for (i = 0; i < nchtab; i++)
910: if (strcmp(&chname[chtab[i]], s) == 0)
911: break;
912: if (i < nchtab)
913: put1(i + 128);
914: }
915:
916: put1(c) /* output char c */
917: int c;
918: {
919: char *pw;
920: register char *p;
921: register int i, k;
922: int j, ofont, code, w;
923:
924: if (!output)
925: return;
926: c -= 32;
927: if (c <= 0) {
928: if (dbg) printf("non-exist 0%o\n", c+32);
929: return;
930: }
931: k = ofont = font;
932: i = fitab[font][c] & BYTEMASK;
933: if (i != 0) { /* it's on this font */
934: p = codetab[font];
935: pw = widthtab[font];
936: } else if (smnt > 0) { /* on special (we hope) */
937: for (k=smnt, j=0; j <= nfonts; j++, k = (k+1) % (nfonts+1))
938: if ((i = fitab[k][c] & BYTEMASK) != 0) {
939: p = codetab[k];
940: pw = widthtab[k];
941: setfont(k);
942: break;
943: }
944: }
945: if (i == 0 || (code = p[i] & BYTEMASK) == 0 || k > nfonts) {
946: if (dbg) printf("not found 0%o\n", c+32);
947: return;
948: }
949: hflush();
950: sendfont();
951: if (dbg) {
952: if (isprint(c+32))
953: printf("%c %d\n", c+32, code);
954: else
955: printf(" C%d\n", code);
956: } else
957: putc(code, tf); /* character is < 254 */
958: font = ofont;
959: }
960:
961: put1a(n) /* put single char by absolute number */
962: int n;
963: {
964: hflush();
965: sendfont();
966: if (dbg) {
967: if (isprint(n))
968: printf("%c %d\n", n, n);
969: else
970: printf(" N%d\n", n);
971: } else
972: putc(n, tf); /* character is < 254 */
973: }
974:
975: setsize(n) /* set point size to n (internal) */
976: int n;
977: {
978:
979: if (!output)
980: return;
981: if (n == size)
982: return; /* already there */
983: /* for now, only cope with integer sizes */
984: putesc("s");
985: putint(pstab[n-1]);
986: size = n;
987: }
988:
989: /* font position info: */
990:
991: struct {
992: char *name;
993: int number;
994: } fontname[NFONT+1];
995:
996: t_fp(n, s, si) /* font position n now contains font s, intname si */
997: int n;
998: char *s, *si;
999: {
1000: fontname[n].name = s;
1001: fontname[n].number = atoi(si);
1002: }
1003:
1004: setfont(n) /* set font to n */
1005: int n;
1006: {
1007: if (!output)
1008: return;
1009: if (n < 0 || n > NFONT)
1010: error(FATAL, "illegal font %d\n", n);
1011: font = n;
1012: }
1013:
1014: sendfont() /* actually send a font command if needed */
1015: {
1016: if (font != lastfont) {
1017: putesc("f");
1018: putint(fontname[font].number);
1019: lastfont = font;
1020: }
1021: }
1022:
1023: putint(n)
1024: {
1025: if (dbg) {
1026: printf("%02d\n", n);
1027: return;
1028: }
1029: putc(n>>8, tf);
1030: putc(n, tf);
1031: }
1032:
1033: putesc(s)
1034: register char *s;
1035: {
1036: if (dbg) {
1037: printf(" esc %s ", s);
1038: return;
1039: }
1040: putc(ESCAPE, tf);
1041: while (*s)
1042: putc(*s++, tf);
1043: }
1044:
1045: putflush() /* flush it out */
1046: {
1047: fflush(tf);
1048: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.