(function-form): Fix spec for
[bpt/emacs.git] / src / keyboard.c
index b5a74be..adfda2e 100644 (file)
@@ -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;
 
@@ -293,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;
@@ -340,6 +367,14 @@ 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;
+
+/* 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;
 
@@ -368,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;
 
@@ -939,6 +977,7 @@ cmd_error (data)
   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.  */
@@ -1020,13 +1059,17 @@ command_loop ()
 {
   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)
@@ -1122,6 +1165,7 @@ command_loop_1 ()
 #endif
 
   current_kboard->Vprefix_arg = Qnil;
+  current_kboard->Vlast_prefix_arg = Qnil;
   Vdeactivate_mark = Qnil;
   waiting_for_input = 0;
   cancel_echoing ();
@@ -1144,16 +1188,22 @@ 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);
     }
 
   /* 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));
@@ -1217,13 +1267,16 @@ 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],
                             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));
 
@@ -1282,13 +1335,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 ();
@@ -1300,13 +1354,16 @@ command_loop_1 ()
        {
          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))
@@ -1331,12 +1388,12 @@ 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));
                  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
@@ -1357,7 +1414,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))
                {
@@ -1441,10 +1498,10 @@ 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;
 
       /* Note that the value cell will never directly contain nil
         if the symbol is a local variable.  */
@@ -1457,6 +1514,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);
@@ -1477,7 +1536,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->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;
@@ -1724,7 +1784,10 @@ static jmp_buf wrong_kboard_jmpbuf;
    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
@@ -1746,23 +1809,28 @@ 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;
-  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.  */
@@ -1771,10 +1839,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)
@@ -1782,10 +1848,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
@@ -1832,7 +1927,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;
     }
 
@@ -2202,11 +2297,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))
     {
@@ -2253,36 +2343,141 @@ 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);
 
+  /* 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++;
 
@@ -3607,35 +3802,23 @@ static char *lispy_function_keys[] =
   {
     /* 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",
@@ -3649,9 +3832,9 @@ static char *lispy_function_keys[] =
     "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 */
@@ -5629,10 +5812,12 @@ static Lisp_Object
 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
@@ -5652,12 +5837,16 @@ parse_menu_item (item, notreal, inmenubar)
      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;
 
@@ -5806,8 +5995,9 @@ parse_menu_item (item, notreal, inmenubar)
   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;
     }
 
@@ -5832,14 +6022,18 @@ parse_menu_item (item, notreal, inmenubar)
   /* 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))
@@ -6564,6 +6758,8 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
 
   int junk;
 
+  raw_keybuf_count = 0;
+
   last_nonmenu_event = Qnil;
 
   delayed_switch_frame = Qnil;
@@ -6784,7 +6980,10 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
          /* 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
@@ -6808,8 +7007,12 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
                 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;
@@ -6820,6 +7023,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;
@@ -6828,6 +7033,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
@@ -6873,6 +7094,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;
 
@@ -6888,6 +7110,8 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
                     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;
@@ -6937,17 +7161,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))
@@ -7455,6 +7668,8 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
       add_command_key (keybuf[t]);
     }
 
+  
+
   return t;
 }
 
@@ -7501,24 +7716,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.")
-  (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]));
@@ -7539,24 +7766,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]));
@@ -7577,7 +7811,7 @@ DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,
       QUIT;
     }
   UNGCPRO;
-  return Fvector (i, keybuf);
+  return unbind_to (count, Fvector (i, keybuf));
 }
 \f
 DEFUN ("command-execute", Fcommand_execute, Scommand_execute, 1, 4, 0,
@@ -7760,7 +7994,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)
@@ -7781,9 +8016,18 @@ DEFUN ("execute-extended-command", Fexecute_extended_command, Sexecute_extended_
                                      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;
@@ -7971,6 +8215,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\
@@ -7989,6 +8245,16 @@ appears in the echo area and in the value of `this-command-keys.'.")
   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,
@@ -8458,7 +8724,9 @@ init_kboard (kb)
 {
   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;
@@ -8603,6 +8871,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);
 
@@ -8708,6 +8979,17 @@ syms_of_keyboard ()
   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;
 
@@ -8742,6 +9024,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);
@@ -8789,7 +9074,9 @@ 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 (&Sclear_this_command_keys);
   defsubr (&Ssuspend_emacs);
   defsubr (&Sabort_recursive_edit);
   defsubr (&Sexit_recursive_edit);
@@ -8820,11 +9107,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.");
@@ -8843,11 +9144,14 @@ command exit.\n\
 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\
@@ -9066,7 +9370,7 @@ whenever `deferred-action-list' is non-nil.");
   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;
@@ -9078,6 +9382,34 @@ 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'.\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