aboutsummaryrefslogtreecommitdiff
path: root/tui.c
diff options
context:
space:
mode:
authorNPScript <nathan@reinerweb.ch>2021-12-20 18:19:17 +0100
committerNPScript <nathan@reinerweb.ch>2021-12-20 18:19:17 +0100
commit25b3356b926e71d25fddef998021e66d7c1a7557 (patch)
tree7e5dc325907a4802d74233998db6cde6605d4b0a /tui.c
init commit
Diffstat (limited to 'tui.c')
-rw-r--r--tui.c207
1 files changed, 207 insertions, 0 deletions
diff --git a/tui.c b/tui.c
new file mode 100644
index 0000000..37bb4c6
--- /dev/null
+++ b/tui.c
@@ -0,0 +1,207 @@
+#include <stdio.h>
+#include <stdarg.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+#include <termios.h>
+
+#include "tui.h"
+
+struct termios term;
+
+unsigned get_term_width() {
+ struct winsize w;
+ ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
+
+ return w.ws_col;
+}
+
+unsigned get_term_height() {
+ struct winsize w;
+ ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
+
+ return w.ws_row;
+}
+
+unsigned get_cursor_x_position() {
+ printf("\033[6n");
+ char buf[32];
+ unsigned n;
+ unsigned m;
+ unsigned x;
+
+ for (char * c = buf; c < buf + 32; ++c) {
+ *c = getch();
+
+ if (*c == 'R') {
+ m = c - buf;
+ break;
+ } else if (*c == ';') {
+ n = c - buf;
+ }
+ }
+
+ x = 0;
+
+ for (int i = m - 1; i > n; --i) {
+ int p = 1;
+
+ for (int j = 0; j < m - 1 - i; ++j)
+ p *= 10;
+
+ x += ((int)buf[i] - 48) * p;
+ }
+
+ return x;
+}
+
+unsigned get_cursor_y_position() {
+ printf("\033[6n");
+ char buf[32];
+ unsigned n;
+ unsigned y;
+ unsigned was_echo = is_echo();
+
+ showecho(0);
+
+ for (char * c = buf; c < buf + 32; ++c) {
+ *c = getch();
+
+ if (*c == 'R') {
+ break;
+ } else if (*c == ';') {
+ n = c - buf;
+ }
+ }
+
+ showecho(was_echo);
+
+ y = 0;
+
+ for (int i = n - 1; i > 1; --i) {
+ int p = 1;
+
+ for (int j = 0; j < n - 1 - i; ++j)
+ p *= 10;
+
+ y += ((int)buf[i] - 48) * p;
+ }
+
+ return y;
+}
+
+void inittui() {
+ printf("\033[?1049h");
+ tcgetattr(fileno(stdin), &term);
+}
+
+void endtui() {
+ printf("\033[?1049l");
+}
+
+char getch() {
+ char c;
+ term.c_lflag &= ~ICANON;
+
+ tcsetattr(fileno(stdin), TCSANOW, &term);
+ c = getc(stdin);
+
+ term.c_lflag |= ICANON;
+ tcsetattr(fileno(stdin), TCSANOW, &term);
+ return c;
+}
+
+void showecho(int echo) {
+ if (!echo)
+ term.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
+ else
+ term.c_lflag |= ECHO | ECHOE | ECHOK | ECHONL;
+ tcsetattr(fileno(stdin), TCSANOW, &term);
+}
+
+int is_echo() {
+ return term.c_iflag & ECHO;
+}
+
+void showcursor(int show) {
+ printf("\033[?25%c", show ? 'h' : 'l');
+}
+
+void printfxy(unsigned x, unsigned y, const char * fmt, ...) {
+ va_list list;
+
+ printf("\033[%d;%dH", y, x);
+
+ va_start(list, fmt);
+ vprintf(fmt, list);
+ va_end(list);
+}
+
+void draw_window(Window * win) {
+ for (int i = 0; i < win->height; ++i)
+ printfxy(win->x, win->y + i, "%*s", win->width, "");
+
+ if (win->has_borders) {
+ printfxy(win->x, win->y, "%s", TLCORNER);
+ for (int i = 1; i < win->width - 1; ++i)
+ printfxy(win->x + i, win->y, "%s", HLINE);
+ printfxy(win->x + win->width - 1, win->y, "%s", TRCORNER);
+
+ printfxy(win->x, win->y + win->height - 1, "%s", BLCORNER);
+ for (int i = 1; i < win->width - 1; ++i)
+ printfxy(win->x + i, win->y + win->height - 1, "%s", HLINE);
+ printfxy(win->x + win->width - 1, win->y + win->height - 1, "%s", BRCORNER);
+
+ for (int i = 1; i < win->height - 1; ++i)
+ printfxy(win->x, win->y + i, "%s", VLINE);
+
+ for (int i = 1; i < win->height - 1; ++i)
+ printfxy(win->x + win->width - 1, win->y + i, "%s", VLINE);
+ }
+
+ fflush(stdout);
+}
+
+void printfxy_to_window(Window * win, int x, int y, const char * fmt, ...) {
+ va_list list;
+ char buf[BUFSIZ];
+ int cx;
+ int cy;
+ int tabstop = 0;
+
+ va_start(list, fmt);
+ vsprintf(buf, fmt, list);
+ va_end(list);
+
+ cx = x + win->x + win->has_borders;
+ cy = y + win->y + win->has_borders;
+
+ if (cy >= (int)(win->y + win->height - win->has_borders))
+ return;
+
+ printf("\033[%d;%dH", cy, cx);
+
+ for (char * c = buf; *c;) {
+ if (*c == '\t') {
+ tabstop = 3;
+ *c = ' ';
+ }
+
+ if (*c == '\n' || cx == win->x + win->width - win->has_borders) {
+ if (++cy >= (int)(win->y + win->height - win->has_borders))
+ break;
+ cx = win->x + win->has_borders;
+ printf("\033[%d;%dH", cy, cx);
+ }
+
+ if (*c != '\n') {
+ if (cy >= (int)(win->y + win->has_borders))
+ putc(*c, stdout);
+ ++cx;
+ }
+
+ if (tabstop)
+ --tabstop;
+ else
+ ++c;
+ }
+}