git: 9front

Download patch

ref: 98cafbe89cc5ff8d20640f8fe246de6177717314
parent: a600a002fbba532248a1c121ceb0c58afa4ee368
author: Ori Bernstein <ori@eigenstate.org>
date: Thu Nov 6 21:57:49 EST 2025

vt: handle cursor movement within escape sequences

--- a/sys/src/cmd/vt/cons.h
+++ b/sys/src/cmd/vt/cons.h
@@ -52,9 +52,8 @@
 extern int	host_avail(void);
 extern void	clear(int,int,int,int);
 extern void	newline(void);
-extern int	get_next_char(void);
+extern int	nextchar(void);
 extern void	ringbell(void);
-extern int	number(Rune *, int *);
 extern void	shift(int,int,int,int);
 extern void	scroll(int,int,int,int);
 extern void	backup(int);
--- a/sys/src/cmd/vt/main.c
+++ b/sys/src/cmd/vt/main.c
@@ -516,7 +516,7 @@
 }
 
 int
-get_next_char(void)
+nextchar(void)
 {
 	int c = peekc;
 
@@ -1417,22 +1417,6 @@
 	y -= half;
 	if(olines)
 		olines -= half;
-}
-
-int
-number(Rune *p, int *got)
-{
-	int c, n = 0;
-
-	if(got)
-		*got = 0;
-	while ((c = get_next_char()) >= '0' && c <= '9'){
-		if(got)
-			*got = 1;
-		n = n*10 + c - '0';
-	}
-	*p = c;
-	return(n);
 }
 
 /* stubs */
--- a/sys/src/cmd/vt/vt.c
+++ b/sys/src/cmd/vt/vt.c
@@ -157,8 +157,9 @@
 	['~']	'.',	/* centered dot: · */
 };
 
-static void setattr(int argc, int *argv);
-static void osc(void);
+static void	setattr(int argc, int *argv);
+static void	osc(void);
+static int	cursctl(int);
 
 void
 fixops(int *operand)
@@ -167,6 +168,33 @@
 		operand[0] = 1;
 }
 
+int
+nextcmd(void)
+{
+	int c;
+
+	do {
+		c = nextchar();
+	}while(cursctl(c));
+	return c;
+}
+
+int
+number(Rune *p, int *got)
+{
+	int c, n = 0;
+
+	if(got)
+		*got = 0;
+	while ((c = nextcmd()) >= '0' && c <= '9'){
+		if(got)
+			*got = 1;
+		n = n*10 + c - '0';
+	}
+	*p = c;
+	return(n);
+}
+
 void
 emulate(void)
 {
@@ -197,7 +225,7 @@
 			x = 0;
 			newline();
 		}
-		buf[0] = get_next_char();
+		buf[0] = nextcmd();
 		buf[1] = '\0';
 		switch(buf[0]) {
 		case '\000':
@@ -209,40 +237,6 @@
 		case '\006':
 			goto Default;
 
-		case '\007':		/* bell */
-			ringbell();
-			break;
-
-		case '\010':		/* backspace */
-			if(x > xmax)
-				x = xmax;
-			if(x > 0)
-				--x;
-			break;
-
-		case '\011':		/* tab to next tab stop; if none, to right margin */
-			for(c=x+1; c<nelem(tabcol) && !tabcol[c]; c++)
-				;
-			if(c < xmax && c < nelem(tabcol))
-				x = c;
-			else
-				x = xmax;
-			break;
-
-		case '\012':		/* linefeed */
-		case '\013':
-		case '\014':
-			newline();
-			if (ttystate[cs->raw].nlcr)
-				x = 0;
-			break;
-
-		case '\015':		/* carriage return */
-			x = 0;
-			if (ttystate[cs->raw].crnl)
-				newline();
-			break;
-
 		case '\016':	/* SO: invoke G1 char set */
 			isgraphics = (isdigit(g1set));
 			break;
@@ -273,7 +267,7 @@
 			break;
 
 		case '\033':
-			switch(get_next_char()){
+			switch(nextcmd()){
 			/*
 			 * 1 - graphic processor option on (no-op; not installed)
 			 */
@@ -389,7 +383,7 @@
 			 * # - Takes a one-digit argument
 			 */
 			case '#':
-				switch(get_next_char()){
+				switch(nextcmd()){
 				case '3':		/* Top half of double-height line */
 				case '4':		/* Bottom half of double-height line */
 				case '5':		/* Single-width single-height line */
@@ -404,7 +398,7 @@
 			 * ( - switch G0 character set
 			 */
 			case '(':
-				g0set = get_next_char();
+				g0set = nextcmd();
 				break;
 
 			/*
@@ -411,7 +405,7 @@
 			 * - switch G1 character set
 			 */
 			case ')':
-				g1set = get_next_char();
+				g1set = nextcmd();
 				break;
 
 			/*
@@ -465,7 +459,7 @@
 						if(noperand == 1){
 							switch(operand[0]){	
 							case 20:	/* set line feed mode */
-								ttystate[cs->raw].nlcr = 1;
+								ttystate[cs->raw].nlcr = 0;
 								break;
 							case 30:	/* screen invisible (? not supported through VT220) */
 								break;
@@ -523,7 +517,7 @@
 							default:
 								break;
 							case 20:	/* set newline mode */
-								ttystate[cs->raw].nlcr = 0;
+								ttystate[cs->raw].nlcr = 1;
 								break;
 							case 30:	/* screen visible (? not supported through VT220) */
 								break;
@@ -897,7 +891,7 @@
 			n = 1;
 			c = 0;
 			while (!cs->raw && host_avail() && x+n<=xmax && n<BUFS
-			    && (c = get_next_char())>=' ' && c<'\177') {
+			    && (c = nextcmd())>=' ' && c<'\177') {
 				buf[n++] = c;
 				c = 0;
 			}
@@ -990,6 +984,50 @@
 	return c - '0';
 }
 
+static int
+cursctl(int c)
+{
+	switch(c){
+	default:
+	    return 0;
+	case '\007':		/* bell */
+		ringbell();
+		break;
+	
+	case '\010':		/* backspace */
+		if(x > xmax)
+			x = xmax;
+		if(x > 0)
+			--x;
+		break;
+	
+	case '\011':		/* tab to next tab stop; if none, to right margin */
+		for(c=x+1; c<nelem(tabcol) && !tabcol[c]; c++)
+			;
+		if(c < xmax && c < nelem(tabcol))
+			x = c;
+		else
+			x = xmax;
+		break;
+	
+	case '\012':		/* linefeed */
+	case '\013':
+	case '\014':
+		newline();
+		if (ttystate[cs->raw].nlcr)
+			x = 0;
+		break;
+	
+	case '\015':		/* carriage return */
+		x = 0;
+		if (ttystate[cs->raw].crnl)
+			newline();
+		break;
+	}
+	return 1;
+}
+
+
 // handle ESC], Operating System Command
 static void
 osc(void)
@@ -1006,7 +1044,7 @@
 		case 2: /* set title */
 			i = 0;
 
-			while((ch = get_next_char()) != '\a') {
+			while((ch = nextcmd()) != '\a') {
 				if(i < nelem(buf) - 1) {
 					buf[i++] = ch;
 				}
@@ -1021,11 +1059,11 @@
 		case 7: /* set pwd */
 			i = 0;
 
-			while((ch = get_next_char()) != '\033'){
+			while((ch = nextcmd()) != '\033'){
 				if(i < sizeof(osc7cwd)-UTFmax-1)
 					i += runetochar(osc7cwd+i, &ch);
 			}
-			get_next_char();
+			nextcmd();
 			osc7cwd[i] = 0;
 
 			/* file://hostname/path → /n/hostname/path */
--