bargraph.c 5.2 KB

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