17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*337314b1Sas145665 * Common Development and Distribution License (the "License"). 6*337314b1Sas145665 * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 21*337314b1Sas145665 227c478bd9Sstevel@tonic-gate /* 23*337314b1Sas145665 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 24*337314b1Sas145665 * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 287c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 297c478bd9Sstevel@tonic-gate 307c478bd9Sstevel@tonic-gate 317c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 327c478bd9Sstevel@tonic-gate /* 337c478bd9Sstevel@tonic-gate * col - filter reverse carraige motions 347c478bd9Sstevel@tonic-gate * 357c478bd9Sstevel@tonic-gate */ 367c478bd9Sstevel@tonic-gate 377c478bd9Sstevel@tonic-gate 387c478bd9Sstevel@tonic-gate #include <stdio.h> 397c478bd9Sstevel@tonic-gate #include <ctype.h> 407c478bd9Sstevel@tonic-gate #include <locale.h> 417c478bd9Sstevel@tonic-gate #include <limits.h> 427c478bd9Sstevel@tonic-gate #include <stdlib.h> 437c478bd9Sstevel@tonic-gate #include <wctype.h> 447c478bd9Sstevel@tonic-gate 457c478bd9Sstevel@tonic-gate #define PL 256 467c478bd9Sstevel@tonic-gate #define ESC '\033' 477c478bd9Sstevel@tonic-gate #define RLF '\013' 487c478bd9Sstevel@tonic-gate #define SI '\017' 497c478bd9Sstevel@tonic-gate #define SO '\016' 507c478bd9Sstevel@tonic-gate #define GREEK 0200 517c478bd9Sstevel@tonic-gate #define LINELN 4096 527c478bd9Sstevel@tonic-gate 537c478bd9Sstevel@tonic-gate wchar_t *page[PL]; 547c478bd9Sstevel@tonic-gate wchar_t lbuff[LINELN], *line; 55*337314b1Sas145665 wchar_t *lbuffend = lbuff + LINELN - 1; 567c478bd9Sstevel@tonic-gate wchar_t ws_blank[2] = {' ', 0}; 577c478bd9Sstevel@tonic-gate char esc_chars, underline, temp_off, smart; 587c478bd9Sstevel@tonic-gate int bflag, xflag, fflag, pflag; 597c478bd9Sstevel@tonic-gate int greeked; 607c478bd9Sstevel@tonic-gate int half; 617c478bd9Sstevel@tonic-gate int cp, lp; 627c478bd9Sstevel@tonic-gate int ll, llh, mustwr; 637c478bd9Sstevel@tonic-gate int pcp = 0; 647c478bd9Sstevel@tonic-gate char *pgmname; 657c478bd9Sstevel@tonic-gate 667c478bd9Sstevel@tonic-gate #define USAGEMSG "usage:\tcol [-bfxp]\n" 677c478bd9Sstevel@tonic-gate 687c478bd9Sstevel@tonic-gate static void outc(wchar_t); 697c478bd9Sstevel@tonic-gate static void store(int); 707c478bd9Sstevel@tonic-gate static void fetch(int); 717c478bd9Sstevel@tonic-gate static void emit(wchar_t *, int); 727c478bd9Sstevel@tonic-gate static void incr(void); 737c478bd9Sstevel@tonic-gate static void decr(void); 747c478bd9Sstevel@tonic-gate static void wsinsert(wchar_t *, int); 75*337314b1Sas145665 static void incr_line(int); 767c478bd9Sstevel@tonic-gate static int wcscrwidth(wchar_t); 777c478bd9Sstevel@tonic-gate 787c478bd9Sstevel@tonic-gate int 797c478bd9Sstevel@tonic-gate main(int argc, char **argv) 807c478bd9Sstevel@tonic-gate { 817c478bd9Sstevel@tonic-gate int i, n; 827c478bd9Sstevel@tonic-gate int opt; 837c478bd9Sstevel@tonic-gate int greek; 847c478bd9Sstevel@tonic-gate int c; 857c478bd9Sstevel@tonic-gate wchar_t wc; 867c478bd9Sstevel@tonic-gate char byte; 877c478bd9Sstevel@tonic-gate static char fbuff[BUFSIZ]; 887c478bd9Sstevel@tonic-gate 897c478bd9Sstevel@tonic-gate setbuf(stdout, fbuff); 907c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 917c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) 927c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" 937c478bd9Sstevel@tonic-gate #endif 947c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 957c478bd9Sstevel@tonic-gate pgmname = argv[0]; 967c478bd9Sstevel@tonic-gate 977c478bd9Sstevel@tonic-gate while ((opt = getopt(argc, argv, "bfxp")) != EOF) 987c478bd9Sstevel@tonic-gate switch (opt) { 997c478bd9Sstevel@tonic-gate case 'b': 1007c478bd9Sstevel@tonic-gate bflag++; 1017c478bd9Sstevel@tonic-gate break; 1027c478bd9Sstevel@tonic-gate case 'x': 1037c478bd9Sstevel@tonic-gate xflag++; 1047c478bd9Sstevel@tonic-gate break; 1057c478bd9Sstevel@tonic-gate case 'f': 1067c478bd9Sstevel@tonic-gate fflag++; 1077c478bd9Sstevel@tonic-gate break; 1087c478bd9Sstevel@tonic-gate case 'p': 1097c478bd9Sstevel@tonic-gate pflag++; 1107c478bd9Sstevel@tonic-gate break; 1117c478bd9Sstevel@tonic-gate case '?': 1127c478bd9Sstevel@tonic-gate default: 1137c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(USAGEMSG)); 1147c478bd9Sstevel@tonic-gate exit(2); 1157c478bd9Sstevel@tonic-gate } 1167c478bd9Sstevel@tonic-gate 1177c478bd9Sstevel@tonic-gate argc -= optind; 1187c478bd9Sstevel@tonic-gate if (argc >= 1) { 1197c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(USAGEMSG)); 1207c478bd9Sstevel@tonic-gate exit(2); 1217c478bd9Sstevel@tonic-gate } 1227c478bd9Sstevel@tonic-gate 1237c478bd9Sstevel@tonic-gate for (ll = 0; ll < PL; ll++) 1247c478bd9Sstevel@tonic-gate page[ll] = 0; 1257c478bd9Sstevel@tonic-gate 1267c478bd9Sstevel@tonic-gate smart = temp_off = underline = esc_chars = '\0'; 1277c478bd9Sstevel@tonic-gate cp = 0; 1287c478bd9Sstevel@tonic-gate ll = 0; 1297c478bd9Sstevel@tonic-gate greek = 0; 1307c478bd9Sstevel@tonic-gate mustwr = PL; 1317c478bd9Sstevel@tonic-gate line = lbuff; 1327c478bd9Sstevel@tonic-gate 1337c478bd9Sstevel@tonic-gate while ((c = getwchar()) != EOF) { 1347c478bd9Sstevel@tonic-gate if (underline && temp_off && c > ' ') { 1357c478bd9Sstevel@tonic-gate outc(ESC); 136*337314b1Sas145665 if (*line) { 137*337314b1Sas145665 incr_line(1); 138*337314b1Sas145665 } 139*337314b1Sas145665 *line = 'X'; 140*337314b1Sas145665 incr_line(1); 1417c478bd9Sstevel@tonic-gate *line = temp_off = '\0'; 1427c478bd9Sstevel@tonic-gate } 1437c478bd9Sstevel@tonic-gate if (c != '\b') 1447c478bd9Sstevel@tonic-gate if (esc_chars) 1457c478bd9Sstevel@tonic-gate esc_chars = '\0'; 1467c478bd9Sstevel@tonic-gate switch (c) { 1477c478bd9Sstevel@tonic-gate case '\n': 1487c478bd9Sstevel@tonic-gate if (underline && !temp_off) { 1497c478bd9Sstevel@tonic-gate if (*line) 150*337314b1Sas145665 incr_line(1); 151*337314b1Sas145665 *line = ESC; 152*337314b1Sas145665 incr_line(1); 153*337314b1Sas145665 *line = 'Y'; 154*337314b1Sas145665 incr_line(1); 1557c478bd9Sstevel@tonic-gate *line = '\0'; 1567c478bd9Sstevel@tonic-gate temp_off = '1'; 1577c478bd9Sstevel@tonic-gate } 1587c478bd9Sstevel@tonic-gate incr(); 1597c478bd9Sstevel@tonic-gate incr(); 1607c478bd9Sstevel@tonic-gate cp = 0; 1617c478bd9Sstevel@tonic-gate continue; 1627c478bd9Sstevel@tonic-gate 1637c478bd9Sstevel@tonic-gate case '\0': 1647c478bd9Sstevel@tonic-gate continue; 1657c478bd9Sstevel@tonic-gate 1667c478bd9Sstevel@tonic-gate case ESC: 1677c478bd9Sstevel@tonic-gate c = getwchar(); 1687c478bd9Sstevel@tonic-gate switch (c) { 1697c478bd9Sstevel@tonic-gate case '7': /* reverse full line feed */ 1707c478bd9Sstevel@tonic-gate decr(); 1717c478bd9Sstevel@tonic-gate decr(); 1727c478bd9Sstevel@tonic-gate break; 1737c478bd9Sstevel@tonic-gate 1747c478bd9Sstevel@tonic-gate case '8': /* reverse half line feed */ 1757c478bd9Sstevel@tonic-gate if (fflag) 1767c478bd9Sstevel@tonic-gate decr(); 1777c478bd9Sstevel@tonic-gate else { 1787c478bd9Sstevel@tonic-gate if (--half < -1) { 1797c478bd9Sstevel@tonic-gate decr(); 1807c478bd9Sstevel@tonic-gate decr(); 1817c478bd9Sstevel@tonic-gate half += 2; 1827c478bd9Sstevel@tonic-gate } 1837c478bd9Sstevel@tonic-gate } 1847c478bd9Sstevel@tonic-gate break; 1857c478bd9Sstevel@tonic-gate 1867c478bd9Sstevel@tonic-gate case '9': /* forward half line feed */ 1877c478bd9Sstevel@tonic-gate if (fflag) 1887c478bd9Sstevel@tonic-gate incr(); 1897c478bd9Sstevel@tonic-gate else { 1907c478bd9Sstevel@tonic-gate if (++half > 0) { 1917c478bd9Sstevel@tonic-gate incr(); 1927c478bd9Sstevel@tonic-gate incr(); 1937c478bd9Sstevel@tonic-gate half -= 2; 1947c478bd9Sstevel@tonic-gate } 1957c478bd9Sstevel@tonic-gate } 1967c478bd9Sstevel@tonic-gate break; 1977c478bd9Sstevel@tonic-gate 1987c478bd9Sstevel@tonic-gate default: 1997c478bd9Sstevel@tonic-gate if (pflag) { /* pass through esc */ 2007c478bd9Sstevel@tonic-gate outc(ESC); 201*337314b1Sas145665 incr_line(1); 2027c478bd9Sstevel@tonic-gate *line = c; 203*337314b1Sas145665 incr_line(1); 2047c478bd9Sstevel@tonic-gate *line = '\0'; 2057c478bd9Sstevel@tonic-gate esc_chars = 1; 2067c478bd9Sstevel@tonic-gate if (c == 'X') 2077c478bd9Sstevel@tonic-gate underline = 1; 2087c478bd9Sstevel@tonic-gate if (c == 'Y' && underline) 2097c478bd9Sstevel@tonic-gate underline = temp_off = '\0'; 2107c478bd9Sstevel@tonic-gate if (c == ']') 2117c478bd9Sstevel@tonic-gate smart = 1; 2127c478bd9Sstevel@tonic-gate if (c == '[') 2137c478bd9Sstevel@tonic-gate smart = '\0'; 2147c478bd9Sstevel@tonic-gate } 2157c478bd9Sstevel@tonic-gate break; 2167c478bd9Sstevel@tonic-gate } 2177c478bd9Sstevel@tonic-gate continue; 2187c478bd9Sstevel@tonic-gate 2197c478bd9Sstevel@tonic-gate case SO: 2207c478bd9Sstevel@tonic-gate greek = GREEK; 2217c478bd9Sstevel@tonic-gate greeked++; 2227c478bd9Sstevel@tonic-gate continue; 2237c478bd9Sstevel@tonic-gate 2247c478bd9Sstevel@tonic-gate case SI: 2257c478bd9Sstevel@tonic-gate greek = 0; 2267c478bd9Sstevel@tonic-gate continue; 2277c478bd9Sstevel@tonic-gate 2287c478bd9Sstevel@tonic-gate case RLF: 2297c478bd9Sstevel@tonic-gate decr(); 2307c478bd9Sstevel@tonic-gate decr(); 2317c478bd9Sstevel@tonic-gate continue; 2327c478bd9Sstevel@tonic-gate 2337c478bd9Sstevel@tonic-gate case '\r': 2347c478bd9Sstevel@tonic-gate cp = 0; 2357c478bd9Sstevel@tonic-gate continue; 2367c478bd9Sstevel@tonic-gate 2377c478bd9Sstevel@tonic-gate case '\t': 2387c478bd9Sstevel@tonic-gate cp = (cp + 8) & -8; 2397c478bd9Sstevel@tonic-gate continue; 2407c478bd9Sstevel@tonic-gate 2417c478bd9Sstevel@tonic-gate case '\b': 2427c478bd9Sstevel@tonic-gate if (esc_chars) { 243*337314b1Sas145665 *line = '\b'; 244*337314b1Sas145665 incr_line(1); 2457c478bd9Sstevel@tonic-gate *line = '\0'; 2467c478bd9Sstevel@tonic-gate } else if (cp > 0) 2477c478bd9Sstevel@tonic-gate cp--; 2487c478bd9Sstevel@tonic-gate continue; 2497c478bd9Sstevel@tonic-gate 2507c478bd9Sstevel@tonic-gate case ' ': 2517c478bd9Sstevel@tonic-gate cp++; 2527c478bd9Sstevel@tonic-gate continue; 2537c478bd9Sstevel@tonic-gate 2547c478bd9Sstevel@tonic-gate default: 2557c478bd9Sstevel@tonic-gate if (iswprint(c)) { /* if printable */ 2567c478bd9Sstevel@tonic-gate if (!greek) { 2577c478bd9Sstevel@tonic-gate outc((wchar_t)c); 2587c478bd9Sstevel@tonic-gate cp += wcscrwidth(c); 2597c478bd9Sstevel@tonic-gate } 2607c478bd9Sstevel@tonic-gate /* 2617c478bd9Sstevel@tonic-gate * EUC (apply SO only when there can 2627c478bd9Sstevel@tonic-gate * be corresponding character in CS1) 2637c478bd9Sstevel@tonic-gate */ 2647c478bd9Sstevel@tonic-gate else if (iswascii(c)) { 2657c478bd9Sstevel@tonic-gate byte = (c | greek); 2667c478bd9Sstevel@tonic-gate n = mbtowc(&wc, &byte, 1); 2677c478bd9Sstevel@tonic-gate if (!iswcntrl(c) && !iswspace(c) && 2687c478bd9Sstevel@tonic-gate n == 1) { 2697c478bd9Sstevel@tonic-gate outc(wc); 2707c478bd9Sstevel@tonic-gate cp += wcscrwidth(wc); 2717c478bd9Sstevel@tonic-gate } else { 2727c478bd9Sstevel@tonic-gate outc((wchar_t)c); 2737c478bd9Sstevel@tonic-gate cp += wcscrwidth(c); 2747c478bd9Sstevel@tonic-gate } 2757c478bd9Sstevel@tonic-gate } else { 2767c478bd9Sstevel@tonic-gate outc((wchar_t)c); 2777c478bd9Sstevel@tonic-gate cp += wcscrwidth(c); 2787c478bd9Sstevel@tonic-gate } 2797c478bd9Sstevel@tonic-gate 2807c478bd9Sstevel@tonic-gate if ((cp + 1) > LINELN) { 2817c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 2827c478bd9Sstevel@tonic-gate gettext("col: Line too long\n")); 2837c478bd9Sstevel@tonic-gate exit(2); 2847c478bd9Sstevel@tonic-gate } 2857c478bd9Sstevel@tonic-gate } 2867c478bd9Sstevel@tonic-gate continue; 2877c478bd9Sstevel@tonic-gate } 2887c478bd9Sstevel@tonic-gate } 2897c478bd9Sstevel@tonic-gate 2907c478bd9Sstevel@tonic-gate for (i = 0; i < PL; i++) 2917c478bd9Sstevel@tonic-gate if (page[(mustwr+i)%PL] != 0) 2927c478bd9Sstevel@tonic-gate emit(page[(mustwr+i) % PL], mustwr+i-PL); 2937c478bd9Sstevel@tonic-gate emit(ws_blank, (llh + 1) & -2); 2947c478bd9Sstevel@tonic-gate return (0); 2957c478bd9Sstevel@tonic-gate } 2967c478bd9Sstevel@tonic-gate 2977c478bd9Sstevel@tonic-gate static void 2987c478bd9Sstevel@tonic-gate outc(wchar_t c) 2997c478bd9Sstevel@tonic-gate { 3007c478bd9Sstevel@tonic-gate int n, i; 3017c478bd9Sstevel@tonic-gate int width, widthl, widthc; 3027c478bd9Sstevel@tonic-gate wchar_t *p1; 3037c478bd9Sstevel@tonic-gate wchar_t c1; 3047c478bd9Sstevel@tonic-gate char esc_chars = '\0'; 3057c478bd9Sstevel@tonic-gate if (lp > cp) { 3067c478bd9Sstevel@tonic-gate line = lbuff; 3077c478bd9Sstevel@tonic-gate lp = 0; 3087c478bd9Sstevel@tonic-gate } 3097c478bd9Sstevel@tonic-gate 3107c478bd9Sstevel@tonic-gate while (lp < cp) { 3117c478bd9Sstevel@tonic-gate if (*line != '\b') 3127c478bd9Sstevel@tonic-gate if (esc_chars) 3137c478bd9Sstevel@tonic-gate esc_chars = '\0'; 3147c478bd9Sstevel@tonic-gate switch (*line) { 3157c478bd9Sstevel@tonic-gate case ESC: 316*337314b1Sas145665 incr_line(1); 3177c478bd9Sstevel@tonic-gate esc_chars = 1; 3187c478bd9Sstevel@tonic-gate break; 3197c478bd9Sstevel@tonic-gate case '\0': 3207c478bd9Sstevel@tonic-gate *line = ' '; 3217c478bd9Sstevel@tonic-gate lp++; 3227c478bd9Sstevel@tonic-gate break; 3237c478bd9Sstevel@tonic-gate case '\b': 3247c478bd9Sstevel@tonic-gate /* if ( ! esc_chars ) */ 3257c478bd9Sstevel@tonic-gate lp--; 3267c478bd9Sstevel@tonic-gate break; 3277c478bd9Sstevel@tonic-gate default: 3287c478bd9Sstevel@tonic-gate lp += wcscrwidth(*line); 3297c478bd9Sstevel@tonic-gate } 330*337314b1Sas145665 incr_line(1); 3317c478bd9Sstevel@tonic-gate } 3327c478bd9Sstevel@tonic-gate while (*line == '\b') { 3337c478bd9Sstevel@tonic-gate /* 3347c478bd9Sstevel@tonic-gate * EUC (For a multi-column character, backspace characters 3357c478bd9Sstevel@tonic-gate * are assumed to be used like "__^H^HXX", where "XX" 3367c478bd9Sstevel@tonic-gate * represents a two-column character, and a backspace 3377c478bd9Sstevel@tonic-gate * always goes back by one column.) 3387c478bd9Sstevel@tonic-gate */ 339*337314b1Sas145665 for (n = 0; *line == '\b'; incr_line(1)) { 3407c478bd9Sstevel@tonic-gate n++; 3417c478bd9Sstevel@tonic-gate lp--; 3427c478bd9Sstevel@tonic-gate } 3437c478bd9Sstevel@tonic-gate while (n > 0 && lp < cp) { 344*337314b1Sas145665 i = *line; 345*337314b1Sas145665 incr_line(1); 3467c478bd9Sstevel@tonic-gate i = wcscrwidth(i); 3477c478bd9Sstevel@tonic-gate n -= i; 3487c478bd9Sstevel@tonic-gate lp += i; 3497c478bd9Sstevel@tonic-gate } 3507c478bd9Sstevel@tonic-gate } 3517c478bd9Sstevel@tonic-gate while (*line == ESC) 352*337314b1Sas145665 incr_line(6); 3537c478bd9Sstevel@tonic-gate widthc = wcscrwidth(c); 3547c478bd9Sstevel@tonic-gate widthl = wcscrwidth(*line); 3557c478bd9Sstevel@tonic-gate if (bflag || (*line == '\0') || *line == ' ') { 3567c478bd9Sstevel@tonic-gate if (*line == '\0' || widthl == widthc) { 3577c478bd9Sstevel@tonic-gate *line = c; 3587c478bd9Sstevel@tonic-gate } else if (widthl > widthc) { 3597c478bd9Sstevel@tonic-gate n = widthl - widthc; 3607c478bd9Sstevel@tonic-gate wsinsert(line, n); 361*337314b1Sas145665 *line = c; 362*337314b1Sas145665 incr_line(1); 363*337314b1Sas145665 for (i = 0; i < n; i++) { 364*337314b1Sas145665 *line = ' '; 365*337314b1Sas145665 incr_line(1); 366*337314b1Sas145665 } 3677c478bd9Sstevel@tonic-gate line = lbuff; 3687c478bd9Sstevel@tonic-gate lp = 0; 3697c478bd9Sstevel@tonic-gate } else { 3707c478bd9Sstevel@tonic-gate n = widthc - widthl; 371*337314b1Sas145665 if (line < lbuffend) { 372*337314b1Sas145665 for (p1 = line+1; n > 0 && p1 < lbuffend; 373*337314b1Sas145665 n -= wcscrwidth(i)) { 3747c478bd9Sstevel@tonic-gate i = *p1++; 375*337314b1Sas145665 } 3767c478bd9Sstevel@tonic-gate *line = c; 377*337314b1Sas145665 if (p1 < lbuffend) { 3787c478bd9Sstevel@tonic-gate (void) wcscpy(line+1, p1); 379*337314b1Sas145665 } else { 380*337314b1Sas145665 (void) fprintf(stderr, 381*337314b1Sas145665 gettext("col: Line too long.\n")); 382*337314b1Sas145665 exit(1); 383*337314b1Sas145665 } 384*337314b1Sas145665 } else { 385*337314b1Sas145665 (void) fprintf(stderr, 386*337314b1Sas145665 gettext("col: Line too long.\n")); 387*337314b1Sas145665 exit(1); 388*337314b1Sas145665 } 3897c478bd9Sstevel@tonic-gate } 3907c478bd9Sstevel@tonic-gate } else { 3917c478bd9Sstevel@tonic-gate if (smart && (widthl == 1) && (widthc == 1)) { 3927c478bd9Sstevel@tonic-gate wchar_t c1, c2, c3, c4, c5, c6, c7; 393*337314b1Sas145665 incr_line(1); 394*337314b1Sas145665 c1 = *line; 395*337314b1Sas145665 *line = ESC; 396*337314b1Sas145665 incr_line(1); 3977c478bd9Sstevel@tonic-gate c2 = *line; 398*337314b1Sas145665 *line = '['; 399*337314b1Sas145665 incr_line(1); 4007c478bd9Sstevel@tonic-gate c3 = *line; 401*337314b1Sas145665 *line = '\b'; 402*337314b1Sas145665 incr_line(1); 4037c478bd9Sstevel@tonic-gate c4 = *line; 404*337314b1Sas145665 *line = ESC; 405*337314b1Sas145665 incr_line(1); 4067c478bd9Sstevel@tonic-gate c5 = *line; 407*337314b1Sas145665 *line = ']'; 408*337314b1Sas145665 incr_line(1); 4097c478bd9Sstevel@tonic-gate c6 = *line; 410*337314b1Sas145665 *line = c; 411*337314b1Sas145665 incr_line(1); 4127c478bd9Sstevel@tonic-gate while (c1) { 4137c478bd9Sstevel@tonic-gate c7 = *line; 414*337314b1Sas145665 *line = c1; 415*337314b1Sas145665 incr_line(1); 4167c478bd9Sstevel@tonic-gate c1 = c2; 4177c478bd9Sstevel@tonic-gate c2 = c3; 4187c478bd9Sstevel@tonic-gate c3 = c4; 4197c478bd9Sstevel@tonic-gate c4 = c5; 4207c478bd9Sstevel@tonic-gate c5 = c6; 4217c478bd9Sstevel@tonic-gate c6 = c7; 4227c478bd9Sstevel@tonic-gate } 4237c478bd9Sstevel@tonic-gate } else { 4247c478bd9Sstevel@tonic-gate if ((widthl == 1) && (widthc == 1)) { 4257c478bd9Sstevel@tonic-gate wchar_t c1, c2, c3; 426*337314b1Sas145665 incr_line(1); 427*337314b1Sas145665 c1 = *line; 428*337314b1Sas145665 *line = '\b'; 429*337314b1Sas145665 incr_line(1); 4307c478bd9Sstevel@tonic-gate c2 = *line; 431*337314b1Sas145665 *line = c; 432*337314b1Sas145665 incr_line(1); 4337c478bd9Sstevel@tonic-gate while (c1) { 4347c478bd9Sstevel@tonic-gate c3 = *line; 435*337314b1Sas145665 *line = c1; 436*337314b1Sas145665 incr_line(1); 4377c478bd9Sstevel@tonic-gate c1 = c2; 4387c478bd9Sstevel@tonic-gate c2 = c3; 4397c478bd9Sstevel@tonic-gate } 4407c478bd9Sstevel@tonic-gate } else { 4417c478bd9Sstevel@tonic-gate width = (widthc > widthl) ? widthc : widthl; 442*337314b1Sas145665 for (i = 0; i < width; i += wcscrwidth(c1)) { 443*337314b1Sas145665 c1 = *line; 444*337314b1Sas145665 incr_line(1); 445*337314b1Sas145665 } 4467c478bd9Sstevel@tonic-gate wsinsert(line, width + (width - widthc + 1)); 447*337314b1Sas145665 for (i = 0; i < width; i++) { 448*337314b1Sas145665 *line = '\b'; 449*337314b1Sas145665 incr_line(1); 450*337314b1Sas145665 } 451*337314b1Sas145665 *line = c; 452*337314b1Sas145665 incr_line(1); 453*337314b1Sas145665 for (i = widthc; i < width; i++) { 454*337314b1Sas145665 *line = ' '; 455*337314b1Sas145665 incr_line(1); 456*337314b1Sas145665 } 4577c478bd9Sstevel@tonic-gate } 4587c478bd9Sstevel@tonic-gate } 4597c478bd9Sstevel@tonic-gate lp = 0; 4607c478bd9Sstevel@tonic-gate line = lbuff; 4617c478bd9Sstevel@tonic-gate } 4627c478bd9Sstevel@tonic-gate } 4637c478bd9Sstevel@tonic-gate 4647c478bd9Sstevel@tonic-gate static void 4657c478bd9Sstevel@tonic-gate store(int lno) 4667c478bd9Sstevel@tonic-gate { 4677c478bd9Sstevel@tonic-gate lno %= PL; 4687c478bd9Sstevel@tonic-gate if (page[lno] != 0) 4697c478bd9Sstevel@tonic-gate free((char *)page[lno]); 4707c478bd9Sstevel@tonic-gate page[lno] = (wchar_t *)malloc((unsigned)(wcslen(lbuff) + 2) 4717c478bd9Sstevel@tonic-gate * sizeof (wchar_t)); 4727c478bd9Sstevel@tonic-gate if (page[lno] == 0) { 4737c478bd9Sstevel@tonic-gate /* fprintf(stderr, "%s: no storage\n", pgmname); */ 4747c478bd9Sstevel@tonic-gate exit(2); 4757c478bd9Sstevel@tonic-gate } 4767c478bd9Sstevel@tonic-gate (void) wcscpy(page[lno], lbuff); 4777c478bd9Sstevel@tonic-gate } 4787c478bd9Sstevel@tonic-gate 4797c478bd9Sstevel@tonic-gate static void 4807c478bd9Sstevel@tonic-gate fetch(int lno) 4817c478bd9Sstevel@tonic-gate { 4827c478bd9Sstevel@tonic-gate wchar_t *p; 4837c478bd9Sstevel@tonic-gate 4847c478bd9Sstevel@tonic-gate lno %= PL; 4857c478bd9Sstevel@tonic-gate p = lbuff; 4867c478bd9Sstevel@tonic-gate while (*p) 4877c478bd9Sstevel@tonic-gate *p++ = '\0'; 4887c478bd9Sstevel@tonic-gate line = lbuff; 4897c478bd9Sstevel@tonic-gate lp = 0; 4907c478bd9Sstevel@tonic-gate if (page[lno]) 4917c478bd9Sstevel@tonic-gate (void) wcscpy(line, page[lno]); 4927c478bd9Sstevel@tonic-gate } 4937c478bd9Sstevel@tonic-gate 4947c478bd9Sstevel@tonic-gate static void 4957c478bd9Sstevel@tonic-gate emit(wchar_t *s, int lineno) 4967c478bd9Sstevel@tonic-gate { 4977c478bd9Sstevel@tonic-gate static int cline = 0; 4987c478bd9Sstevel@tonic-gate int ncp; 4997c478bd9Sstevel@tonic-gate wchar_t *p; 5007c478bd9Sstevel@tonic-gate char cshifted; 5017c478bd9Sstevel@tonic-gate char chr[MB_LEN_MAX + 1]; 5027c478bd9Sstevel@tonic-gate 5037c478bd9Sstevel@tonic-gate int c; 5047c478bd9Sstevel@tonic-gate static int gflag = 0; 5057c478bd9Sstevel@tonic-gate 5067c478bd9Sstevel@tonic-gate if (*s) { 5077c478bd9Sstevel@tonic-gate if (gflag) { 5087c478bd9Sstevel@tonic-gate (void) putchar(SI); 5097c478bd9Sstevel@tonic-gate gflag = 0; 5107c478bd9Sstevel@tonic-gate } 5117c478bd9Sstevel@tonic-gate while (cline < lineno - 1) { 5127c478bd9Sstevel@tonic-gate (void) putchar('\n'); 5137c478bd9Sstevel@tonic-gate pcp = 0; 5147c478bd9Sstevel@tonic-gate cline += 2; 5157c478bd9Sstevel@tonic-gate } 5167c478bd9Sstevel@tonic-gate if (cline != lineno) { 5177c478bd9Sstevel@tonic-gate (void) putchar(ESC); 5187c478bd9Sstevel@tonic-gate (void) putchar('9'); 5197c478bd9Sstevel@tonic-gate cline++; 5207c478bd9Sstevel@tonic-gate } 5217c478bd9Sstevel@tonic-gate if (pcp) 5227c478bd9Sstevel@tonic-gate (void) putchar('\r'); 5237c478bd9Sstevel@tonic-gate pcp = 0; 5247c478bd9Sstevel@tonic-gate p = s; 5257c478bd9Sstevel@tonic-gate while (*p) { 5267c478bd9Sstevel@tonic-gate ncp = pcp; 5277c478bd9Sstevel@tonic-gate while (*p++ == ' ') { 5287c478bd9Sstevel@tonic-gate if ((++ncp & 7) == 0 && !xflag) { 5297c478bd9Sstevel@tonic-gate pcp = ncp; 5307c478bd9Sstevel@tonic-gate (void) putchar('\t'); 5317c478bd9Sstevel@tonic-gate } 5327c478bd9Sstevel@tonic-gate } 5337c478bd9Sstevel@tonic-gate if (!*--p) 5347c478bd9Sstevel@tonic-gate break; 5357c478bd9Sstevel@tonic-gate while (pcp < ncp) { 5367c478bd9Sstevel@tonic-gate (void) putchar(' '); 5377c478bd9Sstevel@tonic-gate pcp++; 5387c478bd9Sstevel@tonic-gate } 5397c478bd9Sstevel@tonic-gate if (greeked) { 5407c478bd9Sstevel@tonic-gate if (wctomb(chr, *p) == 1) { 5417c478bd9Sstevel@tonic-gate if (gflag != (*chr & GREEK) && 5427c478bd9Sstevel@tonic-gate *p != '\b' && 5437c478bd9Sstevel@tonic-gate isascii(*chr ^ (gflag ^ GREEK)) && 5447c478bd9Sstevel@tonic-gate !iscntrl(*chr ^ (gflag ^ GREEK)) && 5457c478bd9Sstevel@tonic-gate !isspace(*chr ^ (gflag ^ GREEK))) { 5467c478bd9Sstevel@tonic-gate if (gflag) 5477c478bd9Sstevel@tonic-gate (void) putchar(SI); 5487c478bd9Sstevel@tonic-gate else 5497c478bd9Sstevel@tonic-gate (void) putchar(SO); 5507c478bd9Sstevel@tonic-gate gflag ^= GREEK; 5517c478bd9Sstevel@tonic-gate } 5527c478bd9Sstevel@tonic-gate } 5537c478bd9Sstevel@tonic-gate } 5547c478bd9Sstevel@tonic-gate c = *p; 5557c478bd9Sstevel@tonic-gate if (greeked) { 5567c478bd9Sstevel@tonic-gate if (wctomb(chr, (wchar_t)c) == 1) { 5577c478bd9Sstevel@tonic-gate cshifted = (*chr ^ GREEK); 5587c478bd9Sstevel@tonic-gate if (isascii(cshifted) && 5597c478bd9Sstevel@tonic-gate !iscntrl(cshifted) && 5607c478bd9Sstevel@tonic-gate !isspace(cshifted)) 5617c478bd9Sstevel@tonic-gate (void) putchar(*chr & ~GREEK); 5627c478bd9Sstevel@tonic-gate } else 5637c478bd9Sstevel@tonic-gate (void) putwchar(c); 5647c478bd9Sstevel@tonic-gate } else 5657c478bd9Sstevel@tonic-gate (void) putwchar(c); 5667c478bd9Sstevel@tonic-gate if (c == '\b') { 5677c478bd9Sstevel@tonic-gate if (*(p-2) && *(p-2) == ESC) { 5687c478bd9Sstevel@tonic-gate pcp++; 5697c478bd9Sstevel@tonic-gate } else 5707c478bd9Sstevel@tonic-gate pcp--; 5717c478bd9Sstevel@tonic-gate } else { 5727c478bd9Sstevel@tonic-gate pcp += wcscrwidth(c); 5737c478bd9Sstevel@tonic-gate } 5747c478bd9Sstevel@tonic-gate p++; 5757c478bd9Sstevel@tonic-gate } 5767c478bd9Sstevel@tonic-gate } 5777c478bd9Sstevel@tonic-gate } 5787c478bd9Sstevel@tonic-gate 5797c478bd9Sstevel@tonic-gate static void 5807c478bd9Sstevel@tonic-gate incr(void) 5817c478bd9Sstevel@tonic-gate { 5827c478bd9Sstevel@tonic-gate store(ll++); 5837c478bd9Sstevel@tonic-gate if (ll > llh) 5847c478bd9Sstevel@tonic-gate llh = ll; 5857c478bd9Sstevel@tonic-gate if (ll >= mustwr && page[ll%PL]) { 5867c478bd9Sstevel@tonic-gate emit(page[ll%PL], ll - PL); 5877c478bd9Sstevel@tonic-gate mustwr++; 5887c478bd9Sstevel@tonic-gate free((char *)page[ll%PL]); 5897c478bd9Sstevel@tonic-gate page[ll%PL] = 0; 5907c478bd9Sstevel@tonic-gate } 5917c478bd9Sstevel@tonic-gate fetch(ll); 5927c478bd9Sstevel@tonic-gate } 5937c478bd9Sstevel@tonic-gate 5947c478bd9Sstevel@tonic-gate static void 5957c478bd9Sstevel@tonic-gate decr(void) 5967c478bd9Sstevel@tonic-gate { 5977c478bd9Sstevel@tonic-gate if (ll > mustwr - PL) { 5987c478bd9Sstevel@tonic-gate store(ll--); 5997c478bd9Sstevel@tonic-gate fetch(ll); 6007c478bd9Sstevel@tonic-gate } 6017c478bd9Sstevel@tonic-gate } 6027c478bd9Sstevel@tonic-gate 6037c478bd9Sstevel@tonic-gate static void 6047c478bd9Sstevel@tonic-gate wsinsert(wchar_t *s, int n) 6057c478bd9Sstevel@tonic-gate { 6067c478bd9Sstevel@tonic-gate wchar_t *p1, *p2; 6077c478bd9Sstevel@tonic-gate 6087c478bd9Sstevel@tonic-gate 6097c478bd9Sstevel@tonic-gate p1 = s + wcslen(s); 6107c478bd9Sstevel@tonic-gate p2 = p1 + n; 6117c478bd9Sstevel@tonic-gate while (p1 >= s) 6127c478bd9Sstevel@tonic-gate *p2-- = *p1--; 6137c478bd9Sstevel@tonic-gate } 6147c478bd9Sstevel@tonic-gate 615*337314b1Sas145665 /* 616*337314b1Sas145665 * incr_line - increments line pointer and checks for array out of bounds 617*337314b1Sas145665 * amt: assumed to be >= 1 618*337314b1Sas145665 * exit on error to avoid line pointer accessing out of the array 619*337314b1Sas145665 */ 620*337314b1Sas145665 static void 621*337314b1Sas145665 incr_line(int amt) 622*337314b1Sas145665 { 623*337314b1Sas145665 if (line < lbuffend - amt + 1) { 624*337314b1Sas145665 line += amt; 625*337314b1Sas145665 } else { 626*337314b1Sas145665 (void) fprintf(stderr, gettext("col: Line too long.\n")); 627*337314b1Sas145665 exit(1); 628*337314b1Sas145665 } 629*337314b1Sas145665 } 630*337314b1Sas145665 631*337314b1Sas145665 6327c478bd9Sstevel@tonic-gate static int 6337c478bd9Sstevel@tonic-gate wcscrwidth(wchar_t wc) 6347c478bd9Sstevel@tonic-gate { 6357c478bd9Sstevel@tonic-gate int nc; 6367c478bd9Sstevel@tonic-gate 6377c478bd9Sstevel@tonic-gate if (wc == 0) { 6387c478bd9Sstevel@tonic-gate /* 6397c478bd9Sstevel@tonic-gate * if wc is a null character, needs to 6407c478bd9Sstevel@tonic-gate * return 1 instead of 0. 6417c478bd9Sstevel@tonic-gate */ 6427c478bd9Sstevel@tonic-gate return (1); 6437c478bd9Sstevel@tonic-gate } 6447c478bd9Sstevel@tonic-gate nc = wcwidth(wc); 6457c478bd9Sstevel@tonic-gate if (nc > 0) { 6467c478bd9Sstevel@tonic-gate return (nc); 6477c478bd9Sstevel@tonic-gate } else { 6487c478bd9Sstevel@tonic-gate return (0); 6497c478bd9Sstevel@tonic-gate } 6507c478bd9Sstevel@tonic-gate } 651