aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/draw
diff options
context:
space:
mode:
authorrsc <devnull@localhost>2004-04-25 20:42:08 +0000
committerrsc <devnull@localhost>2004-04-25 20:42:08 +0000
commit4a4a7c3e5b24c8b8f0625d8bbf0697ab94e45bb6 (patch)
treecdbb7917eb466a610852c80a47482368bb6de157 /src/cmd/draw
parentfa2775106836f35d6e22ffa62cc88253e78f4e08 (diff)
downloadplan9port-4a4a7c3e5b24c8b8f0625d8bbf0697ab94e45bb6.tar.gz
plan9port-4a4a7c3e5b24c8b8f0625d8bbf0697ab94e45bb6.tar.bz2
plan9port-4a4a7c3e5b24c8b8f0625d8bbf0697ab94e45bb6.zip
whoops
Diffstat (limited to 'src/cmd/draw')
-rw-r--r--src/cmd/draw/mc.c309
-rw-r--r--src/cmd/draw/mkfile3
2 files changed, 312 insertions, 0 deletions
diff --git a/src/cmd/draw/mc.c b/src/cmd/draw/mc.c
new file mode 100644
index 00000000..d1071fee
--- /dev/null
+++ b/src/cmd/draw/mc.c
@@ -0,0 +1,309 @@
+/*
+ * 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 <sys/ioctl.h>
+#include <sys/termios.h>
+#include <libc.h>
+#include <draw.h>
+#include <bio.h>
+#include <fcall.h>
+#include <fs.h>
+#include <thread.h>
+
+#define WIDTH 80
+#define TAB 4
+#define WORD_ALLOC_QUANTA 1024
+#define ALLOC_QUANTA 4096
+
+int wordsize(Rune*, int);
+int nexttab(int);
+
+int tabwid;
+int mintab;
+int linewidth=WIDTH;
+int colonflag=0;
+int tabflag=0; /* -t flag turned off forever, except in acme */
+Rune *cbuf, *cbufp;
+Rune **word;
+int maxwidth=0;
+int nalloc=ALLOC_QUANTA;
+int nwalloc=WORD_ALLOC_QUANTA;
+int nchars=0;
+int nwords=0;
+Biobuf bin;
+Biobuf bout;
+
+void getwidth(void), readbuf(int), error(char *);
+void scanwords(void), columnate(void), morechars(void);
+
+void
+threadmain(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();
+ 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);
+}
+void
+error(char *s)
+{
+ fprint(2, "mc: %s\n", s);
+ exits(s);
+}
+void
+readbuf(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);
+}
+void
+scanwords(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 = wordsize(q, p-q-1);
+ if(w > maxwidth)
+ maxwidth = w;
+ q = p;
+ }
+ }
+}
+
+void
+columnate(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 += wordsize(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');
+ }
+}
+
+int
+wordsize(Rune *w, int nw)
+{
+ if(nw < 0)
+ abort();
+ if(font)
+ return runestringnwidth(font, w, nw);
+ return nw;
+}
+
+int
+nexttab(int col)
+{
+ if(tabwid){
+ col += tabwid;
+ col -= col%tabwid;
+ return col;
+ }
+ return (col|(TAB-1))+1;
+}
+
+void
+morechars(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.
+ */
+int
+windowrect(struct winsize *ws)
+{
+ int tty;
+
+ if((tty = open("/dev/tty", OWRITE)) < 0)
+ tty = 1;
+
+ if(ioctl(tty, TIOCGWINSZ, ws) < 0){
+ if(tty != 1)
+ close(tty);
+ return -1;
+ }
+ if(tty != 1)
+ close(tty);
+ return 0;
+}
+
+void
+getwidth(void)
+{
+ Fsys *fs;
+ char buf[500], *p, *f[10];
+ int fd, n, nf;
+ struct winsize ws;
+
+ if((p = getenv("winid")) != nil){
+ fs = nsmount("acme", "");
+ if(fs == nil)
+ return;
+ snprint(buf, sizeof buf, "acme/%d/ctl", atoi(p));
+ if((fd = fsopenfd(fs, buf, OREAD)) < 0)
+ return;
+ if((n=readn(fd, buf, sizeof buf-1)) <= 0)
+ return;
+ buf[n] = 0;
+ if((nf=tokenize(buf, f, nelem(f))) < 7)
+ return;
+ tabwid = 0;
+ if(nf >= 8 && (tabwid = atoi(f[7])) == 0)
+ return;
+ if((font = openfont(nil, f[6])) == nil)
+ return;
+ mintab = stringwidth(font, "0");
+ if(tabwid == 0)
+ tabwid = mintab*4;
+ linewidth = atoi(f[5]);
+ tabflag = 1;
+ return;
+ }
+
+ if((p = getenv("font")) != nil)
+ font = openfont(nil, p);
+ if(windowrect(&ws) < 0)
+ return;
+ if(ws.ws_ypixel == 0)
+ font = nil;
+ if(font)
+ linewidth = ws.ws_ypixel;
+ linewidth = ws.ws_col;
+}
+
diff --git a/src/cmd/draw/mkfile b/src/cmd/draw/mkfile
index 9bbfdfa1..a12abd81 100644
--- a/src/cmd/draw/mkfile
+++ b/src/cmd/draw/mkfile
@@ -5,6 +5,9 @@ SHORTLIB=draw bio 9
<$PLAN9/src/mkmany
+$O.mc: mc.$O
+ $LD -o $target mc.$O -lfs -lmux -lthread -ldraw -lbio -l9 $LDFLAGS
+
$O.stats: stats.$O
$LD -o $target stats.$O -lthread -ldraw -lbio -l9 $LDFLAGS