From 8c6d0495eedc6ee95ae5f3d3fd7b2c598bfa147b Mon Sep 17 00:00:00 2001 From: nick black Date: Fri, 29 Nov 2019 03:56:53 -0500 Subject: [PATCH] input: decode special keys, call notcurses_resize() #79 --- include/notcurses.h | 3 ++- src/input/input.cpp | 29 +++++++++++++++++++++++++---- src/lib/notcurses.c | 35 ++++++++++++++++++++++++----------- tests/notcurses.cpp | 3 +-- 4 files changed, 52 insertions(+), 18 deletions(-) diff --git a/include/notcurses.h b/include/notcurses.h index ec0083e49..ccc75b6ee 100644 --- a/include/notcurses.h +++ b/include/notcurses.h @@ -140,6 +140,7 @@ API int notcurses_render(struct notcurses* nc); // 0 is returned only by notcurses_getc(), to indicate that no input was // available. Otherwise (including on EOF) -1 is returned. typedef enum { + NCKEY_INVALID, NCKEY_RESIZE, NCKEY_UP, NCKEY_RIGHT, @@ -158,7 +159,7 @@ API int notcurses_getc_blocking(const struct notcurses* n, cell* c, // (as signaled via SIGWINCH), notcurses_render() might not function properly. // References to ncplanes remain valid following a resize operation, but the // cursor might have changed position. -API int notcurses_resize(struct notcurses* n); +API int notcurses_resize(struct notcurses* n, int* y, int* x); // Get a reference to the standard plane (one matching our current idea of the // terminal size) for this terminal. diff --git a/src/input/input.cpp b/src/input/input.cpp index 7128a9e64..76d385723 100644 --- a/src/input/input.cpp +++ b/src/input/input.cpp @@ -6,18 +6,34 @@ #include #include +static int dimy, dimx; +static struct notcurses* nc; + +const char* nckeystr(ncspecial_key key){ + switch(key){ + case NCKEY_RESIZE: + notcurses_resize(nc, &dimy, &dimx); + return "resize event"; + case NCKEY_INVALID: return "invalid"; + case NCKEY_LEFT: return "left"; + case NCKEY_UP: return "up"; + case NCKEY_RIGHT: return "right"; + case NCKEY_DOWN: return "down"; + default: return "unknown"; + } +} + int main(void){ if(setlocale(LC_ALL, "") == nullptr){ return EXIT_FAILURE; } notcurses_options opts{}; opts.outfp = stdout; - struct notcurses* nc = notcurses_init(&opts); - if(nc == nullptr){ + if((nc = notcurses_init(&opts)) == nullptr){ return EXIT_FAILURE;; } struct ncplane* n = notcurses_stdplane(nc); - int r, dimy, dimx; + int r; notcurses_term_dim_yx(nc, &dimy, &dimx); cell c = CELL_TRIVIAL_INITIALIZER; if(ncplane_fg_rgb8(n, 255, 255, 255)){ @@ -36,7 +52,12 @@ int main(void){ } if(cell_simple_p(&c)){ char kp = c.gcluster; - if(ncplane_printf(n, "Got keypress: [0x%04x (%04d)] '%c'\n", kp, kp, kp) < 0){ + if(kp == 0){ + if(ncplane_printf(n, "Got special key: [0x%04x (%04d)] '%s'\n", + special, special, nckeystr(special)) < 0){ + break; + } + }else if(ncplane_printf(n, "Got UTF-8: [0x%04x (%04d)] '%c'\n", kp, kp, kp) < 0){ break; } }else{ diff --git a/src/lib/notcurses.c b/src/lib/notcurses.c index 25b47554a..fef595eb5 100644 --- a/src/lib/notcurses.c +++ b/src/lib/notcurses.c @@ -89,12 +89,13 @@ typedef struct notcurses { // only one notcurses object can be the target of signal handlers, due to their // process-wide nature. +static sig_atomic_t resize_seen; static notcurses* _Atomic signal_nc = ATOMIC_VAR_INIT(NULL); // ugh static void (*signal_sa_handler)(int); // stashed signal handler we replaced static void -sigwinch_handler(int signo __attribute__ ((unused))){ - // FIXME +sigwinch_handler(int signo){ + resize_seen = signo; } // this wildly unsafe handler will attempt to restore the screen upon @@ -316,21 +317,19 @@ create_initial_ncplane(notcurses* nc){ return nc->stdscr; } -// Call this when the screen size changes. Takes a flat -// array of *rows * *cols cells (may be NULL if *rows == *cols == 0). Gets the -// new size, and copies what can be copied from the old stdscr. Assumes that -// the screen is always anchored in the same place. -// FIXME rewrite this in terms of ncpanel_resize(n->stdscr) -int notcurses_resize(notcurses* n){ +// Call this when the screen size changes. Acquires the new size, and copies +// what can be copied from the old stdscr. Assumes that the screen is always +// anchored in the same place. +// // FIXME rewrite this in terms of ncpanel_resize(n->stdscr) +int notcurses_resize(notcurses* n, int* rows, int* cols){ int oldrows = n->stdscr->leny; int oldcols = n->stdscr->lenx; - int rows, cols; - if(update_term_dimensions(n, &rows, &cols)){ + if(update_term_dimensions(n, rows, cols)){ return -1; } ncplane* p = n->stdscr; cell* preserved = p->fb; - size_t fbsize = sizeof(*preserved) * (rows * cols); + size_t fbsize = sizeof(*preserved) * (*rows * *cols); if((p->fb = malloc(fbsize)) == NULL){ p->fb = preserved; return -1; @@ -1315,6 +1314,12 @@ handle_getc(const notcurses* nc __attribute__ ((unused)), cell* c, int kpress, } int notcurses_getc(const notcurses* nc, cell* c, ncspecial_key* special){ + if(resize_seen){ + resize_seen = 0; + c->gcluster = 0; + *special = NCKEY_RESIZE; + return 1; + } int r = getc(nc->ttyinfp); if(r < 0){ return r; @@ -1325,6 +1330,14 @@ int notcurses_getc(const notcurses* nc, cell* c, ncspecial_key* special){ int notcurses_getc_blocking(const notcurses* nc, cell* c, ncspecial_key* special){ int r = getc(nc->ttyinfp); if(r < 0){ + if(errno == EINTR){ + if(resize_seen){ + resize_seen = 0; + c->gcluster = 0; + *special = NCKEY_RESIZE; + return 1; + } + } return r; } return handle_getc(nc, c, r, special); diff --git a/tests/notcurses.cpp b/tests/notcurses.cpp index 3c1b8715d..77360ee66 100644 --- a/tests/notcurses.cpp +++ b/tests/notcurses.cpp @@ -56,9 +56,8 @@ TEST_F(NotcursesTest, TermDimensions) { TEST_F(NotcursesTest, ResizeSameSize) { int x, y; notcurses_term_dim_yx(nc_, &y, &x); - EXPECT_EQ(0, notcurses_resize(nc_)); int newx, newy; - notcurses_term_dim_yx(nc_, &newy, &newx); + EXPECT_EQ(0, notcurses_resize(nc_, &newy, &newx)); EXPECT_EQ(newx, x); EXPECT_EQ(newy, y); }