libc: Include <unistd.h> for ftell/ftruncate/truncate prototypes.
[dragonfly.git] / usr.bin / colcrt / colcrt.c
blob0a9332d8ace623e9f116b1ad98ea35782bc7a8a3
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 default:
148 if ((w = wcwidth(c)) <= 0)
149 w = 1; /* XXX */
150 if (outcol + w > 132) {
151 outcol += w;
152 continue;
154 cp = &page[outline][outcol];
155 outcol += w;
156 if (c == '_') {
157 if (suppresul)
158 continue;
159 cp += 132;
160 c = '-';
162 if (*cp == 0) {
163 for (i = 0; i < w; i++)
164 cp[i] = c;
165 dp = cp - (outcol - w);
166 for (cp--; cp >= dp && *cp == 0; cp--)
167 *cp = ' ';
168 } else {
169 if (plus(c, *cp) || plus(*cp, c))
170 *cp = '+';
171 else if (*cp == ' ' || *cp == 0) {
172 for (i = 1; i < w; i++)
173 if (cp[i] != ' ' &&
174 cp[i] != 0)
175 goto cont;
176 for (i = 0; i < w; i++)
177 cp[i] = c;
180 cont:
181 continue;
184 if (ferror(stdin))
185 err(1, NULL);
186 } while (argc > 0);
187 fflush(stdout);
188 exit(0);
191 static void
192 usage(void)
194 fprintf(stderr, "usage: colcrt [-] [-2] [file ...]\n");
195 exit(1);
198 static int
199 plus(wchar_t c, wchar_t d)
202 return ((c == '|' && d == '-') || d == '_');
205 static void
206 pflush(int ol)
208 static int first;
209 int i;
210 wchar_t *cp;
211 char lastomit;
212 int l, w;
214 l = ol;
215 lastomit = 0;
216 if (l > 266)
217 l = 266;
218 else
219 l |= 1;
220 for (i = first | 1; i < l; i++) {
221 move(i, i - 1);
222 move(i, i + 1);
224 for (i = first; i < l; i++) {
225 cp = page[i];
226 if (printall == 0 && lastomit == 0 && *cp == 0) {
227 lastomit = 1;
228 continue;
230 lastomit = 0;
231 while (*cp != L'\0') {
232 if ((w = wcwidth(*cp)) > 0) {
233 putwchar(*cp);
234 cp += w;
235 } else
236 cp++;
238 putwchar(L'\n');
240 wmemcpy(page[0], page[ol], (267 - ol) * 132);
241 wmemset(page[267- ol], L'\0', ol * 132);
242 outline -= ol;
243 outcol = 0;
244 first = 1;
247 static void
248 move(int l, int m)
250 wchar_t *cp, *dp;
252 for (cp = page[l], dp = page[m]; *cp; cp++, dp++) {
253 switch (*cp) {
254 case '|':
255 if (*dp != ' ' && *dp != '|' && *dp != 0)
256 return;
257 break;
258 case ' ':
259 break;
260 default:
261 return;
264 if (*cp == 0) {
265 for (cp = page[l], dp = page[m]; *cp; cp++, dp++)
266 if (*cp == '|')
267 *dp = '|';
268 else if (*dp == 0)
269 *dp = ' ';
270 page[l][0] = 0;