11590Srgrimes/* 21590Srgrimes * Copyright (c) 1980, 1993 31590Srgrimes * The Regents of the University of California. All rights reserved. 41590Srgrimes * 51590Srgrimes * Redistribution and use in source and binary forms, with or without 61590Srgrimes * modification, are permitted provided that the following conditions 71590Srgrimes * are met: 81590Srgrimes * 1. Redistributions of source code must retain the above copyright 91590Srgrimes * notice, this list of conditions and the following disclaimer. 101590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111590Srgrimes * notice, this list of conditions and the following disclaimer in the 121590Srgrimes * documentation and/or other materials provided with the distribution. 131590Srgrimes * 4. Neither the name of the University nor the names of its contributors 141590Srgrimes * may be used to endorse or promote products derived from this software 151590Srgrimes * without specific prior written permission. 161590Srgrimes * 171590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 181590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 191590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 201590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 211590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 221590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 231590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 241590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 251590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 261590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 271590Srgrimes * SUCH DAMAGE. 281590Srgrimes */ 291590Srgrimes 301590Srgrimes#ifndef lint 3128454Scharnierstatic const char copyright[] = 321590Srgrimes"@(#) Copyright (c) 1980, 1993\n\ 331590Srgrimes The Regents of the University of California. All rights reserved.\n"; 341590Srgrimes#endif /* not lint */ 351590Srgrimes 361590Srgrimes#ifndef lint 3728454Scharnier#if 0 381590Srgrimesstatic char sccsid[] = "@(#)ul.c 8.1 (Berkeley) 6/6/93"; 3928454Scharnier#endif 4028454Scharnierstatic const char rcsid[] = 4150477Speter "$FreeBSD$"; 421590Srgrimes#endif /* not lint */ 431590Srgrimes 4428454Scharnier#include <err.h> 45132858Stjr#include <locale.h> 461590Srgrimes#include <stdio.h> 4728454Scharnier#include <stdlib.h> 4828454Scharnier#include <string.h> 4928454Scharnier#include <termcap.h> 5028454Scharnier#include <unistd.h> 51132858Stjr#include <wchar.h> 52200462Sdelphij#include <wctype.h> 531590Srgrimes 541590Srgrimes#define IESC '\033' 551590Srgrimes#define SO '\016' 561590Srgrimes#define SI '\017' 571590Srgrimes#define HFWD '9' 581590Srgrimes#define HREV '8' 591590Srgrimes#define FREV '7' 601590Srgrimes#define MAXBUF 512 611590Srgrimes 621590Srgrimes#define NORMAL 000 631590Srgrimes#define ALTSET 001 /* Reverse */ 641590Srgrimes#define SUPERSC 002 /* Dim */ 651590Srgrimes#define SUBSC 004 /* Dim | Ul */ 661590Srgrimes#define UNDERL 010 /* Ul */ 671590Srgrimes#define BOLD 020 /* Bold */ 681590Srgrimes 69227190Sedstatic int must_use_uc, must_overstrike; 70227190Sedstatic const char 7187303Sdwmalone *CURS_UP, *CURS_RIGHT, *CURS_LEFT, 721590Srgrimes *ENTER_STANDOUT, *EXIT_STANDOUT, *ENTER_UNDERLINE, *EXIT_UNDERLINE, 731590Srgrimes *ENTER_DIM, *ENTER_BOLD, *ENTER_REVERSE, *UNDER_CHAR, *EXIT_ATTRIBUTES; 741590Srgrimes 751590Srgrimesstruct CHAR { 761590Srgrimes char c_mode; 77132858Stjr wchar_t c_char; 78132858Stjr int c_width; /* width or -1 if multi-column char. filler */ 791590Srgrimes} ; 801590Srgrimes 81303075Sgahrstatic struct CHAR sobuf[MAXBUF]; /* static output buffer */ 82303075Sgahrstatic struct CHAR *obuf = sobuf; 83303075Sgahrstatic int buflen = MAXBUF; 84227190Sedstatic int col, maxcol; 85227190Sedstatic int mode; 86227190Sedstatic int halfpos; 87227190Sedstatic int upln; 88227190Sedstatic int iflag; 891590Srgrimes 9092922Simpstatic void usage(void); 91227190Sedstatic void setnewmode(int); 92227190Sedstatic void initcap(void); 93227190Sedstatic void reverse(void); 94227190Sedstatic int outchar(int); 95227190Sedstatic void fwd(void); 96227190Sedstatic void initbuf(void); 97227190Sedstatic void iattr(void); 98227190Sedstatic void overstrike(void); 99227190Sedstatic void flushln(void); 100227190Sedstatic void filter(FILE *); 101227190Sedstatic void outc(wint_t, int); 10228454Scharnier 1031590Srgrimes#define PRINT(s) if (s == NULL) /* void */; else tputs(s, 1, outchar) 1041590Srgrimes 10528789Scharnierint 106102944Sdwmalonemain(int argc, char **argv) 1071590Srgrimes{ 1081590Srgrimes int c; 10987303Sdwmalone const char *termtype; 1101590Srgrimes FILE *f; 1111590Srgrimes char termcap[1024]; 1121590Srgrimes 113132858Stjr setlocale(LC_ALL, ""); 114132858Stjr 1151590Srgrimes termtype = getenv("TERM"); 1161590Srgrimes if (termtype == NULL || (argv[0][0] == 'c' && !isatty(1))) 1171590Srgrimes termtype = "lpr"; 11824360Simp while ((c=getopt(argc, argv, "it:T:")) != -1) 1191590Srgrimes switch(c) { 1201590Srgrimes 1211590Srgrimes case 't': 1221590Srgrimes case 'T': /* for nroff compatibility */ 12387303Sdwmalone termtype = optarg; 1241590Srgrimes break; 1251590Srgrimes case 'i': 1261590Srgrimes iflag = 1; 1271590Srgrimes break; 1281590Srgrimes default: 12928454Scharnier usage(); 1301590Srgrimes } 1311590Srgrimes 1321590Srgrimes switch(tgetent(termcap, termtype)) { 1331590Srgrimes 1341590Srgrimes case 1: 1351590Srgrimes break; 1361590Srgrimes 1371590Srgrimes default: 13828454Scharnier warnx("trouble reading termcap"); 139102412Scharnier /* FALLTHROUGH */ 1401590Srgrimes 1411590Srgrimes case 0: 1421590Srgrimes /* No such terminal type - assume dumb */ 1431590Srgrimes (void)strcpy(termcap, "dumb:os:col#80:cr=^M:sf=^J:am:"); 1441590Srgrimes break; 1451590Srgrimes } 1461590Srgrimes initcap(); 1471590Srgrimes if ( (tgetflag("os") && ENTER_BOLD==NULL ) || 1481590Srgrimes (tgetflag("ul") && ENTER_UNDERLINE==NULL && UNDER_CHAR==NULL)) 1491590Srgrimes must_overstrike = 1; 1501590Srgrimes initbuf(); 1511590Srgrimes if (optind == argc) 1521590Srgrimes filter(stdin); 1531590Srgrimes else for (; optind<argc; optind++) { 1541590Srgrimes f = fopen(argv[optind],"r"); 15528454Scharnier if (f == NULL) 15628454Scharnier err(1, "%s", argv[optind]); 15728454Scharnier else 1581590Srgrimes filter(f); 1591590Srgrimes } 160303075Sgahr if (obuf != sobuf) { 161303075Sgahr free(obuf); 162303075Sgahr } 1631590Srgrimes exit(0); 1641590Srgrimes} 1651590Srgrimes 16628454Scharnierstatic void 167102944Sdwmaloneusage(void) 16828454Scharnier{ 169146466Sru fprintf(stderr, "usage: ul [-i] [-t terminal] [file ...]\n"); 17028454Scharnier exit(1); 17128454Scharnier} 17228454Scharnier 173227190Sedstatic void 174102944Sdwmalonefilter(FILE *f) 1751590Srgrimes{ 176132858Stjr wint_t c; 177132858Stjr int i, w; 178303075Sgahr int copy; 179303075Sgahr 180303075Sgahr copy = 0; 1811590Srgrimes 182303075Sgahr while ((c = getwc(f)) != WEOF) { 183303075Sgahr if (col == buflen) { 184303075Sgahr if (obuf == sobuf) { 185303075Sgahr obuf = NULL; 186303075Sgahr copy = 1; 187303075Sgahr } 188303075Sgahr obuf = realloc(obuf, sizeof(*obuf) * 2 * buflen); 189303075Sgahr if (obuf == NULL) { 190303075Sgahr obuf = sobuf; 191303075Sgahr break; 192303075Sgahr } else if (copy) { 193303075Sgahr memcpy(obuf, sobuf, sizeof(*obuf) * buflen); 194303075Sgahr copy = 0; 195303075Sgahr } 196303075Sgahr bzero((char *)(obuf + buflen), sizeof(*obuf) * buflen); 197303075Sgahr buflen *= 2; 198303075Sgahr } 199303075Sgahr switch(c) { 200303075Sgahr case '\b': 201303075Sgahr if (col > 0) 202303075Sgahr col--; 203303075Sgahr continue; 2041590Srgrimes 205303075Sgahr case '\t': 206303075Sgahr col = (col+8) & ~07; 207303075Sgahr if (col > maxcol) 208303075Sgahr maxcol = col; 209303075Sgahr continue; 2101590Srgrimes 211303075Sgahr case '\r': 212303075Sgahr col = 0; 213303075Sgahr continue; 2141590Srgrimes 215303075Sgahr case SO: 216303075Sgahr mode |= ALTSET; 217303075Sgahr continue; 2181590Srgrimes 219303075Sgahr case SI: 220303075Sgahr mode &= ~ALTSET; 221303075Sgahr continue; 2221590Srgrimes 223303075Sgahr case IESC: 224303075Sgahr switch (c = getwc(f)) { 2251590Srgrimes 226303075Sgahr case HREV: 227303075Sgahr if (halfpos == 0) { 228303075Sgahr mode |= SUPERSC; 229303075Sgahr halfpos--; 230303075Sgahr } else if (halfpos > 0) { 231303075Sgahr mode &= ~SUBSC; 232303075Sgahr halfpos--; 233303075Sgahr } else { 234303075Sgahr halfpos = 0; 235303075Sgahr reverse(); 236303075Sgahr } 237303075Sgahr continue; 2381590Srgrimes 239303075Sgahr case HFWD: 240303075Sgahr if (halfpos == 0) { 241303075Sgahr mode |= SUBSC; 242303075Sgahr halfpos++; 243303075Sgahr } else if (halfpos < 0) { 244303075Sgahr mode &= ~SUPERSC; 245303075Sgahr halfpos++; 246303075Sgahr } else { 247303075Sgahr halfpos = 0; 248303075Sgahr fwd(); 249303075Sgahr } 250303075Sgahr continue; 251303075Sgahr 252303075Sgahr case FREV: 2531590Srgrimes reverse(); 254303075Sgahr continue; 255303075Sgahr 256303075Sgahr default: 257303075Sgahr errx(1, "unknown escape sequence in input: %o, %o", IESC, c); 2581590Srgrimes } 2591590Srgrimes continue; 2601590Srgrimes 261303075Sgahr case '_': 262303075Sgahr if (obuf[col].c_char || obuf[col].c_width < 0) { 263303075Sgahr while (col > 0 && obuf[col].c_width < 0) 264303075Sgahr col--; 265303075Sgahr w = obuf[col].c_width; 266303075Sgahr for (i = 0; i < w; i++) 267303075Sgahr obuf[col++].c_mode |= UNDERL | mode; 268303075Sgahr if (col > maxcol) 269303075Sgahr maxcol = col; 270303075Sgahr continue; 2711590Srgrimes } 272303075Sgahr obuf[col].c_char = '_'; 273303075Sgahr obuf[col].c_width = 1; 274303075Sgahr /* FALLTHROUGH */ 275303075Sgahr case ' ': 276303075Sgahr col++; 277303075Sgahr if (col > maxcol) 278303075Sgahr maxcol = col; 2791590Srgrimes continue; 2801590Srgrimes 281303075Sgahr case '\n': 282303075Sgahr flushln(); 2831590Srgrimes continue; 2841590Srgrimes 285303075Sgahr case '\f': 286303075Sgahr flushln(); 287303075Sgahr putwchar('\f'); 288303075Sgahr continue; 289303075Sgahr 2901590Srgrimes default: 291303075Sgahr if ((w = wcwidth(c)) <= 0) /* non printing */ 292303075Sgahr continue; 293303075Sgahr if (obuf[col].c_char == '\0') { 294303075Sgahr obuf[col].c_char = c; 295303075Sgahr for (i = 0; i < w; i++) 296303075Sgahr obuf[col + i].c_mode = mode; 297303075Sgahr obuf[col].c_width = w; 298303075Sgahr for (i = 1; i < w; i++) 299303075Sgahr obuf[col + i].c_width = -1; 300303075Sgahr } else if (obuf[col].c_char == '_') { 301303075Sgahr obuf[col].c_char = c; 302303075Sgahr for (i = 0; i < w; i++) 303303075Sgahr obuf[col + i].c_mode |= UNDERL|mode; 304303075Sgahr obuf[col].c_width = w; 305303075Sgahr for (i = 1; i < w; i++) 306303075Sgahr obuf[col + i].c_width = -1; 307303075Sgahr } else if ((wint_t)obuf[col].c_char == c) { 308303075Sgahr for (i = 0; i < w; i++) 309303075Sgahr obuf[col + i].c_mode |= BOLD|mode; 310303075Sgahr } else { 311303075Sgahr w = obuf[col].c_width; 312303075Sgahr for (i = 0; i < w; i++) 313303075Sgahr obuf[col + i].c_mode = mode; 314303075Sgahr } 315303075Sgahr col += w; 316132858Stjr if (col > maxcol) 317132858Stjr maxcol = col; 318132858Stjr continue; 319132858Stjr } 3201590Srgrimes } 321132882Stjr if (ferror(f)) 322132882Stjr err(1, NULL); 3231590Srgrimes if (maxcol) 3241590Srgrimes flushln(); 3251590Srgrimes} 3261590Srgrimes 327227190Sedstatic void 328102944Sdwmaloneflushln(void) 3291590Srgrimes{ 33087303Sdwmalone int lastmode; 33187303Sdwmalone int i; 3321590Srgrimes int hadmodes = 0; 3331590Srgrimes 3341590Srgrimes lastmode = NORMAL; 3351590Srgrimes for (i=0; i<maxcol; i++) { 3361590Srgrimes if (obuf[i].c_mode != lastmode) { 3371590Srgrimes hadmodes++; 33828454Scharnier setnewmode(obuf[i].c_mode); 3391590Srgrimes lastmode = obuf[i].c_mode; 3401590Srgrimes } 3411590Srgrimes if (obuf[i].c_char == '\0') { 3421590Srgrimes if (upln) 3431590Srgrimes PRINT(CURS_RIGHT); 3441590Srgrimes else 345132858Stjr outc(' ', 1); 3461590Srgrimes } else 347132858Stjr outc(obuf[i].c_char, obuf[i].c_width); 348132858Stjr if (obuf[i].c_width > 1) 349132858Stjr i += obuf[i].c_width - 1; 3501590Srgrimes } 3511590Srgrimes if (lastmode != NORMAL) { 35228454Scharnier setnewmode(0); 3531590Srgrimes } 3541590Srgrimes if (must_overstrike && hadmodes) 3551590Srgrimes overstrike(); 356132858Stjr putwchar('\n'); 3571590Srgrimes if (iflag && hadmodes) 3581590Srgrimes iattr(); 3591590Srgrimes (void)fflush(stdout); 3601590Srgrimes if (upln) 3611590Srgrimes upln--; 3621590Srgrimes initbuf(); 3631590Srgrimes} 3641590Srgrimes 3651590Srgrimes/* 3661590Srgrimes * For terminals that can overstrike, overstrike underlines and bolds. 3671590Srgrimes * We don't do anything with halfline ups and downs, or Greek. 3681590Srgrimes */ 369227190Sedstatic void 370102944Sdwmaloneoverstrike(void) 3711590Srgrimes{ 372102944Sdwmalone int i; 373132858Stjr wchar_t lbuf[256]; 374132858Stjr wchar_t *cp = lbuf; 3751590Srgrimes int hadbold=0; 3761590Srgrimes 3771590Srgrimes /* Set up overstrike buffer */ 3781590Srgrimes for (i=0; i<maxcol; i++) 3791590Srgrimes switch (obuf[i].c_mode) { 3801590Srgrimes case NORMAL: 3811590Srgrimes default: 3821590Srgrimes *cp++ = ' '; 3831590Srgrimes break; 3841590Srgrimes case UNDERL: 3851590Srgrimes *cp++ = '_'; 3861590Srgrimes break; 3871590Srgrimes case BOLD: 3881590Srgrimes *cp++ = obuf[i].c_char; 389132858Stjr if (obuf[i].c_width > 1) 390132858Stjr i += obuf[i].c_width - 1; 3911590Srgrimes hadbold=1; 3921590Srgrimes break; 3931590Srgrimes } 394132858Stjr putwchar('\r'); 3951590Srgrimes for (*cp=' '; *cp==' '; cp--) 3961590Srgrimes *cp = 0; 3971590Srgrimes for (cp=lbuf; *cp; cp++) 398132858Stjr putwchar(*cp); 3991590Srgrimes if (hadbold) { 400132858Stjr putwchar('\r'); 4011590Srgrimes for (cp=lbuf; *cp; cp++) 402132858Stjr putwchar(*cp=='_' ? ' ' : *cp); 403132858Stjr putwchar('\r'); 4041590Srgrimes for (cp=lbuf; *cp; cp++) 405132858Stjr putwchar(*cp=='_' ? ' ' : *cp); 4061590Srgrimes } 4071590Srgrimes} 4081590Srgrimes 409227190Sedstatic void 410102944Sdwmaloneiattr(void) 4111590Srgrimes{ 412102944Sdwmalone int i; 413132858Stjr wchar_t lbuf[256]; 414132858Stjr wchar_t *cp = lbuf; 4151590Srgrimes 4161590Srgrimes for (i=0; i<maxcol; i++) 4171590Srgrimes switch (obuf[i].c_mode) { 4181590Srgrimes case NORMAL: *cp++ = ' '; break; 4191590Srgrimes case ALTSET: *cp++ = 'g'; break; 4201590Srgrimes case SUPERSC: *cp++ = '^'; break; 4211590Srgrimes case SUBSC: *cp++ = 'v'; break; 4221590Srgrimes case UNDERL: *cp++ = '_'; break; 4231590Srgrimes case BOLD: *cp++ = '!'; break; 4241590Srgrimes default: *cp++ = 'X'; break; 4251590Srgrimes } 4261590Srgrimes for (*cp=' '; *cp==' '; cp--) 4271590Srgrimes *cp = 0; 4281590Srgrimes for (cp=lbuf; *cp; cp++) 429132858Stjr putwchar(*cp); 430132858Stjr putwchar('\n'); 4311590Srgrimes} 4321590Srgrimes 433227190Sedstatic void 434102944Sdwmaloneinitbuf(void) 4351590Srgrimes{ 4361590Srgrimes 437303075Sgahr bzero((char *)obuf, buflen * sizeof(*obuf)); /* depends on NORMAL == 0 */ 4381590Srgrimes col = 0; 4391590Srgrimes maxcol = 0; 4401590Srgrimes mode &= ALTSET; 4411590Srgrimes} 4421590Srgrimes 443227190Sedstatic void 444102944Sdwmalonefwd(void) 4451590Srgrimes{ 44687303Sdwmalone int oldcol, oldmax; 4471590Srgrimes 4481590Srgrimes oldcol = col; 4491590Srgrimes oldmax = maxcol; 4501590Srgrimes flushln(); 4511590Srgrimes col = oldcol; 4521590Srgrimes maxcol = oldmax; 4531590Srgrimes} 4541590Srgrimes 455227190Sedstatic void 456102944Sdwmalonereverse(void) 4571590Srgrimes{ 4581590Srgrimes upln++; 4591590Srgrimes fwd(); 4601590Srgrimes PRINT(CURS_UP); 4611590Srgrimes PRINT(CURS_UP); 4621590Srgrimes upln++; 4631590Srgrimes} 4641590Srgrimes 465227190Sedstatic void 466102944Sdwmaloneinitcap(void) 4671590Srgrimes{ 4681590Srgrimes static char tcapbuf[512]; 4691590Srgrimes char *bp = tcapbuf; 4701590Srgrimes 4711590Srgrimes /* This nonsense attempts to work with both old and new termcap */ 4721590Srgrimes CURS_UP = tgetstr("up", &bp); 4731590Srgrimes CURS_RIGHT = tgetstr("ri", &bp); 4741590Srgrimes if (CURS_RIGHT == NULL) 4751590Srgrimes CURS_RIGHT = tgetstr("nd", &bp); 4761590Srgrimes CURS_LEFT = tgetstr("le", &bp); 4771590Srgrimes if (CURS_LEFT == NULL) 4781590Srgrimes CURS_LEFT = tgetstr("bc", &bp); 4791590Srgrimes if (CURS_LEFT == NULL && tgetflag("bs")) 4801590Srgrimes CURS_LEFT = "\b"; 4811590Srgrimes 4821590Srgrimes ENTER_STANDOUT = tgetstr("so", &bp); 4831590Srgrimes EXIT_STANDOUT = tgetstr("se", &bp); 4841590Srgrimes ENTER_UNDERLINE = tgetstr("us", &bp); 4851590Srgrimes EXIT_UNDERLINE = tgetstr("ue", &bp); 4861590Srgrimes ENTER_DIM = tgetstr("mh", &bp); 4871590Srgrimes ENTER_BOLD = tgetstr("md", &bp); 4881590Srgrimes ENTER_REVERSE = tgetstr("mr", &bp); 4891590Srgrimes EXIT_ATTRIBUTES = tgetstr("me", &bp); 4901590Srgrimes 4911590Srgrimes if (!ENTER_BOLD && ENTER_REVERSE) 4921590Srgrimes ENTER_BOLD = ENTER_REVERSE; 4931590Srgrimes if (!ENTER_BOLD && ENTER_STANDOUT) 4941590Srgrimes ENTER_BOLD = ENTER_STANDOUT; 4951590Srgrimes if (!ENTER_UNDERLINE && ENTER_STANDOUT) { 4961590Srgrimes ENTER_UNDERLINE = ENTER_STANDOUT; 4971590Srgrimes EXIT_UNDERLINE = EXIT_STANDOUT; 4981590Srgrimes } 4991590Srgrimes if (!ENTER_DIM && ENTER_STANDOUT) 5001590Srgrimes ENTER_DIM = ENTER_STANDOUT; 5011590Srgrimes if (!ENTER_REVERSE && ENTER_STANDOUT) 5021590Srgrimes ENTER_REVERSE = ENTER_STANDOUT; 5031590Srgrimes if (!EXIT_ATTRIBUTES && EXIT_STANDOUT) 5041590Srgrimes EXIT_ATTRIBUTES = EXIT_STANDOUT; 5058874Srgrimes 5061590Srgrimes /* 5071590Srgrimes * Note that we use REVERSE for the alternate character set, 5081590Srgrimes * not the as/ae capabilities. This is because we are modelling 5091590Srgrimes * the model 37 teletype (since that's what nroff outputs) and 5101590Srgrimes * the typical as/ae is more of a graphics set, not the greek 5111590Srgrimes * letters the 37 has. 5121590Srgrimes */ 5131590Srgrimes 5141590Srgrimes UNDER_CHAR = tgetstr("uc", &bp); 5151590Srgrimes must_use_uc = (UNDER_CHAR && !ENTER_UNDERLINE); 5161590Srgrimes} 5171590Srgrimes 518227190Sedstatic int 519102944Sdwmaloneoutchar(int c) 5201590Srgrimes{ 521132858Stjr return (putwchar(c) != WEOF ? c : EOF); 5221590Srgrimes} 5231590Srgrimes 5241590Srgrimesstatic int curmode = 0; 5251590Srgrimes 526227190Sedstatic void 527132858Stjroutc(wint_t c, int width) 5281590Srgrimes{ 529132858Stjr int i; 530132858Stjr 531132858Stjr putwchar(c); 5321590Srgrimes if (must_use_uc && (curmode&UNDERL)) { 533132858Stjr for (i = 0; i < width; i++) 534132858Stjr PRINT(CURS_LEFT); 535132858Stjr for (i = 0; i < width; i++) 536132858Stjr PRINT(UNDER_CHAR); 5371590Srgrimes } 5381590Srgrimes} 5391590Srgrimes 540227190Sedstatic void 541102944Sdwmalonesetnewmode(int newmode) 5421590Srgrimes{ 5431590Srgrimes if (!iflag) { 5441590Srgrimes if (curmode != NORMAL && newmode != NORMAL) 54528454Scharnier setnewmode(NORMAL); 5461590Srgrimes switch (newmode) { 5471590Srgrimes case NORMAL: 5481590Srgrimes switch(curmode) { 5491590Srgrimes case NORMAL: 5501590Srgrimes break; 5511590Srgrimes case UNDERL: 5521590Srgrimes PRINT(EXIT_UNDERLINE); 5531590Srgrimes break; 5541590Srgrimes default: 5551590Srgrimes /* This includes standout */ 5561590Srgrimes PRINT(EXIT_ATTRIBUTES); 5571590Srgrimes break; 5581590Srgrimes } 5591590Srgrimes break; 5601590Srgrimes case ALTSET: 5611590Srgrimes PRINT(ENTER_REVERSE); 5621590Srgrimes break; 5631590Srgrimes case SUPERSC: 5641590Srgrimes /* 5651590Srgrimes * This only works on a few terminals. 5661590Srgrimes * It should be fixed. 5671590Srgrimes */ 5681590Srgrimes PRINT(ENTER_UNDERLINE); 5691590Srgrimes PRINT(ENTER_DIM); 5701590Srgrimes break; 5711590Srgrimes case SUBSC: 5721590Srgrimes PRINT(ENTER_DIM); 5731590Srgrimes break; 5741590Srgrimes case UNDERL: 5751590Srgrimes PRINT(ENTER_UNDERLINE); 5761590Srgrimes break; 5771590Srgrimes case BOLD: 5781590Srgrimes PRINT(ENTER_BOLD); 5791590Srgrimes break; 5801590Srgrimes default: 5811590Srgrimes /* 5821590Srgrimes * We should have some provision here for multiple modes 5831590Srgrimes * on at once. This will have to come later. 5841590Srgrimes */ 5851590Srgrimes PRINT(ENTER_STANDOUT); 5861590Srgrimes break; 5871590Srgrimes } 5881590Srgrimes } 5891590Srgrimes curmode = newmode; 5901590Srgrimes} 591