diff --git a/src/crystal/system/win32/file_descriptor.cr b/src/crystal/system/win32/file_descriptor.cr index cd629f0a3f9e..cc9ee508c2be 100644 --- a/src/crystal/system/win32/file_descriptor.cr +++ b/src/crystal/system/win32/file_descriptor.cr @@ -1,5 +1,7 @@ require "c/io" require "c/consoleapi" +require "c/consoleapi2" +require "c/winnls" module Crystal::System::FileDescriptor @volatile_fd : Atomic(LibC::Int) @@ -184,3 +186,16 @@ module Crystal::System::FileDescriptor io end end + +# Enable UTF-8 console I/O for the duration of program execution +if LibC.IsValidCodePage(LibC::CP_UTF8) != 0 + old_input_cp = LibC.GetConsoleCP + if LibC.SetConsoleCP(LibC::CP_UTF8) != 0 + at_exit { LibC.SetConsoleCP(old_input_cp) } + end + + old_output_cp = LibC.GetConsoleOutputCP + if LibC.SetConsoleOutputCP(LibC::CP_UTF8) != 0 + at_exit { LibC.SetConsoleOutputCP(old_output_cp) } + end +end diff --git a/src/lib_c/x86_64-windows-msvc/c/consoleapi.cr b/src/lib_c/x86_64-windows-msvc/c/consoleapi.cr index 44cfeab11261..8eb8467eb3c5 100644 --- a/src/lib_c/x86_64-windows-msvc/c/consoleapi.cr +++ b/src/lib_c/x86_64-windows-msvc/c/consoleapi.cr @@ -2,4 +2,7 @@ require "c/winnt" lib LibC fun GetConsoleMode(hConsoleHandle : HANDLE, lpMode : DWORD*) : BOOL + + fun GetConsoleCP : DWORD + fun GetConsoleOutputCP : DWORD end diff --git a/src/lib_c/x86_64-windows-msvc/c/consoleapi2.cr b/src/lib_c/x86_64-windows-msvc/c/consoleapi2.cr new file mode 100644 index 000000000000..8fc8663e8bc4 --- /dev/null +++ b/src/lib_c/x86_64-windows-msvc/c/consoleapi2.cr @@ -0,0 +1,4 @@ +lib LibC + fun SetConsoleCP(wCodePageID : DWORD) : BOOL + fun SetConsoleOutputCP(wCodePageID : DWORD) : BOOL +end diff --git a/src/lib_c/x86_64-windows-msvc/c/winnls.cr b/src/lib_c/x86_64-windows-msvc/c/winnls.cr new file mode 100644 index 000000000000..dc30230d3865 --- /dev/null +++ b/src/lib_c/x86_64-windows-msvc/c/winnls.cr @@ -0,0 +1,5 @@ +lib LibC + CP_UTF8 = 65001 + + fun IsValidCodePage(codePage : DWORD) : BOOL +end