Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

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