changeset 22945:58a8427745ec

(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.
author Richard M. Stallman <rms@gnu.org>
date Sat, 08 Aug 1998 03:13:39 +0000
parents c2bb9ab28588
children cfde96067373
files src/keyboard.c
diffstat 1 files changed, 129 insertions(+), 49 deletions(-) [+]
line wrap: on
line diff
--- a/src/keyboard.c	Sat Aug 08 03:02:37 1998 +0000
+++ b/src/keyboard.c	Sat Aug 08 03:13:39 1998 +0000
@@ -317,7 +317,10 @@
 /* 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 @@
 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_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 @@
     }
 
   /* 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 @@
       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 @@
 
       /* 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 @@
 
 	      /* 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 @@
 		    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 @@
 		    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 @@
 	  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 @@
 	 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 @@
   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;
-
-  GCPRO1 (c);
+  echo_area_message = Qnil;
+
+  GCPRO2 (c, echo_area_message);
 
  retry:
 
@@ -2274,11 +2288,6 @@
       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 @@
   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 @@
 \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 @@
       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 @@
       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 @@
 
   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 @@
   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 @@
   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 @@
   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 @@
 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