From 7d18f9ae9903e59a2f5fab14efc978f8553b3486 Mon Sep 17 00:00:00 2001 From: "Richard M. Stallman" Date: Sun, 26 Jul 1998 23:03:58 +0000 Subject: [PATCH] (Qinput_method_function): New variable. (syms_of_keyboard): Init and staticpro it. (read_key_sequence): Bind input-method-function, and set it to nil after reading the first event. (raw_keybuf, raw_keybuf_count): New variables, to record raw input events as they are read with read_char. (GROW_RAW_KEYBUF): New macro. (Fthis_single_command_raw_keys): New function. (syms_of_keyboard): defsubr it. (read_char): Call the input method if appropriate. Change logic for distinguishing rereads from new events; use local var `reread'. Take events from Vunread_input_method_events and Vunread_post_input_method_events. (Vunread_input_method_events, Vunread_post_input_method_events) (Vinput_method_function): New variable. (syms_of_keyboard): Set up Lisp vars. (command_loop_1): Check Vunread_input_method_events and Vunread_post_input_method_events along with Vunread_command_events. --- src/keyboard.c | 244 ++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 200 insertions(+), 44 deletions(-) diff --git a/src/keyboard.c b/src/keyboard.c index 0df3f09cd86..e5d0a8946e7 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -128,6 +128,22 @@ Lisp_Object recent_keys; /* A vector, holding the last 100 keystrokes */ 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; @@ -249,6 +265,14 @@ Lisp_Object last_input_char; /* 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; @@ -340,6 +364,10 @@ extern Lisp_Object Vfunction_key_map; 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; @@ -1149,6 +1177,8 @@ command_loop_1 () 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); @@ -1466,6 +1496,8 @@ command_loop_1 () 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); @@ -1757,6 +1789,7 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu) int key_already_recorded = 0; Lisp_Object tem, save; Lisp_Object also_record; + int reread; struct gcpro gcpro1; also_record = Qnil; @@ -1769,10 +1802,12 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu) 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. */ @@ -1781,10 +1816,8 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_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) @@ -1792,10 +1825,39 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu) 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 @@ -1842,7 +1904,7 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu) 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; } @@ -2263,36 +2325,61 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu) } } + /* 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++; @@ -6565,6 +6652,8 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, int junk; + raw_keybuf_count = 0; + last_nonmenu_event = Qnil; delayed_switch_frame = Qnil; @@ -6609,6 +6698,10 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, 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. */ @@ -6780,12 +6873,18 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, #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 @@ -6821,6 +6920,8 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, 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; @@ -6829,6 +6930,22 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, } 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 @@ -6874,6 +6991,7 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, && 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; @@ -6938,17 +7056,6 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, 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)) @@ -7456,6 +7563,8 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, add_command_key (keybuf[t]); } + + return t; } @@ -7972,6 +8081,18 @@ The value is always a vector.") + 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\ @@ -8711,6 +8832,9 @@ syms_of_keyboard () Qpolling_period = intern ("polling-period"); staticpro (&Qpolling_period); + Qinput_method_function = intern ("input-method-function"); + staticpro (&Qinput_method_function); + { struct event_head *p; @@ -8745,6 +8869,9 @@ syms_of_keyboard () 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); @@ -8792,6 +8919,7 @@ syms_of_keyboard () 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); @@ -8823,11 +8951,25 @@ so that you can determine whether the command was run by mouse or not."); "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."); @@ -9084,6 +9226,20 @@ If the value is non-nil and not a number, we wait 2 seconds."); 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 -- 2.39.2