commit ef5c6a6edaf3dcf2cddd46841dc0dd8fce2bf967 from: Russ Cox date: Fri Sep 03 14:21:16 2010 UTC 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 commit - a208917e7a935c019095acd1acd8165f08a54b7a commit + ef5c6a6edaf3dcf2cddd46841dc0dd8fce2bf967 blob - 92b253d33af5c1f4468edcf1b97f25416e717713 blob + 806215df06f9c856bd899bea59955a9a45a3eadd --- src/cmd/9term/9term.c +++ 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); } } blob - ac1432ded5a3172b8a2d01ba23774148f1dc561c blob + e0f866ab51f93d0754fbd725e2183a74e44e546a --- src/cmd/9term/SunOS.c +++ 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) blob - 52b9bb8a0daa6b07f74522d0ef53d4b4216ad995 blob + 4836d24d25337697fbbea51e382c84647ac7758a --- src/cmd/9term/bsdpty.c +++ 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) blob - 4d64349c6b48faa56fe11c7d2a8281b093e22725 blob + 6b91c8698380a0c1aacb8ec7c13bcf7115c62fc3 --- src/cmd/9term/rcstart.c +++ 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 0) + memmove(p, p+i, n-i); + return n-i; +} + +int +dropcrnl(char *p, int n) +{ + char *r, *w; + + for(r=w=p; r #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 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); }