Add support for multibyte characters, based on Bruno Haible's work

in the util-linux package.
This commit is contained in:
Tim J. Robbins 2004-07-29 22:51:54 +00:00
parent dfa9c64b20
commit e5afeeb3be
2 changed files with 81 additions and 56 deletions

View File

@ -32,7 +32,7 @@
.\" @(#)ul.1 8.1 (Berkeley) 6/6/93
.\" $FreeBSD$
.\"
.Dd July 16, 2004
.Dd July 30, 2004
.Dt UL 1
.Os
.Sh NAME
@ -76,23 +76,14 @@ Overrides the terminal type specified in the environment with
.Ar terminal .
.El
.Sh ENVIRONMENT
The following environment variable is used:
.Bl -tag -width TERM
.It Ev TERM
The
.Ev LANG , LC_ALL , LC_CTYPE
and
.Ev TERM
variable is used to relate a tty device
with its device capability description (see
.Xr termcap 5 ) .
.Ev TERM
is set at login time, either by the default terminal type
specified in
.Pa /etc/ttys
or as set during the login process by the user in their
.Pa login
file (see
.Xr environ 7 ) .
.El
environment variables affect the execution of
.Nm
as described in
.Xr environ 7 .
.Sh SEE ALSO
.Xr colcrt 1 ,
.Xr man 1 ,
@ -104,8 +95,6 @@ command usually outputs a series of backspaces and underlines intermixed
with the text to indicate underlining.
No attempt is made to optimize
the backward motion.
.Pp
Multibyte characters are not recognized.
.Sh HISTORY
The
.Nm

View File

@ -46,11 +46,14 @@ static const char rcsid[] =
#endif /* not lint */
#include <err.h>
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <termcap.h>
#include <unistd.h>
#include <wchar.h>
#include <wctype.h>
#define IESC '\033'
#define SO '\016'
@ -75,7 +78,8 @@ const char
struct CHAR {
char c_mode;
char c_char;
wchar_t c_char;
int c_width; /* width or -1 if multi-column char. filler */
} ;
struct CHAR obuf[MAXBUF];
@ -96,7 +100,7 @@ void iattr(void);
void overstrike(void);
void flushln(void);
void filter(FILE *);
void outc(int);
void outc(wint_t, int);
#define PRINT(s) if (s == NULL) /* void */; else tputs(s, 1, outchar)
@ -108,6 +112,8 @@ main(int argc, char **argv)
FILE *f;
char termcap[1024];
setlocale(LC_ALL, "");
termtype = getenv("TERM");
if (termtype == NULL || (argv[0][0] == 'c' && !isatty(1)))
termtype = "lpr";
@ -166,9 +172,10 @@ usage(void)
void
filter(FILE *f)
{
int c;
wint_t c;
int i, w;
while ((c = getc(f)) != EOF && col < MAXBUF) switch(c) {
while ((c = getwc(f)) != WEOF && col < MAXBUF) switch(c) {
case '\b':
if (col > 0)
@ -194,7 +201,7 @@ filter(FILE *f)
continue;
case IESC:
switch (c = getc(f)) {
switch (c = getwc(f)) {
case HREV:
if (halfpos == 0) {
@ -232,10 +239,19 @@ filter(FILE *f)
continue;
case '_':
if (obuf[col].c_char)
obuf[col].c_mode |= UNDERL | mode;
else
obuf[col].c_char = '_';
if (obuf[col].c_char || obuf[col].c_width < 0) {
while (col > 0 && obuf[col].c_width < 0)
col--;
w = obuf[col].c_width;
for (i = 0; i < w; i++)
obuf[col++].c_mode |= UNDERL | mode;
if (col > maxcol)
maxcol = col;
continue;
}
obuf[col].c_char = '_';
obuf[col].c_width = 1;
/* FALLTHROUGH */
case ' ':
col++;
if (col > maxcol)
@ -248,23 +264,35 @@ filter(FILE *f)
case '\f':
flushln();
putchar('\f');
putwchar('\f');
continue;
default:
if (c < ' ') /* non printing */
if ((w = wcwidth(c)) <= 0) /* non printing */
continue;
if (obuf[col].c_char == '\0') {
obuf[col].c_char = c;
obuf[col].c_mode = mode;
for (i = 0; i < w; i++)
obuf[col + i].c_mode = mode;
obuf[col].c_width = w;
for (i = 1; i < w; i++)
obuf[col + i].c_width = -1;
} else if (obuf[col].c_char == '_') {
obuf[col].c_char = c;
obuf[col].c_mode |= UNDERL|mode;
} else if (obuf[col].c_char == c)
obuf[col].c_mode |= BOLD|mode;
else
obuf[col].c_mode = mode;
col++;
for (i = 0; i < w; i++)
obuf[col + i].c_mode |= UNDERL|mode;
obuf[col].c_width = w;
for (i = 1; i < w; i++)
obuf[col + i].c_width = -1;
} else if (obuf[col].c_char == c) {
for (i = 0; i < w; i++)
obuf[col + i].c_mode |= BOLD|mode;
} else {
w = obuf[col].c_width;
for (i = 0; i < w; i++)
obuf[col + i].c_mode = mode;
}
col += w;
if (col > maxcol)
maxcol = col;
continue;
@ -291,16 +319,18 @@ flushln(void)
if (upln)
PRINT(CURS_RIGHT);
else
outc(' ');
outc(' ', 1);
} else
outc(obuf[i].c_char);
outc(obuf[i].c_char, obuf[i].c_width);
if (obuf[i].c_width > 1)
i += obuf[i].c_width - 1;
}
if (lastmode != NORMAL) {
setnewmode(0);
}
if (must_overstrike && hadmodes)
overstrike();
putchar('\n');
putwchar('\n');
if (iflag && hadmodes)
iattr();
(void)fflush(stdout);
@ -317,8 +347,8 @@ void
overstrike(void)
{
int i;
char lbuf[256];
char *cp = lbuf;
wchar_t lbuf[256];
wchar_t *cp = lbuf;
int hadbold=0;
/* Set up overstrike buffer */
@ -333,21 +363,23 @@ overstrike(void)
break;
case BOLD:
*cp++ = obuf[i].c_char;
if (obuf[i].c_width > 1)
i += obuf[i].c_width - 1;
hadbold=1;
break;
}
putchar('\r');
putwchar('\r');
for (*cp=' '; *cp==' '; cp--)
*cp = 0;
for (cp=lbuf; *cp; cp++)
putchar(*cp);
putwchar(*cp);
if (hadbold) {
putchar('\r');
putwchar('\r');
for (cp=lbuf; *cp; cp++)
putchar(*cp=='_' ? ' ' : *cp);
putchar('\r');
putwchar(*cp=='_' ? ' ' : *cp);
putwchar('\r');
for (cp=lbuf; *cp; cp++)
putchar(*cp=='_' ? ' ' : *cp);
putwchar(*cp=='_' ? ' ' : *cp);
}
}
@ -355,8 +387,8 @@ void
iattr(void)
{
int i;
char lbuf[256];
char *cp = lbuf;
wchar_t lbuf[256];
wchar_t *cp = lbuf;
for (i=0; i<maxcol; i++)
switch (obuf[i].c_mode) {
@ -371,8 +403,8 @@ iattr(void)
for (*cp=' '; *cp==' '; cp--)
*cp = 0;
for (cp=lbuf; *cp; cp++)
putchar(*cp);
putchar('\n');
putwchar(*cp);
putwchar('\n');
}
void
@ -463,18 +495,22 @@ initcap(void)
int
outchar(int c)
{
return(putchar(c & 0177));
return (putwchar(c) != WEOF ? c : EOF);
}
static int curmode = 0;
void
outc(int c)
outc(wint_t c, int width)
{
putchar(c);
int i;
putwchar(c);
if (must_use_uc && (curmode&UNDERL)) {
PRINT(CURS_LEFT);
PRINT(UNDER_CHAR);
for (i = 0; i < width; i++)
PRINT(CURS_LEFT);
for (i = 0; i < width; i++)
PRINT(UNDER_CHAR);
}
}