blob: fef6d2dd16a0f3e825cfac058cd85e95075592a2 [file] [log] [blame]
#include <u.h>
#include <libc.h>
#include <draw.h>
#include <thread.h>
#include <bio.h>
#include <mouse.h>
#include <keyboard.h>
void keyboardthread(void *v);
void mousethread(void *v);
void resizethread(void *v);
void updateproc(void *v);
enum {
STACK = 8196,
};
int nokill;
int textmode;
char *title;
Biobuf b;
Image *light;
Image *dark;
Image *text;
Keyboardctl *kc;
Mousectl *mc;
void
initcolor(void)
{
text = display->black;
light = allocimagemix(display, DPalegreen, DWhite);
dark = allocimage(display, Rect(0,0,1,1), CMAP8, 1, DDarkgreen);
}
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, "%d%%", p);
stringbg(screen, addpt(screen->r.min, Pt(Dx(rbar)-30, 4)), text, ZP, display->defaultfont, buf, light, ZP);
lastp = p;
}
if(last != i){
draw(screen, Rect(rbar.min.x+last, rbar.min.y, rbar.min.x+i, rbar.max.y),
dark, nil, ZP);
last = i;
}
flushimage(display, 1);
}
void
resize()
{
Point p, q;
Rectangle r;
r = screen->r;
draw(screen, r, light, nil, ZP);
p = string(screen, addpt(r.min, Pt(4,4)), text, ZP,
display->defaultfont, title);
p.x = r.min.x+4;
p.y += display->defaultfont->height+4;
q = subpt(r.max, Pt(4,4));
rbar = Rpt(p, q);
border(screen, rbar, -2, dark, ZP);
last = 0;
lastp = -1;
flushimage(display, 1);
drawbar();
}
void
keyboardthread(void *v)
{
Rune r;
while(recv(kc->c , &r) == 1){
if ((r == 0x7F || r == 0x03 || r == 'q') && !nokill)
threadexitsall("interrupt");
}
}
void
mousethread(void *v)
{
USED(v);
while(recv(mc->c, 0) == 1); /* to unblock mc->c */
}
void
resizethread(void *v)
{
USED(v);
while(recv(mc->resizec, 0) == 1){
lockdisplay(display);
if(getwindow(display, Refnone) < 0)
sysfatal("attach to window: %r");
resize();
unlockdisplay(display);
}
}
void
updateproc(void *v)
{
char *p, *f[2];
sleep(1000);
while((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);
if(!textmode){
lockdisplay(display);
drawbar();
unlockdisplay(display);
} else
drawbar();
}
threadexitsall("success");
}
void
usage(void)
{
fprint(2, "usage: statusbar [-kt] [-W winsize] 'title'\n");
threadexitsall("usage");
}
void
threadmain(int argc, char **argv)
{
char *p;
int lfd;
p = "300x40@100,100";
ARGBEGIN{
case 'W':
p = ARGF();
break;
case 't':
textmode = 1;
break;
case 'k':
nokill = 1;
break;
default:
usage();
}ARGEND;
if(argc != 1)
usage();
winsize = p;
title = argv[0];
lfd = dup(0, -1);
Binit(&b, lfd, OREAD);
rbar = Rect(0, 0, 60, 1);
if (!textmode){
if(initdraw(0, nil, "bar") < 0)
sysfatal("initdraw: %r");
initcolor();
if((mc = initmouse(nil, screen)) == nil)
sysfatal("initmouse: %r");
if((kc = initkeyboard(nil)) == nil)
sysfatal("initkeyboard: %r");
display->locking = 1;
threadcreate(resizethread, nil, STACK);
threadcreate(keyboardthread, nil, STACK);
threadcreate(mousethread, nil, STACK);
resize();
unlockdisplay(display);
}
proccreate(updateproc, nil, STACK);
}