plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

win.c (5990B)


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