diff options
Diffstat (limited to 'TUI/unix.jai')
| -rw-r--r-- | TUI/unix.jai | 274 |
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); |
