aboutsummaryrefslogtreecommitdiff
path: root/TUI/unix.jai
diff options
context:
space:
mode:
Diffstat (limited to 'TUI/unix.jai')
-rw-r--r--TUI/unix.jai274
1 files changed, 129 insertions, 145 deletions
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);