plan9fox/sys/src/cmd/aux/statusbar.c

238 lines
3.9 KiB
C

#include <u.h>
#include <libc.h>
#include <draw.h>
#include <bio.h>
#include <event.h>
#include <keyboard.h>
int newwin(char*);
int nokill;
int textmode;
char *title;
Image *light;
Image *dark;
Image *text;
void
initcolor(void)
{
text = display->black;
light = allocimagemix(display, DPalegreen, DWhite);
dark = allocimage(display, Rect(0,0,1,1), CMAP8, 1, DDarkgreen);
if(light == nil || dark == nil) sysfatal("initcolor: %r");
}
Rectangle rbar;
vlong n, d;
int last;
int lastp = -1;
char backup[80];
void
drawbar(void)
{
int i, j;
int p;
char buf[400], bar[200];
static char lastbar[200];
if(n > d || n < 0 || d <= 0)
return;
i = (Dx(rbar)*n)/d;
p = (n*100LL)/d;
if(textmode){
if(Dx(rbar) > 150){
rbar.min.x = 0;
rbar.max.x = 150;
return;
}
bar[0] = '|';
for(j=0; j<i; j++)
bar[j+1] = '#';
for(; j<Dx(rbar); j++)
bar[j+1] = '-';
bar[j++] = '|';
bar[j++] = ' ';
sprint(bar+j, "%3d%% ", p);
for(i=0; bar[i]==lastbar[i] && bar[i]; i++)
;
memset(buf, '\b', strlen(lastbar)-i);
strcpy(buf+strlen(lastbar)-i, bar+i);
if(buf[0])
write(1, buf, strlen(buf));
strcpy(lastbar, bar);
return;
}
if(lastp == p && last == i)
return;
if(lastp != p){
sprint(buf, "%3d%%", p);
stringbg(screen, Pt(screen->r.max.x-4-stringwidth(display->defaultfont, buf), screen->r.min.y+4), text, ZP, display->defaultfont, buf, light, ZP);
lastp = p;
}
if(last != i){
if(i > last)
draw(screen, Rect(rbar.min.x+last, rbar.min.y, rbar.min.x+i, rbar.max.y),
dark, nil, ZP);
else
draw(screen, Rect(rbar.min.x+i, rbar.min.y, rbar.min.x+last, rbar.max.y),
light, nil, ZP);
last = i;
}
flushimage(display, 1);
}
void
eresized(int new)
{
if(new && getwindow(display, Refnone) < 0)
fprint(2,"can't reattach to window");
draw(screen, screen->r, light, nil, ZP);
if(title) string(screen, addpt(screen->r.min, Pt(4,4)), text, ZP, font, title);
rbar = insetrect(screen->r, 4);
rbar.min.y += font->height + 4;
border(screen, rbar, -2, dark, ZP);
last = 0;
lastp = -1;
drawbar();
}
void
bar(Biobuf *b)
{
char *p, *f[2];
Event e;
int k, die, parent, child;
parent = getpid();
die = 0;
if(textmode)
child = -1;
else
switch(child = rfork(RFMEM|RFPROC)) {
case 0:
sleep(1000);
while(!die && (k = eread(Ekeyboard|Emouse, &e))) {
if(nokill==0 && k == Ekeyboard && (e.kbdc == Kdel || e.kbdc == Ketx)) {
die = 1;
postnote(PNPROC, parent, "interrupt");
_exits("interrupt");
}
}
_exits(0);
}
while(!die && (p = Brdline(b, '\n'))) {
p[Blinelen(b)-1] = '\0';
if(tokenize(p, f, 2) != 2)
continue;
n = strtoll(f[0], 0, 0);
d = strtoll(f[1], 0, 0);
drawbar();
}
if(textmode)
write(1, "\n", 1);
else
postnote(PNPROC, child, "kill");
}
void
usage(void)
{
fprint(2, "usage: %s [-kt] [-w minx,miny,maxx,maxy] [title]\n", argv0);
exits("usage");
}
void
main(int argc, char **argv)
{
Biobuf b;
char *p, *q;
int lfd;
p = "0,0,200,60";
ARGBEGIN{
case 'w':
p = ARGF();
break;
case 't':
textmode = 1;
break;
case 'k':
nokill = 1;
break;
default:
usage();
}ARGEND;
switch(argc){
default:
usage();
case 1:
title = argv[0];
case 0:
break;
}
lfd = dup(0, -1);
while(q = strchr(p, ','))
*q = ' ';
Binit(&b, lfd, OREAD);
if(textmode || newwin(p) < 0){
textmode = 1;
rbar = Rect(0, 0, 60, 1);
}else{
if(initdraw(0, 0, title ? title : argv0) < 0)
exits("initdraw");
initcolor();
einit(Emouse|Ekeyboard);
eresized(0);
}
bar(&b);
exits(0);
}
int
newwin(char *win)
{
char spec[100];
int cons;
if(win != nil){
snprint(spec, sizeof(spec), "-r %s", win);
win = spec;
}
if(newwindow(win) < 0){
fprint(2, "%s: newwindow: %r", argv0);
return -1;
}
if((cons = open("/dev/cons", OREAD)) < 0){
NoCons:
fprint(2, "%s: can't open /dev/cons: %r", argv0);
return -1;
}
dup(cons, 0);
close(cons);
if((cons = open("/dev/cons", OWRITE)) < 0)
goto NoCons;
dup(cons, 1);
dup(cons, 2);
close(cons);
return 0;
}