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* 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 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 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 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 66 winopenfile(Window *w, char *f) 67 { 68 return winopenfile1(w, f, ORDWR); 69 } 70 71 void 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 83 winname(Window *w, char *s) 84 { 85 ctlprint(w->ctl, "name %s\n", s); 86 } 87 88 void 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 100 winclosebody(Window *w) 101 { 102 if(w->body != nil){ 103 Bterm(w->body); 104 w->body = nil; 105 } 106 } 107 108 void 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 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 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 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 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 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 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 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 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 260 winclean(Window *w) 261 { 262 if(w->body) 263 Bflush(w->body); 264 ctlprint(w->ctl, "clean\n"); 265 } 266 267 int 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 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* 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* 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