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 }