diff options
author | cinap_lenrek <cinap_lenrek@gmx.de> | 2013-06-29 11:26:08 +0200 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@gmx.de> | 2013-06-29 11:26:08 +0200 |
commit | b34a1394c2ecfeffc290e793016ef73eeece79c5 (patch) | |
tree | 3e321e297cb505d996188ede875be642b93a11c8 | |
parent | 1bf892cc6772820e66a1c6cec8b56dbd7248234f (diff) | |
download | plan9front-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.h | 1 | ||||
-rw-r--r-- | sys/src/cmd/rio/wind.c | 103 |
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); |