123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314 |
- #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);
- }
|