Lisp_Object this_command_keys;
int this_command_key_count;
+/* This vector is used as a buffer to record the events that were actually read
+ by read_key_sequence. */
+Lisp_Object raw_keybuf;
+int raw_keybuf_count;
+
+#define GROW_RAW_KEYBUF \
+if (raw_keybuf_count == XVECTOR (raw_keybuf)->size) \
+ { \
+ int newsize = 2 * XVECTOR (raw_keybuf)->size; \
+ Lisp_Object new; \
+ new = Fmake_vector (make_number (newsize), Qnil); \
+ bcopy (XVECTOR (raw_keybuf)->contents, XVECTOR (new)->contents, \
+ raw_keybuf_count * sizeof (Lisp_Object)); \
+ raw_keybuf = new; \
+ }
+
/* Number of elements of this_command_keys
that precede this key sequence. */
int this_single_command_key_start;
/* If not Qnil, a list of objects to be read as subsequent command input. */
Lisp_Object Vunread_command_events;
+/* If not Qnil, a list of objects to be read as subsequent command input
+ including input method processing. */
+Lisp_Object Vunread_input_method_events;
+
+/* If not Qnil, a list of objects to be read as subsequent command input
+ but NOT including input method processing. */
+Lisp_Object Vunread_post_input_method_events;
+
/* If not -1, an event to be read as subsequent command input. */
int unread_command_char;
/* The command being executed by the command loop.
Commands may set this, and the value set will be copied into
current_kboard->Vlast_command instead of the actual command. */
-Lisp_Object this_command;
+Lisp_Object Vthis_command;
+
+/* This is like Vthis_command, except that commands never set it. */
+Lisp_Object real_this_command;
/* The value of point when the last command was executed. */
int last_point_position;
This one takes precedence over ordinary definitions. */
extern Lisp_Object Vkey_translation_map;
+/* If non-nil, this implements the current input method. */
+Lisp_Object Vinput_method_function;
+Lisp_Object Qinput_method_function;
+
+/* When we call Vinput_method_function,
+ this holds the echo area message that was just erased. */
+Lisp_Object Vinput_method_previous_message;
+
/* Non-nil means deactivate the mark at end of this command. */
Lisp_Object Vdeactivate_mark;
Lisp_Object Vdeferred_action_function;
Lisp_Object Qdeferred_action_function;
+Lisp_Object Qinput_method_exit_on_first_char;
+Lisp_Object Qinput_method_use_echo_area;
+
/* File in which we write all commands we read. */
FILE *dribble;
Vexecuting_macro = Qnil;
executing_macro = Qnil;
current_kboard->Vprefix_arg = Qnil;
+ current_kboard->Vlast_prefix_arg = Qnil;
cancel_echoing ();
/* Avoid unquittable loop if data contains a circular list. */
{
if (command_loop_level > 0 || minibuf_level > 0)
{
- return internal_catch (Qexit, command_loop_2, Qnil);
+ Lisp_Object val;
+ val = internal_catch (Qexit, command_loop_2, Qnil);
+ executing_macro = Qnil;
+ return val;
}
else
while (1)
{
internal_catch (Qtop_level, top_level_1, Qnil);
internal_catch (Qtop_level, command_loop_2, Qnil);
+ executing_macro = Qnil;
/* End of file in -batch run causes exit here. */
if (noninteractive)
#endif
current_kboard->Vprefix_arg = Qnil;
+ current_kboard->Vlast_prefix_arg = Qnil;
Vdeactivate_mark = Qnil;
waiting_for_input = 0;
cancel_echoing ();
if (!NILP (Vpost_command_idle_hook) && !NILP (Vrun_hooks))
{
if (NILP (Vunread_command_events)
+ && NILP (Vunread_input_method_events)
+ && NILP (Vunread_post_input_method_events)
&& NILP (Vexecuting_macro)
&& !NILP (sit_for (0, post_command_idle_delay, 0, 1, 1)))
safe_run_hooks (Qpost_command_idle_hook);
}
/* Do this after running Vpost_command_hook, for consistency. */
- current_kboard->Vlast_command = this_command;
+ current_kboard->Vlast_command = Vthis_command;
+ current_kboard->Vreal_last_command = real_this_command;
while (1)
{
+ if (! FRAME_LIVE_P (selected_frame))
+ Fkill_emacs (Qnil);
+
/* Make sure the current window's buffer is selected. */
if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
set_buffer_internal (XBUFFER (XWINDOW (selected_window)->buffer));
before_command_key_count = this_command_key_count;
before_command_echo_length = echo_length ();
- this_command = Qnil;
+ Vthis_command = Qnil;
+ real_this_command = Qnil;
/* Read next key sequence; i gets its length. */
i = read_key_sequence (keybuf, sizeof keybuf / sizeof keybuf[0],
Qnil, 0, 1, 1);
/* A filter may have run while we were reading the input. */
+ if (! FRAME_LIVE_P (selected_frame))
+ Fkill_emacs (Qnil);
if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
set_buffer_internal (XBUFFER (XWINDOW (selected_window)->buffer));
/* Execute the command. */
- this_command = cmd;
+ Vthis_command = cmd;
+ real_this_command = cmd;
/* Note that the value cell will never directly contain nil
if the symbol is a local variable. */
if (!NILP (Vpre_command_hook) && !NILP (Vrun_hooks))
safe_run_hooks (Qpre_command_hook);
-
- if (NILP (this_command))
+
+ if (NILP (Vthis_command))
{
/* nil means key is undefined. */
bitch_at_user ();
{
if (NILP (current_kboard->Vprefix_arg) && ! no_direct)
{
+ /* In case we jump to directly_done. */
+ Vcurrent_prefix_arg = current_kboard->Vprefix_arg;
+
/* Recognize some common commands in common situations and
do them directly. */
- if (EQ (this_command, Qforward_char) && PT < ZV)
+ if (EQ (Vthis_command, Qforward_char) && PT < ZV)
{
struct Lisp_Char_Table *dp
= window_display_table (XWINDOW (selected_window));
- lose = FETCH_BYTE (PT_BYTE);
+ lose = FETCH_CHAR (PT_BYTE);
SET_PT (PT + 1);
if ((dp
? (VECTORP (DISP_CHAR_VECTOR (dp, lose))
no_redisplay = direct_output_forward_char (1);
goto directly_done;
}
- else if (EQ (this_command, Qbackward_char) && PT > BEGV)
+ else if (EQ (Vthis_command, Qbackward_char) && PT > BEGV)
{
struct Lisp_Char_Table *dp
= window_display_table (XWINDOW (selected_window));
SET_PT (PT - 1);
- lose = FETCH_BYTE (PT_BYTE);
+ lose = FETCH_CHAR (PT_BYTE);
if ((dp
? (VECTORP (DISP_CHAR_VECTOR (dp, lose))
? XVECTOR (DISP_CHAR_VECTOR (dp, lose))->size == 1
no_redisplay = direct_output_forward_char (-1);
goto directly_done;
}
- else if (EQ (this_command, Qself_insert_command)
+ else if (EQ (Vthis_command, Qself_insert_command)
/* Try this optimization only on ascii keystrokes. */
&& INTEGERP (last_command_char))
{
nonundocount = 0;
if (NILP (current_kboard->Vprefix_arg))
Fundo_boundary ();
- Fcommand_execute (this_command, Qnil, Qnil, Qnil);
-
+ Fcommand_execute (Vthis_command, Qnil, Qnil, Qnil);
}
directly_done: ;
+ current_kboard->Vlast_prefix_arg = Vcurrent_prefix_arg;
/* Note that the value cell will never directly contain nil
if the symbol is a local variable. */
if (!NILP (Vpost_command_idle_hook) && !NILP (Vrun_hooks))
{
if (NILP (Vunread_command_events)
+ && NILP (Vunread_input_method_events)
+ && NILP (Vunread_post_input_method_events)
&& NILP (Vexecuting_macro)
&& !NILP (sit_for (0, post_command_idle_delay, 0, 1, 1)))
safe_run_hooks (Qpost_command_idle_hook);
then the above doesn't apply. */
if (NILP (current_kboard->Vprefix_arg) || CONSP (last_command_char))
{
- current_kboard->Vlast_command = this_command;
+ current_kboard->Vlast_command = Vthis_command;
+ current_kboard->Vreal_last_command = real_this_command;
cancel_echoing ();
this_command_key_count = 0;
this_single_command_key_start = 0;
MAPS is an array of keymaps; NMAPS is the length of MAPS.
PREV_EVENT is the previous input event, or nil if we are reading
- the first event of a key sequence.
+ the first event of a key sequence (or not reading a key sequence).
+ If PREV_EVENT is t, that is a "magic" value that says
+ not to run input methods, but in other respects to act as if
+ not reading a key sequence.
If USED_MOUSE_MENU is non-null, then we set *USED_MOUSE_MENU to 1
if we used a mouse menu to read the input, or zero otherwise. If
jmp_buf save_jump;
int key_already_recorded = 0;
Lisp_Object tem, save;
+ Lisp_Object echo_area_message;
Lisp_Object also_record;
- struct gcpro gcpro1;
+ int reread;
+ struct gcpro gcpro1, gcpro2;
also_record = Qnil;
before_command_key_count = this_command_key_count;
before_command_echo_length = echo_length ();
c = Qnil;
+ echo_area_message = Qnil;
- GCPRO1 (c);
+ GCPRO2 (c, echo_area_message);
retry:
- if (CONSP (Vunread_command_events))
+ reread = 0;
+ if (CONSP (Vunread_post_input_method_events))
{
- c = XCONS (Vunread_command_events)->car;
- Vunread_command_events = XCONS (Vunread_command_events)->cdr;
+ c = XCONS (Vunread_post_input_method_events)->car;
+ Vunread_post_input_method_events
+ = XCONS (Vunread_post_input_method_events)->cdr;
/* Undo what read_char_x_menu_prompt did when it unread
additional keys returned by Fx_popup_menu. */
&& NILP (XCONS (c)->cdr))
c = XCONS (c)->car;
- if (this_command_key_count == 0)
- goto reread_first;
- else
- goto reread;
+ reread = 1;
+ goto reread_first;
}
if (unread_command_char != -1)
XSETINT (c, unread_command_char);
unread_command_char = -1;
- if (this_command_key_count == 0)
- goto reread_first;
- else
- goto reread;
+ reread = 1;
+ goto reread_first;
+ }
+
+ if (CONSP (Vunread_command_events))
+ {
+ c = XCONS (Vunread_command_events)->car;
+ Vunread_command_events = XCONS (Vunread_command_events)->cdr;
+
+ /* Undo what read_char_x_menu_prompt did when it unread
+ additional keys returned by Fx_popup_menu. */
+ if (CONSP (c)
+ && (SYMBOLP (XCONS (c)->car) || INTEGERP (XCONS (c)->car))
+ && NILP (XCONS (c)->cdr))
+ c = XCONS (c)->car;
+
+ reread = 1;
+ goto reread_for_input_method;
+ }
+
+ if (CONSP (Vunread_input_method_events))
+ {
+ c = XCONS (Vunread_input_method_events)->car;
+ Vunread_input_method_events = XCONS (Vunread_input_method_events)->cdr;
+
+ /* Undo what read_char_x_menu_prompt did when it unread
+ additional keys returned by Fx_popup_menu. */
+ if (CONSP (c)
+ && (SYMBOLP (XCONS (c)->car) || INTEGERP (XCONS (c)->car))
+ && NILP (XCONS (c)->cdr))
+ c = XCONS (c)->car;
+ reread = 1;
+ goto reread_for_input_method;
}
/* If there is no function key translated before
unread_switch_frame = Qnil;
/* This event should make it into this_command_keys, and get echoed
- again, so we go to reread_first, rather than reread. */
+ again, so we do not set `reread'. */
goto reread_first;
}
goto retry;
}
- /* Wipe the echo area. */
- if (echo_area_glyphs)
- safe_run_hooks (Qecho_area_clear_hook);
- echo_area_glyphs = 0;
-
/* Handle things that only apply to characters. */
if (INTEGERP (c))
{
}
}
+ /* Store these characters into recent_keys, the dribble file if any,
+ and the keyboard macro being defined, if any. */
record_char (c);
if (! NILP (also_record))
record_char (also_record);
+ /* Wipe the echo area.
+ But first, if we are about to use an input method,
+ save the echo area contents for it to refer to. */
+ if (INTEGERP (c)
+ && ! NILP (Vinput_method_function)
+ && (unsigned) XINT (c) >= ' '
+ && (unsigned) XINT (c) < 127)
+ Vinput_method_previous_message = echo_area_message = Fcurrent_message ();
+
+ /* Now wipe the echo area. */
+ if (echo_area_glyphs)
+ safe_run_hooks (Qecho_area_clear_hook);
+ echo_area_glyphs = 0;
+
+ reread_for_input_method:
from_macro:
- reread_first:
+ /* Pass this to the input method, if appropriate. */
+ if (INTEGERP (c)
+ && ! NILP (Vinput_method_function)
+ /* Don't run the input method within a key sequence,
+ after the first event of the key sequence. */
+ && NILP (prev_event)
+ && (unsigned) XINT (c) >= ' '
+ && (unsigned) XINT (c) < 127)
+ {
+ Lisp_Object keys;
+ int key_count;
+ struct gcpro gcpro1;
+ int count = specpdl_ptr - specpdl;
+
+ /* Save the echo status. */
+ int saved_immediate_echo = current_kboard->immediate_echo;
+ char *saved_ok_to_echo = ok_to_echo_at_next_pause;
+ int saved_echo_after_prompt = current_kboard->echo_after_prompt;
+
+ if (before_command_restore_flag)
+ {
+ this_command_key_count = before_command_key_count_1;
+ if (this_command_key_count < this_single_command_key_start)
+ this_single_command_key_start = this_command_key_count;
+ echo_truncate (before_command_echo_length_1);
+ before_command_restore_flag = 0;
+ }
- before_command_key_count = this_command_key_count;
- before_command_echo_length = echo_length ();
+ /* Save the this_command_keys status. */
+ key_count = this_command_key_count;
- /* Don't echo mouse motion events. */
- if (echo_keystrokes
- && ! (EVENT_HAS_PARAMETERS (c)
- && EQ (EVENT_HEAD_KIND (EVENT_HEAD (c)), Qmouse_movement)))
+ if (key_count > 0)
+ keys = Fcopy_sequence (this_command_keys);
+ else
+ keys = Qnil;
+ GCPRO1 (keys);
+
+ /* Clear out this_command_keys. */
+ this_command_key_count = 0;
+
+ /* Now wipe the echo area. */
+ if (echo_area_glyphs)
+ safe_run_hooks (Qecho_area_clear_hook);
+ echo_area_glyphs = 0;
+ echo_truncate (0);
+
+ /* If we are not reading a key sequence,
+ never use the echo area. */
+ if (maps == 0)
+ {
+ specbind (Qinput_method_exit_on_first_char, Qt);
+ specbind (Qinput_method_use_echo_area, Qt);
+ }
+
+ /* Call the input method. */
+ tem = call1 (Vinput_method_function, c);
+
+ tem = unbind_to (count, tem);
+
+ /* Restore the saved echoing state
+ and this_command_keys state. */
+ this_command_key_count = key_count;
+ if (key_count > 0)
+ this_command_keys = keys;
+
+ cancel_echoing ();
+ ok_to_echo_at_next_pause = saved_ok_to_echo;
+ current_kboard->echo_after_prompt = saved_echo_after_prompt;
+ if (saved_immediate_echo)
+ echo_now ();
+
+ UNGCPRO;
+
+ /* The input method can return no events. */
+ if (! CONSP (tem))
+ {
+ /* Bring back the previous message, if any. */
+ if (! NILP (echo_area_message))
+ message_with_string ("%s", echo_area_message, 0);
+ goto retry;
+ }
+ /* It returned one event or more. */
+ c = XCONS (tem)->car;
+ Vunread_post_input_method_events
+ = nconc2 (XCONS (tem)->cdr, Vunread_post_input_method_events);
+ }
+
+ reread_first:
+
+ if (this_command_key_count == 0 || ! reread)
{
- echo_char (c);
+ before_command_key_count = this_command_key_count;
+ before_command_echo_length = echo_length ();
+
+ /* Don't echo mouse motion events. */
+ if (echo_keystrokes
+ && ! (EVENT_HAS_PARAMETERS (c)
+ && EQ (EVENT_HEAD_KIND (EVENT_HEAD (c)), Qmouse_movement)))
+ {
+ echo_char (c);
+ if (! NILP (also_record))
+ echo_char (also_record);
+ /* Once we reread a character, echoing can happen
+ the next time we pause to read a new one. */
+ ok_to_echo_at_next_pause = echo_area_glyphs;
+ }
+
+ /* Record this character as part of the current key. */
+ add_command_key (c);
if (! NILP (also_record))
- echo_char (also_record);
- /* Once we reread a character, echoing can happen
- the next time we pause to read a new one. */
- ok_to_echo_at_next_pause = echo_area_glyphs;
+ add_command_key (also_record);
}
- /* Record this character as part of the current key. */
- add_command_key (c);
- if (! NILP (also_record))
- add_command_key (also_record);
-
- /* Re-reading in the middle of a command */
- reread:
last_input_char = c;
num_input_events++;
{
/* X Keysym value */
- 0, 0, 0, 0, 0, 0, 0, 0, /* 0xff00 */
- "backspace",
- "tab",
- "linefeed",
- "clear",
- 0,
- "return",
- 0, 0,
- 0, 0, 0, /* 0xff10 */
- "pause",
- 0, 0, 0, 0, 0, 0, 0,
- "escape",
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0xff00...0f */
+ "backspace", "tab", "linefeed", "clear",
+ 0, "return", 0, 0,
+ 0, 0, 0, "pause", /* 0xff10...1f */
+ 0, 0, 0, 0, 0, 0, 0, "escape",
0, 0, 0, 0,
- 0, "kanji", "muhenkan",
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xff20...2f */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xff30...3f */
+ 0, "kanji", "muhenkan", "henkan", /* 0xff20...2f */
+ "romaji", "hiragana", "katakana", "hiragana-katakana",
+ "zenkaku", "hankaku", "zenkaku-hankaku", "touroku",
+ "massyo", "kana-lock", "kana-shift", "eisu-shift",
+ "eisu-toggle", /* 0xff30...3f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xff40...4f */
- "home", /* 0xff50 */ /* IsCursorKey */
- "left",
- "up",
- "right",
- "down",
- "prior",
- "next",
- "end",
- "begin",
- 0, /* 0xff59 */
- 0, 0, 0, 0, 0, 0,
+ "home", "left", "up", "right", /* 0xff50 */ /* IsCursorKey */
+ "down", "prior", "next", "end",
+ "begin", 0, 0, 0, 0, 0, 0, 0,
"select", /* 0xff60 */ /* IsMiscFunctionKey */
"print",
"execute",
"help",
"break", /* 0xff6b */
- 0, 0, 0, 0, 0, 0, 0, 0, "backtab", 0,
- 0, /* 0xff76 */
- 0, 0, 0, 0, 0, 0, 0, 0, "kp-numlock", /* 0xff7f */
+ 0, 0, 0, 0,
+ 0, 0, 0, 0, "backtab", 0, 0, 0, /* 0xff70... */
+ 0, 0, 0, 0, 0, 0, 0, "kp-numlock", /* 0xff78... */
"kp-space", /* 0xff80 */ /* IsKeypadKey */
0, 0, 0, 0, 0, 0, 0, 0,
"kp-tab", /* 0xff89 */
menu_item_eval_property (sexpr)
Lisp_Object sexpr;
{
+ int count = specpdl_ptr - specpdl;
Lisp_Object val;
+ specbind (Qinhibit_redisplay, Qt);
val = internal_condition_case_1 (Feval, sexpr, Qerror,
menu_item_eval_property_1);
- return val;
+ return unbind_to (count, val);
}
/* This function parses a menu item and leaves the result in the
int notreal, inmenubar;
{
Lisp_Object def, tem, item_string, start;
- Lisp_Object cachelist = Qnil;
- Lisp_Object filter = Qnil;
- Lisp_Object keyhint = Qnil;
+ Lisp_Object cachelist;
+ Lisp_Object filter;
+ Lisp_Object keyhint;
int i;
int newcache = 0;
+ cachelist = Qnil;
+ filter = Qnil;
+ keyhint = Qnil;
+
if (!CONSP (item))
return 0;
def = XVECTOR (item_properties)->contents[ITEM_PROPERTY_DEF];
if (!NILP (filter))
{
- def = menu_item_eval_property (Fcons (XCONS (filter)->car,
- Fcons (def, Qnil)));
+ def = menu_item_eval_property (list2 (XCONS (filter)->car,
+ list2 (Qquote, def)));
+
XVECTOR (item_properties)->contents[ITEM_PROPERTY_DEF] = def;
}
/* 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);
+ /* For a subkeymap, just record its details and exit. */
if (!NILP (tem))
{
XVECTOR (item_properties)->contents[ITEM_PROPERTY_MAP] = tem;
XVECTOR (item_properties)->contents[ITEM_PROPERTY_DEF] = tem;
return 1;
}
- else if (inmenubar > 0)
- return 0; /* Entries in menu bar must be submenus. */
+ /* At the top level in the menu bar, do likewise for commands also.
+ The menu bar does not display equivalent key bindings anyway.
+ ITEM_PROPERTY_DEF is already set up properly. */
+ if (inmenubar > 0)
+ return 1;
/* This is a command. See if there is an equivalent key binding. */
if (NILP (cachelist))
int junk;
+ raw_keybuf_count = 0;
+
last_nonmenu_event = Qnil;
delayed_switch_frame = Qnil;
/* read_char returns t when it shows a menu and the user rejects it.
Just return -1. */
if (EQ (key, Qt))
- return -1;
+ {
+ unbind_to (count, Qnil);
+ return -1;
+ }
/* read_char returns -1 at the end of a macro.
Emacs 18 handles this by returning immediately with a
This is to be more consistent with the behavior
of the command_loop_1. */
if (fix_current_buffer)
- if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
- Fset_buffer (XWINDOW (selected_window)->buffer);
+ {
+ if (! FRAME_LIVE_P (selected_frame))
+ Fkill_emacs (Qnil);
+ if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
+ Fset_buffer (XWINDOW (selected_window)->buffer);
+ }
orig_local_map = get_local_map (PT, current_buffer);
goto replay_sequence;
replay to get the right keymap. */
if (XINT (key) == quit_char && current_buffer != starting_buffer)
{
+ GROW_RAW_KEYBUF;
+ XVECTOR (raw_keybuf)->contents[raw_keybuf_count++] = key;
keybuf[t++] = key;
mock_input = t;
Vquit_flag = Qnil;
}
Vquit_flag = Qnil;
+
+ if (EVENT_HAS_PARAMETERS (key)
+ && EQ (EVENT_HEAD_KIND (EVENT_HEAD (key)), Qswitch_frame))
+ {
+ /* If we're at the beginning of a key sequence, and the caller
+ says it's okay, go ahead and return this event. If we're
+ in the midst of a key sequence, delay it until the end. */
+ if (t > 0 || !can_return_switch_frame)
+ {
+ delayed_switch_frame = key;
+ goto replay_key;
+ }
+ }
+
+ GROW_RAW_KEYBUF;
+ XVECTOR (raw_keybuf)->contents[raw_keybuf_count++] = key;
}
/* Clicks in non-text areas get prefixed by the symbol
&& BUFFERP (XWINDOW (window)->buffer)
&& XBUFFER (XWINDOW (window)->buffer) != current_buffer)
{
+ XVECTOR (raw_keybuf)->contents[raw_keybuf_count++] = key;
keybuf[t] = key;
mock_input = t + 1;
emacsclient). */
record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
+ if (! FRAME_LIVE_P (selected_frame))
+ Fkill_emacs (Qnil);
set_buffer_internal (XBUFFER (XWINDOW (window)->buffer));
orig_local_map = get_local_map (PT, current_buffer);
goto replay_sequence;
goto replay_key;
}
}
- else if (EQ (kind, Qswitch_frame))
- {
- /* If we're at the beginning of a key sequence, and the caller
- says it's okay, go ahead and return this event. If we're
- in the midst of a key sequence, delay it until the end. */
- if (t > 0 || !can_return_switch_frame)
- {
- delayed_switch_frame = key;
- goto replay_key;
- }
- }
else if (CONSP (XCONS (key)->cdr)
&& CONSP (EVENT_START (key))
&& CONSP (XCONS (EVENT_START (key))->cdr))
add_command_key (keybuf[t]);
}
+
+
return t;
}
\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, dont_downcase_last, can_return_switch_frame)
+`function-key-map' for more details.\n\
+\n\
+The optional fifth argument COMMAND-LOOP, if non-nil, means\n\
+that this key sequence is being read by something that will\n\
+read commands one after another. It should be nil if the caller\n\
+will read just one key sequence.")
+ (prompt, continue_echo, dont_downcase_last, can_return_switch_frame, command-loop)
#endif
-DEFUN ("read-key-sequence", Fread_key_sequence, Sread_key_sequence, 1, 4, 0,
+DEFUN ("read-key-sequence", Fread_key_sequence, Sread_key_sequence, 1, 5, 0,
0)
- (prompt, continue_echo, dont_downcase_last, can_return_switch_frame)
+ (prompt, continue_echo, dont_downcase_last, can_return_switch_frame,
+ command_loop)
Lisp_Object prompt, continue_echo, dont_downcase_last;
- Lisp_Object can_return_switch_frame;
+ Lisp_Object can_return_switch_frame, command_loop;
{
Lisp_Object keybuf[30];
register int i;
struct gcpro gcpro1, gcpro2;
+ int count = specpdl_ptr - specpdl;
if (!NILP (prompt))
CHECK_STRING (prompt, 0);
QUIT;
+ specbind (Qinput_method_exit_on_first_char,
+ (NILP (command_loop) ? Qt : Qnil));
+ specbind (Qinput_method_use_echo_area,
+ (NILP (command_loop) ? Qt : Qnil));
+
bzero (keybuf, sizeof keybuf);
GCPRO1 (keybuf[0]);
gcpro1.nvars = (sizeof keybuf/sizeof (keybuf[0]));
QUIT;
}
UNGCPRO;
- return make_event_array (i, keybuf);
+ return unbind_to (count, make_event_array (i, keybuf));
}
DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,
- Sread_key_sequence_vector, 1, 4, 0,
+ Sread_key_sequence_vector, 1, 5, 0,
"Like `read-key-sequence' but always return a vector.")
- (prompt, continue_echo, dont_downcase_last, can_return_switch_frame)
+ (prompt, continue_echo, dont_downcase_last, can_return_switch_frame,
+ command_loop)
Lisp_Object prompt, continue_echo, dont_downcase_last;
- Lisp_Object can_return_switch_frame;
+ Lisp_Object can_return_switch_frame, command_loop;
{
Lisp_Object keybuf[30];
register int i;
struct gcpro gcpro1, gcpro2;
+ int count = specpdl_ptr - specpdl;
if (!NILP (prompt))
CHECK_STRING (prompt, 0);
QUIT;
+ specbind (Qinput_method_exit_on_first_char,
+ (NILP (command_loop) ? Qt : Qnil));
+ specbind (Qinput_method_use_echo_area,
+ (NILP (command_loop) ? Qt : Qnil));
+
bzero (keybuf, sizeof keybuf);
GCPRO1 (keybuf[0]);
gcpro1.nvars = (sizeof keybuf/sizeof (keybuf[0]));
QUIT;
}
UNGCPRO;
- return Fvector (i, keybuf);
+ return unbind_to (count, Fvector (i, keybuf));
}
\f
DEFUN ("command-execute", Fcommand_execute, Scommand_execute, 1, 4, 0,
function = Fintern (function, Qnil);
current_kboard->Vprefix_arg = prefixarg;
- this_command = function;
+ Vthis_command = function;
+ real_this_command = function;
/* If enabled, show which key runs this command. */
if (!NILP (Vsuggest_key_bindings)
Qmouse_movement)))
{
/* But first wait, and skip the message if there is input. */
- if (!NILP (Fsit_for ((NUMBERP (Vsuggest_key_bindings)
- ? Vsuggest_key_bindings : make_number (2)),
- Qnil, Qnil))
+ int delay_time;
+ if (echo_area_glyphs != 0)
+ /* This command displayed something in the echo area;
+ so wait a few seconds, then display our suggestion message. */
+ delay_time = (NUMBERP (Vsuggest_key_bindings)
+ ? XINT (Vsuggest_key_bindings) : 2);
+ else
+ /* This command left the echo area empty,
+ so display our message immediately. */
+ delay_time = 0;
+
+ if (!NILP (Fsit_for (make_number (delay_time), Qnil, Qnil))
&& ! CONSP (Vunread_command_events))
{
Lisp_Object binding;
+ this_single_command_key_start));
}
+DEFUN ("this-single-command-raw-keys", Fthis_single_command_raw_keys,
+ Sthis_single_command_raw_keys, 0, 0, 0,
+ "Return the raw events that were read for this command.\n\
+Unlike `this-single-command-keys', this function's value\n\
+shows the events before all translations (except for input methods).\n\
+The value is always a vector.")
+ ()
+{
+ return Fvector (raw_keybuf_count,
+ (XVECTOR (raw_keybuf)->contents));
+}
+
DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,
Sreset_this_command_lengths, 0, 0, 0,
"Used for complicated reasons in `universal-argument-other-key'.\n\
before_command_restore_flag = 1;
before_command_key_count_1 = before_command_key_count;
before_command_echo_length_1 = before_command_echo_length;
+ return Qnil;
+}
+
+DEFUN ("clear-this-command-keys", Fclear_this_command_keys,
+ Sclear_this_command_keys, 0, 0, 0,
+ "Clear out the vector that `this-command-keys' returns.")
+ ()
+{
+ this_command_key_count = 0;
+ return Qnil;
}
DEFUN ("recursion-depth", Frecursion_depth, Srecursion_depth, 0, 0, 0,
{
kb->Voverriding_terminal_local_map = Qnil;
kb->Vlast_command = Qnil;
+ kb->Vreal_last_command = Qnil;
kb->Vprefix_arg = Qnil;
+ kb->Vlast_prefix_arg = Qnil;
kb->kbd_queue = Qnil;
kb->kbd_queue_has_data = 0;
kb->immediate_echo = 0;
staticpro (&item_properties);
item_properties = Qnil;
+ staticpro (&real_this_command);
+ real_this_command = Qnil;
+
Qtimer_event_handler = intern ("timer-event-handler");
staticpro (&Qtimer_event_handler);
Qpolling_period = intern ("polling-period");
staticpro (&Qpolling_period);
+ Qinput_method_function = intern ("input-method-function");
+ staticpro (&Qinput_method_function);
+
+ Qinput_method_exit_on_first_char = intern ("input-method-exit-on-first-char");
+ staticpro (&Qinput_method_exit_on_first_char);
+ Qinput_method_use_echo_area = intern ("input-method-use-echo-area");
+ staticpro (&Qinput_method_use_echo_area);
+
+ Fset (Qinput_method_exit_on_first_char, Qnil);
+ Fset (Qinput_method_use_echo_area, Qnil);
+
{
struct event_head *p;
this_command_keys = Fmake_vector (make_number (40), Qnil);
staticpro (&this_command_keys);
+ raw_keybuf = Fmake_vector (make_number (30), Qnil);
+ staticpro (&raw_keybuf);
+
Qextended_command_history = intern ("extended-command-history");
Fset (Qextended_command_history, Qnil);
staticpro (&Qextended_command_history);
defsubr (&Sthis_command_keys);
defsubr (&Sthis_command_keys_vector);
defsubr (&Sthis_single_command_keys);
+ defsubr (&Sthis_single_command_raw_keys);
defsubr (&Sreset_this_command_lengths);
+ defsubr (&Sclear_this_command_keys);
defsubr (&Ssuspend_emacs);
defsubr (&Sabort_recursive_edit);
defsubr (&Sexit_recursive_edit);
"Last input event.");
DEFVAR_LISP ("unread-command-events", &Vunread_command_events,
- "List of objects to be read as next command input events.");
+ "List of events to be read as the command input.\n\
+These events are processed first, before actual keyboard input.");
+ Vunread_command_events = Qnil;
DEFVAR_INT ("unread-command-char", &unread_command_char,
"If not -1, an object to be read as next command input event.");
+ DEFVAR_LISP ("unread-post-input-method-events", &Vunread_post_input_method_events,
+ "List of events to be processed as input by input methods.\n\
+These events are processed after `unread-command-events', but\n\
+before actual keyboard input.");
+ Vunread_post_input_method_events = Qnil;
+
+ DEFVAR_LISP ("unread-input-method-events", &Vunread_input_method_events,
+ "List of events to be processed as input by input methods.\n\
+These events are processed after `unread-command-events', but\n\
+before actual keyboard input.");
+ Vunread_input_method_events = Qnil;
+
DEFVAR_LISP ("meta-prefix-char", &meta_prefix_char,
"Meta-prefix character code. Meta-foo as command input\n\
turns into this character followed by foo.");
The value `kill-region' is special; it means that the previous command\n\
was a kill command.");
- DEFVAR_LISP ("this-command", &this_command,
+ DEFVAR_KBOARD ("real-last-command", Vreal_last_command,
+ "Same as `last-command', but never altered by Lisp code.");
+
+ DEFVAR_LISP ("this-command", &Vthis_command,
"The command now being executed.\n\
The command can set this variable; whatever is put here\n\
will be in `last-command' during the following command.");
- this_command = Qnil;
+ Vthis_command = Qnil;
DEFVAR_INT ("auto-save-interval", &auto_save_interval,
"*Number of keyboard input characters between auto-saves.\n\
Vdeferred_action_function = Qnil;
DEFVAR_LISP ("suggest-key-bindings", &Vsuggest_key_bindings,
- "Non-nil means show the equivalent key-binding when M-x command has one.\n\
+ "*Non-nil means show the equivalent key-binding when M-x command has one.\n\
The value can be a length of time to show the message for.\n\
If the value is non-nil and not a number, we wait 2 seconds.");
Vsuggest_key_bindings = Qt;
DEFVAR_LISP ("timer-idle-list", &Vtimer_idle_list,
"List of active idle-time timers in order of increasing time");
Vtimer_idle_list = Qnil;
+
+ DEFVAR_LISP ("input-method-function", &Vinput_method_function,
+ "If non-nil, the function that implements the current input method.\n\
+It's called with one argument, a printing character that was just read.\n\
+\(That means a character with code 040...0176.)\n\
+Typically this function uses `read-event' to read additional events.\n\
+When it does so, it should first bind `input-method-function' to nil\n\
+so it will not be called recursively.\n\
+\n\
+The function should return a list of zero or more events\n\
+to be used as input. If it wants to put back some events\n\
+to be reconsidered, separately, by the input method,\n\
+it can add them to the beginning of `unread-command-events'.\n\
+\n\
+The input method function can find in `input-method-previous-method'\n\
+the previous echo area message.\n\
+\n\
+The input method function should refer to the variables\n\
+`input-method-use-echo-area' and `input-method-exit-on-first-char'\n\
+for guidance on what to do.");
+ Vinput_method_function = Qnil;
+
+ DEFVAR_LISP ("input-method-previous-message",
+ &Vinput_method_previous_message,
+ "When `input-method-function' is called, hold the previous echo area message.\n\
+This variable exists because `read-event' clears the echo area\n\
+before running the input method. It is nil if there was no message.");
+ Vinput_method_previous_message = Qnil;
}
void