11590Srgrimes/* 21590Srgrimes * Copyright (c) 1980, 1993 31590Srgrimes * The Regents of the University of California. All rights reserved. 41590Srgrimes * 51590Srgrimes * Redistribution and use in source and binary forms, with or without 61590Srgrimes * modification, are permitted provided that the following conditions 71590Srgrimes * are met: 81590Srgrimes * 1. Redistributions of source code must retain the above copyright 91590Srgrimes * notice, this list of conditions and the following disclaimer. 101590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111590Srgrimes * notice, this list of conditions and the following disclaimer in the 121590Srgrimes * documentation and/or other materials provided with the distribution. 131590Srgrimes * 4. Neither the name of the University nor the names of its contributors 141590Srgrimes * may be used to endorse or promote products derived from this software 151590Srgrimes * without specific prior written permission. 161590Srgrimes * 171590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 181590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 191590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 201590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 211590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 221590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 231590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 241590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 251590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 261590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 271590Srgrimes * SUCH DAMAGE. 281590Srgrimes */ 291590Srgrimes 301590Srgrimes#ifndef lint 3141568Sarchiestatic const char copyright[] = 321590Srgrimes"@(#) Copyright (c) 1980, 1993\n\ 331590Srgrimes The Regents of the University of California. All rights reserved.\n"; 3487242Smarkm#endif 351590Srgrimes 3687628Sdwmalone#if 0 371590Srgrimes#ifndef lint 3887628Sdwmalonestatic char sccsid[] = "@(#)colcrt.c 8.1 (Berkeley) 6/6/93"; 3962889Skris#endif 4087628Sdwmalone#endif 411590Srgrimes 4287628Sdwmalone#include <sys/cdefs.h> 4387628Sdwmalone__FBSDID("$FreeBSD$"); 4487628Sdwmalone 4532069Salex#include <err.h> 46132916Stjr#include <locale.h> 471590Srgrimes#include <stdio.h> 4878718Sdd#include <stdlib.h> 49200462Sdelphij#include <string.h> 5032069Salex#include <unistd.h> 51132916Stjr#include <wchar.h> 52132915Stjr 531590Srgrimes/* 541590Srgrimes * colcrt - replaces col for crts with new nroff esp. when using tbl. 551590Srgrimes * Bill Joy UCB July 14, 1977 561590Srgrimes * 571590Srgrimes * This filter uses a screen buffer, 267 half-lines by 132 columns. 581590Srgrimes * It interprets the up and down sequences generated by the new 591590Srgrimes * nroff when used with tbl and by \u \d and \r. 601590Srgrimes * General overstriking doesn't work correctly. 611590Srgrimes * Underlining is split onto multiple lines, etc. 621590Srgrimes * 631590Srgrimes * Option - suppresses all underlining. 641590Srgrimes * Option -2 forces printing of all half lines. 651590Srgrimes */ 661590Srgrimes 67227158Sedstatic wchar_t page[267][132]; 681590Srgrimes 69227158Sedstatic int outline = 1; 70227158Sedstatic int outcol; 711590Srgrimes 72227158Sedstatic char suppresul; 73227158Sedstatic char printall; 741590Srgrimes 7592920Simpstatic void move(int, int); 7692920Simpstatic void pflush(int); 77132916Stjrstatic int plus(wchar_t, wchar_t); 7892920Simpstatic void usage(void); 7926958Scharnier 8026958Scharnierint 81102944Sdwmalonemain(int argc, char *argv[]) 821590Srgrimes{ 83132916Stjr wint_t c; 84132916Stjr wchar_t *cp, *dp; 85132916Stjr int ch, i, w; 861590Srgrimes 87132916Stjr setlocale(LC_ALL, ""); 88132916Stjr 8963811Scharnier while ((ch = getopt(argc, argv, "-2")) != -1) 9063811Scharnier switch (ch) { 9163811Scharnier case '-': 9263811Scharnier suppresul = 1; 9363811Scharnier break; 9463811Scharnier case '2': 9563811Scharnier printall = 1; 9663811Scharnier break; 9763811Scharnier default: 9863811Scharnier usage(); 991590Srgrimes } 10063811Scharnier argc -= optind; 10163811Scharnier argv += optind; 10263811Scharnier 1031590Srgrimes do { 1041590Srgrimes if (argc > 0) { 105132915Stjr if (freopen(argv[0], "r", stdin) == NULL) { 1061590Srgrimes fflush(stdout); 10762889Skris err(1, "%s", argv[0]); 1081590Srgrimes } 1091590Srgrimes argc--; 1101590Srgrimes argv++; 1111590Srgrimes } 1121590Srgrimes for (;;) { 113132916Stjr c = getwc(stdin); 114132916Stjr if (c == WEOF) { 1151590Srgrimes pflush(outline); 1161590Srgrimes fflush(stdout); 1171590Srgrimes break; 1181590Srgrimes } 1191590Srgrimes switch (c) { 120132915Stjr case '\n': 121132915Stjr if (outline >= 265) 122132915Stjr pflush(62); 123132915Stjr outline += 2; 124132915Stjr outcol = 0; 125132915Stjr continue; 126132915Stjr case '\016': 127132915Stjr case '\017': 128132915Stjr continue; 129132915Stjr case 033: 130132916Stjr c = getwc(stdin); 131132915Stjr switch (c) { 132132915Stjr case '9': 133132915Stjr if (outline >= 266) 1341590Srgrimes pflush(62); 135132915Stjr outline++; 1361590Srgrimes continue; 137132915Stjr case '8': 138132915Stjr if (outline >= 1) 139132915Stjr outline--; 1401590Srgrimes continue; 141132915Stjr case '7': 142132915Stjr outline -= 2; 143132915Stjr if (outline < 0) 144132915Stjr outline = 0; 1451590Srgrimes continue; 146132915Stjr default: 147132915Stjr continue; 148132915Stjr } 149132915Stjr case '\b': 150132915Stjr if (outcol) 1511590Srgrimes outcol--; 152132915Stjr continue; 153132915Stjr case '\t': 154132915Stjr outcol += 8; 155132915Stjr outcol &= ~7; 156132915Stjr outcol--; 157132915Stjr c = ' '; 158132915Stjr default: 159132916Stjr if ((w = wcwidth(c)) <= 0) 160132916Stjr w = 1; /* XXX */ 161132916Stjr if (outcol + w > 132) { 162132916Stjr outcol += w; 163132915Stjr continue; 164132915Stjr } 165132915Stjr cp = &page[outline][outcol]; 166132916Stjr outcol += w; 167132915Stjr if (c == '_') { 168132915Stjr if (suppresul) 1691590Srgrimes continue; 170132915Stjr cp += 132; 171132915Stjr c = '-'; 172132915Stjr } 173132915Stjr if (*cp == 0) { 174132916Stjr for (i = 0; i < w; i++) 175132916Stjr cp[i] = c; 176132916Stjr dp = cp - (outcol - w); 177132915Stjr for (cp--; cp >= dp && *cp == 0; cp--) 178132915Stjr *cp = ' '; 179132916Stjr } else { 180132915Stjr if (plus(c, *cp) || plus(*cp, c)) 181132915Stjr *cp = '+'; 182132916Stjr else if (*cp == ' ' || *cp == 0) { 183132916Stjr for (i = 1; i < w; i++) 184132916Stjr if (cp[i] != ' ' && 185132916Stjr cp[i] != 0) 186132916Stjr goto cont; 187132916Stjr for (i = 0; i < w; i++) 188132916Stjr cp[i] = c; 189132916Stjr } 190132916Stjr } 191132916Stjrcont: 192132915Stjr continue; 1931590Srgrimes } 1941590Srgrimes } 195132918Stjr if (ferror(stdin)) 196132918Stjr err(1, NULL); 1971590Srgrimes } while (argc > 0); 1981590Srgrimes fflush(stdout); 1991590Srgrimes exit(0); 2001590Srgrimes} 2011590Srgrimes 20226958Scharnierstatic void 203102944Sdwmaloneusage(void) 20426958Scharnier{ 20563811Scharnier fprintf(stderr, "usage: colcrt [-] [-2] [file ...]\n"); 20626958Scharnier exit(1); 20726958Scharnier} 20826958Scharnier 20932069Salexstatic int 210132916Stjrplus(wchar_t c, wchar_t d) 2111590Srgrimes{ 2121590Srgrimes 21332069Salex return ((c == '|' && d == '-') || d == '_'); 2141590Srgrimes} 2151590Srgrimes 21632069Salexstatic void 217102944Sdwmalonepflush(int ol) 2181590Srgrimes{ 219132915Stjr static int first; 220102944Sdwmalone int i; 221132916Stjr wchar_t *cp; 2221590Srgrimes char lastomit; 223132916Stjr int l, w; 2241590Srgrimes 2251590Srgrimes l = ol; 2261590Srgrimes lastomit = 0; 2271590Srgrimes if (l > 266) 2281590Srgrimes l = 266; 2291590Srgrimes else 2301590Srgrimes l |= 1; 2311590Srgrimes for (i = first | 1; i < l; i++) { 2321590Srgrimes move(i, i - 1); 2331590Srgrimes move(i, i + 1); 2341590Srgrimes } 2351590Srgrimes for (i = first; i < l; i++) { 2361590Srgrimes cp = page[i]; 2371590Srgrimes if (printall == 0 && lastomit == 0 && *cp == 0) { 2381590Srgrimes lastomit = 1; 2391590Srgrimes continue; 2401590Srgrimes } 2411590Srgrimes lastomit = 0; 242132916Stjr while (*cp != L'\0') { 243132916Stjr if ((w = wcwidth(*cp)) > 0) { 244132916Stjr putwchar(*cp); 245132916Stjr cp += w; 246132916Stjr } else 247132916Stjr cp++; 248132916Stjr } 249132916Stjr putwchar(L'\n'); 2501590Srgrimes } 251132916Stjr wmemcpy(page[0], page[ol], (267 - ol) * 132); 252132916Stjr wmemset(page[267- ol], L'\0', ol * 132); 2531590Srgrimes outline -= ol; 2541590Srgrimes outcol = 0; 2551590Srgrimes first = 1; 2561590Srgrimes} 2571590Srgrimes 25832069Salexstatic void 259102944Sdwmalonemove(int l, int m) 2601590Srgrimes{ 261132916Stjr wchar_t *cp, *dp; 2621590Srgrimes 2631590Srgrimes for (cp = page[l], dp = page[m]; *cp; cp++, dp++) { 2641590Srgrimes switch (*cp) { 2651590Srgrimes case '|': 2661590Srgrimes if (*dp != ' ' && *dp != '|' && *dp != 0) 2671590Srgrimes return; 2681590Srgrimes break; 2691590Srgrimes case ' ': 2701590Srgrimes break; 2711590Srgrimes default: 2721590Srgrimes return; 2731590Srgrimes } 2741590Srgrimes } 2751590Srgrimes if (*cp == 0) { 2761590Srgrimes for (cp = page[l], dp = page[m]; *cp; cp++, dp++) 2771590Srgrimes if (*cp == '|') 2781590Srgrimes *dp = '|'; 2791590Srgrimes else if (*dp == 0) 2801590Srgrimes *dp = ' '; 2811590Srgrimes page[l][0] = 0; 2821590Srgrimes } 2831590Srgrimes} 284