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