Commit | Line | Data |
---|---|---|
77031d39 MH |
1 | /* |
2 | * | |
3 | * ul - General underline filter. Converts underlines by | |
4 | * the standard backspacing method to the code used by the | |
5 | * particular terminal to underline. | |
6 | * | |
7 | */ | |
8 | #include <stdio.h> | |
9 | char buf[BUFSIZ]; | |
10 | char isul[BUFSIZ]; | |
11 | char termcap[1024]; | |
12 | char ulbuf[BUFSIZ]; | |
13 | char *stul, *endul, *chul; | |
14 | char *backspace; | |
15 | char *termtype; | |
16 | int outc(); | |
17 | char *tgetstr(); | |
18 | char *getenv(); | |
19 | ||
20 | main(argc,argv) char **argv; { | |
21 | register int i; | |
22 | char *cp; | |
23 | FILE *f; | |
24 | ||
25 | /* Figure out kind of terminal and set up special strings. */ | |
26 | termtype = getenv("TERM"); | |
27 | if (termtype == NULL) | |
28 | termtype = "dumb"; | |
29 | while (argc >= 2 && argv[1][0] == '-') { | |
30 | switch(argv[1][1]) { | |
31 | case 't': | |
32 | case 'T': /* for nroff compatibility */ | |
33 | if (argv[1][2]) | |
34 | termtype = &argv[1][2]; | |
35 | else { | |
36 | termtype = argv[2]; | |
37 | argc--; | |
38 | argv++; | |
39 | } | |
40 | break; | |
41 | default: | |
42 | printf("Bad switch: %s\n",argv[1]); | |
43 | exit(1); | |
44 | } | |
45 | } | |
46 | switch(tgetent(termcap, termtype)) { | |
47 | case 1: /* All is well */ | |
48 | /* Terminals that don't need any help. */ | |
49 | if (tgetflag("ul") || tgetflag("os")) | |
50 | execv("/bin/cat",argv); | |
51 | cp = ulbuf; | |
52 | if ((backspace = tgetstr("bc",&cp)) == NULL) | |
53 | backspace = "\b"; | |
54 | /* | |
55 | * Handle terminals that have start underline/stop | |
56 | * underline sequences, as well as those with | |
57 | * underline char sequences (we assume the sequence | |
58 | * moves the cursor forward one character). | |
59 | * If we can't find underline sequences, we | |
60 | * settle for standout sequences. | |
61 | */ | |
62 | if ( (chul=tgetstr("uc",&cp)) == NULL) | |
63 | chul = ""; | |
64 | if ( (stul=tgetstr("us",&cp)) == NULL && | |
65 | (!*chul) && (stul=tgetstr("so",&cp)) == NULL) | |
66 | stul = ""; | |
67 | if ( (endul=tgetstr("ue",&cp)) == NULL && | |
68 | (!*chul) && (endul=tgetstr("se",&cp)) == NULL) | |
69 | endul = ""; | |
70 | break; | |
71 | default:/* error opening/reading termcap */ | |
72 | fprintf(stderr,"trouble reading termcap"); | |
73 | /* fall through to ... */ | |
74 | case 0: /* No such terminal type - assume dumb */ | |
75 | stul = endul = chul = ""; | |
76 | break; | |
77 | } | |
78 | if (argc < 2) filter(stdin); | |
79 | else for (i=1; i<argc; i++) { | |
80 | f = fopen(argv[i],"r"); | |
81 | if (f == NULL) { | |
82 | printf("Can't open %s\n",argv[i]); | |
83 | exit(1); | |
84 | } else filter(f); | |
85 | } | |
86 | exit(0); | |
87 | } | |
88 | ||
89 | filter(f) | |
90 | FILE *f; | |
91 | { | |
92 | register int p, n; | |
93 | register char c; | |
94 | int state; | |
95 | ||
96 | n = 0; | |
97 | for (;;) { | |
98 | p = 0; | |
99 | for (p=0; p<n; p++) { | |
100 | buf[p] = '\0'; | |
101 | isul[p] = 0; | |
102 | } | |
103 | p = n = 0; | |
104 | ||
105 | for (;;) { | |
106 | c = getc(f); | |
107 | if (c==EOF) break; | |
108 | if (c=='\b') { | |
109 | if (p > 0) { | |
110 | p--; | |
111 | } | |
112 | } else if (c=='_' && isul[p]==0 && buf[p]) { | |
113 | isul[p] = 1; | |
114 | p++; | |
115 | } else { | |
116 | if (buf[p] == '_') { | |
117 | isul[p] = 1; | |
118 | } | |
119 | buf[p] = c; | |
120 | p++; | |
121 | if (n < p) n = p; | |
122 | } | |
123 | if (c=='\n') break; | |
124 | } | |
125 | ||
126 | state = 0; | |
127 | for (p=0; p<n; p++) { | |
128 | if (isul[p] != state) | |
129 | tputs(isul[p] ? stul : endul, 1, outc); | |
130 | state = isul[p]; | |
131 | outc(buf[p]); | |
132 | if (isul[p] && *chul) { | |
133 | printf("%s",backspace); | |
134 | tputs(chul, 1, outc); | |
135 | } | |
136 | } | |
137 | if (c==EOF) break; | |
138 | } | |
139 | } | |
140 | ||
141 | outc(c) | |
142 | char c; | |
143 | { | |
144 | putchar(c); | |
145 | } |