summaryrefslogtreecommitdiff
path: root/terminal.c
diff options
context:
space:
mode:
Diffstat (limited to 'terminal.c')
-rw-r--r--terminal.c84
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;
+ }
+}