tSupport Unicode in text input - vaccinewars - be a doctor and try to vaccinate the world
git clone git://src.adamsgaard.dk/vaccinewars
Log
Files
Refs
README
LICENSE
---
commit 594e648055b50a8e1bda0b1401e16502fb48d14c
parent a1765422bbab17983838549b5ef7e909e3fd3247
Author: Ben Webb 
Date:   Sun,  3 Jan 2021 21:57:57 -0800

Support Unicode in text input

When in a UTF-8 locale, allow Unicode characters
tto be input to prompts (e.g. for the user's name).
Closes #60.

Diffstat:
  M ChangeLog.md                        |       5 +++++
  M src/curses_client/curses_client.c   |      58 ++++++++++++++++++++++---------

2 files changed, 47 insertions(+), 16 deletions(-)
---
diff --git a/ChangeLog.md b/ChangeLog.md
t@@ -1,3 +1,8 @@
+# HEAD
+- The text-mode client should now support Unicode input when in UTF-8
+  locales, e.g. allowing player names containing accented characters
+  to be input (#60).
+
 # 1.6.1 - 2020-12-11
 - Improved display in non-English text-mode clients; previously
   columns were not aligned properly in some cases and occasionally
diff --git a/src/curses_client/curses_client.c b/src/curses_client/curses_client.c
t@@ -2272,7 +2272,8 @@ Player *ListPlayers(Player *Play, gboolean Select, char *Prompt)
 char *nice_input(char *prompt, int sy, int sx, gboolean digitsonly,
                  char *displaystr, char passwdchar)
 {
-  int i, c, x;
+  int ibyte, ichar, x;
+  gunichar c;
   gboolean DecimalPoint, Suffix;
   GString *text;
   gchar *ReturnString;
t@@ -2289,47 +2290,72 @@ char *nice_input(char *prompt, int sy, int sx, gboolean digitsonly,
   attrset(TextAttr);
   if (displaystr) {
     if (passwdchar) {
-      for (i = strlen(displaystr); i; i--)
+      int i;
+      for (i = strcharlen(displaystr); i; i--)
         addch((guint)passwdchar);
     } else {
       addstr(displaystr);
     }
-    i = strlen(displaystr);
+    ibyte = strlen(displaystr);
+    ichar = strcharlen(displaystr);
     text = g_string_new(displaystr);
   } else {
-    i = 0;
+    ibyte = ichar = 0;
     text = g_string_new("");
   }
 
   curs_set(1);
   do {
-    move(sy + (x + i) / Width, (x + i) % Width);
+    move(sy + (x + ichar) / Width, (x + ichar) % Width);
     c = bgetch();
-    if ((c == 8 || c == KEY_BACKSPACE || c == 127) && i > 0) {
-      move(sy + (x + i - 1) / Width, (x + i - 1) % Width);
+    if ((c == 8 || c == KEY_BACKSPACE || c == 127) && ichar > 0) {
+      move(sy + (x + ichar - 1) / Width, (x + ichar - 1) % Width);
       addch(' ');
-      i--;
-      if (DecimalPoint && text->str[i] == '.')
+      ichar--;
+      if (LocaleIsUTF8) {
+        char *p = g_utf8_find_prev_char(text->str, text->str+ibyte);
+        assert(p);
+        ibyte = p - text->str;
+      } else {
+        ibyte--;
+      }
+      if (DecimalPoint && text->str[ibyte] == '.')
         DecimalPoint = FALSE;
       if (Suffix)
         Suffix = FALSE;
-      g_string_truncate(text, i);
+      g_string_truncate(text, ibyte);
     } else if (!Suffix) {
       if ((digitsonly && c >= '0' && c <= '9') ||
-          (!digitsonly && c >= 32 && c != '^' && c < 127)) {
-        g_string_append_c(text, c);
-        i++;
-        addch((guint)passwdchar ? passwdchar : c);
+          (!digitsonly && c >= 32 && c != '^' && c != 127)) {
+        if (LocaleIsUTF8) {
+          char utf8buf[20];
+          gint utf8len = g_unichar_to_utf8(c, utf8buf);
+          utf8buf[utf8len] = '\0';
+          ibyte += utf8len;
+          g_string_append(text, utf8buf);
+          if (passwdchar) {
+            addch((guint)passwdchar);
+          } else {
+            addstr(utf8buf);
+          }
+        } else {
+          g_string_append_c(text, c);
+          ibyte++;
+          addch((guint)passwdchar ? passwdchar : c);
+        }
+        ichar++;
       } else if (digitsonly && (c == '.' || c == ',') && !DecimalPoint) {
         g_string_append_c(text, '.');
-        i++;
+        ibyte++;
+        ichar++;
         addch((guint)passwdchar ? passwdchar : c);
         DecimalPoint = TRUE;
       } else if (digitsonly
                  && (c == 'M' || c == 'm' || c == 'k' || c == 'K')
                  && !Suffix) {
         g_string_append_c(text, c);
-        i++;
+        ibyte++;
+        ichar++;
         addch((guint)passwdchar ? passwdchar : c);
         Suffix = TRUE;
       }