📄 mc.c
字号:
/* * mc - columnate * * mc[-][-LINEWIDTH][-t][file...] * - causes break on colon * -LINEWIDTH sets width of line in which to columnate(default 80) * -t suppresses expanding multiple blanks into tabs * */#include <u.h>#include <libc.h>#include <draw.h>#include <bio.h>#define WIDTH 80#define TAB 4#define WORD_ALLOC_QUANTA 1024#define ALLOC_QUANTA 4096int linewidth=WIDTH;int mintab=1;int colonflag=0;int tabflag=0; /* -t flag turned off forever */Rune *cbuf, *cbufp;Rune **word;int maxwidth=0;int nalloc=ALLOC_QUANTA;int nwalloc=WORD_ALLOC_QUANTA;int nchars=0;int nwords=0;int tabwidth=0;Font *font;Biobuf bin;Biobuf bout;void getwidth(void), readbuf(int), error(char *);void scanwords(void), columnate(void), morechars(void);int wordwidth(Rune*, int);int nexttab(int);voidmain(int argc, char *argv[]){ int i; int lineset; int ifd; lineset = 0; Binit(&bout, 1, OWRITE); while(argc > 1 && argv[1][0] == '-'){ --argc; argv++; switch(argv[0][1]){ case '\0': colonflag = 1; break; case 't': tabflag = 0; break; default: linewidth = atoi(&argv[0][1]); if(linewidth <= 1) linewidth = WIDTH; lineset = 1; break; } } if(lineset == 0){ getwidth(); if(linewidth <= 1){ linewidth = WIDTH; font = nil; } } cbuf = cbufp = malloc(ALLOC_QUANTA*(sizeof *cbuf)); word = malloc(WORD_ALLOC_QUANTA*(sizeof *word)); if(word == 0 || cbuf == 0) error("out of memory"); if(argc == 1) readbuf(0); else{ for(i = 1; i < argc; i++){ if((ifd = open(*++argv, OREAD)) == -1) fprint(2, "mc: can't open %s (%r)\n", *argv); else{ readbuf(ifd); Bflush(&bin); close(ifd); } } } columnate(); exits(0);}voiderror(char *s){ fprint(2, "mc: %s\n", s); exits(s);}voidreadbuf(int fd){ int lastwascolon = 0; long c; int linesiz = 0; Binit(&bin, fd, OREAD); do{ if(nchars++ >= nalloc) morechars(); *cbufp++ = c = Bgetrune(&bin); linesiz++; if(c == '\t') { cbufp[-1] = L' '; while(linesiz%TAB != 0) { if(nchars++ >= nalloc) morechars(); *cbufp++ = L' '; linesiz++; } } if(colonflag && c == ':') lastwascolon++; else if(lastwascolon){ if(c == '\n'){ --nchars; /* skip newline */ *cbufp = L'\0'; while(nchars > 0 && cbuf[--nchars] != '\n') ; if(nchars) nchars++; columnate(); if (nchars) Bputc(&bout, '\n'); Bprint(&bout, "%S", cbuf+nchars); nchars = 0; cbufp = cbuf; } lastwascolon = 0; } if(c == '\n') linesiz = 0; }while(c >= 0);}voidscanwords(void){ Rune *p, *q; int i, w; nwords=0; maxwidth=0; for(p = q = cbuf, i = 0; i < nchars; i++){ if(*p++ == L'\n'){ if(nwords >= nwalloc){ nwalloc += WORD_ALLOC_QUANTA; if((word = realloc(word, nwalloc*sizeof(*word)))==0) error("out of memory"); } word[nwords++] = q; p[-1] = L'\0'; w = wordwidth(q, p-q-1); if(w > maxwidth) maxwidth = w; q = p; } }}voidcolumnate(void){ int i, j; int words_per_line; int nlines; int col; int endcol; scanwords(); if(nwords==0) return; maxwidth = nexttab(maxwidth+mintab-1); words_per_line = linewidth/maxwidth; if(words_per_line <= 0) words_per_line = 1; nlines=(nwords+words_per_line-1)/words_per_line; for(i = 0; i < nlines; i++){ col = endcol = 0; for(j = i; j < nwords; j += nlines){ endcol += maxwidth; Bprint(&bout, "%S", word[j]); col += wordwidth(word[j], runestrlen(word[j])); if(j+nlines < nwords){ if(tabflag) { while(col < endcol){ Bputc(&bout, '\t'); col = nexttab(col); } }else{ while(col < endcol){ Bputc(&bout, ' '); col++; } } } } Bputc(&bout, '\n'); }}intwordwidth(Rune *w, int nw){ if(font) return runestringnwidth(font, w, nw); return nw;}intnexttab(int col){ if(tabwidth){ col += tabwidth; col -= col%tabwidth; return col; } return col+1;}voidmorechars(void){ nalloc += ALLOC_QUANTA; if((cbuf = realloc(cbuf, nalloc*sizeof(*cbuf))) == 0) error("out of memory"); cbufp = cbuf+nchars-1;}/* * These routines discover the width of the display. * It takes some work. If we do the easy calls to the * draw library, the screen flashes due to repainting * when mc exits. */jmp_buf drawjmp;voidterror(Display*, char*){ longjmp(drawjmp, 1);}voidgetwidth(void){ int n, fd; char buf[128], *f[10], *p; if(access("/dev/acme", OREAD) >= 0){ if((fd = open("/dev/acme/ctl", OREAD)) < 0) return; n = read(fd, buf, sizeof buf-1); close(fd); if(n <= 0) return; buf[n] = 0; n = tokenize(buf, f, nelem(f)); if(n < 7) return; if((font = openfont(nil, f[6])) == nil) return; if(n >= 8) tabwidth = atoi(f[7]); else tabwidth = 4*stringwidth(font, "0"); mintab = stringwidth(font, "0"); linewidth = atoi(f[5]); tabflag = 1; return; } if((p = getenv("font")) == nil) return; if((font = openfont(nil, p)) == nil) return; if((fd = open("/dev/window", OREAD)) < 0){ font = nil; return; } n = read(fd, buf, 5*12); close(fd); if(n < 5*12){ font = nil; return; } buf[n] = 0; /* window stucture: 4 bit left edge 1 bit gap 12 bit scrollbar 4 bit gap text 4 bit right edge */ linewidth = atoi(buf+3*12) - atoi(buf+1*12) - (4+1+12+4+4); mintab = stringwidth(font, "0"); if((p = getenv("tabstop")) != nil) tabwidth = atoi(p)*stringwidth(font, "0"); if(tabwidth == 0) tabwidth = 4*stringwidth(font, "0"); tabflag = 1;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -