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