win.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  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 <bio.h>
  12. #include <thread.h>
  13. #include "dat.h"
  14. Window*
  15. newwindow(void)
  16. {
  17. char buf[12];
  18. Window *w;
  19. w = emalloc(sizeof(Window));
  20. w->ctl = open("/mnt/wsys/new/ctl", ORDWR|OCEXEC);
  21. if(w->ctl<0 || read(w->ctl, buf, 12)!=12)
  22. error("can't open window ctl file: %r");
  23. ctlprint(w->ctl, "noscroll\n");
  24. w->id = atoi(buf);
  25. w->event = winopenfile(w, "event");
  26. w->addr = winopenfile(w, "addr");
  27. w->body = winopenfile(w, "body");
  28. w->data = winopenfile(w, "data");
  29. w->cevent = chancreate(sizeof(Event*), 0);
  30. return w;
  31. }
  32. void
  33. winsetdump(Window *w, char *dir, char *cmd)
  34. {
  35. if(dir != nil)
  36. ctlprint(w->ctl, "dumpdir %s\n", dir);
  37. if(cmd != nil)
  38. ctlprint(w->ctl, "dump %s\n", cmd);
  39. }
  40. void
  41. wineventproc(void *v)
  42. {
  43. Window *w;
  44. int i;
  45. w = v;
  46. for(i=0; ; i++){
  47. if(i >= NEVENT)
  48. i = 0;
  49. wingetevent(w, &w->e[i]);
  50. sendp(w->cevent, &w->e[i]);
  51. }
  52. }
  53. int
  54. winopenfile(Window *w, char *f)
  55. {
  56. char buf[64];
  57. int fd;
  58. sprint(buf, "/mnt/wsys/%d/%s", w->id, f);
  59. fd = open(buf, ORDWR|OCEXEC);
  60. if(fd < 0)
  61. error("can't open window file %s: %r", f);
  62. return fd;
  63. }
  64. void
  65. wintagwrite(Window *w, char *s, int n)
  66. {
  67. int fd;
  68. fd = winopenfile(w, "tag");
  69. if(write(fd, s, n) != n)
  70. error("tag write: %r");
  71. close(fd);
  72. }
  73. void
  74. winname(Window *w, char *s)
  75. {
  76. ctlprint(w->ctl, "name %s\n", s);
  77. }
  78. int
  79. wingetec(Window *w)
  80. {
  81. if(w->nbuf == 0){
  82. w->nbuf = read(w->event, w->buf, sizeof w->buf);
  83. if(w->nbuf <= 0){
  84. /* probably because window has exited, and only called by wineventproc, so just shut down */
  85. threadexits(nil);
  86. }
  87. w->bufp = w->buf;
  88. }
  89. w->nbuf--;
  90. return *w->bufp++;
  91. }
  92. int
  93. wingeten(Window *w)
  94. {
  95. int n, c;
  96. n = 0;
  97. while('0'<=(c=wingetec(w)) && c<='9')
  98. n = n*10+(c-'0');
  99. if(c != ' ')
  100. error("event number syntax");
  101. return n;
  102. }
  103. int
  104. wingeter(Window *w, char *buf, int *nb)
  105. {
  106. Rune r;
  107. int n;
  108. r = wingetec(w);
  109. buf[0] = r;
  110. n = 1;
  111. if(r >= Runeself) {
  112. while(!fullrune(buf, n))
  113. buf[n++] = wingetec(w);
  114. chartorune(&r, buf);
  115. }
  116. *nb = n;
  117. return r;
  118. }
  119. void
  120. wingetevent(Window *w, Event *e)
  121. {
  122. int i, nb;
  123. e->c1 = wingetec(w);
  124. e->c2 = wingetec(w);
  125. e->q0 = wingeten(w);
  126. e->q1 = wingeten(w);
  127. e->flag = wingeten(w);
  128. e->nr = wingeten(w);
  129. if(e->nr > EVENTSIZE)
  130. error("event string too long");
  131. e->nb = 0;
  132. for(i=0; i<e->nr; i++){
  133. e->r[i] = wingeter(w, e->b+e->nb, &nb);
  134. e->nb += nb;
  135. }
  136. e->r[e->nr] = 0;
  137. e->b[e->nb] = 0;
  138. if(wingetec(w) != '\n')
  139. error("event syntax error");
  140. }
  141. void
  142. winwriteevent(Window *w, Event *e)
  143. {
  144. fprint(w->event, "%c%c%d %d\n", e->c1, e->c2, e->q0, e->q1);
  145. }
  146. static int
  147. nrunes(char *s, int nb)
  148. {
  149. int i, n;
  150. Rune r;
  151. n = 0;
  152. for(i=0; i<nb; n++)
  153. i += chartorune(&r, s+i);
  154. return n;
  155. }
  156. int
  157. winread(Window *w, uint q0, uint q1, char *data)
  158. {
  159. int m, n, nr, nb;
  160. char buf[256];
  161. if(w->addr < 0)
  162. w->addr = winopenfile(w, "addr");
  163. if(w->data < 0)
  164. w->data = winopenfile(w, "data");
  165. m = q0;
  166. nb = 0;
  167. while(m < q1){
  168. n = sprint(buf, "#%d", m);
  169. if(write(w->addr, buf, n) != n)
  170. error("error writing addr: %r");
  171. n = read(w->data, buf, sizeof buf);
  172. if(n < 0)
  173. error("reading data: %r");
  174. nr = nrunes(buf, n);
  175. while(m+nr >q1){
  176. do; while(n>0 && (buf[--n]&0xC0)==0x80);
  177. --nr;
  178. }
  179. if(n == 0)
  180. break;
  181. memmove(data, buf, n);
  182. nb += n;
  183. data += n;
  184. *data = 0;
  185. m += nr;
  186. }
  187. return nb;
  188. }
  189. void
  190. windormant(Window *w)
  191. {
  192. if(w->addr >= 0){
  193. close(w->addr);
  194. w->addr = -1;
  195. }
  196. if(w->body >= 0){
  197. close(w->body);
  198. w->body = -1;
  199. }
  200. if(w->data >= 0){
  201. close(w->data);
  202. w->data = -1;
  203. }
  204. }
  205. int
  206. windel(Window *w, int sure)
  207. {
  208. if(sure)
  209. write(w->ctl, "delete\n", 7);
  210. else if(write(w->ctl, "del\n", 4) != 4)
  211. return 0;
  212. /* event proc will die due to read error from event file */
  213. windormant(w);
  214. close(w->ctl);
  215. w->ctl = -1;
  216. close(w->event);
  217. w->event = -1;
  218. return 1;
  219. }
  220. void
  221. winclean(Window *w)
  222. {
  223. ctlprint(w->ctl, "clean\n");
  224. }
  225. int
  226. winsetaddr(Window *w, char *addr, int errok)
  227. {
  228. if(w->addr < 0)
  229. w->addr = winopenfile(w, "addr");
  230. if(write(w->addr, addr, strlen(addr)) < 0){
  231. if(!errok)
  232. error("error writing addr(%s): %r", addr);
  233. return 0;
  234. }
  235. return 1;
  236. }
  237. int
  238. winselect(Window *w, char *addr, int errok)
  239. {
  240. if(winsetaddr(w, addr, errok)){
  241. ctlprint(w->ctl, "dot=addr\n");
  242. return 1;
  243. }
  244. return 0;
  245. }