win.c 5.7 KB

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