this repo has no description
13
fork

Configure Feed

Select the types of activity you want to include in your feed.

WindowsTty: propagate ERROR_INVALID_HANDLE and provide packed structs

Some improvements to WindowsTty. The init function will now catch and
propagate an error.InvalidHandle so that caller can catch/handle it.

In addition, I added packed structs for the input/output
console modes which makes it convenient to manage the bits and is what
zigwin32 generates for its bindings. I also made these newly added types
and wrapper functions public as they can be generally useful for terminal
applications.

authored by

Jonathan Marler and committed by
Tim Culverhouse
2d5cd811 bd0438a1

+61 -46
+61 -46
src/tty.zig
··· 214 214 stdout: windows.HANDLE, 215 215 216 216 initial_codepage: c_uint, 217 - initial_input_mode: u32, 218 - initial_output_mode: u32, 217 + initial_input_mode: CONSOLE_MODE_INPUT, 218 + initial_output_mode: CONSOLE_MODE_OUTPUT, 219 219 220 220 // a buffer to write key text into 221 221 buf: [4]u8 = undefined, ··· 226 226 227 227 const utf8_codepage: c_uint = 65001; 228 228 229 - const InputMode = struct { 230 - const enable_window_input: u32 = 0x0008; // resize events 231 - const enable_mouse_input: u32 = 0x0010; 232 - const enable_extended_flags: u32 = 0x0080; // allows mouse events 233 - 234 - pub fn rawMode() u32 { 235 - return enable_window_input | enable_mouse_input | enable_extended_flags; 236 - } 229 + /// The input mode set by init 230 + pub const input_raw_mode: CONSOLE_MODE_INPUT = .{ 231 + .WINDOW_INPUT = 1, // resize events 232 + .MOUSE_INPUT = 1, 233 + .EXTENDED_FLAGS = 1, // allow mouse events 237 234 }; 238 235 239 - const OutputMode = struct { 240 - const enable_processed_output: u32 = 0x0001; // handle control sequences 241 - const enable_virtual_terminal_processing: u32 = 0x0004; // handle ANSI sequences 242 - const disable_newline_auto_return: u32 = 0x0008; // disable inserting a new line when we write at the last column 243 - const enable_lvb_grid_worldwide: u32 = 0x0010; // enables reverse video and underline 244 - 245 - fn rawMode() u32 { 246 - return enable_processed_output | 247 - enable_virtual_terminal_processing | 248 - disable_newline_auto_return | 249 - enable_lvb_grid_worldwide; 250 - } 236 + /// The output mode set by init 237 + pub const output_raw_mode: CONSOLE_MODE_OUTPUT = .{ 238 + .PROCESSED_OUTPUT = 1, // handle control sequences 239 + .VIRTUAL_TERMINAL_PROCESSING = 1, // handle ANSI sequences 240 + .DISABLE_NEWLINE_AUTO_RETURN = 1, // disable inserting a new line when we write at the last column 241 + .ENABLE_LVB_GRID_WORLDWIDE = 1, // enables reverse video and underline 251 242 }; 252 243 253 244 pub fn init() !Tty { 254 - const stdin = try windows.GetStdHandle(windows.STD_INPUT_HANDLE); 255 - const stdout = try windows.GetStdHandle(windows.STD_OUTPUT_HANDLE); 245 + const stdin = std.io.getStdIn().handle; 246 + const stdout = std.io.getStdOut().handle; 256 247 257 248 // get initial modes 258 - var initial_input_mode: windows.DWORD = undefined; 259 - var initial_output_mode: windows.DWORD = undefined; 260 249 const initial_output_codepage = windows.kernel32.GetConsoleOutputCP(); 261 - { 262 - if (windows.kernel32.GetConsoleMode(stdin, &initial_input_mode) == 0) { 263 - return windows.unexpectedError(windows.kernel32.GetLastError()); 264 - } 265 - if (windows.kernel32.GetConsoleMode(stdout, &initial_output_mode) == 0) { 266 - return windows.unexpectedError(windows.kernel32.GetLastError()); 267 - } 268 - } 250 + const initial_input_mode = try getConsoleMode(CONSOLE_MODE_INPUT, stdin); 251 + const initial_output_mode = try getConsoleMode(CONSOLE_MODE_OUTPUT, stdout); 269 252 270 253 // set new modes 271 - { 272 - if (windows.kernel32.SetConsoleMode(stdin, InputMode.rawMode()) == 0) 273 - return windows.unexpectedError(windows.kernel32.GetLastError()); 274 - 275 - if (windows.kernel32.SetConsoleMode(stdout, OutputMode.rawMode()) == 0) 276 - return windows.unexpectedError(windows.kernel32.GetLastError()); 277 - 278 - if (windows.kernel32.SetConsoleOutputCP(utf8_codepage) == 0) 279 - return windows.unexpectedError(windows.kernel32.GetLastError()); 280 - } 254 + try setConsoleMode(stdin, input_raw_mode); 255 + try setConsoleMode(stdout, output_raw_mode); 256 + if (windows.kernel32.SetConsoleOutputCP(utf8_codepage) == 0) 257 + return windows.unexpectedError(windows.kernel32.GetLastError()); 281 258 282 259 const self: Tty = .{ 283 260 .stdin = stdin, ··· 295 272 296 273 pub fn deinit(self: Tty) void { 297 274 _ = windows.kernel32.SetConsoleOutputCP(self.initial_codepage); 298 - _ = windows.kernel32.SetConsoleMode(self.stdin, self.initial_input_mode); 299 - _ = windows.kernel32.SetConsoleMode(self.stdout, self.initial_output_mode); 275 + setConsoleMode(self.stdin, self.initial_input_mode) catch {}; 276 + setConsoleMode(self.stdout, self.initial_output_mode) catch {}; 300 277 windows.CloseHandle(self.stdin); 301 278 windows.CloseHandle(self.stdout); 279 + } 280 + 281 + pub const CONSOLE_MODE_INPUT = packed struct(u32) { 282 + PROCESSED_INPUT: u1 = 0, 283 + LINE_INPUT: u1 = 0, 284 + ECHO_INPUT: u1 = 0, 285 + WINDOW_INPUT: u1 = 0, 286 + MOUSE_INPUT: u1 = 0, 287 + INSERT_MODE: u1 = 0, 288 + QUICK_EDIT_MODE: u1 = 0, 289 + EXTENDED_FLAGS: u1 = 0, 290 + AUTO_POSITION: u1 = 0, 291 + VIRTUAL_TERMINAL_INPUT: u1 = 0, 292 + _: u22 = 0, 293 + }; 294 + pub const CONSOLE_MODE_OUTPUT = packed struct(u32) { 295 + PROCESSED_OUTPUT: u1 = 0, 296 + WRAP_AT_EOL_OUTPUT: u1 = 0, 297 + VIRTUAL_TERMINAL_PROCESSING: u1 = 0, 298 + DISABLE_NEWLINE_AUTO_RETURN: u1 = 0, 299 + ENABLE_LVB_GRID_WORLDWIDE: u1 = 0, 300 + _: u27 = 0, 301 + }; 302 + 303 + pub fn getConsoleMode(comptime T: type, handle: windows.HANDLE) !T { 304 + var mode: u32 = undefined; 305 + if (windows.kernel32.GetConsoleMode(handle, &mode) == 0) return switch (windows.kernel32.GetLastError()) { 306 + .INVALID_HANDLE => error.InvalidHandle, 307 + else => |e| windows.unexpectedError(e), 308 + }; 309 + return @bitCast(mode); 310 + } 311 + 312 + pub fn setConsoleMode(handle: windows.HANDLE, mode: anytype) !void { 313 + if (windows.kernel32.SetConsoleMode(handle, @bitCast(mode)) == 0) return switch (windows.kernel32.GetLastError()) { 314 + .INVALID_HANDLE => error.InvalidHandle, 315 + else => |e| windows.unexpectedError(e), 316 + }; 302 317 } 303 318 304 319 pub fn opaqueWrite(ptr: *const anyopaque, bytes: []const u8) !usize {