1*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 2*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 3*7c478bd9Sstevel@tonic-gate 4*7c478bd9Sstevel@tonic-gate 5*7c478bd9Sstevel@tonic-gate /* 6*7c478bd9Sstevel@tonic-gate * Copyright (c) 1980 Regents of the University of California. 7*7c478bd9Sstevel@tonic-gate * All rights reserved. The Berkeley software License Agreement 8*7c478bd9Sstevel@tonic-gate * specifies the terms and conditions for redistribution. 9*7c478bd9Sstevel@tonic-gate */ 10*7c478bd9Sstevel@tonic-gate 11*7c478bd9Sstevel@tonic-gate /* 12*7c478bd9Sstevel@tonic-gate * Copyright (c) 1983, 1984 1985, 1986, 1987, 1988, 2000 Sun Microsystems, Inc. 13*7c478bd9Sstevel@tonic-gate * All Rights Reserved. 14*7c478bd9Sstevel@tonic-gate */ 15*7c478bd9Sstevel@tonic-gate 16*7c478bd9Sstevel@tonic-gate #ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.1 */ 17*7c478bd9Sstevel@tonic-gate 18*7c478bd9Sstevel@tonic-gate #include <stdio.h> 19*7c478bd9Sstevel@tonic-gate #include <locale.h> 20*7c478bd9Sstevel@tonic-gate #include <wctype.h> 21*7c478bd9Sstevel@tonic-gate #include <widec.h> 22*7c478bd9Sstevel@tonic-gate #include <euc.h> 23*7c478bd9Sstevel@tonic-gate #include <limits.h> 24*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 25*7c478bd9Sstevel@tonic-gate 26*7c478bd9Sstevel@tonic-gate #define IESC L'\033' 27*7c478bd9Sstevel@tonic-gate #define SO L'\016' 28*7c478bd9Sstevel@tonic-gate #define SI L'\017' 29*7c478bd9Sstevel@tonic-gate #define HFWD L'9' 30*7c478bd9Sstevel@tonic-gate #define HREV L'8' 31*7c478bd9Sstevel@tonic-gate #define FREV L'7' 32*7c478bd9Sstevel@tonic-gate #define CDUMMY -1 33*7c478bd9Sstevel@tonic-gate 34*7c478bd9Sstevel@tonic-gate #define NORMAL 000 35*7c478bd9Sstevel@tonic-gate #define ALTSET 001 /* Reverse */ 36*7c478bd9Sstevel@tonic-gate #define SUPERSC 002 /* Dim */ 37*7c478bd9Sstevel@tonic-gate #define SUBSC 004 /* Dim | Ul */ 38*7c478bd9Sstevel@tonic-gate #define UNDERL 010 /* Ul */ 39*7c478bd9Sstevel@tonic-gate #define BOLD 020 /* Bold */ 40*7c478bd9Sstevel@tonic-gate 41*7c478bd9Sstevel@tonic-gate #define MEMFCT 16 42*7c478bd9Sstevel@tonic-gate /* 43*7c478bd9Sstevel@tonic-gate * MEMFCT is a number that is likely to be large enough as a factor for 44*7c478bd9Sstevel@tonic-gate * allocating more memory and to be small enough so as not wasting memory 45*7c478bd9Sstevel@tonic-gate */ 46*7c478bd9Sstevel@tonic-gate 47*7c478bd9Sstevel@tonic-gate int must_use_uc, must_overstrike; 48*7c478bd9Sstevel@tonic-gate char *CURS_UP, *CURS_RIGHT, *CURS_LEFT, 49*7c478bd9Sstevel@tonic-gate *ENTER_STANDOUT, *EXIT_STANDOUT, *ENTER_UNDERLINE, *EXIT_UNDERLINE, 50*7c478bd9Sstevel@tonic-gate *ENTER_DIM, *ENTER_BOLD, *ENTER_REVERSE, *UNDER_CHAR, *EXIT_ATTRIBUTES; 51*7c478bd9Sstevel@tonic-gate 52*7c478bd9Sstevel@tonic-gate struct CHAR { 53*7c478bd9Sstevel@tonic-gate char c_mode; 54*7c478bd9Sstevel@tonic-gate wchar_t c_char; 55*7c478bd9Sstevel@tonic-gate }; 56*7c478bd9Sstevel@tonic-gate 57*7c478bd9Sstevel@tonic-gate struct CHAR obuf[LINE_MAX]; 58*7c478bd9Sstevel@tonic-gate int col, maxcol; 59*7c478bd9Sstevel@tonic-gate int mode; 60*7c478bd9Sstevel@tonic-gate int halfpos; 61*7c478bd9Sstevel@tonic-gate int upln; 62*7c478bd9Sstevel@tonic-gate int iflag; 63*7c478bd9Sstevel@tonic-gate 64*7c478bd9Sstevel@tonic-gate eucwidth_t wp; 65*7c478bd9Sstevel@tonic-gate int scrw[4]; 66*7c478bd9Sstevel@tonic-gate 67*7c478bd9Sstevel@tonic-gate main(argc, argv) 68*7c478bd9Sstevel@tonic-gate int argc; 69*7c478bd9Sstevel@tonic-gate char **argv; 70*7c478bd9Sstevel@tonic-gate { 71*7c478bd9Sstevel@tonic-gate int c; 72*7c478bd9Sstevel@tonic-gate char *cp, *termtype; 73*7c478bd9Sstevel@tonic-gate FILE *f; 74*7c478bd9Sstevel@tonic-gate char termcap[1024]; 75*7c478bd9Sstevel@tonic-gate char *getenv(); 76*7c478bd9Sstevel@tonic-gate extern int optind; 77*7c478bd9Sstevel@tonic-gate extern char *optarg; 78*7c478bd9Sstevel@tonic-gate 79*7c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 80*7c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) 81*7c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" 82*7c478bd9Sstevel@tonic-gate #endif 83*7c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 84*7c478bd9Sstevel@tonic-gate 85*7c478bd9Sstevel@tonic-gate getwidth(&wp); 86*7c478bd9Sstevel@tonic-gate scrw[0] = 1; 87*7c478bd9Sstevel@tonic-gate scrw[1] = wp._scrw1; 88*7c478bd9Sstevel@tonic-gate scrw[2] = wp._scrw2; 89*7c478bd9Sstevel@tonic-gate scrw[3] = wp._scrw3; 90*7c478bd9Sstevel@tonic-gate 91*7c478bd9Sstevel@tonic-gate termtype = getenv("TERM"); 92*7c478bd9Sstevel@tonic-gate if (termtype == NULL || (argv[0][0] == 'c' && !isatty(1))) 93*7c478bd9Sstevel@tonic-gate termtype = "lpr"; 94*7c478bd9Sstevel@tonic-gate while ((c=getopt(argc, argv, "it:T:")) != EOF) 95*7c478bd9Sstevel@tonic-gate switch (c) { 96*7c478bd9Sstevel@tonic-gate 97*7c478bd9Sstevel@tonic-gate case 't': 98*7c478bd9Sstevel@tonic-gate case 'T': /* for nroff compatibility */ 99*7c478bd9Sstevel@tonic-gate termtype = optarg; 100*7c478bd9Sstevel@tonic-gate break; 101*7c478bd9Sstevel@tonic-gate case 'i': 102*7c478bd9Sstevel@tonic-gate iflag = 1; 103*7c478bd9Sstevel@tonic-gate break; 104*7c478bd9Sstevel@tonic-gate 105*7c478bd9Sstevel@tonic-gate default: 106*7c478bd9Sstevel@tonic-gate fprintf(stderr, 107*7c478bd9Sstevel@tonic-gate gettext("\ 108*7c478bd9Sstevel@tonic-gate Usage: %s [ -i ] [ -t terminal ] [ filename...]\n"), 109*7c478bd9Sstevel@tonic-gate argv[0]); 110*7c478bd9Sstevel@tonic-gate exit(1); 111*7c478bd9Sstevel@tonic-gate } 112*7c478bd9Sstevel@tonic-gate 113*7c478bd9Sstevel@tonic-gate switch (tgetent(termcap, termtype)) { 114*7c478bd9Sstevel@tonic-gate 115*7c478bd9Sstevel@tonic-gate case 1: 116*7c478bd9Sstevel@tonic-gate break; 117*7c478bd9Sstevel@tonic-gate 118*7c478bd9Sstevel@tonic-gate default: 119*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("trouble reading termcap")); 120*7c478bd9Sstevel@tonic-gate /* fall through to ... */ 121*7c478bd9Sstevel@tonic-gate 122*7c478bd9Sstevel@tonic-gate case 0: 123*7c478bd9Sstevel@tonic-gate /* No such terminal type - assume dumb */ 124*7c478bd9Sstevel@tonic-gate strcpy(termcap, "dumb:os:col#80:cr=^M:sf=^J:am:"); 125*7c478bd9Sstevel@tonic-gate break; 126*7c478bd9Sstevel@tonic-gate } 127*7c478bd9Sstevel@tonic-gate initcap(); 128*7c478bd9Sstevel@tonic-gate if ((tgetflag("os") && ENTER_BOLD==NULL) || 129*7c478bd9Sstevel@tonic-gate (tgetflag("ul") && ENTER_UNDERLINE==NULL && UNDER_CHAR==NULL)) 130*7c478bd9Sstevel@tonic-gate must_overstrike = 1; 131*7c478bd9Sstevel@tonic-gate initbuf(); 132*7c478bd9Sstevel@tonic-gate if (optind == argc) 133*7c478bd9Sstevel@tonic-gate filter(stdin); 134*7c478bd9Sstevel@tonic-gate else for (; optind<argc; optind++) { 135*7c478bd9Sstevel@tonic-gate f = fopen(argv[optind], "r"); 136*7c478bd9Sstevel@tonic-gate if (f == NULL) { 137*7c478bd9Sstevel@tonic-gate perror(argv[optind]); 138*7c478bd9Sstevel@tonic-gate exit(1); 139*7c478bd9Sstevel@tonic-gate } else 140*7c478bd9Sstevel@tonic-gate filter(f); 141*7c478bd9Sstevel@tonic-gate } 142*7c478bd9Sstevel@tonic-gate exit(0); 143*7c478bd9Sstevel@tonic-gate } 144*7c478bd9Sstevel@tonic-gate 145*7c478bd9Sstevel@tonic-gate filter(f) 146*7c478bd9Sstevel@tonic-gate FILE *f; 147*7c478bd9Sstevel@tonic-gate { 148*7c478bd9Sstevel@tonic-gate register wchar_t c; 149*7c478bd9Sstevel@tonic-gate register i; 150*7c478bd9Sstevel@tonic-gate 151*7c478bd9Sstevel@tonic-gate while ((c = getwc(f)) != EOF) { 152*7c478bd9Sstevel@tonic-gate if (maxcol >= LINE_MAX) 153*7c478bd9Sstevel@tonic-gate { 154*7c478bd9Sstevel@tonic-gate fprintf(stderr, 155*7c478bd9Sstevel@tonic-gate gettext("Input line longer than %d characters\n"), LINE_MAX); 156*7c478bd9Sstevel@tonic-gate exit(1); 157*7c478bd9Sstevel@tonic-gate } 158*7c478bd9Sstevel@tonic-gate switch (c) { 159*7c478bd9Sstevel@tonic-gate 160*7c478bd9Sstevel@tonic-gate case L'\b': 161*7c478bd9Sstevel@tonic-gate if (col > 0) 162*7c478bd9Sstevel@tonic-gate col--; 163*7c478bd9Sstevel@tonic-gate continue; 164*7c478bd9Sstevel@tonic-gate 165*7c478bd9Sstevel@tonic-gate case L'\t': 166*7c478bd9Sstevel@tonic-gate col = (col+8) & ~07; 167*7c478bd9Sstevel@tonic-gate if (col > maxcol) 168*7c478bd9Sstevel@tonic-gate maxcol = col; 169*7c478bd9Sstevel@tonic-gate continue; 170*7c478bd9Sstevel@tonic-gate 171*7c478bd9Sstevel@tonic-gate case L'\r': 172*7c478bd9Sstevel@tonic-gate col = 0; 173*7c478bd9Sstevel@tonic-gate continue; 174*7c478bd9Sstevel@tonic-gate 175*7c478bd9Sstevel@tonic-gate case SO: 176*7c478bd9Sstevel@tonic-gate mode |= ALTSET; 177*7c478bd9Sstevel@tonic-gate continue; 178*7c478bd9Sstevel@tonic-gate 179*7c478bd9Sstevel@tonic-gate case SI: 180*7c478bd9Sstevel@tonic-gate mode &= ~ALTSET; 181*7c478bd9Sstevel@tonic-gate continue; 182*7c478bd9Sstevel@tonic-gate 183*7c478bd9Sstevel@tonic-gate case IESC: 184*7c478bd9Sstevel@tonic-gate switch (c = getwc(f)) { 185*7c478bd9Sstevel@tonic-gate case HREV: 186*7c478bd9Sstevel@tonic-gate if (halfpos == 0) { 187*7c478bd9Sstevel@tonic-gate mode |= SUPERSC; 188*7c478bd9Sstevel@tonic-gate halfpos--; 189*7c478bd9Sstevel@tonic-gate } else if (halfpos > 0) { 190*7c478bd9Sstevel@tonic-gate mode &= ~SUBSC; 191*7c478bd9Sstevel@tonic-gate halfpos--; 192*7c478bd9Sstevel@tonic-gate } else { 193*7c478bd9Sstevel@tonic-gate halfpos = 0; 194*7c478bd9Sstevel@tonic-gate reverse(); 195*7c478bd9Sstevel@tonic-gate } 196*7c478bd9Sstevel@tonic-gate continue; 197*7c478bd9Sstevel@tonic-gate 198*7c478bd9Sstevel@tonic-gate case HFWD: 199*7c478bd9Sstevel@tonic-gate if (halfpos == 0) { 200*7c478bd9Sstevel@tonic-gate mode |= SUBSC; 201*7c478bd9Sstevel@tonic-gate halfpos++; 202*7c478bd9Sstevel@tonic-gate } else if (halfpos < 0) { 203*7c478bd9Sstevel@tonic-gate mode &= ~SUPERSC; 204*7c478bd9Sstevel@tonic-gate halfpos++; 205*7c478bd9Sstevel@tonic-gate } else { 206*7c478bd9Sstevel@tonic-gate halfpos = 0; 207*7c478bd9Sstevel@tonic-gate fwd(); 208*7c478bd9Sstevel@tonic-gate } 209*7c478bd9Sstevel@tonic-gate continue; 210*7c478bd9Sstevel@tonic-gate case FREV: 211*7c478bd9Sstevel@tonic-gate reverse(); 212*7c478bd9Sstevel@tonic-gate continue; 213*7c478bd9Sstevel@tonic-gate 214*7c478bd9Sstevel@tonic-gate default: 215*7c478bd9Sstevel@tonic-gate fprintf(stderr, 216*7c478bd9Sstevel@tonic-gate gettext("Unknown escape sequence in input: %o, %o\n"), 217*7c478bd9Sstevel@tonic-gate IESC, c); 218*7c478bd9Sstevel@tonic-gate exit(1); 219*7c478bd9Sstevel@tonic-gate } 220*7c478bd9Sstevel@tonic-gate continue; 221*7c478bd9Sstevel@tonic-gate 222*7c478bd9Sstevel@tonic-gate case L'_': 223*7c478bd9Sstevel@tonic-gate if (obuf[col].c_char) 224*7c478bd9Sstevel@tonic-gate obuf[col].c_mode |= UNDERL | mode; 225*7c478bd9Sstevel@tonic-gate else 226*7c478bd9Sstevel@tonic-gate obuf[col].c_char = '_'; 227*7c478bd9Sstevel@tonic-gate case L' ': 228*7c478bd9Sstevel@tonic-gate col++; 229*7c478bd9Sstevel@tonic-gate if (col > maxcol) 230*7c478bd9Sstevel@tonic-gate maxcol = col; 231*7c478bd9Sstevel@tonic-gate continue; 232*7c478bd9Sstevel@tonic-gate 233*7c478bd9Sstevel@tonic-gate case L'\n': 234*7c478bd9Sstevel@tonic-gate flushln(); 235*7c478bd9Sstevel@tonic-gate continue; 236*7c478bd9Sstevel@tonic-gate 237*7c478bd9Sstevel@tonic-gate default: 238*7c478bd9Sstevel@tonic-gate if (c < L' ') /* non printing */ 239*7c478bd9Sstevel@tonic-gate continue; 240*7c478bd9Sstevel@tonic-gate if (obuf[col].c_char == L'\0') { 241*7c478bd9Sstevel@tonic-gate obuf[col].c_char = c; 242*7c478bd9Sstevel@tonic-gate obuf[col].c_mode = mode; 243*7c478bd9Sstevel@tonic-gate i = scrw[wcsetno(c)]; 244*7c478bd9Sstevel@tonic-gate while (--i > 0) 245*7c478bd9Sstevel@tonic-gate obuf[++col].c_char = CDUMMY; 246*7c478bd9Sstevel@tonic-gate } else if (obuf[col].c_char == L'_') { 247*7c478bd9Sstevel@tonic-gate obuf[col].c_char = c; 248*7c478bd9Sstevel@tonic-gate obuf[col].c_mode |= UNDERL|mode; 249*7c478bd9Sstevel@tonic-gate i = scrw[wcsetno(c)]; 250*7c478bd9Sstevel@tonic-gate while (--i > 0) 251*7c478bd9Sstevel@tonic-gate obuf[++col].c_char = CDUMMY; 252*7c478bd9Sstevel@tonic-gate } else if (obuf[col].c_char == c) 253*7c478bd9Sstevel@tonic-gate obuf[col].c_mode |= BOLD|mode; 254*7c478bd9Sstevel@tonic-gate else { 255*7c478bd9Sstevel@tonic-gate obuf[col].c_char = c; 256*7c478bd9Sstevel@tonic-gate obuf[col].c_mode = mode; 257*7c478bd9Sstevel@tonic-gate } 258*7c478bd9Sstevel@tonic-gate col++; 259*7c478bd9Sstevel@tonic-gate if (col > maxcol) 260*7c478bd9Sstevel@tonic-gate maxcol = col; 261*7c478bd9Sstevel@tonic-gate continue; 262*7c478bd9Sstevel@tonic-gate } 263*7c478bd9Sstevel@tonic-gate } 264*7c478bd9Sstevel@tonic-gate if (maxcol) 265*7c478bd9Sstevel@tonic-gate flushln(); 266*7c478bd9Sstevel@tonic-gate } 267*7c478bd9Sstevel@tonic-gate 268*7c478bd9Sstevel@tonic-gate flushln() 269*7c478bd9Sstevel@tonic-gate { 270*7c478bd9Sstevel@tonic-gate register lastmode; 271*7c478bd9Sstevel@tonic-gate register i; 272*7c478bd9Sstevel@tonic-gate int hadmodes = 0; 273*7c478bd9Sstevel@tonic-gate 274*7c478bd9Sstevel@tonic-gate lastmode = NORMAL; 275*7c478bd9Sstevel@tonic-gate for (i=0; i<maxcol; i++) { 276*7c478bd9Sstevel@tonic-gate if (obuf[i].c_mode != lastmode) { 277*7c478bd9Sstevel@tonic-gate hadmodes++; 278*7c478bd9Sstevel@tonic-gate setmode(obuf[i].c_mode); 279*7c478bd9Sstevel@tonic-gate lastmode = obuf[i].c_mode; 280*7c478bd9Sstevel@tonic-gate } 281*7c478bd9Sstevel@tonic-gate if (obuf[i].c_char == L'\0') { 282*7c478bd9Sstevel@tonic-gate if (upln) { 283*7c478bd9Sstevel@tonic-gate puts(CURS_RIGHT); 284*7c478bd9Sstevel@tonic-gate } else 285*7c478bd9Sstevel@tonic-gate outc(L' '); 286*7c478bd9Sstevel@tonic-gate } else 287*7c478bd9Sstevel@tonic-gate outc(obuf[i].c_char); 288*7c478bd9Sstevel@tonic-gate } 289*7c478bd9Sstevel@tonic-gate if (lastmode != NORMAL) { 290*7c478bd9Sstevel@tonic-gate setmode(0); 291*7c478bd9Sstevel@tonic-gate } 292*7c478bd9Sstevel@tonic-gate if (must_overstrike && hadmodes) 293*7c478bd9Sstevel@tonic-gate overstrike(); 294*7c478bd9Sstevel@tonic-gate putwchar(L'\n'); 295*7c478bd9Sstevel@tonic-gate if (iflag && hadmodes) 296*7c478bd9Sstevel@tonic-gate iattr(); 297*7c478bd9Sstevel@tonic-gate if (upln) 298*7c478bd9Sstevel@tonic-gate upln--; 299*7c478bd9Sstevel@tonic-gate initbuf(); 300*7c478bd9Sstevel@tonic-gate } 301*7c478bd9Sstevel@tonic-gate 302*7c478bd9Sstevel@tonic-gate /* 303*7c478bd9Sstevel@tonic-gate * For terminals that can overstrike, overstrike underlines and bolds. 304*7c478bd9Sstevel@tonic-gate * We don't do anything with halfline ups and downs, or Greek. 305*7c478bd9Sstevel@tonic-gate */ 306*7c478bd9Sstevel@tonic-gate overstrike() 307*7c478bd9Sstevel@tonic-gate { 308*7c478bd9Sstevel@tonic-gate register int i, n; 309*7c478bd9Sstevel@tonic-gate wchar_t *cp, *scp; 310*7c478bd9Sstevel@tonic-gate size_t szbf = 256, tszbf; 311*7c478bd9Sstevel@tonic-gate int hadbold=0; 312*7c478bd9Sstevel@tonic-gate 313*7c478bd9Sstevel@tonic-gate scp = (wchar_t *)malloc(sizeof (wchar_t) * szbf); 314*7c478bd9Sstevel@tonic-gate if (!scp) { 315*7c478bd9Sstevel@tonic-gate /* this kind of message need not to be gettext'ed */ 316*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "malloc failed\n"); 317*7c478bd9Sstevel@tonic-gate exit(1); 318*7c478bd9Sstevel@tonic-gate } 319*7c478bd9Sstevel@tonic-gate cp = scp; 320*7c478bd9Sstevel@tonic-gate tszbf = szbf; 321*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 322*7c478bd9Sstevel@tonic-gate /* 323*7c478bd9Sstevel@tonic-gate * to allocate a memory after the chunk of the current scp 324*7c478bd9Sstevel@tonic-gate * and to make sure the following realloc() allocates 325*7c478bd9Sstevel@tonic-gate * memory from different chunks. 326*7c478bd9Sstevel@tonic-gate */ 327*7c478bd9Sstevel@tonic-gate (void) malloc(1024 * 1024); 328*7c478bd9Sstevel@tonic-gate #endif 329*7c478bd9Sstevel@tonic-gate 330*7c478bd9Sstevel@tonic-gate /* Set up overstrike buffer */ 331*7c478bd9Sstevel@tonic-gate for (i=0; i<maxcol; i++) { 332*7c478bd9Sstevel@tonic-gate n = scrw[wcsetno(obuf[i].c_char)]; 333*7c478bd9Sstevel@tonic-gate if (tszbf <= n) { 334*7c478bd9Sstevel@tonic-gate /* may not enough buffer for this char */ 335*7c478bd9Sstevel@tonic-gate size_t pos; 336*7c478bd9Sstevel@tonic-gate 337*7c478bd9Sstevel@tonic-gate /* obtain the offset of cp */ 338*7c478bd9Sstevel@tonic-gate pos = cp - scp; 339*7c478bd9Sstevel@tonic-gate /* reallocate another (n * MEMFCT) * sizeof (wchar_t) */ 340*7c478bd9Sstevel@tonic-gate scp = (wchar_t *)realloc(scp, 341*7c478bd9Sstevel@tonic-gate sizeof (wchar_t) * (szbf + (n * MEMFCT))); 342*7c478bd9Sstevel@tonic-gate if (!scp) { 343*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "malloc failed\n"); 344*7c478bd9Sstevel@tonic-gate exit(1); 345*7c478bd9Sstevel@tonic-gate } 346*7c478bd9Sstevel@tonic-gate /* get the new address of cp */ 347*7c478bd9Sstevel@tonic-gate cp = scp + pos; 348*7c478bd9Sstevel@tonic-gate szbf += n * MEMFCT; 349*7c478bd9Sstevel@tonic-gate tszbf += n * MEMFCT; 350*7c478bd9Sstevel@tonic-gate } 351*7c478bd9Sstevel@tonic-gate switch (obuf[i].c_mode) { 352*7c478bd9Sstevel@tonic-gate case NORMAL: 353*7c478bd9Sstevel@tonic-gate default: 354*7c478bd9Sstevel@tonic-gate tszbf -= n; 355*7c478bd9Sstevel@tonic-gate *cp++ = L' '; 356*7c478bd9Sstevel@tonic-gate while (--n > 0) { 357*7c478bd9Sstevel@tonic-gate *cp++ = L' '; 358*7c478bd9Sstevel@tonic-gate i++; 359*7c478bd9Sstevel@tonic-gate } 360*7c478bd9Sstevel@tonic-gate break; 361*7c478bd9Sstevel@tonic-gate case UNDERL: 362*7c478bd9Sstevel@tonic-gate tszbf -= n; 363*7c478bd9Sstevel@tonic-gate *cp++ = L'_'; 364*7c478bd9Sstevel@tonic-gate while (--n > 0) { 365*7c478bd9Sstevel@tonic-gate *cp++ = L'_'; 366*7c478bd9Sstevel@tonic-gate i++; 367*7c478bd9Sstevel@tonic-gate } 368*7c478bd9Sstevel@tonic-gate break; 369*7c478bd9Sstevel@tonic-gate case BOLD: 370*7c478bd9Sstevel@tonic-gate tszbf--; 371*7c478bd9Sstevel@tonic-gate *cp++ = obuf[i].c_char; 372*7c478bd9Sstevel@tonic-gate hadbold=1; 373*7c478bd9Sstevel@tonic-gate break; 374*7c478bd9Sstevel@tonic-gate } 375*7c478bd9Sstevel@tonic-gate } 376*7c478bd9Sstevel@tonic-gate putwchar(L'\r'); 377*7c478bd9Sstevel@tonic-gate for (*cp=L' '; *cp==L' '; cp--) 378*7c478bd9Sstevel@tonic-gate *cp = L'\0'; 379*7c478bd9Sstevel@tonic-gate for (cp=scp; *cp; cp++) 380*7c478bd9Sstevel@tonic-gate putwchar(*cp); 381*7c478bd9Sstevel@tonic-gate if (hadbold) { 382*7c478bd9Sstevel@tonic-gate putwchar(L'\r'); 383*7c478bd9Sstevel@tonic-gate for (cp=scp; *cp; cp++) 384*7c478bd9Sstevel@tonic-gate putwchar(*cp==L'_' ? L' ' : *cp); 385*7c478bd9Sstevel@tonic-gate putwchar(L'\r'); 386*7c478bd9Sstevel@tonic-gate for (cp=scp; *cp; cp++) 387*7c478bd9Sstevel@tonic-gate putwchar(*cp==L'_' ? L' ' : *cp); 388*7c478bd9Sstevel@tonic-gate } 389*7c478bd9Sstevel@tonic-gate free(scp); 390*7c478bd9Sstevel@tonic-gate } 391*7c478bd9Sstevel@tonic-gate 392*7c478bd9Sstevel@tonic-gate iattr() 393*7c478bd9Sstevel@tonic-gate { 394*7c478bd9Sstevel@tonic-gate register int i, n; 395*7c478bd9Sstevel@tonic-gate wchar_t *cp, *scp; 396*7c478bd9Sstevel@tonic-gate register wchar_t cx; 397*7c478bd9Sstevel@tonic-gate size_t szbf = 256, tszbf; 398*7c478bd9Sstevel@tonic-gate 399*7c478bd9Sstevel@tonic-gate scp = (wchar_t *)malloc(sizeof (wchar_t) * szbf); 400*7c478bd9Sstevel@tonic-gate if (!scp) { 401*7c478bd9Sstevel@tonic-gate /* this kind of message need not to be gettext'ed */ 402*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "malloc failed\n"); 403*7c478bd9Sstevel@tonic-gate exit(1); 404*7c478bd9Sstevel@tonic-gate } 405*7c478bd9Sstevel@tonic-gate cp = scp; 406*7c478bd9Sstevel@tonic-gate tszbf = szbf; 407*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 408*7c478bd9Sstevel@tonic-gate /* 409*7c478bd9Sstevel@tonic-gate * to allocate a memory after the chunk of the current scp 410*7c478bd9Sstevel@tonic-gate * and to make sure the following realloc() allocates 411*7c478bd9Sstevel@tonic-gate * memory from different chunks. 412*7c478bd9Sstevel@tonic-gate */ 413*7c478bd9Sstevel@tonic-gate (void) malloc(1024 * 1024); 414*7c478bd9Sstevel@tonic-gate #endif 415*7c478bd9Sstevel@tonic-gate for (i=0; i<maxcol; i++) { 416*7c478bd9Sstevel@tonic-gate switch (obuf[i].c_mode) { 417*7c478bd9Sstevel@tonic-gate case NORMAL: cx = ' '; break; 418*7c478bd9Sstevel@tonic-gate case ALTSET: cx = 'g'; break; 419*7c478bd9Sstevel@tonic-gate case SUPERSC: cx = '^'; break; 420*7c478bd9Sstevel@tonic-gate case SUBSC: cx = 'v'; break; 421*7c478bd9Sstevel@tonic-gate case UNDERL: cx = '_'; break; 422*7c478bd9Sstevel@tonic-gate case BOLD: cx = '!'; break; 423*7c478bd9Sstevel@tonic-gate default: cx = 'X'; break; 424*7c478bd9Sstevel@tonic-gate } 425*7c478bd9Sstevel@tonic-gate n = scrw[wcsetno(obuf[i].c_char)]; 426*7c478bd9Sstevel@tonic-gate if (tszbf <= n) { 427*7c478bd9Sstevel@tonic-gate /* may not enough buffer for this char */ 428*7c478bd9Sstevel@tonic-gate size_t pos; 429*7c478bd9Sstevel@tonic-gate 430*7c478bd9Sstevel@tonic-gate /* obtain the offset of cp */ 431*7c478bd9Sstevel@tonic-gate pos = cp - scp; 432*7c478bd9Sstevel@tonic-gate /* reallocate another (n * MEMFCT) * sizeof (wchar_t) */ 433*7c478bd9Sstevel@tonic-gate scp = (wchar_t *)realloc(scp, 434*7c478bd9Sstevel@tonic-gate sizeof (wchar_t) * (szbf + (n * MEMFCT))); 435*7c478bd9Sstevel@tonic-gate if (!scp) { 436*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "malloc failed\n"); 437*7c478bd9Sstevel@tonic-gate exit(1); 438*7c478bd9Sstevel@tonic-gate } 439*7c478bd9Sstevel@tonic-gate /* get the new address of cp */ 440*7c478bd9Sstevel@tonic-gate cp = scp + pos; 441*7c478bd9Sstevel@tonic-gate szbf += n * MEMFCT; 442*7c478bd9Sstevel@tonic-gate tszbf += n * MEMFCT; 443*7c478bd9Sstevel@tonic-gate } 444*7c478bd9Sstevel@tonic-gate tszbf -= n; 445*7c478bd9Sstevel@tonic-gate *cp++ = cx; 446*7c478bd9Sstevel@tonic-gate while (--n > 0) { 447*7c478bd9Sstevel@tonic-gate *cp++ = cx; 448*7c478bd9Sstevel@tonic-gate i++; 449*7c478bd9Sstevel@tonic-gate } 450*7c478bd9Sstevel@tonic-gate } 451*7c478bd9Sstevel@tonic-gate for (*cp=L' '; *cp==L' '; cp--) 452*7c478bd9Sstevel@tonic-gate *cp = L'\0'; 453*7c478bd9Sstevel@tonic-gate for (cp=scp; *cp; cp++) 454*7c478bd9Sstevel@tonic-gate putwchar(*cp); 455*7c478bd9Sstevel@tonic-gate putwchar(L'\n'); 456*7c478bd9Sstevel@tonic-gate free(scp); 457*7c478bd9Sstevel@tonic-gate } 458*7c478bd9Sstevel@tonic-gate 459*7c478bd9Sstevel@tonic-gate initbuf() 460*7c478bd9Sstevel@tonic-gate { 461*7c478bd9Sstevel@tonic-gate register i; 462*7c478bd9Sstevel@tonic-gate 463*7c478bd9Sstevel@tonic-gate /* following depends on NORMAL == 000 */ 464*7c478bd9Sstevel@tonic-gate for (i = 0; i < LINE_MAX; i++) 465*7c478bd9Sstevel@tonic-gate obuf[i].c_char = obuf[i].c_mode = 0; 466*7c478bd9Sstevel@tonic-gate 467*7c478bd9Sstevel@tonic-gate col = 0; 468*7c478bd9Sstevel@tonic-gate maxcol = 0; 469*7c478bd9Sstevel@tonic-gate mode &= ALTSET; 470*7c478bd9Sstevel@tonic-gate } 471*7c478bd9Sstevel@tonic-gate 472*7c478bd9Sstevel@tonic-gate fwd() 473*7c478bd9Sstevel@tonic-gate { 474*7c478bd9Sstevel@tonic-gate register oldcol, oldmax; 475*7c478bd9Sstevel@tonic-gate 476*7c478bd9Sstevel@tonic-gate oldcol = col; 477*7c478bd9Sstevel@tonic-gate oldmax = maxcol; 478*7c478bd9Sstevel@tonic-gate flushln(); 479*7c478bd9Sstevel@tonic-gate col = oldcol; 480*7c478bd9Sstevel@tonic-gate maxcol = oldmax; 481*7c478bd9Sstevel@tonic-gate } 482*7c478bd9Sstevel@tonic-gate 483*7c478bd9Sstevel@tonic-gate reverse() 484*7c478bd9Sstevel@tonic-gate { 485*7c478bd9Sstevel@tonic-gate upln++; 486*7c478bd9Sstevel@tonic-gate fwd(); 487*7c478bd9Sstevel@tonic-gate puts(CURS_UP); 488*7c478bd9Sstevel@tonic-gate puts(CURS_UP); 489*7c478bd9Sstevel@tonic-gate upln++; 490*7c478bd9Sstevel@tonic-gate } 491*7c478bd9Sstevel@tonic-gate 492*7c478bd9Sstevel@tonic-gate initcap() 493*7c478bd9Sstevel@tonic-gate { 494*7c478bd9Sstevel@tonic-gate static char tcapbuf[512]; 495*7c478bd9Sstevel@tonic-gate char *termtype; 496*7c478bd9Sstevel@tonic-gate char *bp = tcapbuf; 497*7c478bd9Sstevel@tonic-gate char *getenv(), *tgetstr(); 498*7c478bd9Sstevel@tonic-gate 499*7c478bd9Sstevel@tonic-gate /* This nonsense attempts to work with both old and new termcap */ 500*7c478bd9Sstevel@tonic-gate CURS_UP = tgetstr("up", &bp); 501*7c478bd9Sstevel@tonic-gate CURS_RIGHT = tgetstr("ri", &bp); 502*7c478bd9Sstevel@tonic-gate if (CURS_RIGHT == NULL) 503*7c478bd9Sstevel@tonic-gate CURS_RIGHT = tgetstr("nd", &bp); 504*7c478bd9Sstevel@tonic-gate CURS_LEFT = tgetstr("le", &bp); 505*7c478bd9Sstevel@tonic-gate if (CURS_LEFT == NULL) 506*7c478bd9Sstevel@tonic-gate CURS_LEFT = tgetstr("bc", &bp); 507*7c478bd9Sstevel@tonic-gate if (CURS_LEFT == NULL && tgetflag("bs")) 508*7c478bd9Sstevel@tonic-gate CURS_LEFT = "\b"; 509*7c478bd9Sstevel@tonic-gate 510*7c478bd9Sstevel@tonic-gate ENTER_STANDOUT = tgetstr("so", &bp); 511*7c478bd9Sstevel@tonic-gate EXIT_STANDOUT = tgetstr("se", &bp); 512*7c478bd9Sstevel@tonic-gate ENTER_UNDERLINE = tgetstr("us", &bp); 513*7c478bd9Sstevel@tonic-gate EXIT_UNDERLINE = tgetstr("ue", &bp); 514*7c478bd9Sstevel@tonic-gate ENTER_DIM = tgetstr("mh", &bp); 515*7c478bd9Sstevel@tonic-gate ENTER_BOLD = tgetstr("md", &bp); 516*7c478bd9Sstevel@tonic-gate ENTER_REVERSE = tgetstr("mr", &bp); 517*7c478bd9Sstevel@tonic-gate EXIT_ATTRIBUTES = tgetstr("me", &bp); 518*7c478bd9Sstevel@tonic-gate 519*7c478bd9Sstevel@tonic-gate if (!ENTER_BOLD && ENTER_REVERSE) 520*7c478bd9Sstevel@tonic-gate ENTER_BOLD = ENTER_REVERSE; 521*7c478bd9Sstevel@tonic-gate if (!ENTER_BOLD && ENTER_STANDOUT) 522*7c478bd9Sstevel@tonic-gate ENTER_BOLD = ENTER_STANDOUT; 523*7c478bd9Sstevel@tonic-gate if (!ENTER_UNDERLINE && ENTER_STANDOUT) { 524*7c478bd9Sstevel@tonic-gate ENTER_UNDERLINE = ENTER_STANDOUT; 525*7c478bd9Sstevel@tonic-gate EXIT_UNDERLINE = EXIT_STANDOUT; 526*7c478bd9Sstevel@tonic-gate } 527*7c478bd9Sstevel@tonic-gate if (!ENTER_DIM && ENTER_STANDOUT) 528*7c478bd9Sstevel@tonic-gate ENTER_DIM = ENTER_STANDOUT; 529*7c478bd9Sstevel@tonic-gate if (!ENTER_REVERSE && ENTER_STANDOUT) 530*7c478bd9Sstevel@tonic-gate ENTER_REVERSE = ENTER_STANDOUT; 531*7c478bd9Sstevel@tonic-gate if (!EXIT_ATTRIBUTES && EXIT_STANDOUT) 532*7c478bd9Sstevel@tonic-gate EXIT_ATTRIBUTES = EXIT_STANDOUT; 533*7c478bd9Sstevel@tonic-gate 534*7c478bd9Sstevel@tonic-gate /* 535*7c478bd9Sstevel@tonic-gate * Note that we use REVERSE for the alternate character set, 536*7c478bd9Sstevel@tonic-gate * not the as/ae capabilities. This is because we are modelling 537*7c478bd9Sstevel@tonic-gate * the model 37 teletype (since that's what nroff outputs) and 538*7c478bd9Sstevel@tonic-gate * the typical as/ae is more of a graphics set, not the greek 539*7c478bd9Sstevel@tonic-gate * letters the 37 has. 540*7c478bd9Sstevel@tonic-gate */ 541*7c478bd9Sstevel@tonic-gate 542*7c478bd9Sstevel@tonic-gate #ifdef notdef 543*7c478bd9Sstevel@tonic-gate printf("so %s se %s us %s ue %s me %s\n", 544*7c478bd9Sstevel@tonic-gate ENTER_STANDOUT, EXIT_STANDOUT, ENTER_UNDERLINE, 545*7c478bd9Sstevel@tonic-gate EXIT_UNDERLINE, EXIT_ATTRIBUTES); 546*7c478bd9Sstevel@tonic-gate #endif 547*7c478bd9Sstevel@tonic-gate UNDER_CHAR = tgetstr("uc", &bp); 548*7c478bd9Sstevel@tonic-gate must_use_uc = (UNDER_CHAR && !ENTER_UNDERLINE); 549*7c478bd9Sstevel@tonic-gate } 550*7c478bd9Sstevel@tonic-gate 551*7c478bd9Sstevel@tonic-gate outchar(c) 552*7c478bd9Sstevel@tonic-gate char c; 553*7c478bd9Sstevel@tonic-gate { 554*7c478bd9Sstevel@tonic-gate putchar(c&0177); 555*7c478bd9Sstevel@tonic-gate } 556*7c478bd9Sstevel@tonic-gate 557*7c478bd9Sstevel@tonic-gate puts(str) 558*7c478bd9Sstevel@tonic-gate const char *str; 559*7c478bd9Sstevel@tonic-gate { 560*7c478bd9Sstevel@tonic-gate if (str) 561*7c478bd9Sstevel@tonic-gate tputs(str, 1, outchar); 562*7c478bd9Sstevel@tonic-gate } 563*7c478bd9Sstevel@tonic-gate 564*7c478bd9Sstevel@tonic-gate static curmode = 0; 565*7c478bd9Sstevel@tonic-gate outc(c) 566*7c478bd9Sstevel@tonic-gate wchar_t c; 567*7c478bd9Sstevel@tonic-gate { 568*7c478bd9Sstevel@tonic-gate register int m, n; 569*7c478bd9Sstevel@tonic-gate 570*7c478bd9Sstevel@tonic-gate if (c == CDUMMY) 571*7c478bd9Sstevel@tonic-gate return; 572*7c478bd9Sstevel@tonic-gate putwchar(c); 573*7c478bd9Sstevel@tonic-gate if (must_use_uc && (curmode & UNDERL)) { 574*7c478bd9Sstevel@tonic-gate m = n = scrw[wcsetno(c)]; 575*7c478bd9Sstevel@tonic-gate puts(CURS_LEFT); 576*7c478bd9Sstevel@tonic-gate while (--m > 0) 577*7c478bd9Sstevel@tonic-gate puts(CURS_LEFT); 578*7c478bd9Sstevel@tonic-gate puts(UNDER_CHAR); 579*7c478bd9Sstevel@tonic-gate while (--n > 0) 580*7c478bd9Sstevel@tonic-gate puts(UNDER_CHAR); 581*7c478bd9Sstevel@tonic-gate } 582*7c478bd9Sstevel@tonic-gate } 583*7c478bd9Sstevel@tonic-gate 584*7c478bd9Sstevel@tonic-gate setmode(newmode) 585*7c478bd9Sstevel@tonic-gate int newmode; 586*7c478bd9Sstevel@tonic-gate { 587*7c478bd9Sstevel@tonic-gate if (!iflag) 588*7c478bd9Sstevel@tonic-gate { 589*7c478bd9Sstevel@tonic-gate if (curmode != NORMAL && newmode != NORMAL) 590*7c478bd9Sstevel@tonic-gate setmode(NORMAL); 591*7c478bd9Sstevel@tonic-gate switch (newmode) { 592*7c478bd9Sstevel@tonic-gate case NORMAL: 593*7c478bd9Sstevel@tonic-gate switch (curmode) { 594*7c478bd9Sstevel@tonic-gate case NORMAL: 595*7c478bd9Sstevel@tonic-gate break; 596*7c478bd9Sstevel@tonic-gate case UNDERL: 597*7c478bd9Sstevel@tonic-gate puts(EXIT_UNDERLINE); 598*7c478bd9Sstevel@tonic-gate break; 599*7c478bd9Sstevel@tonic-gate default: 600*7c478bd9Sstevel@tonic-gate /* This includes standout */ 601*7c478bd9Sstevel@tonic-gate puts(EXIT_ATTRIBUTES); 602*7c478bd9Sstevel@tonic-gate break; 603*7c478bd9Sstevel@tonic-gate } 604*7c478bd9Sstevel@tonic-gate break; 605*7c478bd9Sstevel@tonic-gate case ALTSET: 606*7c478bd9Sstevel@tonic-gate puts(ENTER_REVERSE); 607*7c478bd9Sstevel@tonic-gate break; 608*7c478bd9Sstevel@tonic-gate case SUPERSC: 609*7c478bd9Sstevel@tonic-gate /* 610*7c478bd9Sstevel@tonic-gate * This only works on a few terminals. 611*7c478bd9Sstevel@tonic-gate * It should be fixed. 612*7c478bd9Sstevel@tonic-gate */ 613*7c478bd9Sstevel@tonic-gate puts(ENTER_UNDERLINE); 614*7c478bd9Sstevel@tonic-gate puts(ENTER_DIM); 615*7c478bd9Sstevel@tonic-gate break; 616*7c478bd9Sstevel@tonic-gate case SUBSC: 617*7c478bd9Sstevel@tonic-gate puts(ENTER_DIM); 618*7c478bd9Sstevel@tonic-gate break; 619*7c478bd9Sstevel@tonic-gate case UNDERL: 620*7c478bd9Sstevel@tonic-gate puts(ENTER_UNDERLINE); 621*7c478bd9Sstevel@tonic-gate break; 622*7c478bd9Sstevel@tonic-gate case BOLD: 623*7c478bd9Sstevel@tonic-gate puts(ENTER_BOLD); 624*7c478bd9Sstevel@tonic-gate break; 625*7c478bd9Sstevel@tonic-gate default: 626*7c478bd9Sstevel@tonic-gate /* 627*7c478bd9Sstevel@tonic-gate * We should have some provision here for multiple modes 628*7c478bd9Sstevel@tonic-gate * on at once. This will have to come later. 629*7c478bd9Sstevel@tonic-gate */ 630*7c478bd9Sstevel@tonic-gate puts(ENTER_STANDOUT); 631*7c478bd9Sstevel@tonic-gate break; 632*7c478bd9Sstevel@tonic-gate } 633*7c478bd9Sstevel@tonic-gate } 634*7c478bd9Sstevel@tonic-gate curmode = newmode; 635*7c478bd9Sstevel@tonic-gate } 636