commit 8947c1f29122ab2e506b2bb723a4fc92bd9d3a59 from: Omar Polo date: Sun Mar 21 13:05:58 2021 UTC [ui] read also non-ASCII codepoints commit - 174b3cdfa1168b20ec02e75e0161e5c802a05e85 commit + 8947c1f29122ab2e506b2bb723a4fc92bd9d3a59 blob - 319abdfb8a27f50215b9bbe4230af846808b62b9 blob + 404312ec0aba8b3eca9ca668466fb8ffe6e5b933 --- telescope.h +++ telescope.h @@ -255,6 +255,8 @@ void ui_notify(const char*, ...) __attribute__((form void ui_end(void); /* utf.8 */ +uint32_t utf8_decode(uint32_t*restrict, uint32_t*restrict, uint8_t); +void utf8_encode(uint32_t, char*); char *utf8_nth(char*, size_t); size_t utf8_cplen(char*); size_t utf8_chwidth(uint32_t); blob - bf812fbd3a8ba6fd7bfddf8740a956b0930cbec9 blob + ac2a27eb58345f3820fc77fe3e629e65c662714e --- ui.c +++ ui.c @@ -117,6 +117,7 @@ static void bp_select(void); static struct vline *nth_line(struct tab*, size_t); static struct tab *current_tab(void); +static int readkey(void); static void dispatch_stdio(int, short, void*); static void handle_clear_minibuf(int, short, void*); static void handle_resize(int, short, void*); @@ -139,7 +140,7 @@ static void switch_to_tab(struct tab*); static struct tab *new_tab(const char*); static void usage(void); -static struct { int meta, key; } thiskey; +static struct { short meta; int key; uint32_t cp; } thiskey; static WINDOW *tabline, *body, *modeline, *minibuf; static int body_lines, body_cols; @@ -1079,37 +1080,62 @@ current_tab(void) abort(); } -static void -dispatch_stdio(int fd, short ev, void *d) +static int +readkey(void) { - struct keymap *k; - const char *keyname; - char tmp[2] = {0}; + uint32_t state = 0; - thiskey.key = wgetch(body); - if (thiskey.key == ERR) - return; - if (thiskey.key == 27) { - /* TODO: make escape-time customizable */ + if ((thiskey.key = wgetch(body)) == ERR) + return 0; - thiskey.meta = 1; + thiskey.meta = thiskey.key == 27; + if (thiskey.meta) { thiskey.key = wgetch(body); if (thiskey.key == ERR || thiskey.key == 27) { thiskey.meta = 0; thiskey.key = 27; } - } else - thiskey.meta = 0; + } + + thiskey.cp = 0; + if ((unsigned int)thiskey.key < UINT8_MAX) { + while (1) { + if (!utf8_decode(&state, &thiskey.cp, (uint8_t)thiskey.key)) + break; + if ((thiskey.key = wgetch(body)) == ERR) { + message("Error decoding user input"); + return 0; + } + } + } + return 1; +} + +static void +dispatch_stdio(int fd, short ev, void *d) +{ + struct keymap *k; + const char *keyname; + char tmp[5] = {0}; + + if (!readkey()) + return; + if (keybuf[0] != '\0') strlcat(keybuf, " ", sizeof(keybuf)); if (thiskey.meta) strlcat(keybuf, "M-", sizeof(keybuf)); - if ((keyname = unkbd(thiskey.key)) != NULL) - strlcat(keybuf, keyname, sizeof(keybuf)); - else { - tmp[0] = thiskey.key; + if (thiskey.cp != 0) { + utf8_encode(thiskey.cp, tmp); strlcat(keybuf, tmp, sizeof(keybuf)); + } else { + if ((keyname = unkbd(thiskey.key)) != NULL) + strlcat(keybuf, keyname, sizeof(keybuf)); + else { + tmp[0] = thiskey.key; + strlcat(keybuf, tmp, sizeof(keybuf)); + } } TAILQ_FOREACH(k, ¤t_map->m, keymaps) { blob - a77cea6636e1e8fd8f3183ad8a30cb9d87518ddd blob + 127fbb5153f75ff8a6135564ac27df0b9d7ae17c --- utf8.c +++ utf8.c @@ -48,7 +48,7 @@ static const uint8_t utf8d[] = { 1,3,1,1,1,1,1,3,1,3,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // s7..s8 }; -static inline uint32_t +uint32_t utf8_decode(uint32_t* restrict state, uint32_t* restrict codep, uint8_t byte) { uint32_t type = utf8d[byte]; @@ -63,6 +63,28 @@ utf8_decode(uint32_t* restrict state, uint32_t* restri /* end of the converter, utility functions ahead */ +/* encode cp in s. s must be at least 4 bytes wide */ +void +utf8_encode(uint32_t cp, char *s) +{ + if (cp <= 0x7F) { + *s = (uint8_t)cp; + } else if (cp <= 0x7FF) { + s[1] = (uint8_t)(( cp & 0x3F ) + 0x80); + s[0] = (uint8_t)(((cp >> 6) & 0x1F) + 0xC0); + } else if (cp <= 0xFFFF) { + s[2] = (uint8_t)(( cp & 0x3F) + 0x80); + s[1] = (uint8_t)(((cp >> 6) & 0x3F) + 0x80); + s[0] = (uint8_t)(((cp >> 12) & 0x0F) + 0xE0); + } else if (cp <= 0x10FFFF) { + s[3] = (uint8_t)(( cp & 0x3F) + 0x80); + s[2] = (uint8_t)(((cp >> 6) & 0x3F) + 0x80); + s[1] = (uint8_t)(((cp >> 12) & 0x3F) + 0x80); + s[0] = (uint8_t)(((cp >> 18) & 0x07) + 0xF0); + } else + s[0] = '\0'; +} + char * utf8_nth(char *s, size_t n) {