summaryrefslogtreecommitdiff
path: root/sys/src/cmd/histogram.c
diff options
context:
space:
mode:
authorTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
committerTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
commite5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch)
treed8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/histogram.c
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/histogram.c')
-rwxr-xr-xsys/src/cmd/histogram.c314
1 files changed, 314 insertions, 0 deletions
diff --git a/sys/src/cmd/histogram.c b/sys/src/cmd/histogram.c
new file mode 100755
index 000000000..3de1950fb
--- /dev/null
+++ b/sys/src/cmd/histogram.c
@@ -0,0 +1,314 @@
+#include <u.h>
+#include <libc.h>
+#include <draw.h>
+#include <bio.h>
+#include <thread.h>
+#include <mouse.h>
+#include <keyboard.h>
+
+enum {
+ STACK = 8*1024,
+
+ Dot = 2, /* height of dot */
+ Lx = 4, /* x offset */
+ Ly = 4, /* y offset */
+ Bw = 2, /* border width */
+};
+
+Image *neutral;
+Image *light;
+Image *dark;
+Image *txtcolor;
+
+char *title = "histogram";
+Rectangle hrect;
+Point maxvloc;
+double *data;
+double vmax = 100, scale = 1.0;
+uint nval;
+int dontdie = 0, col = 1;
+
+int colors[][3] = {
+ { 0xFFAAAAFF, 0xFFAAAAFF, 0xBB5D5DFF }, /* Peach */
+ { DPalebluegreen, DPalegreygreen, DPurpleblue }, /* Aqua */
+ { DPaleyellow, DDarkyellow, DYellowgreen }, /* Yellow */
+ { DPalegreen, DMedgreen, DDarkgreen }, /* Green */
+ { 0x00AAFFFF, 0x00AAFFFF, 0x0088CCFF }, /* Blue */
+ { 0xEEEEEEFF, 0xCCCCCCFF, 0x888888F }, /* Grey */
+};
+
+void
+initcolor(int i)
+{
+ neutral = allocimagemix(display, colors[i][0], DWhite);
+ light = allocimage(display, Rect(0,0,1,1), CMAP8, 1, colors[i][1]);
+ dark = allocimage(display, Rect(0,0,1,1), CMAP8, 1, colors[i][2]);
+ txtcolor = display->black;
+}
+
+void*
+erealloc(void *v, ulong sz)
+{
+ v = realloc(v, sz);
+ if(v == nil){
+ sysfatal("realloc: %r");
+ threadexitsall("memory");
+ }
+ return v;
+}
+
+Point
+datapoint(int x, double v)
+{
+ Point p;
+ double y;
+
+ p.x = x;
+ y = (v*scale) / vmax;
+ p.y = hrect.max.y - Dy(hrect)*y - Dot;
+ if(p.y < hrect.min.y)
+ p.y = hrect.min.y;
+ if(p.y > hrect.max.y - Dot)
+ p.y = hrect.max.y - Dot;
+ return p;
+}
+
+void
+drawdatum(int x, double prev, double v)
+{
+ Point p, q;
+
+ p = datapoint(x, v);
+ q = datapoint(x, prev);
+ if(p.y < q.y){
+ draw(screen, Rect(p.x, hrect.min.y, p.x+1, p.y), neutral,
+ nil, ZP);
+ draw(screen, Rect(p.x, p.y, p.x+1, q.y+Dot), dark, nil, ZP);
+ draw(screen, Rect(p.x, q.y+Dot, p.x+1, hrect.max.y), light,
+ nil, ZP);
+ }else{
+ draw(screen, Rect(p.x, hrect.min.y, p.x+1, q.y), neutral,
+ nil, ZP);
+ draw(screen, Rect(p.x, q.y, p.x+1, p.y+Dot), dark, nil, ZP);
+ draw(screen, Rect(p.x, p.y+Dot, p.x+1, hrect.max.y), light,
+ nil, ZP);
+ }
+
+}
+
+void
+updatehistogram(double v)
+{
+ char buf[32];
+
+ draw(screen, hrect, screen, nil, Pt(hrect.min.x+1, hrect.min.y));
+ if(v * scale > vmax)
+ v = vmax / scale;
+ drawdatum(hrect.max.x-1, data[0], v);
+ memmove(&data[1], &data[0], (nval-1) * sizeof data[0]);
+ data[0] = v;
+ snprint(buf, sizeof buf, "%0.9f", v);
+ stringbg(screen, maxvloc, txtcolor, ZP, display->defaultfont, buf,
+ neutral, ZP);
+ flushimage(display, 1);
+}
+
+void
+redrawhistogram(int new)
+{
+ Point p, q;
+ Rectangle r;
+ uint onval = nval;
+ int i;
+ char buf[32];
+
+ if(new && getwindow(display, Refnone) < 0)
+ sysfatal("getwindow: %r");
+
+ r = screen->r;
+ draw(screen, r, neutral, nil, ZP);
+ p = string(screen, addpt(r.min, Pt(Lx, Ly)), txtcolor, ZP,
+ display->defaultfont, title);
+
+ p.x = r.min.x + Lx;
+ p.y += display->defaultfont->height + Ly;
+
+ q = subpt(r.max, Pt(Lx, Ly));
+ hrect = Rpt(p, q);
+
+ maxvloc = Pt(r.max.x - Lx - stringwidth(display->defaultfont,
+ "999999999"), r.min.y + Ly);
+
+ nval = abs(Dx(hrect));
+ if(nval != onval){
+ data = erealloc(data, nval * sizeof data[0]);
+ if(nval > onval)
+ memset(data+onval, 0, (nval - onval) * sizeof data[0]);
+ }
+
+ border(screen, hrect, -Bw, dark, ZP);
+ snprint(buf, sizeof buf, "%0.9f", data[0]);
+ stringbg(screen, maxvloc, txtcolor, ZP, display->defaultfont, buf,
+ neutral, ZP);
+ draw(screen, hrect, neutral, nil, ZP);
+ for(i = 1; i < nval - 1; i++)
+ drawdatum(hrect.max.x - i, data[i-1], data[i]);
+ drawdatum(hrect.min.x, data[i], data[i]);
+ flushimage(display, 1);
+}
+
+void
+reader(void *arg)
+{
+ int fd;
+ double v;
+ char *p, *f[2];
+ uchar buf[512];
+ Biobufhdr b;
+ Channel *c = arg;
+
+ threadsetname("reader");
+ fd = dup(0, -1);
+ Binits(&b, fd, OREAD, buf, sizeof buf);
+
+ while((p = Brdline(&b, '\n')) != nil) {
+ p[Blinelen(&b) - 1] = '\0';
+ if(tokenize(p, f, 1) != 1)
+ continue;
+ v = strtod(f[0], 0);
+ send(c, &v);
+ }
+ if(!dontdie)
+ threadexitsall(nil);
+}
+
+
+void
+histogram(char *rect)
+{
+ int rm;
+ double dm;
+ Channel *dc;
+ Keyboardctl *kc;
+ Mouse mm;
+ Mousectl *mc;
+ Rune km;
+ Alt a[] = {
+ /* c v op */
+ {nil, &dm, CHANRCV}, /* data from stdin */
+ {nil, &mm, CHANRCV}, /* mouse message */
+ {nil, &km, CHANRCV}, /* keyboard runes */
+ {nil, &rm, CHANRCV}, /* resize event */
+ {nil, nil, CHANEND},
+ };
+ static char *mitems[] = {
+ "exit",
+ nil
+ };
+ static Menu menu = {
+ mitems,
+ nil,
+ -1
+ };
+
+ memset(&mm, 0, sizeof mm);
+ memset(&km, 0, sizeof km);
+ dm = rm = 0;
+
+ if(newwindow(rect) < 0)
+ sysfatal("newwindow: %r");
+ if(initdraw(nil, nil, "histogram") < 0)
+ sysfatal("initdraw: %r");
+
+ initcolor(col);
+
+ mc = initmouse(nil, screen);
+ if(!mc)
+ sysfatal("initmouse: %r");
+ kc = initkeyboard(nil);
+ if(!kc)
+ sysfatal("initkeyboard: %r");
+
+ dc = chancreate(sizeof dm, 10);
+ if(!dc)
+ sysfatal("chancreate: %r");
+
+ a[0].c = dc;
+ a[1].c = mc->c;
+ a[2].c = kc->c;
+ a[3].c = mc->resizec;
+
+ proccreate(reader, a[0].c, STACK + sizeof(Biobuf));
+
+ redrawhistogram(0);
+ for(;;)
+ switch(alt(a)){
+ case 0:
+ updatehistogram(dm);
+ break;
+ case 1:
+ if(mm.buttons & 4 && menuhit(3, mc, &menu, nil) == 0)
+ goto done;
+ break;
+ case 2:
+ if(km == 0x7F)
+ goto done;
+ break;
+ case 3:
+ redrawhistogram(1);
+ break;
+ default:
+ sysfatal("shouldn't happen");
+ }
+done:
+ closekeyboard(kc);
+ closemouse(mc);
+ chanfree(a[0].c);
+ threadexitsall(nil);
+}
+
+void
+usage(void)
+{
+ fprint(2, "usage: histogram [-h] [-c index] [-r minx,miny,maxx,maxy] "
+ "[-s scale] [-t title] [-v maxv]\n");
+ exits("usage");
+}
+
+void
+threadmain(int argc, char **argv)
+{
+ char *p, *q;
+
+ p = "-r 0,0,400,150";
+
+ ARGBEGIN{
+ case 'v':
+ vmax = strtod(EARGF(usage()), 0);
+ break;
+ case 'r':
+ p = smprint("-r %s", EARGF(usage()));
+ break;
+ case 's':
+ scale = strtod(EARGF(usage()), 0);
+ if(scale <= 0)
+ usage();
+ break;
+ case 'h':
+ dontdie = 1;
+ break;
+ case 't':
+ title = EARGF(usage());
+ break;
+ case 'c':
+ col = atoi(EARGF(usage())) % nelem(colors);
+ break;
+ default:
+ usage();
+ }ARGEND;
+
+ while((q = strchr(p, ',')) != nil)
+ *q = ' ';
+
+ histogram(p);
+}