statusbar.c 6.4 KB

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