Commit 74c1de23 authored by Richard M. Stallman's avatar Richard M. Stallman

(parse_menu_item): Support keywords :keys and

:key-sequence.  Some changes to provide GC-protection. Some
cosmetic changes.
(syms_of_keyboard): Define new symbols `:keys' and `:key-sequence'.
parent 871fb8d0
......@@ -460,7 +460,8 @@ Lisp_Object Qevent_symbol_elements;
/* menu item parts */
Lisp_Object Qmenu_alias;
Lisp_Object Qmenu_enable;
Lisp_Object QCenable, QCvisible, QChelp, QCfilter, QCbutton, QCtoggle, QCradio;
Lisp_Object QCenable, QCvisible, QChelp, QCfilter, QCkeys, QCkey_sequence;
Lisp_Object QCbutton, QCtoggle, QCradio;
extern Lisp_Object Vdefine_key_rebound_commands;
extern Lisp_Object Qmenu_item;
......@@ -5552,14 +5553,18 @@ parse_menu_item (item, notreal, inmenubar)
Lisp_Object item;
int notreal, inmenubar;
{
Lisp_Object def, tem;
Lisp_Object def, tem, item_string, start, type;
Lisp_Object type = Qnil;
Lisp_Object cachelist = Qnil;
Lisp_Object filter = Qnil;
Lisp_Object item_string, start;
Lisp_Object cachelist;
Lisp_Object filter;
Lisp_Object keyhint;
int i;
struct gcpro gcpro1, gcpro2, gcpro3;
int newcache = 0;
cachelist = Qnil;
filter = Qnil;
keyhint = Qnil;
#define RET0 \
if (1) \
......@@ -5666,9 +5671,25 @@ parse_menu_item (item, notreal, inmenubar)
XVECTOR (item_properties)->contents[ITEM_PROPERTY_HELP]
= XCONS (item)->car;
else if (EQ (tem, QCfilter))
filter = XCONS (item)->car;
filter = item;
else if (EQ (tem, QCkey_sequence))
{
tem = XCONS (item)->car;
if (NILP (cachelist)
&& (SYMBOLP (tem) || STRINGP (tem) || VECTORP (tem)))
/* Be GC protected. Set keyhint to item instead of tem. */
keyhint = item;
}
else if (EQ (tem, QCkeys))
{
tem = XCONS (item)->car;
if (CONSP (tem) || STRINGP (tem) && NILP (cachelist))
XVECTOR (item_properties)->contents[ITEM_PROPERTY_KEYEQ]
= tem;
}
else if (EQ (tem, QCbutton) && CONSP (XCONS (item)->car))
{
Lisp_Object type;
tem = XCONS (item)->car;
type = XCONS (tem)->car;
if (EQ (type, QCtoggle) || EQ (type, QCradio))
......@@ -5703,17 +5724,18 @@ parse_menu_item (item, notreal, inmenubar)
def = XVECTOR (item_properties)->contents[ITEM_PROPERTY_DEF];
if (!NILP (filter))
{
def = menu_item_eval_property (Fcons (filter, Fcons (def, Qnil)));
def = menu_item_eval_property (Fcons (XCONS (filter)->car,
Fcons (def, Qnil)));
XVECTOR (item_properties)->contents[ITEM_PROPERTY_DEF] = def;
}
/* If we got no definition, this item is just unselectable text which
is ok when in a submenu and if there is an item string. */
is OK in a submenu but not in the menubar. */
item_string = XVECTOR (item_properties)->contents[ITEM_PROPERTY_NAME];
if (NILP (def))
{
UNGCPRO;
return (!inmenubar && STRINGP (item_string) ? 1 : 0);
return (inmenubar ? 0 : 1);
}
/* Enable or disable selection of item. */
......@@ -5730,6 +5752,7 @@ parse_menu_item (item, notreal, inmenubar)
}
/* See if this is a separate pane or a submenu. */
def = XVECTOR (item_properties)->contents[ITEM_PROPERTY_DEF];
tem = get_keymap_1 (def, 0, 1);
if (!NILP (tem))
{
......@@ -5748,54 +5771,104 @@ parse_menu_item (item, notreal, inmenubar)
CHECK_IMPURE (start);
XCONS (start)->cdr = Fcons (Fcons (Qnil, Qnil), XCONS (start)->cdr);
cachelist = XCONS (XCONS (start)->cdr)->car;
/* We have not checked this before so check it now. */
tem = def;
newcache = 1;
tem = XVECTOR (item_properties)->contents[ITEM_PROPERTY_KEYEQ];
if (!NILP (keyhint))
{
XCONS (cachelist)->car = XCONS (keyhint)->car;
newcache = 0;
}
else if (VECTORP (XCONS (cachelist)->car)) /* Saved key */
else if (STRINGP (tem))
{
tem = Fkey_binding (XCONS (cachelist)->car, Qnil);
if (EQ (tem, def)
/* If the command is an alias for another
(such as easymenu.el and lmenu.el set it up),
check if the original command matches the cached command. */
|| (SYMBOLP (def) && EQ (tem, XSYMBOL (def)->function)))
tem = Qnil; /* Don't need to recompute key binding. */
else
tem = def;
XCONS (cachelist)->cdr = Fsubstitute_command_keys (tem);
XCONS (cachelist)->car = Qt;
}
/* If something had no key binding before, don't recheck it
because that is too slow--except if we have a list of rebound
commands in Vdefine_key_rebound_commands, do recheck any command
that appears in that list. */
else if (!NILP (XCONS (cachelist)->car))
tem = def; /* Should signal an error here. */
else if (
/* Should we check everything when precomputing key bindings? */
/* notreal || */
CONSP (Vdefine_key_rebound_commands)
&& !NILP (Fmemq (def, Vdefine_key_rebound_commands)))
tem = def;
else
tem = Qnil;
}
tem = XCONS (cachelist)->car;
if (!EQ (tem, Qt))
{
int chkcache = 0;
Lisp_Object prefix;
if (!NILP (tem))
tem = Fkey_binding (tem, Qnil);
prefix = XVECTOR (item_properties)->contents[ITEM_PROPERTY_KEYEQ];
if (CONSP (prefix))
{
def = XCONS (prefix)->car;
prefix = XCONS (prefix)->cdr;
}
else
def = XVECTOR (item_properties)->contents[ITEM_PROPERTY_DEF];
if (NILP (XCONS (cachelist)->car)) /* Have no saved key. */
{
/* Recompute equivalent key binding.
If the command is an alias for another
(such as easymenu.el and lmenu.el set it up),
see if the original command name has equivalent keys.
Otherwise look up the specified command itself.
We don't try both, because that makes easymenu menus slow. */
if (newcache /* Always check first time. */
/* Should we check everything when precomputing key
bindings? */
/* || notreal */
/* If something had no key binding before, don't recheck it
because that is too slow--except if we have a list of
rebound commands in Vdefine_key_rebound_commands, do
recheck any command that appears in that list. */
|| (CONSP (Vdefine_key_rebound_commands)
&& !NILP (Fmemq (def, Vdefine_key_rebound_commands))))
chkcache = 1;
}
/* We had a saved key. Is it still bound to the command? */
else if (NILP (tem)
|| !EQ (tem, def)
/* If the command is an alias for another
(such as lmenu.el set it up), check if the
original command matches the cached command. */
&& !(SYMBOLP (def) && EQ (tem, XSYMBOL (def)->function)))
chkcache = 1; /* Need to recompute key binding. */
if (chkcache)
{
/* Recompute equivalent key binding. If the command is an alias
for another (such as lmenu.el set it up), see if the original
command name has equivalent keys. Otherwise look up the
specified command itself. We don't try both, because that
makes lmenu menus slow. */
if (SYMBOLP (def) && SYMBOLP (XSYMBOL (def)->function)
&& ! NILP (Fget (def, Qmenu_alias)))
tem = XSYMBOL (def)->function;
tem = Fwhere_is_internal (tem, Qnil, Qt, Qnil);
def = XSYMBOL (def)->function;
tem = Fwhere_is_internal (def, Qnil, Qt, Qnil);
XCONS (cachelist)->car = tem;
XCONS (cachelist)->cdr
= (NILP (tem) ? Qnil
:
concat2 (build_string (" ("),
concat2 (Fkey_description (tem), build_string (")"))));
if (NILP (tem))
{
XCONS (cachelist)->cdr = Qnil;
chkcache = 0;
}
}
else if (!NILP (keyhint) && !NILP (XCONS (cachelist)->car))
{
tem = XCONS (cachelist)->car;
chkcache = 1;
}
newcache = chkcache;
if (chkcache)
{
tem = Fkey_description (tem);
if (CONSP (prefix))
{
if (STRINGP (XCONS (prefix)->car))
tem = concat2 (XCONS (prefix)->car, tem);
if (STRINGP (XCONS (prefix)->cdr))
tem = concat2 (tem, XCONS (prefix)->cdr);
}
XCONS (cachelist)->cdr = tem;
}
}
tem = XCONS (cachelist)->cdr;
if (newcache && !NILP (tem))
{
tem = concat3 (build_string (" ("), tem, build_string (")"));
XCONS (cachelist)->cdr = tem;
}
/* If we only want to precompute equivalent key bindings, stop here. */
......@@ -8493,6 +8566,10 @@ syms_of_keyboard ()
staticpro (&QCfilter);
QCbutton = intern (":button");
staticpro (&QCbutton);
QCkeys = intern (":keys");
staticpro (&QCkeys);
QCkey_sequence = intern (":key-sequence");
staticpro (&QCkey_sequence);
QCtoggle = intern (":toggle");
staticpro (&QCtoggle);
QCradio = intern (":radio");
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment