Commit | Line | Data |
---|---|---|
3b600ead TL |
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 | ||
10 | char *page[PL]; | |
11 | char lbuff [LINELN], *line; | |
12 | int bflag, hflag, fflag; | |
13 | int half; | |
14 | int cp, lp; | |
15 | int ll, llh, mustwr; | |
16 | int pcp = 0; | |
17 | char *pgmname; | |
18 | char *strcpy(); | |
19 | ||
20 | main (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 | ||
161 | outc (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 | ||
207 | store (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 | ||
222 | fetch(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 | } | |
235 | emit (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 | ||
289 | incr() | |
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 | ||
303 | decr() | |
304 | { | |
305 | if (ll > mustwr - PL) { | |
306 | store (ll--); | |
307 | fetch (ll); | |
308 | } | |
309 | } |