Use UTF-8 on Windows 10 Version 1903, fix #1195

Allows Ninja to use descriptions, filenames and environment variables
with characters outside of the ANSI codepage on Windows. Build manifests
are now UTF-8 by default (this change needs to be emphasized in the
release notes).

WriteConsoleOutput doesn't support UTF-8, but it's deprecated on newer
Windows 10 versions anyway (or as Microsoft likes to put it: "no longer
a part of our ecosystem roadmap"). We'll use the VT100 sequence just as
we do on Linux and macOS.

https://docs.microsoft.com/en-us/windows/uwp/design/globalizing/use-utf8-code-page
https://docs.microsoft.com/en-us/windows/console/writeconsoleoutput
https://docs.microsoft.com/de-de/windows/console/console-virtual-terminal-sequences
This commit is contained in:
Jan Niklas Hasse 2021-02-17 21:59:20 +01:00
parent 9c66e69846
commit 00459e2b44
3 changed files with 32 additions and 15 deletions

View File

@ -137,6 +137,10 @@ endif()
add_executable(ninja src/ninja.cc)
target_link_libraries(ninja PRIVATE libninja libninja-re2c)
if(WIN32)
target_sources(ninja PRIVATE windows/ninja.manifest)
endif()
# Adds browse mode into the ninja binary if it's supported by the host platform.
if(platform_supports_ninja_browse)
# Inlines src/browse.py into the browse_py.h header, so that it can be included

View File

@ -87,22 +87,27 @@ void LinePrinter::Print(string to_print, LineType type) {
GetConsoleScreenBufferInfo(console_, &csbi);
to_print = ElideMiddle(to_print, static_cast<size_t>(csbi.dwSize.X));
// We don't want to have the cursor spamming back and forth, so instead of
// printf use WriteConsoleOutput which updates the contents of the buffer,
// but doesn't move the cursor position.
COORD buf_size = { csbi.dwSize.X, 1 };
COORD zero_zero = { 0, 0 };
SMALL_RECT target = {
csbi.dwCursorPosition.X, csbi.dwCursorPosition.Y,
static_cast<SHORT>(csbi.dwCursorPosition.X + csbi.dwSize.X - 1),
csbi.dwCursorPosition.Y
};
vector<CHAR_INFO> char_data(csbi.dwSize.X);
for (size_t i = 0; i < static_cast<size_t>(csbi.dwSize.X); ++i) {
char_data[i].Char.AsciiChar = i < to_print.size() ? to_print[i] : ' ';
char_data[i].Attributes = csbi.wAttributes;
if (supports_color_) { // this means ENABLE_VIRTUAL_TERMINAL_PROCESSING
// succeeded
printf("%s\x1B[K", to_print.c_str()); // Clear to end of line.
fflush(stdout);
} else {
// We don't want to have the cursor spamming back and forth, so instead of
// printf use WriteConsoleOutput which updates the contents of the buffer,
// but doesn't move the cursor position.
COORD buf_size = { csbi.dwSize.X, 1 };
COORD zero_zero = { 0, 0 };
SMALL_RECT target = { csbi.dwCursorPosition.X, csbi.dwCursorPosition.Y,
static_cast<SHORT>(csbi.dwCursorPosition.X +
csbi.dwSize.X - 1),
csbi.dwCursorPosition.Y };
vector<CHAR_INFO> char_data(csbi.dwSize.X);
for (size_t i = 0; i < static_cast<size_t>(csbi.dwSize.X); ++i) {
char_data[i].Char.AsciiChar = i < to_print.size() ? to_print[i] : ' ';
char_data[i].Attributes = csbi.wAttributes;
}
WriteConsoleOutput(console_, &char_data[0], buf_size, zero_zero, &target);
}
WriteConsoleOutput(console_, &char_data[0], buf_size, zero_zero, &target);
#else
// Limit output to width of the terminal if provided so we don't cause
// line-wrapping.

8
windows/ninja.manifest Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<application>
<windowsSettings>
<activeCodePage xmlns="http://schemas.microsoft.com/SMI/2019/WindowsSettings">UTF-8</activeCodePage>
</windowsSettings>
</application>
</assembly>