colcrt.c revision 132918
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 * 3. All advertising materials mentioning features or use of this software 141590Srgrimes * must display the following acknowledgement: 151590Srgrimes * This product includes software developed by the University of 161590Srgrimes * California, Berkeley and its contributors. 171590Srgrimes * 4. Neither the name of the University nor the names of its contributors 181590Srgrimes * may be used to endorse or promote products derived from this software 191590Srgrimes * without specific prior written permission. 201590Srgrimes * 211590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 221590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 251590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311590Srgrimes * SUCH DAMAGE. 321590Srgrimes */ 331590Srgrimes 341590Srgrimes#ifndef lint 3541568Sarchiestatic const char copyright[] = 361590Srgrimes"@(#) Copyright (c) 1980, 1993\n\ 371590Srgrimes The Regents of the University of California. All rights reserved.\n"; 3887242Smarkm#endif 391590Srgrimes 4087628Sdwmalone#if 0 411590Srgrimes#ifndef lint 4287628Sdwmalonestatic char sccsid[] = "@(#)colcrt.c 8.1 (Berkeley) 6/6/93"; 4362889Skris#endif 4487628Sdwmalone#endif 451590Srgrimes 4687628Sdwmalone#include <sys/cdefs.h> 4787628Sdwmalone__FBSDID("$FreeBSD: head/usr.bin/colcrt/colcrt.c 132918 2004-07-31 06:22:57Z tjr $"); 4887628Sdwmalone 4932069Salex#include <err.h> 50132916Stjr#include <locale.h> 511590Srgrimes#include <stdio.h> 5278718Sdd#include <stdlib.h> 5332069Salex#include <string.h> 5432069Salex#include <unistd.h> 55132916Stjr#include <wchar.h> 56132915Stjr 571590Srgrimes/* 581590Srgrimes * colcrt - replaces col for crts with new nroff esp. when using tbl. 591590Srgrimes * Bill Joy UCB July 14, 1977 601590Srgrimes * 611590Srgrimes * This filter uses a screen buffer, 267 half-lines by 132 columns. 621590Srgrimes * It interprets the up and down sequences generated by the new 631590Srgrimes * nroff when used with tbl and by \u \d and \r. 641590Srgrimes * General overstriking doesn't work correctly. 651590Srgrimes * Underlining is split onto multiple lines, etc. 661590Srgrimes * 671590Srgrimes * Option - suppresses all underlining. 681590Srgrimes * Option -2 forces printing of all half lines. 691590Srgrimes */ 701590Srgrimes 71132916Stjrwchar_t page[267][132]; 721590Srgrimes 731590Srgrimesint outline = 1; 741590Srgrimesint outcol; 751590Srgrimes 761590Srgrimeschar suppresul; 771590Srgrimeschar printall; 781590Srgrimes 7992920Simpstatic void move(int, int); 8092920Simpstatic void pflush(int); 81132916Stjrstatic int plus(wchar_t, wchar_t); 8292920Simpstatic void usage(void); 8326958Scharnier 8426958Scharnierint 85102944Sdwmalonemain(int argc, char *argv[]) 861590Srgrimes{ 87132916Stjr wint_t c; 88132916Stjr wchar_t *cp, *dp; 89132916Stjr int ch, i, w; 901590Srgrimes 91132916Stjr setlocale(LC_ALL, ""); 92132916Stjr 9363811Scharnier while ((ch = getopt(argc, argv, "-2")) != -1) 9463811Scharnier switch (ch) { 9563811Scharnier case '-': 9663811Scharnier suppresul = 1; 9763811Scharnier break; 9863811Scharnier case '2': 9963811Scharnier printall = 1; 10063811Scharnier break; 10163811Scharnier default: 10263811Scharnier usage(); 1031590Srgrimes } 10463811Scharnier argc -= optind; 10563811Scharnier argv += optind; 10663811Scharnier 1071590Srgrimes do { 1081590Srgrimes if (argc > 0) { 109132915Stjr if (freopen(argv[0], "r", stdin) == NULL) { 1101590Srgrimes fflush(stdout); 11162889Skris err(1, "%s", argv[0]); 1121590Srgrimes } 1131590Srgrimes argc--; 1141590Srgrimes argv++; 1151590Srgrimes } 1161590Srgrimes for (;;) { 117132916Stjr c = getwc(stdin); 118132916Stjr if (c == WEOF) { 1191590Srgrimes pflush(outline); 1201590Srgrimes fflush(stdout); 1211590Srgrimes break; 1221590Srgrimes } 1231590Srgrimes switch (c) { 124132915Stjr case '\n': 125132915Stjr if (outline >= 265) 126132915Stjr pflush(62); 127132915Stjr outline += 2; 128132915Stjr outcol = 0; 129132915Stjr continue; 130132915Stjr case '\016': 131132915Stjr case '\017': 132132915Stjr continue; 133132915Stjr case 033: 134132916Stjr c = getwc(stdin); 135132915Stjr switch (c) { 136132915Stjr case '9': 137132915Stjr if (outline >= 266) 1381590Srgrimes pflush(62); 139132915Stjr outline++; 1401590Srgrimes continue; 141132915Stjr case '8': 142132915Stjr if (outline >= 1) 143132915Stjr outline--; 1441590Srgrimes continue; 145132915Stjr case '7': 146132915Stjr outline -= 2; 147132915Stjr if (outline < 0) 148132915Stjr outline = 0; 1491590Srgrimes continue; 150132915Stjr default: 151132915Stjr continue; 152132915Stjr } 153132915Stjr case '\b': 154132915Stjr if (outcol) 1551590Srgrimes outcol--; 156132915Stjr continue; 157132915Stjr case '\t': 158132915Stjr outcol += 8; 159132915Stjr outcol &= ~7; 160132915Stjr outcol--; 161132915Stjr c = ' '; 162132915Stjr default: 163132916Stjr if ((w = wcwidth(c)) <= 0) 164132916Stjr w = 1; /* XXX */ 165132916Stjr if (outcol + w > 132) { 166132916Stjr outcol += w; 167132915Stjr continue; 168132915Stjr } 169132915Stjr cp = &page[outline][outcol]; 170132916Stjr outcol += w; 171132915Stjr if (c == '_') { 172132915Stjr if (suppresul) 1731590Srgrimes continue; 174132915Stjr cp += 132; 175132915Stjr c = '-'; 176132915Stjr } 177132915Stjr if (*cp == 0) { 178132916Stjr for (i = 0; i < w; i++) 179132916Stjr cp[i] = c; 180132916Stjr dp = cp - (outcol - w); 181132915Stjr for (cp--; cp >= dp && *cp == 0; cp--) 182132915Stjr *cp = ' '; 183132916Stjr } else { 184132915Stjr if (plus(c, *cp) || plus(*cp, c)) 185132915Stjr *cp = '+'; 186132916Stjr else if (*cp == ' ' || *cp == 0) { 187132916Stjr for (i = 1; i < w; i++) 188132916Stjr if (cp[i] != ' ' && 189132916Stjr cp[i] != 0) 190132916Stjr goto cont; 191132916Stjr for (i = 0; i < w; i++) 192132916Stjr cp[i] = c; 193132916Stjr } 194132916Stjr } 195132916Stjrcont: 196132915Stjr continue; 1971590Srgrimes } 1981590Srgrimes } 199132918Stjr if (ferror(stdin)) 200132918Stjr err(1, NULL); 2011590Srgrimes } while (argc > 0); 2021590Srgrimes fflush(stdout); 2031590Srgrimes exit(0); 2041590Srgrimes} 2051590Srgrimes 20626958Scharnierstatic void 207102944Sdwmaloneusage(void) 20826958Scharnier{ 20963811Scharnier fprintf(stderr, "usage: colcrt [-] [-2] [file ...]\n"); 21026958Scharnier exit(1); 21126958Scharnier} 21226958Scharnier 21332069Salexstatic int 214132916Stjrplus(wchar_t c, wchar_t d) 2151590Srgrimes{ 2161590Srgrimes 21732069Salex return ((c == '|' && d == '-') || d == '_'); 2181590Srgrimes} 2191590Srgrimes 22032069Salexstatic void 221102944Sdwmalonepflush(int ol) 2221590Srgrimes{ 223132915Stjr static int first; 224102944Sdwmalone int i; 225132916Stjr wchar_t *cp; 2261590Srgrimes char lastomit; 227132916Stjr int l, w; 2281590Srgrimes 2291590Srgrimes l = ol; 2301590Srgrimes lastomit = 0; 2311590Srgrimes if (l > 266) 2321590Srgrimes l = 266; 2331590Srgrimes else 2341590Srgrimes l |= 1; 2351590Srgrimes for (i = first | 1; i < l; i++) { 2361590Srgrimes move(i, i - 1); 2371590Srgrimes move(i, i + 1); 2381590Srgrimes } 2391590Srgrimes for (i = first; i < l; i++) { 2401590Srgrimes cp = page[i]; 2411590Srgrimes if (printall == 0 && lastomit == 0 && *cp == 0) { 2421590Srgrimes lastomit = 1; 2431590Srgrimes continue; 2441590Srgrimes } 2451590Srgrimes lastomit = 0; 246132916Stjr while (*cp != L'\0') { 247132916Stjr if ((w = wcwidth(*cp)) > 0) { 248132916Stjr putwchar(*cp); 249132916Stjr cp += w; 250132916Stjr } else 251132916Stjr cp++; 252132916Stjr } 253132916Stjr putwchar(L'\n'); 2541590Srgrimes } 255132916Stjr wmemcpy(page[0], page[ol], (267 - ol) * 132); 256132916Stjr wmemset(page[267- ol], L'\0', ol * 132); 2571590Srgrimes outline -= ol; 2581590Srgrimes outcol = 0; 2591590Srgrimes first = 1; 2601590Srgrimes} 2611590Srgrimes 26232069Salexstatic void 263102944Sdwmalonemove(int l, int m) 2641590Srgrimes{ 265132916Stjr wchar_t *cp, *dp; 2661590Srgrimes 2671590Srgrimes for (cp = page[l], dp = page[m]; *cp; cp++, dp++) { 2681590Srgrimes switch (*cp) { 2691590Srgrimes case '|': 2701590Srgrimes if (*dp != ' ' && *dp != '|' && *dp != 0) 2711590Srgrimes return; 2721590Srgrimes break; 2731590Srgrimes case ' ': 2741590Srgrimes break; 2751590Srgrimes default: 2761590Srgrimes return; 2771590Srgrimes } 2781590Srgrimes } 2791590Srgrimes if (*cp == 0) { 2801590Srgrimes for (cp = page[l], dp = page[m]; *cp; cp++, dp++) 2811590Srgrimes if (*cp == '|') 2821590Srgrimes *dp = '|'; 2831590Srgrimes else if (*dp == 0) 2841590Srgrimes *dp = ' '; 2851590Srgrimes page[l][0] = 0; 2861590Srgrimes } 2871590Srgrimes} 288