From 8f98fb5ce46c27ede2c5589a2a63fb7cb602cc8f Mon Sep 17 00:00:00 2001 From: Sascha Wildner Date: Mon, 30 Dec 2013 22:10:28 +0100 Subject: [PATCH] ul(1): Sync with FreeBSD (mainly for multibyte char support). --- usr.bin/ul/Makefile | 3 +- usr.bin/ul/ul.1 | 41 +++++----- usr.bin/ul/ul.c | 182 ++++++++++++++++++++++++++------------------ 3 files changed, 130 insertions(+), 96 deletions(-) diff --git a/usr.bin/ul/Makefile b/usr.bin/ul/Makefile index a65225d161..e9b89617f9 100644 --- a/usr.bin/ul/Makefile +++ b/usr.bin/ul/Makefile @@ -1,7 +1,8 @@ # @(#)Makefile 8.1 (Berkeley) 6/6/93 -# $DragonFly: src/usr.bin/ul/Makefile,v 1.3 2007/08/27 16:51:00 pavalos Exp $ +# $FreeBSD: head/usr.bin/ul/Makefile 87700 2001-12-11 23:27:23Z markm $ PROG= ul + DPADD= ${LIBTERMCAP} LDADD= -ltermcap diff --git a/usr.bin/ul/ul.1 b/usr.bin/ul/ul.1 index 8591b2e38d..6548093706 100644 --- a/usr.bin/ul/ul.1 +++ b/usr.bin/ul/ul.1 @@ -26,10 +26,9 @@ .\" SUCH DAMAGE. .\" .\" @(#)ul.1 8.1 (Berkeley) 6/6/93 -.\" $FreeBSD: src/usr.bin/ul/ul.1,v 1.6.2.4 2002/06/21 15:29:52 charnier Exp $ -.\" $DragonFly: src/usr.bin/ul/ul.1,v 1.4 2006/04/17 18:01:38 swildner Exp $ +.\" $FreeBSD: head/usr.bin/ul/ul.1 216370 2010-12-11 08:32:16Z joel $ .\" -.Dd June 6, 1993 +.Dd December 30, 2013 .Dt UL 1 .Os .Sh NAME @@ -39,7 +38,7 @@ .Nm .Op Fl i .Op Fl t Ar terminal -.Op Ar name Ar ... +.Op Ar .Sh DESCRIPTION The .Nm @@ -61,35 +60,30 @@ degenerates to If the terminal cannot underline, underlining is ignored. .Pp The following options are available: -.Bl -tag -width Ds +.Bl -tag -width indent .It Fl i Underlining is indicated by a separate line containing appropriate -dashes `\-'; this is useful when you want to look at the underlining +dashes +.Ql \- ; +this is useful when you want to look at the underlining which is present in an .Xr nroff 1 -output stream on a crt-terminal. +output stream on a CRT-terminal. .It Fl t Ar terminal 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 EXIT STATUS +.Ex -std .Sh SEE ALSO .Xr colcrt 1 , .Xr man 1 , @@ -103,5 +97,6 @@ command appeared in The .Xr nroff 1 command usually outputs a series of backspaces and underlines intermixed -with the text to indicate underlining. No attempt is made to optimize +with the text to indicate underlining. +No attempt is made to optimize the backward motion. diff --git a/usr.bin/ul/ul.c b/usr.bin/ul/ul.c index 6581051675..07e710bdba 100644 --- a/usr.bin/ul/ul.c +++ b/usr.bin/ul/ul.c @@ -28,16 +28,18 @@ * * @(#) Copyright (c) 1980, 1993 The Regents of the University of California. All rights reserved. * @(#)ul.c 8.1 (Berkeley) 6/6/93 - * $FreeBSD: src/usr.bin/ul/ul.c,v 1.6.2.1 2000/08/23 08:49:49 kris Exp $ - * $DragonFly: src/usr.bin/ul/ul.c,v 1.4 2005/01/05 02:40:23 cpressey Exp $ + * FreeBSD: head/usr.bin/ul/ul.c 245093 2013-01-06 03:08:27Z andrew $ */ #include +#include #include #include #include #include #include +#include +#include #define IESC '\033' #define SO '\016' @@ -54,35 +56,37 @@ #define UNDERL 010 /* Ul */ #define BOLD 020 /* Bold */ -int must_use_uc, must_overstrike; -const char *CURS_UP, *CURS_RIGHT, *CURS_LEFT, +static int must_use_uc, must_overstrike; +static const char + *CURS_UP, *CURS_RIGHT, *CURS_LEFT, *ENTER_STANDOUT, *EXIT_STANDOUT, *ENTER_UNDERLINE, *EXIT_UNDERLINE, *ENTER_DIM, *ENTER_BOLD, *ENTER_REVERSE, *UNDER_CHAR, *EXIT_ATTRIBUTES; 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]; -int col, maxcol; -int mode; -int halfpos; -int upln; -int iflag; +static struct CHAR obuf[MAXBUF]; +static int col, maxcol; +static int mode; +static int halfpos; +static int upln; +static int iflag; static void usage(void); -void setnewmode(int); -void initcap(void); -void reverse(void); -int outchar(int); -void fwd(void); -void initbuf(void); -void iattr(void); -void overstrike(void); -void flushln(void); -void filter(FILE *); -void outc(int); +static void setnewmode(int); +static void initcap(void); +static void reverse(void); +static int outchar(int); +static void fwd(void); +static void initbuf(void); +static void iattr(void); +static void overstrike(void); +static void flushln(void); +static void filter(FILE *); +static void outc(wint_t, int); #define PRINT(s) if (s == NULL) /* void */; else tputs(s, 1, outchar) @@ -94,6 +98,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"; @@ -102,7 +108,7 @@ main(int argc, char **argv) case 't': case 'T': /* for nroff compatibility */ - termtype = optarg; + termtype = optarg; break; case 'i': iflag = 1; @@ -118,7 +124,7 @@ main(int argc, char **argv) default: warnx("trouble reading termcap"); - /* fall through to ... */ + /* FALLTHROUGH */ case 0: /* No such terminal type - assume dumb */ @@ -145,16 +151,17 @@ main(int argc, char **argv) static void usage(void) { - fprintf(stderr, "usage: ul [-i] [-t terminal] file...\n"); + fprintf(stderr, "usage: ul [-i] [-t terminal] [file ...]\n"); exit(1); } -void +static 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) @@ -180,7 +187,7 @@ filter(FILE *f) continue; case IESC: - switch (c = getc(f)) { + switch (c = getwc(f)) { case HREV: if (halfpos == 0) { @@ -218,10 +225,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) @@ -234,32 +250,46 @@ 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 ((wint_t)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; } + if (ferror(f)) + err(1, NULL); if (maxcol) flushln(); } -void +static void flushln(void) { int lastmode; @@ -277,16 +307,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); @@ -299,12 +331,12 @@ flushln(void) * For terminals that can overstrike, overstrike underlines and bolds. * We don't do anything with halfline ups and downs, or Greek. */ -void +static 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 */ @@ -319,30 +351,32 @@ 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); } } -void +static void iattr(void) { int i; - char lbuf[256]; - char *cp = lbuf; + wchar_t lbuf[256]; + wchar_t *cp = lbuf; for (i=0; i