Plan 9 from Bell Labs’s /usr/web/sources/contrib/fst/root/sys/src/cmd/aux/histogram.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


#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, vmax = 100;
double scale = 1.0;
uint nval;
int dontdie = 0;
int 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;
	sprint(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);
	sprint(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)
{
	Channel *c = arg;
	Biobufhdr b;
	int fd;
	char *p, *f[2];
	uchar buf[512];
	double v;

	threadsetname("reader");
	fd = dup(0, -1);
	Binits(&b, fd, OREAD, buf, 512);

	while(p = Brdline(&b, '\n')) {
		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)
{
	Mousectl *mc;
	Keyboardctl *kc;
	Channel *dc;
	double dm;
	Mouse mm;
	Rune km;
	int rm;
	char *mitems[] = {
		"exit",
		nil
	};
	Menu menu = {
		mitems,
		nil,
		-1
	};

	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},
	};

	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: aux/histogram [-h] [-c color index[-v maxv] [-s scale] [-r minx,miny,maxx,maxy] [-t 'title']\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", ARGF());
		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()));
		col %= sizeof(colors)/sizeof(colors[0]);
		break;
	default:
		usage();
	}ARGEND;

	while(q = strchr(p, ','))
		*q = ' ';

	histogram(p);
}


Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.