Blob


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>
9 void keyboardthread(void *v);
10 void mousethread(void *v);
11 void resizethread(void *v);
12 void updateproc(void *v);
14 enum {
15 STACK = 8196,
16 };
18 int nokill;
19 int textmode;
20 char *title;
22 Biobuf b;
23 Image *light;
24 Image *dark;
25 Image *text;
26 Keyboardctl *kc;
27 Mousectl *mc;
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 }
37 Rectangle rbar;
38 vlong n, d;
39 int last;
40 int lastp = -1;
42 char backup[80];
44 void
45 drawbar(void)
46 {
47 int i, j;
48 int p;
49 char buf[400], bar[200];
50 static char lastbar[200];
52 if(n > d || n < 0 || d <= 0)
53 return;
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 }
81 if(lastp == p && last == i)
82 return;
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 }
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 }
98 void
99 resize()
101 Point p, q;
102 Rectangle r;
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);
109 p.x = r.min.x+4;
110 p.y += display->defaultfont->height+4;
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;
118 flushimage(display, 1);
119 drawbar();
122 void
123 keyboardthread(void *v)
125 Rune r;
127 while(recv(kc->c , &r) == 1){
128 if ((r == 0x7F || r == 0x03 || r == 'q') && !nokill)
129 threadexitsall("interrupt");
133 void
134 mousethread(void *v)
136 USED(v);
138 while(recv(mc->c, 0) == 1); /* to unblock mc->c */
141 void
142 resizethread(void *v)
144 USED(v);
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);
155 void
156 updateproc(void *v)
158 char *p, *f[2];
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();
174 threadexitsall("success");
177 void
178 usage(void)
180 fprint(2, "usage: statusbar [-kt] [-W winsize] 'title'\n");
181 threadexitsall("usage");
184 void
185 threadmain(int argc, char **argv)
187 char *p;
188 int lfd;
190 p = "300x40@100,100";
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;
206 if(argc != 1)
207 usage();
209 winsize = p;
211 title = argv[0];
213 lfd = dup(0, -1);
214 Binit(&b, lfd, OREAD);
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);
232 proccreate(updateproc, nil, STACK);