From d5eecefb55bb40146efd15ebe4eb37878e28ebf1 Mon Sep 17 00:00:00 2001 From: "Richard M. Stallman" Date: Sat, 8 Aug 1998 03:13:39 +0000 Subject: [PATCH] (Vthis_command): Renamed from this_command. (real_this_command): New variable, but not a Lisp variable; updated like Vthis_command, but never altered by Lisp programs. (command_loop_1): Use real_this_command to set Vreal_last_command. (read_char): When input method returns no chars, call cancel_echoing. Restore the previous echo area message and this_command_keys, too. (Vinput_method_previous_message): New variable. (syms_of_keyboard): Set up lisp variable. (Qinput_method_exit_on_first_char, Qinput_method_use_echo_area): New variables. (syms_of_keyboard): Initialize them. (Fread_key_sequence): New arg COMMAND_LOOP. Bind those variables. --- src/keyboard.c | 176 +++++++++++++++++++++++++++++++++++-------------- 1 file changed, 128 insertions(+), 48 deletions(-) diff --git a/src/keyboard.c b/src/keyboard.c index 3c5ebbb9b8d..4bad07131d6 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -317,7 +317,10 @@ int last_auto_save; /* 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; @@ -368,6 +371,10 @@ extern Lisp_Object Vkey_translation_map; 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; @@ -396,6 +403,9 @@ Lisp_Object Vdeferred_action_list; 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; @@ -1185,8 +1195,8 @@ command_loop_1 () } /* Do this after running Vpost_command_hook, for consistency. */ - current_kboard->Vlast_command = this_command; - current_kboard->Vreal_last_command = this_command; + current_kboard->Vlast_command = Vthis_command; + current_kboard->Vreal_last_command = real_this_command; while (1) { @@ -1253,7 +1263,8 @@ command_loop_1 () 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], @@ -1318,13 +1329,14 @@ command_loop_1 () /* 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 (); @@ -1341,7 +1353,7 @@ command_loop_1 () /* 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)); @@ -1370,7 +1382,7 @@ command_loop_1 () 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)); @@ -1396,7 +1408,7 @@ command_loop_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)) { @@ -1480,7 +1492,7 @@ command_loop_1 () 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; @@ -1518,8 +1530,8 @@ command_loop_1 () then the above doesn't apply. */ if (NILP (current_kboard->Vprefix_arg) || CONSP (last_command_char)) { - current_kboard->Vlast_command = this_command; - current_kboard->Vreal_last_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; @@ -1788,17 +1800,19 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu) jmp_buf save_jump; int key_already_recorded = 0; Lisp_Object tem, save; + Lisp_Object echo_area_message; Lisp_Object also_record; int reread; - struct gcpro gcpro1; + 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: @@ -2274,11 +2288,6 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu) 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)) { @@ -2331,27 +2340,53 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu) 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: /* 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) + if (INTEGERP (c) + && ! NILP (Vinput_method_function) + && (unsigned) XINT (c) >= ' ' + && (unsigned) XINT (c) < 127) + { + Lisp_Object keys; + int key_count = this_command_key_count - 1; + int saved = current_kboard->immediate_echo; + struct gcpro gcpro1; + + keys = Fcopy_sequence (this_command_keys); + GCPRO1 (keys); + tem = call1 (Vinput_method_function, c); + UNGCPRO; + current_kboard->immediate_echo = saved; + /* The input method can return no events. */ + if (! CONSP (tem)) { - 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); + /* Bring back the previous message, if any. */ + if (! NILP (Vinput_method_previous_message)) + message_with_string ("%s", echo_area_message, 0); + this_command_keys = keys; + this_command_key_count = key_count; + cancel_echoing (); + 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: @@ -7611,24 +7646,36 @@ is nil, then the event will be put off until after the current key sequence.\n\ \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.") +`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) #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])); @@ -7649,24 +7696,31 @@ DEFUN ("read-key-sequence", Fread_key_sequence, Sread_key_sequence, 1, 4, 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])); @@ -7687,7 +7741,7 @@ DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector, QUIT; } UNGCPRO; - return Fvector (i, keybuf); + return unbind_to (count, Fvector (i, keybuf)); } DEFUN ("command-execute", Fcommand_execute, Scommand_execute, 1, 4, 0, @@ -7870,7 +7924,8 @@ DEFUN ("execute-extended-command", Fexecute_extended_command, Sexecute_extended_ 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) @@ -8736,6 +8791,9 @@ syms_of_keyboard () 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); @@ -8844,6 +8902,14 @@ syms_of_keyboard () 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; @@ -9000,11 +9066,11 @@ was a kill command."); DEFVAR_KBOARD ("real-last-command", Vreal_last_command, "Same as `last-command', but never altered by Lisp code."); - DEFVAR_LISP ("this-command", &this_command, + 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\ @@ -9247,8 +9313,22 @@ so it will not be called recursively.\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'."); +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-mehod-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 -- 2.39.2