video/console: Implement relative cursor movement ANSI handling
authorAndre Przywara <andre.przywara@arm.com>
Sat, 23 Mar 2019 01:29:57 +0000 (01:29 +0000)
committerAnatolij Gustschin <agust@denx.de>
Sun, 14 Apr 2019 12:18:47 +0000 (14:18 +0200)
The ANSI terminal escapce sequence standard defines relative cursor
movement commands (ESC [ A-F). So far the DM_VIDEO console code was
ignoring them.

Interpret those sequences and move the cursor by the requested amount of
rows or columns in the right direction. This brings the code on par with
the legacy video console driver (cfb_console).

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
drivers/video/vidconsole-uclass.c

index 3ff65f3232958bbe364b21dd226e7c03b1cf1c27..6cf9124c42b5d0d106106b97599167f80f9886c1 100644 (file)
@@ -259,6 +259,43 @@ static void vidconsole_escape_char(struct udevice *dev, char ch)
        priv->escape = 0;
 
        switch (ch) {
+       case 'A':
+       case 'B':
+       case 'C':
+       case 'D':
+       case 'E':
+       case 'F': {
+               int row, col, num;
+               char *s = priv->escape_buf;
+
+               /*
+                * Cursor up/down: [%dA, [%dB, [%dE, [%dF
+                * Cursor left/right: [%dD, [%dC
+                */
+               s++;    /* [ */
+               s = parsenum(s, &num);
+               if (num == 0)                   /* No digit in sequence ... */
+                       num = 1;                /* ... means "move by 1". */
+
+               get_cursor_position(priv, &row, &col);
+               if (ch == 'A' || ch == 'F')
+                       row -= num;
+               if (ch == 'C')
+                       col += num;
+               if (ch == 'D')
+                       col -= num;
+               if (ch == 'B' || ch == 'E')
+                       row += num;
+               if (ch == 'E' || ch == 'F')
+                       col = 0;
+               if (col < 0)
+                       col = 0;
+               if (row < 0)
+                       row = 0;
+               /* Right and bottom overflows are handled in the callee. */
+               set_cursor_position(priv, row, col);
+               break;
+       }
        case 'H':
        case 'f': {
                int row, col;