static Lisp_Object describe_buffer_bindings ();
static void describe_command ();
static void describe_map ();
-static void describe_map_2 ();
\f
/* Keymap object support - constructors and predicates. */
get_keymap (object)
Lisp_Object object;
{
- return get_keymap_1 (object, 0, 0);
+ return get_keymap_1 (object, 1, 0);
}
and INDEX is the object to look up in KEYMAP to yield the definition.
Also if OBJECT has a menu string as the first element,
- remove that. Also remove a menu help string as second element. */
+ remove that. Also remove a menu help string as second element.
+
+ If AUTOLOAD is nonzero, load autoloadable keymaps
+ that are referred to with indirection. */
Lisp_Object
-get_keyelt (object)
+get_keyelt (object, autoload)
register Lisp_Object object;
+ int autoload;
{
while (1)
{
register Lisp_Object map, tem;
/* If the contents are (KEYMAP . ELEMENT), go indirect. */
- map = get_keymap_1 (Fcar_safe (object), 0, 0);
+ map = get_keymap_1 (Fcar_safe (object), 0, autoload);
tem = Fkeymapp (map);
if (!NILP (tem))
object = access_keymap (map, Fcdr (object), 0, 0);
int length;
struct gcpro gcpro1, gcpro2, gcpro3;
- keymap = get_keymap (keymap);
+ keymap = get_keymap_1 (keymap, 1, 1);
if (XTYPE (key) != Lisp_Vector
&& XTYPE (key) != Lisp_String)
if (idx == length)
RETURN_UNGCPRO (store_in_keymap (keymap, c, def));
- cmd = get_keyelt (access_keymap (keymap, c, 0, 1));
+ cmd = get_keyelt (access_keymap (keymap, c, 0, 1), 1);
/* If this key is undefined, make it a prefix. */
if (NILP (cmd))
int t_ok = ! NILP (accept_default);
int meta_bit;
- keymap = get_keymap (keymap);
+ keymap = get_keymap_1 (keymap, 1, 1);
if (XTYPE (key) != Lisp_Vector
&& XTYPE (key) != Lisp_String)
idx++;
}
- cmd = get_keyelt (access_keymap (keymap, c, t_ok, 0));
+ cmd = get_keyelt (access_keymap (keymap, c, t_ok, 0), 1);
if (idx == length)
return cmd;
- keymap = get_keymap_1 (cmd, 0, 0);
+ keymap = get_keymap_1 (cmd, 0, 1);
if (NILP (keymap))
return make_number (idx);
optional second argument ACCEPT-DEFAULT is non-nil, `key-binding' does\n\
recognize the default bindings, just as `read-key-sequence' does.")
(key, accept_default)
- Lisp_Object key;
+ Lisp_Object key, accept_default;
{
Lisp_Object *maps, value;
int nmaps, i;
register Lisp_Object tem;
register Lisp_Object cmd;
- cmd = get_keyelt (XVECTOR (elt)->contents[i]);
+ cmd = get_keyelt (XVECTOR (elt)->contents[i], 0);
if (NILP (cmd)) continue;
tem = Fkeymapp (cmd);
if (!NILP (tem))
{
register Lisp_Object cmd, tem, filter;
- cmd = get_keyelt (XCONS (elt)->cdr);
+ cmd = get_keyelt (XCONS (elt)->cdr, 0);
/* Ignore definitions that aren't keymaps themselves. */
tem = Fkeymapp (cmd);
if (!NILP (tem))
/* Search through indirections unless that's not wanted. */
if (NILP (noindirect))
- binding = get_keyelt (binding);
+ binding = get_keyelt (binding, 0);
/* End this iteration if this element does not match
the target. */
Lisp_Object arg;
{
Lisp_Object descbuf, prefix, shadow;
- register Lisp_Object start1, start2;
+ register Lisp_Object start1;
+ struct gcpro gcpro1;
char *alternate_heading
= "\
descbuf = XCONS (arg)->car;
prefix = XCONS (arg)->cdr;
shadow = Qnil;
+ GCPRO1 (shadow);
Fset_buffer (Vstandard_output);
because it takes care of other features when doing so. */
char *title, *p;
- if (XTYPE (modes[i]) == Lisp_Symbol)
- {
- p = title = (char *) alloca (40 + XSYMBOL (modes[i])->name->size);
- *p++ = '`';
- bcopy (XSYMBOL (modes[i])->name->data, p,
- XSYMBOL (modes[i])->name->size);
- p += XSYMBOL (modes[i])->name->size;
- *p++ = '\'';
- }
- else
- {
- p = title = (char *) alloca (40 + 20);
- bcopy ("Strangely Named", p, sizeof ("Strangely Named") - 1);
- p += sizeof ("Strangely Named") - 1;
- }
+ if (XTYPE (modes[i]) != Lisp_Symbol)
+ abort();
+
+ p = title = (char *) alloca (40 + XSYMBOL (modes[i])->name->size);
+ *p++ = '`';
+ bcopy (XSYMBOL (modes[i])->name->data, p,
+ XSYMBOL (modes[i])->name->size);
+ p += XSYMBOL (modes[i])->name->size;
+ *p++ = '\'';
bcopy (" Minor Mode Bindings", p, sizeof (" Minor Mode Bindings") - 1);
p += sizeof (" Minor Mode Bindings") - 1;
*p = 0;
"Global Bindings", 0);
Fset_buffer (descbuf);
+ UNGCPRO;
return Qnil;
}
char *title;
int nomenu;
{
- Lisp_Object maps;
- struct gcpro gcpro1;
+ Lisp_Object maps, seen, sub_shadows;
+ struct gcpro gcpro1, gcpro2, gcpro3;
int something = 0;
char *key_heading
= "\
--- -------\n";
maps = Faccessible_keymaps (startmap, prefix);
- GCPRO1 (maps);
+ seen = Qnil;
+ sub_shadows = Qnil;
+ GCPRO3 (maps, seen, sub_shadows);
if (nomenu)
{
for (; !NILP (maps); maps = Fcdr (maps))
{
- register Lisp_Object elt, prefix, sub_shadows, tail;
+ register Lisp_Object elt, prefix, tail;
elt = Fcar (maps);
prefix = Fcar (elt);
what we should use. */
else
{
- shmap = Flookup_key (shadow, Fcar (elt), Qt);
+ shmap = Flookup_key (shmap, Fcar (elt), Qt);
if (XTYPE (shmap) == Lisp_Int)
shmap = Qnil;
}
sub_shadows = Fcons (shmap, sub_shadows);
}
- describe_map (Fcdr (elt), Fcar (elt), partial, sub_shadows);
+ describe_map (Fcdr (elt), Fcar (elt), describe_command,
+ partial, sub_shadows, &seen);
skip: ;
}
}
}
-/* Describe the contents of map MAP, assuming that this map itself is
- reached by the sequence of prefix keys KEYS (a string or vector).
- PARTIAL, SHADOW is as in `describe_map_tree' above. */
-
-static void
-describe_map (map, keys, partial, shadow)
- Lisp_Object map, keys;
- int partial;
- Lisp_Object shadow;
-{
- register Lisp_Object keysdesc;
-
- if (!NILP (keys) && XFASTINT (Flength (keys)) > 0)
- {
- Lisp_Object tem;
- /* Call Fkey_description first, to avoid GC bug for the other string. */
- tem = Fkey_description (keys);
- keysdesc = concat2 (tem, build_string (" "));
- }
- else
- keysdesc = Qnil;
-
- describe_map_2 (map, keysdesc, describe_command, partial, shadow);
-}
-
/* Like Flookup_key, but uses a list of keymaps SHADOW instead of a single map.
Returns the first non-nil binding found in any of those maps. */
return Qnil;
}
-/* Insert a description of KEYMAP into the current buffer. */
+/* Describe the contents of map MAP, assuming that this map itself is
+ reached by the sequence of prefix keys KEYS (a string or vector).
+ PARTIAL, SHADOW are as in `describe_map_tree' above. */
static void
-describe_map_2 (keymap, elt_prefix, elt_describer, partial, shadow)
- register Lisp_Object keymap;
- Lisp_Object elt_prefix;
+describe_map (map, keys, elt_describer, partial, shadow, seen)
+ register Lisp_Object map;
+ Lisp_Object keys;
int (*elt_describer) ();
int partial;
Lisp_Object shadow;
+ Lisp_Object *seen;
{
+ Lisp_Object elt_prefix;
Lisp_Object tail, definition, event;
Lisp_Object tem;
Lisp_Object suppress;
int first = 1;
struct gcpro gcpro1, gcpro2, gcpro3;
+ if (!NILP (keys) && XFASTINT (Flength (keys)) > 0)
+ {
+ /* Call Fkey_description first, to avoid GC bug for the other string. */
+ tem = Fkey_description (keys);
+ elt_prefix = concat2 (tem, build_string (" "));
+ }
+ else
+ elt_prefix = Qnil;
+
if (partial)
suppress = intern ("suppress-keymap");
GCPRO3 (elt_prefix, definition, kludge);
- for (tail = XCONS (keymap)->cdr; CONSP (tail); tail = Fcdr (tail))
+ for (tail = map; CONSP (tail); tail = XCONS (tail)->cdr)
{
QUIT;
if (XTYPE (XCONS (tail)->car) == Lisp_Vector)
describe_vector (XCONS (tail)->car,
elt_prefix, elt_describer, partial, shadow);
- else
+ else if (CONSP (XCONS (tail)->car))
{
- event = Fcar_safe (Fcar (tail));
- definition = get_keyelt (Fcdr_safe (Fcar (tail)));
+ event = XCONS (XCONS (tail)->car)->car;
+
+ /* Ignore bindings whose "keys" are not really valid events.
+ (We get these in the frames and buffers menu.) */
+ if (! (SYMBOLP (event) || INTEGERP (event)))
+ continue;
+
+ definition = get_keyelt (XCONS (XCONS (tail)->car)->cdr, 0);
/* Don't show undefined commands or suppressed commands. */
if (NILP (definition)) continue;
if (!NILP (tem)) continue;
}
- tem = Flookup_key (keymap, kludge, Qt);
+ tem = Flookup_key (map, kludge, Qt);
if (! EQ (tem, definition)) continue;
if (first)
for alignment purposes. */
(*elt_describer) (definition);
}
+ else if (EQ (XCONS (tail)->car, Qkeymap))
+ {
+ /* The same keymap might be in the structure twice, if we're
+ using an inherited keymap. So skip anything we've already
+ encountered. */
+ tem = Fassq (tail, *seen);
+ if (CONSP (tem) && Fequal (XCONS (tem)->car, keys))
+ break;
+ *seen = Fcons (Fcons (tail, keys), *seen);
+ }
}
UNGCPRO;
for (i = 0; i < XVECTOR (vector)->size; i++)
{
QUIT;
- tem1 = get_keyelt (XVECTOR (vector)->contents[i]);
+ tem1 = get_keyelt (XVECTOR (vector)->contents[i], 0);
if (NILP (tem1)) continue;
/* Find all consecutive characters that have the same definition. */
while (i + 1 < XVECTOR (vector)->size
- && (tem2 = get_keyelt (XVECTOR (vector)->contents[i+1]),
+ && (tem2 = get_keyelt (XVECTOR (vector)->contents[i+1], 0),
EQ (tem2, tem1)))
i++;