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