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