xref: /original-bsd/usr.bin/colcrt/colcrt.c (revision 1e7fda44)
1 static char *sccsid = "@(#)colcrt.c	4.2 (Berkeley) 04/03/81";
2 #include <stdio.h>
3 /*
4  * colcrt - replaces col for crts with new nroff esp. when using tbl.
5  * Bill Joy UCB July 14, 1977
6  *
7  * This filter uses a screen buffer, 267 half-lines by 132 columns.
8  * It interprets the up and down sequences generated by the new
9  * nroff when used with tbl and by \u \d and \r.
10  * General overstriking doesn't work correctly.
11  * Underlining is split onto multiple lines, etc.
12  *
13  * Option - suppresses all underlining.
14  * Option -2 forces printing of all half lines.
15  */
16 
17 char	page[267][132];
18 
19 int	outline = 1;
20 int	outcol;
21 
22 char	buf[BUFSIZ];
23 char	suppresul;
24 char	printall;
25 
26 char	*progname;
27 FILE	*f;
28 
29 main(argc, argv)
30 	int argc;
31 	char *argv[];
32 {
33 	register c;
34 	register char *cp, *dp;
35 
36 	argc--;
37 	progname = *argv++;
38 	while (argc > 0 && argv[0][0] == '-') {
39 		switch (argv[0][1]) {
40 			case 0:
41 				suppresul = 1;
42 				break;
43 			case '2':
44 				printall = 1;
45 				break;
46 			default:
47 				printf("usage: %s [ - ] [ -2 ] [ file ... ]\n", progname);
48 				fflush(stdout);
49 				exit(1);
50 		}
51 		argc--;
52 		argv++;
53 	}
54 	setbuf(stdout, buf);
55 	do {
56 		if (argc > 0) {
57 			close(0);
58 			if ((f=fopen(argv[0], "r")
59 ) < 0) {
60 				fflush(stdout);
61 				perror(argv[0]);
62 				fflush(stdout);
63 				exit (1);
64 			}
65 			argc--;
66 			argv++;
67 		}
68 		for (;;) {
69 			c = getc(stdin);
70 			if (c == -1) {
71 				pflush(outline);
72 				fflush(stdout);
73 				break;
74 			}
75 			switch (c) {
76 				case '\n':
77 					if (outline >= 265)
78 						pflush(62);
79 					outline += 2;
80 					outcol = 0;
81 					continue;
82 				case '\016':
83 					case '\017':
84 					continue;
85 				case 033:
86 					c = getc(stdin);
87 					switch (c) {
88 						case '9':
89 							if (outline >= 266)
90 								pflush(62);
91 							outline++;
92 							continue;
93 						case '8':
94 							if (outline >= 1)
95 								outline--;
96 							continue;
97 						case '7':
98 							outline -= 2;
99 							if (outline < 0)
100 								outline = 0;
101 							continue;
102 						default:
103 							continue;
104 					}
105 				case '\b':
106 					if (outcol)
107 						outcol--;
108 					continue;
109 				case '\t':
110 					outcol += 8;
111 					outcol &= ~7;
112 					outcol--;
113 					c = ' ';
114 				default:
115 					if (outcol >= 132) {
116 						outcol++;
117 						continue;
118 					}
119 					cp = &page[outline][outcol];
120 					outcol++;
121 					if (c == '_') {
122 						if (suppresul)
123 							continue;
124 						cp += 132;
125 						c = '-';
126 					}
127 					if (*cp == 0) {
128 						*cp = c;
129 						dp = cp - outcol;
130 						for (cp--; cp >= dp && *cp == 0; cp--)
131 							*cp = ' ';
132 					} else
133 						if (plus(c, *cp) || plus(*cp, c))
134 							*cp = '+';
135 						else if (*cp == ' ' || *cp == 0)
136 							*cp = c;
137 					continue;
138 			}
139 		}
140 	} while (argc > 0);
141 	fflush(stdout);
142 	exit(0);
143 }
144 
145 plus(c, d)
146 	char c, d;
147 {
148 
149 	return (c == '|' && d == '-' || d == '_');
150 }
151 
152 int first;
153 
154 pflush(ol)
155 	int ol;
156 {
157 	register int i, j;
158 	register char *cp;
159 	char lastomit;
160 	int l;
161 
162 	l = ol;
163 	lastomit = 0;
164 	if (l > 266)
165 		l = 266;
166 	else
167 		l |= 1;
168 	for (i = first | 1; i < l; i++) {
169 		move(i, i - 1);
170 		move(i, i + 1);
171 	}
172 	for (i = first; i < l; i++) {
173 		cp = page[i];
174 		if (printall == 0 && lastomit == 0 && *cp == 0) {
175 			lastomit = 1;
176 			continue;
177 		}
178 		lastomit = 0;
179 		printf("%s\n", cp);
180 	}
181 	copy(page, page[ol], (267 - ol) * 132);
182 	clear(page[267- ol], ol * 132);
183 	outline -= ol;
184 	outcol = 0;
185 	first = 1;
186 }
187 move(l, m)
188 	int l, m;
189 {
190 	register char *cp, *dp;
191 
192 	for (cp = page[l], dp = page[m]; *cp; cp++, dp++) {
193 		switch (*cp) {
194 			case '|':
195 				if (*dp != ' ' && *dp != '|' && *dp != 0)
196 					return;
197 				break;
198 			case ' ':
199 				break;
200 			default:
201 				return;
202 		}
203 	}
204 	if (*cp == 0) {
205 		for (cp = page[l], dp = page[m]; *cp; cp++, dp++)
206 			if (*cp == '|')
207 				*dp = '|';
208 			else if (*dp == 0)
209 				*dp = ' ';
210 		page[l][0] = 0;
211 	}
212 }
213 
214 copy(to, from, i)
215 	register char *to, *from;
216 	register int i;
217 {
218 
219 	if (i > 0)
220 		do
221 			*to++ = *from++;
222 		while (--i);
223 }
224 
225 clear(at, cnt)
226 	register char *at;
227 	register int cnt;
228 {
229 
230 	if (cnt > 0)
231 		do
232 			*at++ = 0;
233 		while (--cnt);
234 }
235