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