xref: /netbsd-src/usr.bin/colcrt/colcrt.c (revision 5f7096188587a2c7c95fa3c69b78e1ec9c7923d0)
1 /*
2  * Copyright (c) 1980 The Regents of the University of California.
3  * 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 
34 #ifndef lint
35 char copyright[] =
36 "@(#) Copyright (c) 1980 The Regents of the University of California.\n\
37  All rights reserved.\n";
38 #endif /* not lint */
39 
40 #ifndef lint
41 /*static char sccsid[] = "from: @(#)colcrt.c	5.4 (Berkeley) 6/1/90";*/
42 static char rcsid[] = "$Id: colcrt.c,v 1.2 1993/08/01 18:17:31 mycroft Exp $";
43 #endif /* not lint */
44 
45 #include <stdio.h>
46 /*
47  * colcrt - replaces col for crts with new nroff esp. when using tbl.
48  * Bill Joy UCB July 14, 1977
49  *
50  * This filter uses a screen buffer, 267 half-lines by 132 columns.
51  * It interprets the up and down sequences generated by the new
52  * nroff when used with tbl and by \u \d and \r.
53  * General overstriking doesn't work correctly.
54  * Underlining is split onto multiple lines, etc.
55  *
56  * Option - suppresses all underlining.
57  * Option -2 forces printing of all half lines.
58  */
59 
60 char	page[267][132];
61 
62 int	outline = 1;
63 int	outcol;
64 
65 char	suppresul;
66 char	printall;
67 
68 char	*progname;
69 FILE	*f;
70 
71 main(argc, argv)
72 	int argc;
73 	char *argv[];
74 {
75 	register c;
76 	register char *cp, *dp;
77 
78 	argc--;
79 	progname = *argv++;
80 	while (argc > 0 && argv[0][0] == '-') {
81 		switch (argv[0][1]) {
82 			case 0:
83 				suppresul = 1;
84 				break;
85 			case '2':
86 				printall = 1;
87 				break;
88 			default:
89 				printf("usage: %s [ - ] [ -2 ] [ file ... ]\n", progname);
90 				fflush(stdout);
91 				exit(1);
92 		}
93 		argc--;
94 		argv++;
95 	}
96 	do {
97 		if (argc > 0) {
98 			close(0);
99 			if (!(f = fopen(argv[0], "r"))) {
100 				fflush(stdout);
101 				perror(argv[0]);
102 				exit (1);
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 plus(c, d)
185 	char c, d;
186 {
187 
188 	return (c == '|' && d == '-' || d == '_');
189 }
190 
191 int first;
192 
193 pflush(ol)
194 	int ol;
195 {
196 	register int i, j;
197 	register char *cp;
198 	char lastomit;
199 	int l;
200 
201 	l = ol;
202 	lastomit = 0;
203 	if (l > 266)
204 		l = 266;
205 	else
206 		l |= 1;
207 	for (i = first | 1; i < l; i++) {
208 		move(i, i - 1);
209 		move(i, i + 1);
210 	}
211 	for (i = first; i < l; i++) {
212 		cp = page[i];
213 		if (printall == 0 && lastomit == 0 && *cp == 0) {
214 			lastomit = 1;
215 			continue;
216 		}
217 		lastomit = 0;
218 		printf("%s\n", cp);
219 	}
220 	bcopy(page[ol], page, (267 - ol) * 132);
221 	bzero(page[267- ol], ol * 132);
222 	outline -= ol;
223 	outcol = 0;
224 	first = 1;
225 }
226 
227 move(l, m)
228 	int l, m;
229 {
230 	register char *cp, *dp;
231 
232 	for (cp = page[l], dp = page[m]; *cp; cp++, dp++) {
233 		switch (*cp) {
234 			case '|':
235 				if (*dp != ' ' && *dp != '|' && *dp != 0)
236 					return;
237 				break;
238 			case ' ':
239 				break;
240 			default:
241 				return;
242 		}
243 	}
244 	if (*cp == 0) {
245 		for (cp = page[l], dp = page[m]; *cp; cp++, dp++)
246 			if (*cp == '|')
247 				*dp = '|';
248 			else if (*dp == 0)
249 				*dp = ' ';
250 		page[l][0] = 0;
251 	}
252 }
253