From 011babddb6c8b679f198d6c84cdfd85ca23396a5 Mon Sep 17 00:00:00 2001 From: "Victor M. Varela" Date: Sun, 2 Aug 2026 19:56:03 +0200 Subject: [PATCH 1/2] Fix: UTF-8 console output on Windows (Issue #201) Add setupConsoleOutput() calling SetConsoleOutputCP(65001) and SetConsoleMode with ENABLE_VIRTUAL_TERMINAL_PROCESSING on Windows startup. Compile-time gated via builtin.os.tag. No-op on non-Windows. Closes #201 --- src/main.zig | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/main.zig b/src/main.zig index 07eac25..2fe7a4a 100644 --- a/src/main.zig +++ b/src/main.zig @@ -17,6 +17,34 @@ const inspect_mode = @import("modes/inspect.zig"); const repl_mode = @import("modes/repl.zig"); const completions_mod = @import("completions.zig"); +// Windows console UTF-8 setup (Issue #201) +const windows = @import("std").os.windows; +const DWORD = windows.DWORD; +const HANDLE = windows.HANDLE; +const BOOL = windows.BOOL; +const UINT = windows.UINT; +const LPDWORD = *DWORD; + +const STD_OUTPUT_HANDLE: DWORD = @bitCast(@as(i32, -11)); +const ENABLE_VIRTUAL_TERMINAL_PROCESSING: DWORD = 0x0004; + +extern "kernel32" fn SetConsoleOutputCP(wCodePageID: UINT) callconv(.winapi) BOOL; +extern "kernel32" fn GetStdHandle(nStdHandle: DWORD) callconv(.winapi) HANDLE; +extern "kernel32" fn GetConsoleMode(hConsoleHandle: HANDLE, lpMode: LPDWORD) callconv(.winapi) BOOL; +extern "kernel32" fn SetConsoleMode(hConsoleHandle: HANDLE, dwMode: DWORD) callconv(.winapi) BOOL; + +/// Best-effort UTF-8 + VT support for the Windows console (Issue #201). +/// No-op on non-Windows: body eliminated at compile time. +fn setupConsoleOutput() void { + if (@import("builtin").os.tag == .windows) { + _ = SetConsoleOutputCP(65001); + const handle = GetStdHandle(STD_OUTPUT_HANDLE); + var mode: DWORD = 0; + _ = GetConsoleMode(handle, &mode); + _ = SetConsoleMode(handle, mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING); + } +} + const VERSION: []const u8 = build_options.version; const SqlPipeError = args_mod.SqlPipeError; @@ -374,6 +402,9 @@ pub fn main(init: std.process.Init.Minimal) void { // ponytail: c_allocator; DebugAllocator deinit was _ = discarded, leak detection was off const allocator = std.heap.c_allocator; + // Windows: enable UTF-8 output + VT processing for box-drawing chars (Issue #201) + setupConsoleOutput(); + var io = std.Io.Threaded.init_single_threaded; var stderr_buf: [1024]u8 = undefined; From 500fe4c0d5b3a6daf5f043bec5e1a7eb9f98b821 Mon Sep 17 00:00:00 2001 From: "Victor M. Varela" Date: Sun, 2 Aug 2026 20:01:23 +0200 Subject: [PATCH 2/2] Review fixes: add INVALID_HANDLE_VALUE check, inline windows import, add comment --- src/main.zig | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/main.zig b/src/main.zig index 2fe7a4a..ac07ea6 100644 --- a/src/main.zig +++ b/src/main.zig @@ -18,15 +18,15 @@ const repl_mode = @import("modes/repl.zig"); const completions_mod = @import("completions.zig"); // Windows console UTF-8 setup (Issue #201) -const windows = @import("std").os.windows; -const DWORD = windows.DWORD; -const HANDLE = windows.HANDLE; -const BOOL = windows.BOOL; -const UINT = windows.UINT; +const DWORD = std.os.windows.DWORD; +const HANDLE = std.os.windows.HANDLE; +const BOOL = std.os.windows.BOOL; +const UINT = std.os.windows.UINT; const LPDWORD = *DWORD; -const STD_OUTPUT_HANDLE: DWORD = @bitCast(@as(i32, -11)); +const STD_OUTPUT_HANDLE: DWORD = @bitCast(@as(i32, -11)); // 0xFFFFFFF5 const ENABLE_VIRTUAL_TERMINAL_PROCESSING: DWORD = 0x0004; +const INVALID_HANDLE_VALUE: HANDLE = @ptrFromInt(std.math.maxInt(usize)); extern "kernel32" fn SetConsoleOutputCP(wCodePageID: UINT) callconv(.winapi) BOOL; extern "kernel32" fn GetStdHandle(nStdHandle: DWORD) callconv(.winapi) HANDLE; @@ -39,6 +39,7 @@ fn setupConsoleOutput() void { if (@import("builtin").os.tag == .windows) { _ = SetConsoleOutputCP(65001); const handle = GetStdHandle(STD_OUTPUT_HANDLE); + if (handle == INVALID_HANDLE_VALUE) return; var mode: DWORD = 0; _ = GetConsoleMode(handle, &mode); _ = SetConsoleMode(handle, mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING);