|
|
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 50
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: invalidfont();
424: break;
425: /* these don't belong here... */
426: case 'H': /* char height */
427: fscanf(fp, "%d", &n);
428: t_charht(n);
429: break;
430: case 'S': /* slant */
431: fscanf(fp, "%d", &n);
432: t_slant(n);
433: break;
434: }
435: while ((c = getc(fp)) != '\n') /* skip rest of input line */
436: if (c == EOF)
437: break;
438: }
439:
440: fileinit() /* read in font and code files, etc. */
441: {
442: int i, fin, nw, s;
443: char *malloc(), *filebase, *p;
444: char temp[60];
445:
446: /* open table for device,
447: /* read in resolution, size info, font info, etc.
448: /* and set params
449: */
450: sprintf(temp, "%s/dev%s/DESC.out", fontdir, devname);
451: if ((fin = open(temp, 0)) < 0)
452: error(FATAL, "can't open tables for %s\n", temp);
453: read(fin, &dev, sizeof(struct dev));
454: nfonts = dev.nfonts;
455: nsizes = dev.nsizes;
456: nchtab = dev.nchtab;
457: filebase = malloc(dev.filesize); /* enough room for whole file */
458: read(fin, filebase, dev.filesize); /* all at once */
459: pstab = (short *) filebase;
460: chtab = pstab + nsizes + 1;
461: chname = (char *) (chtab + dev.nchtab);
462: p = chname + dev.lchname;
463: for (i = 1; i <= nfonts; i++) {
464: fontbase[i] = (struct Font *) p;
465: nw = *p & BYTEMASK; /* 1st thing is width count */
466: if (smnt == 0 && fontbase[i]->specfont == 1)
467: smnt = i; /* first special font */
468: p += sizeof(struct Font); /* that's what's on the beginning */
469: widthtab[i] = p;
470: codetab[i] = p + 2 * nw;
471: fitab[i] = p + 3 * nw;
472: p += 3 * nw + dev.nchtab + 128 - 32;
473: t_fp(i, fontbase[i]->namefont, fontbase[i]->intname);
474: if(dbg > 1) fontprint(i);
475: }
476: fontbase[0] = (struct Font *) malloc(3*255 + dev.nchtab + (128-32) + sizeof (struct Font));
477: widthtab[0] = (char *) fontbase[0] + sizeof (struct Font);
478: fontbase[0]->nwfont = 255;
479: close(fin);
480: for (i = nfonts+1; i <= NFONT; i++)
481: fontbase[i] = 0;
482: }
483:
484: fontprint(i) /* debugging print of font i (0,...) */
485: {
486: int j, k, n;
487: char *p;
488:
489: printf("font %d:\n", i);
490: p = (char *) fontbase[i];
491: n = fontbase[i]->nwfont & BYTEMASK;
492: printf("base=0%o, nchars=%d, spec=%d, name=%s, widtab=0%o, fitab=0%o\n",
493: p, n, fontbase[i]->specfont, fontbase[i]->namefont, widthtab[i], fitab[i]);
494: printf("widths:\n");
495: for (j=0; j <= n; j++) {
496: printf(" %2d", widthtab[i][j] & BYTEMASK);
497: if (j % 20 == 19) printf("\n");
498: }
499: printf("\ncodetab:\n");
500: for (j=0; j <= n; j++) {
501: printf(" %2d", codetab[i][j] & BYTEMASK);
502: if (j % 20 == 19) printf("\n");
503: }
504: printf("\nfitab:\n");
505: for (j=0; j <= dev.nchtab + 128-32; j++) {
506: printf(" %2d", fitab[i][j] & BYTEMASK);
507: if (j % 20 == 19) printf("\n");
508: }
509: printf("\n");
510: }
511:
512: loadfont(n, s, s1) /* load font info for font s on position n (0...) */
513: int n;
514: char *s, *s1;
515: {
516: char temp[60];
517: int fin, nw, norig, sz;
518:
519: if (n < 0 || n > NFONT)
520: error(FATAL, "illegal fp command %d %s", n, s);
521: if (strcmp(s, fontbase[n]->namefont) == 0)
522: return;
523: if (s1 && s1[0])
524: s = s1;
525: sprintf(temp, "%s/dev%s/%s.out", fontdir, devname, s);
526: if (fontbase[n] == 0) {
527: sz = sizeof(struct Font) + 3 * 255 + dev.nchtab
528: + 128 - 32;
529: fontbase[n] = (struct Font *) malloc(sz);
530: fontbase[n]->nwfont = 255;
531: if (n > nfonts)
532: nfonts = n;
533: }
534: if ((fin = open(temp, 0)) < 0)
535: error(FATAL, "can't open font table %s", temp);
536: norig = fontbase[n]->nwfont & BYTEMASK;
537: read(fin, fontbase[n], 3*norig + nchtab+128-32 + sizeof(struct Font));
538: if ((fontbase[n]->nwfont & BYTEMASK) > norig)
539: error(FATAL, "Font %s too big for position %d\n", s, n);
540: close(fin);
541: nw = fontbase[n]->nwfont & BYTEMASK;
542: widthtab[n] = (char *) fontbase[n] + sizeof(struct Font);
543: codetab[n] = (char *) widthtab[n] + 2 * nw;
544: fitab[n] = (char *) widthtab[n] + 3 * nw;
545: t_fp(n, fontbase[n]->namefont, fontbase[n]->intname);
546: fontbase[n]->nwfont = norig; /* so can later use full original size */
547: if (dbg > 1) fontprint(n);
548: }
549:
550: done()
551: {
552: if (tf == NULL)
553: exit(1);
554: putint(0); /* some no-ops */
555: putint(0);
556: t_reset('s');
557: exit(0);
558: }
559:
560: error(f, s, a1, a2, a3, a4, a5, a6, a7) {
561: fprintf(stderr, "d202: ");
562: fprintf(stderr, s, a1, a2, a3, a4, a5, a6, a7);
563: fprintf(stderr, "\n");
564: if (f)
565: done();
566: }
567:
568:
569: /*
570: Here beginneth all the stuff that really depends
571: on the 202 (we hope).
572: */
573:
574:
575: char devname[20] = "202";
576:
577: #define RES 972 /* 202 is 288 goobies per inch vertically */
578: /* but 972 horizontally! */
579: /* can get 486 vertically by using electronic baseline jump */
580: #define TRAILER (14 * res)
581: #define LMARGIN 0 /* left margin offset */
582: #define HMAX (48 * (res/6)) /* maximum horizontal size = 48 picas */
583: #define VMAX (15 * res) /* 15 inch page */
584:
585: #define HOR 254 /* next int is horizontal motion */
586: #define ESCAPE 255 /* general-purpose escape for all others */
587: #define BASEINIT -162 /* initial baseline for 202 */
588:
589:
590:
591: int lastc, lastw; /* last character and width (not used) */
592: int lastfont = -2; /* last real font sent to 202 */
593:
594: invalidfont() { lastfont = -2; }
595:
596: long paper; /* paper used */
597:
598: int refscr = 0;
599:
600: t_init(reinit) /* initialize device */
601: int reinit;
602: {
603: int i;
604:
605: hpos = vpos = oldv = oldh = 0;
606: refscr = 0;
607: /* the above are not true until the code below happens*/
608: setsize(t_size(10)); /* start somewhere */
609: setfont(font = 1);
610: sendfont();
611: putesc("v");
612: putint(72); /* 1/4 inch initial lead */
613: putesc("j");
614: putint(BASEINIT);
615: putesc("H");
616: putint(0); /* make sure at left */
617:
618: if (drawdot) { /* -. flag was given */
619: drawsize = 2;
620: } else {
621: for (i = 0; i < nchtab; i++)
622: if (strcmp(&chname[chtab[i]], "l.") == 0)
623: break;
624: if (i < nchtab) {
625: drawdot = i + 128;
626: drawsize = 1;
627: } else {
628: drawdot = '.';
629: drawsize = 2; /* half size */
630: }
631: }
632: }
633:
634: #define MAXSTATE 5
635:
636: struct state {
637: int ssize;
638: int sfont;
639: int shpos;
640: int svpos;
641: int shorig;
642: int svorig;
643: };
644: struct state state[MAXSTATE];
645: struct state *statep = state;
646:
647: t_push() /* begin a new block */
648: {
649: hflush();
650: statep->ssize = size;
651: statep->sfont = font;
652: statep->shorig = horig;
653: statep->svorig = vorig;
654: statep->shpos = hpos;
655: statep->svpos = vpos;
656: horig = hpos;
657: vorig = vpos;
658: hpos = vpos = 0;
659: if (statep++ >= state+MAXSTATE)
660: error(FATAL, "{ nested too deep");
661: hpos = vpos = 0;
662: }
663:
664: t_pop() /* pop to previous state */
665: {
666: if (--statep < state)
667: error(FATAL, "extra }");
668: size = statep->ssize;
669: font = statep->sfont;
670: hpos = statep->shpos;
671: vpos = statep->svpos;
672: horig = statep->shorig;
673: vorig = statep->svorig;
674: }
675:
676: t_page(n) /* do whatever new page functions */
677: {
678: int i;
679:
680: if (output) {
681: if (tf != stdout)
682: paper += vpos;
683: if (++scount >= spage) {
684: t_reset('p');
685: scount = 0;
686: }
687: }
688: refscr -= vpos;
689: vpos = 0;
690: oldv = 0;
691: output = 1;
692: putesc("p");
693: putint(n);
694: putesc("H");
695: putint(0);
696: putflush();
697: if (nolist == 0)
698: return; /* no -o specified */
699: if (n > maxolist) /* we've gone past the end */
700: done();
701: output = 0;
702: for (i = 0; i < nolist; i += 2)
703: if (n >= olist[i] && n <= olist[i+1]) {
704: output = 1;
705: break;
706: }
707: }
708:
709: t_newline() /* do whatever for the end of a line */
710: {
711: hpos = 0; /* because we're now back at the left margin */
712: if (output)
713: putesc("n");
714: }
715:
716: t_size(n) /* convert integer to internal size number*/
717: int n;
718: {
719: int i;
720:
721: if (n <= pstab[0])
722: return(1);
723: else if (n >= pstab[nsizes-1])
724: return(nsizes);
725: for (i = 0; n > pstab[i]; i++)
726: ;
727: return(i+1);
728: }
729:
730: t_charht(n) /* set character height to n */
731: int n;
732: {
733: putesc("xH");
734: putint(n);
735: putc('\n', tf);
736: }
737:
738: t_slant(n) /* set slant to n */
739: int n;
740: {
741: putesc("xS");
742: putint(n);
743: putc('\n', tf);
744: }
745:
746: t_font(s) /* convert string to internal font number */
747: char *s;
748: {
749: int n;
750:
751: n = atoi(s);
752: if (n < 0 || n > nfonts)
753: n = 1;
754: return(n);
755: }
756:
757: t_text(s) /* print string s as text. not used */
758: char *s;
759: {
760: int c, w;
761: char str[100];
762:
763: if (!output)
764: return;
765: while (c = *s++) {
766: if (c == '\\') {
767: switch (c = *s++) {
768: case '\\':
769: case 'e':
770: put1('\\');
771: break;
772: case '(':
773: str[0] = *s++;
774: str[1] = *s++;
775: str[2] = '\0';
776: put1s(str);
777: break;
778: }
779: } else {
780: put1(c);
781: }
782: hmot(lastw);
783: if (dbg) printf("width = %d\n", lastw);
784: }
785: }
786:
787: t_reset(c)
788: {
789: int n;
790:
791: if (output)
792: paper += vpos;
793: output = 1; /* by God */
794: if (c == 'p')
795: putesc("xp\n");
796: else
797: putesc("xs\n");
798: fflush(tf);
799: }
800:
801: char *tracct = "/usr/adm/tracct";
802:
803: account() /* record paper use */
804: {
805: FILE *f = NULL;
806: char *name, *getlogin();
807:
808: if (tf == stdout)
809: return;
810: f = fopen(tracct, "a");
811: if(f != NULL) {
812: name = getlogin();
813: if (name == NULL)
814: name = "???";
815: fprintf(f, "%4d %s\n", (int)(paper/res + 20+6)/12, name);
816: }
817: }
818:
819: t_trailer()
820: {
821: /* vpos = oldv = 0;
822: /* vgoto(TRAILER);
823: /* vpos = oldv = 0;
824: */
825: }
826:
827: hflush() /* actual horizontal output occurs here */
828: {
829: register int dh;
830: int htrue;
831:
832: if (!output)
833: return;
834: htrue = hpos + horig;
835: dh = htrue - oldh;
836: if (dh > 0 && dh < 256) {
837: if (dbg)
838: printf(" h%d\n", dh & BYTEMASK);
839: else {
840: putc(HOR, tf);
841: putc(dh, tf);
842: }
843: } else if (dh != 0) {
844: if (dbg)
845: printf(" esc H %d\n", htrue+xoffset);
846: else {
847: putesc("H");
848: putint(htrue+xoffset);
849: }
850: }
851: oldh = htrue + horig;
852: }
853:
854: vgoto(n)
855: {
856: int deltav, nelec, ps, vtrue, ntrue;
857:
858: /* To understand this function, you need to know the
859: /* following characteristics of the 202:
860: /* one unit of electronic baseline jump = 1/486 inch;
861: /* one unit of mechanical motion = 1/288 inch;
862: /* further, mechanical motion accumulates and persists,
863: /* while electronic baseline jump persists but doesn't accumulate.
864: /* The window is 1296 units high, and we leave a margin on top of
865: /* 14*(current point size) and on the bottom of 4*(curr pt sz).
866: /* Our inductive assertion on entering this function
867: /* is that the current vertical position is within the margins.
868: /* If we want to move to a point between the margins, we
869: /* perform this motion with a pure electronic baseline jump.
870: /* Otherwise, we move the paper mechanically so that the desired
871: /* point is close to the top of the screen, subject to the margin
872: /* constraints.
873: */
874:
875: if (!output)
876: return;
877: if (dbg) printf(" vgoto %d to %d\n", vpos, n);
878: ps = (pstab[size]-1)>72?72:pstab[size-1];
879: vtrue = vpos + vorig;
880: ntrue = n + vorig;
881: if (refscr < ntrue || refscr - windowht - 14*ps > ntrue) {
882: /* mechanical motion */
883: deltav = ntrue - refscr;
884: if (deltav < 0 && deltav > -54)
885: deltav -= 54;
886: if (deltav > 0 && deltav < 54)
887: deltav += 54;
888: deltav = (deltav > 0) ? ((deltav/54)*54) : -((-(deltav-53)/54)*54);
889: if (deltav) {
890: putesc ("v");
891: if (deltav > 0)
892: putint(deltav/54*16);
893: else
894: putint(-(-deltav/54)*16);
895: refscr += deltav;
896: vtrue += deltav;
897: }
898: }
899: if (ntrue - vtrue) {
900: nelec = -(324 - (refscr - ntrue));
901: if (nelec > 0)
902: nelec /= 2;
903: else
904: nelec = -((-nelec) / 2);
905: putesc("j");
906: putint(nelec);
907: }
908: vpos = n;
909: }
910:
911:
912: put1s(s) /* s is a funny char name */
913: char *s;
914: {
915: int i;
916: static char lasti = 0; /* cache last hit */
917:
918: if (!output)
919: return;
920: if (dbg) printf("%s ", s);
921: if (strcmp(&chname[chtab[lasti]], s) != 0)
922: for (i = 0; i < nchtab; i++)
923: if (strcmp(&chname[chtab[i]], s) == 0)
924: break;
925: if (i < nchtab)
926: put1(i + 128);
927: }
928:
929: put1(c) /* output char c */
930: int c;
931: {
932: char *pw;
933: register char *p;
934: register int i, k;
935: int j, ofont, code, w;
936:
937: if (!output)
938: return;
939: c -= 32;
940: if (c <= 0) {
941: if (dbg) printf("non-exist 0%o\n", c+32);
942: return;
943: }
944: k = ofont = font;
945: i = fitab[font][c] & BYTEMASK;
946: if (i != 0) { /* it's on this font */
947: p = codetab[font];
948: pw = widthtab[font];
949: } else if (smnt > 0) { /* on special (we hope) */
950: for (k=smnt, j=0; j <= nfonts; j++, k = (k+1) % (nfonts+1))
951: if ((i = fitab[k][c] & BYTEMASK) != 0) {
952: p = codetab[k];
953: pw = widthtab[k];
954: setfont(k);
955: break;
956: }
957: }
958: if (i == 0 || (code = p[i] & BYTEMASK) == 0 || k > nfonts) {
959: if (dbg) printf("not found 0%o\n", c+32);
960: return;
961: }
962: hflush();
963: sendfont();
964: if (dbg) {
965: if (isprint(c+32))
966: printf("%c %d\n", c+32, code);
967: else
968: printf(" C%d\n", code);
969: } else
970: putc(code, tf); /* character is < 254 */
971: font = ofont;
972: }
973:
974: put1a(n) /* put single char by absolute number */
975: int n;
976: {
977: hflush();
978: sendfont();
979: if (dbg) {
980: if (isprint(n))
981: printf("%c %d\n", n, n);
982: else
983: printf(" N%d\n", n);
984: } else
985: putc(n, tf); /* character is < 254 */
986: }
987:
988: setsize(n) /* set point size to n (internal) */
989: int n;
990: {
991:
992: if (!output)
993: return;
994: if (n == size)
995: return; /* already there */
996: /* for now, only cope with integer sizes */
997: putesc("s");
998: putint(pstab[n-1]);
999: size = n;
1000: }
1001:
1002: /* font position info: */
1003:
1004: struct {
1005: char *name;
1006: int number;
1007: } fontname[NFONT+1];
1008:
1009: t_fp(n, s, si) /* font position n now contains font s, intname si */
1010: int n;
1011: char *s, *si;
1012: {
1013: fontname[n].name = s;
1014: fontname[n].number = atoi(si);
1015: }
1016:
1017: setfont(n) /* set font to n */
1018: int n;
1019: {
1020: if (!output)
1021: return;
1022: if (n < 0 || n > NFONT)
1023: error(FATAL, "illegal font %d\n", n);
1024: font = n;
1025: }
1026:
1027: sendfont() /* actually send a font command if needed */
1028: {
1029: if (font != lastfont) {
1030: putesc("f");
1031: putint(fontname[font].number);
1032: lastfont = font;
1033: }
1034: }
1035:
1036: putint(n)
1037: {
1038: if (dbg) {
1039: printf("%02d\n", n);
1040: return;
1041: }
1042: putc(n>>8, tf);
1043: putc(n, tf);
1044: }
1045:
1046: putesc(s)
1047: register char *s;
1048: {
1049: if (dbg) {
1050: printf(" esc %s ", s);
1051: return;
1052: }
1053: putc(ESCAPE, tf);
1054: while (*s)
1055: putc(*s++, tf);
1056: }
1057:
1058: putflush() /* flush it out */
1059: {
1060: fflush(tf);
1061: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.