diff options
Diffstat (limited to 'TUI/windows.jai')
| -rw-r--r-- | TUI/windows.jai | 87 |
1 files changed, 79 insertions, 8 deletions
diff --git a/TUI/windows.jai b/TUI/windows.jai index ef0cfa8..24dbece 100644 --- a/TUI/windows.jai +++ b/TUI/windows.jai @@ -3,11 +3,19 @@ kernel32 :: #system_library "kernel32"; + // https://learn.microsoft.com/en-us/windows/console/getconsolescreenbufferinfo GetConsoleScreenBufferInfo :: (hConsoleOutput: HANDLE, lpConsoleScreenBufferInfo: *CONSOLE_SCREEN_BUFFER_INFO) -> bool #foreign kernel32; - ReadConsoleA :: (hConsoleHandle: HANDLE, buff : *u8, chars_to_read : s32, chars_read : *s32, lpInputControl := *void ) -> bool #foreign kernel32; - // ReadConsole :: (hConsoleInput: HANDLE, lpBuffer: *u8, nNumberOfCharsToRead: s32, lpNumberOfCharsRead: *s32, pInputControl := *void) -> bool #foreign kernel32; + + // https://learn.microsoft.com/en-us/windows/console/readconsole + ReadConsoleA :: (hConsoleInput: HANDLE, lpBuffer: *u8, nNumberOfCharsToRead: s32, lpNumberOfCharsRead: *s32, pInputControl := *void) -> bool #foreign kernel32; + + // https://learn.microsoft.com/en-us/windows/console/getconsolemode GetConsoleMode :: (hConsoleHandle: HANDLE, lpMode: *u32) -> bool #foreign kernel32; + + // https://learn.microsoft.com/en-us/windows/console/setconsolemode SetConsoleMode :: (hConsoleHandle: HANDLE, dwMode: u32) -> bool #foreign kernel32; + + // https://learn.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-getlasterror GetLastError :: () -> s32 #foreign kernel32; ENABLE_VIRTUAL_TERMINAL_INPUT :: 0x0200; @@ -18,6 +26,28 @@ DISABLE_NEWLINE_AUTO_RETURN :: 0x0008; ENABLE_LVB_GRID_WORLDWIDE :: 0x0010; + + // https://learn.microsoft.com/en-us/windows/console/setconsolemode + Console_Mode :: enum_flags u32 { + _UNUSED_0001_; + ENABLE_LINE_INPUT; // If enable, ReadFile or ReadConsole function return on CR; otherwise they return when one or more characters are available. + ENABLE_ECHO_INPUT; // Echoes input on screen. Only available if ENABLE_LINE_INPUT is set. + _UNUSED_0008_; + ENABLE_MOUSE_INPUT; // + ENABLE_INSERT_MODE; // If enabled, text entered will be inserted at the current cursor location and all text following that location will not be overwritten. When disabled, all following text will be overwritten. + _UNSED_0040_; + _UNSED_0080_; + _UNSED_0100_; + ENABLE_VIRTUAL_TERMINAL_INPUT; // + _UNSED_0400_; + _UNSED_0800_; + _UNSED_1000_; + _UNSED_2000_; + _UNSED_4000_; + _UNSED_8000_; + } + + // https://learn.microsoft.com/en-us/windows/win32/winprog/windows-data-types SHORT :: s16; WORD :: u16; DWORD :: s32; @@ -46,8 +76,13 @@ stdin: HANDLE; initial_stdin_mode: u32; + default_stdin_mode: Console_Mode; + blocking_stdin_mode: Console_Mode; + unblocking_stdin_mode: Console_Mode; + stdout: HANDLE; initial_stdout_mode: u32; + default_stdout_mode: Console_Mode; OS_prepare_terminal :: () { @@ -64,14 +99,17 @@ OS_prepare_terminal :: () { print("Failed to get input mode.", to_standard_error = true); return; } - if SetConsoleMode(stdin, initial_stdin_mode | ENABLE_VIRTUAL_TERMINAL_INPUT) == false { + default_stdin_mode = (cast(Console_Mode) initial_stdin_mode) | .ENABLE_VIRTUAL_TERMINAL_INPUT; + blocking_stdin_mode = default_stdin_mode | .ENABLE_LINE_INPUT | .ENABLE_ECHO_INPUT; + unblocking_stdin_mode = default_stdin_mode & ~.ENABLE_LINE_INPUT & ~.ENABLE_ECHO_INPUT; + + if SetConsoleMode(stdin, xx default_stdin_mode) == false { print("Failed to set input mode: %.", GetLastError(), to_standard_error = true); return; } // stdout stdout = GetStdHandle(STD_OUTPUT_HANDLE); - outMode: u32 = 0; if stdout == INVALID_HANDLE_VALUE { print("Invalid output handler.", to_standard_error = true); return; @@ -80,20 +118,19 @@ OS_prepare_terminal :: () { print("Failed to get output mode.", to_standard_error = true); return; } - if SetConsoleMode(stdout, initial_stdout_mode | ENABLE_PROCESSED_OUTPUT| ENABLE_VIRTUAL_TERMINAL_PROCESSING) == false { + default_stdout_mode = (cast(Console_Mode) initial_stdout_mode) | ENABLE_PROCESSED_OUTPUT| ENABLE_VIRTUAL_TERMINAL_PROCESSING; + + if SetConsoleMode(stdout, xx default_stdout_mode) == false { print("Failed to set output mode: %.", GetLastError(), to_standard_error = true); return; } } OS_reset_terminal :: () { - print("TODO TUI\n", to_standard_error = true); - if SetConsoleMode(stdin, initial_stdin_mode) == false { print("Failed to reset input mode: %.", GetLastError(), to_standard_error = true); return; } - if SetConsoleMode(stdout, initial_stdout_mode) == false { print("Failed to reset output mode: %.", GetLastError(), to_standard_error = true); return; @@ -109,3 +146,37 @@ OS_get_terminal_size :: () -> rows: int, columns: int { return rows, columns; } + +OS_read_input :: (mode: Input_Mode) -> string { + result: string = ---; + + if mode == { + case .HUMAN; + assert(SetConsoleMode(stdin, xx blocking_stdin_mode), "Failed to set input mode to blocking mode."); // @speed TODO Could check if was already set before applying. + + case .MACHINE; + // assert(SetConsoleMode(stdin, xx unblocking_stdin_mode), "Failed to set input mode to unblocking mode."); // @speed TODO Could check if was already set before applying. + if SetConsoleMode(stdin, xx unblocking_stdin_mode) == false { + print("Failed to set input mode: %.", GetLastError(), to_standard_error = true); + exit(0); + } + } + + MAX_BYTES_TO_READ :: 10; + temp : [MAX_BYTES_TO_READ] u8; + bytes_read : s32; + + if ReadConsoleA(stdin, temp.data, xx temp.count, *bytes_read) { + + // TODO If the number of bytes_read is equal to the buffer size... we may have some more data to read?! + // ---> To fix this, we should check the last read byte and see if it's a newline! + + result.data = alloc(bytes_read); + result.count = bytes_read; + memcpy(result.data, temp.data, bytes_read); + } + + assert(SetConsoleMode(stdin, xx default_stdin_mode), "Failed to set default input mode."); // @speed TODO Maybe compare current mode with default one before applying?! + + return result; +}; |
