shithub: puzzles

Download patch

ref: 9dbcfa765ba59a8201425df18bec09c7bc334c5e
parent: 015bd1447472f82a5607ecb5fabaf25bf37cd4e2
author: Ben Harris <bjh21@bjh21.me.uk>
date: Thu Feb 23 17:32:53 EST 2023

More cleverness in midend_process_key()

It now strips off modifier flags from keys that shouldn't have them and
maps printable characters with MOD_CTRL to the corresponding control
characters.  It also catches Ctrl+Shift+Z because that obviously belongs
in the midend.

I've updated the JavaScript front-end to take advantage of these
changes.  Other front ends are unchanged and should work just as they
did before.

--- a/devel.but
+++ b/devel.but
@@ -3191,8 +3191,9 @@
 The parameters \c{x} and \c{y} are identical to the ones passed to the
 back end function \cw{interpret_move()} (\k{backend-interpret-move}).
 
-\c{button} is \e{almost} identical to the parameter passed to
-\cw{interpret_move()}. However, some additional special button values
+\c{button} is similar to the parameter passed to
+\cw{interpret_move()}. However, the midend is more relaxed about
+values passed to in, and some additional special button values
 are defined for the front end to pass to the midend (see below).
 
 Also, the front end is \e{not} required to provide guarantees about
@@ -3265,6 +3266,11 @@
 items the same, by translating each of them into a button code passed
 to the midend, and handle quitting by noticing the \c{false} return
 value from \cw{midend_process_key()}.)
+
+The midend tolerates any modifier being set on any key and removes
+them as necessary before passing the key on to the backend.  It will
+also handle translating printable characters combined with
+\cw{MOD_CTRL} into control characters.
 
 \H{midend-request-keys} \cw{midend_request_keys()}
 
--- a/emcc.c
+++ b/emcc.c
@@ -408,19 +408,9 @@
         keyevent = keycode;
 
     if (keyevent >= 0) {
-        if (shift && (keyevent >= 0x100 && !IS_UI_FAKE_KEY(keyevent)))
-            keyevent |= MOD_SHFT;
-
-        if (ctrl && !IS_UI_FAKE_KEY(keyevent)) {
-            if (keyevent >= 0x100)
-                keyevent |= MOD_CTRL;
-            else
-                keyevent &= 0x1F;
-        }
-
-        if ('0' <= keyevent && keyevent <= '9' &&
-            location == DOM_KEY_LOCATION_NUMPAD)
-            keyevent |= MOD_NUM_KEYPAD;
+        if (shift) keyevent |= MOD_SHFT;
+        if (ctrl) keyevent |= MOD_CTRL;
+        if (location == DOM_KEY_LOCATION_NUMPAD) keyevent |= MOD_NUM_KEYPAD;
 
         midend_process_key(me, 0, 0, keyevent, &handled);
         post_move();
--- a/midend.c
+++ b/midend.c
@@ -1140,6 +1140,10 @@
      * of '\n' etc for keyboard-based cursors. The choice of buttons
      * here could eventually be controlled by a runtime configuration
      * option.
+     *
+     * We also handle converting MOD_CTRL|'a' etc into '\x01' etc,
+     * specially recognising Ctrl+Shift+Z, and stripping modifier
+     * flags off keys that aren't meant to have them.
      */
     if (IS_MOUSE_DRAG(button) || IS_MOUSE_RELEASE(button)) {
         if (me->pressed_mouse_button) {
@@ -1169,6 +1173,18 @@
                         (LEFT_RELEASE - LEFT_BUTTON)), handled);
     }
 
+    /* Canonicalise CTRL+ASCII. */
+    if ((button & MOD_CTRL) && (button & ~MOD_MASK) < 0x80)
+        button = button & (0x1f | (MOD_MASK & ~MOD_CTRL));
+    /* Special handling to make CTRL+SHFT+Z into REDO. */
+    if ((button & (~MOD_MASK | MOD_SHFT)) == (MOD_SHFT | '\x1A'))
+        button = UI_REDO;
+    /* interpret_move() expects CTRL and SHFT only on cursor keys. */
+    if (!IS_CURSOR_MOVE(button & ~MOD_MASK))
+        button &= ~(MOD_CTRL | MOD_SHFT);
+    /* ... and NUM_KEYPAD only on ASCII values. */
+    if ((button & ~MOD_MASK) >= 0x80)
+        button &= ~MOD_NUM_KEYPAD;
     /*
      * Translate keyboard presses to cursor selection.
      */