/* Manipulation of keymaps
Copyright (C) 1985, 1986, 1987, 1988, 1993, 1994, 1995,
1998, 1999, 2000, 2001, 2002, 2003, 2004,
- 2005, 2006 Free Software Foundation, Inc.
+ 2005, 2006, 2007 Free Software Foundation, Inc.
This file is part of GNU Emacs.
GNU Emacs is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
+the Free Software Foundation; either version 3, or (at your option)
any later version.
GNU Emacs is distributed in the hope that it will be useful,
#include <config.h>
#include <stdio.h>
+#if HAVE_ALLOCA_H
+# include <alloca.h>
+#endif
#include "lisp.h"
#include "commands.h"
#include "buffer.h"
#include "charset.h"
#include "keyboard.h"
+#include "frame.h"
#include "termhooks.h"
#include "blockinput.h"
#include "puresize.h"
#include "intervals.h"
#include "keymap.h"
+#include "window.h"
/* The number of elements in keymap vectors. */
#define DENSE_TABLE_SIZE (0200)
/* List of emulation mode keymap alists. */
Lisp_Object Vemulation_mode_map_alists;
-/* Keymap mapping ASCII function key sequences onto their preferred forms.
- Initialized by the terminal-specific lisp files. See DEFVAR for more
- documentation. */
-Lisp_Object Vfunction_key_map;
-
-/* Keymap mapping ASCII function key sequences onto their preferred forms. */
-Lisp_Object Vkey_translation_map;
-
/* A list of all commands given new bindings since a certain time
when nil was stored here.
This is used to speed up recomputation of menu key equivalents
if (CHAR_TABLE_P (XCAR (list)))
{
- Lisp_Object indices[3];
+ int indices[3];
map_char_table (fix_submap_inheritance, Qnil,
XCAR (list), XCAR (list),
}
else if (CHAR_TABLE_P (binding))
{
- Lisp_Object indices[3];
+ int indices[3];
map_char_table (map_keymap_char_table_item, Qnil, binding, binding,
Fcons (make_save_value (fun, 0),
Fcons (make_save_value (data, 0),
DEFUN ("map-keymap", Fmap_keymap, Smap_keymap, 2, 3, 0,
doc: /* Call FUNCTION once for each event binding in KEYMAP.
FUNCTION is called with two arguments: the event that is bound, and
-the definition it is bound to.
+the definition it is bound to. If the event is an integer, it may be
+a generic character (see Info node `(elisp)Splitting Characters'), and
+that means that all actual character events belonging to that generic
+character are bound to the definition.
If KEYMAP has a parent, the parent's bindings are included as well.
This works recursively: if the parent has itself a parent, then the
Lisp_Object elt = XCAR (keymap);
if (CHAR_TABLE_P (elt))
{
- Lisp_Object indices[3];
+ int indices[3];
elt = Fcopy_sequence (elt);
map_char_table (copy_keymap_1, Qnil, elt, elt, elt, 0, indices);
}
or another symbol whose function definition is used, etc.),
a cons (STRING . DEFN), meaning that DEFN is the definition
(DEFN should be a valid definition in its own right),
- or a cons (MAP . CHAR), meaning use definition of CHAR in keymap MAP.
+ or a cons (MAP . CHAR), meaning use definition of CHAR in keymap MAP,
+ or an extended menu item definition.
+ (See info node `(elisp)Extended Menu Items'.)
If KEYMAP is a sparse keymap with a binding for KEY, the existing
binding is altered. If there is no binding for KEY, the new pair
if (SYMBOLP (def) && !EQ (Vdefine_key_rebound_commands, Qt))
Vdefine_key_rebound_commands = Fcons (def, Vdefine_key_rebound_commands);
- meta_bit = VECTORP (key) ? meta_modifier : 0x80;
+ meta_bit = (VECTORP (key) || (STRINGP (key) && STRING_MULTIBYTE (key))
+ ? meta_modifier : 0x80);
- if (VECTORP (def) && ASIZE (def) > 0 && CONSP (AREF (def, make_number (0))))
+ if (VECTORP (def) && ASIZE (def) > 0 && CONSP (AREF (def, 0)))
{ /* DEF is apparently an XEmacs-style keyboard macro. */
Lisp_Object tmp = Fmake_vector (make_number (ASIZE (def)), Qnil);
int i = ASIZE (def);
/* This function may GC (it calls Fkey_binding). */
-DEFUN ("command-remapping", Fcommand_remapping, Scommand_remapping, 1, 1, 0,
- doc: /* Return the remapping for command COMMAND in current keymaps.
-Returns nil if COMMAND is not remapped (or not a symbol). */)
- (command)
- Lisp_Object command;
+DEFUN ("command-remapping", Fcommand_remapping, Scommand_remapping, 1, 3, 0,
+ doc: /* Return the remapping for command COMMAND.
+Returns nil if COMMAND is not remapped (or not a symbol).
+
+If the optional argument POSITION is non-nil, it specifies a mouse
+position as returned by `event-start' and `event-end', and the
+remapping occurs in the keymaps associated with it. It can also be a
+number or marker, in which case the keymap properties at the specified
+buffer position instead of point are used. The KEYMAPS argument is
+ignored if POSITION is non-nil.
+
+If the optional argument KEYMAPS is non-nil, it should be a list of
+keymaps to search for command remapping. Otherwise, search for the
+remapping in all currently active keymaps. */)
+ (command, position, keymaps)
+ Lisp_Object command, position, keymaps;
{
if (!SYMBOLP (command))
return Qnil;
ASET (command_remapping_vector, 1, command);
- return Fkey_binding (command_remapping_vector, Qnil, Qt);
+
+ if (NILP (keymaps))
+ return Fkey_binding (command_remapping_vector, Qnil, Qt, position);
+ else
+ {
+ Lisp_Object maps, binding;
+
+ for (maps = keymaps; !NILP (maps); maps = Fcdr (maps))
+ {
+ binding = Flookup_key (Fcar (maps), command_remapping_vector, Qnil);
+ if (!NILP (binding) && !INTEGERP (binding))
+ return binding;
+ }
+ return Qnil;
+ }
}
/* Value is number if KEY is too long; nil if valid but has no definition. */
DEFUN ("lookup-key", Flookup_key, Slookup_key, 2, 3, 0,
doc: /* In keymap KEYMAP, look up key sequence KEY. Return the definition.
-nil means undefined. See doc of `define-key' for kinds of definitions.
+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
c = Fevent_convert_list (c);
/* Turn the 8th bit of string chars into a meta modifier. */
- if (INTEGERP (c) && XINT (c) & 0x80 && STRINGP (key))
+ if (STRINGP (key) && XINT (c) & 0x80 && !STRING_MULTIBYTE (key))
XSETINT (c, (XINT (c) | meta_modifier) & ~0x80);
/* Allow string since binding for `menu-bar-select-buffer'
static Lisp_Object *cmm_modes = NULL, *cmm_maps = NULL;
static int cmm_size = 0;
-/* Store a pointer to an array of the keymaps of the currently active
- minor modes in *buf, and return the number of maps it contains.
+/* Store a pointer to an array of the currently active minor modes in
+ *modeptr, a pointer to an array of the keymaps of the currently
+ active minor modes in *mapptr, and return the number of maps
+ *mapptr contains.
This function always returns a pointer to the same buffer, and may
free or reallocate it, so if you want to keep it for a long time or
}
DEFUN ("current-active-maps", Fcurrent_active_maps, Scurrent_active_maps,
- 0, 1, 0,
+ 0, 2, 0,
doc: /* Return a list of the currently active keymaps.
OLP if non-nil indicates that we should obey `overriding-local-map' and
-`overriding-terminal-local-map'. */)
- (olp)
- Lisp_Object olp;
+`overriding-terminal-local-map'. POSITION can specify a click position
+like in the respective argument of `key-binding'. */)
+ (olp, position)
+ Lisp_Object olp, position;
{
- Lisp_Object keymaps = Fcons (current_global_map, Qnil);
+ int count = SPECPDL_INDEX ();
+
+ Lisp_Object keymaps;
+
+ /* If a mouse click position is given, our variables are based on
+ the buffer clicked on, not the current buffer. So we may have to
+ switch the buffer here. */
+
+ if (CONSP (position))
+ {
+ Lisp_Object window;
+
+ window = POSN_WINDOW (position);
+
+ if (WINDOWP (window)
+ && BUFFERP (XWINDOW (window)->buffer)
+ && XBUFFER (XWINDOW (window)->buffer) != current_buffer)
+ {
+ /* Arrange to go back to the original buffer once we're done
+ processing the key sequence. We don't use
+ save_excursion_{save,restore} here, in analogy to
+ `read-key-sequence' to avoid saving point. Maybe this
+ would not be a problem here, but it is easier to keep
+ things the same.
+ */
+
+ record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
+
+ set_buffer_internal (XBUFFER (XWINDOW (window)->buffer));
+ }
+ }
+
+ keymaps = Fcons (current_global_map, Qnil);
if (!NILP (olp))
{
}
if (NILP (XCDR (keymaps)))
{
- Lisp_Object local;
Lisp_Object *maps;
int nmaps, i;
- /* This usually returns the buffer's local map,
- but that can be overridden by a `local-map' property. */
- local = get_local_map (PT, current_buffer, Qlocal_map);
- if (!NILP (local))
- keymaps = Fcons (local, keymaps);
+ Lisp_Object keymap, local_map;
+ EMACS_INT pt;
+
+ pt = INTEGERP (position) ? XINT (position)
+ : MARKERP (position) ? marker_position (position)
+ : PT;
+
+ /* Get the buffer local maps, possibly overriden by text or
+ overlay properties */
+
+ local_map = get_local_map (pt, current_buffer, Qlocal_map);
+ keymap = get_local_map (pt, current_buffer, Qkeymap);
+
+ if (CONSP (position))
+ {
+ Lisp_Object string;
+
+ /* For a mouse click, get the local text-property keymap
+ of the place clicked on, rather than point. */
+
+ if (POSN_INBUFFER_P (position))
+ {
+ Lisp_Object pos;
+
+ pos = POSN_BUFFER_POSN (position);
+ if (INTEGERP (pos)
+ && XINT (pos) >= BEG && XINT (pos) <= Z)
+ {
+ local_map = get_local_map (XINT (pos),
+ current_buffer, Qlocal_map);
+
+ keymap = get_local_map (XINT (pos),
+ current_buffer, Qkeymap);
+ }
+ }
+
+ /* If on a mode line string with a local keymap,
+ or for a click on a string, i.e. overlay string or a
+ string displayed via the `display' property,
+ consider `local-map' and `keymap' properties of
+ that string. */
+
+ if (string = POSN_STRING (position),
+ (CONSP (string) && STRINGP (XCAR (string))))
+ {
+ Lisp_Object pos, map;
+
+ pos = XCDR (string);
+ string = XCAR (string);
+ if (INTEGERP (pos)
+ && XINT (pos) >= 0
+ && XINT (pos) < SCHARS (string))
+ {
+ map = Fget_text_property (pos, Qlocal_map, string);
+ if (!NILP (map))
+ local_map = map;
+
+ map = Fget_text_property (pos, Qkeymap, string);
+ if (!NILP (map))
+ keymap = map;
+ }
+ }
+
+ }
+
+ if (!NILP (local_map))
+ keymaps = Fcons (local_map, keymaps);
/* Now put all the minor mode keymaps on the list. */
nmaps = current_minor_maps (0, &maps);
if (!NILP (maps[i]))
keymaps = Fcons (maps[i], keymaps);
- /* This returns nil unless there is a `keymap' property. */
- local = get_local_map (PT, current_buffer, Qkeymap);
- if (!NILP (local))
- keymaps = Fcons (local, keymaps);
+ if (!NILP (keymap))
+ keymaps = Fcons (keymap, keymaps);
}
+ unbind_to (count, Qnil);
+
return keymaps;
}
/* GC is possible in this function if it autoloads a keymap. */
-DEFUN ("key-binding", Fkey_binding, Skey_binding, 1, 3, 0,
+DEFUN ("key-binding", Fkey_binding, Skey_binding, 1, 4, 0,
doc: /* Return the binding for command KEY in current keymaps.
KEY is a string or vector, a sequence of keystrokes.
The binding is probably a symbol with a function definition.
Like the normal command loop, `key-binding' will remap the command
resulting from looking up KEY by looking up the command in the
current keymaps. However, if the optional third argument NO-REMAP
-is non-nil, `key-binding' returns the unmapped command. */)
- (key, accept_default, no_remap)
- Lisp_Object key, accept_default, no_remap;
+is non-nil, `key-binding' returns the unmapped command.
+
+If KEY is a key sequence initiated with the mouse, the used keymaps
+will depend on the clicked mouse position with regard to the buffer
+and possible local keymaps on strings.
+
+If the optional argument POSITION is non-nil, it specifies a mouse
+position as returned by `event-start' and `event-end', and the lookup
+occurs in the keymaps associated with it instead of KEY. It can also
+be a number or marker, in which case the keymap properties at the
+specified buffer position instead of point are used.
+ */)
+ (key, accept_default, no_remap, position)
+ Lisp_Object key, accept_default, no_remap, position;
{
Lisp_Object *maps, value;
int nmaps, i;
- struct gcpro gcpro1;
+ struct gcpro gcpro1, gcpro2;
+ int count = SPECPDL_INDEX ();
- GCPRO1 (key);
+ GCPRO2 (key, position);
-#ifdef HAVE_MOUSE
- if (VECTORP (key)
- && ASIZE (key) > 0
- && CONSP (AREF (key, 0))
- && SYMBOLP (XCAR (AREF (key, 0)))
- && CONSP (XCDR (AREF (key, 0))))
+ if (NILP (position) && VECTORP (key))
{
- Lisp_Object map, obj, pos = XCAR (XCDR (AREF (key, 0)));
+ Lisp_Object event
+ /* mouse events may have a symbolic prefix indicating the
+ scrollbar or mode line */
+ = AREF (key, SYMBOLP (AREF (key, 0)) && ASIZE (key) > 1 ? 1 : 0);
+
+ /* We are not interested in locations without event data */
- if (XINT (Flength (pos)) == 10 && INTEGERP (XCAR (XCDR (pos))))
+ if (EVENT_HAS_PARAMETERS (event) && CONSP (XCDR (event)))
{
- obj = Fnth (make_number(4), pos);
- map = Fget_char_property (XCAR (XCDR (pos)),
- Qkeymap,
- NILP (obj) ?
- Fwindow_buffer (XCAR (pos))
- : XCAR (obj));
- if (!NILP (Fkeymapp (map)))
- {
- value = Flookup_key (map, key, accept_default);
- if (! NILP (value) && !INTEGERP (value))
- goto done;
- }
+ Lisp_Object kind = EVENT_HEAD_KIND (EVENT_HEAD (event));
+ if (EQ (kind, Qmouse_click))
+ position = EVENT_START (event);
}
}
-#endif /* HAVE_MOUSE */
- if (!NILP (current_kboard->Voverriding_terminal_local_map))
+ /* Key sequences beginning with mouse clicks
+ are read using the keymaps of the buffer clicked on, not
+ the current buffer. So we may have to switch the buffer
+ here. */
+
+ if (CONSP (position))
+ {
+ Lisp_Object window;
+
+ window = POSN_WINDOW (position);
+
+ if (WINDOWP (window)
+ && BUFFERP (XWINDOW (window)->buffer)
+ && XBUFFER (XWINDOW (window)->buffer) != current_buffer)
+ {
+ /* Arrange to go back to the original buffer once we're done
+ processing the key sequence. We don't use
+ save_excursion_{save,restore} here, in analogy to
+ `read-key-sequence' to avoid saving point. Maybe this
+ would not be a problem here, but it is easier to keep
+ things the same.
+ */
+
+ record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
+
+ set_buffer_internal (XBUFFER (XWINDOW (window)->buffer));
+ }
+ }
+
+ if (! NILP (current_kboard->Voverriding_terminal_local_map))
{
value = Flookup_key (current_kboard->Voverriding_terminal_local_map,
key, accept_default);
if (! NILP (value) && !INTEGERP (value))
goto done;
}
- else if (!NILP (Voverriding_local_map))
+ else if (! NILP (Voverriding_local_map))
{
value = Flookup_key (Voverriding_local_map, key, accept_default);
if (! NILP (value) && !INTEGERP (value))
}
else
{
- Lisp_Object local;
+ Lisp_Object keymap, local_map;
+ EMACS_INT pt;
+
+ pt = INTEGERP (position) ? XINT (position)
+ : MARKERP (position) ? marker_position (position)
+ : PT;
+
+ local_map = get_local_map (pt, current_buffer, Qlocal_map);
+ keymap = get_local_map (pt, current_buffer, Qkeymap);
+
+ if (CONSP (position))
+ {
+ Lisp_Object string;
+
+ /* For a mouse click, get the local text-property keymap
+ of the place clicked on, rather than point. */
+
+ if (POSN_INBUFFER_P (position))
+ {
+ Lisp_Object pos;
+
+ pos = POSN_BUFFER_POSN (position);
+ if (INTEGERP (pos)
+ && XINT (pos) >= BEG && XINT (pos) <= Z)
+ {
+ local_map = get_local_map (XINT (pos),
+ current_buffer, Qlocal_map);
- local = get_local_map (PT, current_buffer, Qkeymap);
- if (! NILP (local))
+ keymap = get_local_map (XINT (pos),
+ current_buffer, Qkeymap);
+ }
+ }
+
+ /* If on a mode line string with a local keymap,
+ or for a click on a string, i.e. overlay string or a
+ string displayed via the `display' property,
+ consider `local-map' and `keymap' properties of
+ that string. */
+
+ if (string = POSN_STRING (position),
+ (CONSP (string) && STRINGP (XCAR (string))))
+ {
+ Lisp_Object pos, map;
+
+ pos = XCDR (string);
+ string = XCAR (string);
+ if (INTEGERP (pos)
+ && XINT (pos) >= 0
+ && XINT (pos) < SCHARS (string))
+ {
+ map = Fget_text_property (pos, Qlocal_map, string);
+ if (!NILP (map))
+ local_map = map;
+
+ map = Fget_text_property (pos, Qkeymap, string);
+ if (!NILP (map))
+ keymap = map;
+ }
+ }
+
+ }
+
+ if (! NILP (keymap))
{
- value = Flookup_key (local, key, accept_default);
+ value = Flookup_key (keymap, key, accept_default);
if (! NILP (value) && !INTEGERP (value))
goto done;
}
goto done;
}
- local = get_local_map (PT, current_buffer, Qlocal_map);
- if (! NILP (local))
+ if (! NILP (local_map))
{
- value = Flookup_key (local, key, accept_default);
+ value = Flookup_key (local_map, key, accept_default);
if (! NILP (value) && !INTEGERP (value))
goto done;
}
value = Flookup_key (current_global_map, key, accept_default);
done:
+ unbind_to (count, Qnil);
+
UNGCPRO;
if (NILP (value) || INTEGERP (value))
return Qnil;
if (NILP (no_remap) && SYMBOLP (value))
{
Lisp_Object value1;
- if (value1 = Fcommand_remapping (value), !NILP (value1))
+ if (value1 = Fcommand_remapping (value, position, Qnil), !NILP (value1))
value = value1;
}
\f
/* Help functions for describing and documenting keymaps. */
+struct accessible_keymaps_data {
+ Lisp_Object maps, tail, thisseq;
+ /* Does the current sequence end in the meta-prefix-char? */
+ int is_metized;
+};
static void
-accessible_keymaps_1 (key, cmd, maps, tail, thisseq, is_metized)
- Lisp_Object maps, tail, thisseq, key, cmd;
- int is_metized; /* If 1, `key' is assumed to be INTEGERP. */
+accessible_keymaps_1 (key, cmd, args, data)
+ Lisp_Object key, cmd, args;
+ /* Use void* to be compatible with map_keymap_function_t. */
+ void *data;
{
+ struct accessible_keymaps_data *d = data; /* Cast! */
+ Lisp_Object maps = d->maps;
+ Lisp_Object tail = d->tail;
+ Lisp_Object thisseq = d->thisseq;
+ int is_metized = d->is_metized && INTEGERP (key);
Lisp_Object tem;
cmd = get_keymap (get_keyelt (cmd, 0), 0, 0);
}
}
-static void
-accessible_keymaps_char_table (args, index, cmd)
- Lisp_Object args, index, cmd;
-{
- accessible_keymaps_1 (index, cmd,
- XCAR (XCAR (args)),
- XCAR (XCDR (args)),
- XCDR (XCDR (args)),
- XINT (XCDR (XCAR (args))));
-}
-
/* This function cannot GC. */
DEFUN ("accessible-keymaps", Faccessible_keymaps, Saccessible_keymaps,
Lisp_Object keymap, prefix;
{
Lisp_Object maps, tail;
- int prefixlen = 0;
+ int prefixlen = XINT (Flength (prefix));
/* no need for gcpro because we don't autoload any keymaps. */
- if (!NILP (prefix))
- prefixlen = XINT (Flength (prefix));
-
if (!NILP (prefix))
{
/* If a prefix was specified, start with the keymap (if any) for
if the prefix is not defined in this particular map.
It might even give us a list that isn't a keymap. */
tem = get_keymap (tem, 0, 0);
- if (CONSP (tem))
+ /* If the keymap is autoloaded `tem' is not a cons-cell, but we still
+ want to return it. */
+ if (!NILP (tem))
{
/* Convert PREFIX to a vector now, so that later on
we don't have to deal with the possibility of a string. */
for (tail = maps; CONSP (tail); tail = XCDR (tail))
{
- register Lisp_Object thisseq, thismap;
+ struct accessible_keymaps_data data;
+ register Lisp_Object thismap = Fcdr (XCAR (tail));
Lisp_Object last;
- /* Does the current sequence end in the meta-prefix-char? */
- int is_metized;
- thisseq = Fcar (Fcar (tail));
- thismap = Fcdr (Fcar (tail));
- last = make_number (XINT (Flength (thisseq)) - 1);
- is_metized = (XINT (last) >= 0
+ data.thisseq = Fcar (XCAR (tail));
+ data.maps = maps;
+ data.tail = tail;
+ last = make_number (XINT (Flength (data.thisseq)) - 1);
+ /* Does the current sequence end in the meta-prefix-char? */
+ data.is_metized = (XINT (last) >= 0
/* Don't metize the last char of PREFIX. */
&& XINT (last) >= prefixlen
- && EQ (Faref (thisseq, last), meta_prefix_char));
-
- for (; CONSP (thismap); thismap = XCDR (thismap))
- {
- Lisp_Object elt;
-
- elt = XCAR (thismap);
-
- QUIT;
-
- if (CHAR_TABLE_P (elt))
- {
- Lisp_Object indices[3];
-
- map_char_table (accessible_keymaps_char_table, Qnil, elt,
- elt, Fcons (Fcons (maps, make_number (is_metized)),
- Fcons (tail, thisseq)),
- 0, indices);
- }
- else if (VECTORP (elt))
- {
- register int i;
+ && EQ (Faref (data.thisseq, last), meta_prefix_char));
- /* Vector keymap. Scan all the elements. */
- for (i = 0; i < ASIZE (elt); i++)
- accessible_keymaps_1 (make_number (i), AREF (elt, i),
- maps, tail, thisseq, is_metized);
-
- }
- else if (CONSP (elt))
- accessible_keymaps_1 (XCAR (elt), XCDR (elt),
- maps, tail, thisseq,
- is_metized && INTEGERP (XCAR (elt)));
-
- }
+ /* Since we can't run lisp code, we can't scan autoloaded maps. */
+ if (CONSP (thismap))
+ map_keymap (thismap, accessible_keymaps_1, Qnil, &data, 0);
}
-
return maps;
}
-\f
Lisp_Object Qsingle_key_description, Qkey_description;
/* This function cannot GC. */
len += 2;
}
else if (len == 0)
- return empty_string;
+ return empty_unibyte_string;
return Fconcat (len - 1, args);
}
else
SPLIT_CHAR (without_bits, charset, c1, c2);
- if (charset
- && CHARSET_DEFINED_P (charset)
- && ((c1 >= 0 && c1 < 32)
- || (c2 >= 0 && c2 < 32)))
+ if (! CHAR_VALID_P (without_bits, 1))
+ {
+ char buf[256];
+
+ sprintf (buf, "Invalid char code %ld", XINT (key));
+ return build_string (buf);
+ }
+ else if (charset
+ && ((c1 == 0 && c2 == -1) || c2 == 0))
{
/* Handle a generic character. */
Lisp_Object name;
- name = CHARSET_TABLE_INFO (charset, CHARSET_LONG_NAME_IDX);
+ char buf[256];
+
+ name = CHARSET_TABLE_INFO (charset, CHARSET_SHORT_NAME_IDX);
CHECK_STRING (name);
- return concat2 (build_string ("Character set "), name);
+ if (c1 == 0)
+ /* Only a charset is specified. */
+ sprintf (buf, "Generic char %d: all of ", without_bits);
+ else
+ /* 1st code-point of 2-dimensional charset is specified. */
+ sprintf (buf, "Generic char %d: row %d of ", without_bits, c1);
+ return concat2 (build_string (buf), name);
}
else
{
/* where-is - finding a command in a set of keymaps. */
static Lisp_Object where_is_internal ();
-static Lisp_Object where_is_internal_1 ();
-static void where_is_internal_2 ();
+static void where_is_internal_1 P_ ((Lisp_Object key, Lisp_Object binding,
+ Lisp_Object args, void *data));
/* 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. */
static Lisp_Object Vmouse_events;
+struct where_is_internal_data {
+ Lisp_Object definition, noindirect, this, last;
+ int last_is_meta;
+ Lisp_Object sequences;
+};
+
/* This function can GC if Flookup_key autoloads any keymaps. */
static Lisp_Object
/* 1 means ignore all menu bindings entirely. */
int nomenus = !NILP (firstonly) && !EQ (firstonly, Qnon_ascii);
- /* If this command is remapped, then it has no key bindings
- of its own. */
- if (NILP (no_remap) && SYMBOLP (definition))
- {
- Lisp_Object tem;
- if (tem = Fcommand_remapping (definition), !NILP (tem))
- return Qnil;
- }
-
found = keymaps;
while (CONSP (found))
{
found = Qnil;
sequences = Qnil;
+ /* If this command is remapped, then it has no key bindings
+ of its own. */
+ if (NILP (no_remap)
+ && SYMBOLP (definition)
+ && !NILP (Fcommand_remapping (definition, Qnil, keymaps)))
+ RETURN_UNGCPRO (Qnil);
+
for (; !NILP (maps); maps = Fcdr (maps))
{
/* Key sequence to reach map, and the map that it reaches */
register Lisp_Object this, map, tem;
+ struct where_is_internal_data data;
/* In order to fold [META-PREFIX-CHAR CHAR] sequences into
[M-CHAR] sequences, check if last character of the sequence
QUIT;
- while (CONSP (map))
- {
- /* Because the code we want to run on each binding is rather
- large, we don't want to have two separate loop bodies for
- sparse keymap bindings and tables; we want to iterate one
- loop body over both keymap and vector bindings.
-
- For this reason, if Fcar (map) is a vector, we don't
- advance map to the next element until i indicates that we
- have finished off the vector. */
- Lisp_Object elt, key, binding;
- elt = XCAR (map);
- map = XCDR (map);
+ data.definition = definition;
+ data.noindirect = noindirect;
+ data.this = this;
+ data.last = last;
+ data.last_is_meta = last_is_meta;
+ data.sequences = Qnil;
- sequences = Qnil;
+ if (CONSP (map))
+ map_keymap (map, where_is_internal_1, Qnil, &data, 0);
- QUIT;
+ sequences = data.sequences;
- /* Set key and binding to the current key and binding, and
- advance map and i to the next binding. */
- if (VECTORP (elt))
+ while (CONSP (sequences))
+ {
+ Lisp_Object sequence, remapped, function;
+
+ sequence = XCAR (sequences);
+ sequences = XCDR (sequences);
+
+ /* If the current sequence is a command remapping with
+ format [remap COMMAND], find the key sequences
+ which run COMMAND, and use those sequences instead. */
+ remapped = Qnil;
+ if (NILP (no_remap)
+ && VECTORP (sequence) && XVECTOR (sequence)->size == 2
+ && EQ (AREF (sequence, 0), Qremap)
+ && (function = AREF (sequence, 1), SYMBOLP (function)))
{
- Lisp_Object sequence;
- int i;
- /* In a vector, look at each element. */
- for (i = 0; i < XVECTOR (elt)->size; i++)
+ Lisp_Object remapped1;
+
+ remapped1 = where_is_internal (function, keymaps, firstonly, noindirect, Qt);
+ if (CONSP (remapped1))
{
- binding = AREF (elt, i);
- XSETFASTINT (key, i);
- sequence = where_is_internal_1 (binding, key, definition,
- noindirect, this,
- last, nomenus, last_is_meta);
- if (!NILP (sequence))
- sequences = Fcons (sequence, sequences);
+ /* Verify that this key binding actually maps to the
+ remapped command (see below). */
+ if (!EQ (shadow_lookup (keymaps, XCAR (remapped1), Qnil), function))
+ continue;
+ sequence = XCAR (remapped1);
+ remapped = XCDR (remapped1);
+ goto record_sequence;
}
}
- else if (CHAR_TABLE_P (elt))
- {
- Lisp_Object indices[3];
- Lisp_Object args;
-
- args = Fcons (Fcons (Fcons (definition, noindirect),
- Qnil), /* Result accumulator. */
- Fcons (Fcons (this, last),
- Fcons (make_number (nomenus),
- make_number (last_is_meta))));
- map_char_table (where_is_internal_2, Qnil, elt, elt, args,
- 0, indices);
- sequences = XCDR (XCAR (args));
- }
- else if (CONSP (elt))
- {
- Lisp_Object sequence;
- key = XCAR (elt);
- binding = XCDR (elt);
+ /* Verify that this key binding is not shadowed by another
+ binding for the same key, before we say it exists.
- sequence = where_is_internal_1 (binding, key, definition,
- noindirect, this,
- last, nomenus, last_is_meta);
- if (!NILP (sequence))
- sequences = Fcons (sequence, sequences);
- }
+ Mechanism: look for local definition of this key and if
+ it is defined and does not match what we found then
+ ignore this key.
+ Either nil or number as value from Flookup_key
+ means undefined. */
+ if (!EQ (shadow_lookup (keymaps, sequence, Qnil), definition))
+ continue;
- while (!NILP (sequences))
+ record_sequence:
+ /* Don't annoy user with strings from a menu such as
+ Select Paste. Change them all to "(any string)",
+ so that there seems to be only one menu item
+ to report. */
+ if (! NILP (sequence))
{
- Lisp_Object sequence, remapped, function;
-
- sequence = XCAR (sequences);
- sequences = XCDR (sequences);
-
- /* If the current sequence is a command remapping with
- format [remap COMMAND], find the key sequences
- which run COMMAND, and use those sequences instead. */
- remapped = Qnil;
- if (NILP (no_remap)
- && VECTORP (sequence) && XVECTOR (sequence)->size == 2
- && EQ (AREF (sequence, 0), Qremap)
- && (function = AREF (sequence, 1), SYMBOLP (function)))
- {
- Lisp_Object remapped1;
-
- remapped1 = where_is_internal (function, keymaps, firstonly, noindirect, Qt);
- if (CONSP (remapped1))
- {
- /* Verify that this key binding actually maps to the
- remapped command (see below). */
- if (!EQ (shadow_lookup (keymaps, XCAR (remapped1), Qnil), function))
- continue;
- sequence = XCAR (remapped1);
- remapped = XCDR (remapped1);
- goto record_sequence;
- }
- }
-
- /* Verify that this key binding is not shadowed by another
- binding for the same key, before we say it exists.
-
- Mechanism: look for local definition of this key and if
- it is defined and does not match what we found then
- ignore this key.
-
- Either nil or number as value from Flookup_key
- means undefined. */
- if (!EQ (shadow_lookup (keymaps, sequence, Qnil), definition))
- continue;
-
- record_sequence:
- /* Don't annoy user with strings from a menu such as
- Select Paste. Change them all to "(any string)",
- so that there seems to be only one menu item
- to report. */
- if (! NILP (sequence))
- {
- Lisp_Object tem;
- tem = Faref (sequence, make_number (XVECTOR (sequence)->size - 1));
- if (STRINGP (tem))
- Faset (sequence, make_number (XVECTOR (sequence)->size - 1),
- build_string ("(any string)"));
- }
+ Lisp_Object tem;
+ tem = Faref (sequence, make_number (XVECTOR (sequence)->size - 1));
+ if (STRINGP (tem))
+ Faset (sequence, make_number (XVECTOR (sequence)->size - 1),
+ build_string ("(any string)"));
+ }
- /* It is a true unshadowed match. Record it, unless it's already
- been seen (as could happen when inheriting keymaps). */
- if (NILP (Fmember (sequence, found)))
- found = Fcons (sequence, found);
-
- /* If firstonly is Qnon_ascii, then we can return the first
- binding we find. If firstonly is not Qnon_ascii but not
- nil, then we should return the first ascii-only binding
- we find. */
- if (EQ (firstonly, Qnon_ascii))
- RETURN_UNGCPRO (sequence);
- else if (!NILP (firstonly) && ascii_sequence_p (sequence))
- RETURN_UNGCPRO (sequence);
-
- if (CONSP (remapped))
- {
- sequence = XCAR (remapped);
- remapped = XCDR (remapped);
- goto record_sequence;
- }
+ /* It is a true unshadowed match. Record it, unless it's already
+ been seen (as could happen when inheriting keymaps). */
+ if (NILP (Fmember (sequence, found)))
+ found = Fcons (sequence, found);
+
+ /* If firstonly is Qnon_ascii, then we can return the first
+ binding we find. If firstonly is not Qnon_ascii but not
+ nil, then we should return the first ascii-only binding
+ we find. */
+ if (EQ (firstonly, Qnon_ascii))
+ RETURN_UNGCPRO (sequence);
+ else if (!NILP (firstonly) && ascii_sequence_p (sequence))
+ RETURN_UNGCPRO (sequence);
+
+ if (CONSP (remapped))
+ {
+ sequence = XCAR (remapped);
+ remapped = XCDR (remapped);
+ goto record_sequence;
}
}
}
else if (!NILP (keymap))
keymaps = Fcons (keymap, Fcons (current_global_map, Qnil));
else
- keymaps = Fcurrent_active_maps (Qnil);
+ keymaps = Fcurrent_active_maps (Qnil, Qnil);
/* Only use caching for the menubar (i.e. called with (def nil t nil).
We don't really need to check `keymap'. */
return result;
}
-/* This is the function that Fwhere_is_internal calls using map_char_table.
- ARGS has the form
- (((DEFINITION . NOINDIRECT) . (KEYMAP . RESULT))
- .
- ((THIS . LAST) . (NOMENUS . LAST_IS_META)))
- Since map_char_table doesn't really use the return value from this function,
- we the result append to RESULT, the slot in ARGS.
-
- This function can GC because it calls where_is_internal_1 which can
- GC. */
-
-static void
-where_is_internal_2 (args, key, binding)
- Lisp_Object args, key, binding;
-{
- Lisp_Object definition, noindirect, this, last;
- Lisp_Object result, sequence;
- int nomenus, last_is_meta;
- struct gcpro gcpro1, gcpro2, gcpro3;
-
- GCPRO3 (args, key, binding);
- result = XCDR (XCAR (args));
- definition = XCAR (XCAR (XCAR (args)));
- noindirect = XCDR (XCAR (XCAR (args)));
- this = XCAR (XCAR (XCDR (args)));
- last = XCDR (XCAR (XCDR (args)));
- nomenus = XFASTINT (XCAR (XCDR (XCDR (args))));
- last_is_meta = XFASTINT (XCDR (XCDR (XCDR (args))));
-
- sequence = where_is_internal_1 (binding, key, definition, noindirect,
- this, last, nomenus, last_is_meta);
-
- if (!NILP (sequence))
- XSETCDR (XCAR (args), Fcons (sequence, result));
-
- UNGCPRO;
-}
-
-
/* This function can GC because get_keyelt can. */
-static Lisp_Object
-where_is_internal_1 (binding, key, definition, noindirect, this, last,
- nomenus, last_is_meta)
- Lisp_Object binding, key, definition, noindirect, this, last;
- int nomenus, last_is_meta;
+static void
+where_is_internal_1 (key, binding, args, data)
+ Lisp_Object key, binding, args;
+ void *data;
{
+ struct where_is_internal_data *d = data; /* Cast! */
+ Lisp_Object definition = d->definition;
+ Lisp_Object noindirect = d->noindirect;
+ Lisp_Object this = d->this;
+ Lisp_Object last = d->last;
+ int last_is_meta = d->last_is_meta;
Lisp_Object sequence;
/* Search through indirections unless that's not wanted. */
|| EQ (binding, definition)
|| (CONSP (definition) && !NILP (Fequal (binding, definition)))))
/* Doesn't match. */
- return Qnil;
+ return;
/* We have found a match. Construct the key sequence where we found it. */
if (INTEGERP (key) && last_is_meta)
{
Lisp_Object sequences = Fgethash (binding, where_is_cache, Qnil);
Fputhash (binding, Fcons (sequence, sequences), where_is_cache);
- return Qnil;
}
else
- return sequence;
+ d->sequences = Fcons (sequence, d->sequences);
}
\f
/* describe-bindings - summarizing all the bindings in a set of keymaps. */
You type Translation\n\
-------- -----------\n";
+ CHECK_BUFFER (buffer);
+
shadow = Qnil;
GCPRO1 (shadow);
outbuf = Fcurrent_buffer ();
/* Report on alternates for keys. */
- if (STRINGP (Vkeyboard_translate_table) && !NILP (prefix))
+ if (STRINGP (current_kboard->Vkeyboard_translate_table) && !NILP (prefix))
{
int c;
- const unsigned char *translate = SDATA (Vkeyboard_translate_table);
- int translate_len = SCHARS (Vkeyboard_translate_table);
+ const unsigned char *translate = SDATA (current_kboard->Vkeyboard_translate_table);
+ int translate_len = SCHARS (current_kboard->Vkeyboard_translate_table);
for (c = 0; c < translate_len; c++)
if (translate[c] != c)
insert ("\n", 1);
/* Insert calls signal_after_change which may GC. */
- translate = SDATA (Vkeyboard_translate_table);
+ translate = SDATA (current_kboard->Vkeyboard_translate_table);
}
insert ("\n", 1);
}
- if (!NILP (Vkey_translation_map))
- describe_map_tree (Vkey_translation_map, 0, Qnil, prefix,
+ if (!NILP (current_kboard->Vlocal_key_translation_map))
+ describe_map_tree (current_kboard->Vlocal_key_translation_map, 0, Qnil, prefix,
"Key translations", nomenu, 1, 0, 0);
"\f\nGlobal Bindings", nomenu, 0, 1, 0);
/* Print the function-key-map translations under this prefix. */
- if (!NILP (Vfunction_key_map))
- describe_map_tree (Vfunction_key_map, 0, Qnil, prefix,
+ if (!NILP (current_kboard->Vlocal_function_key_map))
+ describe_map_tree (current_kboard->Vlocal_function_key_map, 0, Qnil, prefix,
"\f\nFunction key map translations", nomenu, 1, 0, 0);
UNGCPRO;
tem = shadow_lookup (shadow, kludge, Qt);
if (!NILP (tem))
{
+ /* If both bindings are keymaps, this key is a prefix key,
+ so don't say it is shadowed. */
+ if (KEYMAPP (definition) && KEYMAPP (tem))
+ ;
/* Avoid generating duplicate entries if the
- shadowed binding has the same definition. */
- if (mention_shadow && !EQ (tem, definition))
+ shadowed binding has the same definition. */
+ else if (mention_shadow && !EQ (tem, definition))
this_shadowed = 1;
else
continue;
`minor-mode-map-alist' and `minor-mode-overriding-map-alist'. */);
Vemulation_mode_map_alists = Qnil;
-
- DEFVAR_LISP ("function-key-map", &Vfunction_key_map,
- doc: /* Keymap that translates key sequences to key sequences during input.
-This is used mainly for mapping ASCII function key sequences into
-real Emacs function key events (symbols).
-
-The `read-key-sequence' function replaces any subsequence bound by
-`function-key-map' with its binding. More precisely, when the active
-keymaps have no binding for the current key sequence but
-`function-key-map' binds a suffix of the sequence to a vector or string,
-`read-key-sequence' replaces the matching suffix with its binding, and
-continues with the new sequence.
-
-If the binding is a function, it is called with one argument (the prompt)
-and its return value (a key sequence) is used.
-
-The events that come from bindings in `function-key-map' are not
-themselves looked up in `function-key-map'.
-
-For example, suppose `function-key-map' binds `ESC O P' to [f1].
-Typing `ESC O P' to `read-key-sequence' would return [f1]. Typing
-`C-x ESC O P' would return [?\\C-x f1]. If [f1] were a prefix
-key, typing `ESC O P x' would return [f1 x]. */);
- Vfunction_key_map = Fmake_sparse_keymap (Qnil);
-
- DEFVAR_LISP ("key-translation-map", &Vkey_translation_map,
- doc: /* Keymap of key translations that can override keymaps.
-This keymap works like `function-key-map', but comes after that,
-and its non-prefix bindings override ordinary bindings. */);
- Vkey_translation_map = Qnil;
-
staticpro (&Vmouse_events);
Vmouse_events = Fcons (intern ("menu-bar"),
Fcons (intern ("tool-bar"),