diff --git a/NEWS.md b/NEWS.md index e286e0fba..413dcbd22 100644 --- a/NEWS.md +++ b/NEWS.md @@ -35,6 +35,9 @@ rearrangements of Notcurses. * `CELL_TRIVIAL_INITIALIZER`, `CELL_CHAR_INITIALIZER`, and `CELL_INITIALIZER` are all now prefixed with `NC`. * A new resize callback, `ncplane_resize_placewithin()`, has been added. + * The `ncinput` struct has a new field, `utf8`. `notcurses_get()` will fill + in this array of `char` with the NUL-terminated UTF-8 representation of + the input whenever one exists. * 2.4.9 (2021-11-11) * Added `ncnmetric()`, which uses `snprintf()` internally. `ncmetric()` diff --git a/doc/man/man3/notcurses_input.3.md b/doc/man/man3/notcurses_input.3.md index f53f5fe9e..902abc0a1 100644 --- a/doc/man/man3/notcurses_input.3.md +++ b/doc/man/man3/notcurses_input.3.md @@ -18,6 +18,7 @@ typedef struct ncinput { uint32_t id; // Unicode codepoint int y; // Y cell coordinate of event, -1 for undefined int x; // X cell coordinate of event, -1 for undefined + char utf8[5]; // utf8 representation, when one exists bool alt; // Was Alt held during the event? bool shift; // Was Shift held during the event? bool ctrl; // Was Ctrl held during the event? @@ -69,6 +70,8 @@ must be explicitly enabled via **notcurses_mice_enable**. The full 32-bit range of Unicode is supported (see **unicode(7)**), with synthesized events mapped above the 1,114,112 codepoints of Unicode 14.0's seventeen Planes. Unicode characters are returned directly as UCS-32, one codepoint at a time. +When the input has a UTF8 representation, it is written to **utf8**; this +field is always NUL-terminated. notcurses takes its keyboard input from **stdin**, which will be placed into non-blocking mode for the duration of operation. The terminal is put into diff --git a/include/notcurses/notcurses.h b/include/notcurses/notcurses.h index ba8159c66..cec46d130 100644 --- a/include/notcurses/notcurses.h +++ b/include/notcurses/notcurses.h @@ -1065,6 +1065,7 @@ nckey_mouse_p(uint32_t r){ typedef struct ncinput { uint32_t id; // Unicode codepoint or synthesized NCKEY event int y, x; // y/x cell coordinate of event, -1 for undefined + char utf8[5]; // utf8 representation, if one exists bool alt; // was alt held? bool shift; // was shift held? bool ctrl; // was ctrl held? diff --git a/src/input/input.cpp b/src/input/input.cpp index 310f39015..98a8b8d72 100644 --- a/src/input/input.cpp +++ b/src/input/input.cpp @@ -346,7 +346,7 @@ int input_demo(ncpp::NotCurses* nc) { } }else{ n->set_fg_rgb8(64, 128, 250); - n->printf("Unicode: [0x%08x] '%lc'", r, (wchar_t)r); + n->printf("Unicode: [0x%08x] '%s'", r, ni.utf8); } } unsigned x; diff --git a/src/lib/in.c b/src/lib/in.c index 7e8da3221..c70d195b6 100644 --- a/src/lib/in.c +++ b/src/lib/in.c @@ -2220,6 +2220,10 @@ internal_get(inputctx* ictx, const struct timespec* ts, ncinput* ni){ uint32_t id; if(ictx->drain){ logerror("input is being drained\n"); + if(ni){ + memset(ni, 0, sizeof(*ni)); + ni->id = (uint32_t)-1; + } return (uint32_t)-1; } pthread_mutex_lock(&ictx->ilock); @@ -2239,9 +2243,16 @@ internal_get(inputctx* ictx, const struct timespec* ts, ncinput* ni){ int r = pthread_cond_timedwait(&ictx->icond, &ictx->ilock, ts); if(r == ETIMEDOUT){ pthread_mutex_unlock(&ictx->ilock); + if(ni){ + memset(ni, 0, sizeof(*ni)); + } return 0; }else if(r < 0){ inc_input_errors(ictx); + if(ni){ + memset(ni, 0, sizeof(*ni)); + ni->id = (uint32_t)-1; + } return (uint32_t)-1; } } @@ -2249,6 +2260,9 @@ internal_get(inputctx* ictx, const struct timespec* ts, ncinput* ni){ id = ictx->inputs[ictx->iread].id; if(ni){ memcpy(ni, &ictx->inputs[ictx->iread], sizeof(*ni)); + if(notcurses_ucs32_to_utf8(&ni->id, 1, (unsigned char*)ni->utf8, sizeof(ni->utf8)) < 0){ + ni->utf8[0] = 0; + } } if(++ictx->iread == ictx->isize){ ictx->iread = 0; @@ -2278,14 +2292,8 @@ internal_get(inputctx* ictx, const struct timespec* ts, ncinput* ni){ // infp has already been set non-blocking uint32_t notcurses_get(notcurses* nc, const struct timespec* absdl, ncinput* ni){ - uint32_t id = internal_get(nc->tcache.ictx, absdl, ni); - if(ni){ - if(id == (uint32_t)-1){ - ni->id = id; - } - } - logdebug("returning 0x%08x\n", id); - return id; + uint32_t ret = internal_get(nc->tcache.ictx, absdl, ni); + return ret; } // FIXME better performance if we move this within the locked area