xref: /csrg-svn/usr.bin/col/col.c (revision 16487)
1 static char *sccsid = "@(#)col.c	4.2 (Berkeley) 05/15/84";
2 # include <stdio.h>
3 # define PL 256
4 # define ESC '\033'
5 # define RLF '\013'
6 # define SI '\017'
7 # define SO '\016'
8 # define GREEK 0200
9 # define LINELN 800
10 
11 char *page[PL];
12 char lbuff [LINELN], *line;
13 int bflag, hflag, fflag;
14 int half;
15 int cp, lp;
16 int ll, llh, mustwr;
17 int pcp = 0;
18 char *pgmname;
19 char	*strcpy();
20 
21 main (argc, argv)
22 	int argc; char **argv;
23 {
24 	int i;
25 	int greek;
26 	register int c;
27 
28 	pgmname = argv[0];
29 
30 	for (i = 1; i < argc; i++) {
31 		register char *p;
32 		if (*argv[i] != '-') {
33 			fprintf (stderr, "%s: bad option %s\n",
34 				pgmname, argv[i]);
35 			exit (2);
36 		}
37 		for (p = argv[i]+1; *p; p++) {
38 			switch (*p) {
39 			case 'b':
40 				bflag++;
41 				break;
42 
43 			case 'h':
44 				hflag++;
45 				break;
46 
47 			case 'f':
48 				fflag++;
49 				break;
50 
51 			default:
52 				fprintf (stderr, "%s: bad option letter %c\n",
53 					pgmname, *p);
54 				exit (2);
55 			}
56 		}
57 	}
58 
59 	for (ll=0; ll<PL; ll++)
60 		page[ll] = 0;
61 
62 	cp = 0;
63 	ll = 0;
64 	greek = 0;
65 	mustwr = PL;
66 	line = lbuff;
67 
68 	while ((c = getchar()) != EOF) {
69 		switch (c) {
70 		case '\n':
71 			incr();
72 			incr();
73 			cp = 0;
74 			continue;
75 
76 		case '\0':
77 			continue;
78 
79 		case ESC:
80 			c = getchar();
81 			switch (c) {
82 			case '7':	/* reverse full line feed */
83 				decr();
84 				decr();
85 				break;
86 
87 			case '8':	/* reverse half line feed */
88 				if (fflag)
89 					decr();
90 				else {
91 					if (--half < -1) {
92 						decr();
93 						decr();
94 						half += 2;
95 					}
96 				}
97 				break;
98 
99 			case '9':	/* forward half line feed */
100 				if (fflag)
101 					incr();
102 				else {
103 					if (++half > 0) {
104 						incr();
105 						incr();
106 						half -= 2;
107 					}
108 				}
109 				break;
110 			}
111 			continue;
112 
113 		case SO:
114 			greek = GREEK;
115 			continue;
116 
117 		case SI:
118 			greek = 0;
119 			continue;
120 
121 		case RLF:
122 			decr();
123 			decr();
124 			continue;
125 
126 		case '\r':
127 			cp = 0;
128 			continue;
129 
130 		case '\t':
131 			cp = (cp + 8) & -8;
132 			continue;
133 
134 		case '\b':
135 			if (cp > 0)
136 				cp--;
137 			continue;
138 
139 		case ' ':
140 			cp++;
141 			continue;
142 
143 		default:
144 			c &= 0177;
145 			if (c > 040 && c < 0177) {	/* if printable */
146 				outc(c | greek);
147 				cp++;
148 			}
149 			continue;
150 		}
151 	}
152 
153 	for (i=0; i<PL; i++)
154 		if (page[(mustwr+i)%PL] != 0)
155 			emit (page[(mustwr+i) % PL], mustwr+i-PL);
156 	emit (" ", (llh + 1) & -2);
157 	exit(0);
158 }
159 
160 outc (c)
161 	register char c;
162 {
163 	if (lp > cp) {
164 		line = lbuff;
165 		lp = 0;
166 	}
167 
168 	while (lp < cp) {
169 		switch (*line) {
170 		case '\0':
171 			*line = ' ';
172 			lp++;
173 			break;
174 
175 		case '\b':
176 			lp--;
177 			break;
178 
179 		default:
180 			lp++;
181 		}
182 		line++;
183 	}
184 	while (*line == '\b') {
185 		line += 2;
186 	}
187 	if (bflag || *line == '\0' || *line == ' ')
188 		*line = c;
189 	else {
190 		register char c1, c2, c3;
191 		c1 = *++line;
192 		*line++ = '\b';
193 		c2 = *line;
194 		*line++ = c;
195 		while (c1) {
196 			c3 = *line;
197 			*line++ = c1;
198 			c1 = c2;
199 			c2 = c3;
200 		}
201 		lp = 0;
202 		line = lbuff;
203 	}
204 }
205 
206 store (lno)
207 {
208 	char *malloc();
209 
210 	lno %= PL;
211 	if (page[lno] != 0)
212 		free (page[lno]);
213 	page[lno] = malloc((unsigned)strlen(lbuff) + 2);
214 	if (page[lno] == 0) {
215 		fprintf (stderr, "%s: no storage\n", pgmname);
216 		exit (2);
217 	}
218 	strcpy (page[lno],lbuff);
219 }
220 
221 fetch(lno)
222 {
223 	register char *p;
224 
225 	lno %= PL;
226 	p = lbuff;
227 	while (*p)
228 		*p++ = '\0';
229 	line = lbuff;
230 	lp = 0;
231 	if (page[lno])
232 		strcpy (line, page[lno]);
233 }
234 emit (s, lineno)
235 	char *s;
236 	int lineno;
237 {
238 	static int cline = 0;
239 	register int ncp;
240 	register char *p;
241 	static int gflag = 0;
242 
243 	if (*s) {
244 		while (cline < lineno - 1) {
245 			putchar ('\n');
246 			pcp = 0;
247 			cline += 2;
248 		}
249 		if (cline != lineno) {
250 			putchar (ESC);
251 			putchar ('9');
252 			cline++;
253 		}
254 		if (pcp)
255 			putchar ('\r');
256 		pcp = 0;
257 		p = s;
258 		while (*p) {
259 			ncp = pcp;
260 			while (*p++ == ' ') {
261 				if ((++ncp & 7) == 0 && hflag) {
262 					pcp = ncp;
263 					putchar ('\t');
264 				}
265 			}
266 			if (!*--p)
267 				break;
268 			while (pcp < ncp) {
269 				putchar (' ');
270 				pcp++;
271 			}
272 			if (gflag != (*p & GREEK) && *p != '\b') {
273 				if (gflag)
274 					putchar (SI);
275 				else
276 					putchar (SO);
277 				gflag ^= GREEK;
278 			}
279 			putchar (*p & ~GREEK);
280 			if (*p++ == '\b')
281 				pcp--;
282 			else
283 				pcp++;
284 		}
285 	}
286 }
287 
288 incr()
289 {
290 	store (ll++);
291 	if (ll > llh)
292 		llh = ll;
293 	if (ll >= mustwr && page[ll%PL]) {
294 		emit (page[ll%PL], ll - PL);
295 		mustwr++;
296 		free (page[ll%PL]);
297 		page[ll%PL] = 0;
298 	}
299 	fetch (ll);
300 }
301 
302 decr()
303 {
304 	if (ll > mustwr - PL) {
305 		store (ll--);
306 		fetch (ll);
307 	}
308 }
309