]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
gdb: Support UTF-8 output on MS-Windows terminal
authorEli Zaretskii <eliz@gnu.org>
Thu, 22 Jan 2026 11:03:13 +0000 (13:03 +0200)
committerEli Zaretskii <eliz@gnu.org>
Thu, 22 Jan 2026 11:03:13 +0000 (13:03 +0200)
This detects when the Windows Terminal uses codepage 65001
(a.k.a. "UTF-8") for output, and sets the default host
charset to UTF-8 in that case.  It also enables Emoji
styling, as the Windows terminal supports it in that case.

* gdb/charset.c (INIT_GDB_FILE) [USE_WIN32API]: If the Windows
console uses codepage 65001, set default host charset to UTF-8, and
switch to the "C" locale, to prevent Windows from interpreting UTF-8
sequences written to the console.
* gdb/mingw-hdep.c (windows_initialize_console): Don't disable Emoji
here...
* gdb/charset.c (INIT_GDB_FILE) [USE_WIN32API]: ...disable them here
instead, and only if the console doesn't use UTF-8.

gdb/charset.c
gdb/charset.h
gdb/mingw-hdep.c

index 7c6cd938c324cf46b01f7d8af34020feb1fb7aa6..eaddfb57098598fcbb9d68a5ed34346abc72b2a8 100644 (file)
@@ -19,6 +19,7 @@
 
 #include "charset.h"
 #include "cli/cli-cmds.h"
+#include "cli/cli-style.h"
 #include "gdbsupport/gdb_obstack.h"
 #include "gdbsupport/gdb_wait.h"
 #include "charset-list.h"
@@ -1009,11 +1010,28 @@ INIT_GDB_FILE (charset)
   {
     /* "CP" + x<=5 digits + paranoia.  */
     static char w32_host_default_charset[16];
-
-    snprintf (w32_host_default_charset, sizeof w32_host_default_charset,
-             "CP%d", GetACP());
+    unsigned codepage = mingw_get_codeset ();
+
+    /* The rest of the code expects a literal "UTF-8" and doesn't know
+       anything about codepage 65001.  */
+    if (codepage == 65001)
+      {
+       strcpy (w32_host_default_charset, "UTF-8");
+       /* This is needed to force Windows CRT output functions treat
+          output as simple stream of bytes, instead of trying to
+          interpret it as encoded non-ASCII text, which will fail if
+          the system locale's codeset is NOT UTF-8.  */
+       setlocale (LC_CTYPE, "C");
+      }
+    else
+      snprintf (w32_host_default_charset, sizeof w32_host_default_charset,
+               "CP%u", codepage);
     auto_host_charset_name = w32_host_default_charset;
     auto_target_charset_name = auto_host_charset_name;
+
+    /* Windows Terminal supports Emoji when using UTF-8 output.  */
+    if (strcmp (w32_host_default_charset, "UTF-8") != 0)
+      no_emojis ();
   }
 #endif
 #endif
index 6cfab83b8962b54e9003c3a2454987f0226be6d0..431590f5000181a92b879bfa6870f7a9b4c196bc 100644 (file)
@@ -165,4 +165,8 @@ char host_letter_to_control_character (char c);
 #define HOST_UTF32 "UTF-32LE"
 #endif
 
+#ifdef __MINGW32__
+  unsigned int mingw_get_codeset ();
+#endif
+
 #endif /* GDB_CHARSET_H */
index 1fad256bc42c742117f08744c4c672a37f540bdb..efad50c4cbeb4d8bb955d474fb9841ecb2a957de 100644 (file)
 #include "gdbsupport/event-loop.h"
 #include "gdbsupport/gdb_select.h"
 #include "inferior.h"
-#include "cli/cli-style.h"
 #include "command.h"
 #include "cli/cli-cmds.h"
 #include "terminal.h"
+#include "charset.h"
 
 #include <windows.h>
 #include <signal.h>
@@ -258,9 +258,6 @@ windows_initialize_console ()
     }
   else if (hstdout != INVALID_HANDLE_VALUE)
     mingw_use_console_color_apis = -1; /* valid, but not a console device */
-
-  if (mingw_use_console_color_apis > 0)
-    no_emojis ();
 }
 
 void
@@ -440,6 +437,27 @@ gdb_console_fputs (const char *linebuf, FILE *fstream)
   return 1;
 }
 
+unsigned int
+mingw_get_codeset ()
+{
+  unsigned int default_codepage = GetACP ();
+  unsigned int output_codepage = GetConsoleOutputCP ();
+
+  /* Multibyte writes will not work correctly if written one byte at a
+     time, which is what gdb_console_fputs above does.  So if they set
+     the console's output to use UTF-8, only use that if we have
+     successfully set up the terminal for Virtual Terminal Sequences,
+     and are using 'fputs' directly.  */
+  if (output_codepage == 0     /* GetConsoleOutputCP failed */
+      || (output_codepage == 65001
+         && output_codepage != default_codepage
+         && !(mingw_use_console_color_apis < 0
+              && hstdout != INVALID_HANDLE_VALUE
+              && orig_console_mode != 0)))
+    return default_codepage;
+  return output_codepage;
+}
+
 /* See inferior.h.  */
 
 tribool