1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright (c) 1998, 2001 by Sun Microsystems, Inc. 24*7c478bd9Sstevel@tonic-gate * All Rights Reserved 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 29*7c478bd9Sstevel@tonic-gate 30*7c478bd9Sstevel@tonic-gate 31*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 32*7c478bd9Sstevel@tonic-gate /* 33*7c478bd9Sstevel@tonic-gate * col - filter reverse carraige motions 34*7c478bd9Sstevel@tonic-gate * 35*7c478bd9Sstevel@tonic-gate */ 36*7c478bd9Sstevel@tonic-gate 37*7c478bd9Sstevel@tonic-gate 38*7c478bd9Sstevel@tonic-gate #include <stdio.h> 39*7c478bd9Sstevel@tonic-gate #include <ctype.h> 40*7c478bd9Sstevel@tonic-gate #include <locale.h> 41*7c478bd9Sstevel@tonic-gate #include <limits.h> 42*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 43*7c478bd9Sstevel@tonic-gate #include <wctype.h> 44*7c478bd9Sstevel@tonic-gate 45*7c478bd9Sstevel@tonic-gate #define PL 256 46*7c478bd9Sstevel@tonic-gate #define ESC '\033' 47*7c478bd9Sstevel@tonic-gate #define RLF '\013' 48*7c478bd9Sstevel@tonic-gate #define SI '\017' 49*7c478bd9Sstevel@tonic-gate #define SO '\016' 50*7c478bd9Sstevel@tonic-gate #define GREEK 0200 51*7c478bd9Sstevel@tonic-gate #define LINELN 4096 52*7c478bd9Sstevel@tonic-gate 53*7c478bd9Sstevel@tonic-gate wchar_t *page[PL]; 54*7c478bd9Sstevel@tonic-gate wchar_t lbuff[LINELN], *line; 55*7c478bd9Sstevel@tonic-gate wchar_t ws_blank[2] = {' ', 0}; 56*7c478bd9Sstevel@tonic-gate char esc_chars, underline, temp_off, smart; 57*7c478bd9Sstevel@tonic-gate int bflag, xflag, fflag, pflag; 58*7c478bd9Sstevel@tonic-gate int greeked; 59*7c478bd9Sstevel@tonic-gate int half; 60*7c478bd9Sstevel@tonic-gate int cp, lp; 61*7c478bd9Sstevel@tonic-gate int ll, llh, mustwr; 62*7c478bd9Sstevel@tonic-gate int pcp = 0; 63*7c478bd9Sstevel@tonic-gate char *pgmname; 64*7c478bd9Sstevel@tonic-gate 65*7c478bd9Sstevel@tonic-gate #define USAGEMSG "usage:\tcol [-bfxp]\n" 66*7c478bd9Sstevel@tonic-gate 67*7c478bd9Sstevel@tonic-gate static void outc(wchar_t); 68*7c478bd9Sstevel@tonic-gate static void store(int); 69*7c478bd9Sstevel@tonic-gate static void fetch(int); 70*7c478bd9Sstevel@tonic-gate static void emit(wchar_t *, int); 71*7c478bd9Sstevel@tonic-gate static void incr(void); 72*7c478bd9Sstevel@tonic-gate static void decr(void); 73*7c478bd9Sstevel@tonic-gate static void wsinsert(wchar_t *, int); 74*7c478bd9Sstevel@tonic-gate static int wcscrwidth(wchar_t); 75*7c478bd9Sstevel@tonic-gate 76*7c478bd9Sstevel@tonic-gate int 77*7c478bd9Sstevel@tonic-gate main(int argc, char **argv) 78*7c478bd9Sstevel@tonic-gate { 79*7c478bd9Sstevel@tonic-gate int i, n; 80*7c478bd9Sstevel@tonic-gate int opt; 81*7c478bd9Sstevel@tonic-gate int greek; 82*7c478bd9Sstevel@tonic-gate int c; 83*7c478bd9Sstevel@tonic-gate wchar_t wc; 84*7c478bd9Sstevel@tonic-gate char byte; 85*7c478bd9Sstevel@tonic-gate static char fbuff[BUFSIZ]; 86*7c478bd9Sstevel@tonic-gate 87*7c478bd9Sstevel@tonic-gate setbuf(stdout, fbuff); 88*7c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 89*7c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) 90*7c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" 91*7c478bd9Sstevel@tonic-gate #endif 92*7c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 93*7c478bd9Sstevel@tonic-gate pgmname = argv[0]; 94*7c478bd9Sstevel@tonic-gate 95*7c478bd9Sstevel@tonic-gate while ((opt = getopt(argc, argv, "bfxp")) != EOF) 96*7c478bd9Sstevel@tonic-gate switch (opt) { 97*7c478bd9Sstevel@tonic-gate case 'b': 98*7c478bd9Sstevel@tonic-gate bflag++; 99*7c478bd9Sstevel@tonic-gate break; 100*7c478bd9Sstevel@tonic-gate case 'x': 101*7c478bd9Sstevel@tonic-gate xflag++; 102*7c478bd9Sstevel@tonic-gate break; 103*7c478bd9Sstevel@tonic-gate case 'f': 104*7c478bd9Sstevel@tonic-gate fflag++; 105*7c478bd9Sstevel@tonic-gate break; 106*7c478bd9Sstevel@tonic-gate case 'p': 107*7c478bd9Sstevel@tonic-gate pflag++; 108*7c478bd9Sstevel@tonic-gate break; 109*7c478bd9Sstevel@tonic-gate case '?': 110*7c478bd9Sstevel@tonic-gate default: 111*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(USAGEMSG)); 112*7c478bd9Sstevel@tonic-gate exit(2); 113*7c478bd9Sstevel@tonic-gate } 114*7c478bd9Sstevel@tonic-gate 115*7c478bd9Sstevel@tonic-gate argc -= optind; 116*7c478bd9Sstevel@tonic-gate if (argc >= 1) { 117*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(USAGEMSG)); 118*7c478bd9Sstevel@tonic-gate exit(2); 119*7c478bd9Sstevel@tonic-gate } 120*7c478bd9Sstevel@tonic-gate 121*7c478bd9Sstevel@tonic-gate for (ll = 0; ll < PL; ll++) 122*7c478bd9Sstevel@tonic-gate page[ll] = 0; 123*7c478bd9Sstevel@tonic-gate 124*7c478bd9Sstevel@tonic-gate smart = temp_off = underline = esc_chars = '\0'; 125*7c478bd9Sstevel@tonic-gate cp = 0; 126*7c478bd9Sstevel@tonic-gate ll = 0; 127*7c478bd9Sstevel@tonic-gate greek = 0; 128*7c478bd9Sstevel@tonic-gate mustwr = PL; 129*7c478bd9Sstevel@tonic-gate line = lbuff; 130*7c478bd9Sstevel@tonic-gate 131*7c478bd9Sstevel@tonic-gate while ((c = getwchar()) != EOF) { 132*7c478bd9Sstevel@tonic-gate if (underline && temp_off && c > ' ') { 133*7c478bd9Sstevel@tonic-gate outc(ESC); 134*7c478bd9Sstevel@tonic-gate if (*line) line++; 135*7c478bd9Sstevel@tonic-gate *line++ = 'X'; 136*7c478bd9Sstevel@tonic-gate *line = temp_off = '\0'; 137*7c478bd9Sstevel@tonic-gate } 138*7c478bd9Sstevel@tonic-gate if (c != '\b') 139*7c478bd9Sstevel@tonic-gate if (esc_chars) 140*7c478bd9Sstevel@tonic-gate esc_chars = '\0'; 141*7c478bd9Sstevel@tonic-gate switch (c) { 142*7c478bd9Sstevel@tonic-gate case '\n': 143*7c478bd9Sstevel@tonic-gate if (underline && !temp_off) { 144*7c478bd9Sstevel@tonic-gate if (*line) 145*7c478bd9Sstevel@tonic-gate line++; 146*7c478bd9Sstevel@tonic-gate *line++ = ESC; 147*7c478bd9Sstevel@tonic-gate *line++ = 'Y'; 148*7c478bd9Sstevel@tonic-gate *line = '\0'; 149*7c478bd9Sstevel@tonic-gate temp_off = '1'; 150*7c478bd9Sstevel@tonic-gate } 151*7c478bd9Sstevel@tonic-gate incr(); 152*7c478bd9Sstevel@tonic-gate incr(); 153*7c478bd9Sstevel@tonic-gate cp = 0; 154*7c478bd9Sstevel@tonic-gate continue; 155*7c478bd9Sstevel@tonic-gate 156*7c478bd9Sstevel@tonic-gate case '\0': 157*7c478bd9Sstevel@tonic-gate continue; 158*7c478bd9Sstevel@tonic-gate 159*7c478bd9Sstevel@tonic-gate case ESC: 160*7c478bd9Sstevel@tonic-gate c = getwchar(); 161*7c478bd9Sstevel@tonic-gate switch (c) { 162*7c478bd9Sstevel@tonic-gate case '7': /* reverse full line feed */ 163*7c478bd9Sstevel@tonic-gate decr(); 164*7c478bd9Sstevel@tonic-gate decr(); 165*7c478bd9Sstevel@tonic-gate break; 166*7c478bd9Sstevel@tonic-gate 167*7c478bd9Sstevel@tonic-gate case '8': /* reverse half line feed */ 168*7c478bd9Sstevel@tonic-gate if (fflag) 169*7c478bd9Sstevel@tonic-gate decr(); 170*7c478bd9Sstevel@tonic-gate else { 171*7c478bd9Sstevel@tonic-gate if (--half < -1) { 172*7c478bd9Sstevel@tonic-gate decr(); 173*7c478bd9Sstevel@tonic-gate decr(); 174*7c478bd9Sstevel@tonic-gate half += 2; 175*7c478bd9Sstevel@tonic-gate } 176*7c478bd9Sstevel@tonic-gate } 177*7c478bd9Sstevel@tonic-gate break; 178*7c478bd9Sstevel@tonic-gate 179*7c478bd9Sstevel@tonic-gate case '9': /* forward half line feed */ 180*7c478bd9Sstevel@tonic-gate if (fflag) 181*7c478bd9Sstevel@tonic-gate incr(); 182*7c478bd9Sstevel@tonic-gate else { 183*7c478bd9Sstevel@tonic-gate if (++half > 0) { 184*7c478bd9Sstevel@tonic-gate incr(); 185*7c478bd9Sstevel@tonic-gate incr(); 186*7c478bd9Sstevel@tonic-gate half -= 2; 187*7c478bd9Sstevel@tonic-gate } 188*7c478bd9Sstevel@tonic-gate } 189*7c478bd9Sstevel@tonic-gate break; 190*7c478bd9Sstevel@tonic-gate 191*7c478bd9Sstevel@tonic-gate default: 192*7c478bd9Sstevel@tonic-gate if (pflag) { /* pass through esc */ 193*7c478bd9Sstevel@tonic-gate outc(ESC); 194*7c478bd9Sstevel@tonic-gate line++; 195*7c478bd9Sstevel@tonic-gate *line = c; 196*7c478bd9Sstevel@tonic-gate line++; 197*7c478bd9Sstevel@tonic-gate *line = '\0'; 198*7c478bd9Sstevel@tonic-gate esc_chars = 1; 199*7c478bd9Sstevel@tonic-gate if (c == 'X') 200*7c478bd9Sstevel@tonic-gate underline = 1; 201*7c478bd9Sstevel@tonic-gate if (c == 'Y' && underline) 202*7c478bd9Sstevel@tonic-gate underline = temp_off = '\0'; 203*7c478bd9Sstevel@tonic-gate if (c == ']') 204*7c478bd9Sstevel@tonic-gate smart = 1; 205*7c478bd9Sstevel@tonic-gate if (c == '[') 206*7c478bd9Sstevel@tonic-gate smart = '\0'; 207*7c478bd9Sstevel@tonic-gate } 208*7c478bd9Sstevel@tonic-gate break; 209*7c478bd9Sstevel@tonic-gate } 210*7c478bd9Sstevel@tonic-gate continue; 211*7c478bd9Sstevel@tonic-gate 212*7c478bd9Sstevel@tonic-gate case SO: 213*7c478bd9Sstevel@tonic-gate greek = GREEK; 214*7c478bd9Sstevel@tonic-gate greeked++; 215*7c478bd9Sstevel@tonic-gate continue; 216*7c478bd9Sstevel@tonic-gate 217*7c478bd9Sstevel@tonic-gate case SI: 218*7c478bd9Sstevel@tonic-gate greek = 0; 219*7c478bd9Sstevel@tonic-gate continue; 220*7c478bd9Sstevel@tonic-gate 221*7c478bd9Sstevel@tonic-gate case RLF: 222*7c478bd9Sstevel@tonic-gate decr(); 223*7c478bd9Sstevel@tonic-gate decr(); 224*7c478bd9Sstevel@tonic-gate continue; 225*7c478bd9Sstevel@tonic-gate 226*7c478bd9Sstevel@tonic-gate case '\r': 227*7c478bd9Sstevel@tonic-gate cp = 0; 228*7c478bd9Sstevel@tonic-gate continue; 229*7c478bd9Sstevel@tonic-gate 230*7c478bd9Sstevel@tonic-gate case '\t': 231*7c478bd9Sstevel@tonic-gate cp = (cp + 8) & -8; 232*7c478bd9Sstevel@tonic-gate continue; 233*7c478bd9Sstevel@tonic-gate 234*7c478bd9Sstevel@tonic-gate case '\b': 235*7c478bd9Sstevel@tonic-gate if (esc_chars) { 236*7c478bd9Sstevel@tonic-gate *line++ = '\b'; 237*7c478bd9Sstevel@tonic-gate *line = '\0'; 238*7c478bd9Sstevel@tonic-gate } else if (cp > 0) 239*7c478bd9Sstevel@tonic-gate cp--; 240*7c478bd9Sstevel@tonic-gate continue; 241*7c478bd9Sstevel@tonic-gate 242*7c478bd9Sstevel@tonic-gate case ' ': 243*7c478bd9Sstevel@tonic-gate cp++; 244*7c478bd9Sstevel@tonic-gate continue; 245*7c478bd9Sstevel@tonic-gate 246*7c478bd9Sstevel@tonic-gate default: 247*7c478bd9Sstevel@tonic-gate if (iswprint(c)) { /* if printable */ 248*7c478bd9Sstevel@tonic-gate if (!greek) { 249*7c478bd9Sstevel@tonic-gate outc((wchar_t)c); 250*7c478bd9Sstevel@tonic-gate cp += wcscrwidth(c); 251*7c478bd9Sstevel@tonic-gate } 252*7c478bd9Sstevel@tonic-gate /* 253*7c478bd9Sstevel@tonic-gate * EUC (apply SO only when there can 254*7c478bd9Sstevel@tonic-gate * be corresponding character in CS1) 255*7c478bd9Sstevel@tonic-gate */ 256*7c478bd9Sstevel@tonic-gate else if (iswascii(c)) { 257*7c478bd9Sstevel@tonic-gate byte = (c | greek); 258*7c478bd9Sstevel@tonic-gate n = mbtowc(&wc, &byte, 1); 259*7c478bd9Sstevel@tonic-gate if (!iswcntrl(c) && !iswspace(c) && 260*7c478bd9Sstevel@tonic-gate n == 1) { 261*7c478bd9Sstevel@tonic-gate outc(wc); 262*7c478bd9Sstevel@tonic-gate cp += wcscrwidth(wc); 263*7c478bd9Sstevel@tonic-gate } else { 264*7c478bd9Sstevel@tonic-gate outc((wchar_t)c); 265*7c478bd9Sstevel@tonic-gate cp += wcscrwidth(c); 266*7c478bd9Sstevel@tonic-gate } 267*7c478bd9Sstevel@tonic-gate } else { 268*7c478bd9Sstevel@tonic-gate outc((wchar_t)c); 269*7c478bd9Sstevel@tonic-gate cp += wcscrwidth(c); 270*7c478bd9Sstevel@tonic-gate } 271*7c478bd9Sstevel@tonic-gate 272*7c478bd9Sstevel@tonic-gate if ((cp + 1) > LINELN) { 273*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 274*7c478bd9Sstevel@tonic-gate gettext("col: Line too long\n")); 275*7c478bd9Sstevel@tonic-gate exit(2); 276*7c478bd9Sstevel@tonic-gate } 277*7c478bd9Sstevel@tonic-gate } 278*7c478bd9Sstevel@tonic-gate continue; 279*7c478bd9Sstevel@tonic-gate } 280*7c478bd9Sstevel@tonic-gate } 281*7c478bd9Sstevel@tonic-gate 282*7c478bd9Sstevel@tonic-gate for (i = 0; i < PL; i++) 283*7c478bd9Sstevel@tonic-gate if (page[(mustwr+i)%PL] != 0) 284*7c478bd9Sstevel@tonic-gate emit(page[(mustwr+i) % PL], mustwr+i-PL); 285*7c478bd9Sstevel@tonic-gate emit(ws_blank, (llh + 1) & -2); 286*7c478bd9Sstevel@tonic-gate return (0); 287*7c478bd9Sstevel@tonic-gate } 288*7c478bd9Sstevel@tonic-gate 289*7c478bd9Sstevel@tonic-gate static void 290*7c478bd9Sstevel@tonic-gate outc(wchar_t c) 291*7c478bd9Sstevel@tonic-gate { 292*7c478bd9Sstevel@tonic-gate int n, i; 293*7c478bd9Sstevel@tonic-gate int width, widthl, widthc; 294*7c478bd9Sstevel@tonic-gate wchar_t *p1; 295*7c478bd9Sstevel@tonic-gate wchar_t c1; 296*7c478bd9Sstevel@tonic-gate char esc_chars = '\0'; 297*7c478bd9Sstevel@tonic-gate if (lp > cp) { 298*7c478bd9Sstevel@tonic-gate line = lbuff; 299*7c478bd9Sstevel@tonic-gate lp = 0; 300*7c478bd9Sstevel@tonic-gate } 301*7c478bd9Sstevel@tonic-gate 302*7c478bd9Sstevel@tonic-gate while (lp < cp) { 303*7c478bd9Sstevel@tonic-gate if (*line != '\b') 304*7c478bd9Sstevel@tonic-gate if (esc_chars) 305*7c478bd9Sstevel@tonic-gate esc_chars = '\0'; 306*7c478bd9Sstevel@tonic-gate switch (*line) { 307*7c478bd9Sstevel@tonic-gate case ESC: 308*7c478bd9Sstevel@tonic-gate line++; 309*7c478bd9Sstevel@tonic-gate esc_chars = 1; 310*7c478bd9Sstevel@tonic-gate break; 311*7c478bd9Sstevel@tonic-gate case '\0': 312*7c478bd9Sstevel@tonic-gate *line = ' '; 313*7c478bd9Sstevel@tonic-gate lp++; 314*7c478bd9Sstevel@tonic-gate break; 315*7c478bd9Sstevel@tonic-gate case '\b': 316*7c478bd9Sstevel@tonic-gate /* if ( ! esc_chars ) */ 317*7c478bd9Sstevel@tonic-gate lp--; 318*7c478bd9Sstevel@tonic-gate break; 319*7c478bd9Sstevel@tonic-gate default: 320*7c478bd9Sstevel@tonic-gate lp += wcscrwidth(*line); 321*7c478bd9Sstevel@tonic-gate } 322*7c478bd9Sstevel@tonic-gate line++; 323*7c478bd9Sstevel@tonic-gate } 324*7c478bd9Sstevel@tonic-gate while (*line == '\b') { 325*7c478bd9Sstevel@tonic-gate /* 326*7c478bd9Sstevel@tonic-gate * EUC (For a multi-column character, backspace characters 327*7c478bd9Sstevel@tonic-gate * are assumed to be used like "__^H^HXX", where "XX" 328*7c478bd9Sstevel@tonic-gate * represents a two-column character, and a backspace 329*7c478bd9Sstevel@tonic-gate * always goes back by one column.) 330*7c478bd9Sstevel@tonic-gate */ 331*7c478bd9Sstevel@tonic-gate for (n = 0; *line == '\b'; line++) { 332*7c478bd9Sstevel@tonic-gate n++; 333*7c478bd9Sstevel@tonic-gate lp--; 334*7c478bd9Sstevel@tonic-gate } 335*7c478bd9Sstevel@tonic-gate while (n > 0 && lp < cp) { 336*7c478bd9Sstevel@tonic-gate i = *line++; 337*7c478bd9Sstevel@tonic-gate i = wcscrwidth(i); 338*7c478bd9Sstevel@tonic-gate n -= i; 339*7c478bd9Sstevel@tonic-gate lp += i; 340*7c478bd9Sstevel@tonic-gate } 341*7c478bd9Sstevel@tonic-gate } 342*7c478bd9Sstevel@tonic-gate while (*line == ESC) 343*7c478bd9Sstevel@tonic-gate line += 6; 344*7c478bd9Sstevel@tonic-gate widthc = wcscrwidth(c); 345*7c478bd9Sstevel@tonic-gate widthl = wcscrwidth(*line); 346*7c478bd9Sstevel@tonic-gate if (bflag || (*line == '\0') || *line == ' ') { 347*7c478bd9Sstevel@tonic-gate if (*line == '\0' || widthl == widthc) { 348*7c478bd9Sstevel@tonic-gate *line = c; 349*7c478bd9Sstevel@tonic-gate } else if (widthl > widthc) { 350*7c478bd9Sstevel@tonic-gate n = widthl - widthc; 351*7c478bd9Sstevel@tonic-gate wsinsert(line, n); 352*7c478bd9Sstevel@tonic-gate *line++ = c; 353*7c478bd9Sstevel@tonic-gate for (i = 0; i < n; i++) 354*7c478bd9Sstevel@tonic-gate *line++ = ' '; 355*7c478bd9Sstevel@tonic-gate line = lbuff; 356*7c478bd9Sstevel@tonic-gate lp = 0; 357*7c478bd9Sstevel@tonic-gate } else { 358*7c478bd9Sstevel@tonic-gate n = widthc - widthl; 359*7c478bd9Sstevel@tonic-gate for (p1 = line+1; n > 0; n -= wcscrwidth(i)) 360*7c478bd9Sstevel@tonic-gate i = *p1++; 361*7c478bd9Sstevel@tonic-gate *line = c; 362*7c478bd9Sstevel@tonic-gate (void) wcscpy(line+1, p1); 363*7c478bd9Sstevel@tonic-gate 364*7c478bd9Sstevel@tonic-gate } 365*7c478bd9Sstevel@tonic-gate } else { 366*7c478bd9Sstevel@tonic-gate if (smart && (widthl == 1) && (widthc == 1)) { 367*7c478bd9Sstevel@tonic-gate wchar_t c1, c2, c3, c4, c5, c6, c7; 368*7c478bd9Sstevel@tonic-gate c1 = *++line; 369*7c478bd9Sstevel@tonic-gate *line++ = ESC; 370*7c478bd9Sstevel@tonic-gate c2 = *line; 371*7c478bd9Sstevel@tonic-gate *line++ = '['; 372*7c478bd9Sstevel@tonic-gate c3 = *line; 373*7c478bd9Sstevel@tonic-gate *line++ = '\b'; 374*7c478bd9Sstevel@tonic-gate c4 = *line; 375*7c478bd9Sstevel@tonic-gate *line++ = ESC; 376*7c478bd9Sstevel@tonic-gate c5 = *line; 377*7c478bd9Sstevel@tonic-gate *line++ = ']'; 378*7c478bd9Sstevel@tonic-gate c6 = *line; 379*7c478bd9Sstevel@tonic-gate *line++ = c; 380*7c478bd9Sstevel@tonic-gate while (c1) { 381*7c478bd9Sstevel@tonic-gate c7 = *line; 382*7c478bd9Sstevel@tonic-gate *line++ = c1; 383*7c478bd9Sstevel@tonic-gate c1 = c2; 384*7c478bd9Sstevel@tonic-gate c2 = c3; 385*7c478bd9Sstevel@tonic-gate c3 = c4; 386*7c478bd9Sstevel@tonic-gate c4 = c5; 387*7c478bd9Sstevel@tonic-gate c5 = c6; 388*7c478bd9Sstevel@tonic-gate c6 = c7; 389*7c478bd9Sstevel@tonic-gate } 390*7c478bd9Sstevel@tonic-gate } else { 391*7c478bd9Sstevel@tonic-gate if ((widthl == 1) && (widthc == 1)) { 392*7c478bd9Sstevel@tonic-gate wchar_t c1, c2, c3; 393*7c478bd9Sstevel@tonic-gate c1 = *++line; 394*7c478bd9Sstevel@tonic-gate *line++ = '\b'; 395*7c478bd9Sstevel@tonic-gate c2 = *line; 396*7c478bd9Sstevel@tonic-gate *line++ = c; 397*7c478bd9Sstevel@tonic-gate while (c1) { 398*7c478bd9Sstevel@tonic-gate c3 = *line; 399*7c478bd9Sstevel@tonic-gate *line++ = c1; 400*7c478bd9Sstevel@tonic-gate c1 = c2; 401*7c478bd9Sstevel@tonic-gate c2 = c3; 402*7c478bd9Sstevel@tonic-gate } 403*7c478bd9Sstevel@tonic-gate } else { 404*7c478bd9Sstevel@tonic-gate width = (widthc > widthl) ? widthc : widthl; 405*7c478bd9Sstevel@tonic-gate for (i = 0; i < width; i += wcscrwidth(c1)) 406*7c478bd9Sstevel@tonic-gate c1 = *line++; 407*7c478bd9Sstevel@tonic-gate wsinsert(line, width + (width - widthc + 1)); 408*7c478bd9Sstevel@tonic-gate for (i = 0; i < width; i++) 409*7c478bd9Sstevel@tonic-gate *line++ = '\b'; 410*7c478bd9Sstevel@tonic-gate *line++ = c; 411*7c478bd9Sstevel@tonic-gate for (i = widthc; i < width; i++) 412*7c478bd9Sstevel@tonic-gate *line++ = ' '; 413*7c478bd9Sstevel@tonic-gate } 414*7c478bd9Sstevel@tonic-gate } 415*7c478bd9Sstevel@tonic-gate lp = 0; 416*7c478bd9Sstevel@tonic-gate line = lbuff; 417*7c478bd9Sstevel@tonic-gate } 418*7c478bd9Sstevel@tonic-gate } 419*7c478bd9Sstevel@tonic-gate 420*7c478bd9Sstevel@tonic-gate static void 421*7c478bd9Sstevel@tonic-gate store(int lno) 422*7c478bd9Sstevel@tonic-gate { 423*7c478bd9Sstevel@tonic-gate lno %= PL; 424*7c478bd9Sstevel@tonic-gate if (page[lno] != 0) 425*7c478bd9Sstevel@tonic-gate free((char *)page[lno]); 426*7c478bd9Sstevel@tonic-gate page[lno] = (wchar_t *)malloc((unsigned)(wcslen(lbuff) + 2) 427*7c478bd9Sstevel@tonic-gate * sizeof (wchar_t)); 428*7c478bd9Sstevel@tonic-gate if (page[lno] == 0) { 429*7c478bd9Sstevel@tonic-gate /* fprintf(stderr, "%s: no storage\n", pgmname); */ 430*7c478bd9Sstevel@tonic-gate exit(2); 431*7c478bd9Sstevel@tonic-gate } 432*7c478bd9Sstevel@tonic-gate (void) wcscpy(page[lno], lbuff); 433*7c478bd9Sstevel@tonic-gate } 434*7c478bd9Sstevel@tonic-gate 435*7c478bd9Sstevel@tonic-gate static void 436*7c478bd9Sstevel@tonic-gate fetch(int lno) 437*7c478bd9Sstevel@tonic-gate { 438*7c478bd9Sstevel@tonic-gate wchar_t *p; 439*7c478bd9Sstevel@tonic-gate 440*7c478bd9Sstevel@tonic-gate lno %= PL; 441*7c478bd9Sstevel@tonic-gate p = lbuff; 442*7c478bd9Sstevel@tonic-gate while (*p) 443*7c478bd9Sstevel@tonic-gate *p++ = '\0'; 444*7c478bd9Sstevel@tonic-gate line = lbuff; 445*7c478bd9Sstevel@tonic-gate lp = 0; 446*7c478bd9Sstevel@tonic-gate if (page[lno]) 447*7c478bd9Sstevel@tonic-gate (void) wcscpy(line, page[lno]); 448*7c478bd9Sstevel@tonic-gate } 449*7c478bd9Sstevel@tonic-gate 450*7c478bd9Sstevel@tonic-gate static void 451*7c478bd9Sstevel@tonic-gate emit(wchar_t *s, int lineno) 452*7c478bd9Sstevel@tonic-gate { 453*7c478bd9Sstevel@tonic-gate static int cline = 0; 454*7c478bd9Sstevel@tonic-gate int ncp; 455*7c478bd9Sstevel@tonic-gate wchar_t *p; 456*7c478bd9Sstevel@tonic-gate char cshifted; 457*7c478bd9Sstevel@tonic-gate char chr[MB_LEN_MAX + 1]; 458*7c478bd9Sstevel@tonic-gate 459*7c478bd9Sstevel@tonic-gate int c; 460*7c478bd9Sstevel@tonic-gate static int gflag = 0; 461*7c478bd9Sstevel@tonic-gate 462*7c478bd9Sstevel@tonic-gate if (*s) { 463*7c478bd9Sstevel@tonic-gate if (gflag) { 464*7c478bd9Sstevel@tonic-gate (void) putchar(SI); 465*7c478bd9Sstevel@tonic-gate gflag = 0; 466*7c478bd9Sstevel@tonic-gate } 467*7c478bd9Sstevel@tonic-gate while (cline < lineno - 1) { 468*7c478bd9Sstevel@tonic-gate (void) putchar('\n'); 469*7c478bd9Sstevel@tonic-gate pcp = 0; 470*7c478bd9Sstevel@tonic-gate cline += 2; 471*7c478bd9Sstevel@tonic-gate } 472*7c478bd9Sstevel@tonic-gate if (cline != lineno) { 473*7c478bd9Sstevel@tonic-gate (void) putchar(ESC); 474*7c478bd9Sstevel@tonic-gate (void) putchar('9'); 475*7c478bd9Sstevel@tonic-gate cline++; 476*7c478bd9Sstevel@tonic-gate } 477*7c478bd9Sstevel@tonic-gate if (pcp) 478*7c478bd9Sstevel@tonic-gate (void) putchar('\r'); 479*7c478bd9Sstevel@tonic-gate pcp = 0; 480*7c478bd9Sstevel@tonic-gate p = s; 481*7c478bd9Sstevel@tonic-gate while (*p) { 482*7c478bd9Sstevel@tonic-gate ncp = pcp; 483*7c478bd9Sstevel@tonic-gate while (*p++ == ' ') { 484*7c478bd9Sstevel@tonic-gate if ((++ncp & 7) == 0 && !xflag) { 485*7c478bd9Sstevel@tonic-gate pcp = ncp; 486*7c478bd9Sstevel@tonic-gate (void) putchar('\t'); 487*7c478bd9Sstevel@tonic-gate } 488*7c478bd9Sstevel@tonic-gate } 489*7c478bd9Sstevel@tonic-gate if (!*--p) 490*7c478bd9Sstevel@tonic-gate break; 491*7c478bd9Sstevel@tonic-gate while (pcp < ncp) { 492*7c478bd9Sstevel@tonic-gate (void) putchar(' '); 493*7c478bd9Sstevel@tonic-gate pcp++; 494*7c478bd9Sstevel@tonic-gate } 495*7c478bd9Sstevel@tonic-gate if (greeked) { 496*7c478bd9Sstevel@tonic-gate if (wctomb(chr, *p) == 1) { 497*7c478bd9Sstevel@tonic-gate if (gflag != (*chr & GREEK) && 498*7c478bd9Sstevel@tonic-gate *p != '\b' && 499*7c478bd9Sstevel@tonic-gate isascii(*chr ^ (gflag ^ GREEK)) && 500*7c478bd9Sstevel@tonic-gate !iscntrl(*chr ^ (gflag ^ GREEK)) && 501*7c478bd9Sstevel@tonic-gate !isspace(*chr ^ (gflag ^ GREEK))) { 502*7c478bd9Sstevel@tonic-gate if (gflag) 503*7c478bd9Sstevel@tonic-gate (void) putchar(SI); 504*7c478bd9Sstevel@tonic-gate else 505*7c478bd9Sstevel@tonic-gate (void) putchar(SO); 506*7c478bd9Sstevel@tonic-gate gflag ^= GREEK; 507*7c478bd9Sstevel@tonic-gate } 508*7c478bd9Sstevel@tonic-gate } 509*7c478bd9Sstevel@tonic-gate } 510*7c478bd9Sstevel@tonic-gate c = *p; 511*7c478bd9Sstevel@tonic-gate if (greeked) { 512*7c478bd9Sstevel@tonic-gate if (wctomb(chr, (wchar_t)c) == 1) { 513*7c478bd9Sstevel@tonic-gate cshifted = (*chr ^ GREEK); 514*7c478bd9Sstevel@tonic-gate if (isascii(cshifted) && 515*7c478bd9Sstevel@tonic-gate !iscntrl(cshifted) && 516*7c478bd9Sstevel@tonic-gate !isspace(cshifted)) 517*7c478bd9Sstevel@tonic-gate (void) putchar(*chr & ~GREEK); 518*7c478bd9Sstevel@tonic-gate } else 519*7c478bd9Sstevel@tonic-gate (void) putwchar(c); 520*7c478bd9Sstevel@tonic-gate } else 521*7c478bd9Sstevel@tonic-gate (void) putwchar(c); 522*7c478bd9Sstevel@tonic-gate if (c == '\b') { 523*7c478bd9Sstevel@tonic-gate if (*(p-2) && *(p-2) == ESC) { 524*7c478bd9Sstevel@tonic-gate pcp++; 525*7c478bd9Sstevel@tonic-gate } else 526*7c478bd9Sstevel@tonic-gate pcp--; 527*7c478bd9Sstevel@tonic-gate } else { 528*7c478bd9Sstevel@tonic-gate pcp += wcscrwidth(c); 529*7c478bd9Sstevel@tonic-gate } 530*7c478bd9Sstevel@tonic-gate p++; 531*7c478bd9Sstevel@tonic-gate } 532*7c478bd9Sstevel@tonic-gate } 533*7c478bd9Sstevel@tonic-gate } 534*7c478bd9Sstevel@tonic-gate 535*7c478bd9Sstevel@tonic-gate static void 536*7c478bd9Sstevel@tonic-gate incr(void) 537*7c478bd9Sstevel@tonic-gate { 538*7c478bd9Sstevel@tonic-gate store(ll++); 539*7c478bd9Sstevel@tonic-gate if (ll > llh) 540*7c478bd9Sstevel@tonic-gate llh = ll; 541*7c478bd9Sstevel@tonic-gate if (ll >= mustwr && page[ll%PL]) { 542*7c478bd9Sstevel@tonic-gate emit(page[ll%PL], ll - PL); 543*7c478bd9Sstevel@tonic-gate mustwr++; 544*7c478bd9Sstevel@tonic-gate free((char *)page[ll%PL]); 545*7c478bd9Sstevel@tonic-gate page[ll%PL] = 0; 546*7c478bd9Sstevel@tonic-gate } 547*7c478bd9Sstevel@tonic-gate fetch(ll); 548*7c478bd9Sstevel@tonic-gate } 549*7c478bd9Sstevel@tonic-gate 550*7c478bd9Sstevel@tonic-gate static void 551*7c478bd9Sstevel@tonic-gate decr(void) 552*7c478bd9Sstevel@tonic-gate { 553*7c478bd9Sstevel@tonic-gate if (ll > mustwr - PL) { 554*7c478bd9Sstevel@tonic-gate store(ll--); 555*7c478bd9Sstevel@tonic-gate fetch(ll); 556*7c478bd9Sstevel@tonic-gate } 557*7c478bd9Sstevel@tonic-gate } 558*7c478bd9Sstevel@tonic-gate 559*7c478bd9Sstevel@tonic-gate static void 560*7c478bd9Sstevel@tonic-gate wsinsert(wchar_t *s, int n) 561*7c478bd9Sstevel@tonic-gate { 562*7c478bd9Sstevel@tonic-gate wchar_t *p1, *p2; 563*7c478bd9Sstevel@tonic-gate 564*7c478bd9Sstevel@tonic-gate 565*7c478bd9Sstevel@tonic-gate p1 = s + wcslen(s); 566*7c478bd9Sstevel@tonic-gate p2 = p1 + n; 567*7c478bd9Sstevel@tonic-gate while (p1 >= s) 568*7c478bd9Sstevel@tonic-gate *p2-- = *p1--; 569*7c478bd9Sstevel@tonic-gate } 570*7c478bd9Sstevel@tonic-gate 571*7c478bd9Sstevel@tonic-gate static int 572*7c478bd9Sstevel@tonic-gate wcscrwidth(wchar_t wc) 573*7c478bd9Sstevel@tonic-gate { 574*7c478bd9Sstevel@tonic-gate int nc; 575*7c478bd9Sstevel@tonic-gate 576*7c478bd9Sstevel@tonic-gate if (wc == 0) { 577*7c478bd9Sstevel@tonic-gate /* 578*7c478bd9Sstevel@tonic-gate * if wc is a null character, needs to 579*7c478bd9Sstevel@tonic-gate * return 1 instead of 0. 580*7c478bd9Sstevel@tonic-gate */ 581*7c478bd9Sstevel@tonic-gate return (1); 582*7c478bd9Sstevel@tonic-gate } 583*7c478bd9Sstevel@tonic-gate nc = wcwidth(wc); 584*7c478bd9Sstevel@tonic-gate if (nc > 0) { 585*7c478bd9Sstevel@tonic-gate return (nc); 586*7c478bd9Sstevel@tonic-gate } else { 587*7c478bd9Sstevel@tonic-gate return (0); 588*7c478bd9Sstevel@tonic-gate } 589*7c478bd9Sstevel@tonic-gate } 590