From d02d46d27982a8e351736067ab9787f87052b989 Mon Sep 17 00:00:00 2001 From: HampusM Date: Wed, 29 Jun 2022 20:17:23 +0200 Subject: refactor: add termios abstraction --- src/engine/io/terminal.cpp | 54 +++++++++++++++++++ src/engine/io/terminal.hpp | 130 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 184 insertions(+) create mode 100644 src/engine/io/terminal.cpp create mode 100644 src/engine/io/terminal.hpp (limited to 'src/engine/io') diff --git a/src/engine/io/terminal.cpp b/src/engine/io/terminal.cpp new file mode 100644 index 0000000..e6d7d3a --- /dev/null +++ b/src/engine/io/terminal.cpp @@ -0,0 +1,54 @@ +#include "terminal.hpp" + +TerminalState::TerminalState(termios term_attrs) noexcept : _term_attrs(term_attrs) {} + +void TerminalState::set_input_mode_flag(TerminalInputModeFlag flag, bool is_on) noexcept +{ + auto flag_num = static_cast(flag); + + _term_attrs.c_iflag &= is_on ? flag_num : ~flag_num; +} + +void TerminalState::set_output_mode_flag(TerminalOutputModeFlag flag, bool is_on) noexcept +{ + auto flag_num = static_cast(flag); + + _term_attrs.c_oflag &= is_on ? flag_num : ~flag_num; +} + +void TerminalState::set_control_mode_flag( + TerminalControlModeFlag flag, + bool is_on) noexcept +{ + auto flag_num = static_cast(flag); + + _term_attrs.c_cflag &= is_on ? flag_num : ~flag_num; +} + +void TerminalState::set_local_mode_flag(TerminalLocalModeFlag flag, bool is_on) noexcept +{ + auto flag_num = static_cast(flag); + + _term_attrs.c_lflag &= is_on ? flag_num : ~flag_num; +} + +auto TerminalState::get_attributes() noexcept -> termios +{ + return _term_attrs; +} + +auto get_terminal_state(int term_fd) noexcept -> TerminalState +{ + termios term_attrs{}; + + tcgetattr(term_fd, &term_attrs); + + return TerminalState(term_attrs); +} + +void set_terminal_state(int term_fd, TerminalState state) noexcept +{ + auto state_attrs = state.get_attributes(); + + tcsetattr(term_fd, TCSAFLUSH, &state_attrs); +} diff --git a/src/engine/io/terminal.hpp b/src/engine/io/terminal.hpp new file mode 100644 index 0000000..27455bb --- /dev/null +++ b/src/engine/io/terminal.hpp @@ -0,0 +1,130 @@ +#pragma once + +#include + +enum class TerminalControlModeFlag +{ + csize = 0000060, + cs5 = 0000000, + cs6 = 0000020, + cs7 = 0000040, + cs8 = 0000060, + cstopb = 0000100, + cread = 0000200, + parenb = 0000400, + parodd = 0001000, + hupcl = 0002000, + clocal = 0004000, +}; + +enum class TerminalInputModeFlag +{ + 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 = 8,th 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, // Map uppercase characters to lowercase on input (not in POSIX) + ixon = 0002000, // Enable start/stop output control + ixany = 0004000, // Enable any character to restart output + 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) +}; + +enum class TerminalOutputModeFlag +{ + opost = 0000001, // Post-process output + 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 on output + onocr = 0000020, // No CR output at column = 0 + onlret = 0000040, // NL performs CR function + ofill = 0000100, // Use fill characters for delay + ofdel = 0000200, // Fill is DEL + nldly = 0000400, // Select newline delays: + nl0 = 0000000, // Newline type = 0 + nl1 = 0000400, // Newline type = 1 + crdly = 0003000, // Select carriage-return delays: + cr0 = 0000000, // Carriage-return delay type = 0 + cr1 = 0001000, // Carriage-return delay type = 1 + cr2 = 0002000, // Carriage-return delay type = 2 + cr3 = 0003000, // Carriage-return delay type = 3 + tabdly = 0014000, // Select horizontal-tab delays: + tab0 = 0000000, // Horizontal-tab delay type = 0 + tab1 = 0004000, // Horizontal-tab delay type = 1 + tab2 = 0010000, // Horizontal-tab delay type = 2 + tab3 = 0014000, // Expand tabs to spaces + bsdly = 0020000, // Select backspace delays: + bs0 = 0000000, // Backspace-delay type = 0 + bs1 = 0020000, // Backspace-delay type = 1 + ffdly = 0100000, // Select form-feed delays: + ff0 = 0000000, // Form-feed delay type = 0 + ff1 = 0100000, // Form-feed delay type = 1 + vtdly = 0040000, // Select vertical-tab delays: + vt0 = 0000000, // Vertical-tab delay type = 0 + vt1 = 0040000, // Vertical-tab delay type = 1 + xtabs = 0014000, +}; + +enum class TerminalLocalModeFlag +{ + isig = 0000001, // When any of the characters INTR, QUIT, SUSP, or DSUSP are received, + // generate the corresponding signal + icanon = 0000002, // Canonical input + xcase = 0000004, + echo = 0000010, // Echo input characters + echoe = 0000020, // Echo erase character as error-correcting backspace + echok = 0000040, // Echo KILL + echonl = 0000100, // Echo NL + noflsh = 0000200, // Disable flush after interrupt or quit + tostop = 0000400, // Send SIGTTOU for background output + echoctl = 0001000, /* If ECHO is also set, terminal special characters + other than TAB, NL, START, and STOP are echoed as + ^X, where X is the character with ASCII code = 0,x40 + greater than the special character + (not in POSIX) */ + echoprt = 0002000, /* If ICANON and ECHO are also set, characters are + printed as they are being erased + (not in POSIX) */ + echoke = 0004000, /* If ICANON is also set, KILL is echoed by erasing + each character on the line, as specified by ECHOE + and ECHOPRT (not in POSIX) */ + flusho = 0010000, /* Output is being flushed This flag is toggled by + typing the DISCARD character (not in POSIX) */ + pendin = 0040000, /* All characters in the input queue are reprinted + when the next character is read + (not in POSIX) */ + iexten = 0100000, // Enable implementation-defined input processing + extproc = 0200000, +}; + +class TerminalState +{ +public: + TerminalState() = default; + + explicit TerminalState(termios term_attrs) noexcept; + + void set_input_mode_flag(TerminalInputModeFlag flag, bool is_on) noexcept; + + void set_output_mode_flag(TerminalOutputModeFlag flag, bool is_on) noexcept; + + void set_control_mode_flag(TerminalControlModeFlag flag, bool is_on) noexcept; + + void set_local_mode_flag(TerminalLocalModeFlag flag, bool is_on) noexcept; + + auto get_attributes() noexcept -> termios; + +private: + termios _term_attrs; +}; + +auto get_terminal_state(int term_fd) noexcept -> TerminalState; + +void set_terminal_state(int term_fd, TerminalState state) noexcept; + -- cgit v1.2.3-18-g5258