From 9f905622a2678d65056d0a525934cae8b54ede6b Mon Sep 17 00:00:00 2001 From: javalsai Date: Fri, 4 Jul 2025 01:41:56 +0200 Subject: [PATCH] chore: dry and modularize a bit --- include/util.h | 3 +++ src/ui.c | 69 +++++++++++++++++--------------------------------- src/util.c | 13 ++++++++++ 3 files changed, 39 insertions(+), 46 deletions(-) diff --git a/include/util.h b/include/util.h index 126533c..9dce5fd 100644 --- a/include/util.h +++ b/include/util.h @@ -1,6 +1,7 @@ #ifndef UTILH_ #define UTILH_ +#include #include #include #include @@ -12,6 +13,8 @@ int find_keyname(enum keys* at, const char* name); enum keys find_ansi(const char* seq); void read_press(u_char* length, char* out); +// non blocking, waits up to tv, returns true if actually read +bool read_press_nb(u_char* length, char* out, struct timeval* tv); bool utf8_iscont(char byte); size_t utf8len(const char* str); diff --git a/src/ui.c b/src/ui.c index e3bb949..0d6a271 100644 --- a/src/ui.c +++ b/src/ui.c @@ -46,7 +46,7 @@ static void print_session(struct uint_point origin, struct session session, static void print_user(struct uint_point origin, struct user user, bool multiple); static void print_passwd(struct uint_point origin, uint length, bool err); -static void print_ui(); +static void scratch_print_ui(); // ansi resource: https://gist.github.com/fnky/458719343aabd01cfb17a3a4f7296797 static struct termios orig_term; @@ -58,38 +58,12 @@ struct config* g_config = NULL; static volatile sig_atomic_t need_resize = 0; -static void process_sigwinch(int) { +static void process_sigwinch(int signal) { need_resize = 1; } -void resize_ui() { - ioctl(STDOUT_FILENO, TIOCGWINSZ, &window); - - if (window.ws_row < BOX_HEIGHT + INNER_BOX_OUT_MARGIN * 2 || - window.ws_col < BOX_WIDTH + INNER_BOX_OUT_MARGIN * 2) { - printf("\033[2J\033[H"); // Clear screen - printf("\x1b[1;31mScreen too small\x1b[0m\n"); - printf("\x1b[%s;%sm\x1b[2J", g_config->colors.bg, g_config->colors.fg); - return; - } - - printf("\033[2J\033[H"); // Clear screen - - print_ui(); -} - void setup(struct config* config) { g_config = config; - ioctl(STDOUT_FILENO, TIOCGWINSZ, &window); - - // at least - // 2 padding top and bottom for footer and vertical compensation - // 2 padding left & right to not overflow footer width - if (window.ws_row < BOX_HEIGHT + INNER_BOX_OUT_MARGIN * 2 || - window.ws_col < BOX_WIDTH + INNER_BOX_OUT_MARGIN * 2) { - (void)fprintf(stderr, "\x1b[1;31mScreen too small\x1b[0m\n"); - exit(1); - } tcgetattr(STDOUT_FILENO, &orig_term); term = orig_term; // save term @@ -197,7 +171,19 @@ void ui_update_ofield(struct opts_field* NNULLABLE self) { } static char* unknown_str = "unknown"; -void print_ui() { +void scratch_print_ui() { + ioctl(STDOUT_FILENO, TIOCGWINSZ, &window); + + if (window.ws_row < BOX_HEIGHT + INNER_BOX_OUT_MARGIN * 2 || + window.ws_col < BOX_WIDTH + INNER_BOX_OUT_MARGIN * 2) { + printf("\033[2J\033[H"); // Clear screen + printf("\x1b[1;31mScreen too small\x1b[0m\n"); + printf("\x1b[%s;%sm\x1b[2J", g_config->colors.bg, g_config->colors.fg); + return; + } + + printf("\033[2J\033[H"); // Clear screen + // hostnames larger won't render properly const u_char HOSTNAME_SIZE = VALUES_COL - VALUES_SEPR - BOX_HMARGIN; char hostname_buf[HOSTNAME_SIZE]; @@ -239,8 +225,13 @@ void print_ui() { ui_update_cursor_focus(); } +#define READ_NONBLOCK_DELAY 100000 // NOLINTNEXTLINE(readability-function-cognitive-complexity) int load(struct Vector* users, struct Vector* sessions) { + struct timeval tv; + tv.tv_sec = 0; + tv.tv_usec = READ_NONBLOCK_DELAY; // timeout = 100ms + /// SETUP gusers = users; gsessions = sessions; @@ -278,7 +269,7 @@ int load(struct Vector* users, struct Vector* sessions) { free(initial_state.session_opt); } - print_ui(); + scratch_print_ui(); /// INTERACTIVE u_char len; @@ -287,24 +278,10 @@ int load(struct Vector* users, struct Vector* sessions) { while (true) { if (need_resize) { need_resize = 0; - resize_ui(); + scratch_print_ui(); } - // Async press handling (magic) - fd_set fds; - FD_ZERO(&fds); - FD_SET(STDIN_FILENO, &fds); - struct timeval tv; - tv.tv_sec = 0; - tv.tv_usec = 100000; // timeout = 100ms - // Wait for input with timeout - int ret = select(STDIN_FILENO + 1, &fds, NULL, NULL, &tv); - if (ret < 0) { - if (errno == EINTR) continue; // Interrupted by signal - } - if (ret == 0) continue; // Timeout - - read_press(&len, seq); + if (!read_press_nb(&len, seq, &tv)) continue; if (*seq == '\x1b') { enum keys ansi_code = find_ansi(seq); if (ansi_code != -1) { diff --git a/src/util.c b/src/util.c index 7701f9f..12864d4 100644 --- a/src/util.c +++ b/src/util.c @@ -1,3 +1,5 @@ +#include +#include #include #include #include @@ -53,6 +55,17 @@ void read_press(u_char* length, char* out) { } } +bool read_press_nb(u_char* length, char* out, struct timeval* tv) { + fd_set fds; + FD_ZERO(&fds); + FD_SET(STDIN_FILENO, &fds); + int ret = select(STDIN_FILENO + 1, &fds, NULL, NULL, tv); + if ((ret < 0 && errno == EINTR) || ret == 0) return false; + + read_press(length, out); + return true; +} + // https://stackoverflow.com/a/48040042 static int selret_magic() { fd_set set;