efi_loader: updating the cursor position
authorHeinrich Schuchardt <xypron.glpk@gmx.de>
Sun, 29 Apr 2018 14:24:25 +0000 (16:24 +0200)
committerAlexander Graf <agraf@suse.de>
Sun, 3 Jun 2018 13:27:20 +0000 (15:27 +0200)
The current coding advances the column by the number of UTF-8 bytes.
The column should be increased by one per unicode character.

The UEFI spec provides advance rules for U+0000, U+0008, U+000A,
and U000D. All other characters, including control characters
U+0007 (bel) and U+0009 (tab), have to increase the column by one.

Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
Signed-off-by: Alexander Graf <agraf@suse.de>
lib/efi_loader/efi_console.c

index d777db8a3ed13cb888eccae5fb2182ae42bd6e65..10fb224901ad4b3c91f1a5297e4911cfa259eabb 100644 (file)
@@ -116,25 +116,36 @@ static efi_status_t EFIAPI efi_cout_output_string(
 
        unsigned int n16 = utf16_strlen(string);
        char buf[MAX_UTF8_PER_UTF16 * n16 + 1];
-       char *p;
+       u16 *p;
 
        *utf16_to_utf8((u8 *)buf, string, n16) = '\0';
 
        fputs(stdout, buf);
 
-       for (p = buf; *p; p++) {
+       /*
+        * Update the cursor position.
+        *
+        * The UEFI spec provides advance rules for U+0000, U+0008, U+000A,
+        * and U000D. All other characters, including control characters
+        * U+0007 (bel) and U+0009 (tab), have to increase the column by one.
+        */
+       for (p = string; *p; ++p) {
                switch (*p) {
-               case '\r':   /* carriage-return */
-                       con->cursor_column = 0;
+               case '\b':      /* U+0008, backspace */
+                       con->cursor_column = max(0, con->cursor_column - 1);
                        break;
-               case '\n':   /* newline */
+               case '\n':      /* U+000A, newline */
                        con->cursor_column = 0;
                        con->cursor_row++;
                        break;
-               case '\t':   /* tab, assume 8 char align */
+               case '\r':      /* U+000D, carriage-return */
+                       con->cursor_column = 0;
                        break;
-               case '\b':   /* backspace */
-                       con->cursor_column = max(0, con->cursor_column - 1);
+               case 0xd800 ... 0xdbff:
+                       /*
+                        * Ignore high surrogates, we do not want to count a
+                        * Unicode character twice.
+                        */
                        break;
                default:
                        con->cursor_column++;