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
This commit is contained in:
parent
a208917e7a
commit
ef5c6a6eda
6 changed files with 129 additions and 61 deletions
|
|
@ -22,7 +22,6 @@ int plumbfd;
|
||||||
int rcpid;
|
int rcpid;
|
||||||
int rcfd;
|
int rcfd;
|
||||||
int sfd;
|
int sfd;
|
||||||
int noecho;
|
|
||||||
Window *w;
|
Window *w;
|
||||||
char *fontname;
|
char *fontname;
|
||||||
|
|
||||||
|
|
@ -412,6 +411,9 @@ rcoutputproc(void *arg)
|
||||||
fprint(2, "9term: rc read error: %r\n");
|
fprint(2, "9term: rc read error: %r\n");
|
||||||
threadexitsall("eof on rc output");
|
threadexitsall("eof on rc output");
|
||||||
}
|
}
|
||||||
|
n = echocancel(data+cnt, n);
|
||||||
|
if(n == 0)
|
||||||
|
continue;
|
||||||
cnt += n;
|
cnt += n;
|
||||||
r = runemalloc(cnt);
|
r = runemalloc(cnt);
|
||||||
cvttorunes(data, cnt-UTFmax, r, &nb, &nr, nil);
|
cvttorunes(data, cnt-UTFmax, r, &nb, &nr, nil);
|
||||||
|
|
@ -428,7 +430,7 @@ rcoutputproc(void *arg)
|
||||||
nr = label(r, nr);
|
nr = label(r, nr);
|
||||||
if(nr == 0)
|
if(nr == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
recv(w->conswrite, &cwm);
|
recv(w->conswrite, &cwm);
|
||||||
pair.s = r;
|
pair.s = r;
|
||||||
pair.ns = nr;
|
pair.ns = nr;
|
||||||
|
|
@ -499,7 +501,6 @@ void
|
||||||
rcinputproc(void *arg)
|
rcinputproc(void *arg)
|
||||||
{
|
{
|
||||||
static char data[9000];
|
static char data[9000];
|
||||||
int s;
|
|
||||||
Consreadmesg crm;
|
Consreadmesg crm;
|
||||||
Channel *c1, *c2;
|
Channel *c1, *c2;
|
||||||
Stringpair pair;
|
Stringpair pair;
|
||||||
|
|
@ -513,12 +514,11 @@ rcinputproc(void *arg)
|
||||||
pair.ns = sizeof data;
|
pair.ns = sizeof data;
|
||||||
send(c1, &pair);
|
send(c1, &pair);
|
||||||
recv(c2, &pair);
|
recv(c2, &pair);
|
||||||
|
|
||||||
s = setecho(sfd, 0);
|
if(isecho(sfd))
|
||||||
|
echoed(pair.s, pair.ns);
|
||||||
if(write(rcfd, pair.s, pair.ns) < 0)
|
if(write(rcfd, pair.s, pair.ns) < 0)
|
||||||
threadexitsall(nil);
|
threadexitsall(nil);
|
||||||
if(s)
|
|
||||||
setecho(sfd, s);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -77,25 +77,6 @@ isecho(int fd)
|
||||||
return (ttmode.c_lflag&ICANON && ttmode.c_lflag&ECHO);
|
return (ttmode.c_lflag&ICANON && ttmode.c_lflag&ECHO);
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
int
|
||||||
getintr(int fd)
|
getintr(int fd)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -96,29 +96,6 @@ isecho(int fd)
|
||||||
return ttmode.c_lflag&ECHO;
|
return ttmode.c_lflag&ECHO;
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
int
|
||||||
getintr(int fd)
|
getintr(int fd)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -87,8 +87,6 @@ rcstart(int argc, char **argv, int *pfd, int *tfd)
|
||||||
dup(sfd, 2);
|
dup(sfd, 2);
|
||||||
sys("stty tabs -onlcr icanon echo erase '^h' intr '^?'", 0);
|
sys("stty tabs -onlcr icanon echo erase '^h' intr '^?'", 0);
|
||||||
sys("stty onocr", 1); /* not available on mac */
|
sys("stty onocr", 1); /* not available on mac */
|
||||||
if(noecho)
|
|
||||||
sys("stty -echo", 0);
|
|
||||||
for(i=3; i<100; i++)
|
for(i=3; i<100; i++)
|
||||||
close(i);
|
close(i);
|
||||||
signal(SIGINT, SIG_DFL);
|
signal(SIGINT, SIG_DFL);
|
||||||
|
|
@ -111,3 +109,73 @@ rcstart(int argc, char **argv, int *pfd, int *tfd)
|
||||||
return pid;
|
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;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,9 @@ extern void updatewinsize(int, int, int, int);
|
||||||
extern int rcfd;
|
extern int rcfd;
|
||||||
extern int rcstart(int, char*[], int*, int*);
|
extern int rcstart(int, char*[], int*, int*);
|
||||||
extern int isecho(int);
|
extern int isecho(int);
|
||||||
extern int setecho(int, int);
|
|
||||||
extern int noecho;
|
extern int noecho;
|
||||||
extern int getintr(int);
|
extern int getintr(int);
|
||||||
extern int loginshell;
|
extern int loginshell;
|
||||||
|
extern void echoed(char*, int);
|
||||||
|
extern int echocancel(char*, int);
|
||||||
|
extern int dropcrnl(char*, int);
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@
|
||||||
#include <9pclient.h>
|
#include <9pclient.h>
|
||||||
#include "term.h"
|
#include "term.h"
|
||||||
|
|
||||||
int noecho = 1;
|
|
||||||
|
|
||||||
#define EVENTSIZE 256
|
#define EVENTSIZE 256
|
||||||
#define STACK 32768
|
#define STACK 32768
|
||||||
|
|
@ -71,6 +70,7 @@ void sende(Event*, int, CFid*, CFid*, CFid*, int);
|
||||||
char *onestring(int, char**);
|
char *onestring(int, char**);
|
||||||
int delete(Event*);
|
int delete(Event*);
|
||||||
void deltype(uint, uint);
|
void deltype(uint, uint);
|
||||||
|
void sendbs(int, int);
|
||||||
void runproc(void*);
|
void runproc(void*);
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|
@ -349,6 +349,7 @@ stdinproc(void *v)
|
||||||
CFid *afd = addrfd;
|
CFid *afd = addrfd;
|
||||||
int fd0 = rcfd;
|
int fd0 = rcfd;
|
||||||
Event e, e2, e3, e4;
|
Event e, e2, e3, e4;
|
||||||
|
int n;
|
||||||
|
|
||||||
USED(v);
|
USED(v);
|
||||||
|
|
||||||
|
|
@ -411,7 +412,10 @@ stdinproc(void *v)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'D':
|
case 'D':
|
||||||
q.p -= delete(&e);
|
n = delete(&e);
|
||||||
|
q.p -= n;
|
||||||
|
if(!isecho(fd0))
|
||||||
|
sendbs(fd0, n);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'x':
|
case 'x':
|
||||||
|
|
@ -491,6 +495,14 @@ stdoutproc(void *v)
|
||||||
n = read(fd1, buf+npart, 8192);
|
n = read(fd1, buf+npart, 8192);
|
||||||
if(n <= 0)
|
if(n <= 0)
|
||||||
error(nil);
|
error(nil);
|
||||||
|
|
||||||
|
n = echocancel(buf+npart, n);
|
||||||
|
if(n == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
n = dropcrnl(buf+npart, n);
|
||||||
|
if(n == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
/* squash NULs */
|
/* squash NULs */
|
||||||
s = memchr(buf+npart, 0, n);
|
s = memchr(buf+npart, 0, n);
|
||||||
|
|
@ -525,8 +537,10 @@ stdoutproc(void *v)
|
||||||
qlock(&q.lk);
|
qlock(&q.lk);
|
||||||
m = sprint(x, "#%d", q.p);
|
m = sprint(x, "#%d", q.p);
|
||||||
if(fswrite(afd, x, m) != m){
|
if(fswrite(afd, x, m) != m){
|
||||||
fprint(2, "stdout writing address: %r; resetting\n");
|
fprint(2, "stdout writing address %s: %r; resetting\n", x);
|
||||||
fswrite(afd, "$", 1);
|
if(fswrite(afd, "$", 1) < 0)
|
||||||
|
fprint(2, "reset: %r\n");
|
||||||
|
fsseek(afd, 0, 0);
|
||||||
m = fsread(afd, x, sizeof x-1);
|
m = fsread(afd, x, sizeof x-1);
|
||||||
if(m >= 0){
|
if(m >= 0){
|
||||||
x[m] = 0;
|
x[m] = 0;
|
||||||
|
|
@ -660,13 +674,18 @@ addtype(int c, uint p0, char *b, int nb, int nr)
|
||||||
void
|
void
|
||||||
sendtype(int fd0)
|
sendtype(int fd0)
|
||||||
{
|
{
|
||||||
int i, n, nr;
|
int i, n, nr, raw;
|
||||||
|
|
||||||
while(ntypebreak){
|
raw = !isecho(fd0);
|
||||||
|
while(ntypebreak || (raw && ntypeb > 0)){
|
||||||
for(i=0; i<ntypeb; i++)
|
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;
|
n = i+1;
|
||||||
i++;
|
i++;
|
||||||
|
if(isecho(fd0))
|
||||||
|
echoed(typing, n);
|
||||||
if(write(fd0, typing, n) != n)
|
if(write(fd0, typing, n) != n)
|
||||||
error("sending to program");
|
error("sending to program");
|
||||||
nr = nrunes(typing, i);
|
nr = nrunes(typing, i);
|
||||||
|
|
@ -674,7 +693,6 @@ sendtype(int fd0)
|
||||||
ntyper -= nr;
|
ntyper -= nr;
|
||||||
ntypeb -= i;
|
ntypeb -= i;
|
||||||
memmove(typing, typing+i, ntypeb);
|
memmove(typing, typing+i, ntypeb);
|
||||||
ntypebreak--;
|
|
||||||
goto cont2;
|
goto cont2;
|
||||||
}
|
}
|
||||||
print("no breakchar\n");
|
print("no breakchar\n");
|
||||||
|
|
@ -683,6 +701,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
|
void
|
||||||
deltype(uint p0, uint p1)
|
deltype(uint p0, uint p1)
|
||||||
{
|
{
|
||||||
|
|
@ -738,6 +772,12 @@ type(Event *e, int fd0, CFid *afd, CFid *dfd)
|
||||||
m += nr;
|
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);
|
sendtype(fd0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue