summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@gmx.de>2013-06-29 11:26:08 +0200
committercinap_lenrek <cinap_lenrek@gmx.de>2013-06-29 11:26:08 +0200
commitb34a1394c2ecfeffc290e793016ef73eeece79c5 (patch)
tree3e321e297cb505d996188ede875be642b93a11c8
parent1bf892cc6772820e66a1c6cec8b56dbd7248234f (diff)
downloadplan9front-b34a1394c2ecfeffc290e793016ef73eeece79c5.tar.xz
rio: run filename completion in background process
this avoids locking up rio when doing filename completion on a unresponsive directory.
-rw-r--r--sys/src/cmd/rio/dat.h1
-rw-r--r--sys/src/cmd/rio/wind.c103
2 files changed, 70 insertions, 34 deletions
diff --git a/sys/src/cmd/rio/dat.h b/sys/src/cmd/rio/dat.h
index 1f12eef48..e1d617ac9 100644
--- a/sys/src/cmd/rio/dat.h
+++ b/sys/src/cmd/rio/dat.h
@@ -139,6 +139,7 @@ struct Window
Channel *mouseread; /* chan(Mousereadmesg) */
Channel *wctlread; /* chan(Consreadmesg) */
Channel *kbdread; /* chan(Kbdreadmesg) */
+ Channel *complete; /* chan(Completion*) */
uint nr; /* number of runes in window */
uint maxr; /* number of runes allocated in r */
Rune *r;
diff --git a/sys/src/cmd/rio/wind.c b/sys/src/cmd/rio/wind.c
index 6fd67a559..d8c47d4cb 100644
--- a/sys/src/cmd/rio/wind.c
+++ b/sys/src/cmd/rio/wind.c
@@ -44,6 +44,7 @@ wmk(Image *i, Mousectl *mc, Channel *ck, Channel *cctl, int scrolling)
w->kbdread = chancreate(sizeof(Kbdreadmesg), 0);
w->mouseread = chancreate(sizeof(Mousereadmesg), 0);
w->wctlread = chancreate(sizeof(Consreadmesg), 0);
+ w->complete = chancreate(sizeof(Completion*), 0);
w->scrollr = r;
w->scrollr.max.x = r.min.x+Scrollwid;
w->lastsr = ZR;
@@ -157,17 +158,19 @@ wclose(Window *w)
return 1;
}
+void
+showcandidates(Window *, Completion *);
void
winctl(void *arg)
{
Rune *rp, *bp, *tp, *up;
- uint qh;
+ uint qh, q0;
int nr, nb, c, wid, i, npart, initial, lastb;
char *s, *t, part[3];
Window *w;
Mousestate *mp, m;
- enum { WKbd, WKbdread, WMouse, WMouseread, WCtl, WCwrite, WCread, WWread, NWALT };
+ enum { WKbd, WKbdread, WMouse, WMouseread, WCtl, WCwrite, WCread, WWread, WComplete, NWALT };
Alt alts[NWALT+1];
Mousereadmesg mrm;
Kbdreadmesg krm;
@@ -176,6 +179,7 @@ winctl(void *arg)
Consreadmesg cwrm;
Stringpair pair;
Wctlmesg wcm;
+ Completion *cr;
char buf[4*12+1], *kbdq[8], *kbds;
int kbdqr, kbdqw;
@@ -215,6 +219,9 @@ winctl(void *arg)
alts[WWread].c = w->wctlread;
alts[WWread].v = &cwrm;
alts[WWread].op = CHANSND;
+ alts[WComplete].c = w->complete;
+ alts[WComplete].v = &cr;
+ alts[WComplete].op = CHANRCV;
alts[NWALT].op = CHANEND;
memset(kbdq, 0, sizeof(kbdq));
@@ -418,6 +425,21 @@ winctl(void *arg)
}
send(cwrm.c2, &pair);
continue;
+ case WComplete:
+ if(!w->deleted){
+ if(!cr->advance)
+ showcandidates(w, cr);
+ if(cr->advance){
+ rp = runesmprint("%s", cr->string);
+ nr = runestrlen(rp);
+ q0 = w->q0;
+ q0 = winsert(w, rp, nr, q0);
+ wshow(w, q0+nr);
+ free(rp);
+ }
+ }
+ freecompletion(cr);
+ break;
}
if(!w->deleted)
flushimage(display, 1);
@@ -507,24 +529,53 @@ showcandidates(Window *w, Completion *c)
free(rp);
}
-Rune*
+typedef struct Completejob Completejob;
+struct Completejob
+{
+ char *dir;
+ char *str;
+ Window *win;
+};
+
+void
+completeproc(void *arg)
+{
+ Completejob *job;
+ Completion *c;
+ char buf[128];
+
+ job = arg;
+ snprint(buf, sizeof(buf), "namecomplete %s", job->dir);
+ threadsetname(buf);
+
+ c = complete(job->dir, job->str);
+ if(c != nil && sendp(job->win->complete, c) <= 0)
+ freecompletion(c);
+
+ wclose(job->win);
+
+ free(job->dir);
+ free(job->str);
+ free(job);
+}
+
+void
namecomplete(Window *w)
{
int nstr, npath;
- Rune *rp, *path, *str;
- Completion *c;
- char *s, *dir, *root;
+ Rune *path, *str;
+ char *dir, *root;
+ Completejob *job;
/* control-f: filename completion; works back to white space or / */
if(w->q0<w->nr && w->r[w->q0]>' ') /* must be at end of word */
- return nil;
+ return;
nstr = windfilewidth(w, w->q0, TRUE);
str = runemalloc(nstr);
runemove(str, w->r+(w->q0-nstr), nstr);
npath = windfilewidth(w, w->q0-nstr, FALSE);
path = runemalloc(npath);
runemove(path, w->r+(w->q0-nstr-npath), npath);
- rp = nil;
/* is path rooted? if not, we need to make it relative to window path */
if(npath>0 && path[0]=='/'){
@@ -538,34 +589,24 @@ namecomplete(Window *w)
dir = malloc(strlen(root)+1+UTFmax*npath+1);
sprint(dir, "%s/%.*S", root, npath, path);
}
- dir = cleanname(dir);
-
- s = smprint("%.*S", nstr, str);
- c = complete(dir, s);
- free(s);
- if(c == nil)
- goto Return;
- if(!c->advance)
- showcandidates(w, c);
+ /* run in background, winctl will collect the result on w->complete chan */
+ job = emalloc(sizeof *job);
+ job->str = smprint("%.*S", nstr, str);
+ job->dir = cleanname(dir);
+ job->win = w;
+ incref(w);
+ proccreate(completeproc, job, STACK);
- if(c->advance)
- rp = runesmprint("%s", c->string);
-
- Return:
- freecompletion(c);
- free(dir);
free(path);
free(str);
- return rp;
}
void
wkeyctl(Window *w, Rune r)
{
uint q0 ,q1;
- int n, nb, nr;
- Rune *rp;
+ int n, nb;
int *notefd;
switch(r){
@@ -679,14 +720,7 @@ wkeyctl(Window *w, Rune r)
return;
case Kack: /* ^F: file name completion */
case Kins: /* Insert: file name completion */
- rp = namecomplete(w);
- if(rp == nil)
- return;
- nr = runestrlen(rp);
- q0 = w->q0;
- q0 = winsert(w, rp, nr, q0);
- wshow(w, q0+nr);
- free(rp);
+ namecomplete(w);
return;
case Kbs: /* ^H: erase character */
case Knack: /* ^U: erase line */
@@ -1193,6 +1227,7 @@ wctlmesg(Window *w, int m, Rectangle r, void *p)
chanfree(w->mouseread);
chanfree(w->wctlread);
chanfree(w->kbdread);
+ chanfree(w->complete);
free(w->raw);
free(w->r);
free(w->dir);