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