win.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  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 "win.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 = -1; /* will be opened when needed */
  27. w->body = nil;
  28. w->data = -1;
  29. w->cevent = chancreate(sizeof(Event*), 0);
  30. if(w->cevent == nil)
  31. error("cevent is nil: %r");
  32. return w;
  33. }
  34. void
  35. winsetdump(Window *w, char *dir, char *cmd)
  36. {
  37. if(dir != nil)
  38. ctlprint(w->ctl, "dumpdir %s\n", dir);
  39. if(cmd != nil)
  40. ctlprint(w->ctl, "dump %s\n", cmd);
  41. }
  42. void
  43. wineventproc(void *v)
  44. {
  45. Window *w;
  46. int i;
  47. threadsetname("wineventproc");
  48. w = v;
  49. for(i=0; ; i++){
  50. if(i >= NEVENT)
  51. i = 0;
  52. wingetevent(w, &w->e[i]);
  53. sendp(w->cevent, &w->e[i]);
  54. }
  55. }
  56. int
  57. winopenfile(Window *w, char *f)
  58. {
  59. char buf[64];
  60. int fd;
  61. sprint(buf, "/mnt/wsys/%d/%s", w->id, f);
  62. fd = open(buf, ORDWR|OCEXEC);
  63. if(fd < 0)
  64. error("can't open window file %s: %r", f);
  65. return fd;
  66. }
  67. void
  68. wintagwrite(Window *w, char *s, int n)
  69. {
  70. int fd;
  71. fd = winopenfile(w, "tag");
  72. if(write(fd, s, n) != n)
  73. error("tag write: %r");
  74. close(fd);
  75. }
  76. void
  77. winname(Window *w, char *s)
  78. {
  79. ctlprint(w->ctl, "name %s\n", s);
  80. }
  81. void
  82. winopenbody(Window *w, int mode)
  83. {
  84. char buf[256];
  85. sprint(buf, "/mnt/wsys/%d/body", w->id);
  86. w->body = Bopen(buf, mode|OCEXEC);
  87. if(w->body == nil)
  88. error("can't open window body file: %r");
  89. }
  90. void
  91. winclosebody(Window *w)
  92. {
  93. if(w->body != nil){
  94. Bterm(w->body);
  95. w->body = nil;
  96. }
  97. }
  98. void
  99. winwritebody(Window *w, char *s, int n)
  100. {
  101. if(w->body == nil)
  102. winopenbody(w, OWRITE);
  103. if(Bwrite(w->body, s, n) != n)
  104. error("write error to window: %r");
  105. }
  106. int
  107. wingetec(Window *w)
  108. {
  109. if(w->nbuf == 0){
  110. w->nbuf = read(w->event, w->buf, sizeof w->buf);
  111. if(w->nbuf <= 0){
  112. /* probably because window has exited, and only called by wineventproc, so just shut down */
  113. threadexits(nil);
  114. }
  115. w->bufp = w->buf;
  116. }
  117. w->nbuf--;
  118. return *w->bufp++;
  119. }
  120. int
  121. wingeten(Window *w)
  122. {
  123. int n, c;
  124. n = 0;
  125. while('0'<=(c=wingetec(w)) && c<='9')
  126. n = n*10+(c-'0');
  127. if(c != ' ')
  128. error("event number syntax");
  129. return n;
  130. }
  131. int
  132. wingeter(Window *w, char *buf, int *nb)
  133. {
  134. Rune r;
  135. int n;
  136. r = wingetec(w);
  137. buf[0] = r;
  138. n = 1;
  139. if(r >= Runeself) {
  140. while(!fullrune(buf, n))
  141. buf[n++] = wingetec(w);
  142. chartorune(&r, buf);
  143. }
  144. *nb = n;
  145. return r;
  146. }
  147. void
  148. wingetevent(Window *w, Event *e)
  149. {
  150. int i, nb;
  151. e->c1 = wingetec(w);
  152. e->c2 = wingetec(w);
  153. e->q0 = wingeten(w);
  154. e->q1 = wingeten(w);
  155. e->flag = wingeten(w);
  156. e->nr = wingeten(w);
  157. if(e->nr > EVENTSIZE)
  158. error("event string too long");
  159. e->nb = 0;
  160. for(i=0; i<e->nr; i++){
  161. e->r[i] = wingeter(w, e->b+e->nb, &nb);
  162. e->nb += nb;
  163. }
  164. e->r[e->nr] = 0;
  165. e->b[e->nb] = 0;
  166. if(wingetec(w) != '\n')
  167. error("event syntax error");
  168. }
  169. void
  170. winwriteevent(Window *w, Event *e)
  171. {
  172. fprint(w->event, "%c%c%d %d\n", e->c1, e->c2, e->q0, e->q1);
  173. }
  174. static int
  175. nrunes(char *s, int nb)
  176. {
  177. int i, n;
  178. Rune r;
  179. n = 0;
  180. for(i=0; i<nb; n++)
  181. i += chartorune(&r, s+i);
  182. return n;
  183. }
  184. void
  185. winread(Window *w, uint q0, uint q1, char *data)
  186. {
  187. int m, n, nr;
  188. char buf[256];
  189. if(w->addr < 0)
  190. w->addr = winopenfile(w, "addr");
  191. if(w->data < 0)
  192. w->data = winopenfile(w, "data");
  193. m = q0;
  194. while(m < q1){
  195. n = sprint(buf, "#%d", m);
  196. if(write(w->addr, buf, n) != n)
  197. error("error writing addr: %r");
  198. n = read(w->data, buf, sizeof buf);
  199. if(n <= 0)
  200. error("reading data: %r");
  201. nr = nrunes(buf, n);
  202. while(m+nr >q1){
  203. do; while(n>0 && (buf[--n]&0xC0)==0x80);
  204. --nr;
  205. }
  206. if(n == 0)
  207. break;
  208. memmove(data, buf, n);
  209. data += n;
  210. *data = 0;
  211. m += nr;
  212. }
  213. }
  214. void
  215. windormant(Window *w)
  216. {
  217. if(w->addr >= 0){
  218. close(w->addr);
  219. w->addr = -1;
  220. }
  221. if(w->body != nil){
  222. Bterm(w->body);
  223. w->body = nil;
  224. }
  225. if(w->data >= 0){
  226. close(w->data);
  227. w->data = -1;
  228. }
  229. }
  230. int
  231. windel(Window *w, int sure)
  232. {
  233. if(sure)
  234. write(w->ctl, "delete\n", 7);
  235. else if(write(w->ctl, "del\n", 4) != 4)
  236. return 0;
  237. /* event proc will die due to read error from event file */
  238. windormant(w);
  239. close(w->ctl);
  240. w->ctl = -1;
  241. close(w->event);
  242. w->event = -1;
  243. return 1;
  244. }
  245. void
  246. winclean(Window *w)
  247. {
  248. if(w->body)
  249. Bflush(w->body);
  250. ctlprint(w->ctl, "clean\n");
  251. }
  252. int
  253. winsetaddr(Window *w, char *addr, int errok)
  254. {
  255. if(w->addr < 0)
  256. w->addr = winopenfile(w, "addr");
  257. if(write(w->addr, addr, strlen(addr)) < 0){
  258. if(!errok)
  259. error("error writing addr(%s): %r", addr);
  260. return 0;
  261. }
  262. return 1;
  263. }
  264. int
  265. winselect(Window *w, char *addr, int errok)
  266. {
  267. if(winsetaddr(w, addr, errok)){
  268. ctlprint(w->ctl, "dot=addr\n");
  269. return 1;
  270. }
  271. return 0;
  272. }
  273. char*
  274. winreadbody(Window *w, int *np) /* can't use readfile because acme doesn't report the length */
  275. {
  276. char *s;
  277. int m, na, n;
  278. if(w->body != nil)
  279. winclosebody(w);
  280. winopenbody(w, OREAD);
  281. s = nil;
  282. na = 0;
  283. n = 0;
  284. for(;;){
  285. if(na < n+512){
  286. na += 1024;
  287. s = realloc(s, na+1);
  288. }
  289. m = Bread(w->body, s+n, na-n);
  290. if(m <= 0)
  291. break;
  292. n += m;
  293. }
  294. s[n] = 0;
  295. winclosebody(w);
  296. *np = n;
  297. return s;
  298. }