Drop main() prototype. Syncs with NetBSD-8
[minix.git] / usr.bin / ul / ul.c
blob95809a344c958c65844d92a3a7e96c7d673a0578
1 /* $NetBSD: ul.c,v 1.16 2012/03/20 20:34:59 matt Exp $ */
3 /*
4 * Copyright (c) 1980, 1993
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
32 #include <sys/cdefs.h>
33 #ifndef lint
34 __COPYRIGHT("@(#) Copyright (c) 1980, 1993\
35 The Regents of the University of California. All rights reserved.");
36 #endif /* not lint */
38 #ifndef lint
39 #if 0
40 static char sccsid[] = "@(#)ul.c 8.1 (Berkeley) 6/6/93";
41 #endif
42 __RCSID("$NetBSD: ul.c,v 1.16 2012/03/20 20:34:59 matt Exp $");
43 #endif /* not lint */
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <string.h>
48 #include <term.h>
49 #include <unistd.h>
51 #define IESC '\033'
52 #define SO '\016'
53 #define SI '\017'
54 #define HFWD '9'
55 #define HREV '8'
56 #define FREV '7'
57 #define MAXBUF 512
59 #define NORMAL 000
60 #define ALTSET 001 /* Reverse */
61 #define SUPERSC 002 /* Dim */
62 #define SUBSC 004 /* Dim | Ul */
63 #define UNDERL 010 /* Ul */
64 #define BOLD 020 /* Bold */
66 struct tinfo *info;
67 int must_overstrike;
68 const char *CURS_UP, *CURS_RIGHT, *CURS_LEFT,
69 *ENTER_STANDOUT, *EXIT_STANDOUT, *ENTER_UNDERLINE, *EXIT_UNDERLINE,
70 *ENTER_DIM, *ENTER_BOLD, *ENTER_REVERSE, *UNDER_CHAR, *EXIT_ATTRIBUTES;
72 struct CHAR {
73 char c_mode;
74 char c_char;
75 } ;
77 struct CHAR obuf[MAXBUF];
78 int col, maxcol;
79 int mode;
80 int halfpos;
81 int upln;
82 int iflag;
84 int main __P((int, char **));
85 void filter __P((FILE *));
86 void flushln __P((void));
87 void fwd __P((void));
88 void iattr __P((void));
89 void initbuf __P((void));
90 void initcap __P((void));
91 void outc __P((int));
92 int outchar __P((int));
93 void overstrike __P((void));
94 void reverse __P((void));
95 void setulmode __P((int));
98 #define PRINT(s) if (s == NULL) /* void */; else tputs(s, 1, outchar)
101 main(int argc, char **argv)
103 int c;
104 const char *termtype;
105 FILE *f;
107 termtype = getenv("TERM");
108 if (termtype == NULL || (argv[0][0] == 'c' && !isatty(1)))
109 termtype = "lpr";
110 while ((c=getopt(argc, argv, "it:T:")) != -1)
111 switch(c) {
113 case 't':
114 case 'T': /* for nroff compatibility */
115 termtype = optarg;
116 break;
117 case 'i':
118 iflag = 1;
119 break;
121 default:
122 fprintf(stderr,
123 "usage: %s [ -i ] [ -tTerm ] file...\n",
124 argv[0]);
125 exit(1);
128 setupterm(termtype, 0, NULL);
129 if ((over_strike && enter_bold_mode == NULL) ||
130 (transparent_underline && enter_underline_mode == NULL &&
131 underline_char == NULL))
132 initbuf();
133 if (optind == argc)
134 filter(stdin);
135 else for (; optind<argc; optind++) {
136 f = fopen(argv[optind],"r");
137 if (f == NULL) {
138 perror(argv[optind]);
139 exit(1);
142 filter(f);
143 fclose(f);
145 exit(0);
148 void
149 filter(FILE *f)
151 int c;
153 while ((c = getc(f)) != EOF) switch(c) {
155 case '\b':
156 if (col > 0)
157 col--;
158 continue;
160 case '\t':
161 col = (col+8) & ~07;
162 if (col > maxcol)
163 maxcol = col;
164 continue;
166 case '\r':
167 col = 0;
168 continue;
170 case SO:
171 mode |= ALTSET;
172 continue;
174 case SI:
175 mode &= ~ALTSET;
176 continue;
178 case IESC:
179 switch (c = getc(f)) {
181 case HREV:
182 if (halfpos == 0) {
183 mode |= SUPERSC;
184 halfpos--;
185 } else if (halfpos > 0) {
186 mode &= ~SUBSC;
187 halfpos--;
188 } else {
189 halfpos = 0;
190 reverse();
192 continue;
194 case HFWD:
195 if (halfpos == 0) {
196 mode |= SUBSC;
197 halfpos++;
198 } else if (halfpos < 0) {
199 mode &= ~SUPERSC;
200 halfpos++;
201 } else {
202 halfpos = 0;
203 fwd();
205 continue;
207 case FREV:
208 reverse();
209 continue;
211 default:
212 fprintf(stderr,
213 "Unknown escape sequence in input: %o, %o\n",
214 IESC, c);
215 exit(1);
217 continue;
219 case '_':
220 if (obuf[col].c_char)
221 obuf[col].c_mode |= UNDERL | mode;
222 else
223 obuf[col].c_char = '_';
224 case ' ':
225 col++;
226 if (col > maxcol)
227 maxcol = col;
228 continue;
230 case '\n':
231 flushln();
232 continue;
234 case '\f':
235 flushln();
236 putchar('\f');
237 continue;
239 default:
240 if (c < ' ') /* non printing */
241 continue;
242 if (obuf[col].c_char == '\0') {
243 obuf[col].c_char = c;
244 obuf[col].c_mode = mode;
245 } else if (obuf[col].c_char == '_') {
246 obuf[col].c_char = c;
247 obuf[col].c_mode |= UNDERL|mode;
248 } else if (obuf[col].c_char == c)
249 obuf[col].c_mode |= BOLD|mode;
250 else
251 obuf[col].c_mode = mode;
252 col++;
253 if (col > maxcol)
254 maxcol = col;
255 continue;
257 if (maxcol)
258 flushln();
261 void
262 flushln(void)
264 int lastmode;
265 int i;
266 int hadmodes = 0;
268 lastmode = NORMAL;
269 for (i=0; i<maxcol; i++) {
270 if (obuf[i].c_mode != lastmode) {
271 hadmodes++;
272 setulmode(obuf[i].c_mode);
273 lastmode = obuf[i].c_mode;
275 if (obuf[i].c_char == '\0') {
276 if (upln) {
277 PRINT(cursor_right);
279 else {
280 outc(' ');
282 } else
283 outc(obuf[i].c_char);
285 if (lastmode != NORMAL) {
286 setulmode(0);
288 if (must_overstrike && hadmodes)
289 overstrike();
290 putchar('\n');
291 if (iflag && hadmodes)
292 iattr();
293 (void)fflush(stdout);
294 if (upln)
295 upln--;
296 initbuf();
300 * For terminals that can overstrike, overstrike underlines and bolds.
301 * We don't do anything with halfline ups and downs, or Greek.
303 void
304 overstrike(void)
306 int i;
307 char lbuf[256];
308 char *cp = lbuf;
309 int hadbold=0;
311 /* Set up overstrike buffer */
312 for (i=0; i<maxcol; i++)
313 switch (obuf[i].c_mode) {
314 case NORMAL:
315 default:
316 *cp++ = ' ';
317 break;
318 case UNDERL:
319 *cp++ = '_';
320 break;
321 case BOLD:
322 *cp++ = obuf[i].c_char;
323 hadbold=1;
324 break;
326 putchar('\r');
327 for (*cp=' '; *cp==' '; cp--)
328 *cp = 0;
329 for (cp=lbuf; *cp; cp++)
330 putchar(*cp);
331 if (hadbold) {
332 putchar('\r');
333 for (cp=lbuf; *cp; cp++)
334 putchar(*cp=='_' ? ' ' : *cp);
335 putchar('\r');
336 for (cp=lbuf; *cp; cp++)
337 putchar(*cp=='_' ? ' ' : *cp);
341 void
342 iattr(void)
344 int i;
345 char lbuf[256];
346 char *cp = lbuf;
348 for (i=0; i<maxcol; i++)
349 switch (obuf[i].c_mode) {
350 case NORMAL: *cp++ = ' '; break;
351 case ALTSET: *cp++ = 'g'; break;
352 case SUPERSC: *cp++ = '^'; break;
353 case SUBSC: *cp++ = 'v'; break;
354 case UNDERL: *cp++ = '_'; break;
355 case BOLD: *cp++ = '!'; break;
356 default: *cp++ = 'X'; break;
358 for (*cp=' '; *cp==' '; cp--)
359 *cp = 0;
360 for (cp=lbuf; *cp; cp++)
361 putchar(*cp);
362 putchar('\n');
365 void
366 initbuf(void)
369 memset((char *)obuf, 0, sizeof (obuf)); /* depends on NORMAL == 0 */
370 col = 0;
371 maxcol = 0;
372 mode &= ALTSET;
375 void
376 fwd(void)
378 int oldcol, oldmax;
380 oldcol = col;
381 oldmax = maxcol;
382 flushln();
383 col = oldcol;
384 maxcol = oldmax;
387 void
388 reverse(void)
390 upln++;
391 fwd();
392 PRINT(cursor_up);
393 PRINT(cursor_up);
394 upln++;
398 outchar(int c)
400 return (putchar(c & 0177));
403 static int curmode = 0;
405 void
406 outc(int c)
408 putchar(c);
409 if (underline_char && !enter_underline_mode && (curmode & UNDERL)) {
410 if (cursor_left)
411 PRINT(cursor_left);
412 else
413 putchar('\b');
414 PRINT(underline_char);
418 void
419 setulmode(int newmode)
421 if (!iflag) {
422 if (curmode != NORMAL && newmode != NORMAL)
423 setulmode(NORMAL);
424 switch (newmode) {
425 case NORMAL:
426 switch(curmode) {
427 case NORMAL:
428 break;
429 case UNDERL:
430 if (enter_underline_mode)
431 PRINT(exit_underline_mode);
432 else
433 PRINT(exit_standout_mode);
434 break;
435 default:
436 /* This includes standout */
437 if (exit_attribute_mode)
438 PRINT(exit_attribute_mode);
439 else
440 PRINT(exit_standout_mode);
441 break;
443 break;
444 case ALTSET:
445 if (enter_reverse_mode)
446 PRINT(enter_reverse_mode);
447 else
448 PRINT(enter_standout_mode);
449 break;
450 case SUPERSC:
452 * This only works on a few terminals.
453 * It should be fixed.
455 PRINT(enter_underline_mode);
456 PRINT(enter_dim_mode);
457 break;
458 case SUBSC:
459 if (enter_dim_mode)
460 PRINT(enter_dim_mode);
461 else
462 PRINT(enter_standout_mode);
463 break;
464 case UNDERL:
465 if (enter_underline_mode)
466 PRINT(enter_underline_mode);
467 else
468 PRINT(enter_standout_mode);
469 break;
470 case BOLD:
471 if (enter_bold_mode)
472 PRINT(enter_bold_mode);
473 else
474 PRINT(enter_reverse_mode);
475 break;
476 default:
478 * We should have some provision here for multiple modes
479 * on at once. This will have to come later.
481 PRINT(enter_standout_mode);
482 break;
485 curmode = newmode;