2 * Copyright 2000 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
6 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
7 /* All Rights Reserved */
10 * Copyright (c) 1980 Regents of the University of California.
11 * All rights reserved. The Berkeley software License Agreement
12 * specifies the terms and conditions for redistribution.
15 #pragma ident "%Z%%M% %I% %E% SMI"
38 #define ALTSET 001 /* Reverse */
39 #define SUPERSC 002 /* Dim */
40 #define SUBSC 004 /* Dim | Ul */
41 #define UNDERL 010 /* Ul */
42 #define BOLD 020 /* Bold */
46 * MEMFCT is a number that is likely to be large enough as a factor for
47 * allocating more memory and to be small enough so as not wasting memory
50 int must_use_uc
, must_overstrike
;
51 char *CURS_UP
, *CURS_RIGHT
, *CURS_LEFT
,
52 *ENTER_STANDOUT
, *EXIT_STANDOUT
, *ENTER_UNDERLINE
, *EXIT_UNDERLINE
,
53 *ENTER_DIM
, *ENTER_BOLD
, *ENTER_REVERSE
, *UNDER_CHAR
, *EXIT_ATTRIBUTES
;
60 struct CHAR obuf
[LINE_MAX
];
70 void setmode(int newmode
);
78 void overstrike(void);
80 void ul_filter(FILE *f
);
81 void ul_puts(char *str
);
84 main(int argc
, char **argv
)
93 (void) setlocale(LC_ALL
, "");
94 #if !defined(TEXT_DOMAIN)
95 #define TEXT_DOMAIN "SYS_TEST"
97 (void) textdomain(TEXT_DOMAIN
);
105 termtype
= getenv("TERM");
106 if (termtype
== NULL
|| (argv
[0][0] == 'c' && !isatty(1)))
108 while ((c
= getopt(argc
, argv
, "it:T:")) != EOF
)
112 case 'T': /* for nroff compatibility */
120 (void) fprintf(stderr
,
122 Usage: %s [ -i ] [ -t terminal ] [ filename...]\n"),
127 switch (tgetent(termcap
, termtype
)) {
133 (void) fprintf(stderr
, gettext("trouble reading termcap"));
137 /* No such terminal type - assume dumb */
138 (void) strcpy(termcap
, "dumb:os:col#80:cr=^M:sf=^J:am:");
142 if ((tgetflag("os") && ENTER_BOLD
== NULL
) || (tgetflag("ul") &&
143 ENTER_UNDERLINE
== NULL
&& UNDER_CHAR
== NULL
))
148 else for (; optind
< argc
; optind
++) {
149 f
= fopen(argv
[optind
], "r");
151 perror(argv
[optind
]);
165 while ((c
= getwc(f
)) != EOF
) {
166 if (maxcol
>= LINE_MAX
) {
167 (void) fprintf(stderr
,
168 gettext("Input line longer than %d characters\n"), LINE_MAX
);
197 switch (c
= getwc(f
)) {
202 } else if (halfpos
> 0) {
215 } else if (halfpos
< 0) {
228 (void) fprintf(stderr
,
229 gettext("Unknown escape sequence in input: %o, %o\n"),
236 if (obuf
[col
].c_char
)
237 obuf
[col
].c_mode
|= UNDERL
| mode
;
239 obuf
[col
].c_char
= '_';
253 if (c
< L
' ') /* non printing */
255 if (obuf
[col
].c_char
== L
'\0') {
256 obuf
[col
].c_char
= c
;
257 obuf
[col
].c_mode
= mode
;
258 i
= scrw
[wcsetno(c
)];
260 obuf
[++col
].c_char
= CDUMMY
;
261 } else if (obuf
[col
].c_char
== L
'_') {
262 obuf
[col
].c_char
= c
;
263 obuf
[col
].c_mode
|= UNDERL
|mode
;
264 i
= scrw
[wcsetno(c
)];
266 obuf
[++col
].c_char
= CDUMMY
;
267 } else if (obuf
[col
].c_char
== c
)
268 obuf
[col
].c_mode
|= BOLD
|mode
;
270 obuf
[col
].c_char
= c
;
271 obuf
[col
].c_mode
= mode
;
291 for (i
= 0; i
< maxcol
; i
++) {
292 if (obuf
[i
].c_mode
!= lastmode
) {
294 setmode(obuf
[i
].c_mode
);
295 lastmode
= obuf
[i
].c_mode
;
297 if (obuf
[i
].c_char
== L
'\0') {
303 outc(obuf
[i
].c_char
);
305 if (lastmode
!= NORMAL
) {
308 if (must_overstrike
&& hadmodes
)
310 (void) putwchar(L
'\n');
311 if (iflag
&& hadmodes
)
319 * For terminals that can overstrike, overstrike underlines and bolds.
320 * We don't do anything with halfline ups and downs, or Greek.
327 size_t szbf
= 256, tszbf
;
330 scp
= (wchar_t *)malloc(sizeof (wchar_t) * szbf
);
332 /* this kind of message need not to be gettext'ed */
333 (void) fprintf(stderr
, "malloc failed\n");
340 * to allocate a memory after the chunk of the current scp
341 * and to make sure the following realloc() allocates
342 * memory from different chunks.
344 (void) malloc(1024 * 1024);
347 /* Set up overstrike buffer */
348 for (i
= 0; i
< maxcol
; i
++) {
349 n
= scrw
[wcsetno(obuf
[i
].c_char
)];
351 /* may not enough buffer for this char */
354 /* obtain the offset of cp */
356 /* reallocate another (n * MEMFCT) * sizeof (wchar_t) */
357 scp
= (wchar_t *)realloc(scp
,
358 sizeof (wchar_t) * (szbf
+ (n
* MEMFCT
)));
360 (void) fprintf(stderr
, "malloc failed\n");
363 /* get the new address of cp */
368 switch (obuf
[i
].c_mode
) {
388 *cp
++ = obuf
[i
].c_char
;
393 (void) putwchar(L
'\r');
394 for (*cp
= L
' '; *cp
== L
' '; cp
--)
396 for (cp
= scp
; *cp
; cp
++)
397 (void) putwchar(*cp
);
399 (void) putwchar(L
'\r');
400 for (cp
= scp
; *cp
; cp
++)
401 (void) putwchar(*cp
== L
'_' ? L
' ' : *cp
);
402 (void) putwchar(L
'\r');
403 for (cp
= scp
; *cp
; cp
++)
404 (void) putwchar(*cp
== L
'_' ? L
' ' : *cp
);
415 size_t szbf
= 256, tszbf
;
417 scp
= (wchar_t *)malloc(sizeof (wchar_t) * szbf
);
419 /* this kind of message need not to be gettext'ed */
420 (void) fprintf(stderr
, "malloc failed\n");
427 * to allocate a memory after the chunk of the current scp
428 * and to make sure the following realloc() allocates
429 * memory from different chunks.
431 (void) malloc(1024 * 1024);
433 for (i
= 0; i
< maxcol
; i
++) {
434 switch (obuf
[i
].c_mode
) {
435 case NORMAL
: cx
= ' '; break;
436 case ALTSET
: cx
= 'g'; break;
437 case SUPERSC
: cx
= '^'; break;
438 case SUBSC
: cx
= 'v'; break;
439 case UNDERL
: cx
= '_'; break;
440 case BOLD
: cx
= '!'; break;
441 default: cx
= 'X'; break;
443 n
= scrw
[wcsetno(obuf
[i
].c_char
)];
445 /* may not enough buffer for this char */
448 /* obtain the offset of cp */
450 /* reallocate another (n * MEMFCT) * sizeof (wchar_t) */
451 scp
= (wchar_t *)realloc(scp
,
452 sizeof (wchar_t) * (szbf
+ (n
* MEMFCT
)));
454 (void) fprintf(stderr
, "malloc failed\n");
457 /* get the new address of cp */
469 for (*cp
= L
' '; *cp
== L
' '; cp
--)
471 for (cp
= scp
; *cp
; cp
++)
472 (void) putwchar(*cp
);
473 (void) putwchar(L
'\n');
482 /* following depends on NORMAL == 000 */
483 for (i
= 0; i
< LINE_MAX
; i
++)
484 obuf
[i
].c_char
= obuf
[i
].c_mode
= 0;
516 static char tcapbuf
[512];
519 /* This nonsense attempts to work with both old and new termcap */
520 CURS_UP
= tgetstr("up", &bp
);
521 CURS_RIGHT
= tgetstr("ri", &bp
);
522 if (CURS_RIGHT
== NULL
)
523 CURS_RIGHT
= tgetstr("nd", &bp
);
524 CURS_LEFT
= tgetstr("le", &bp
);
525 if (CURS_LEFT
== NULL
)
526 CURS_LEFT
= tgetstr("bc", &bp
);
527 if (CURS_LEFT
== NULL
&& tgetflag("bs"))
530 ENTER_STANDOUT
= tgetstr("so", &bp
);
531 EXIT_STANDOUT
= tgetstr("se", &bp
);
532 ENTER_UNDERLINE
= tgetstr("us", &bp
);
533 EXIT_UNDERLINE
= tgetstr("ue", &bp
);
534 ENTER_DIM
= tgetstr("mh", &bp
);
535 ENTER_BOLD
= tgetstr("md", &bp
);
536 ENTER_REVERSE
= tgetstr("mr", &bp
);
537 EXIT_ATTRIBUTES
= tgetstr("me", &bp
);
539 if (!ENTER_BOLD
&& ENTER_REVERSE
)
540 ENTER_BOLD
= ENTER_REVERSE
;
541 if (!ENTER_BOLD
&& ENTER_STANDOUT
)
542 ENTER_BOLD
= ENTER_STANDOUT
;
543 if (!ENTER_UNDERLINE
&& ENTER_STANDOUT
) {
544 ENTER_UNDERLINE
= ENTER_STANDOUT
;
545 EXIT_UNDERLINE
= EXIT_STANDOUT
;
547 if (!ENTER_DIM
&& ENTER_STANDOUT
)
548 ENTER_DIM
= ENTER_STANDOUT
;
549 if (!ENTER_REVERSE
&& ENTER_STANDOUT
)
550 ENTER_REVERSE
= ENTER_STANDOUT
;
551 if (!EXIT_ATTRIBUTES
&& EXIT_STANDOUT
)
552 EXIT_ATTRIBUTES
= EXIT_STANDOUT
;
555 * Note that we use REVERSE for the alternate character set,
556 * not the as/ae capabilities. This is because we are modelling
557 * the model 37 teletype (since that's what nroff outputs) and
558 * the typical as/ae is more of a graphics set, not the greek
559 * letters the 37 has.
563 printf("so %s se %s us %s ue %s me %s\n",
564 ENTER_STANDOUT
, EXIT_STANDOUT
, ENTER_UNDERLINE
,
565 EXIT_UNDERLINE
, EXIT_ATTRIBUTES
);
567 UNDER_CHAR
= tgetstr("uc", &bp
);
568 must_use_uc
= (UNDER_CHAR
&& !ENTER_UNDERLINE
);
574 (void) putchar(c
&0177);
582 (void) tputs(str
, 1, outchar
);
585 static int curmode
= 0;
595 if (must_use_uc
&& (curmode
& UNDERL
)) {
596 m
= n
= scrw
[wcsetno(c
)];
610 if (curmode
!= NORMAL
&& newmode
!= NORMAL
)
618 ul_puts(EXIT_UNDERLINE
);
621 /* This includes standout */
622 ul_puts(EXIT_ATTRIBUTES
);
627 ul_puts(ENTER_REVERSE
);
631 * This only works on a few terminals.
632 * It should be fixed.
634 ul_puts(ENTER_UNDERLINE
);
641 ul_puts(ENTER_UNDERLINE
);
648 * We should have some provision here for multiple modes
649 * on at once. This will have to come later.
651 ul_puts(ENTER_STANDOUT
);