47
47
#include <stdlib.h> /* for getenv() */
48
48
#include <limits.h> /* for INT_MAX */
49
49
#include <signal.h> /* for signal() */
54
54
#include "xalloc.h"
55
55
#include "widechar.h"
57
58
#ifdef HAVE_WIDECHAR
58
static int put1wc(int c) /* Output an ASCII character as a wide character */
59
/* Output an ASCII character as a wide character */
60
static int put1wc(int c)
60
if (putwchar(c) == WEOF)
62
if (putwchar(c) == WEOF)
65
#define putwp(s) tputs(s,1,put1wc)
67
#define putwp(s) tputs(s, STDOUT_FILENO, put1wc)
67
69
#define putwp(s) putp(s)
72
void overstrike(void);
78
void outc(wint_t c, int width);
79
void setmode(int newmode);
72
static void usage(FILE *out);
73
static int handle_escape(FILE * f);
74
static void filter(FILE *f);
75
static void flushln(void);
76
static void overstrike(void);
77
static void iattr(void);
78
static void initbuf(void);
79
static void fwd(void);
80
static void reverse(void);
81
static void initinfo(void);
82
static void outc(wint_t c, int width);
83
static void setmode(int newmode);
80
84
static void setcol(int newcol);
81
85
static void needcol(int col);
82
86
static void sig_handler(int signo);
87
static void print_out(char *line);
84
89
#define IESC '\033'
94
99
#define SUBSC 004 /* Dim | Ul */
95
100
#define UNDERL 010 /* Ul */
96
101
#define BOLD 020 /* Bold */
99
103
int must_use_uc, must_overstrike;
100
char *CURS_UP, *CURS_RIGHT, *CURS_LEFT,
101
*ENTER_STANDOUT, *EXIT_STANDOUT, *ENTER_UNDERLINE, *EXIT_UNDERLINE,
102
*ENTER_DIM, *ENTER_BOLD, *ENTER_REVERSE, *UNDER_CHAR, *EXIT_ATTRIBUTES;
110
123
struct CHAR *obuf;
111
int obuflen; /* Tracks number of elements in obuf. */
118
#define PRINT(s) if (s == NULL) /* void */; else putwp(s)
131
static void __attribute__((__noreturn__))
136
" %s [options] [file...]\n"), program_invocation_short_name);
140
" -t, --terminal TERMINAL override the TERM environment variable\n"
141
" -i, --indicated underlining is indicated via a separate line\n"
142
" -V, --version output version information and exit\n"
143
" -h, --help display this help and exit\n\n"));
145
exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
120
148
int main(int argc, char **argv)
150
int c, ret, tflag = 0;
154
static const struct option longopts[] = {
155
{ "terminal", required_argument, 0, 't' },
156
{ "indicated", no_argument, 0, 'i' },
157
{ "version", no_argument, 0, 'V' },
158
{ "help", no_argument, 0, 'h' },
126
162
setlocale(LC_ALL, "");
127
163
bindtextdomain(PACKAGE, LOCALEDIR);
128
164
textdomain(PACKAGE);
131
167
signal(SIGTERM, sig_handler);
133
169
termtype = getenv("TERM");
134
if (termtype == NULL || (argv[0][0] == 'c' && !isatty(1)))
172
* FIXME: why terminal type is lpr when command begins with c and has
173
* no terminal? If this behavior can be explained please insert
174
* refrence or remove the code. In case this truly is desired command
175
* behavior this should be mentioned in manual page.
177
if (termtype == NULL || (argv[0][0] == 'c' && !isatty(STDOUT_FILENO)))
135
178
termtype = "lpr";
136
while ((c = getopt(argc, argv, "it:T:")) != -1)
180
while ((c = getopt_long(argc, argv, "it:T:Vh", longopts, NULL)) != -1)
140
case 'T': /* for nroff compatibility */
185
/* for nroff compatibility */
193
printf(_("%s from %s\n"), program_invocation_short_name,
149
_("Usage: %s [ -i ] [ -tTerm ] file...\n"),
150
program_invocation_short_name);
153
setupterm(termtype, 1, &ret);
201
setupterm(termtype, STDOUT_FILENO, &ret);
161
209
/* fall through to ... */
164
/* No such terminal type - assume dumb */
165
setupterm("dumb", 1, (int *)0);
213
warnx(_("terminal `%s' is not known, defaulting to `dumb'"),
215
setupterm("dumb", STDOUT_FILENO, (int *)0);
169
if ( (tigetflag("os") && ENTER_BOLD==NULL ) ||
170
(tigetflag("ul") && ENTER_UNDERLINE==NULL && UNDER_CHAR==NULL))
219
if ((tigetflag("os") && ENTER_BOLD==NULL ) ||
220
(tigetflag("ul") && ENTER_UNDERLINE==NULL && UNDER_CHAR==NULL))
173
223
if (optind == argc)
175
else for (; optind<argc; optind++) {
176
f = fopen(argv[optind],"r");
178
err(EXIT_FAILURE, _("%s: open failed"), argv[optind]);
226
for (; optind < argc; optind++) {
227
f = fopen(argv[optind],"r");
229
err(EXIT_FAILURE, _("%s: open failed"),
181
234
if (ferror(stdout) || fclose(stdout))
182
235
return EXIT_FAILURE;
184
238
return EXIT_SUCCESS;
241
static int handle_escape(FILE * f)
245
switch (c = getwc(f)) {
250
} else if (halfpos > 0) {
262
} else if (halfpos < 0) {
280
static void filter(FILE *f)
192
while ((c = getwc(f)) != WEOF) switch(c) {
285
while ((c = getwc(f)) != WEOF)
353
416
* For terminals that can overstrike, overstrike underlines and bolds.
354
417
* We don't do anything with halfline ups and downs, or Greek.
356
void overstrike(void)
419
static void overstrike(void)
360
register wchar_t *lbuf = __builtin_alloca((maxcol+1)*sizeof(wchar_t));
423
register wchar_t *lbuf = __builtin_alloca((maxcol + 1) * sizeof(wchar_t));
425
wchar_t lbuf[BUFSIZ];
364
427
register wchar_t *cp = lbuf;
367
430
/* Set up overstrike buffer */
368
for (i=0; i<maxcol; i++)
431
for (i = 0; i < maxcol; i++)
369
432
switch (obuf[i].c_mode) {
385
for (*cp=' '; *cp==' '; cp--)
448
for (*cp = ' '; *cp == ' '; cp--)
387
for (cp=lbuf; *cp; cp++)
450
for (cp = lbuf; *cp; cp++)
391
for (cp=lbuf; *cp; cp++)
392
putwchar(*cp=='_' ? ' ' : *cp);
454
for (cp = lbuf; *cp; cp++)
455
putwchar(*cp == '_' ? ' ' : *cp);
394
for (cp=lbuf; *cp; cp++)
395
putwchar(*cp=='_' ? ' ' : *cp);
457
for (cp = lbuf; *cp; cp++)
458
putwchar(*cp == '_' ? ' ' : *cp);
462
static void iattr(void)
403
466
register char *lbuf = __builtin_alloca((maxcol+1)*sizeof(char));
407
470
register char *cp = lbuf;
409
for (i=0; i<maxcol; i++)
472
for (i = 0; i < maxcol; i++)
410
473
switch (obuf[i].c_mode) {
411
474
case NORMAL: *cp++ = ' '; break;
412
475
case ALTSET: *cp++ = 'g'; break;
416
479
case BOLD: *cp++ = '!'; break;
417
480
default: *cp++ = 'X'; break;
419
for (*cp=' '; *cp==' '; cp--)
482
for (*cp = ' '; *cp == ' '; cp--)
421
for (cp=lbuf; *cp; cp++)
484
for (cp = lbuf; *cp; cp++)
489
static void initbuf(void)
428
if (obuf == NULL) { /* First time. */
430
494
obuf = xmalloc(sizeof(struct CHAR) * obuflen);
504
568
static int curmode = 0;
507
outc(wint_t c, int width) {
570
static void outc(wint_t c, int width) {
511
574
if (must_use_uc && (curmode&UNDERL)) {
512
for (i=0; i<width; i++)
514
for (i=0; i<width; i++)
575
for (i = 0; i < width; i++)
576
print_out(CURS_LEFT);
577
for (i = 0; i < width; i++)
578
print_out(UNDER_CHAR);
519
void setmode(int newmode)
582
static void setmode(int newmode)
522
585
if (curmode != NORMAL && newmode != NORMAL)
524
587
switch (newmode) {
530
PRINT(EXIT_UNDERLINE);
593
print_out(EXIT_UNDERLINE);
533
596
/* This includes standout */
534
PRINT(EXIT_ATTRIBUTES);
597
print_out(EXIT_ATTRIBUTES);
539
PRINT(ENTER_REVERSE);
602
print_out(ENTER_REVERSE);
543
606
* This only works on a few terminals.
544
607
* It should be fixed.
546
PRINT(ENTER_UNDERLINE);
609
print_out(ENTER_UNDERLINE);
610
print_out(ENTER_DIM);
613
print_out(ENTER_DIM);
553
PRINT(ENTER_UNDERLINE);
616
print_out(ENTER_UNDERLINE);
619
print_out(ENTER_BOLD);
560
623
* We should have some provision here for multiple modes
561
624
* on at once. This will have to come later.
563
PRINT(ENTER_STANDOUT);
626
print_out(ENTER_STANDOUT);
567
630
curmode = newmode;
633
static void setcol(int newcol) {
588
649
errx(EXIT_FAILURE, _("Input line too long."));
590
651
/* Similar paranoia: double only up to INT_MAX. */
591
obuflen = ((INT_MAX / 2) < obuflen)
652
if (obuflen < (INT_MAX / 2))
595
657
/* Now we can try to expand obuf. */
596
658
obuf = xrealloc(obuf, sizeof(struct CHAR) * obuflen);
600
static void sig_handler(int signo)
662
static void sig_handler(int signo __attribute__ ((__unused__)))
602
664
_exit(EXIT_SUCCESS);
667
static void print_out(char *line)