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