aboutsummaryrefslogtreecommitdiff
path: root/TUI/windows.jai
diff options
context:
space:
mode:
Diffstat (limited to 'TUI/windows.jai')
-rw-r--r--TUI/windows.jai87
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;
+};