1152616Sle/* 2152616Sle * Copyright (c) 1980, 1993 3152631Sle * The Regents of the University of California. All rights reserved. 4152616Sle * 5152616Sle * Redistribution and use in source and binary forms, with or without 6152616Sle * modification, are permitted provided that the following conditions 7152631Sle * are met: 8152631Sle * 1. Redistributions of source code must retain the above copyright 9152631Sle * notice, this list of conditions and the following disclaimer. 10152631Sle * 2. Redistributions in binary form must reproduce the above copyright 11152616Sle * notice, this list of conditions and the following disclaimer in the 12152616Sle * documentation and/or other materials provided with the distribution. 13152616Sle * 4. Neither the name of the University nor the names of its contributors 14152616Sle * may be used to endorse or promote products derived from this software 15152616Sle * without specific prior written permission. 16152616Sle * 17152616Sle * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18152616Sle * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19152616Sle * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20152616Sle * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21152616Sle * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22152616Sle * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23152616Sle * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24152616Sle * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25152616Sle * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26152616Sle * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27152616Sle * SUCH DAMAGE. 28152631Sle */ 29152616Sle 30152616Sle#ifndef lint 31266014Smariusstatic const char copyright[] = 32152616Sle"@(#) Copyright (c) 1980, 1993\n\ 33152616Sle The Regents of the University of California. All rights reserved.\n"; 34152616Sle#endif 35152616Sle 36152616Sle#if 0 37152616Sle#ifndef lint 38152616Slestatic char sccsid[] = "@(#)colcrt.c 8.1 (Berkeley) 6/6/93"; 39152616Sle#endif 40152616Sle#endif 41152616Sle 42152616Sle#include <sys/cdefs.h> 43190507Slulf__FBSDID("$FreeBSD$"); 44190507Slulf 45233648Seadler#include <err.h> 46190507Slulf#include <locale.h> 47190507Slulf#include <stdio.h> 48190507Slulf#include <stdlib.h> 49190507Slulf#include <string.h> 50162842Sru#include <unistd.h> 51162842Sru#include <wchar.h> 52162842Sru 53152631Sle/* 54152616Sle * colcrt - replaces col for crts with new nroff esp. when using tbl. 55152616Sle * Bill Joy UCB July 14, 1977 56162842Sru * 57162842Sru * This filter uses a screen buffer, 267 half-lines by 132 columns. 58152616Sle * It interprets the up and down sequences generated by the new 59190507Slulf * nroff when used with tbl and by \u \d and \r. 60190507Slulf * General overstriking doesn't work correctly. 61235873Swblock * Underlining is split onto multiple lines, etc. 62235873Swblock * 63190507Slulf * Option - suppresses all underlining. 64152616Sle * Option -2 forces printing of all half lines. 65152616Sle */ 66152616Sle 67152631Slestatic wchar_t page[267][132]; 68152631Sle 69152616Slestatic int outline = 1; 70152616Slestatic int outcol; 71190507Slulf 72190507Slulfstatic char suppresul; 73190507Slulfstatic char printall; 74190507Slulf 75190507Slulfstatic void move(int, int); 76190507Slulfstatic void pflush(int); 77190507Slulfstatic int plus(wchar_t, wchar_t); 78190507Slulfstatic void usage(void); 79190507Slulf 80190507Slulfint 81190507Slulfmain(int argc, char *argv[]) 82190507Slulf{ 83190884Slulf wint_t c; 84190884Slulf wchar_t *cp, *dp; 85190884Slulf int ch, i, w; 86190884Slulf 87162842Sru setlocale(LC_ALL, ""); 88152631Sle 89152631Sle while ((ch = getopt(argc, argv, "-2")) != -1) 90152616Sle switch (ch) { 91162842Sru case '-': 92162842Sru suppresul = 1; 93162842Sru break; 94162842Sru case '2': 95162842Sru printall = 1; 96162842Sru break; 97162842Sru default: 98152616Sle usage(); 99152616Sle } 100162842Sru argc -= optind; 101162842Sru argv += optind; 102152616Sle 103152631Sle do { 104152616Sle if (argc > 0) { 105152616Sle if (freopen(argv[0], "r", stdin) == NULL) { 106190507Slulf fflush(stdout); 107233648Seadler err(1, "%s", argv[0]); 108190507Slulf } 109190507Slulf argc--; 110233648Seadler argv++; 111190507Slulf } 112190507Slulf for (;;) { 113190507Slulf c = getwc(stdin); 114162842Sru if (c == WEOF) { 115162842Sru pflush(outline); 116162842Sru fflush(stdout); 117152616Sle break; 118152616Sle } 119162842Sru switch (c) { 120162842Sru case '\n': 121152616Sle if (outline >= 265) 122152616Sle pflush(62); 123190507Slulf outline += 2; 124190507Slulf outcol = 0; 125190507Slulf continue; 126190507Slulf case '\016': 127190507Slulf case '\017': 128190507Slulf continue; 129190507Slulf case 033: 130190507Slulf c = getwc(stdin); 131162842Sru switch (c) { 132162842Sru case '9': 133152616Sle if (outline >= 266) 134190507Slulf pflush(62); 135190507Slulf outline++; 136162842Sru continue; 137162842Sru case '8': 138152616Sle if (outline >= 1) 139162842Sru outline--; 140162842Sru continue; 141152616Sle case '7': 142162842Sru outline -= 2; 143152616Sle if (outline < 0) 144162842Sru outline = 0; 145152631Sle continue; 146152616Sle default: 147162842Sru continue; 148162842Sru } 149152616Sle case '\b': 150190507Slulf if (outcol) 151190507Slulf outcol--; 152235873Swblock continue; 153235873Swblock case '\t': 154190507Slulf outcol += 8; 155162842Sru outcol &= ~7; 156162842Sru outcol--; 157162842Sru c = ' '; 158152616Sle default: 159152616Sle if ((w = wcwidth(c)) <= 0) 160152616Sle w = 1; /* XXX */ 161152631Sle if (outcol + w > 132) { 162152616Sle outcol += w; 163152616Sle continue; 164162842Sru } 165162842Sru cp = &page[outline][outcol]; 166162842Sru outcol += w; 167152631Sle if (c == '_') { 168152616Sle if (suppresul) 169152616Sle continue; 170152616Sle cp += 132; 171266014Smarius c = '-'; 172157052Sle } 173157052Sle if (*cp == 0) { 174157052Sle for (i = 0; i < w; i++) 175162842Sru cp[i] = c; 176152631Sle dp = cp - (outcol - w); 177152616Sle for (cp--; cp >= dp && *cp == 0; cp--) 178152616Sle *cp = ' '; 179162842Sru } else { 180152631Sle if (plus(c, *cp) || plus(*cp, c)) 181152616Sle *cp = '+'; 182152616Sle else if (*cp == ' ' || *cp == 0) { 183162842Sru for (i = 1; i < w; i++) 184152631Sle if (cp[i] != ' ' && 185162842Sru cp[i] != 0) 186162842Sru goto cont; 187152616Sle for (i = 0; i < w; i++) 188152616Sle cp[i] = c; 189162842Sru } 190152616Sle } 191162842Srucont: 192162842Sru continue; 193190507Slulf } 194190507Slulf } 195190507Slulf if (ferror(stdin)) 196190507Slulf err(1, NULL); 197162842Sru } while (argc > 0); 198152616Sle fflush(stdout); 199152616Sle exit(0); 200190507Slulf} 201190507Slulf 202190507Slulfstatic void 203190507Slulfusage(void) 204190507Slulf{ 205190507Slulf fprintf(stderr, "usage: colcrt [-] [-2] [file ...]\n"); 206235873Swblock exit(1); 207235873Swblock} 208235873Swblock 209152616Slestatic int 210152616Sleplus(wchar_t c, wchar_t d) 211152616Sle{ 212152616Sle 213152616Sle return ((c == '|' && d == '-') || d == '_'); 214162842Sru} 215162842Sru 216152616Slestatic void 217162842Srupflush(int ol) 218162842Sru{ 219152616Sle static int first; 220152616Sle int i; 221152616Sle wchar_t *cp; 222162842Sru char lastomit; 223152616Sle int l, w; 224152616Sle 225152616Sle l = ol; 226152616Sle lastomit = 0; 227152616Sle if (l > 266) 228152616Sle l = 266; 229152616Sle else 230162842Sru l |= 1; 231162842Sru for (i = first | 1; i < l; i++) { 232162842Sru move(i, i - 1); 233152631Sle move(i, i + 1); 234152616Sle } 235152616Sle for (i = first; i < l; i++) { 236152616Sle cp = page[i]; 237152631Sle if (printall == 0 && lastomit == 0 && *cp == 0) { 238152616Sle lastomit = 1; 239152616Sle continue; 240162842Sru } 241162842Sru lastomit = 0; 242152616Sle while (*cp != L'\0') { 243152616Sle if ((w = wcwidth(*cp)) > 0) { 244152631Sle putwchar(*cp); 245152616Sle cp += w; 246152616Sle } else 247162842Sru cp++; 248162842Sru } 249152616Sle putwchar(L'\n'); 250152616Sle } 251152631Sle wmemcpy(page[0], page[ol], (267 - ol) * 132); 252152616Sle wmemset(page[267- ol], L'\0', ol * 132); 253152616Sle outline -= ol; 254152616Sle outcol = 0; 255152616Sle first = 1; 256152616Sle} 257152616Sle 258152616Slestatic void 259152616Slemove(int l, int m) 260152616Sle{ 261152616Sle wchar_t *cp, *dp; 262162842Sru 263152616Sle for (cp = page[l], dp = page[m]; *cp; cp++, dp++) { 264152616Sle switch (*cp) { 265152616Sle case '|': 266162842Sru if (*dp != ' ' && *dp != '|' && *dp != 0) 267162842Sru return; 268162842Sru break; 269162842Sru case ' ': 270162842Sru break; 271162842Sru default: 272162842Sru return; 273162842Sru } 274152616Sle } 275162842Sru if (*cp == 0) { 276152616Sle for (cp = page[l], dp = page[m]; *cp; cp++, dp++) 277152616Sle if (*cp == '|') 278152616Sle *dp = '|'; 279152616Sle else if (*dp == 0) 280152616Sle *dp = ' '; 281190507Slulf page[l][0] = 0; 282255977Spluknet } 283255977Spluknet} 284235873Swblock