kernel - Permanently fix FP bug - completely remove lazy heuristic
[dragonfly.git] / usr.bin / colcrt / colcrt.c
blob295ef57eb7bd5d14d46ac68f038b87aef3df6929
1 /*
2 * Copyright (c) 1980, 1993
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
29 * @(#) Copyright (c) 1980, 1993 The Regents of the University of California. All rights reserved.
30 * @(#)colcrt.c 8.1 (Berkeley) 6/6/93
31 * $FreeBSD: head/usr.bin/colcrt/colcrt.c 227158 2011-11-06 08:14:28Z ed $
34 #include <err.h>
35 #include <locale.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <unistd.h>
40 #include <wchar.h>
43 * colcrt - replaces col for crts with new nroff esp. when using tbl.
44 * Bill Joy UCB July 14, 1977
46 * This filter uses a screen buffer, 267 half-lines by 132 columns.
47 * It interprets the up and down sequences generated by the new
48 * nroff when used with tbl and by \u \d and \r.
49 * General overstriking doesn't work correctly.
50 * Underlining is split onto multiple lines, etc.
52 * Option - suppresses all underlining.
53 * Option -2 forces printing of all half lines.
56 static wchar_t page[267][132];
58 static int outline = 1;
59 static int outcol;
61 static char suppresul;
62 static char printall;
64 static void move(int, int);
65 static void pflush(int);
66 static int plus(wchar_t, wchar_t);
67 static void usage(void);
69 int
70 main(int argc, char *argv[])
72 wint_t c;
73 wchar_t *cp, *dp;
74 int ch, i, w;
76 setlocale(LC_ALL, "");
78 while ((ch = getopt(argc, argv, "-2")) != -1)
79 switch (ch) {
80 case '-':
81 suppresul = 1;
82 break;
83 case '2':
84 printall = 1;
85 break;
86 default:
87 usage();
89 argc -= optind;
90 argv += optind;
92 do {
93 if (argc > 0) {
94 if (freopen(argv[0], "r", stdin) == NULL) {
95 fflush(stdout);
96 err(1, "%s", argv[0]);
98 argc--;
99 argv++;
101 for (;;) {
102 c = getwc(stdin);
103 if (c == WEOF) {
104 pflush(outline);
105 fflush(stdout);
106 break;
108 switch (c) {
109 case '\n':
110 if (outline >= 265)
111 pflush(62);
112 outline += 2;
113 outcol = 0;
114 continue;
115 case '\016':
116 case '\017':
117 continue;
118 case 033:
119 c = getwc(stdin);
120 switch (c) {
121 case '9':
122 if (outline >= 266)
123 pflush(62);
124 outline++;
125 continue;
126 case '8':
127 if (outline >= 1)
128 outline--;
129 continue;
130 case '7':
131 outline -= 2;
132 if (outline < 0)
133 outline = 0;
134 continue;
135 default:
136 continue;
138 case '\b':
139 if (outcol)
140 outcol--;
141 continue;
142 case '\t':
143 outcol += 8;
144 outcol &= ~7;
145 outcol--;
146 c = ' ';
147 /* FALLTHROUGH */
148 default:
149 if ((w = wcwidth(c)) <= 0)
150 w = 1; /* XXX */
151 if (outcol + w > 132) {
152 outcol += w;
153 continue;
155 cp = &page[outline][outcol];
156 outcol += w;
157 if (c == '_') {
158 if (suppresul)
159 continue;
160 cp += 132;
161 c = '-';
163 if (*cp == 0) {
164 for (i = 0; i < w; i++)
165 cp[i] = c;
166 dp = cp - (outcol - w);
167 for (cp--; cp >= dp && *cp == 0; cp--)
168 *cp = ' ';
169 } else {
170 if (plus(c, *cp) || plus(*cp, c))
171 *cp = '+';
172 else if (*cp == ' ' || *cp == 0) {
173 for (i = 1; i < w; i++)
174 if (cp[i] != ' ' &&
175 cp[i] != 0)
176 goto cont;
177 for (i = 0; i < w; i++)
178 cp[i] = c;
181 cont:
182 continue;
185 if (ferror(stdin))
186 err(1, NULL);
187 } while (argc > 0);
188 fflush(stdout);
189 exit(0);
192 static void
193 usage(void)
195 fprintf(stderr, "usage: colcrt [-] [-2] [file ...]\n");
196 exit(1);
199 static int
200 plus(wchar_t c, wchar_t d)
203 return ((c == '|' && d == '-') || d == '_');
206 static void
207 pflush(int ol)
209 static int first;
210 int i;
211 wchar_t *cp;
212 char lastomit;
213 int l, w;
215 l = ol;
216 lastomit = 0;
217 if (l > 266)
218 l = 266;
219 else
220 l |= 1;
221 for (i = first | 1; i < l; i++) {
222 move(i, i - 1);
223 move(i, i + 1);
225 for (i = first; i < l; i++) {
226 cp = page[i];
227 if (printall == 0 && lastomit == 0 && *cp == 0) {
228 lastomit = 1;
229 continue;
231 lastomit = 0;
232 while (*cp != L'\0') {
233 if ((w = wcwidth(*cp)) > 0) {
234 putwchar(*cp);
235 cp += w;
236 } else
237 cp++;
239 putwchar(L'\n');
241 wmemcpy(page[0], page[ol], (267 - ol) * 132);
242 wmemset(page[267- ol], L'\0', ol * 132);
243 outline -= ol;
244 outcol = 0;
245 first = 1;
248 static void
249 move(int l, int m)
251 wchar_t *cp, *dp;
253 for (cp = page[l], dp = page[m]; *cp; cp++, dp++) {
254 switch (*cp) {
255 case '|':
256 if (*dp != ' ' && *dp != '|' && *dp != 0)
257 return;
258 break;
259 case ' ':
260 break;
261 default:
262 return;
265 if (*cp == 0) {
266 for (cp = page[l], dp = page[m]; *cp; cp++, dp++)
267 if (*cp == '|')
268 *dp = '|';
269 else if (*dp == 0)
270 *dp = ' ';
271 page[l][0] = 0;