|
|
1.1 root 1: /*
2: * Copyright (c) 1980 Regents of the University of California.
3: * All rights reserved. The Berkeley software License Agreement
4: * specifies the terms and conditions for redistribution.
5: */
6:
7: #ifndef lint
8: char copyright[] =
9: "@(#) Copyright (c) 1980 Regents of the University of California.\n\
10: All rights reserved.\n";
11: #endif not lint
12:
13: #ifndef lint
14: static char sccsid[] = "@(#)ul.c 5.1 (Berkeley) 5/31/85";
15: #endif not lint
16:
17: #include <stdio.h>
18:
19: #define IESC '\033'
20: #define SO '\016'
21: #define SI '\017'
22: #define HFWD '9'
23: #define HREV '8'
24: #define FREV '7'
25: #define MAXBUF 512
26:
27: #define NORMAL 000
28: #define ALTSET 001 /* Reverse */
29: #define SUPERSC 002 /* Dim */
30: #define SUBSC 004 /* Dim | Ul */
31: #define UNDERL 010 /* Ul */
32: #define BOLD 020 /* Bold */
33:
34: int must_use_uc, must_overstrike;
35: char *CURS_UP, *CURS_RIGHT, *CURS_LEFT,
36: *ENTER_STANDOUT, *EXIT_STANDOUT, *ENTER_UNDERLINE, *EXIT_UNDERLINE,
37: *ENTER_DIM, *ENTER_BOLD, *ENTER_REVERSE, *UNDER_CHAR, *EXIT_ATTRIBUTES;
38:
39: struct CHAR {
40: char c_mode;
41: char c_char;
42: } ;
43:
44: struct CHAR obuf[MAXBUF];
45: int col, maxcol;
46: int mode;
47: int halfpos;
48: int upln;
49: int iflag;
50:
51: main(argc, argv)
52: int argc;
53: char **argv;
54: {
55: int c;
56: char *cp, *termtype;
57: FILE *f;
58: char termcap[1024];
59: char *getenv();
60: extern int optind;
61: extern char *optarg;
62:
63: termtype = getenv("TERM");
64: if (termtype == NULL || (argv[0][0] == 'c' && !isatty(1)))
65: termtype = "lpr";
66: while ((c=getopt(argc, argv, "it:T:")) != EOF)
67: switch(c) {
68:
69: case 't':
70: case 'T': /* for nroff compatibility */
71: termtype = optarg;
72: break;
73: case 'i':
74: iflag = 1;
75: break;
76:
77: default:
78: fprintf(stderr,
79: "Usage: %s [ -i ] [ -tTerm ] file...\n",
80: argv[0]);
81: exit(1);
82: }
83:
84: switch(tgetent(termcap, termtype)) {
85:
86: case 1:
87: break;
88:
89: default:
90: fprintf(stderr,"trouble reading termcap");
91: /* fall through to ... */
92:
93: case 0:
94: /* No such terminal type - assume dumb */
95: strcpy(termcap, "dumb:os:col#80:cr=^M:sf=^J:am:");
96: break;
97: }
98: initcap();
99: if ( (tgetflag("os") && ENTER_BOLD==NULL ) ||
100: (tgetflag("ul") && ENTER_UNDERLINE==NULL && UNDER_CHAR==NULL))
101: must_overstrike = 1;
102: initbuf();
103: if (optind == argc)
104: filter(stdin);
105: else for (; optind<argc; optind++) {
106: f = fopen(argv[optind],"r");
107: if (f == NULL) {
108: perror(argv[optind]);
109: exit(1);
110: } else
111: filter(f);
112: }
113: exit(0);
114: }
115:
116: filter(f)
117: FILE *f;
118: {
119: register c;
120:
121: while((c = getc(f)) != EOF) switch(c) {
122:
123: case '\b':
124: if (col > 0)
125: col--;
126: continue;
127:
128: case '\t':
129: col = (col+8) & ~07;
130: if (col > maxcol)
131: maxcol = col;
132: continue;
133:
134: case '\r':
135: col = 0;
136: continue;
137:
138: case SO:
139: mode |= ALTSET;
140: continue;
141:
142: case SI:
143: mode &= ~ALTSET;
144: continue;
145:
146: case IESC:
147: switch (c = getc(f)) {
148:
149: case HREV:
150: if (halfpos == 0) {
151: mode |= SUPERSC;
152: halfpos--;
153: } else if (halfpos > 0) {
154: mode &= ~SUBSC;
155: halfpos--;
156: } else {
157: halfpos = 0;
158: reverse();
159: }
160: continue;
161:
162: case HFWD:
163: if (halfpos == 0) {
164: mode |= SUBSC;
165: halfpos++;
166: } else if (halfpos < 0) {
167: mode &= ~SUPERSC;
168: halfpos++;
169: } else {
170: halfpos = 0;
171: fwd();
172: }
173: continue;
174:
175: case FREV:
176: reverse();
177: continue;
178:
179: default:
180: fprintf(stderr,
181: "Unknown escape sequence in input: %o, %o\n",
182: IESC, c);
183: exit(1);
184: }
185: continue;
186:
187: case '_':
188: if (obuf[col].c_char)
189: obuf[col].c_mode |= UNDERL | mode;
190: else
191: obuf[col].c_char = '_';
192: case ' ':
193: col++;
194: if (col > maxcol)
195: maxcol = col;
196: continue;
197:
198: case '\n':
199: flushln();
200: continue;
201:
202: default:
203: if (c < ' ') /* non printing */
204: continue;
205: if (obuf[col].c_char == '\0') {
206: obuf[col].c_char = c;
207: obuf[col].c_mode = mode;
208: } else if (obuf[col].c_char == '_') {
209: obuf[col].c_char = c;
210: obuf[col].c_mode |= UNDERL|mode;
211: } else if (obuf[col].c_char == c)
212: obuf[col].c_mode |= BOLD|mode;
213: else {
214: obuf[col].c_mode = c;
215: obuf[col].c_mode = mode;
216: }
217: col++;
218: if (col > maxcol)
219: maxcol = col;
220: continue;
221: }
222: if (maxcol)
223: flushln();
224: }
225:
226: flushln()
227: {
228: register lastmode;
229: register i;
230: int hadmodes = 0;
231:
232: lastmode = NORMAL;
233: for (i=0; i<maxcol; i++) {
234: if (obuf[i].c_mode != lastmode) {
235: hadmodes++;
236: setmode(obuf[i].c_mode);
237: lastmode = obuf[i].c_mode;
238: }
239: if (obuf[i].c_char == '\0') {
240: if (upln) {
241: puts(CURS_RIGHT);
242: } else
243: outc(' ');
244: } else
245: outc(obuf[i].c_char);
246: }
247: if (lastmode != NORMAL) {
248: setmode(0);
249: }
250: if (must_overstrike && hadmodes)
251: overstrike();
252: putchar('\n');
253: if (iflag && hadmodes)
254: iattr();
255: fflush(stdout);
256: if (upln)
257: upln--;
258: initbuf();
259: }
260:
261: /*
262: * For terminals that can overstrike, overstrike underlines and bolds.
263: * We don't do anything with halfline ups and downs, or Greek.
264: */
265: overstrike()
266: {
267: register int i;
268: char lbuf[256];
269: register char *cp = lbuf;
270: int hadbold=0;
271:
272: /* Set up overstrike buffer */
273: for (i=0; i<maxcol; i++)
274: switch (obuf[i].c_mode) {
275: case NORMAL:
276: default:
277: *cp++ = ' ';
278: break;
279: case UNDERL:
280: *cp++ = '_';
281: break;
282: case BOLD:
283: *cp++ = obuf[i].c_char;
284: hadbold=1;
285: break;
286: }
287: putchar('\r');
288: for (*cp=' '; *cp==' '; cp--)
289: *cp = 0;
290: for (cp=lbuf; *cp; cp++)
291: putchar(*cp);
292: if (hadbold) {
293: putchar('\r');
294: for (cp=lbuf; *cp; cp++)
295: putchar(*cp=='_' ? ' ' : *cp);
296: putchar('\r');
297: for (cp=lbuf; *cp; cp++)
298: putchar(*cp=='_' ? ' ' : *cp);
299: }
300: }
301:
302: iattr()
303: {
304: register int i;
305: char lbuf[256];
306: register char *cp = lbuf;
307:
308: for (i=0; i<maxcol; i++)
309: switch (obuf[i].c_mode) {
310: case NORMAL: *cp++ = ' '; break;
311: case ALTSET: *cp++ = 'g'; break;
312: case SUPERSC: *cp++ = '^'; break;
313: case SUBSC: *cp++ = 'v'; break;
314: case UNDERL: *cp++ = '_'; break;
315: case BOLD: *cp++ = '!'; break;
316: default: *cp++ = 'X'; break;
317: }
318: for (*cp=' '; *cp==' '; cp--)
319: *cp = 0;
320: for (cp=lbuf; *cp; cp++)
321: putchar(*cp);
322: putchar('\n');
323: }
324:
325: initbuf()
326: {
327:
328: bzero(obuf, sizeof (obuf)); /* depends on NORMAL == 0 */
329: col = 0;
330: maxcol = 0;
331: mode &= ALTSET;
332: }
333:
334: fwd()
335: {
336: register oldcol, oldmax;
337:
338: oldcol = col;
339: oldmax = maxcol;
340: flushln();
341: col = oldcol;
342: maxcol = oldmax;
343: }
344:
345: reverse()
346: {
347: upln++;
348: fwd();
349: puts(CURS_UP);
350: puts(CURS_UP);
351: upln++;
352: }
353:
354: initcap()
355: {
356: static char tcapbuf[512];
357: char *termtype;
358: char *bp = tcapbuf;
359: char *getenv(), *tgetstr();
360:
361: /* This nonsense attempts to work with both old and new termcap */
362: CURS_UP = tgetstr("up", &bp);
363: CURS_RIGHT = tgetstr("ri", &bp);
364: if (CURS_RIGHT == NULL)
365: CURS_RIGHT = tgetstr("nd", &bp);
366: CURS_LEFT = tgetstr("le", &bp);
367: if (CURS_LEFT == NULL)
368: CURS_LEFT = tgetstr("bc", &bp);
369: if (CURS_LEFT == NULL && tgetflag("bs"))
370: CURS_LEFT = "\b";
371:
372: ENTER_STANDOUT = tgetstr("so", &bp);
373: EXIT_STANDOUT = tgetstr("se", &bp);
374: ENTER_UNDERLINE = tgetstr("us", &bp);
375: EXIT_UNDERLINE = tgetstr("ue", &bp);
376: ENTER_DIM = tgetstr("mh", &bp);
377: ENTER_BOLD = tgetstr("md", &bp);
378: ENTER_REVERSE = tgetstr("mr", &bp);
379: EXIT_ATTRIBUTES = tgetstr("me", &bp);
380:
381: if (!ENTER_BOLD && ENTER_REVERSE)
382: ENTER_BOLD = ENTER_REVERSE;
383: if (!ENTER_BOLD && ENTER_STANDOUT)
384: ENTER_BOLD = ENTER_STANDOUT;
385: if (!ENTER_UNDERLINE && ENTER_STANDOUT) {
386: ENTER_UNDERLINE = ENTER_STANDOUT;
387: EXIT_UNDERLINE = EXIT_STANDOUT;
388: }
389: if (!ENTER_DIM && ENTER_STANDOUT)
390: ENTER_DIM = ENTER_STANDOUT;
391: if (!ENTER_REVERSE && ENTER_STANDOUT)
392: ENTER_REVERSE = ENTER_STANDOUT;
393: if (!EXIT_ATTRIBUTES && EXIT_STANDOUT)
394: EXIT_ATTRIBUTES = EXIT_STANDOUT;
395:
396: /*
397: * Note that we use REVERSE for the alternate character set,
398: * not the as/ae capabilities. This is because we are modelling
399: * the model 37 teletype (since that's what nroff outputs) and
400: * the typical as/ae is more of a graphics set, not the greek
401: * letters the 37 has.
402: */
403:
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.