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;
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;
+
/* Non-nil means deactivate the mark at end of this command. */
Lisp_Object Vdeactivate_mark;
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);
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);
int key_already_recorded = 0;
Lisp_Object tem, save;
Lisp_Object also_record;
+ int reread;
struct gcpro gcpro1;
also_record = Qnil;
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;
}
}
}
+ /* 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);
+ reread_for_input_method:
from_macro:
- reread_first:
+ /* Pass this to the input method, if appropriate. */
+ if (INTEGERP (c))
+ {
+ /* If this is a printing character, run the input method. */
+ if (! NILP (Vinput_method_function)
+ && (unsigned) XINT (c) >= ' '
+ && (unsigned) XINT (c) < 127)
+ {
+ int saved = current_kboard->immediate_echo;
+ tem = call1 (Vinput_method_function, c);
+ current_kboard->immediate_echo = saved;
+ /* The input method can return no events. */
+ if (! CONSP (tem))
+ 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);
+ }
+ }
- before_command_key_count = this_command_key_count;
- before_command_echo_length = echo_length ();
+ reread_first:
- /* Don't echo mouse motion events. */
- if (echo_keystrokes
- && ! (EVENT_HAS_PARAMETERS (c)
- && EQ (EVENT_HEAD_KIND (EVENT_HEAD (c)), Qmouse_movement)))
+ 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++;
int junk;
+ raw_keybuf_count = 0;
+
last_nonmenu_event = Qnil;
delayed_switch_frame = Qnil;
orig_local_map = get_local_map (PT, current_buffer);
+ /* Bind input-method-function so that we can set it to nil
+ temporarily after the first input event. */
+ specbind (Qinput_method_function, Vinput_method_function);
+
/* We jump here when the key sequence has been thoroughly changed, and
we need to rescan it starting from the beginning. When we jump here,
keybuf[0..mock_input] holds the sequence we should reread. */
#endif
key = read_char (NILP (prompt), nmaps, submaps, last_nonmenu_event,
&used_mouse_menu);
+
+ /* Turn off input methods after a prefix character. */
+ Vinput_method_function = 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
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;
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;
}
+ 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\
Qpolling_period = intern ("polling-period");
staticpro (&Qpolling_period);
+ Qinput_method_function = intern ("input-method-function");
+ staticpro (&Qinput_method_function);
+
{
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 (&Ssuspend_emacs);
defsubr (&Sabort_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.");
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'.");
+ Vinput_method_function = Qnil;
}
void