Blob


1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include <thread.h>
5 #include <plumb.h>
6 #include <9pclient.h>
7 #include "dat.h"
9 Window*
10 newwindow(void)
11 {
12 char buf[12];
13 Window *w;
15 w = emalloc(sizeof(Window));
16 w->ctl = fsopen(acmefs, "new/ctl", ORDWR|OCEXEC);
17 if(w->ctl == nil || fsread(w->ctl, buf, 12)!=12)
18 error("can't open window ctl file: %r");
20 ctlprint(w->ctl, "noscroll\n");
21 w->id = atoi(buf);
22 w->event = winopenfile(w, "event");
23 w->addr = nil; /* will be opened when needed */
24 w->body = nil;
25 w->data = nil;
26 w->cevent = chancreate(sizeof(Event*), 0);
27 return w;
28 }
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 }
39 void
40 wineventproc(void *v)
41 {
42 Window *w;
43 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 }
54 static CFid*
55 winopenfile1(Window *w, char *f, int m)
56 {
57 char buf[64];
58 CFid* fd;
60 sprint(buf, "%d/%s", w->id, f);
61 fd = fsopen(acmefs, buf, m|OCEXEC);
62 if(fd == nil)
63 error("can't open window file %s: %r", f);
64 return fd;
65 }
67 CFid*
68 winopenfile(Window *w, char *f)
69 {
70 return winopenfile1(w, f, ORDWR);
71 }
73 void
74 wintagwrite(Window *w, char *s, int n)
75 {
76 CFid* fid;
78 fid = winopenfile(w, "tag");
79 if(fswrite(fid, s, n) != n)
80 error("tag write: %r");
81 fsclose(fid);
82 }
84 void
85 winname(Window *w, char *s)
86 {
87 ctlprint(w->ctl, "name %s\n", s);
88 }
90 void
91 winopenbody(Window *w, int mode)
92 {
93 char buf[256];
94 CFid* fid;
96 sprint(buf, "%d/body", w->id);
97 fid = fsopen(acmefs, buf, mode|OCEXEC);
98 w->body = fid;
99 if(w->body == nil)
100 error("can't open window body file: %r");
103 void
104 winclosebody(Window *w)
106 if(w->body != nil){
107 fsclose(w->body);
108 w->body = nil;
112 void
113 winwritebody(Window *w, char *s, int n)
115 if(w->body == nil)
116 winopenbody(w, OWRITE);
117 if(fswrite(w->body, s, n) != n)
118 error("write error to window: %r");
121 int
122 wingetec(Window *w)
124 if(w->nbuf == 0){
125 w->nbuf = fsread(w->event, w->buf, sizeof w->buf);
126 if(w->nbuf <= 0){
127 /* probably because window has exited, and only called by wineventproc, so just shut down */
128 threadexits(nil);
130 w->bufp = w->buf;
132 w->nbuf--;
133 return *w->bufp++;
136 int
137 wingeten(Window *w)
139 int n, c;
141 n = 0;
142 while('0'<=(c=wingetec(w)) && c<='9')
143 n = n*10+(c-'0');
144 if(c != ' ')
145 error("event number syntax");
146 return n;
149 int
150 wingeter(Window *w, char *buf, int *nb)
152 Rune r;
153 int n;
155 r = wingetec(w);
156 buf[0] = r;
157 n = 1;
158 if(r >= Runeself) {
159 while(!fullrune(buf, n))
160 buf[n++] = wingetec(w);
161 chartorune(&r, buf);
163 *nb = n;
164 return r;
167 void
168 wingetevent(Window *w, Event *e)
170 int i, nb;
172 e->c1 = wingetec(w);
173 e->c2 = wingetec(w);
174 e->q0 = wingeten(w);
175 e->q1 = wingeten(w);
176 e->flag = wingeten(w);
177 e->nr = wingeten(w);
178 if(e->nr > EVENTSIZE)
179 error("event string too long");
180 e->nb = 0;
181 for(i=0; i<e->nr; i++){
182 e->r[i] = wingeter(w, e->b+e->nb, &nb);
183 e->nb += nb;
185 e->r[e->nr] = 0;
186 e->b[e->nb] = 0;
187 if(wingetec(w) != '\n')
188 error("event syntax error");
191 void
192 winwriteevent(Window *w, Event *e)
194 fsprint(w->event, "%c%c%d %d\n", e->c1, e->c2, e->q0, e->q1);
197 void
198 winread(Window *w, uint q0, uint q1, char *data)
200 int m, n, nr;
201 char buf[256];
203 if(w->addr == nil)
204 w->addr = winopenfile(w, "addr");
205 if(w->data == nil)
206 w->data = winopenfile(w, "data");
207 m = q0;
208 while(m < q1){
209 n = sprint(buf, "#%d", m);
210 if(fswrite(w->addr, buf, n) != n)
211 error("error writing addr: %r");
212 n = fsread(w->data, buf, sizeof buf);
213 if(n <= 0)
214 error("reading data: %r");
215 nr = utfnlen(buf, n);
216 while(m+nr >q1){
217 do; while(n>0 && (buf[--n]&0xC0)==0x80);
218 --nr;
220 if(n == 0)
221 break;
222 memmove(data, buf, n);
223 data += n;
224 *data = 0;
225 m += nr;
229 void
230 windormant(Window *w)
232 if(w->addr != nil){
233 fsclose(w->addr);
234 w->addr = nil;
236 if(w->body != nil){
237 fsclose(w->body);
238 w->body = nil;
240 if(w->data != nil){
241 fsclose(w->data);
242 w->data = nil;
247 int
248 windel(Window *w, int sure)
250 if(sure)
251 fswrite(w->ctl, "delete\n", 7);
252 else if(fswrite(w->ctl, "del\n", 4) != 4)
253 return 0;
254 /* event proc will die due to read error from event file */
255 windormant(w);
256 fsclose(w->ctl);
257 w->ctl = nil;
258 fsclose(w->event);
259 w->event = nil;
260 return 1;
263 void
264 winclean(Window *w)
266 ctlprint(w->ctl, "clean\n");
269 int
270 winsetaddr(Window *w, char *addr, int errok)
272 if(w->addr == nil)
273 w->addr = winopenfile(w, "addr");
274 if(fswrite(w->addr, addr, strlen(addr)) < 0){
275 if(!errok)
276 error("error writing addr(%s): %r", addr);
277 return 0;
279 return 1;
282 int
283 winselect(Window *w, char *addr, int errok)
285 if(winsetaddr(w, addr, errok)){
286 ctlprint(w->ctl, "dot=addr\n");
287 return 1;
289 return 0;
292 char*
293 winreadbody(Window *w, int *np) /* can't use readfile because acme doesn't report the length */
295 char *s;
296 int m, na, n;
298 if(w->body != nil)
299 winclosebody(w);
300 winopenbody(w, OREAD);
301 s = nil;
302 na = 0;
303 n = 0;
304 for(;;){
305 if(na < n+512){
306 na += 1024;
307 s = realloc(s, na+1);
309 m = fsread(w->body, s+n, na-n);
310 if(m <= 0)
311 break;
312 n += m;
314 s[n] = 0;
315 winclosebody(w);
316 *np = n;
317 return s;
320 char*
321 winselection(Window *w)
323 int m, n;
324 char *buf;
325 char tmp[256];
326 CFid* fid;
328 fid = winopenfile1(w, "rdsel", OREAD);
329 if(fid == nil)
330 error("can't open rdsel: %r");
331 n = 0;
332 buf = nil;
333 for(;;){
334 m = fsread(fid, tmp, sizeof tmp);
335 if(m <= 0)
336 break;
337 buf = erealloc(buf, n+m+1);
338 memmove(buf+n, tmp, m);
339 n += m;
340 buf[n] = '\0';
342 fsclose(fid);
343 return buf;