/* Keymap mapping ASCII function key sequences onto their preferred forms. */
extern Lisp_Object Vfunction_key_map;
+/* Keymap mapping ASCII function key sequences onto their preferred forms. */
+Lisp_Object Vkey_translation_map;
+
/* Non-nil means deactivate the mark at end of this command. */
Lisp_Object Vdeactivate_mark;
static int read_avail_input ();
static void get_input_pending ();
static Lisp_Object read_char_menu_prompt ();
+static Lisp_Object make_lispy_event ();
+static Lisp_Object make_lispy_movement ();
+static Lisp_Object modify_event_symbol ();
+static Lisp_Object make_lispy_switch_frame ();
/* > 0 if we are to echo keystrokes. */
static int echo_keystrokes;
no_redisplay = 0;
this_command_key_count = 0;
+ /* Make sure this hook runs after commands that get errors and
+ throw to top level. */
+ if (!NILP (Vpost_command_hook))
+ call1 (Vrun_hooks, Qpost_command_hook);
+
while (1)
{
/* Install chars successfully executed in kbd macro. */
}
\f
-/* Low level keyboard/mouse input.
- kbd_buffer_store_event places events in kbd_buffer, and
- kbd_buffer_get_event retrieves them.
- mouse_moved indicates when the mouse has moved again, and
- *mouse_position_hook provides the mouse position. */
-
-/* Set this for debugging, to have a way to get out */
-int stop_character;
-
-extern int frame_garbaged;
-
-/* Return true iff there are any events in the queue that read-char
- would return. If this returns false, a read-char would block. */
-static int
-readable_events ()
-{
- return ! EVENT_QUEUES_EMPTY;
-}
-
-
/* Restore mouse tracking enablement. See Ftrack_mouse for the only use
of this function. */
static Lisp_Object
val = Fprogn (args);
return unbind_to (count, val);
}
+\f
+/* Low level keyboard/mouse input.
+ kbd_buffer_store_event places events in kbd_buffer, and
+ kbd_buffer_get_event retrieves them.
+ mouse_moved indicates when the mouse has moved again, and
+ *mouse_position_hook provides the mouse position. */
+
+/* Return true iff there are any events in the queue that read-char
+ would return. If this returns false, a read-char would block. */
+static int
+readable_events ()
+{
+ return ! EVENT_QUEUES_EMPTY;
+}
+
+/* Set this for debugging, to have a way to get out */
+int stop_character;
/* Store an event obtained at interrupt level into kbd_buffer, fifo */
kbd_store_ptr++;
}
}
-
-static Lisp_Object make_lispy_event ();
-static Lisp_Object make_lispy_movement ();
-static Lisp_Object modify_event_symbol ();
-static Lisp_Object make_lispy_switch_frame ();
+\f
+/* Read one event from the event buffer, waiting if necessary.
+ The value is a Lisp object representing the event.
+ The value is nil for an event that should be ignored,
+ or that was handled here.
+ We always read and discard one event. */
static Lisp_Object
kbd_buffer_get_event ()
return obj;
}
- retry:
/* Wait until there is input available. */
for (;;)
{
obj = Qnil;
/* These two kinds of events get special handling
- and don't actually appear to the command loop. */
+ and don't actually appear to the command loop.
+ We return nil for them. */
if (event->kind == selection_request_event)
{
#ifdef HAVE_X11
abort ();
#endif
}
+ /* Just discard these, by returning nil.
+ (They shouldn't be found in the buffer,
+ but on some machines it appears they do show up.) */
+ else if (event->kind == no_event)
+ kbd_fetch_ptr = event + 1;
/* If this event is on a different frame, return a switch-frame this
time, and leave the event in the queue for next time. */
}
}
}
+ /* Try generating a mouse motion event. */
else if (do_mouse_tracking && mouse_moved)
{
FRAME_PTR f = 0;
something for us to read! */
abort ();
-#if 0
- /* If something gave back nil as the Lispy event,
- it means the event was discarded, so try again. */
- if (NILP (obj))
- goto retry;
-#endif
-
input_pending = readable_events ();
#ifdef MULTI_FRAME
return (obj);
}
-
-/* Process any events that are not user-visible. */
+\f
+/* Process any events that are not user-visible,
+ then return, without reading any user-visible events. */
void
swallow_events ()
get_input_pending (&input_pending);
}
-
+\f
/* Caches for modify_event_symbol. */
static Lisp_Object func_key_syms;
static Lisp_Object mouse_syms;
int fkey_start = 0, fkey_end = 0;
Lisp_Object fkey_map;
+ /* Likewise, for key_translation_map. */
+ int keytran_start = 0, keytran_end = 0;
+ Lisp_Object keytran_map;
+
/* If we receive a ``switch-frame'' event in the middle of a key sequence,
we put it off for later. While we're reading, we keep the event here. */
Lisp_Object delayed_switch_frame;
delayed_switch_frame = Qnil;
fkey_map = Vfunction_key_map;
+ keytran_map = Vkey_translation_map;
- /* If there is no function key map, turn off function key scanning. */
+ /* If there is no function-key-map, turn off function key scanning. */
if (NILP (Fkeymapp (Vfunction_key_map)))
fkey_start = fkey_end = bufsize + 1;
+ /* If there is no key-translation-map, turn off scanning. */
+ if (NILP (Fkeymapp (Vkey_translation_map)))
+ keytran_start = keytran_end = bufsize + 1;
+
if (INTERACTIVE)
{
if (prompt)
|| (first_binding >= nmaps
&& fkey_start < t
/* mock input is never part of a function key's sequence. */
- && mock_input <= fkey_start))
+ && mock_input <= fkey_start)
+ || (first_binding >= nmaps
+ && keytran_start < t
+ /* mock input is never part of a function key's sequence. */
+ && mock_input <= keytran_start))
{
Lisp_Object key;
int used_mouse_menu = 0;
}
}
}
+
+ /* Look for this sequence in key-translation-map. */
+ {
+ Lisp_Object keytran_next;
+
+ /* Scan from keytran_end until we find a bound suffix. */
+ while (keytran_end < t)
+ {
+ Lisp_Object key;
+
+ key = keybuf[keytran_end++];
+ /* Look up meta-characters by prefixing them
+ with meta_prefix_char. I hate this. */
+ if (XTYPE (key) == Lisp_Int && XINT (key) & meta_modifier)
+ {
+ keytran_next
+ = get_keymap_1
+ (get_keyelt
+ (access_keymap (keytran_map, meta_prefix_char, 1, 0)),
+ 0, 1);
+ XFASTINT (key) = XFASTINT (key) & ~meta_modifier;
+ }
+ else
+ keytran_next = keytran_map;
+
+ keytran_next
+ = get_keyelt (access_keymap (keytran_next, key, 1, 0));
+
+ /* If keybuf[keytran_start..keytran_end] is bound in the
+ function key map and it's a suffix of the current
+ sequence (i.e. keytran_end == t), replace it with
+ the binding and restart with keytran_start at the end. */
+ if ((VECTORP (keytran_next) || STRINGP (keytran_next))
+ && keytran_end == t)
+ {
+ int len = Flength (keytran_next);
+
+ t = keytran_start + len;
+ if (t >= bufsize)
+ error ("key sequence too long");
+
+ if (VECTORP (keytran_next))
+ bcopy (XVECTOR (keytran_next)->contents,
+ keybuf + keytran_start,
+ (t - keytran_start) * sizeof (keybuf[0]));
+ else if (STRINGP (keytran_next))
+ {
+ int i;
+
+ for (i = 0; i < len; i++)
+ XFASTINT (keybuf[keytran_start + i])
+ = XSTRING (keytran_next)->data[i];
+ }
+
+ mock_input = t;
+ keytran_start = keytran_end = t;
+ keytran_map = Vkey_translation_map;
+
+ goto replay_sequence;
+ }
+
+ keytran_map = get_keymap_1 (keytran_next, 0, 1);
+
+ /* If we no longer have a bound suffix, try a new positions for
+ keytran_start. */
+ if (NILP (keytran_map))
+ {
+ keytran_end = ++keytran_start;
+ keytran_map = Vkey_translation_map;
+ }
+ }
+ }
}
read_key_sequence_cmd = (first_binding < nmaps
return t;
}
+#if 0 /* This doc string is too long for some compilers.
+ This commented-out definition serves for DOC. */
DEFUN ("read-key-sequence", Fread_key_sequence, Sread_key_sequence, 1, 2, 0,
"Read a sequence of keystrokes and return as a string or vector.\n\
The sequence is sufficient to specify a non-prefix command in the\n\
`read-key-sequence' checks `function-key-map' for function key\n\
sequences, where they wouldn't conflict with ordinary bindings. See\n\
`function-key-map' for more details.")
+ (prompt, continue_echo)
+#endif
+
+DEFUN ("read-key-sequence", Fread_key_sequence, Sread_key_sequence, 1, 2, 0,
+ 0)
(prompt, continue_echo)
Lisp_Object prompt, continue_echo;
{
If string is of length N, character codes N and up are untranslated.");
Vkeyboard_translate_table = Qnil;
+ DEFVAR_LISP ("key-translation-map", &Vkey_translation_map,
+ "Keymap of key translations that can override keymaps.\n\
+This keymap works like `function-key-map', but comes after that,\n\
+and applies even for keys that have ordinary bindings.");
+ Vkey_translation_map = Qnil;
+
DEFVAR_BOOL ("menu-prompting", &menu_prompting,
"Non-nil means prompt with menus when appropriate.\n\
This is done when reading from a keymap that has a prompt string,\n\
DEFVAR_LISP ("menu-bar-final-items", &Vmenu_bar_final_items,
"List of menu bar items to move to the end of the menu bar.\n\
-The elements of the listare event types that may have menu bar bindings.");
+The elements of the list are event types that may have menu bar bindings.");
Vmenu_bar_final_items = Qnil;
}