xref: /plan9/sys/src/cmd/aux/statusbar.c (revision 360053c830964336c451d94d3711af93cb0045f0)
118027f8cSDavid du Colombier #include <u.h>
218027f8cSDavid du Colombier #include <libc.h>
318027f8cSDavid du Colombier #include <draw.h>
418027f8cSDavid du Colombier #include <bio.h>
518027f8cSDavid du Colombier #include <event.h>
618027f8cSDavid du Colombier 
718027f8cSDavid du Colombier enum {PNCTL=3};
818027f8cSDavid du Colombier 
918027f8cSDavid du Colombier static char* rdenv(char*);
1018027f8cSDavid du Colombier int newwin(char*);
1118027f8cSDavid du Colombier Rectangle screenrect(void);
1218027f8cSDavid du Colombier 
1318027f8cSDavid du Colombier int nokill;
1418027f8cSDavid du Colombier int textmode;
1518027f8cSDavid du Colombier char *title;
1618027f8cSDavid du Colombier 
1718027f8cSDavid du Colombier Image *light;
1818027f8cSDavid du Colombier Image *dark;
1918027f8cSDavid du Colombier Image *text;
2018027f8cSDavid du Colombier 
2118027f8cSDavid du Colombier void
initcolor(void)2218027f8cSDavid du Colombier initcolor(void)
2318027f8cSDavid du Colombier {
2418027f8cSDavid du Colombier 	text = display->black;
2518027f8cSDavid du Colombier 	light = allocimagemix(display, DPalegreen, DWhite);
2618027f8cSDavid du Colombier 	dark = allocimage(display, Rect(0,0,1,1), CMAP8, 1, DDarkgreen);
2718027f8cSDavid du Colombier }
2818027f8cSDavid du Colombier 
2918027f8cSDavid du Colombier Rectangle rbar;
3018027f8cSDavid du Colombier Point ptext;
3118027f8cSDavid du Colombier vlong n, d;
3218027f8cSDavid du Colombier int last;
3318027f8cSDavid du Colombier int lastp = -1;
3418027f8cSDavid du Colombier 
3518027f8cSDavid du Colombier char backup[80];
3618027f8cSDavid du Colombier 
3718027f8cSDavid du Colombier void
drawbar(void)3818027f8cSDavid du Colombier drawbar(void)
3918027f8cSDavid du Colombier {
4018027f8cSDavid du Colombier 	int i, j;
4118027f8cSDavid du Colombier 	int p;
4218027f8cSDavid du Colombier 	char buf[400], bar[200];
4318027f8cSDavid du Colombier 	static char lastbar[200];
4418027f8cSDavid du Colombier 
4518027f8cSDavid du Colombier 	if(n > d || n < 0 || d <= 0)
4618027f8cSDavid du Colombier 		return;
4718027f8cSDavid du Colombier 
4818027f8cSDavid du Colombier 	i = (Dx(rbar)*n)/d;
4918027f8cSDavid du Colombier 	p = (n*100LL)/d;
5018027f8cSDavid du Colombier 
5118027f8cSDavid du Colombier 	if(textmode){
5218027f8cSDavid du Colombier 		if(Dx(rbar) > 150){
5318027f8cSDavid du Colombier 			rbar.min.x = 0;
5418027f8cSDavid du Colombier 			rbar.max.x = 150;
5518027f8cSDavid du Colombier 			return;
5618027f8cSDavid du Colombier 		}
5718027f8cSDavid du Colombier 		bar[0] = '|';
5818027f8cSDavid du Colombier 		for(j=0; j<i; j++)
5918027f8cSDavid du Colombier 			bar[j+1] = '#';
6018027f8cSDavid du Colombier 		for(; j<Dx(rbar); j++)
6118027f8cSDavid du Colombier 			bar[j+1] = '-';
6218027f8cSDavid du Colombier 		bar[j++] = '|';
6318027f8cSDavid du Colombier 		bar[j++] = ' ';
6418027f8cSDavid du Colombier 		sprint(bar+j, "%3d%% ", p);
6518027f8cSDavid du Colombier 		for(i=0; bar[i]==lastbar[i] && bar[i]; i++)
6618027f8cSDavid du Colombier 			;
6718027f8cSDavid du Colombier 		memset(buf, '\b', strlen(lastbar)-i);
6818027f8cSDavid du Colombier 		strcpy(buf+strlen(lastbar)-i, bar+i);
6918027f8cSDavid du Colombier 		if(buf[0])
7018027f8cSDavid du Colombier 			write(1, buf, strlen(buf));
7118027f8cSDavid du Colombier 		strcpy(lastbar, bar);
7218027f8cSDavid du Colombier 		return;
7318027f8cSDavid du Colombier 	}
7418027f8cSDavid du Colombier 
7518027f8cSDavid du Colombier 	if(lastp == p && last == i)
7618027f8cSDavid du Colombier 		return;
7718027f8cSDavid du Colombier 
7818027f8cSDavid du Colombier 	if(lastp != p){
7918027f8cSDavid du Colombier 		sprint(buf, "%d%%", p);
8018027f8cSDavid du Colombier 
8118027f8cSDavid du Colombier 		stringbg(screen, addpt(screen->r.min, Pt(Dx(rbar)-30, 4)), text, ZP, display->defaultfont, buf, light, ZP);
8218027f8cSDavid du Colombier 		lastp = p;
8318027f8cSDavid du Colombier 	}
8418027f8cSDavid du Colombier 
8518027f8cSDavid du Colombier 	if(last != i){
86*360053c8SDavid du Colombier 		if(i > last)
8718027f8cSDavid du Colombier 			draw(screen, Rect(rbar.min.x+last, rbar.min.y, rbar.min.x+i, rbar.max.y),
8818027f8cSDavid du Colombier 				dark, nil, ZP);
89*360053c8SDavid du Colombier 		else
90*360053c8SDavid du Colombier 			draw(screen, Rect(rbar.min.x+i, rbar.min.y, rbar.min.x+last, rbar.max.y),
91*360053c8SDavid du Colombier 				light, nil, ZP);
9218027f8cSDavid du Colombier 		last = i;
9318027f8cSDavid du Colombier 	}
9418027f8cSDavid du Colombier 	flushimage(display, 1);
9518027f8cSDavid du Colombier }
9618027f8cSDavid du Colombier 
9718027f8cSDavid du Colombier void
eresized(int new)9818027f8cSDavid du Colombier eresized(int new)
9918027f8cSDavid du Colombier {
10018027f8cSDavid du Colombier 	Point p, q;
10118027f8cSDavid du Colombier 	Rectangle r;
10218027f8cSDavid du Colombier 
10318027f8cSDavid du Colombier 	if(new && getwindow(display, Refnone) < 0)
10418027f8cSDavid du Colombier 		fprint(2,"can't reattach to window");
10518027f8cSDavid du Colombier 
10618027f8cSDavid du Colombier 	r = screen->r;
10718027f8cSDavid du Colombier 	draw(screen, r, light, nil, ZP);
10818027f8cSDavid du Colombier 	p = string(screen, addpt(r.min, Pt(4,4)), text, ZP,
10918027f8cSDavid du Colombier 		display->defaultfont, title);
11018027f8cSDavid du Colombier 
11118027f8cSDavid du Colombier 	p.x = r.min.x+4;
11218027f8cSDavid du Colombier 	p.y += display->defaultfont->height+4;
11318027f8cSDavid du Colombier 
11418027f8cSDavid du Colombier 	q = subpt(r.max, Pt(4,4));
11518027f8cSDavid du Colombier 	rbar = Rpt(p, q);
11618027f8cSDavid du Colombier 
11718027f8cSDavid du Colombier 	ptext = Pt(r.max.x-4-stringwidth(display->defaultfont, "100%"), r.min.x+4);
11818027f8cSDavid du Colombier 	border(screen, rbar, -2, dark, ZP);
11918027f8cSDavid du Colombier 	last = 0;
12018027f8cSDavid du Colombier 	lastp = -1;
12118027f8cSDavid du Colombier 
12218027f8cSDavid du Colombier 	drawbar();
12318027f8cSDavid du Colombier }
12418027f8cSDavid du Colombier 
12518027f8cSDavid du Colombier void
bar(Biobuf * b)12618027f8cSDavid du Colombier bar(Biobuf *b)
12718027f8cSDavid du Colombier {
12818027f8cSDavid du Colombier 	char *p, *f[2];
12918027f8cSDavid du Colombier 	Event e;
13018027f8cSDavid du Colombier 	int k, die, parent, child;
13118027f8cSDavid du Colombier 
13218027f8cSDavid du Colombier 	parent = getpid();
13318027f8cSDavid du Colombier 
13418027f8cSDavid du Colombier 	die = 0;
13518027f8cSDavid du Colombier 	if(textmode)
13618027f8cSDavid du Colombier 		child = -1;
13718027f8cSDavid du Colombier 	else
13818027f8cSDavid du Colombier 	switch(child = rfork(RFMEM|RFPROC)) {
13918027f8cSDavid du Colombier 	case 0:
14018027f8cSDavid du Colombier 		sleep(1000);
14118027f8cSDavid du Colombier 		while(!die && (k = eread(Ekeyboard|Emouse, &e))) {
14218027f8cSDavid du Colombier 			if(nokill==0 && k == Ekeyboard && (e.kbdc == 0x7F || e.kbdc == 0x03)) { /* del, ctl-c */
14318027f8cSDavid du Colombier 				die = 1;
14418027f8cSDavid du Colombier 				postnote(PNPROC, parent, "interrupt");
14518027f8cSDavid du Colombier 				_exits("interrupt");
14618027f8cSDavid du Colombier 			}
14718027f8cSDavid du Colombier 		}
14818027f8cSDavid du Colombier 		_exits(0);
14918027f8cSDavid du Colombier 	}
15018027f8cSDavid du Colombier 
15118027f8cSDavid du Colombier 	while(!die && (p = Brdline(b, '\n'))) {
15218027f8cSDavid du Colombier 		p[Blinelen(b)-1] = '\0';
15318027f8cSDavid du Colombier 		if(tokenize(p, f, 2) != 2)
15418027f8cSDavid du Colombier 			continue;
15518027f8cSDavid du Colombier 		n = strtoll(f[0], 0, 0);
15618027f8cSDavid du Colombier 		d = strtoll(f[1], 0, 0);
15718027f8cSDavid du Colombier 		drawbar();
15818027f8cSDavid du Colombier 	}
15918027f8cSDavid du Colombier 	postnote(PNCTL, child, "kill");
16018027f8cSDavid du Colombier }
16118027f8cSDavid du Colombier 
16218027f8cSDavid du Colombier 
16318027f8cSDavid du Colombier void
usage(void)16418027f8cSDavid du Colombier usage(void)
16518027f8cSDavid du Colombier {
166a4162ed5SDavid du Colombier 	fprint(2, "usage: aux/statusbar [-kt] [-w minx,miny,maxx,maxy] 'title'\n");
16718027f8cSDavid du Colombier 	exits("usage");
16818027f8cSDavid du Colombier }
16918027f8cSDavid du Colombier 
17018027f8cSDavid du Colombier void
main(int argc,char ** argv)17118027f8cSDavid du Colombier main(int argc, char **argv)
17218027f8cSDavid du Colombier {
17318027f8cSDavid du Colombier 	Biobuf b;
17418027f8cSDavid du Colombier 	char *p, *q;
17518027f8cSDavid du Colombier 	int lfd;
17618027f8cSDavid du Colombier 
17718027f8cSDavid du Colombier 	p = "0,0,200,60";
17818027f8cSDavid du Colombier 
17918027f8cSDavid du Colombier 	ARGBEGIN{
18018027f8cSDavid du Colombier 	case 'w':
18118027f8cSDavid du Colombier 		p = ARGF();
18218027f8cSDavid du Colombier 		break;
18318027f8cSDavid du Colombier 	case 't':
18418027f8cSDavid du Colombier 		textmode = 1;
18518027f8cSDavid du Colombier 		break;
18618027f8cSDavid du Colombier 	case 'k':
18718027f8cSDavid du Colombier 		nokill = 1;
18818027f8cSDavid du Colombier 		break;
18918027f8cSDavid du Colombier 	default:
19018027f8cSDavid du Colombier 		usage();
19118027f8cSDavid du Colombier 	}ARGEND;
19218027f8cSDavid du Colombier 
19318027f8cSDavid du Colombier 	if(argc != 1)
19418027f8cSDavid du Colombier 		usage();
19518027f8cSDavid du Colombier 
19618027f8cSDavid du Colombier 	title = argv[0];
19718027f8cSDavid du Colombier 
19818027f8cSDavid du Colombier 	lfd = dup(0, -1);
19918027f8cSDavid du Colombier 
20018027f8cSDavid du Colombier 	while(q = strchr(p, ','))
20118027f8cSDavid du Colombier 		*q = ' ';
20218027f8cSDavid du Colombier 	Binit(&b, lfd, OREAD);
20318027f8cSDavid du Colombier 	if(textmode || newwin(p) < 0){
20418027f8cSDavid du Colombier 		textmode = 1;
20518027f8cSDavid du Colombier 		rbar = Rect(0, 0, 60, 1);
20618027f8cSDavid du Colombier 	}else{
2072cca75a1SDavid du Colombier 		if(initdraw(0, 0, "bar") < 0)
2082cca75a1SDavid du Colombier 			exits("initdraw");
20918027f8cSDavid du Colombier 		initcolor();
21018027f8cSDavid du Colombier 		einit(Emouse|Ekeyboard);
21118027f8cSDavid du Colombier 		eresized(0);
21218027f8cSDavid du Colombier 	}
21318027f8cSDavid du Colombier 	bar(&b);
2142cca75a1SDavid du Colombier 
2152cca75a1SDavid du Colombier 	exits(0);
21618027f8cSDavid du Colombier }
21718027f8cSDavid du Colombier 
21818027f8cSDavid du Colombier 
21918027f8cSDavid du Colombier /* all code below this line should be in the library, but is stolen from colors instead */
22018027f8cSDavid du Colombier static char*
rdenv(char * name)22118027f8cSDavid du Colombier rdenv(char *name)
22218027f8cSDavid du Colombier {
22318027f8cSDavid du Colombier 	char *v;
22418027f8cSDavid du Colombier 	int fd, size;
22518027f8cSDavid du Colombier 
22618027f8cSDavid du Colombier 	fd = open(name, OREAD);
22718027f8cSDavid du Colombier 	if(fd < 0)
22818027f8cSDavid du Colombier 		return 0;
22918027f8cSDavid du Colombier 	size = seek(fd, 0, 2);
23018027f8cSDavid du Colombier 	v = malloc(size+1);
23118027f8cSDavid du Colombier 	if(v == 0){
23218027f8cSDavid du Colombier 		fprint(2, "%s: can't malloc: %r\n", argv0);
23318027f8cSDavid du Colombier 		exits("no mem");
23418027f8cSDavid du Colombier 	}
23518027f8cSDavid du Colombier 	seek(fd, 0, 0);
23618027f8cSDavid du Colombier 	read(fd, v, size);
23718027f8cSDavid du Colombier 	v[size] = 0;
23818027f8cSDavid du Colombier 	close(fd);
23918027f8cSDavid du Colombier 	return v;
24018027f8cSDavid du Colombier }
24118027f8cSDavid du Colombier 
24218027f8cSDavid du Colombier int
newwin(char * win)24318027f8cSDavid du Colombier newwin(char *win)
24418027f8cSDavid du Colombier {
24518027f8cSDavid du Colombier 	char *srv, *mntsrv;
24618027f8cSDavid du Colombier 	char spec[100];
24718027f8cSDavid du Colombier 	int srvfd, cons, pid;
24818027f8cSDavid du Colombier 
24918027f8cSDavid du Colombier 	switch(rfork(RFFDG|RFPROC|RFNAMEG|RFENVG|RFNOTEG|RFNOWAIT)){
25018027f8cSDavid du Colombier 	case -1:
251a4162ed5SDavid du Colombier 		fprint(2, "statusbar: can't fork: %r\n");
25218027f8cSDavid du Colombier 		return -1;
25318027f8cSDavid du Colombier 	case 0:
25418027f8cSDavid du Colombier 		break;
25518027f8cSDavid du Colombier 	default:
25618027f8cSDavid du Colombier 		exits(0);
25718027f8cSDavid du Colombier 	}
25818027f8cSDavid du Colombier 
25918027f8cSDavid du Colombier 	srv = rdenv("/env/wsys");
26018027f8cSDavid du Colombier 	if(srv == 0){
26118027f8cSDavid du Colombier 		mntsrv = rdenv("/mnt/term/env/wsys");
26218027f8cSDavid du Colombier 		if(mntsrv == 0){
263a4162ed5SDavid du Colombier 			fprint(2, "statusbar: can't find $wsys\n");
26418027f8cSDavid du Colombier 			return -1;
26518027f8cSDavid du Colombier 		}
26618027f8cSDavid du Colombier 		srv = malloc(strlen(mntsrv)+10);
26718027f8cSDavid du Colombier 		sprint(srv, "/mnt/term%s", mntsrv);
26818027f8cSDavid du Colombier 		free(mntsrv);
26918027f8cSDavid du Colombier 		pid  = 0;			/* can't send notes to remote processes! */
27018027f8cSDavid du Colombier 	}else
27118027f8cSDavid du Colombier 		pid = getpid();
27218027f8cSDavid du Colombier 	USED(pid);
27318027f8cSDavid du Colombier 	srvfd = open(srv, ORDWR);
27418027f8cSDavid du Colombier 	free(srv);
27518027f8cSDavid du Colombier 	if(srvfd == -1){
276a4162ed5SDavid du Colombier 		fprint(2, "statusbar: can't open %s: %r\n", srv);
27718027f8cSDavid du Colombier 		return -1;
27818027f8cSDavid du Colombier 	}
27918027f8cSDavid du Colombier 	sprint(spec, "new -r %s", win);
28018027f8cSDavid du Colombier 	if(mount(srvfd, -1, "/mnt/wsys", 0, spec) == -1){
281a4162ed5SDavid du Colombier 		fprint(2, "statusbar: can't mount /mnt/wsys: %r (spec=%s)\n", spec);
28218027f8cSDavid du Colombier 		return -1;
28318027f8cSDavid du Colombier 	}
28418027f8cSDavid du Colombier 	close(srvfd);
28518027f8cSDavid du Colombier 	unmount("/mnt/acme", "/dev");
28618027f8cSDavid du Colombier 	bind("/mnt/wsys", "/dev", MBEFORE);
28718027f8cSDavid du Colombier 	cons = open("/dev/cons", OREAD);
28818027f8cSDavid du Colombier 	if(cons==-1){
28918027f8cSDavid du Colombier 	NoCons:
290a4162ed5SDavid du Colombier 		fprint(2, "statusbar: can't open /dev/cons: %r");
29118027f8cSDavid du Colombier 		return -1;
29218027f8cSDavid du Colombier 	}
29318027f8cSDavid du Colombier 	dup(cons, 0);
29418027f8cSDavid du Colombier 	close(cons);
29518027f8cSDavid du Colombier 	cons = open("/dev/cons", OWRITE);
29618027f8cSDavid du Colombier 	if(cons==-1)
29718027f8cSDavid du Colombier 		goto NoCons;
29818027f8cSDavid du Colombier 	dup(cons, 1);
29918027f8cSDavid du Colombier 	dup(cons, 2);
30018027f8cSDavid du Colombier 	close(cons);
30118027f8cSDavid du Colombier //	wctlfd = open("/dev/wctl", OWRITE);
30218027f8cSDavid du Colombier 	return 0;
30318027f8cSDavid du Colombier }
30418027f8cSDavid du Colombier 
30518027f8cSDavid du Colombier Rectangle
screenrect(void)30618027f8cSDavid du Colombier screenrect(void)
30718027f8cSDavid du Colombier {
30818027f8cSDavid du Colombier 	int fd;
30918027f8cSDavid du Colombier 	char buf[12*5];
31018027f8cSDavid du Colombier 
31118027f8cSDavid du Colombier 	fd = open("/dev/screen", OREAD);
31218027f8cSDavid du Colombier 	if(fd == -1)
31318027f8cSDavid du Colombier 		fd=open("/mnt/term/dev/screen", OREAD);
31418027f8cSDavid du Colombier 	if(fd == -1){
31518027f8cSDavid du Colombier 		fprint(2, "%s: can't open /dev/screen: %r\n", argv0);
31618027f8cSDavid du Colombier 		exits("window read");
31718027f8cSDavid du Colombier 	}
31818027f8cSDavid du Colombier 	if(read(fd, buf, sizeof buf) != sizeof buf){
31918027f8cSDavid du Colombier 		fprint(2, "%s: can't read /dev/screen: %r\n", argv0);
32018027f8cSDavid du Colombier 		exits("screen read");
32118027f8cSDavid du Colombier 	}
32218027f8cSDavid du Colombier 	close(fd);
32318027f8cSDavid du Colombier 	return Rect(atoi(buf+12), atoi(buf+24), atoi(buf+36), atoi(buf+48));
32418027f8cSDavid du Colombier }
32518027f8cSDavid du Colombier 
32618027f8cSDavid du Colombier int
postnote(int group,int pid,char * note)32718027f8cSDavid du Colombier postnote(int group, int pid, char *note)
32818027f8cSDavid du Colombier {
32918027f8cSDavid du Colombier 	char file[128];
33018027f8cSDavid du Colombier 	int f, r;
33118027f8cSDavid du Colombier 
33218027f8cSDavid du Colombier 	switch(group) {
33318027f8cSDavid du Colombier 	case PNPROC:
33418027f8cSDavid du Colombier 		sprint(file, "/proc/%d/note", pid);
33518027f8cSDavid du Colombier 		break;
33618027f8cSDavid du Colombier 	case PNGROUP:
33718027f8cSDavid du Colombier 		sprint(file, "/proc/%d/notepg", pid);
33818027f8cSDavid du Colombier 		break;
33918027f8cSDavid du Colombier 	case PNCTL:
34018027f8cSDavid du Colombier 		sprint(file, "/proc/%d/ctl", pid);
34118027f8cSDavid du Colombier 		break;
34218027f8cSDavid du Colombier 	default:
34318027f8cSDavid du Colombier 		return -1;
34418027f8cSDavid du Colombier 	}
34518027f8cSDavid du Colombier 
34618027f8cSDavid du Colombier 	f = open(file, OWRITE);
34718027f8cSDavid du Colombier 	if(f < 0)
34818027f8cSDavid du Colombier 		return -1;
34918027f8cSDavid du Colombier 
35018027f8cSDavid du Colombier 	r = strlen(note);
35118027f8cSDavid du Colombier 	if(write(f, note, r) != r) {
35218027f8cSDavid du Colombier 		close(f);
35318027f8cSDavid du Colombier 		return -1;
35418027f8cSDavid du Colombier 	}
35518027f8cSDavid du Colombier 	close(f);
35618027f8cSDavid du Colombier 	return 0;
35718027f8cSDavid du Colombier }
358