summaryrefslogtreecommitdiff
path: root/src/keymap.c
diff options
context:
space:
mode:
authorStefan Kangas <stefan@marxist.se>2021-10-28 12:30:42 +0200
committerStefan Kangas <stefan@marxist.se>2021-10-28 12:30:42 +0200
commit0f8417d597cbcb136b1e1c2326c701d83c5a2da9 (patch)
tree9acd3725e67b092e2d57dbdc9cb909aa347389c2 /src/keymap.c
parent7e2b973d60cfd30f1828fabd8d9f33127f24e54a (diff)
downloademacs-0f8417d597cbcb136b1e1c2326c701d83c5a2da9.tar.gz
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.
Diffstat (limited to 'src/keymap.c')
-rw-r--r--src/keymap.c80
1 files changed, 59 insertions, 21 deletions
diff --git a/src/keymap.c b/src/keymap.c
index 940a6f492ec..f7529f808bf 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. */