emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

emacs-28 0f8417d: Be more allowing when looking for menu-bar items


From: Stefan Kangas
Subject: emacs-28 0f8417d: Be more allowing when looking for menu-bar items
Date: Thu, 28 Oct 2021 06:47:56 -0400 (EDT)

branch: emacs-28
commit 0f8417d597cbcb136b1e1c2326c701d83c5a2da9
Author: Stefan Kangas <stefan@marxist.se>
Commit: Stefan Kangas <stefan@marxist.se>

    Be more allowing when looking for menu-bar items
    
    Don't merge to master.  This is a safe-for-release fix for Bug#50752.
    
    * src/keymap.c (lookup_key_1): Factor out function from
    Flookup_key.
    (Flookup_key): Be case insensitive when looking for Qmenu_bar
    items.  (Bug#50752)
    
    * test/src/keymap-tests.el
    (keymap-lookup-key/mixed-case)
    (keymap-lookup-key/mixed-case-multibyte): New tests.
---
 etc/NEWS                 |  8 +++++
 src/keymap.c             | 80 +++++++++++++++++++++++++++++++++++-------------
 test/src/keymap-tests.el | 10 ++++++
 3 files changed, 77 insertions(+), 21 deletions(-)

diff --git a/etc/NEWS b/etc/NEWS
index a2b7baf..9f1a001 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -4344,6 +4344,14 @@ The new optional "," parameter has been added, and
 These have a format like "2020-01-15T16:12:21-08:00".
 
 ---
+** 'lookup-key' is more allowing when searching for extended menu items.
+When looking for a menu item '[menu-bar Foo-Bar]', first try to find
+an exact match, then look for the lowercased '[menu-bar foo-bar]'.
+It will only try to downcase ASCII characters in the range "A-Z".
+This improves backwards-compatibility when converting menus to use
+'easy-menu-define'.
+
+---
 ** 'make-network-process', 'make-serial-process' ':coding' behavior change.
 Previously, passing ':coding nil' to either of these functions would
 override any non-nil binding for 'coding-system-for-read' and
diff --git a/src/keymap.c b/src/keymap.c
index 940a6f4..f7529f8 100644
--- a/src/keymap.c
+++ b/src/keymap.c
@@ -1183,27 +1183,8 @@ remapping in all currently active keymaps.  */)
   return FIXNUMP (command) ? Qnil : command;
 }
 
-/* Value is number if KEY is too long; nil if valid but has no definition.  */
-/* GC is possible in this function.  */
-
-DEFUN ("lookup-key", Flookup_key, Slookup_key, 2, 3, 0,
-       doc: /* Look up key sequence KEY in KEYMAP.  Return the definition.
-A value of nil means undefined.  See doc of `define-key'
-for kinds of definitions.
-
-A number as value means KEY is "too long";
-that is, characters or symbols in it except for the last one
-fail to be a valid sequence of prefix characters in KEYMAP.
-The number is how many characters at the front of KEY
-it takes to reach a non-prefix key.
-KEYMAP can also be a list of keymaps.
-
-Normally, `lookup-key' ignores bindings for t, which act as default
-bindings, used when nothing else in the keymap applies; this makes it
-usable as a general function for probing keymaps.  However, if the
-third optional argument ACCEPT-DEFAULT is non-nil, `lookup-key' will
-recognize the default bindings, just as `read-key-sequence' does.  */)
-  (Lisp_Object keymap, Lisp_Object key, Lisp_Object accept_default)
+static Lisp_Object
+lookup_key_1 (Lisp_Object keymap, Lisp_Object key, Lisp_Object accept_default)
 {
   bool t_ok = !NILP (accept_default);
 
@@ -1243,6 +1224,63 @@ recognize the default bindings, just as 
`read-key-sequence' does.  */)
     }
 }
 
+/* Value is number if KEY is too long; nil if valid but has no definition.  */
+/* GC is possible in this function.  */
+
+DEFUN ("lookup-key", Flookup_key, Slookup_key, 2, 3, 0,
+       doc: /* Look up key sequence KEY in KEYMAP.  Return the definition.
+A value of nil means undefined.  See doc of `define-key'
+for kinds of definitions.
+
+A number as value means KEY is "too long";
+that is, characters or symbols in it except for the last one
+fail to be a valid sequence of prefix characters in KEYMAP.
+The number is how many characters at the front of KEY
+it takes to reach a non-prefix key.
+KEYMAP can also be a list of keymaps.
+
+Normally, `lookup-key' ignores bindings for t, which act as default
+bindings, used when nothing else in the keymap applies; this makes it
+usable as a general function for probing keymaps.  However, if the
+third optional argument ACCEPT-DEFAULT is non-nil, `lookup-key' will
+recognize the default bindings, just as `read-key-sequence' does.  */)
+  (Lisp_Object keymap, Lisp_Object key, Lisp_Object accept_default)
+{
+  Lisp_Object found = lookup_key_1 (keymap, key, accept_default);
+  if (!NILP (found) && !NUMBERP (found))
+    return found;
+
+  /* Menu definitions might use mixed case symbols (notably in old
+     versions of `easy-menu-define').  We accept this variation for
+     backwards-compatibility.  (Bug#50752)  */
+  ptrdiff_t key_len = ASIZE (key);
+  if (VECTORP (key) && key_len > 0 && EQ (AREF (key, 0), Qmenu_bar))
+    {
+      Lisp_Object new_key = make_vector (key_len, Qnil);
+      for (int i = 0; i < key_len; ++i)
+       {
+         Lisp_Object sym = Fsymbol_name (AREF (key, i));
+         USE_SAFE_ALLOCA;
+         unsigned char *dst = SAFE_ALLOCA (SBYTES (sym) + 1);
+         memcpy (dst, SSDATA (sym), SBYTES (sym));
+         /* We can walk the string data byte by byte, because UTF-8
+            encoding ensures that no other byte of any multibyte
+            sequence will ever include a 7-bit byte equal to an ASCII
+            single-byte character.  */
+         for (int j = 0; j < SBYTES (sym); ++j)
+           if (dst[j] >= 'A' && dst[j] <= 'Z')
+             dst[j] += 'a' - 'A';  /* Convert to lower case.  */
+         ASET (new_key, i, Fintern (make_multibyte_string ((char *) dst,
+                                                           SCHARS (sym),
+                                                           SBYTES (sym)),
+                                    Qnil));
+         SAFE_FREE ();
+       }
+      found = lookup_key_1 (keymap, new_key, accept_default);
+    }
+  return found;
+}
+
 /* Make KEYMAP define event C as a keymap (i.e., as a prefix).
    Assume that currently it does not define C at all.
    Return the keymap.  */
diff --git a/test/src/keymap-tests.el b/test/src/keymap-tests.el
index 68b42c3..1943e71 100644
--- a/test/src/keymap-tests.el
+++ b/test/src/keymap-tests.el
@@ -124,6 +124,16 @@
 ;; (ert-deftest keymap-lookup-key/accept-default ()
 ;;   ...)
 
+(ert-deftest keymap-lookup-key/mixed-case ()
+  "Backwards compatibility behaviour (Bug#50752)."
+  (let ((map (make-keymap)))
+    (define-key map [menu-bar foo bar] 'foo)
+    (should (eq (lookup-key map [menu-bar foo bar]) 'foo))
+    (should (eq (lookup-key map [menu-bar Foo Bar]) 'foo)))
+  (let ((map (make-keymap)))
+    (define-key map [menu-bar i-bar] 'foo)
+    (should (eq (lookup-key map [menu-bar I-bar]) 'foo))))
+
 (ert-deftest describe-buffer-bindings/header-in-current-buffer ()
   "Header should be inserted into the current buffer.
 https://debbugs.gnu.org/39149#31";



reply via email to

[Prev in Thread] Current Thread [Next in Thread]