Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 21 additions & 19 deletions src/crystal/system/win32/file_descriptor.cr
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,26 @@ module Crystal::System::FileDescriptor
LibC.SetConsoleMode(windows_handle, old_mode)
end
end

def self.setup_console : Nil
# 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

# Start a dedicated thread to block on reads from the console. Doesn't need
# an isolated execution context because there's no fiber communication (only
# thread communication) and only blocking I/O within the thread.
@@reader_thread = ::Thread.new("CONSOLE") { ConsoleUtils.reader_loop }
end
end

private module ConsoleUtils
Expand Down Expand Up @@ -521,13 +541,8 @@ private module ConsoleUtils
@@read_requests = Deque(ReadRequest).new
@@bytes_read = Deque(Int32).new
@@mtx = ::Thread::Mutex.new
{% if flag?(:execution_context) %}
@@reader_thread = ::Fiber::ExecutionContext::Isolated.new("READER-LOOP") { reader_loop }
{% else %}
@@reader_thread = ::Thread.new { reader_loop }
{% end %}

private def self.reader_loop
def self.reader_loop
while true
request = @@mtx.synchronize do
loop do
Expand All @@ -547,16 +562,3 @@ private module ConsoleUtils
end
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
5 changes: 4 additions & 1 deletion src/kernel.cr
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
require "crystal/at_exit_handlers"

{% unless flag?(:win32) %}
{% if flag?(:win32) %}
# Set console to UTF-8 and start thread to read from STDIN asynchronously.
Crystal::System::FileDescriptor.setup_console
{% else %}
require "c/unistd"
{% end %}

Expand Down
Loading