Add support for dead accent keys for Latin-1
authorMatthew Mondor <mmondor@rpi.xisop>
Sat, 16 Apr 2022 10:39:10 +0000 (06:39 -0400)
committerMatthew Mondor <mmondor@rpi.xisop>
Sat, 16 Apr 2022 10:39:10 +0000 (06:39 -0400)
utils/textclient.c

index 8f4db2f..4a3d081 100644 (file)
@@ -22,7 +22,6 @@
  * Adapted for more complete xterm emulation by Matthew Mondor.
  */
 
-#include <stdbool.h>
 #include "utils.h"
 #include "utf8wc.h"
 
@@ -38,6 +37,8 @@
 # include <X11/Intrinsic.h>
 #endif
 
+#include <ctype.h>
+#include <stdbool.h>
 #include <stdio.h>
 
 #include <signal.h>
@@ -633,6 +634,79 @@ kv(unsigned int state, const char *norm, const char *shift,
        return norm;
 }
 
+/* dead key -> char -> result */
+struct kdead_s {
+       KeySym k;
+       const char *from;
+       const char *to;
+};
+
+static const struct kdead_s kdead_map[] = {
+       { XK_dead_grave,
+               "AEIOUaeiou",
+               "\300\310\314\322\331\340\350\354\362\371" },
+       { XK_dead_acute,
+               "AEIOUYaeiouy",
+               "\301\311\315\323\332\335\341\351\355\363\372\375" },
+       { XK_dead_circumflex,
+               "AEIOUaeiou",
+               "\302\312\316\324\333\342\352\356\364\373" },
+       { XK_dead_tilde,
+               "ANOano",
+               "\303\321\325\343\361\365" },
+       { XK_dead_diaeresis,
+               "AEIOUaeiouy",
+               "\304\313\317\326\334\344\353\357\366\374\377" },
+       { XK_dead_abovering,
+               "Aa",
+               "\305\345" },
+       { XK_dead_cedilla,
+               "Cc",
+               "\307\347" },
+       { 0, NULL, NULL }
+};
+
+static KeySym dead = 0;
+
+/*
+ * Returns true if keysym or c must be sent, false if it must be dropped.
+ * May substitute c to the appropriate Latin-1 character.
+ */
+static bool
+kdead_filter(KeySym keysym, unsigned char *c)
+{
+
+       /* Dead key previously sent, see if we need to substitute c */
+       if (dead != 0 && isalpha(*c)) {
+               const struct kdead_s *k;
+               int i;
+               KeySym ks = dead;
+
+               dead = 0;
+               for (k = kdead_map; k->k != 0; k++) {
+                       if (k->k != ks)
+                               continue;
+                       for (i = 0; k->from[i] != '\0'; i++) {
+                               if (k->from[i] == (char)*c) {
+                                       *c = (unsigned char)k->to[i];
+                                       return true;
+                               }
+                       }
+               }
+
+               return false;
+       }
+
+       /* Remember dead key */
+       if (keysym >= XK_dead_grave && keysym <= XK_dead_greek) {
+               dead = keysym;
+               return false;
+       }
+
+       /* Passthrough */
+       return true;
+}
+
 Bool
 textclient_putc (text_data *d, XKeyEvent *k)
 {
@@ -888,6 +962,9 @@ send:
                return True;
        }
 
+       if (!kdead_filter(keysym, &c))
+               return False;
+
   if (c != 0 && d->pipe)
     {
       /* Swap DEL/BS if necessary, avoid if already swapped above. */