xref: /plan9/sys/src/cmd/aux/statusbar.c (revision 360053c830964336c451d94d3711af93cb0045f0)
1 #include <u.h>
2 #include <libc.h>
3 #include <draw.h>
4 #include <bio.h>
5 #include <event.h>
6 
7 enum {PNCTL=3};
8 
9 static char* rdenv(char*);
10 int newwin(char*);
11 Rectangle screenrect(void);
12 
13 int nokill;
14 int textmode;
15 char *title;
16 
17 Image *light;
18 Image *dark;
19 Image *text;
20 
21 void
initcolor(void)22 initcolor(void)
23 {
24 	text = display->black;
25 	light = allocimagemix(display, DPalegreen, DWhite);
26 	dark = allocimage(display, Rect(0,0,1,1), CMAP8, 1, DDarkgreen);
27 }
28 
29 Rectangle rbar;
30 Point ptext;
31 vlong n, d;
32 int last;
33 int lastp = -1;
34 
35 char backup[80];
36 
37 void
drawbar(void)38 drawbar(void)
39 {
40 	int i, j;
41 	int p;
42 	char buf[400], bar[200];
43 	static char lastbar[200];
44 
45 	if(n > d || n < 0 || d <= 0)
46 		return;
47 
48 	i = (Dx(rbar)*n)/d;
49 	p = (n*100LL)/d;
50 
51 	if(textmode){
52 		if(Dx(rbar) > 150){
53 			rbar.min.x = 0;
54 			rbar.max.x = 150;
55 			return;
56 		}
57 		bar[0] = '|';
58 		for(j=0; j<i; j++)
59 			bar[j+1] = '#';
60 		for(; j<Dx(rbar); j++)
61 			bar[j+1] = '-';
62 		bar[j++] = '|';
63 		bar[j++] = ' ';
64 		sprint(bar+j, "%3d%% ", p);
65 		for(i=0; bar[i]==lastbar[i] && bar[i]; i++)
66 			;
67 		memset(buf, '\b', strlen(lastbar)-i);
68 		strcpy(buf+strlen(lastbar)-i, bar+i);
69 		if(buf[0])
70 			write(1, buf, strlen(buf));
71 		strcpy(lastbar, bar);
72 		return;
73 	}
74 
75 	if(lastp == p && last == i)
76 		return;
77 
78 	if(lastp != p){
79 		sprint(buf, "%d%%", p);
80 
81 		stringbg(screen, addpt(screen->r.min, Pt(Dx(rbar)-30, 4)), text, ZP, display->defaultfont, buf, light, ZP);
82 		lastp = p;
83 	}
84 
85 	if(last != i){
86 		if(i > last)
87 			draw(screen, Rect(rbar.min.x+last, rbar.min.y, rbar.min.x+i, rbar.max.y),
88 				dark, nil, ZP);
89 		else
90 			draw(screen, Rect(rbar.min.x+i, rbar.min.y, rbar.min.x+last, rbar.max.y),
91 				light, nil, ZP);
92 		last = i;
93 	}
94 	flushimage(display, 1);
95 }
96 
97 void
eresized(int new)98 eresized(int new)
99 {
100 	Point p, q;
101 	Rectangle r;
102 
103 	if(new && getwindow(display, Refnone) < 0)
104 		fprint(2,"can't reattach to window");
105 
106 	r = screen->r;
107 	draw(screen, r, light, nil, ZP);
108 	p = string(screen, addpt(r.min, Pt(4,4)), text, ZP,
109 		display->defaultfont, title);
110 
111 	p.x = r.min.x+4;
112 	p.y += display->defaultfont->height+4;
113 
114 	q = subpt(r.max, Pt(4,4));
115 	rbar = Rpt(p, q);
116 
117 	ptext = Pt(r.max.x-4-stringwidth(display->defaultfont, "100%"), r.min.x+4);
118 	border(screen, rbar, -2, dark, ZP);
119 	last = 0;
120 	lastp = -1;
121 
122 	drawbar();
123 }
124 
125 void
bar(Biobuf * b)126 bar(Biobuf *b)
127 {
128 	char *p, *f[2];
129 	Event e;
130 	int k, die, parent, child;
131 
132 	parent = getpid();
133 
134 	die = 0;
135 	if(textmode)
136 		child = -1;
137 	else
138 	switch(child = rfork(RFMEM|RFPROC)) {
139 	case 0:
140 		sleep(1000);
141 		while(!die && (k = eread(Ekeyboard|Emouse, &e))) {
142 			if(nokill==0 && k == Ekeyboard && (e.kbdc == 0x7F || e.kbdc == 0x03)) { /* del, ctl-c */
143 				die = 1;
144 				postnote(PNPROC, parent, "interrupt");
145 				_exits("interrupt");
146 			}
147 		}
148 		_exits(0);
149 	}
150 
151 	while(!die && (p = Brdline(b, '\n'))) {
152 		p[Blinelen(b)-1] = '\0';
153 		if(tokenize(p, f, 2) != 2)
154 			continue;
155 		n = strtoll(f[0], 0, 0);
156 		d = strtoll(f[1], 0, 0);
157 		drawbar();
158 	}
159 	postnote(PNCTL, child, "kill");
160 }
161 
162 
163 void
usage(void)164 usage(void)
165 {
166 	fprint(2, "usage: aux/statusbar [-kt] [-w minx,miny,maxx,maxy] 'title'\n");
167 	exits("usage");
168 }
169 
170 void
main(int argc,char ** argv)171 main(int argc, char **argv)
172 {
173 	Biobuf b;
174 	char *p, *q;
175 	int lfd;
176 
177 	p = "0,0,200,60";
178 
179 	ARGBEGIN{
180 	case 'w':
181 		p = ARGF();
182 		break;
183 	case 't':
184 		textmode = 1;
185 		break;
186 	case 'k':
187 		nokill = 1;
188 		break;
189 	default:
190 		usage();
191 	}ARGEND;
192 
193 	if(argc != 1)
194 		usage();
195 
196 	title = argv[0];
197 
198 	lfd = dup(0, -1);
199 
200 	while(q = strchr(p, ','))
201 		*q = ' ';
202 	Binit(&b, lfd, OREAD);
203 	if(textmode || newwin(p) < 0){
204 		textmode = 1;
205 		rbar = Rect(0, 0, 60, 1);
206 	}else{
207 		if(initdraw(0, 0, "bar") < 0)
208 			exits("initdraw");
209 		initcolor();
210 		einit(Emouse|Ekeyboard);
211 		eresized(0);
212 	}
213 	bar(&b);
214 
215 	exits(0);
216 }
217 
218 
219 /* all code below this line should be in the library, but is stolen from colors instead */
220 static char*
rdenv(char * name)221 rdenv(char *name)
222 {
223 	char *v;
224 	int fd, size;
225 
226 	fd = open(name, OREAD);
227 	if(fd < 0)
228 		return 0;
229 	size = seek(fd, 0, 2);
230 	v = malloc(size+1);
231 	if(v == 0){
232 		fprint(2, "%s: can't malloc: %r\n", argv0);
233 		exits("no mem");
234 	}
235 	seek(fd, 0, 0);
236 	read(fd, v, size);
237 	v[size] = 0;
238 	close(fd);
239 	return v;
240 }
241 
242 int
newwin(char * win)243 newwin(char *win)
244 {
245 	char *srv, *mntsrv;
246 	char spec[100];
247 	int srvfd, cons, pid;
248 
249 	switch(rfork(RFFDG|RFPROC|RFNAMEG|RFENVG|RFNOTEG|RFNOWAIT)){
250 	case -1:
251 		fprint(2, "statusbar: can't fork: %r\n");
252 		return -1;
253 	case 0:
254 		break;
255 	default:
256 		exits(0);
257 	}
258 
259 	srv = rdenv("/env/wsys");
260 	if(srv == 0){
261 		mntsrv = rdenv("/mnt/term/env/wsys");
262 		if(mntsrv == 0){
263 			fprint(2, "statusbar: can't find $wsys\n");
264 			return -1;
265 		}
266 		srv = malloc(strlen(mntsrv)+10);
267 		sprint(srv, "/mnt/term%s", mntsrv);
268 		free(mntsrv);
269 		pid  = 0;			/* can't send notes to remote processes! */
270 	}else
271 		pid = getpid();
272 	USED(pid);
273 	srvfd = open(srv, ORDWR);
274 	free(srv);
275 	if(srvfd == -1){
276 		fprint(2, "statusbar: can't open %s: %r\n", srv);
277 		return -1;
278 	}
279 	sprint(spec, "new -r %s", win);
280 	if(mount(srvfd, -1, "/mnt/wsys", 0, spec) == -1){
281 		fprint(2, "statusbar: can't mount /mnt/wsys: %r (spec=%s)\n", spec);
282 		return -1;
283 	}
284 	close(srvfd);
285 	unmount("/mnt/acme", "/dev");
286 	bind("/mnt/wsys", "/dev", MBEFORE);
287 	cons = open("/dev/cons", OREAD);
288 	if(cons==-1){
289 	NoCons:
290 		fprint(2, "statusbar: can't open /dev/cons: %r");
291 		return -1;
292 	}
293 	dup(cons, 0);
294 	close(cons);
295 	cons = open("/dev/cons", OWRITE);
296 	if(cons==-1)
297 		goto NoCons;
298 	dup(cons, 1);
299 	dup(cons, 2);
300 	close(cons);
301 //	wctlfd = open("/dev/wctl", OWRITE);
302 	return 0;
303 }
304 
305 Rectangle
screenrect(void)306 screenrect(void)
307 {
308 	int fd;
309 	char buf[12*5];
310 
311 	fd = open("/dev/screen", OREAD);
312 	if(fd == -1)
313 		fd=open("/mnt/term/dev/screen", OREAD);
314 	if(fd == -1){
315 		fprint(2, "%s: can't open /dev/screen: %r\n", argv0);
316 		exits("window read");
317 	}
318 	if(read(fd, buf, sizeof buf) != sizeof buf){
319 		fprint(2, "%s: can't read /dev/screen: %r\n", argv0);
320 		exits("screen read");
321 	}
322 	close(fd);
323 	return Rect(atoi(buf+12), atoi(buf+24), atoi(buf+36), atoi(buf+48));
324 }
325 
326 int
postnote(int group,int pid,char * note)327 postnote(int group, int pid, char *note)
328 {
329 	char file[128];
330 	int f, r;
331 
332 	switch(group) {
333 	case PNPROC:
334 		sprint(file, "/proc/%d/note", pid);
335 		break;
336 	case PNGROUP:
337 		sprint(file, "/proc/%d/notepg", pid);
338 		break;
339 	case PNCTL:
340 		sprint(file, "/proc/%d/ctl", pid);
341 		break;
342 	default:
343 		return -1;
344 	}
345 
346 	f = open(file, OWRITE);
347 	if(f < 0)
348 		return -1;
349 
350 	r = strlen(note);
351 	if(write(f, note, r) != r) {
352 		close(f);
353 		return -1;
354 	}
355 	close(f);
356 	return 0;
357 }
358