changeset 2104:3e7e5395f0bc

non-ASCII keybindings Alexander Voigt has kindly done some testing, and it seems that this makes bindings to most keys on a German keyboard possible -- except those that need AltGr don't work yet.
author corvid <corvid@lavabit.com>
date Do, 23 Jun 2011 19:24:11 +0000
parents 16e52ecf20a8
children 447d1374ba6a
files ChangeLog src/keys.cc src/utf8.cc src/utf8.hh
diffstat 4 files changed, 27 insertions(+), 11 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Di Jun 21 21:06:38 2011 -0400
+++ b/ChangeLog	Do Jun 23 19:24:11 2011 +0000
@@ -12,6 +12,7 @@
    Patches: Jorge Arellano Cid
 +- Remove --enable-ansi configure option.
  - Limit saved cookie size.
+ - Allow binding to non-ASCII keys.
    Patches: corvid
 
 -----------------------------------------------------------------------------
--- a/src/keys.cc	Di Jun 21 21:06:38 2011 -0400
+++ b/src/keys.cc	Do Jun 23 19:24:11 2011 +0000
@@ -17,6 +17,7 @@
 
 #include "dlib/dlib.h"
 #include "keys.hh"
+#include "utf8.hh"
 #include "msg.h"
 
 /*
@@ -172,20 +173,25 @@
 {
    KeysCommand_t ret = KEYS_NOP;
    KeyBinding_t keyNode;
-   // We're only interested in some flags
-   keyNode.modifier = Fl::event_state() &
-     (FL_SHIFT | FL_CTRL | FL_ALT | FL_META);
 
-   if (keyNode.modifier == FL_SHIFT &&
-       ispunct(Fl::event_text()[0])) {
-      // Get key code for a shifted character
-      keyNode.key = Fl::event_text()[0];
-      keyNode.modifier = 0;
+   keyNode.modifier = Fl::event_state() & (FL_SHIFT | FL_CTRL |FL_ALT|FL_META);
+   if (iscntrl(Fl::event_text()[0])) {
+      keyNode.key = Fl::event_key();
    } else {
-      keyNode.key = Fl::event_key();
+      const char *beyond = Fl::event_text() + Fl::event_length();
+      keyNode.key = a_Utf8_decode(Fl::event_text(), beyond, NULL);
+
+      /* BUG: The idea is to drop the modifiers if their use results in a
+       * different character (e.g., if shift-8 gives '*', drop the shift,
+       * but if ctrl-6 gives '6', keep the ctrl), but we have to compare a
+       * keysym with a Unicode codepoint, which only works for characters
+       * below U+0100 (those known to latin-1).
+       */
+      if (keyNode.key != Fl::event_key())
+         keyNode.modifier = 0;
    }
-
-   _MSG("getKeyCmd: key=%d, mod=%d\n", keyNode.key, keyNode.modifier);
+   _MSG("getKeyCmd: evkey=0x%x evtext=\'%s\' key=0x%x, mod=0x%x\n",
+        Fl::event_key(), Fl::event_text(), keyNode.key, keyNode.modifier);
    void *data = dList_find_sorted(bindings, &keyNode, nodeByKeyCmp);
    if (data)
       ret = ((KeyBinding_t*)data)->cmd;
@@ -311,6 +317,9 @@
    // Get key code
    if (!key[1]) {
       keycode = *key;
+   } else if (a_Utf8_char_count(keystr, strlen(keystr)) == 1) {
+      const char *beyond = keystr + strlen(keystr);
+      keycode = a_Utf8_decode(keystr, beyond, NULL);
    } else if (key[0] == '0' && key[1] == 'x') {
       /* keysym. For details on values reported, see fltk's fltk/events.h */
       keycode = strtol(key, NULL, 0x10);
--- a/src/utf8.cc	Di Jun 21 21:06:38 2011 -0400
+++ b/src/utf8.cc	Do Jun 23 19:24:11 2011 +0000
@@ -100,3 +100,8 @@
            (unicode >= 0x20d0 && unicode <= 0x20ff) ||
            (unicode >= 0xfe20 && unicode <= 0xfe2f));
 }
+
+int a_Utf8_char_count(const char *str, int len)
+{
+   return fl_utf_nb_char((const uchar_t*)str, len);
+}
--- a/src/utf8.hh	Di Jun 21 21:06:38 2011 -0400
+++ b/src/utf8.hh	Do Jun 23 19:24:11 2011 +0000
@@ -24,6 +24,7 @@
 int a_Utf8_test(const char* src, unsigned int srclen);
 bool_t a_Utf8_ideographic(const char *s, const char *end, int *len);
 bool_t a_Utf8_combining_char(int unicode);
+int a_Utf8_char_count(const char *str, int len);
 
 #ifdef __cplusplus
 }