From 65adffcf572c98c0198affcdf729d989fec253ae Mon Sep 17 00:00:00 2001 From: dam Date: Wed, 20 Sep 2023 18:00:20 +0100 Subject: Moved TUI into a module with split OS-based implementations. --- tui.jai | 363 ---------------------------------------------------------------- 1 file changed, 363 deletions(-) delete mode 100644 tui.jai (limited to 'tui.jai') diff --git a/tui.jai b/tui.jai deleted file mode 100644 index e2ecaaf..0000000 --- a/tui.jai +++ /dev/null @@ -1,363 +0,0 @@ - -// TODO Change this into a module with subfiles windows.jai and unix.jai -// #if OS == .WINDOWS { -// #load "windows.jai"; -// } else #if (OS == .LINUX) || (OS == .MACOS) { -// #load "unix.jai"; -// } else { -// #assert(false, "Unsupported OS."); -// } - - -// TODO On OS validations, use .LINUX or .MACOS to allow MACOS users to enj... errmmm test this. - -#import "Basic"; -#import "String"; - - - // https://learn.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences - // https://learn.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences#designate-character-set - // https://github.com/MicrosoftDocs/Console-Docs/blob/main/docs/console-virtual-terminal-sequences.md - -isTUIActive := false; // TODO Rename this variable. - - -Drawings :: struct { - CornerBR :: "\x6A"; - CornerTR :: "\x6B"; - CornerTL :: "\x6C"; - CornerBL :: "\x6D"; - Cross :: "\x6E"; - LineH :: "\x71"; - TeeL :: "\x74"; - TeeR :: "\x75"; - TeeB :: "\x76"; - TeeT :: "\x77"; - LineV :: "\x78"; - - Blank :: "\x5F"; - Diamond :: "\x60"; - Checkerboard :: "\x61"; - PlusMinus :: "\x67"; - LessThanOrEqual :: "\x79"; - GreaterThanOrEqual :: "\x7A"; - Pi :: "\x7B"; - NotEqual :: "\x7C"; - CenteredDot :: "\x7E"; -} - -Commands :: struct { - EnterAlternateBuffer :: "\e[?1049h"; - EnterMainBuffer :: "\e[?1049l"; - - EnterDrawingMode :: "\e(0"; - EnterNormalMode :: "\e(B"; - ClearScreen :: "\e[2J"; - ClearLine :: "\e[2K"; - - RefreshWindow :: "\e[7t"; // TODO Not yet tested. - - SetUTF8 :: "\e%G"; // TODO TEST ME PLEASE - - // Cursor Visibility - ShowCursor :: "\e[?25h"; - HideCursor :: "\e[?25l"; - StartBlinking :: "\e[?25h]"; - StopBlinking :: "\e[?25l]"; - SaveCursorPosition :: "\e7"; - RestoreCursorPosition :: "\e8"; - - // Cursor Shape - DefaultShape :: "\e[0 q"; - BlinkingBlockShape :: "\e[1 q"; - SteadyBlockShape :: "\e[2 q"; - BlinkingUnderlineShape :: "\e[3 q"; - SteadyUnderlineShape :: "\e[4 q"; - BlinkingBarShape :: "\e[5 q"; - SteadyBarShape :: "\e[6 q"; - - // Input Mode - KeypadAppMode :: "\e="; - KeypadNumMode :: "\e>"; - CursorAppMode :: "\e[?1h"; - CursorNormalMode :: "\e[?1l"; - - // Query State - QueryCursorPosition :: "\e[6n"; // Emits the cursor position as: "ESC [ ; R" Where = row and = column. - QueryDeviceAttributes :: "\e[0c"; - QueryWindowSizeInChars :: "\e[18t"; // Emits the window size as: "ESC [ 8 ; t" Where = row and = column. - -} - -start :: () { - #if OS == .LINUX { - // TODO Required to do unlocking input. - tcgetattr(STDIN_FILENO, *__term); - term_new := __term; - - term_new.c_iflag &= 0xFFFFFA14;// ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON); - term_new.c_oflag &= 0xFFFFFFFE;// ~OPOST; - term_new.c_lflag &= 0xFFFF7FB4;// ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); - term_new.c_cflag &= 0xFFFFFECF;// ~(CSIZE | PARENB); - term_new.c_cflag |= 0x00000030; - - tcsetattr(STDIN_FILENO, 0, *term_new); - } - else { - print("TODO TUI\n", to_standard_error = true); - - - // stdin - stdin = GetStdHandle(STD_INPUT_HANDLE ); - if stdin == INVALID_HANDLE_VALUE { - print("Invalid input handler.", to_standard_error = true); - return; - } - if GetConsoleMode(stdin, *initial_stdin_mode) == false { - print("Failed to get input mode.", to_standard_error = true); - return; - } - if SetConsoleMode(stdin, initial_stdin_mode | ENABLE_VIRTUAL_TERMINAL_INPUT) == 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; - } - if GetConsoleMode(stdout, *initial_stdout_mode) == false { - 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 { - print("Failed to set output mode: %.", GetLastError(), to_standard_error = true); - return; - } - } - write_strings(Commands.HideCursor, Commands.SaveCursorPosition, Commands.EnterAlternateBuffer, Commands.SetUTF8); - isTUIActive = true; -} - -stop :: () { - isTUIActive = false; - write_strings(Commands.EnterMainBuffer, Commands.RestoreCursorPosition, Commands.ShowCursor); - - #if OS == .LINUX { - tcsetattr(STDIN_FILENO, 0, *__term); // return echo - } - else { - 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; - } - } -} - -draw_box :: (x: int, y: int, width: int, height: int, to_standard_error := false) { - - - // TODO Hardcoded box starting at 1,1... fix this! - - write_strings( - // Commands.EnterNormalMode, - Commands.EnterDrawingMode, - "\e[1;1H", // Move to position 1,1 - // TODO // Move pointer to top-left corner. - Drawings.CornerTL, - to_standard_error = to_standard_error); - - for 1..width-2 { - write_string(Drawings.LineH, to_standard_error = to_standard_error); - } - write_string(Drawings.CornerTR, to_standard_error = to_standard_error); - - - // TODO Take care of the temporary allocations. - for idx: 2..height-1 { - tmpL := tprint("\e[%;%H", idx, 1); - tmpR := tprint("\e[%;%H", idx, width); - write_strings( - tmpL, - Drawings.LineV, - tmpR, - Drawings.LineV, - to_standard_error = to_standard_error); - } - - tmpBL := tprint("\e[%;%H", height, 1); - write_strings( - tmpBL, - Drawings.CornerBL, - to_standard_error = to_standard_error); - for 1..width-2 { - write_string(Drawings.LineH, to_standard_error = to_standard_error); - } - write_string(Drawings.CornerBR, to_standard_error = to_standard_error); - - write_strings( - // TODO // print - Commands.EnterNormalMode, - to_standard_error = to_standard_error); -} - -clear_screen :: inline () { - write_string(Commands.ClearScreen); -} - - -// get_cursor_position :: () -> row: int, column: int { -// assert(isTUIActive, "TUI is not active."); // TODO -// write_string(TUI.Commands.QueryCursorPosition); // Returned "\e[21;1R" -// read_input() -// } - - -// read_input: () -> string; - -#if OS == .LINUX { - #import "Basic"; - #import "POSIX"; - - __term : My_Termios; - - My_Termios :: struct { - c_iflag : u32; // Input mode flags. - c_oflag : u32; // Output mode flags. - c_cflag : u32; // Control modes flags. - c_lflag : u32; // Local modes flags. - c_line : u8; // Line discipline. - c_cc : [32]u8; // Control characters. - c_ispeed : u32; // Input speed (baud rates). - c_ospeed : u32; // Output speed (baud rates). - } - - // Required to do unlocking input. - libc :: #system_library "libc"; - - // https://codebrowser.dev/glibc/glibc/sysdeps/unix/sysv/linux/tcsetattr.c.html - tcsetattr :: (fd : s32, optional_actions : s32, termios_p : *My_Termios) -> s32 #foreign libc; - - // https://codebrowser.dev/glibc/glibc/sysdeps/unix/sysv/linux/tcgetattr.c.html - tcgetattr :: (fd : s32, termios_p : *My_Termios) -> s32 #foreign libc; - - - - read_input :: () -> string { - buffer: [8192] u8; - bytes_read := read(STDIN_FILENO, buffer.data, buffer.count-1); - str := to_string(buffer.data, bytes_read); - return str; - }; - - get_buffer_size :: () -> rows: int, columns: int { - buffer: [512] u8; - write_string(Commands.QueryWindowSizeInChars); - bytes_read := read(STDIN_FILENO, buffer.data, buffer.count-1); - - str := to_string(buffer.data, bytes_read); - - // Result: [8;79;156t - assert( - buffer.data[0] == #char "\e" && - buffer.data[1] == #char "[" && - buffer.data[2] == #char "8", - "Query windows size in chars returned invalid response."); - - parts := split(str, ";"); - rows := parse_int(*parts[1]); - columns := parse_int(*parts[2]); - return rows, columns; - } - -} -else #if OS == .WINDOWS { - #import "Windows"; - - ENABLE_VIRTUAL_TERMINAL_INPUT :: 0x0200; - - ENABLE_PROCESSED_OUTPUT :: 0x0001; - ENABLE_WRAP_AT_EOL_OUTPUT :: 0x0002; - ENABLE_VIRTUAL_TERMINAL_PROCESSING :: 0x0004; - DISABLE_NEWLINE_AUTO_RETURN :: 0x0008; - ENABLE_LVB_GRID_WORLDWIDE :: 0x0010; - - SHORT :: s16; - WORD :: u16; - DWORD :: s32; - - COORD :: struct { - X : SHORT; - Y : SHORT; - } - - SMALL_RECT :: struct { - Left : SHORT; - Top : SHORT; - Right : SHORT; - Bottom : SHORT; - } - - CONSOLE_SCREEN_BUFFER_INFO :: struct { - dwSize : COORD; - dwCursorPosition : COORD; - - wAttributes : WORD; - srWindow : SMALL_RECT; - dwMaximumWindowSize : COORD; - } - - kernel32 :: #system_library "kernel32"; - - 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; - GetConsoleMode :: (hConsoleHandle: HANDLE, lpMode: *u32) -> bool #foreign kernel32; - SetConsoleMode :: (hConsoleHandle: HANDLE, dwMode: u32) -> bool #foreign kernel32; - GetLastError :: () -> s32 #foreign kernel32; - - stdin: HANDLE; - initial_stdin_mode: u32; - stdout: HANDLE; - initial_stdout_mode: u32; - - // #run read_input = () -> string { - read_input :: () -> string { - MAX_BYTES_TO_READ :: 1024; - temp : [MAX_BYTES_TO_READ] u8; - result: string = ---; - bytes_read : s32; - - if !ReadConsoleA( stdin, temp.data, xx temp.count, *bytes_read ) - return ""; - - result.data = alloc(bytes_read); - result.count = bytes_read; - memcpy(result.data, temp.data, bytes_read); - return result; - }; - - get_buffer_size :: () -> rows: int, columns: int { - - // GET WINDOW CHAR SIZE - - - ScreenBufferInfo: CONSOLE_SCREEN_BUFFER_INFO; - GetConsoleScreenBufferInfo(stdout, *ScreenBufferInfo); - Size: COORD; - Size.X = ScreenBufferInfo.srWindow.Right - ScreenBufferInfo.srWindow.Left + 1; - Size.Y = ScreenBufferInfo.srWindow.Bottom - ScreenBufferInfo.srWindow.Top + 1; - - return Size.Y, Size.X; - } -} -- cgit v1.2.3