aboutsummaryrefslogtreecommitdiff
path: root/TUI/module.jai
diff options
context:
space:
mode:
authordam <dam@gudinoff>2023-09-28 00:51:40 +0100
committerdam <dam@gudinoff>2023-09-28 00:51:40 +0100
commit32621b9b18a285dfd5e9e225073809bc49b14f39 (patch)
treed033b328603df8c51bcee91cf2ce2ebd0959f4cb /TUI/module.jai
parentaa4550e5871ca3e21942f2f612666fd41f90eadb (diff)
downloadtask-time-tracker-32621b9b18a285dfd5e9e225073809bc49b14f39.tar.zst
task-time-tracker-32621b9b18a285dfd5e9e225073809bc49b14f39.zip
Working read_input prototype.
Diffstat (limited to 'TUI/module.jai')
-rw-r--r--TUI/module.jai170
1 files changed, 49 insertions, 121 deletions
diff --git a/TUI/module.jai b/TUI/module.jai
index 3298e59..ec319d7 100644
--- a/TUI/module.jai
+++ b/TUI/module.jai
@@ -9,13 +9,6 @@
#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";
@@ -86,16 +79,20 @@ Commands :: struct {
}
-// TODO Maybe rename to "setup()"
+
+initialized := false;
+
+
start :: () {
+ if initialized return;
write_strings(Commands.HideCursor, Commands.SaveCursorPosition, Commands.EnterAlternateBuffer, Commands.SetUTF8);
OS_prepare_terminal();
- isTUIActive = true;
+ initialized = true;
}
-// TODO Maybe rename to "reset()"
stop :: () {
- isTUIActive = false;
+ if initialized == false return;
+ initialized = false;
OS_reset_terminal();
write_strings(Commands.EnterMainBuffer, Commands.RestoreCursorPosition, Commands.ShowCursor);
}
@@ -146,19 +143,17 @@ draw_box :: (x: int, y: int, width: int, height: int) {
// TODO Maybe rename to "clear()"
clear_terminal :: inline () {
+ assert(initialized, "TUI is not ready.");
write_string(Commands.ClearScreen);
}
// TODO Maybe rename to "get_size()"
get_terminal_size :: () -> rows: int, columns: int {
+ assert(initialized, "TUI is not ready.");
rows, columns := OS_get_terminal_size();
return rows, columns;
}
-// read_input: () -> string {
- // return OS_read_input();
-// }
-
set_cursor_position :: (row: int, column: int) {
auto_release_temp();
tmp_string := tprint(Commands.SetCursorPosition, row, column);
@@ -166,21 +161,24 @@ set_cursor_position :: (row: int, column: int) {
}
get_cursor_position :: () -> row: int, column: int {
- assert(isTUIActive, "TUI is not active."); // TODO
+ assert(initialized, "TUI is not ready."); // TODO Should I use this inside each and every procedure?
+
+ auto_release_temp();
+
+ write_string(Commands.QueryCursorPosition);
- // TODO Hide input echo.
+ input := talloc_string(64);
+ input.count = OS_read_input(input.data, input.count); // TODO Does not check for read errors.
- write_string(Commands.QueryCursorPosition); // Returned
- input := read_input(.MACHINE);
- // Result: \e[21;1R
+ // Expected message format: \e[<r>;<c>R
+ // where <r> is the number of rows and <c> of columns.
assert(
- input.data[0] == #char "\e" &&
- input.data[1] == #char "[" &&
- input.data[input.count-1] == #char "R",
+ input[0] == #char "\e" &&
+ input[1] == #char "[" &&
+ input[input.count-1] == #char "R",
"Query cursor position returned invalid response.");
- input.data += 2;
- print(">%<\n", input);
+ advance(*input, 2);
parts := split(input, ";");
row := parse_int(*parts[0]);
column := parse_int(*parts[1]);
@@ -192,12 +190,33 @@ Input_Mode :: enum u8 {
MACHINE; // Hides cursor, hides input, and reads right away once the first input is available.
}
-read_input :: (mode: Input_Mode = .HUMAN) -> string {
- if mode == .HUMAN write_string(Commands.ShowCursor);
- defer if mode == .HUMAN write_string(Commands.HideCursor);
- return OS_read_input(mode);
-}
+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 {
@@ -205,95 +224,4 @@ read_input :: (mode: Input_Mode = .HUMAN) -> string {
}
else #if OS == .LINUX || OS == .MACOS {
// Prototyping zone... keep clear!
- OS_read_input :: (mode: Input_Mode) -> string {
-
- term : My_Termios;
- tcgetattr(STDIN_FILENO, *term);
-
- // Input modes.
- 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.
- __NOT_USED__;
- IMAXBEL; // Ring bell when input queue is full.
- IUCLC; // Translate upper case input to lower case.
- }
-
- // Local modes.
- 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.
- TOSTOP; // Send SIGTTOU for background output.
- FLUSHO; // Output being flushed (state).
- XCASE; // Canonical upper/lower case.
- NOKERNINFO; // Disable VSTATUS.
- PENDIN; // Retype pending input (state).
- NOFLSH; // Disable flush after interrupt.
-
- }
-
- backup: My_Termios;
- tcgetattr(STDIN_FILENO, *backup);
-
- if mode == {
- case .HUMAN;
- term.c_iflag |= xx cast(Input_Modes)(.IXOFF | .ICRNL);
- term.c_lflag |= xx cast(Local_Modes)(.NOKERNINFO | .ECHO | .ECHOE | .ECHOKE);
-
- case .MACHINE;
- iflags: Input_Modes = (.IGNBRK | .BRKINT | .PARMRK | .ISTRIP | .INLCR | .IGNCR | .ICRNL | .IXON);
- term.c_iflag &= xx ~(iflags);
- lflags: Local_Modes = (.ECHO | .ECHONL | .ICANON | .IEXTEN);
- term.c_lflag &= xx ~lflags;
- }
-
- // term.c_iflag &= 0xFFFFFA14;// ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
- // term.c_oflag &= 0xFFFFFFFE;// ~OPOST;
- // term.c_lflag &= 0xFFFF7FB4;// ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
- // term.c_cflag &= 0xFFFFFECF;// ~(CSIZE | PARENB);
- // term.c_cflag |= 0x00000030;
-
- tcsetattr(STDIN_FILENO, 0, *term);
-
- result: string = ---;
- buffer: [8192] u8;
- write_string(Commands.ShowCursor);
- bytes_read := read(STDIN_FILENO, buffer.data, buffer.count-1);
- write_string(Commands.HideCursor);
-
- // TODO WIP WIP WIP
- result.data = alloc(bytes_read, temp);
- memcpy(result.data, buffer.data, bytes_read);
- result.count = bytes_read;
- // result = "jat";
- // result.count = bytes_read;
- // result.data = buffer.data;
- // result = copy_temporary_string(buffer);
- // result = tprint("%", xx buffer.data);
- // result = to_string(buffer.data, bytes_read); // TODO WIP WIP WIP This is still using the stack allocated buffer and WILL FAIL!
-
- tcsetattr(STDIN_FILENO, 0, *backup);
-
- return result;
- };
}