123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304 |
- /*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
- /* col - eliminate reverse line feeds */
- #include <u.h>
- #include <libc.h>
- #include <ctype.h>
- #include <bio.h>
- enum {
- ESC = '\033',
- RLF = '\013',
- PL = 256,
- LINELN = 800,
- Tabstop = 8, /* must be power of 2 */
- };
- static int bflag, xflag, fflag;
- static int cp, lp;
- static int half;
- static int ll, llh, mustwr;
- static int pcp = 0;
- static char *page[PL];
- static char *line;
- static char lbuff[LINELN];
- static Biobuf bin, bout;
- void emit(char *s, int lineno);
- void incr(void), decr(void);
- void outc(Rune);
- static void
- usage(void)
- {
- fprint(2, "usage: %s [-bfx]\n", argv0);
- exits("usage");
- }
- void
- main(int argc, char **argv)
- {
- int i, lno;
- int32_t ch;
- Rune c;
- ARGBEGIN{
- case 'b':
- bflag++;
- break;
- case 'f':
- fflag++;
- break;
- case 'x':
- xflag++;
- break;
- default:
- usage();
- }ARGEND;
- for (ll=0; ll < PL; ll++)
- page[ll] = nil;
- cp = 0;
- ll = 0;
- mustwr = PL;
- line = lbuff;
- Binit(&bin, 0, OREAD);
- Binit(&bout, 1, OWRITE);
- while ((ch = Bgetrune(&bin)) != Beof) {
- c = ch;
- switch (c) {
- case '\n':
- incr();
- incr();
- cp = 0;
- break;
- case '\0':
- break;
- case ESC:
- c = Bgetrune(&bin);
- switch (c) {
- case '7': /* reverse full line feed */
- decr();
- decr();
- break;
- case '8': /* reverse half line feed */
- if (fflag)
- decr();
- else
- if (--half < -1) {
- decr();
- decr();
- half += 2;
- }
- break;
- case '9': /* forward half line feed */
- if (fflag)
- incr();
- else
- if (++half > 0) {
- incr();
- incr();
- half -= 2;
- }
- break;
- }
- break;
- case RLF:
- decr();
- decr();
- break;
- case '\r':
- cp = 0;
- break;
- case '\t':
- cp = (cp + Tabstop) & -Tabstop;
- break;
- case '\b':
- if (cp > 0)
- cp--;
- break;
- case ' ':
- cp++;
- break;
- default:
- if (!isascii(c) || isprint(c)) {
- outc(c);
- cp++;
- }
- break;
- }
- }
- for (i=0; i < PL; i++) {
- lno = (mustwr+i) % PL;
- if (page[lno] != 0)
- emit(page[lno], mustwr+i-PL);
- }
- emit(" ", (llh + 1) & -2);
- exits(0);
- }
- void
- outc(Rune c)
- {
- if (lp > cp) {
- line = lbuff;
- lp = 0;
- }
- while (lp < cp) {
- switch (*line) {
- case '\0':
- *line = ' ';
- lp++;
- break;
- case '\b':
- lp--;
- break;
- default:
- lp++;
- break;
- }
- line++;
- }
- while (*line == '\b')
- line += 2;
- if (bflag || *line == '\0' || *line == ' ')
- cp += runetochar(line, &c) - 1;
- else {
- char c1, c2, c3;
- c1 = *++line;
- *line++ = '\b';
- c2 = *line;
- *line++ = c;
- while (c1) {
- c3 = *line;
- *line++ = c1;
- c1 = c2;
- c2 = c3;
- }
- lp = 0;
- line = lbuff;
- }
- }
- void
- store(int lno)
- {
- lno %= PL;
- if (page[lno] != nil)
- free(page[lno]);
- page[lno] = malloc((unsigned)strlen(lbuff) + 2);
- if (page[lno] == nil)
- sysfatal("out of memory");
- strcpy(page[lno], lbuff);
- }
- void
- fetch(int lno)
- {
- char *p;
- lno %= PL;
- p = lbuff;
- while (*p)
- *p++ = '\0';
- line = lbuff;
- lp = 0;
- if (page[lno])
- strcpy(line, page[lno]);
- }
- void
- emit(char *s, int lineno)
- {
- int ncp;
- char *p;
- static int cline = 0;
- if (*s) {
- while (cline < lineno - 1) {
- Bputc(&bout, '\n');
- pcp = 0;
- cline += 2;
- }
- if (cline != lineno) {
- Bputc(&bout, ESC);
- Bputc(&bout, '9');
- cline++;
- }
- if (pcp)
- Bputc(&bout, '\r');
- pcp = 0;
- p = s;
- while (*p) {
- ncp = pcp;
- while (*p++ == ' ')
- if ((++ncp & 7) == 0 && !xflag) {
- pcp = ncp;
- Bputc(&bout, '\t');
- }
- if (!*--p)
- break;
- while (pcp < ncp) {
- Bputc(&bout, ' ');
- pcp++;
- }
- Bputc(&bout, *p);
- if (*p++ == '\b')
- pcp--;
- else
- pcp++;
- }
- }
- }
- void
- incr(void)
- {
- int lno;
- store(ll++);
- if (ll > llh)
- llh = ll;
- lno = ll % PL;
- if (ll >= mustwr && page[lno]) {
- emit(page[lno], ll - PL);
- mustwr++;
- free(page[lno]);
- page[lno] = nil;
- }
- fetch(ll);
- }
- void
- decr(void)
- {
- if (ll > mustwr - PL) {
- store(ll--);
- fetch(ll);
- }
- }
|