diff options
author | Russ Cox <rsc@swtch.com> | 2010-09-03 10:21:16 -0400 |
---|---|---|
committer | Russ Cox <rsc@swtch.com> | 2010-09-03 10:21:16 -0400 |
commit | ef5c6a6edaf3dcf2cddd46841dc0dd8fce2bf967 (patch) | |
tree | e984e781353aa989307b53056ea664185317fc60 /src/cmd/9term | |
parent | a208917e7a935c019095acd1acd8165f08a54b7a (diff) | |
download | plan9port-ef5c6a6edaf3dcf2cddd46841dc0dd8fce2bf967.tar.gz plan9port-ef5c6a6edaf3dcf2cddd46841dc0dd8fce2bf967.tar.bz2 plan9port-ef5c6a6edaf3dcf2cddd46841dc0dd8fce2bf967.zip |
9term, win: better echo cancellation
Also just drop \r from output.
It's a losing battle to keep turning it off.
R=rsc
http://codereview.appspot.com/2128042
Diffstat (limited to 'src/cmd/9term')
-rw-r--r-- | src/cmd/9term/9term.c | 14 | ||||
-rw-r--r-- | src/cmd/9term/SunOS.c | 19 | ||||
-rw-r--r-- | src/cmd/9term/bsdpty.c | 23 | ||||
-rw-r--r-- | src/cmd/9term/rcstart.c | 72 | ||||
-rw-r--r-- | src/cmd/9term/term.h | 4 | ||||
-rw-r--r-- | src/cmd/9term/win.c | 58 |
6 files changed, 129 insertions, 61 deletions
diff --git a/src/cmd/9term/9term.c b/src/cmd/9term/9term.c index 92b253d3..806215df 100644 --- a/src/cmd/9term/9term.c +++ b/src/cmd/9term/9term.c @@ -22,7 +22,6 @@ int plumbfd; int rcpid; int rcfd; int sfd; -int noecho; Window *w; char *fontname; @@ -412,6 +411,9 @@ rcoutputproc(void *arg) fprint(2, "9term: rc read error: %r\n"); threadexitsall("eof on rc output"); } + n = echocancel(data+cnt, n); + if(n == 0) + continue; cnt += n; r = runemalloc(cnt); cvttorunes(data, cnt-UTFmax, r, &nb, &nr, nil); @@ -428,7 +430,7 @@ rcoutputproc(void *arg) nr = label(r, nr); if(nr == 0) continue; - + recv(w->conswrite, &cwm); pair.s = r; pair.ns = nr; @@ -499,7 +501,6 @@ void rcinputproc(void *arg) { static char data[9000]; - int s; Consreadmesg crm; Channel *c1, *c2; Stringpair pair; @@ -513,12 +514,11 @@ rcinputproc(void *arg) pair.ns = sizeof data; send(c1, &pair); recv(c2, &pair); - - s = setecho(sfd, 0); + + if(isecho(sfd)) + echoed(pair.s, pair.ns); if(write(rcfd, pair.s, pair.ns) < 0) threadexitsall(nil); - if(s) - setecho(sfd, s); } } diff --git a/src/cmd/9term/SunOS.c b/src/cmd/9term/SunOS.c index ac1432de..e0f866ab 100644 --- a/src/cmd/9term/SunOS.c +++ b/src/cmd/9term/SunOS.c @@ -78,25 +78,6 @@ isecho(int fd) } int -setecho(int fd, int newe) -{ - int old; - - if(tcgetattr(fd, &ttmode) < 0) - fprint(2, "tcgetattr: %r\n"); - old = (ttmode.c_lflag&ECHO)==ECHO; - if(old != newe){ - if(newe) - ttmode.c_lflag |= ECHO; - else - ttmode.c_lflag &= ~ECHO; - if(tcsetattr(fd, TCSANOW, &ttmode) < 0) - fprint(2, "tcsetattr: %r\n"); - } - return old; -} - -int getintr(int fd) { if(tcgetattr(fd, &ttmode) < 0) diff --git a/src/cmd/9term/bsdpty.c b/src/cmd/9term/bsdpty.c index 52b9bb8a..4836d24d 100644 --- a/src/cmd/9term/bsdpty.c +++ b/src/cmd/9term/bsdpty.c @@ -97,29 +97,6 @@ isecho(int fd) } int -setecho(int fd, int newe) -{ - int old; - - if(tcgetattr(fd, &ttmode) < 0) - fprint(2, "tcgetattr: %r\n"); - old = ttmode.c_lflag & ECHO; - if(old != newe){ - ttmode.c_lflag &= ~ECHO; - ttmode.c_lflag |= newe; - /* - * I tried using TCSADRAIN here, but that causes - * hangs if there is any output waiting for us. - * I guess TCSADRAIN is intended for use by our - * clients, not by us. - */ - if(tcsetattr(fd, 0, &ttmode) < 0) - fprint(2, "tcsetattr: %r\n"); - } - return old; -} - -int getintr(int fd) { if(tcgetattr(fd, &ttmode) < 0) diff --git a/src/cmd/9term/rcstart.c b/src/cmd/9term/rcstart.c index 4d64349c..6b91c869 100644 --- a/src/cmd/9term/rcstart.c +++ b/src/cmd/9term/rcstart.c @@ -87,8 +87,6 @@ rcstart(int argc, char **argv, int *pfd, int *tfd) dup(sfd, 2); sys("stty tabs -onlcr icanon echo erase '^h' intr '^?'", 0); sys("stty onocr", 1); /* not available on mac */ - if(noecho) - sys("stty -echo", 0); for(i=3; i<100; i++) close(i); signal(SIGINT, SIG_DFL); @@ -111,3 +109,73 @@ rcstart(int argc, char **argv, int *pfd, int *tfd) return pid; } +struct { + Lock l; + char buf[1<<20]; + int r, w; +} echo; + +void +echoed(char *p, int n) +{ + lock(&echo.l); + if(echo.r > 0) { + memmove(echo.buf, echo.buf+echo.r, echo.w-echo.r); + echo.w -= echo.r; + echo.r = 0; + } + if(echo.w+n > sizeof echo.buf) + echo.r = echo.w = 0; + if(echo.w+n > sizeof echo.buf) + n = 0; + memmove(echo.buf+echo.w, p, n); + echo.w += n; + unlock(&echo.l); +} + +int +echocancel(char *p, int n) +{ + int i; + + lock(&echo.l); + for(i=0; i<n; i++) { + if(echo.r < echo.w) { + if(echo.buf[echo.r] == p[i]) { + echo.r++; + continue; + } + if(echo.buf[echo.r] == '\n' && p[i] == '\r') + continue; + if(p[i] == 0x08) { + if(i+2 <= n && p[i+1] == ' ' && p[i+2] == 0x08) + i += 2; + continue; + } + } + echo.r = echo.w; + break; + } + unlock(&echo.l); + if(i > 0) + memmove(p, p+i, n-i); + return n-i; +} + +int +dropcrnl(char *p, int n) +{ + char *r, *w; + + for(r=w=p; r<p+n; r++) { + if(r+1<p+n && *r == '\r' && *(r+1) == '\n') + continue; + if(*r == 0x08) { + if(r+2<=p+n && *(r+1) == ' ' && *(r+2) == 0x08) + r += 2; + continue; + } + *w++ = *r; + } + return w-p; +} diff --git a/src/cmd/9term/term.h b/src/cmd/9term/term.h index c8d9926f..e7a1f6b2 100644 --- a/src/cmd/9term/term.h +++ b/src/cmd/9term/term.h @@ -4,7 +4,9 @@ extern void updatewinsize(int, int, int, int); extern int rcfd; extern int rcstart(int, char*[], int*, int*); extern int isecho(int); -extern int setecho(int, int); extern int noecho; extern int getintr(int); extern int loginshell; +extern void echoed(char*, int); +extern int echocancel(char*, int); +extern int dropcrnl(char*, int); diff --git a/src/cmd/9term/win.c b/src/cmd/9term/win.c index bed7f2aa..25dfccc9 100644 --- a/src/cmd/9term/win.c +++ b/src/cmd/9term/win.c @@ -5,7 +5,6 @@ #include <9pclient.h> #include "term.h" -int noecho = 1; #define EVENTSIZE 256 #define STACK 32768 @@ -71,6 +70,7 @@ void sende(Event*, int, CFid*, CFid*, CFid*, int); char *onestring(int, char**); int delete(Event*); void deltype(uint, uint); +void sendbs(int, int); void runproc(void*); int @@ -349,6 +349,7 @@ stdinproc(void *v) CFid *afd = addrfd; int fd0 = rcfd; Event e, e2, e3, e4; + int n; USED(v); @@ -411,7 +412,10 @@ stdinproc(void *v) break; case 'D': - q.p -= delete(&e); + n = delete(&e); + q.p -= n; + if(!isecho(fd0)) + sendbs(fd0, n); break; case 'x': @@ -491,6 +495,14 @@ stdoutproc(void *v) n = read(fd1, buf+npart, 8192); if(n <= 0) error(nil); + + n = echocancel(buf+npart, n); + if(n == 0) + continue; + + n = dropcrnl(buf+npart, n); + if(n == 0) + continue; /* squash NULs */ s = memchr(buf+npart, 0, n); @@ -525,8 +537,10 @@ stdoutproc(void *v) qlock(&q.lk); m = sprint(x, "#%d", q.p); if(fswrite(afd, x, m) != m){ - fprint(2, "stdout writing address: %r; resetting\n"); - fswrite(afd, "$", 1); + fprint(2, "stdout writing address %s: %r; resetting\n", x); + if(fswrite(afd, "$", 1) < 0) + fprint(2, "reset: %r\n"); + fsseek(afd, 0, 0); m = fsread(afd, x, sizeof x-1); if(m >= 0){ x[m] = 0; @@ -660,13 +674,18 @@ addtype(int c, uint p0, char *b, int nb, int nr) void sendtype(int fd0) { - int i, n, nr; - - while(ntypebreak){ + int i, n, nr, raw; + + raw = !isecho(fd0); + while(ntypebreak || (raw && ntypeb > 0)){ for(i=0; i<ntypeb; i++) - if(typing[i]=='\n' || typing[i]==0x04){ + if(typing[i]=='\n' || typing[i]==0x04 || (i==ntypeb-1 && raw)){ + if((typing[i] == '\n' || typing[i] == 0x04) && ntypebreak > 0) + ntypebreak--; n = i+1; i++; + if(isecho(fd0)) + echoed(typing, n); if(write(fd0, typing, n) != n) error("sending to program"); nr = nrunes(typing, i); @@ -674,7 +693,6 @@ sendtype(int fd0) ntyper -= nr; ntypeb -= i; memmove(typing, typing+i, ntypeb); - ntypebreak--; goto cont2; } print("no breakchar\n"); @@ -684,6 +702,22 @@ cont2:; } void +sendbs(int fd0, int n) +{ + char buf[128]; + int m; + + memset(buf, 0x08, sizeof buf); + while(n > 0) { + m = sizeof buf; + if(m > n) + m = n; + n -= m; + write(fd0, buf, m); + } +} + +void deltype(uint p0, uint p1) { int w; @@ -738,6 +772,12 @@ type(Event *e, int fd0, CFid *afd, CFid *dfd) m += nr; } } + if(!isecho(fd0)) { + n = sprint(buf, "#%d,#%d", e->q0, e->q1); + fswrite(afd, buf, n); + fswrite(dfd, "", 0); + q.p -= e->q1 - e->q0; + } sendtype(fd0); } |