diff options
Diffstat (limited to 'TUI/module.jai')
| -rw-r--r-- | TUI/module.jai | 194 |
1 files changed, 194 insertions, 0 deletions
diff --git a/TUI/module.jai b/TUI/module.jai new file mode 100644 index 0000000..67a9edd --- /dev/null +++ b/TUI/module.jai @@ -0,0 +1,194 @@ +#if OS == .WINDOWS { + #load "windows.jai"; +} else #if (OS == .LINUX) || (OS == .MACOS) { + #load "unix.jai"; +} else { + #assert(false, "Unsupported OS."); +} + +#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> ; <c> R" Where <r> = row and <c> = column. + QueryDeviceAttributes :: "\e[0c"; + QueryWindowSizeInChars :: "\e[18t"; // Emits the window size as: "ESC [ 8 <r> ; <c> t" Where <r> = row and <c> = column. + +} + +start :: () { + OS_prepare_terminal(); + write_strings(Commands.HideCursor, Commands.SaveCursorPosition, Commands.EnterAlternateBuffer, Commands.SetUTF8); + isTUIActive = true; +} + +stop :: () { + isTUIActive = false; + write_strings(Commands.EnterMainBuffer, Commands.RestoreCursorPosition, Commands.ShowCursor); + OS_reset_terminal(); +} + +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_terminal_size :: () -> rows: int, columns: int { + rows, columns := OS_get_terminal_size(); + return rows, columns; +} + +// read_input: () -> string { + // return OS_read_input(); +// } + +// 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 == .WINDOWS { + + // #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; + }; +} +else #if OS == .LINUX || OS == .MACOS { + #import "Basic"; + #import "POSIX"; + + 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; + }; +} |
