From: Max Kellermann Date: Mon, 6 Oct 2008 14:57:44 +0000 (+0200) Subject: wreadln: wait for complete multibyte sequence in wreadln_insert_byte() X-Git-Tag: v0.12_alpha1~48 X-Git-Url: https://git.tokkee.org/?a=commitdiff_plain;h=36db27016bbb60534c14692861f9490cde4a6967;p=ncmpc.git wreadln: wait for complete multibyte sequence in wreadln_insert_byte() For multibyte input, we should use wget_wch(), but this function isn't supported properly on some platforms. Add a patch which completes a multibyte character with multiple non-blocking reads. We'll see how portable this hack is... --- diff --git a/src/wreadln.c b/src/wreadln.c index 926f223..08ba991 100644 --- a/src/wreadln.c +++ b/src/wreadln.c @@ -26,6 +26,10 @@ #include #include +#ifdef ENABLE_WIDE +#include +#endif + #define KEY_CTRL_A 1 #define KEY_CTRL_B 2 #define KEY_CTRL_C 3 @@ -120,16 +124,66 @@ static inline void drawline(const struct wreadln *wr) doupdate(); } +#ifdef ENABLE_WIDE +static bool +multibyte_is_complete(const char *p, size_t length) +{ + GError *error = NULL; + gchar *q = g_locale_to_utf8(p, length, + NULL, NULL, &error); + if (q != NULL) { + g_free(q); + return true; + } else { + g_error_free(error); + return false; + } +} +#endif + static void wreadln_insert_byte(struct wreadln *wr, gint key) { size_t rest = strlen(wr->line + wr->cursor) + 1; +#ifdef ENABLE_WIDE + char buffer[32] = { key }; + size_t length = 1; + struct pollfd pfd = { + .fd = 0, + .events = POLLIN, + }; + int ret; + + /* wide version: try to complete the multibyte sequence */ + + while (length < sizeof(buffer)) { + if (multibyte_is_complete(buffer, length)) + /* sequence is complete */ + break; + + /* poll for more bytes on stdin, without timeout */ + + ret = poll(&pfd, 1, 0); + if (ret <= 0) + /* no more input from keyboard */ + break; + + buffer[length++] = wgetch(wr->w); + } + + memmove(wr->line + wr->cursor + length, + wr->line + wr->cursor, rest); + memcpy(wr->line + wr->cursor, buffer, length); + +#else const size_t length = 1; memmove(wr->line + wr->cursor + length, wr->line + wr->cursor, rest); wr->line[wr->cursor] = key; +#endif + wr->cursor += length; if (wr->cursor >= (size_t)wr->width && wr->start < wr->cursor - wr->width + 1)