1 /*	$OpenBSD: colcrt.c,v 1.8 2003/07/02 21:04:09 deraadt Exp $	*/
2 /*	$NetBSD: colcrt.c,v 1.3 1995/03/26 05:31:00 glass Exp $	*/
3 
4 /*
5  * Copyright (c) 1980, 1993
6  *	The Regents of the University of California.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. Neither the name of the University nor the names of its contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  */
32 
33 #ifndef lint
34 static char copyright[] =
35 "@(#) Copyright (c) 1980, 1993\n\
36 	The Regents of the University of California.  All rights reserved.\n";
37 #endif /* not lint */
38 
39 #ifndef lint
40 #if 0
41 static char sccsid[] = "@(#)colcrt.c	8.1 (Berkeley) 6/6/93";
42 #else
43 static char rcsid[] = "$OpenBSD: colcrt.c,v 1.8 2003/07/02 21:04:09 deraadt Exp $";
44 #endif
45 #endif /* not lint */
46 
47 #include <sys/types.h>
48 #include <unistd.h>
49 #include <stdlib.h>
50 #include <string.h>
51 #include <stdio.h>
52 #include <err.h>
53 
54 /*
55  * colcrt - replaces col for crts with new nroff esp. when using tbl.
56  * Bill Joy UCB July 14, 1977
57  *
58  * This filter uses a screen buffer, 267 half-lines by 132 columns.
59  * It interprets the up and down sequences generated by the new
60  * nroff when used with tbl and by \u \d and \r.
61  * General overstriking doesn't work correctly.
62  * Underlining is split onto multiple lines, etc.
63  *
64  * Option - suppresses all underlining.
65  * Option -2 forces printing of all half lines.
66  */
67 
68 char	page[267][132];
69 
70 int	outline = 1;
71 int	outcol;
72 
73 char	suppresul;
74 char	printall;
75 
76 FILE	*f;
77 
78 void	pflush(int);
79 int	plus(char, char);
80 void	move(int, int);
81 
82 int
main(int argc,char * argv[])83 main(int argc, char *argv[])
84 {
85 	extern char *__progname;
86 	char *cp, *dp;
87 	int c;
88 
89 	argc--;
90 	argv++;
91 	while (argc > 0 && argv[0][0] == '-') {
92 		switch (argv[0][1]) {
93 			case 0:
94 				suppresul = 1;
95 				break;
96 			case '2':
97 				printall = 1;
98 				break;
99 			default:
100 				fprintf(stderr,
101 				    "usage: %s [ - ] [ -2 ] [ file ... ]\n",
102 				    __progname);
103 				fflush(stdout);
104 				exit(1);
105 		}
106 		argc--;
107 		argv++;
108 	}
109 	do {
110 		if (argc > 0) {
111 			close(0);
112 			if (!(f = fopen(argv[0], "r"))) {
113 				fflush(stdout);
114 				err(1, "fopen: %s", argv[0]);
115 			}
116 			argc--;
117 			argv++;
118 		}
119 		for (;;) {
120 			c = getc(stdin);
121 			if (c == -1) {
122 				pflush(outline);
123 				fflush(stdout);
124 				break;
125 			}
126 			switch (c) {
127 				case '\n':
128 					if (outline >= 265)
129 						pflush(62);
130 					outline += 2;
131 					outcol = 0;
132 					continue;
133 				case '\016':
134 					case '\017':
135 					continue;
136 				case 033:
137 					c = getc(stdin);
138 					switch (c) {
139 						case '9':
140 							if (outline >= 266)
141 								pflush(62);
142 							outline++;
143 							continue;
144 						case '8':
145 							if (outline >= 1)
146 								outline--;
147 							continue;
148 						case '7':
149 							outline -= 2;
150 							if (outline < 0)
151 								outline = 0;
152 							continue;
153 						default:
154 							continue;
155 					}
156 				case '\b':
157 					if (outcol)
158 						outcol--;
159 					continue;
160 				case '\t':
161 					outcol += 8;
162 					outcol &= ~7;
163 					outcol--;
164 					c = ' ';
165 				default:
166 					if (outcol >= 132) {
167 						outcol++;
168 						continue;
169 					}
170 					cp = &page[outline][outcol];
171 					outcol++;
172 					if (c == '_') {
173 						if (suppresul)
174 							continue;
175 						cp += 132;
176 						c = '-';
177 					}
178 					if (*cp == 0) {
179 						*cp = c;
180 						dp = cp - outcol;
181 						for (cp--; cp >= dp && *cp == 0; cp--)
182 							*cp = ' ';
183 					} else
184 						if (plus(c, *cp) || plus(*cp, c))
185 							*cp = '+';
186 						else if (*cp == ' ' || *cp == 0)
187 							*cp = c;
188 					continue;
189 			}
190 		}
191 	} while (argc > 0);
192 	fflush(stdout);
193 	exit(0);
194 }
195 
196 int
plus(char c,char d)197 plus(char c, char d)
198 {
199 
200 	return ((c == '|' && d == '-') || d == '_');
201 }
202 
203 int first;
204 
205 void
pflush(int ol)206 pflush(int ol)
207 {
208 	int i;
209 	char *cp;
210 	char lastomit;
211 	int l;
212 
213 	l = ol;
214 	lastomit = 0;
215 	if (l > 266)
216 		l = 266;
217 	else
218 		l |= 1;
219 	for (i = first | 1; i < l; i++) {
220 		move(i, i - 1);
221 		move(i, i + 1);
222 	}
223 	for (i = first; i < l; i++) {
224 		cp = page[i];
225 		if (printall == 0 && lastomit == 0 && *cp == 0) {
226 			lastomit = 1;
227 			continue;
228 		}
229 		lastomit = 0;
230 		printf("%s\n", cp);
231 	}
232 	memmove(page, page[ol], (267 - ol) * 132);
233 	bzero(page[267- ol], ol * 132);
234 	outline -= ol;
235 	outcol = 0;
236 	first = 1;
237 }
238 
239 void
move(int l,int m)240 move(int l, int m)
241 {
242 	char *cp, *dp;
243 
244 	for (cp = page[l], dp = page[m]; *cp; cp++, dp++) {
245 		switch (*cp) {
246 			case '|':
247 				if (*dp != ' ' && *dp != '|' && *dp != 0)
248 					return;
249 				break;
250 			case ' ':
251 				break;
252 			default:
253 				return;
254 		}
255 	}
256 	if (*cp == 0) {
257 		for (cp = page[l], dp = page[m]; *cp; cp++, dp++)
258 			if (*cp == '|')
259 				*dp = '|';
260 			else if (*dp == 0)
261 				*dp = ' ';
262 		page[l][0] = 0;
263 	}
264 }
265