|
|
1.1 root 1: /*
2: * hp [-e] [-m]
3: * convert nroff TTY37 output to right form for HP2640x terminals.
4: * -e indicates enhanced terminal with underline, etc.
5: * -m requests minimization of output by removing multiple newlines
6: */
7:
8: char hpvers[] = "@(#)hp.c 1.6";
9:
10: #include <stdio.h>
11: #include <signal.h>
12: #include <sys/types.h>
13: #include <sys/stat.h>
14: #include <sgtty.h>
15: #define ESC 033 /* escape */
16: #define HFWD '9'
17: #define HREV '8'
18: #define FREV '7'
19: #define SO 016 /* shift out - enter greek */
20: #define SI 017 /* shift in */
21: #define LF '\n'
22: #define CR 015
23: #define NFLAG 0200 /* hi-bit flag for non-showing chars */
24: #define NMASK 0177
25: #define AMP 046 /* & */
26: #define DEE 0144 /* d */
27: #define BFSIZ 4096 /* size of output buffer */
28: /* (bigger because of tbl weirds */
29: /* and nroff idiosyncracies */
30:
31: /* puty adds control char to output, marked by hi-bit */
32: #define puty(c) putx(c|NFLAG)
33: #define flg(x) ((char)(x|NFLAG)) /* set hi-bit of x */
34: int nlcnt, /* accumulated newline count */
35: frevcnt, /* accumulated reverse line-feeds */
36: halfpos, /* half-line position: -1 = above, +1 = below */
37: restrict = 1, /* 0==> full terminal, 1==> no display enhancements */
38: minimiz; /* 0==> normal, 1==> remove extra newlines */
39: char *ttydev;
40: int svstmode; /* for mesg restore */
41: int restore();
42: char *ttyname();
43: int svsgflgs;
44: struct sgttyb sgb;
45: int retcode = 2; /* return code */
46: char peekbuf[2];
47: char *peekstr = peekbuf; /* lookahead ptr */
48:
49: char outbf[BFSIZ]; /* output assembly buffer */
50: char *bfnext = outbf, /* addr of next empty byte */
51: *bflast = &outbf[BFSIZ-1]; /* addr of last usable byte */
52:
53: /* normal display enhancement strings */
54: char *enunder = "\033&dD", /* underline */
55: *ennorml = "\033&d@", /* normal output */
56: *ensuper = "\033&dH", /* superscript (half) */
57: *ensubsc = "\033&dL", /* subscript (half, underlined */
58: *enrestr = "\033&dB"; /* restricted (inverse only) */
59:
60: int restore();
61: main(argc, argv)
62: char **argv;
63: {
64: register c;
65: scanarg(argc,argv);
66: if (((int)signal(SIGINT, SIG_IGN) & 01) == 0)
67: signal(SIGINT, restore);
68: if (gtty(1, &sgb) == 0)
69: fixtty();
70: setbuf(stdin, calloc(BUFSIZ,1));
71: while((c = getchal()) != EOF) {
72: if (nlcnt && c != LF) flushnl();
73: if (frevcnt && c != ESC) flushrv();
74: if (c == LF) {
75: if (++nlcnt == 1) flushln();
76: continue;
77: }
78: if (c == ESC)
79: escape();
80: else if (c == SO)
81: special();
82: else if (c == '\b')
83: backsp();
84: else if (c == '_') { /* C nroff */
85: if ((c = getchal()) == '\b') {
86: undersc();
87: } else {
88: putx('_');
89: peekbuf[0] = c;
90: peekstr = peekbuf;
91: }
92: }
93: else
94: putx(c);
95: }
96: flusher();
97: retcode = 0;
98: restore();
99: }
100:
101: getchal()
102: {
103: if (*peekstr)
104: return(*peekstr++);
105: return(getchar());
106: }
107:
108: /* scanarg: scan arguments and set flags; ignore unknown args */
109: scanarg(argc,argv)
110: int argc; char **argv;
111: {
112: register char *p;
113: while ( --argc > 0) {
114: p = *++argv;
115: if (*p == '-') {
116: ++p;
117: if (*p == 'e') restrict = 0;
118: else if (*p == 'm') minimiz = 1;
119: }
120: }
121: if (restrict)
122: enunder = ensuper = ensubsc = enrestr;
123: }
124:
125: /* fixtty: get tty status and save; remove delay and CR-LF mapping */
126: fixtty()
127: {
128: struct stat sb;
129:
130: svsgflgs = sgb.sg_flags;
131: sgb.sg_flags &= ~(ALLDELAY|CRMOD);
132: stty(1, &sgb); /* stty nl nl0 cr0 tab0 ff0 */
133: fstat(1, &sb);
134: svstmode = sb.st_mode;
135: ttydev = ttyname(1);
136: if (ttydev && *ttydev)
137: chmod(ttydev, 0600); /* mesg n */
138: }
139:
140: /* flusher: flush accumulated newlines, reverse line feeds, buffer */
141: flusher()
142: {
143: flushln();
144: if (nlcnt) flushnl();
145: if (frevcnt) flushrv();
146: fflush(stdout);
147: }
148:
149: /* flushrv: flush accumulated reverse line feeds */
150: flushrv()
151: {
152: while (frevcnt--)
153: putstr("\033T");
154: putstr(ennorml);
155: frevcnt = 0;
156: }
157:
158: /* flushnl: flush accumulated newlines (count in nlcnt) */
159: flushnl()
160: {
161: if (minimiz != 0 && nlcnt > 2) nlcnt = 2;
162: putchar(CR);
163: while (nlcnt--)
164: putchar(LF);
165: nlcnt = 0;
166: }
167:
168: putstr(p)
169: char *p;
170: {
171: register char *pp;
172: pp = p;
173: while (*pp) puty(*pp++);
174: }
175:
176: restore(){
177: if (isatty(1)) {
178: sgb.sg_flags = svsgflgs;
179: stty(1, &sgb);
180: if (ttydev && *ttydev)
181: chmod(ttydev, svstmode);
182: }
183: exit(retcode);
184: }
185:
186: char tab[] = {
187: 'A','A', /* alpha */
188: 'B','B', /* beta */
189: 'D','W', /* delta */
190: 'W','V', /* DELTA */
191: 'S','E', /* epsilon */
192: 'N','H', /* eta */
193: '\\','Q', /* gamma */
194: 'G','+', /* GAMMA */
195: 'o','<', /* infinity - not in M37 */
196: '^','\'', /* integral */
197: 'L','G', /* lambda */
198: 'E',';', /* LAMBDA */
199: 'M','M', /* mu */
200: '[','$', /* nabla (del) */
201: '_','\\', /* not */
202: '@','N', /* nu */
203: 'C','L', /* omega */
204: 'Z',':', /* OMEGA */
205: ']','F', /* partial */
206: 'U','D', /* phi */
207: 'F','.', /* PHI */
208: 'V','C', /* psi */
209: 'H',',', /* PSI */
210: 'J','P', /* pi */
211: 'P','*', /* PI */
212: 'K','O', /* rho */
213: 'Y','S', /* sigma */
214: 'R','?', /* SIGMA */
215: 'I','T', /* tau */
216: 'T','R', /* theta */
217: 'O','J', /* THETA */
218: 'X','U', /* xi */
219: 'Q','Z', /* zeta */
220: 'v','Y',
221: 0
222: };
223:
224: char spec1[] = {LF,SO,0};
225: special(){
226: register int c;
227: register char *p;
228: puty(SO);
229: while ((c = getchal()) != EOF) {
230: if (c == SI) {
231: puty(c);
232: return;
233: }
234: if (c == LF) {
235: peekstr = spec1;
236: return;
237: }
238: for (p = tab; *p != 0; p += 2)
239: if (c == *p) {
240: c = *++p;
241: break;
242: }
243: putx(c);
244: }
245: }
246:
247: /* escape: handle escape sequences */
248: escape()
249: {
250: register int c;
251: c = getchal();
252: if (frevcnt && c != FREV) flushrv();
253: switch (c) {
254: case FREV:
255: frevcnt++;
256: break;
257: case HREV:
258: if (halfpos == 0) {
259: putstr(ensuper);
260: halfpos--;
261: }
262: else if (halfpos > 0) {
263: putstr(ennorml);
264: halfpos--;
265: }
266: else {
267: putstr("\033T"); /* roll back 1 */
268: putstr(ennorml);
269: halfpos = 0;
270: }
271: break;
272: case HFWD:
273: if (halfpos == 0) {
274: putstr(ensubsc);
275: halfpos++;
276: }
277: else if (halfpos < 0) {
278: putstr(ennorml);
279: halfpos++;
280: }
281: else {
282: putstr("\033S"); /* roll up 1, i.e., LF w/o CR */
283: putstr(ennorml);
284: halfpos = 0;
285: }
286: break;
287: case '&':
288: putstr("\033&");
289: puty(c = getchal());
290: if (c == 'd') puty(getchal());
291: break;
292: case ')':
293: putstr("\033)");
294: puty(getchal());
295: break;
296: default:
297: puty(ESC);
298: puty(getchal());
299: break;
300: }
301: }
302:
303: char peeku[3];
304: /* backsp: handle backspacing */
305: /* sequences are handled such that : ( \b is backspace ) */
306: /* a\b_ -> a in inverse video */
307: /* _\ba -> a in inverse video */
308: /* c\bd -> c in inverse video */
309: /* if a control char (ESC) precedes or follows '\b' */
310: /* then an actual backspace movement is performed */
311: backsp()
312: {
313: register char *bftmp;
314: register int c;
315: char *bfhi;
316: int i, j, ncnt, bscnt;
317: char *p, *p1;
318: p = bfnext-2;
319: p1 = bfnext-4;
320: /* check if last char put in buffer was escape sequence */
321: /* if so, put backspace control sequence in buffer */
322: /* check against "\033&d" */
323: if ((*p == flg(ESC)) ||
324: (*p1++ == flg(ESC) && *p1++==flg(AMP) && *p1==flg(DEE))) {
325: putstr("\033D");
326: while((c=getchal())=='\b') putstr("\033D");
327: /* put last char back */
328: peeku[0] = c;
329: peeku[1] = '\0';
330: peekstr = peeku;
331: return;
332: }
333: bscnt = 1;
334: c = getchal();
335: /* count backspaces */
336: while (c == '\b') {
337: bscnt++;
338: c = getchal();
339: }
340: /* read in chars until bscnt have been read */
341: /* or until an ESC is read */
342: ncnt = 0;
343: if (c!=ESC) {
344: for (ncnt=0; (ncnt<bscnt && c!=ESC); ncnt++)
345: c = getchal();
346: /* since there were normal chars with backsp */
347: /* insert inverse video chars in buffer */
348: bftmp = bfhi = bfnext + 4;
349: for (i=0; i<bscnt;)
350: if (((*--bftmp = *--bfnext) & NFLAG) == 0) i++;
351: putstr(enunder);
352: bfnext = bfhi;
353: }
354: /* if number of bcksp is not = to number normal chars */
355: /* then some bcksp chars will be inserted as actual */
356: /* bcksp movement and not inverse video for another char */
357: j = bscnt - ncnt;
358: if (j == 0) putstr(ennorml);
359: else {
360: /* move chars over and insert normal char seq */
361: if (ncnt > 0) {
362: bftmp = bfhi = bfnext + 4;
363: for (i=0; i<j;)
364: if (((*--bftmp = *--bfnext) & NFLAG) == 0) i++;
365: putstr(ennorml);
366: bfnext = bfhi;
367: }
368: /* insert backspace movement chars */
369: while (j--) putstr("\033D");
370: }
371: /* put last char read back */
372: peeku[0] = c;
373: peeku[1] = '\0';
374: peekstr = peeku;
375: }
376: /* undersc: handle C nroff's (_ BS char)+ sequences
377: * assumes _ BS already found
378: * if char is a control char, put char back and break.
379: */
380: undersc()
381: {
382: register char c;
383:
384: putstr(enunder);
385: while (1) {
386: if ((c=getchal())==ESC) {
387: peeku[0] = c; peeku[1] = '\0';
388: peekstr = peeku;
389: break;
390: }
391: else
392: putx(c);
393: if ((c = getchal()) != '_') {
394: peeku[0] = c; peeku[1] = '\0';
395: peekstr = peeku;
396: break;
397: }
398: if ((c = getchal()) != '\b') {
399: peeku[0] = '_'; peeku[1] = c;
400: peekstr = peeku;
401: break;
402: }
403: }
404: putstr(ennorml);
405: }
406:
407: /* flushln: flush out accumulated line */
408: flushln()
409: {
410: register char c, *p;
411: putx('\0');
412: p = outbf;
413: while (c = (*p++ & NMASK)) putchar(c);
414: bfnext = outbf;
415: }
416:
417: /* putx: add normal (printing) char to output */
418: putx(c)
419: char c;
420: {
421: if (bfnext <= bflast)
422: *bfnext++ = c;
423: else die("line too long\n");
424: }
425:
426: die(mesg)
427: char *mesg;
428: {
429: register char *p;
430: char *c = "hp: ";
431:
432: write(2, c, 4);
433: p = mesg;
434: while (*p)
435: write(2, p++, 1);
436: restore();
437: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.