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