diff options
| author | NPScript <nathan@reinerweb.ch> | 2021-12-20 18:19:17 +0100 |
|---|---|---|
| committer | NPScript <nathan@reinerweb.ch> | 2021-12-20 18:19:17 +0100 |
| commit | 25b3356b926e71d25fddef998021e66d7c1a7557 (patch) | |
| tree | 7e5dc325907a4802d74233998db6cde6605d4b0a /tui.c | |
init commit
Diffstat (limited to 'tui.c')
| -rw-r--r-- | tui.c | 207 |
1 files changed, 207 insertions, 0 deletions
@@ -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; + } +} |