Commit Diff


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<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;
+}
blob - c8d9926f705e7eb714562da1eba77a0095a4cfec
blob + e7a1f6b24de43d657aeb4aaa69e59be6b95f50e5
--- src/cmd/9term/term.h
+++ 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);
blob - bed7f2aae93aaf0f1c69873148f221b1e60484f8
blob + 25dfccc96b9120098a526970df19b8c29f52ecb4
--- src/cmd/9term/win.c
+++ 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);
 }