Index: usr.bin/ul/ul.c =================================================================== --- usr.bin/ul/ul.c (revision 301965) +++ usr.bin/ul/ul.c (working copy) @@ -1,561 +1,586 @@ /* * Copyright (c) 1980, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef lint static const char copyright[] = "@(#) Copyright (c) 1980, 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #ifndef lint #if 0 static char sccsid[] = "@(#)ul.c 8.1 (Berkeley) 6/6/93"; #endif static const char rcsid[] = "$FreeBSD$"; #endif /* not lint */ #include #include #include #include #include #include #include #include #include #define IESC '\033' #define SO '\016' #define SI '\017' #define HFWD '9' #define HREV '8' #define FREV '7' #define MAXBUF 512 #define NORMAL 000 #define ALTSET 001 /* Reverse */ #define SUPERSC 002 /* Dim */ #define SUBSC 004 /* Dim | Ul */ #define UNDERL 010 /* Ul */ #define BOLD 020 /* Bold */ 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; wchar_t c_char; int c_width; /* width or -1 if multi-column char. filler */ } ; -static struct CHAR obuf[MAXBUF]; +static struct CHAR sobuf[MAXBUF]; /* static output buffer */ +static struct CHAR *obuf = sobuf; +static int buflen = MAXBUF; static int col, maxcol; static int mode; static int halfpos; static int upln; static int iflag; static void usage(void); 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) int main(int argc, char **argv) { int c; const char *termtype; FILE *f; char termcap[1024]; setlocale(LC_ALL, ""); termtype = getenv("TERM"); if (termtype == NULL || (argv[0][0] == 'c' && !isatty(1))) termtype = "lpr"; while ((c = getopt(argc, argv, "it:T:")) != -1) switch (c) { case 't': case 'T': /* for nroff compatibility */ termtype = optarg; break; case 'i': iflag = 1; break; default: usage(); } switch (tgetent(termcap, termtype)) { case 1: break; default: warnx("trouble reading termcap"); /* FALLTHROUGH */ case 0: /* No such terminal type - assume dumb */ (void)strcpy(termcap, "dumb:os:col#80:cr=^M:sf=^J:am:"); break; } initcap(); if ((tgetflag("os") && ENTER_BOLD == NULL ) || (tgetflag("ul") && ENTER_UNDERLINE == NULL && UNDER_CHAR == NULL)) must_overstrike = 1; initbuf(); if (optind == argc) filter(stdin); else for (; optind 0) + col--; + continue; - case '\b': - if (col > 0) - col--; - continue; + case '\t': + col = (col+8) & ~07; + if (col > maxcol) + maxcol = col; + continue; - case '\t': - col = (col+8) & ~07; - if (col > maxcol) - maxcol = col; - continue; + case '\r': + col = 0; + continue; - case '\r': - col = 0; - continue; + case SO: + mode |= ALTSET; + continue; - case SO: - mode |= ALTSET; - continue; + case SI: + mode &= ~ALTSET; + continue; - case SI: - mode &= ~ALTSET; - continue; + case IESC: + switch (c = getwc(f)) { - case IESC: - switch (c = getwc(f)) { + case HREV: + if (halfpos == 0) { + mode |= SUPERSC; + halfpos--; + } else if (halfpos > 0) { + mode &= ~SUBSC; + halfpos--; + } else { + halfpos = 0; + reverse(); + } + continue; - case HREV: - if (halfpos == 0) { - mode |= SUPERSC; - halfpos--; - } else if (halfpos > 0) { - mode &= ~SUBSC; - halfpos--; - } else { - halfpos = 0; + case HFWD: + if (halfpos == 0) { + mode |= SUBSC; + halfpos++; + } else if (halfpos < 0) { + mode &= ~SUPERSC; + halfpos++; + } else { + halfpos = 0; + fwd(); + } + continue; + + case FREV: reverse(); + continue; + + default: + errx(1, "unknown escape sequence in input: %o, %o", IESC, c); } continue; - case HFWD: - if (halfpos == 0) { - mode |= SUBSC; - halfpos++; - } else if (halfpos < 0) { - mode &= ~SUPERSC; - halfpos++; - } else { - halfpos = 0; - fwd(); + case '_': + 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) + maxcol = col; continue; - case FREV: - reverse(); + case '\n': + flushln(); continue; + case '\f': + flushln(); + putwchar('\f'); + continue; + default: - errx(1, "unknown escape sequence in input: %o, %o", IESC, c); - } - continue; - - case '_': - 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 ((w = wcwidth(c)) <= 0) /* non printing */ + continue; + if (obuf[col].c_char == '\0') { + obuf[col].c_char = c; + 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; + 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; } - obuf[col].c_char = '_'; - obuf[col].c_width = 1; - /* FALLTHROUGH */ - case ' ': - col++; - if (col > maxcol) - maxcol = col; - continue; - - case '\n': - flushln(); - continue; - - case '\f': - flushln(); - putwchar('\f'); - continue; - - default: - if ((w = wcwidth(c)) <= 0) /* non printing */ - continue; - if (obuf[col].c_char == '\0') { - obuf[col].c_char = c; - 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; - 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(); } static void flushln(void) { int lastmode; int i; int hadmodes = 0; lastmode = NORMAL; for (i = 0; i < maxcol; i++) { if (obuf[i].c_mode != lastmode) { hadmodes++; setnewmode(obuf[i].c_mode); lastmode = obuf[i].c_mode; } if (obuf[i].c_char == '\0') { if (upln) PRINT(CURS_RIGHT); else outc(' ', 1); } else 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(); putwchar('\n'); if (iflag && hadmodes) iattr(); (void)fflush(stdout); if (upln) upln--; initbuf(); } /* * For terminals that can overstrike, overstrike underlines and bolds. * We don't do anything with halfline ups and downs, or Greek. */ static void overstrike(void) { int i; wchar_t lbuf[256]; wchar_t *cp = lbuf; int hadbold=0; /* Set up overstrike buffer */ for (i=0; i 1) i += obuf[i].c_width - 1; hadbold=1; break; } putwchar('\r'); for (*cp=' '; *cp==' '; cp--) *cp = 0; for (cp=lbuf; *cp; cp++) putwchar(*cp); if (hadbold) { putwchar('\r'); for (cp=lbuf; *cp; cp++) putwchar(*cp=='_' ? ' ' : *cp); putwchar('\r'); for (cp=lbuf; *cp; cp++) putwchar(*cp=='_' ? ' ' : *cp); } } static void iattr(void) { int i; wchar_t lbuf[256]; wchar_t *cp = lbuf; for (i=0; i