diff --git a/tte b/tte index 321ab58..25a8c6b 100755 Binary files a/tte and b/tte differ diff --git a/tte.c b/tte.c index f8e622c..868574c 100644 --- a/tte.c +++ b/tte.c @@ -1,7 +1,87 @@ +/*** Include section ***/ + +#include +#include +#include +#include +#include #include +/*** Data section ***/ + +struct termios orig_termios; + +/*** Terminal section ***/ + +void die(const char* s) { + // perror looks for global errno variable and then prints + // a descriptive error mesage for it. + perror(s); + exit(1); +} + +void disableRawMode() { + if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &orig_termios) == -1) + die("Failed to disable raw mode"); +} + +void enableRawMode() { + // Save original terminal state into orig_termios. + if (tcgetattr(STDIN_FILENO, &orig_termios) == -1) + die("Failed to get current terminal state"); + // At exit, restore the original state. + atexit(disableRawMode); + + // Modify the original state to enter in raw mode. + struct termios raw = orig_termios; + // This disables Ctrl-M, Ctrl-S and Ctrl-Q commands. + // (BRKINT, INPCK and ISTRIP are not estrictly mandatory, + // but it is recommended to turn them off in case any + // system needs it). + raw.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON); + // Turning off all output processing (\r\n). + raw.c_oflag &= ~(OPOST); + // Setting character size to 8 bits per byte (it should be + // like that on most systems, but whatever). + raw.c_cflag |= (CS8); + // Using NOT operator on ECHO | ICANON | IEXTEN | ISIG and + // then bitwise-AND them with flags field in order to + // force c_lflag 4th bit to become 0. This disables + // chars being printed (ECHO) and let us turn off + // canonical mode in order to read input byte-by-byte + // instead of line-by-line (ICANON), ISIG disables + // Ctrl-C command and IEXTEN the Ctrl-V one. + raw.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG); + // read() function now returns as soon as there is any + // input to be read. + raw.c_cc[VMIN] = 0; + // Forcing read() function to return every 1/10 of a + // second if there is nothing to read. + raw.c_cc[VTIME] = 1; + + if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw) == -1) + die("Failed to set raw mode"); +} + +/*** Init section ***/ + int main() { - char c; - while (read(STDIN_FILENO, &c, 1) == 1); + enableRawMode(); + + while (1) { + char c = '\0'; + // Ignoring EAGAIN to make it work on Cygwin. + if (read(STDIN_FILENO, &c, 1) == -1 && errno != EAGAIN) + die("Error reading input"); + + if (isprint(c)) + printf("%d ('%c')\r\n", c, c); + else + printf("%d\n\r", c); + + if (c == 'q') + break; + } + return 0; } \ No newline at end of file