win.c 5.0 KB

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