|
|
1.1 root 1: #ifndef lint
2: static char sccsid[] = "@(#)ul.c 4.5 (Berkeley) 8/11/83";
3: #endif
4:
5: #include <stdio.h>
6:
7: #define IESC '\033'
8: #define SO '\016'
9: #define SI '\017'
10: #define HFWD '9'
11: #define HREV '8'
12: #define FREV '7'
13: #define MAXBUF 512
14:
15: #define NORMAL 000
16: #define ALTSET 001 /* Reverse */
17: #define SUPERSC 002 /* Dim */
18: #define SUBSC 004 /* Dim | Ul */
19: #define UNDERL 010 /* Ul */
20: #define BOLD 020 /* Bold */
21:
22: int must_use_uc, must_overstrike;
23: char *CURS_UP, *CURS_RIGHT, *CURS_LEFT,
24: *ENTER_STANDOUT, *EXIT_STANDOUT, *ENTER_UNDERLINE, *EXIT_UNDERLINE,
25: *ENTER_DIM, *ENTER_BOLD, *ENTER_REVERSE, *UNDER_CHAR, *EXIT_ATTRIBUTES;
26:
27: struct CHAR {
28: char c_mode;
29: char c_char;
30: } ;
31:
32: char buf[BUFSIZ];
33:
34: struct CHAR obuf[MAXBUF];
35: int col, maxcol;
36: int mode;
37: int halfpos;
38: int upln;
39: int iflag;
40:
41: main(argc, argv)
42: int argc;
43: char **argv;
44: {
45: int c;
46: char *cp, *termtype;
47: FILE *f;
48: char termcap[1024];
49: char *getenv();
50: extern int optind;
51: extern char *optarg;
52:
53: termtype = getenv("TERM");
54: if (termtype == NULL || (argv[0][0] == 'c' && !isatty(1)))
55: termtype = "lpr";
56: while ((c=getopt(argc, argv, "it:T:")) != EOF)
57: switch(c) {
58:
59: case 't':
60: case 'T': /* for nroff compatibility */
61: termtype = optarg;
62: break;
63: case 'i':
64: iflag = 1;
65: break;
66:
67: default:
68: fprintf(stderr,
69: "Usage: %s [ -i ] [ -tTerm ] file...\n",
70: argv[0]);
71: exit(1);
72: }
73:
74: switch(tgetent(termcap, termtype)) {
75:
76: case 1:
77: break;
78:
79: default:
80: fprintf(stderr,"trouble reading termcap");
81: /* fall through to ... */
82:
83: case 0:
84: /* No such terminal type - assume dumb */
85: strcpy(termcap, "dumb:os:col#80:cr=^M:sf=^J:am:");
86: break;
87: }
88: initcap();
89: if ( (tgetflag("os") && ENTER_BOLD==NULL ) ||
90: (tgetflag("ul") && ENTER_UNDERLINE==NULL && UNDER_CHAR==NULL))
91: must_overstrike = 1;
92: setbuf(stdout, buf);
93: initbuf();
94: if (optind == argc)
95: filter(stdin);
96: else for (; optind<argc; optind++) {
97: f = fopen(argv[optind],"r");
98: if (f == NULL) {
99: perror(argv[optind]);
100: exit(1);
101: } else
102: filter(f);
103: }
104: exit(0);
105: }
106:
107: filter(f)
108: FILE *f;
109: {
110: register c;
111:
112: while((c = getc(f)) != EOF) switch(c) {
113:
114: case '\b':
115: if (col > 0)
116: col--;
117: continue;
118:
119: case '\t':
120: col = (col+8) & ~07;
121: if (col > maxcol)
122: maxcol = col;
123: continue;
124:
125: case '\r':
126: col = 0;
127: continue;
128:
129: case SO:
130: mode |= ALTSET;
131: continue;
132:
133: case SI:
134: mode &= ~ALTSET;
135: continue;
136:
137: case IESC:
138: switch (c = getc(f)) {
139:
140: case HREV:
141: if (halfpos == 0) {
142: mode |= SUPERSC;
143: halfpos--;
144: } else if (halfpos > 0) {
145: mode &= ~SUBSC;
146: halfpos--;
147: } else {
148: halfpos = 0;
149: reverse();
150: }
151: continue;
152:
153: case HFWD:
154: if (halfpos == 0) {
155: mode |= SUBSC;
156: halfpos++;
157: } else if (halfpos < 0) {
158: mode &= ~SUPERSC;
159: halfpos++;
160: } else {
161: halfpos = 0;
162: fwd();
163: }
164: continue;
165:
166: case FREV:
167: reverse();
168: continue;
169:
170: default:
171: fprintf(stderr,
172: "Unknown escape sequence in input: %o, %o\n",
173: IESC, c);
174: exit(1);
175: }
176: continue;
177:
178: case '_':
179: if (obuf[col].c_char)
180: obuf[col].c_mode |= UNDERL | mode;
181: else
182: obuf[col].c_char = '_';
183: case ' ':
184: col++;
185: if (col > maxcol)
186: maxcol = col;
187: continue;
188:
189: case '\n':
190: flushln();
191: continue;
192:
193: default:
194: if (c < ' ') /* non printing */
195: continue;
196: if (obuf[col].c_char == '\0') {
197: obuf[col].c_char = c;
198: obuf[col].c_mode = mode;
199: } else if (obuf[col].c_char == '_') {
200: obuf[col].c_char = c;
201: obuf[col].c_mode |= UNDERL|mode;
202: } else if (obuf[col].c_char == c)
203: obuf[col].c_mode |= BOLD|mode;
204: else {
205: obuf[col].c_mode = c;
206: obuf[col].c_mode = mode;
207: }
208: col++;
209: if (col > maxcol)
210: maxcol = col;
211: continue;
212: }
213: if (maxcol)
214: flushln();
215: }
216:
217: flushln()
218: {
219: register lastmode;
220: register i;
221: int hadmodes = 0;
222:
223: lastmode = NORMAL;
224: for (i=0; i<maxcol; i++) {
225: if (obuf[i].c_mode != lastmode) {
226: hadmodes++;
227: setmode(obuf[i].c_mode);
228: lastmode = obuf[i].c_mode;
229: }
230: if (obuf[i].c_char == '\0') {
231: if (upln) {
232: puts(CURS_RIGHT);
233: } else
234: outc(' ');
235: } else
236: outc(obuf[i].c_char);
237: }
238: if (lastmode != NORMAL) {
239: setmode(0);
240: }
241: if (must_overstrike && hadmodes)
242: overstrike();
243: putchar('\n');
244: if (iflag && hadmodes)
245: iattr();
246: fflush(stdout);
247: if (upln)
248: upln--;
249: initbuf();
250: }
251:
252: /*
253: * For terminals that can overstrike, overstrike underlines and bolds.
254: * We don't do anything with halfline ups and downs, or Greek.
255: */
256: overstrike()
257: {
258: register int i;
259: char lbuf[256];
260: register char *cp = lbuf;
261: int hadbold=0;
262:
263: /* Set up overstrike buffer */
264: for (i=0; i<maxcol; i++)
265: switch (obuf[i].c_mode) {
266: case NORMAL:
267: default:
268: *cp++ = ' ';
269: break;
270: case UNDERL:
271: *cp++ = '_';
272: break;
273: case BOLD:
274: *cp++ = obuf[i].c_char;
275: hadbold=1;
276: break;
277: }
278: putchar('\r');
279: for (*cp=' '; *cp==' '; cp--)
280: *cp = 0;
281: for (cp=lbuf; *cp; cp++)
282: putchar(*cp);
283: if (hadbold) {
284: putchar('\r');
285: for (cp=lbuf; *cp; cp++)
286: putchar(*cp=='_' ? ' ' : *cp);
287: putchar('\r');
288: for (cp=lbuf; *cp; cp++)
289: putchar(*cp=='_' ? ' ' : *cp);
290: }
291: }
292:
293: iattr()
294: {
295: register int i;
296: char lbuf[256];
297: register char *cp = lbuf;
298:
299: for (i=0; i<maxcol; i++)
300: switch (obuf[i].c_mode) {
301: case NORMAL: *cp++ = ' '; break;
302: case ALTSET: *cp++ = 'g'; break;
303: case SUPERSC: *cp++ = '^'; break;
304: case SUBSC: *cp++ = 'v'; break;
305: case UNDERL: *cp++ = '_'; break;
306: case BOLD: *cp++ = '!'; break;
307: default: *cp++ = 'X'; break;
308: }
309: for (*cp=' '; *cp==' '; cp--)
310: *cp = 0;
311: for (cp=lbuf; *cp; cp++)
312: putchar(*cp);
313: putchar('\n');
314: }
315:
316: initbuf()
317: {
318: register i;
319:
320: for (i=0; i<MAXBUF; i++) {
321: obuf[i].c_char = '\0';
322: obuf[i].c_mode = NORMAL;
323: }
324: col = 0;
325: maxcol = 0;
326: mode &= ALTSET;
327: }
328:
329: fwd()
330: {
331: register oldcol, oldmax;
332:
333: oldcol = col;
334: oldmax = maxcol;
335: flushln();
336: col = oldcol;
337: maxcol = oldmax;
338: }
339:
340: reverse()
341: {
342: upln++;
343: fwd();
344: puts(CURS_UP);
345: puts(CURS_UP);
346: upln++;
347: }
348:
349: initcap()
350: {
351: static char tcapbuf[512];
352: char *termtype;
353: char *bp = tcapbuf;
354: char *getenv(), *tgetstr();
355:
356: /* This nonsense attempts to work with both old and new termcap */
357: CURS_UP = tgetstr("up", &bp);
358: CURS_RIGHT = tgetstr("ri", &bp);
359: if (CURS_RIGHT == NULL)
360: CURS_RIGHT = tgetstr("nd", &bp);
361: CURS_LEFT = tgetstr("le", &bp);
362: if (CURS_LEFT == NULL)
363: CURS_LEFT = tgetstr("bc", &bp);
364: if (CURS_LEFT == NULL && tgetflag("bs"))
365: CURS_LEFT = "\b";
366:
367: ENTER_STANDOUT = tgetstr("so", &bp);
368: EXIT_STANDOUT = tgetstr("se", &bp);
369: ENTER_UNDERLINE = tgetstr("us", &bp);
370: EXIT_UNDERLINE = tgetstr("ue", &bp);
371: ENTER_DIM = tgetstr("mh", &bp);
372: ENTER_BOLD = tgetstr("md", &bp);
373: ENTER_REVERSE = tgetstr("mr", &bp);
374: EXIT_ATTRIBUTES = tgetstr("me", &bp);
375:
376: if (!ENTER_BOLD && ENTER_REVERSE)
377: ENTER_BOLD = ENTER_REVERSE;
378: if (!ENTER_BOLD && ENTER_STANDOUT)
379: ENTER_BOLD = ENTER_STANDOUT;
380: if (!ENTER_UNDERLINE && ENTER_STANDOUT) {
381: ENTER_UNDERLINE = ENTER_STANDOUT;
382: EXIT_UNDERLINE = EXIT_STANDOUT;
383: }
384: if (!ENTER_DIM && ENTER_STANDOUT)
385: ENTER_DIM = ENTER_STANDOUT;
386: if (!ENTER_REVERSE && ENTER_STANDOUT)
387: ENTER_REVERSE = ENTER_STANDOUT;
388: if (!EXIT_ATTRIBUTES && EXIT_STANDOUT)
389: EXIT_ATTRIBUTES = EXIT_STANDOUT;
390:
391: /*
392: * Note that we use REVERSE for the alternate character set,
393: * not the as/ae capabilities. This is because we are modelling
394: * the model 37 teletype (since that's what nroff outputs) and
395: * the typical as/ae is more of a graphics set, not the greek
396: * letters the 37 has.
397: */
398:
399: #ifdef notdef
400: printf("so %s se %s us %s ue %s me %s\n",
401: ENTER_STANDOUT, EXIT_STANDOUT, ENTER_UNDERLINE,
402: EXIT_UNDERLINE, EXIT_ATTRIBUTES);
403: #endif
404: UNDER_CHAR = tgetstr("uc", &bp);
405: must_use_uc = (UNDER_CHAR && !ENTER_UNDERLINE);
406: }
407:
408: outchar(c)
409: char c;
410: {
411: putchar(c&0177);
412: }
413:
414: puts(str)
415: char *str;
416: {
417: if (str)
418: tputs(str, 1, outchar);
419: }
420:
421: static curmode = 0;
422: outc(c)
423: char c;
424: {
425: putchar(c);
426: if (must_use_uc && (curmode&UNDERL)) {
427: puts(CURS_LEFT);
428: puts(UNDER_CHAR);
429: }
430: }
431:
432: setmode(newmode)
433: int newmode;
434: {
435: if (!iflag)
436: {
437: if (curmode != NORMAL && newmode != NORMAL)
438: setmode(NORMAL);
439: switch (newmode) {
440: case NORMAL:
441: switch(curmode) {
442: case NORMAL:
443: break;
444: case UNDERL:
445: puts(EXIT_UNDERLINE);
446: break;
447: default:
448: /* This includes standout */
449: puts(EXIT_ATTRIBUTES);
450: break;
451: }
452: break;
453: case ALTSET:
454: puts(ENTER_REVERSE);
455: break;
456: case SUPERSC:
457: /*
458: * This only works on a few terminals.
459: * It should be fixed.
460: */
461: puts(ENTER_UNDERLINE);
462: puts(ENTER_DIM);
463: break;
464: case SUBSC:
465: puts(ENTER_DIM);
466: break;
467: case UNDERL:
468: puts(ENTER_UNDERLINE);
469: break;
470: case BOLD:
471: puts(ENTER_BOLD);
472: break;
473: default:
474: /*
475: * We should have some provision here for multiple modes
476: * on at once. This will have to come later.
477: */
478: puts(ENTER_STANDOUT);
479: break;
480: }
481: }
482: curmode = newmode;
483: }
484: /* @(#)getopt.c 3.2 */
485: #define ERR(s, c) if(opterr){\
486: fputs(argv[0], stderr);\
487: fputs(s, stderr);\
488: fputc(c, stderr);\
489: fputc('\n', stderr);}
490:
491: int opterr = 1;
492: int optind = 1;
493: char *optarg;
494: char *index();
495:
496: int
497: getopt (argc, argv, opts)
498: char **argv, *opts;
499: {
500: static int sp = 1;
501: char c;
502: char *cp;
503:
504: if (sp == 1)
505: if (optind >= argc ||
506: argv[optind][0] != '-' || argv[optind][1] == '\0')
507: return EOF;
508: else if (strcmp(argv[optind], "--") == NULL) {
509: optind++;
510: return EOF;
511: }
512: else if (strcmp(argv[optind], "-?") == NULL) {
513: optind++;
514: return '?';
515: }
516: c = argv[optind][sp];
517: if (c == ':' || (cp=index(opts, c)) == NULL) {
518: ERR (": illegal option -- ", c);
519: if (argv[optind][++sp] == '\0') {
520: optind++;
521: sp = 1;
522: }
523: return '?';
524: }
525: if (*++cp == ':') {
526: if (argv[optind][2] != '\0')
527: optarg = &argv[optind++][sp+1];
528: else if (++optind >= argc) {
529: ERR (": option requires an argument -- ", c);
530: sp = 1;
531: return '?';
532: } else
533: optarg = argv[optind++];
534: sp = 1;
535: }
536: else if (argv[optind][++sp] == '\0') {
537: sp = 1;
538: optind++;
539: }
540: return c;
541: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.