diff options
Diffstat (limited to 'TUI/unix.jai')
| -rw-r--r-- | TUI/unix.jai | 136 |
1 files changed, 99 insertions, 37 deletions
diff --git a/TUI/unix.jai b/TUI/unix.jai index 6bcf13a..20d1a2a 100644 --- a/TUI/unix.jai +++ b/TUI/unix.jai @@ -14,93 +14,158 @@ // 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. - __NOT_USED__; + + _1000_; IMAXBEL; // Ring bell when input queue is full. IUCLC; // Translate upper case input to lower case. + _8000_; + } + + // 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_; } + // 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. + } + + 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. - } - + Terminal_IO_Mode :: struct { - c_iflag : u32; // Input mode flags. - c_oflag : u32; // Output mode flags. - c_cflag : u32; // Control modes flags. - c_lflag : u32; // Local modes flags. - c_line : u8; // Line discipline. - c_cc : [32]u8; // Control characters. + 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). } - initial_tio_mode : Terminal_IO_Mode; + initial_tio_mode: Terminal_IO_Mode; default_tio_mode: Terminal_IO_Mode; - blocking_tio_mode: Terminal_IO_Mode; - unblocking_tio_mode: Terminal_IO_Mode; + human_tio_mode: Terminal_IO_Mode; #scope_export OS_prepare_terminal :: () { - // TODO Required to do unlocking input. tcgetattr(STDIN_FILENO, *initial_tio_mode); - default_tio_mode := initial_tio_mode; - default_tio_mode.c_iflag &= 0xFFFFFA14;// ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON); - default_tio_mode.c_oflag &= 0xFFFFFFFE;// ~OPOST; - default_tio_mode.c_lflag &= 0xFFFF7FB4;// ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); - default_tio_mode.c_cflag &= 0xFFFFFECF;// ~(CSIZE | PARENB); - default_tio_mode.c_cflag |= 0x00000030; // TODO WHAT IS THIS? + 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); - blocking_tio_mode = default_tio_mode; - blocking_tio_mode.c_iflag |= xx cast(Input_Modes)(.IXOFF | .ICRNL); - blocking_tio_mode.c_lflag |= xx cast(Local_Modes)(.NOKERNINFO | .ECHO | .ECHOE | .ECHOKE); - - unblocking_tio_mode = default_tio_mode; - iflags: Input_Modes = (.IGNBRK | .BRKINT | .PARMRK | .ISTRIP | .INLCR | .IGNCR | .ICRNL | .IXON); - unblocking_tio_mode.c_iflag &= xx ~(iflags); - lflags: Local_Modes = (.ECHO | .ECHONL | .ICANON | .IEXTEN); - unblocking_tio_mode.c_lflag &= xx ~lflags; + 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); } OS_reset_terminal :: () { - tcsetattr(STDIN_FILENO, 0, *initial_tio_mode); // return echo + tcsetattr(STDIN_FILENO, 0, *initial_tio_mode); } OS_get_terminal_size :: () -> rows: int, columns: int { @@ -125,19 +190,16 @@ OS_get_terminal_size :: () -> rows: int, columns: int { return rows, columns; } -// TODO Maybe we should use a NON-BLOCKING state by default... and only change to blocking when performing a HUMAN read...? - OS_set_input_mode :: (mode: Input_Mode) { + tio_mode: *Terminal_IO_Mode = ---; if mode == { case .HUMAN; - tcsetattr(STDIN_FILENO, 0, *blocking_tio_mode); - // TODO get_error_value_and_string :: () -> (error_code: OS_Error_Code, description: string) - case .MACHINE; - tcsetattr(STDIN_FILENO, 0, *unblocking_tio_mode); - // TODO get_error_value_and_string :: () -> (error_code: OS_Error_Code, description: string) + tio_mode = *human_tio_mode; case; - // TODO ERROR + 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_read_input :: (buffer: *u8, bytes_to_read: s64) -> bytes_read: s64, error: bool = false, error_message: string = "" { |
