less -> more
[unix-history] / usr / src / usr.bin / col / col.c
CommitLineData
c155beb2 1static char *sccsid = "@(#)col.c 4.2 (Berkeley) %G%";
faa0f83d
BJ
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
11char *page[PL];
12char lbuff [LINELN], *line;
13int bflag, hflag, fflag;
14int half;
15int cp, lp;
16int ll, llh, mustwr;
17int pcp = 0;
18char *pgmname;
19char *strcpy();
20
21main (argc, argv)
22 int argc; char **argv;
23{
24 int i;
25 int greek;
26 register int c;
faa0f83d 27
faa0f83d
BJ
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
160outc (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
206store (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
221fetch(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}
234emit (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
288incr()
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
302decr()
303{
304 if (ll > mustwr - PL) {
305 store (ll--);
306 fetch (ll);
307 }
308}