12 Dot = 2, /* height of dot */
13 Lx = 4, /* x offset */
14 Ly = 4, /* y offset */
15 Bw = 2, /* border width */
23 char *title = "histogram";
27 double vmax = 100, scale = 1.0;
29 int dontdie = 0, col = 1;
32 { 0xFFAAAAFF, 0xFFAAAAFF, 0xBB5D5DFF }, /* Peach */
33 { DPalebluegreen, DPalegreygreen, DPurpleblue }, /* Aqua */
34 { DPaleyellow, DDarkyellow, DYellowgreen }, /* Yellow */
35 { DPalegreen, DMedgreen, DDarkgreen }, /* Green */
36 { 0x00AAFFFF, 0x00AAFFFF, 0x0088CCFF }, /* Blue */
37 { 0xEEEEEEFF, 0xCCCCCCFF, 0x888888F }, /* Grey */
43 neutral = allocimagemix(display, colors[i][0], DWhite);
44 light = allocimage(display, Rect(0,0,1,1), CMAP8, 1, colors[i][1]);
45 dark = allocimage(display, Rect(0,0,1,1), CMAP8, 1, colors[i][2]);
46 txtcolor = display->black;
50 erealloc(void *v, ulong sz)
54 sysfatal("realloc: %r");
55 threadexitsall("memory");
61 datapoint(int x, double v)
68 p.y = hrect.max.y - Dy(hrect)*y - Dot;
71 if(p.y > hrect.max.y - Dot)
72 p.y = hrect.max.y - Dot;
77 drawdatum(int x, double prev, double v)
82 q = datapoint(x, prev);
84 draw(screen, Rect(p.x, hrect.min.y, p.x+1, p.y), neutral,
86 draw(screen, Rect(p.x, p.y, p.x+1, q.y+Dot), dark, nil, ZP);
87 draw(screen, Rect(p.x, q.y+Dot, p.x+1, hrect.max.y), light,
90 draw(screen, Rect(p.x, hrect.min.y, p.x+1, q.y), neutral,
92 draw(screen, Rect(p.x, q.y, p.x+1, p.y+Dot), dark, nil, ZP);
93 draw(screen, Rect(p.x, p.y+Dot, p.x+1, hrect.max.y), light,
100 updatehistogram(double v)
104 draw(screen, hrect, screen, nil, Pt(hrect.min.x+1, hrect.min.y));
107 drawdatum(hrect.max.x-1, data[0], v);
108 memmove(&data[1], &data[0], (nval-1) * sizeof data[0]);
110 snprint(buf, sizeof buf, "%0.9f", v);
111 stringbg(screen, maxvloc, txtcolor, ZP, display->defaultfont, buf,
113 flushimage(display, 1);
117 redrawhistogram(int new)
125 if(new && getwindow(display, Refnone) < 0)
126 sysfatal("getwindow: %r");
129 draw(screen, r, neutral, nil, ZP);
130 p = string(screen, addpt(r.min, Pt(Lx, Ly)), txtcolor, ZP,
131 display->defaultfont, title);
134 p.y += display->defaultfont->height + Ly;
136 q = subpt(r.max, Pt(Lx, Ly));
139 maxvloc = Pt(r.max.x - Lx - stringwidth(display->defaultfont,
140 "999999999"), r.min.y + Ly);
142 nval = abs(Dx(hrect));
144 data = erealloc(data, nval * sizeof data[0]);
146 memset(data+onval, 0, (nval - onval) * sizeof data[0]);
149 border(screen, hrect, -Bw, dark, ZP);
150 snprint(buf, sizeof buf, "%0.9f", data[0]);
151 stringbg(screen, maxvloc, txtcolor, ZP, display->defaultfont, buf,
153 draw(screen, hrect, neutral, nil, ZP);
154 for(i = 1; i < nval - 1; i++)
155 drawdatum(hrect.max.x - i, data[i-1], data[i]);
156 drawdatum(hrect.min.x, data[i], data[i]);
157 flushimage(display, 1);
170 threadsetname("reader");
172 Binits(&b, fd, OREAD, buf, sizeof buf);
174 while((p = Brdline(&b, '\n')) != nil) {
175 p[Blinelen(&b) - 1] = '\0';
176 if(tokenize(p, f, 1) != 1)
187 histogram(char *rect)
198 {nil, &dm, CHANRCV}, /* data from stdin */
199 {nil, &mm, CHANRCV}, /* mouse message */
200 {nil, &km, CHANRCV}, /* keyboard runes */
201 {nil, &rm, CHANRCV}, /* resize event */
204 static char *mitems[] = {
214 memset(&mm, 0, sizeof mm);
215 memset(&km, 0, sizeof km);
218 if(newwindow(rect) < 0)
219 sysfatal("newwindow: %r");
220 if(initdraw(nil, nil, "histogram") < 0)
221 sysfatal("initdraw: %r");
225 mc = initmouse(nil, screen);
227 sysfatal("initmouse: %r");
228 kc = initkeyboard(nil);
230 sysfatal("initkeyboard: %r");
232 dc = chancreate(sizeof dm, 10);
234 sysfatal("chancreate: %r");
239 a[3].c = mc->resizec;
241 proccreate(reader, a[0].c, STACK + sizeof(Biobuf));
250 if(mm.buttons & 4 && menuhit(3, mc, &menu, nil) == 0)
261 sysfatal("shouldn't happen");
273 fprint(2, "usage: histogram [-h] [-c index] [-r minx,miny,maxx,maxy] "
274 "[-s scale] [-t title] [-v maxv]\n");
279 threadmain(int argc, char **argv)
283 p = "-r 0,0,400,150";
287 vmax = strtod(EARGF(usage()), 0);
290 p = smprint("-r %s", EARGF(usage()));
293 scale = strtod(EARGF(usage()), 0);
301 title = EARGF(usage());
304 col = atoi(EARGF(usage())) % nelem(colors);
310 while((q = strchr(p, ',')) != nil)