diff options
Diffstat (limited to 'terminal.c')
-rw-r--r-- | terminal.c | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/terminal.c b/terminal.c new file mode 100644 index 0000000..c24f46d --- /dev/null +++ b/terminal.c @@ -0,0 +1,84 @@ +#include "terminal.h" + +#include <stdio.h> +#include <stdlib.h> +#include <sys/ioctl.h> +#include <termios.h> +#include <unistd.h> + +static struct termios original_termios; + +void die(const char* message) +{ + /* Clear the screen */ + write(STDOUT_FILENO, "\x1b[2J", 4); + write(STDOUT_FILENO, "\x1b[H", 3); + + perror(message); + exit(1); +} + +void disable_raw_mode() +{ + if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &original_termios) == -1) + die("tcsetattr"); +} + +/* Disables any input and output processing from the terminal */ +void enable_raw_mode() +{ + if (tcgetattr(STDIN_FILENO, &original_termios) == -1) + die("tcgetattr"); + + atexit(disable_raw_mode); + + struct termios raw = original_termios; + raw.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON); + raw.c_oflag &= ~(OPOST); + raw.c_cflag |= (CS8); + raw.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG); + + raw.c_cc[VMIN] = 0; + raw.c_cc[VTIME] = 1; + + if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw) == -1) + die("tcsetattr"); +} + +int get_cursor_position(int* rows, int* cols) +{ + char buffer[32]; + unsigned int i = 0; + + if (write(STDOUT_FILENO, "\x1b[6n", 4) != 4) + return -1; + + while (i < sizeof(buffer) - 1) { + if (read(STDIN_FILENO, &buffer[i], 1) != 1) break; + if (buffer[i] == 'R') break; + i++; + } + buffer[i] = '\0'; + + printf("\r\n&buffer[1]: '%s'\r\n", &buffer[1]); + + if (buffer[0] != '\x1b' || buffer[1] != '[') return -1; + if (sscanf(&buffer[2], "%d;%d", rows, cols) != 2) return -1; + + return 0; +} + +int get_window_size(int* rows, int* cols) +{ + struct winsize size; + + if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &size) == -1 || size.ws_col == 0) { + if (write(STDOUT_FILENO, "\x1b[999C\x1b[999B", 12) != 12) + return -1; + return get_cursor_position(rows, cols); + } else { + *cols = size.ws_col; + *rows = size.ws_row; + return 0; + } +} |