plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

statusbar.c (3806B)


      1 #include <u.h>
      2 #include <libc.h>
      3 #include <draw.h>
      4 #include <thread.h>
      5 #include <bio.h>
      6 #include <mouse.h>
      7 #include <keyboard.h>
      8 
      9 void keyboardthread(void *v);
     10 void mousethread(void *v);
     11 void resizethread(void *v);
     12 void updateproc(void *v);
     13 
     14 enum {
     15 	STACK = 8196,
     16 };
     17 
     18 int nokill;
     19 int textmode;
     20 char *title;
     21 
     22 Biobuf b;
     23 Image *light;
     24 Image *dark;
     25 Image *text;
     26 Keyboardctl *kc;
     27 Mousectl *mc;
     28 
     29 void
     30 initcolor(void)
     31 {
     32 	text = display->black;
     33 	light = allocimagemix(display, DPalegreen, DWhite);
     34 	dark = allocimage(display, Rect(0,0,1,1), CMAP8, 1, DDarkgreen);
     35 }
     36 
     37 Rectangle rbar;
     38 vlong n, d;
     39 int last;
     40 int lastp = -1;
     41 
     42 char backup[80];
     43 
     44 void
     45 drawbar(void)
     46 {
     47 	int i, j;
     48 	int p;
     49 	char buf[400], bar[200];
     50 	static char lastbar[200];
     51 
     52 	if(n > d || n < 0 || d <= 0)
     53 		return;
     54 
     55 	i = (Dx(rbar)*n)/d;
     56 	p = (n*100LL)/d;
     57 	if(textmode){
     58 		if(Dx(rbar) > 150){
     59 			rbar.min.x = 0;
     60 			rbar.max.x = 150;
     61 			return;
     62 		}
     63 		bar[0] = '|';
     64 		for(j=0; j<i; j++)
     65 			bar[j+1] = '#';
     66 		for(; j<Dx(rbar); j++)
     67 			bar[j+1] = '-';
     68 		bar[j++] = '|';
     69 		bar[j++] = ' ';
     70 		sprint(bar+j, "%3d%% ", p);
     71 		for(i=0; bar[i]==lastbar[i] && bar[i]; i++)
     72 			;
     73 		memset(buf, '\b', strlen(lastbar)-i);
     74 		strcpy(buf+strlen(lastbar)-i, bar+i);
     75 		if(buf[0])
     76 			write(1, buf, strlen(buf));
     77 		strcpy(lastbar, bar);
     78 		return;
     79 	}
     80 
     81 	if(lastp == p && last == i)
     82 		return;
     83 
     84 	if(lastp != p){
     85 		sprint(buf, "%d%%", p);
     86 		stringbg(screen, addpt(screen->r.min, Pt(Dx(rbar)-30, 4)), text, ZP, display->defaultfont, buf, light, ZP);
     87 		lastp = p;
     88 	}
     89 
     90 	if(last != i){
     91 		draw(screen, Rect(rbar.min.x+last, rbar.min.y, rbar.min.x+i, rbar.max.y),
     92 			dark, nil, ZP);
     93 		last = i;
     94 	}
     95 	flushimage(display, 1);
     96 }
     97 
     98 void
     99 resize()
    100 {
    101 	Point p, q;
    102 	Rectangle r;
    103 
    104 	r = screen->r;
    105 	draw(screen, r, light, nil, ZP);
    106 	p = string(screen, addpt(r.min, Pt(4,4)), text, ZP,
    107 		display->defaultfont, title);
    108 
    109 	p.x = r.min.x+4;
    110 	p.y += display->defaultfont->height+4;
    111 
    112 	q = subpt(r.max, Pt(4,4));
    113 	rbar = Rpt(p, q);
    114 	border(screen, rbar, -2, dark, ZP);
    115 	last = 0;
    116 	lastp = -1;
    117 
    118 	flushimage(display, 1);
    119 	drawbar();
    120 }
    121 
    122 void
    123 keyboardthread(void *v)
    124 {
    125 	Rune r;
    126 
    127 	while(recv(kc->c , &r) == 1){
    128 		if ((r == 0x7F || r == 0x03 || r == 'q') && !nokill)
    129 			threadexitsall("interrupt");
    130 	}
    131 }
    132 
    133 void
    134 mousethread(void *v)
    135 {
    136 	USED(v);
    137 
    138 	while(recv(mc->c, 0) == 1); /* to unblock mc->c */
    139 }
    140 
    141 void
    142 resizethread(void *v)
    143 {
    144 	USED(v);
    145 
    146 	while(recv(mc->resizec, 0) == 1){
    147 		lockdisplay(display);
    148 		if(getwindow(display, Refnone) < 0)
    149 			sysfatal("attach to window: %r");
    150 		resize();
    151 		unlockdisplay(display);
    152 	}
    153 }
    154 
    155 void
    156 updateproc(void *v)
    157 {
    158 	char *p, *f[2];
    159 
    160 	sleep(1000);
    161 	while((p = Brdline(&b, '\n'))){
    162 		p[Blinelen(&b)-1] = '\0';
    163 		if(tokenize(p, f, 2) != 2)
    164 			continue;
    165 		n = strtoll(f[0], 0, 0);
    166 		d = strtoll(f[1], 0, 0);
    167 		if(!textmode){
    168 			lockdisplay(display);
    169 			drawbar();
    170 			unlockdisplay(display);
    171 		} else
    172 			drawbar();
    173 	}
    174 	threadexitsall("success");
    175 }
    176 
    177 void
    178 usage(void)
    179 {
    180 	fprint(2, "usage: statusbar [-kt] [-W winsize] 'title'\n");
    181 	threadexitsall("usage");
    182 }
    183 
    184 void
    185 threadmain(int argc, char **argv)
    186 {
    187 	char *p;
    188 	int lfd;
    189 
    190 	p = "300x40@100,100";
    191 
    192 	ARGBEGIN{
    193 	case 'W':
    194 		p = ARGF();
    195 		break;
    196 	case 't':
    197 		textmode = 1;
    198 		break;
    199 	case 'k':
    200 		nokill = 1;
    201 		break;
    202 	default:
    203 		usage();
    204 	}ARGEND;
    205 
    206 	if(argc != 1)
    207 		usage();
    208 
    209 	winsize = p;
    210 
    211 	title = argv[0];
    212 
    213 	lfd = dup(0, -1);
    214 	Binit(&b, lfd, OREAD);
    215 
    216 	rbar = Rect(0, 0, 60, 1);
    217 	if (!textmode){
    218 		if(initdraw(0, nil, "bar") < 0)
    219 			sysfatal("initdraw: %r");
    220 		initcolor();
    221 		if((mc = initmouse(nil, screen)) == nil)
    222 			sysfatal("initmouse: %r");
    223 		if((kc = initkeyboard(nil)) == nil)
    224 			sysfatal("initkeyboard: %r");
    225 		display->locking = 1;
    226 		threadcreate(resizethread, nil, STACK);
    227 		threadcreate(keyboardthread, nil, STACK);
    228 		threadcreate(mousethread, nil, STACK);
    229 		resize();
    230 		unlockdisplay(display);
    231 	}
    232 	proccreate(updateproc, nil, STACK);
    233 }