#include "terminal.h" #include #include #include #include #include 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; } }