Skip to content

Commit 24e383b

Browse files
committed
Add UTF-8 filename support on Windows
1 parent 88b8969 commit 24e383b

File tree

4 files changed

+51
-3
lines changed

4 files changed

+51
-3
lines changed

CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,9 @@ if(MSVC)
241241
# because `/W4;/WX` is returned as a single string.
242242
add_compile_options( /W4;$<$<BOOL:${KTX_WERROR}>:/WX> )
243243
add_compile_options( $<IF:$<CONFIG:Debug>,/Gz,/O2> )
244+
# Enable UTF-8 support
245+
add_compile_options( $<$<C_COMPILER_ID:MSVC>:/utf-8> )
246+
add_compile_options( $<$<CXX_COMPILER_ID:MSVC>:/utf-8> )
244247
elseif(${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU"
245248
OR ${CMAKE_CXX_COMPILER_ID} MATCHES "Clang")
246249
add_compile_options( -Wall -Wextra $<$<BOOL:${KTX_WERROR}>:-Werror>)

tests/cts

Submodule cts updated 44 files

tools/ktx/command.cpp

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,20 @@
1313
#include <fmt/ostream.h>
1414
#include <fmt/printf.h>
1515

16-
#if defined(_WIN32) && defined(DEBUG)
17-
#include <windows.h> // For functions used by launchDebugger
16+
#if defined(_WIN32)
17+
#define WIN32_LEAN_AND_MEAN
18+
#include <windows.h>
19+
20+
std::wstring ConvertToUTF16(std::string str) {
21+
std::wstring result;
22+
int len = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), static_cast<int>(str.length()), NULL, 0);
23+
if (len > 0)
24+
{
25+
result.resize(len);
26+
MultiByteToWideChar(CP_UTF8, 0, str.c_str(), static_cast<int>(str.length()), &result[0], len);
27+
}
28+
return result;
29+
}
1830
#endif
1931

2032
// -------------------------------------------------------------------------------------------------
@@ -111,7 +123,11 @@ InputStream::InputStream(const std::string& filepath, Reporter& report) :
111123
stdinBuffer << std::cin.rdbuf();
112124
activeStream = &stdinBuffer;
113125
} else {
126+
#if defined(_WIN32)
127+
file.open(ConvertToUTF16(filepath).c_str(), std::ios::binary | std::ios::in);
128+
#else
114129
file.open(filepath, std::ios::binary | std::ios::in);
130+
#endif
115131
if (!file)
116132
report.fatal(rc::IO_FAILURE, "Could not open input file \"{}\": {}.", filepath, errnoMessage());
117133
activeStream = &file;
@@ -134,7 +150,11 @@ OutputStream::OutputStream(const std::string& filepath, Reporter& report) :
134150
#endif
135151
file = stdout;
136152
} else {
153+
#if defined(_WIN32)
154+
file = _wfopen(ConvertToUTF16(filepath).c_str(), L"wb");
155+
#else
137156
file = std::fopen(filepath.c_str(), "wb");
157+
#endif
138158
if (!file)
139159
report.fatal(rc::IO_FAILURE, "Could not open output file \"{}\": {}.", filepath, errnoMessage());
140160
}

tools/ktx/ktx_main.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,19 @@
77
#include "stdafx.h"
88
#include <iostream>
99
#include <string>
10+
#include <memory>
1011
#include <unordered_map>
1112

1213
#include <cxxopts.hpp>
1314
#include <fmt/ostream.h>
1415
#include <fmt/printf.h>
1516

17+
#if defined(_WIN32)
18+
#define WIN32_LEAN_AND_MEAN
19+
#include <windows.h>
20+
#include <shellapi.h>
21+
#endif
22+
1623
// -------------------------------------------------------------------------------------------------
1724

1825
namespace ktx {
@@ -185,6 +192,24 @@ int _tmain(int argc, _TCHAR* argv[]) {
185192
// // pbxproj file, so it can't be disabled in a generated project.
186193
// // Remove these from the arguments under consideration.
187194

195+
#if defined(_WIN32)
196+
// Windows does not support UTF-8 argv so we have to manually acquire it
197+
LPWSTR commandLine = GetCommandLineW();
198+
LPWSTR* wideArgv = CommandLineToArgvW(commandLine, &argc);
199+
std::vector<std::unique_ptr<_TCHAR[]>> utf8Argv(argc);
200+
for (int i = 0; i < argc; ++i) {
201+
int byteSize = WideCharToMultiByte(CP_UTF8, 0, wideArgv[i], -1, nullptr, 0, nullptr, nullptr);
202+
utf8Argv[i] = std::make_unique<_TCHAR[]>(byteSize);
203+
WideCharToMultiByte(CP_UTF8, 0, wideArgv[i], -1, utf8Argv[i].get(), byteSize, nullptr, nullptr);
204+
argv[i] = utf8Argv[i].get();
205+
}
206+
207+
// Set UTF-8 codepage for the console
208+
if (!SetConsoleOutputCP(CP_UTF8)) {
209+
fmt::print(std::cerr, "{} warning: failed to set UTF-8 code page for console output.\n", argv[0]);
210+
}
211+
#endif
212+
188213
if (argc >= 2) {
189214
// Has a subcommand, attempt to lookup
190215

0 commit comments

Comments
 (0)