Code

wreadln: wait for complete multibyte sequence in wreadln_insert_byte()
authorMax Kellermann <max@duempel.org>
Mon, 6 Oct 2008 14:57:44 +0000 (16:57 +0200)
committerMax Kellermann <max@duempel.org>
Mon, 6 Oct 2008 14:57:44 +0000 (16:57 +0200)
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...

src/wreadln.c

index 926f223b7fcdc031347cb811370be1a7fdf920cb..08ba991f27dcb0d44de9cdeab93607a5ce3bb924 100644 (file)
 #include <string.h>
 #include <glib.h>
 
+#ifdef ENABLE_WIDE
+#include <sys/poll.h>
+#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)