diff options
| author | dam <dam@gudinoff> | 2023-10-16 00:48:04 +0100 |
|---|---|---|
| committer | dam <dam@gudinoff> | 2023-10-16 00:48:04 +0100 |
| commit | 3b9f4f990ab0e865ec8e6277381e5aff0b178665 (patch) | |
| tree | e46c7a14b4c2accd97001708768884c101883933 | |
| parent | 27269b059e7a5ae72a85b243919ad849ed672643 (diff) | |
| download | task-time-tracker-3b9f4f990ab0e865ec8e6277381e5aff0b178665.tar.zst task-time-tracker-3b9f4f990ab0e865ec8e6277381e5aff0b178665.zip | |
First prototype of TUI reading the input using another thread.
| -rw-r--r-- | TUI/module.jai | 187 | ||||
| -rw-r--r-- | TUI/unix.jai | 274 | ||||
| -rw-r--r-- | ttt.jai | 151 |
3 files changed, 399 insertions, 213 deletions
diff --git a/TUI/module.jai b/TUI/module.jai index 034ec15..7a7dc54 100644 --- a/TUI/module.jai +++ b/TUI/module.jai @@ -8,6 +8,7 @@ #import "Basic"; #import "String"; +#import "Thread"; Drawings :: struct { CornerBR :: "\x6A"; @@ -84,18 +85,144 @@ Commands :: struct { initialized := false; +input_buffer_mutex: Mutex; +input_buffer: string; +input_counter: s64; +read_buffer: [4096] u8; + +input_process_thread: Thread; + +Key :: u8; // TODO To be improved. +Keys :: enum u8 { + None :: 0; + Resize :: 1; //410; // TODO Why?! +} + +input_semaphore: Semaphore; +key_semaphore: Semaphore; +key_mutex: Mutex; +key_input := Keys.None; +key_resize := Keys.None; +// key_queue: [2] Key; // TODO Queue with size 1!? hmmm nice! +// key_queue_idx := 0; + + + +// queue_semaphore: Semaphore; +// queue_mutex: Mutex; +// queue :: Keys; + +// Notes +// So, the semaphore usage should indicate the items on the key_queue. +// If we don't want to use a queue, maybe we can use two Key items, one for user input, and another, with higher priority, for Resize. + +dam :: (msg: string) { + print(msg, to_standard_error = true); +} + +process_input :: (thread: *Thread) -> s64 { + char: u8; + dam(">START signal_input\n"); + defer dam(">STOP signal_input\n"); + while(true) { + if initialized == false return 0; + if key_input != Keys.None { // TODO Reading without mutex... + dam("waiting.."); + sleep_milliseconds(100); + dam("!\n\r"); + continue; + } + dam("reading.."); + bytes_read := OS_read_input(*char, 1); + dam("!\n\r"); + if bytes_read > 0 { + lock(*key_mutex); + defer unlock(*key_mutex); + key_input = xx char; + dam("signaling.."); + dam("!\n\r"); + signal(*key_semaphore); + } + } + return 0; +} + +process_resize :: (signal : s32) #c_call { + new_context : Context; + push_context new_context { + if signal != SIGWINCH return; + lock(*key_mutex); + defer unlock(*key_mutex); + // TODO Only signal the key_semaphore if we don't already have a Resize on the queue. + if key_resize != Key.None continue; + key_resize = Keys.Resize; + signal(*key_semaphore); + } +} + +get_key :: (wait_milliseconds: s32) -> Key { + wait_for(*key_semaphore, wait_milliseconds); + + lock(*key_mutex); + defer unlock(*key_mutex); + + if key_resize != Keys.None { + defer key_resize = Keys.None; + return xx key_resize; + } + + defer key_input = Keys.None; + return xx key_input; +} + + start :: () { - if initialized return; - write_strings(Commands.HideCursor, Commands.SaveCursorPosition, Commands.EnterAlternateBuffer, Commands.SetUTF8); + if initialized == true return; +dam("A"); + // write_strings(Commands.HideCursor, Commands.SaveCursorPosition, Commands.EnterAlternateBuffer, Commands.SetUTF8); OS_prepare_terminal(); +dam("B"); + input_buffer = alloc_string(4096); + init(*input_buffer_mutex, "input_buffer_mutex"); + assert(thread_init(*input_process_thread, process_input), "Failed to initialize thread."); +dam("C"); + // init(*input_semaphore); + init(*key_semaphore); + init(*key_mutex, "key_mutex"); +dam("D"); initialized = true; + thread_start(*input_process_thread); +dam("E"); } stop :: () { if initialized == false return; initialized = false; + + // signal(*input_semaphore); // TODO Maybe use tcflush ??? + thread_deinit(*input_process_thread); + + // destroy(*input_semaphore); + destroy(*key_semaphore); + OS_reset_terminal(); - write_strings(Commands.EnterMainBuffer, Commands.RestoreCursorPosition, Commands.ShowCursor); + // write_strings(Commands.EnterMainBuffer, Commands.RestoreCursorPosition, Commands.ShowCursor); +} + +get_str :: () -> string { + lock(*input_buffer_mutex); + defer unlock(*input_buffer_mutex); + return input_buffer; + // return tprint("%", to_string(input_buffer)); + // print("%", tprint("%", input_buffer)); + // return tprint("%", input_buffer); +} + +flush_input :: () { + // TODO + lock(*input_buffer_mutex); + defer unlock(*input_buffer_mutex); + input_buffer.count = 0; } draw_box :: (x: int, y: int, width: int, height: int) { @@ -191,33 +318,33 @@ Input_Mode :: enum u8 { MACHINE; // Hides cursor, hides input, and reads right away once the first input is available. } -read_input :: (allocator: Allocator = temp, $mode: Input_Mode = .HUMAN) -> string { - #if mode == .HUMAN { - write_string(Commands.ShowCursor); - defer write_string(Commands.HideCursor); - - OS_set_input_mode(.HUMAN); - defer OS_set_input_mode(.MACHINE); - } - - assert(allocator.proc != null, "Argument 'allocator.proc' has invalid null value."); - - #assert(mode != .MACHINE); // TODO Keep an eye if I try to use read_input for machine read. Eventually, remove mode from the procedure arguments. - - builder: String_Builder(); - builder.allocator = allocator; - init_string_builder(*builder); - - while(1) { - buffer := get_current_buffer(*builder); - buffer_data := get_buffer_data(buffer); - buffer.count = OS_read_input(buffer_data, buffer.allocated); // TODO Does not check for read errors. - if buffer.count == 0 || buffer_data[buffer.count-1] == #char "\n" break; - assert(buffer.count == buffer.allocated); // TODO If newline wasn't detected, it's because the buffer got full. - expand(*builder); - } - return builder_to_string(*builder, allocator); -} +// read_input :: (allocator: Allocator = temp, $mode: Input_Mode = .HUMAN) -> string { + // #if mode == .HUMAN { + // write_string(Commands.ShowCursor); + // defer write_string(Commands.HideCursor); + // + // OS_set_input_mode(.HUMAN); + // defer OS_set_input_mode(.MACHINE); + // } +// + // assert(allocator.proc != null, "Argument 'allocator.proc' has invalid null value."); +// + // #assert(mode != .MACHINE); // TODO Keep an eye if I try to use read_input for machine read. Eventually, remove mode from the procedure arguments. + // + // builder: String_Builder(); + // builder.allocator = allocator; + // init_string_builder(*builder); + // + // while(1) { + // buffer := get_current_buffer(*builder); + // buffer_data := get_buffer_data(buffer); + // buffer.count = OS_read_input(buffer_data, buffer.allocated); // TODO Does not check for read errors. + // if buffer.count == 0 || buffer_data[buffer.count-1] == #char "\n" break; + // assert(buffer.count == buffer.allocated); // TODO If newline wasn't detected, it's because the buffer got full. + // expand(*builder); + // } + // return builder_to_string(*builder, allocator); +// } #if OS == .WINDOWS { diff --git a/TUI/unix.jai b/TUI/unix.jai index 434935b..1bfa400 100644 --- a/TUI/unix.jai +++ b/TUI/unix.jai @@ -6,175 +6,158 @@ // Required to do unlocking input. libc :: #system_library "libc"; + // TODO Remote this. + cfmakeraw :: (termios: *Terminal_IO_Mode) -> void #foreign libc; + // https://codebrowser.dev/glibc/glibc/sysdeps/unix/sysv/linux/tcsetattr.c.html - tcsetattr :: (fd : s32, optional_actions : s32, termios_p : *Terminal_IO_Mode) -> s32 #foreign libc; + tcsetattr :: (fd: s32, optional_actions: s32, termios_p : *Terminal_IO_Mode) -> s32 #foreign libc; // https://codebrowser.dev/glibc/glibc/sysdeps/unix/sysv/linux/tcgetattr.c.html - tcgetattr :: (fd : s32, termios_p : *Terminal_IO_Mode) -> s32 #foreign libc; + tcgetattr :: (fd: s32, termios_p: *Terminal_IO_Mode) -> s32 #foreign libc; + + // Information for the termios.h enums is platform dependent and was retrieved from: + // https://elixir.bootlin.com/glibc/latest/source/sysdeps/unix/sysv/linux/bits/termios.h + // Set Attributes Actions. + SetAttributesActions :: enum u32 { + TCSANOW :: 0; // Change immediately. + TCSADRAIN :: 1; // Change when pending output is written. + TCSAFLUSH :: 2; // Flush pending input before changing. + } // Input modes. - // https://elixir.bootlin.com/glibc/latest/source/bits/termios.h Input_Modes :: enum_flags u32 { - IGNBRK; // Ignore break condition. - BRKINT; // Signal interrupt on break. - IGNPAR; // Ignore characters with parity errors. - PARMRK; // Mark parity and framing errors. - - INPCK; // Enable input parity check. - ISTRIP; // Strip 8th bit off characters. - INLCR; // Map NL to CR on input. - IGNCR; // Ignore CR. - - ICRNL; // Map CR to NL on input. - IXON; // Enable start/stop output control. - IXOFF; // Enable start/stop input control. - IXANY; // Any character will restart after stop. - - _1000_; - IMAXBEL; // Ring bell when input queue is full. - IUCLC; // Translate upper case input to lower case. not in POSIX - _8000_; + IGNBRK :: 0000001; // Ignore break condition. + BRKINT :: 0000002; // Signal interrupt on break. + IGNPAR :: 0000004; // Ignore characters with parity errors. + PARMRK :: 0000010; // Mark parity and framing errors. + INPCK :: 0000020; // Enable input parity check. + ISTRIP :: 0000040; // Strip 8th bit off characters. + INLCR :: 0000100; // Map NL to CR on input. + IGNCR :: 0000200; // Ignore CR. + ICRNL :: 0000400; // Map CR to NL on input. + IUCLC :: 0001000; // Translate upper case input to lower case (not in POSIX). + IXON :: 0002000; // Enable start/stop output control. + IXANY :: 0004000; // Any character will restart after stop. + IXOFF :: 0010000; // Enable start/stop input control. + IMAXBEL :: 0020000; // Ring bell when input queue is full (not in POSIX). + IUTF8 :: 0040000; // Input is UTF8 (not in POSIX). } - + // Output modes. - // https://elixir.bootlin.com/glibc/latest/source/bits/termios.h Output_Modes :: enum_flags u32 { - OPOST; // Perform output processing. - ONLCR; // Map NL to CR-NL on output. - _UNUSED_0004_; - ONOEOT; // Discard EOT (^D) on output. - OCRNL; // Map CR to NL. - ONOCR; // Discard CR's when on column 0. - ONLRET; // Move to column 0 on NL. - _UNUSED_0080_; + OPOST :: 0000001; // Perform output processing. + OLCUC :: 0000002; // Map lowercase characters to uppercase on output (not in POSIX). + ONLCR :: 0000004; // Map NL to CR-NL on output. + OCRNL :: 0000010; // Map CR to NL. + ONOCR :: 0000020; // Discard CR's when on column 0. + ONLRET :: 0000040; // Move to column 0 on NL. + OFILL :: 0000100; // Send fill characters for delays. + OFDEL :: 0000200; // Fill is DEL. + VTDLY :: 0040000; // Select vertical-tab delays: + VT0 :: 0000000; // Vertical-tab delay type 0. + VT1 :: 0040000; // Vertical-tab delay type 1. } - + // Control modes. - // https://elixir.bootlin.com/glibc/latest/source/bits/termios.h - Control_Modes :: enum_flags u32 { - CIGNORE; // Ignore these control flags. - _0002_; - _0004_; - _0008_; - - _0010_; - _0020_; - _0040_; - _0080_; - - _0100_; - _0200_; - CSTOPB; // Two stop bits instead of one. - CREAD; // Enable receiver. - - PARENB; // Parity enable. - PARODD; // Odd parity instead of even. - HUPCL; // Hang up on last close. - CLOCAL; // Ignore modem status lines. - - CRTSCTS; // RTS/CTS flow control. - CDTRCTS; // DTR/CTS flow control. - _0004_0000_; - _0008_0000_; - - MDMBUF; // DTR/DCD flow control. + Control_Modes :: enum u32 { + CS5 :: 0000000; // 5 bits per byte. + CS6 :: 0000020; // 6 bits per byte. + CS7 :: 0000040; // 7 bits per byte. + CS8 :: 0000060; // 8 bits per byte. + CSIZE :: 0000060; // Number of bits per byte (mask). + CSTOPB :: 0000100; // Two stop bits instead of one. + CREAD :: 0000200; // Enable receiver. + PARENB :: 0000400; // Parity enable. + PARODD :: 0001000; // Odd parity instead of even. + HUPCL :: 0002000; // Hang up on last close. + CLOCAL :: 0004000; } - - CHWFLOW :Control_Modes : (.MDMBUF | .CRTSCTS | .CDTRCTS); // All types of flow control. - CS5 :Control_Modes : 0x0000; // 5 bits per byte. - CS6 :Control_Modes : 0x0100; // 6 bits per byte. - CS7 :Control_Modes : 0x0200; // 7 bits per byte. - CS8 :Control_Modes : CS6|CS7; // 8 bits per byte. - CSIZE :Control_Modes : CS5|CS6|CS7|CS8; // Number of bits per byte (mask). - + // Local modes. - // https://elixir.bootlin.com/glibc/latest/source/bits/termios.h Local_Modes :: enum_flags u32 { - ECHOKE; // Visual erase for KILL. - ECHOE; // Visual erase for ERASE. - ECHOK; // Echo NL after KILL. - ECHO; // Enable echo. - - ECHONL; // Echo NL even if ECHO is off. - ECHOPRT; // Hardcopy visual erase. - ECHOCTL; // Echo control characters as ^X. - ISIG; // Enable signals. - - ICANON; // Do erase and kill processing. - ALTWERASE; // Alternate WERASE algorithm. - IEXTEN; // Enable DISCARD and LNEXT. - EXTPROC; // External processing. - - _1000_; - _2000_; - _4000_; - _8000_; - - _0001_0000_; - _0002_0000_; - // TODO Maybe reduce the amount of unused flags by setting the value when there are holes on the table. - // TOSTOP :: 0x0004_0000; // Send SIGTTOU for background output. - TOSTOP; // Send SIGTTOU for background output. - FLUSHO; // Output being flushed (state). - - XCASE; // Canonical upper/lower case. - NOKERNINFO; // Disable VSTATUS. - _0040_0000_; - _0080_0000_; - - _0100_0000_; - PENDIN; // Retype pending input (state). - _0400_0000_; - NOFLSH; // Disable flush after interrupt. + ISIG :: 0000001; // Enable signals. + ICANON :: 0000002; // Do erase and kill processing. + ECHO :: 0000010; // Enable echo. + ECHOE :: 0000020; // Visual erase for ERASE. + ECHOK :: 0000040; // Echo NL after KILL. + ECHONL :: 0000100; // Echo NL even if ECHO is off. + NOFLSH :: 0000200; // Disable flush after interrupt. + TOSTOP :: 0000400; // Send SIGTTOU for background output. + IEXTEN :: 0100000; // Enable DISCARD and LNEXT. } - Terminal_IO_Mode :: struct { - c_iflag : Input_Modes; // Input mode flags. - c_oflag : Output_Modes; // Output mode flags. - c_cflag : Control_Modes; // Control modes flags. - c_lflag : Local_Modes; // 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). + // Control Characters + Control_Chars :: enum u8 { + VINTR :: 0; + VQUIT :: 1; + VERASE :: 2; + VKILL :: 3; + VEOF :: 4; + VTIME :: 5; // Time-out value (tenths of a second) [!ICANON]. + VMIN :: 6; // Minimum number of bytes read at once [!ICANON]. + VSWTC :: 7; + VSTART :: 8; + VSTOP :: 9; + VSUSP :: 10; + VEOL :: 11; + VREPRINT :: 12; + VDISCARD :: 13; + VWERASE :: 14; + VLNEXT :: 15; + VEOL2 :: 16; } - + // The struct termios. + Terminal_IO_Mode :: struct { + c_iflag : Input_Modes; // Input mode flags. + c_oflag : Output_Modes; // Output mode flags. + c_cflag : Control_Modes; // Control modes flags. + c_lflag : Local_Modes; // Local modes flags. + c_line : u8; // Line discipline. + c_cc : [32]Control_Chars;// Control characters. + c_ispeed : u32; // Input speed (baud rates). + c_ospeed : u32; // Output speed (baud rates). + } + initial_tio_mode: Terminal_IO_Mode; - default_tio_mode: Terminal_IO_Mode; // TODO Rename to 'raw_tio_mode' - human_tio_mode: Terminal_IO_Mode; // TODO Rename to 'cooked_tio_mode' + raw_tio_mode: Terminal_IO_Mode; #scope_export OS_prepare_terminal :: () { - tcgetattr(STDIN_FILENO, *initial_tio_mode); - - default_tio_mode = initial_tio_mode; - default_tio_mode.c_iflag &= ~(.IGNBRK | .BRKINT | .PARMRK | .ISTRIP | .INLCR | .IGNCR | .ICRNL | .IXOFF); - default_tio_mode.c_oflag &= ~(.OPOST); - default_tio_mode.c_cflag &= ~(CSIZE | .PARENB); - default_tio_mode.c_lflag &= ~(.ECHOCTL |.ECHO | .ECHOE | .ECHOKE); - - human_tio_mode = default_tio_mode; - human_tio_mode.c_iflag |= (.IXOFF | .ICRNL); - human_tio_mode.c_lflag |= (.NOKERNINFO | .ECHO | .ECHOE | .ECHOKE); - - tcsetattr(STDIN_FILENO, 0, *default_tio_mode); + error: s32; + tcgetattr(STDIN_FILENO, *initial_tio_mode); // TODO Log on error. + raw_tio_mode = initial_tio_mode; + raw_tio_mode.c_iflag &= ~(.IGNBRK | .BRKINT | .PARMRK | .ISTRIP | .INLCR | .IGNCR | .ICRNL | .IXON); + raw_tio_mode.c_oflag &= ~(.OPOST); + raw_tio_mode.c_lflag &= ~(.ECHO | .ECHONL | .ICANON | .ISIG | .IEXTEN); + raw_tio_mode.c_cflag &= ~(.CSIZE | .PARENB); + raw_tio_mode.c_cflag |= .CS8; + raw_tio_mode.c_cc[Control_Chars.VMIN] = 0; + raw_tio_mode.c_cc[Control_Chars.VTIME] = 1; + tcsetattr(STDIN_FILENO, 0, *raw_tio_mode); // TODO Log on error. } OS_reset_terminal :: () { - tcsetattr(STDIN_FILENO, 0, *initial_tio_mode); + tcsetattr(STDIN_FILENO, 0, *initial_tio_mode); // TODO Log on error. } OS_get_terminal_size :: () -> rows: int, columns: int { auto_release_temp(); - input := talloc_string(64); + flush_input(); + + // input := talloc_string(64); write_string(Commands.QueryWindowSizeInChars); - input.count = OS_read_input(input.data, input.count); + // input.count = OS_read_input(input.data, input.count); + sleep_milliseconds(1); //TODO WHYYYY??? GOD DAMIT THREADS... + input := get_str(); + // input[0] = #char "x"; + // print(">%<", xx input); + // print("#<#"); // Expected message format: [8;<r>;<c>t // where <r> is the number of rows and <c> of columns. @@ -182,6 +165,7 @@ OS_get_terminal_size :: () -> rows: int, columns: int { input[0] == #char "\e" && input[1] == #char "[" && input[2] == #char "8", + //input[input.count-1] == #char "t", "Query windows size in chars returned invalid response."); parts := split(input, ";"); @@ -190,17 +174,17 @@ OS_get_terminal_size :: () -> rows: int, columns: int { return rows, columns; } -OS_set_input_mode :: (mode: Input_Mode) { - tio_mode: *Terminal_IO_Mode = ---; - if mode == { - case .HUMAN; - tio_mode = *human_tio_mode; - case; - tio_mode = *default_tio_mode; - } - tcsetattr(STDIN_FILENO, 0, tio_mode); - // TODO get_error_value_and_string :: () -> (error_code: OS_Error_Code, description: string) -} +// OS_set_input_mode :: (mode: Input_Mode) { + // tio_mode: *Terminal_IO_Mode = ---; + // if mode == { + // case .HUMAN; + // tio_mode = *human_tio_mode; + // case; + // tio_mode = *cooked_tio_mode; + // } + // tcsetattr(STDIN_FILENO, 0, tio_mode); + // // TODO get_error_value_and_string :: () -> (error_code: OS_Error_Code, description: string) +// } OS_read_input :: (buffer: *u8, bytes_to_read: s64) -> bytes_read: s64, error: bool = false, error_message: string = "" { bytes_read := read(STDIN_FILENO, buffer, xx bytes_to_read); @@ -1181,50 +1181,125 @@ read_enter_confirmation :: inline (row: int, style: int, message: string) -> boo main :: () { - // -- -- -- TODO WIP Testing TUI -- START - TUI.start(); - TUI.clear_terminal(); - rows, columns := TUI.get_terminal_size(); - TUI.draw_box(1, 1, columns, rows); - TUI.set_cursor_position(4, 4); - c_row, c_column := TUI.get_cursor_position(); - TUI.set_cursor_position(3, 3); - input := TUI.read_input(); + #if 0 { + print("test 0\n"); + TUI.test(); + return; + } - // sleep_milliseconds(5000); - TUI.stop(); - print("- - -\n"); - print("window r:c = %:%\n", rows, columns); - print("cursor r:c = %:%\n", c_row, c_column); - print("input = %\n", input); - return; + #if 0 { + print("test 1\n"); + TUI.start(); + buffer: [8] u8; + brss, error, msg := TUI.OS_read_input(buffer.data, buffer.count); + TUI.stop(); + if error == true print("error:%", msg); + print("br:%", brss); + print("input:%", cast(string)buffer); + TUI.stop(); + return; + } + #if 0 { + print("test 2\n"); + key: TUI.Key = #char "d"; + while(key != #char "q") { + // key = TUI.get_key(10); + buffer: [8] u8; + buffer[0] = 0; + brss := TUI.OS_read_input(buffer.data, 1); + if brss > 0 { + key = buffer[0]; + print(">%<", xx key); + } + else { + print(":"); + } + sleep_milliseconds(10); + } + TUI.stop(); + return; + } - str: string; + #if 1 { + print("test 3\n"); + TUI.start(); + key: TUI.Key = #char "d"; + while(key != #char "q") { + __mark := get_temporary_storage_mark(); + key = TUI.get_key(3000); + // sleep_milliseconds(10); + + if key != xx TUI.Keys.None print_character(key); + else write_string("-"); + set_temporary_storage_mark(__mark); + } + TUI.stop(); + return; + } + + // TUI.start_new_mode(); + // sleep_milliseconds(3000); + xrows, xcolumns := TUI.get_terminal_size(); + TUI.draw_box(1, 1, xcolumns, xrows); + // print("<beep>"); + bbb: [64] u8; + + br, err, err_msg := TUI.OS_read_input(bbb.data, 5); + print(">%/%/%/%\n", cast(string)bbb, br, err, err_msg); + sleep_milliseconds(3000); + // coisa := TUI.get_str(); + // print("\n>%<\n", coisa); + print("stopping\n"); + // TUI.stop_new_mode(); + TUI.stop(); + return; - write_string("\e(0"); // Enter Line drawing mode - write_string("\e[104;93m"); // bright yellow on bright blue - write_string("x"); // in line drawing mode, \x78 -> \u2502 "Vertical Bar" - write_string("\e[10m"); // restore color - write_string("\e(B"); // exit line drawing mode - sleep_milliseconds(1000); + // -- -- -- TODO WIP Testing TUI -- START + // TUI.start(); + // TUI.clear_terminal(); + // rows, columns := TUI.get_terminal_size(); + // TUI.draw_box(1, 1, columns, rows); + // TUI.set_cursor_position(4, 4); + // c_row, c_column := TUI.get_cursor_position(); + // TUI.set_cursor_position(3, 3); + // input := TUI.read_input(); - // str = "\e[sWOW\e[u\e[1P"; - str = "\e[sWOW"; - // write(STDIN_FILENO, str.data, xx str.count); - write_string(str); - sleep_milliseconds(1000); - - str = "\e[?25l"; - // write(STDIN_FILENO, str.data, xx str.count); - write_string(str); - sleep_milliseconds(1000); - - str = "\e[?25h"; - // write(STDIN_FILENO, str.data, xx str.count); - write_string(str); - return; + // sleep_milliseconds(5000); + // TUI.stop(); + // print("- - -\n"); + // print("window r:c = %:%\n", rows, columns); + // print("cursor r:c = %:%\n", c_row, c_column); + // print("input = %\n", input); + // return; +// +// + // str: string; +// + // write_string("\e(0"); // Enter Line drawing mode + // write_string("\e[104;93m"); // bright yellow on bright blue + // write_string("x"); // in line drawing mode, \x78 -> \u2502 "Vertical Bar" + // write_string("\e[10m"); // restore color + // write_string("\e(B"); // exit line drawing mode + // sleep_milliseconds(1000); + + + // // str = "\e[sWOW\e[u\e[1P"; + // str = "\e[sWOW"; + // // write(STDIN_FILENO, str.data, xx str.count); + // write_string(str); + // sleep_milliseconds(1000); + // + // str = "\e[?25l"; + // // write(STDIN_FILENO, str.data, xx str.count); + // write_string(str); + // sleep_milliseconds(1000); + // + // str = "\e[?25h"; + // // write(STDIN_FILENO, str.data, xx str.count); + // write_string(str); + // return; // -- -- -- TODO WIP Testing TUI -- STOP |
