[syslinux] [PATCH] Fix backspace when editing a multiline cmdline

Robbie Harwood rharwood at redhat.com
Thu Oct 21 12:33:56 PDT 2021


Once the cmdline had passed the width of the screen, adding additional
characters introduced a spurious newline, and another newline at the
width of input.  Furthermore, hitting backspace would not start
redrawing at the end of input, but rather at the beginning of the
current line - resulting in extra duplicate lines scrolling the console.

First, fix the assumption that the length of cmdline is the width - it
needs to include the length of the prompt (i.e., length of input and
space).

Second, fix the behavior of single-line redraw (i.e., redraw == 1) to
move the cursor to the row the line begins at.

Third, don't scroll the cursor down when a line wrap would occur - it's
not necessary since line wrap is enabled, and results in the extra blank
line.

Finally, comment all used escape sequences so that I don't need to look
them up again.

Signed-off-by: Robbie Harwood <rharwood at redhat.com>
---
 com32/elflink/ldlinux/cli.c | 33 ++++++++++++++++++---------------
 1 file changed, 18 insertions(+), 15 deletions(-)

diff --git a/com32/elflink/ldlinux/cli.c b/com32/elflink/ldlinux/cli.c
index 3119b11f..4913f038 100644
--- a/com32/elflink/ldlinux/cli.c
+++ b/com32/elflink/ldlinux/cli.c
@@ -135,6 +135,7 @@ const char *edit_cmdline(const char *input, int top /*, int width */ ,
     struct cli_command *comm_counter = NULL;
     clock_t kbd_to = kbdtimeout;
     clock_t tto = totaltimeout;
+    int prompt_len = 1 + strlen(input);
 
     if (!width) {
 	int height;
@@ -144,7 +145,7 @@ const char *edit_cmdline(const char *input, int top /*, int width */ ,
 
     len = cursor = 0;
     prev_len = 0;
-    x = y = 0;
+    y = 0;
 
     /*
      * Before we start messing with the x,y coordinates print 'input'
@@ -152,6 +153,7 @@ const char *edit_cmdline(const char *input, int top /*, int width */ ,
      * previously.
      */
     printf("%s ", input);
+    x = prompt_len;
 
     while (!done) {
 	if (redraw > 1) {
@@ -162,8 +164,7 @@ const char *edit_cmdline(const char *input, int top /*, int width */ ,
 	    if (pDraw_Menu)
 		    (*pDraw_Menu) (-1, top, 1);
 	    prev_len = 0;
-	    printf("\033[2J\033[H");
-	    // printf("\033[0m\033[2J\033[H");
+	    printf("\033[2J\033[H"); /* Clear entire screen; move to 0, 0. */
 	}
 
 	if (redraw > 0) {
@@ -172,10 +173,14 @@ const char *edit_cmdline(const char *input, int top /*, int width */ ,
 	    prev_len = max(len, prev_len);
 
 	    /* Redraw the command line */
-	    printf("\033[?25l");
-	    printf("\033[1G%s ", input);
+	    printf("\033[?25l"); /* Hide cursor. */
+	    printf("\033[1G"); /* Column 1. */
+	    if (y > 0)
+		printf("\033[%dA", y); /* Directly up. */
 
-	    x = strlen(input);
+	    printf("%s ", input);
+
+	    x = prompt_len;
 	    y = 0;
 	    at = 0;
 	    while (at < prev_len) {
@@ -183,23 +188,22 @@ const char *edit_cmdline(const char *input, int top /*, int width */ ,
 		at++;
 		x++;
 		if (x >= width) {
-		    printf("\r\n");
 		    x = 0;
 		    y++;
 		}
 	    }
-	    printf("\033[K\r");
+	    printf("\033[K\r"); /* Clear to end of line; go to beginning. */
 
-	    dy = y - (cursor + strlen(input) + 1) / width;
-	    x = (cursor + strlen(input) + 1) % width;
+	    dy = y - (cursor + prompt_len) / width;
+	    x = (cursor + prompt_len) % width;
 
 	    if (dy) {
-		printf("\033[%dA", dy);
+		printf("\033[%dA", dy); /* Cursor directly up. */
 		y -= dy;
 	    }
 	    if (x)
-		printf("\033[%dC", x);
-	    printf("\033[?25h");
+		printf("\033[%dC", x); /* Cursor forward. */
+	    printf("\033[?25h"); /* Show cursor. */
 	    prev_len = len;
 	    redraw = 0;
 	}
@@ -439,7 +443,6 @@ const char *edit_cmdline(const char *input, int top /*, int width */ ,
 		    cursor++;
 		    x++;
 		    if (x >= width) {
-			printf("\r\n\033[K");
 			y++;
 			x = 0;
 		    }
@@ -459,7 +462,7 @@ const char *edit_cmdline(const char *input, int top /*, int width */ ,
 	}
     }
 
-    printf("\033[?7h");
+    printf("\033[?7h"); /* Enable line wrap. */
 
     /* Add the command to the history if its length is larger than 0 */
     len = strlen(ret);
-- 
2.33.0



More information about the Syslinux mailing list