gdb: Support UTF-8 output on MS-Windows terminal

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.
This commit is contained in:
Eli Zaretskii 2026-01-22 13:03:13 +02:00
parent 0a4433b3c9
commit 43c658ff0c
3 changed files with 46 additions and 6 deletions

View 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];
unsigned codepage = mingw_get_codeset ();
snprintf (w32_host_default_charset, sizeof w32_host_default_charset,
"CP%d", GetACP());
/* 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

View 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 */

View file

@ -24,10 +24,10 @@
#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