]> code.delx.au - gnu-emacs/blobdiff - src/keyboard.c
(remove-overlays): Fix last change.
[gnu-emacs] / src / keyboard.c
index a1b8ad34b078e3f6b28de3a380a1893aaca7d8ab..364fa893539e09cf0e4f30b34a777ebf14d2f58b 100644 (file)
@@ -242,6 +242,9 @@ static int inhibit_local_menu_bar_menus;
 /* Nonzero means C-g should cause immediate error-signal.  */
 int immediate_quit;
 
+/* The user's hook function for outputting an error message.  */
+Lisp_Object Vcommand_error_function;
+
 /* The user's ERASE setting.  */
 Lisp_Object Vtty_erase_char;
 
@@ -1003,7 +1006,7 @@ recursive_edit_1 ()
   /* Handle throw from read_minibuf when using minibuffer
      while it's active but we're in another window.  */
   if (STRINGP (val))
-    Fsignal (Qerror, Fcons (val, Qnil));
+    xsignal1 (Qerror, val);
 
   return unbind_to (count, Qnil);
 }
@@ -1230,52 +1233,47 @@ cmd_error_internal (data, context)
      Lisp_Object data;
      char *context;
 {
-  Lisp_Object stream;
-  int kill_emacs_p = 0;
   struct frame *sf = SELECTED_FRAME ();
 
+  /* The immediate context is not interesting for Quits,
+     since they are asyncronous.  */
+  if (EQ (XCAR (data), Qquit))
+    Vsignaling_function = Qnil;
+
   Vquit_flag = Qnil;
   Vinhibit_quit = Qt;
-  clear_message (1, 0);
 
+  /* Use user's specified output function if any.  */
+  if (!NILP (Vcommand_error_function))
+    call3 (Vcommand_error_function, data,
+          build_string (context ? context : ""),
+          Vsignaling_function);
   /* If the window system or terminal frame hasn't been initialized
-     yet, or we're not interactive, it's best to dump this message out
-     to stderr and exit.  */
-  if (!sf->glyphs_initialized_p
-      /* This is the case of the frame dumped with Emacs, when we're
-        running under a window system.  */
-      || (!NILP (Vwindow_system)
-         && !inhibit_window_system
-         && FRAME_TERMCAP_P (sf))
-      || noninteractive)
-    {
-      stream = Qexternal_debugging_output;
-      kill_emacs_p = 1;
+     yet, or we're not interactive, write the message to stderr and exit.  */
+  else if (!sf->glyphs_initialized_p
+          /* This is the case of the frame dumped with Emacs, when we're
+             running under a window system.  */
+          || (!NILP (Vwindow_system)
+              && !inhibit_window_system
+              && FRAME_TERMCAP_P (sf))
+          || noninteractive)
+    {
+      print_error_message (data, Qexternal_debugging_output,
+                          context, Vsignaling_function);
+      Fterpri (Qexternal_debugging_output);
+      Fkill_emacs (make_number (-1));
     }
   else
     {
+      clear_message (1, 0);
       Fdiscard_input ();
       message_log_maybe_newline ();
       bitch_at_user ();
-      stream = Qt;
-    }
-
-  /* The immediate context is not interesting for Quits,
-     since they are asyncronous.  */
-  if (EQ (XCAR (data), Qquit))
-    Vsignaling_function = Qnil;
 
-  print_error_message (data, stream, context, Vsignaling_function);
+      print_error_message (data, Qt, context, Vsignaling_function);
+    }
 
   Vsignaling_function = Qnil;
-
-  /* If the window system or terminal frame hasn't been initialized
-     yet, or we're in -batch mode, this error should cause Emacs to exit.  */
-  if (kill_emacs_p)
-    {
-      Fterpri (stream);
-      Fkill_emacs (make_number (-1));
-    }
 }
 \f
 Lisp_Object command_loop_1 ();
@@ -1389,6 +1387,72 @@ DEFUN ("abort-recursive-edit", Fabort_recursive_edit, Sabort_recursive_edit, 0,
   return Qnil;
 }
 \f
+#ifdef HAVE_MOUSE
+
+/* Restore mouse tracking enablement.  See Ftrack_mouse for the only use
+   of this function.  */
+
+static Lisp_Object
+tracking_off (old_value)
+     Lisp_Object old_value;
+{
+  do_mouse_tracking = old_value;
+  if (NILP (old_value))
+    {
+      /* Redisplay may have been preempted because there was input
+        available, and it assumes it will be called again after the
+        input has been processed.  If the only input available was
+        the sort that we have just disabled, then we need to call
+        redisplay.  */
+      if (!readable_events (READABLE_EVENTS_DO_TIMERS_NOW))
+       {
+         redisplay_preserve_echo_area (6);
+         get_input_pending (&input_pending,
+                            READABLE_EVENTS_DO_TIMERS_NOW);
+       }
+    }
+  return Qnil;
+}
+
+DEFUN ("track-mouse", Ftrack_mouse, Strack_mouse, 0, UNEVALLED, 0,
+       doc: /* Evaluate BODY with mouse movement events enabled.
+Within a `track-mouse' form, mouse motion generates input events that
+you can read with `read-event'.
+Normally, mouse motion is ignored.
+usage: (track-mouse BODY ...)  */)
+     (args)
+     Lisp_Object args;
+{
+  int count = SPECPDL_INDEX ();
+  Lisp_Object val;
+
+  record_unwind_protect (tracking_off, do_mouse_tracking);
+
+  do_mouse_tracking = Qt;
+
+  val = Fprogn (args);
+  return unbind_to (count, val);
+}
+
+/* If mouse has moved on some frame, return one of those frames.
+   Return 0 otherwise.  */
+
+static FRAME_PTR
+some_mouse_moved ()
+{
+  Lisp_Object tail, frame;
+
+  FOR_EACH_FRAME (tail, frame)
+    {
+      if (XFRAME (frame)->mouse_moved)
+       return XFRAME (frame);
+    }
+
+  return 0;
+}
+
+#endif /* HAVE_MOUSE */
+\f
 /* This is the actual command reading loop,
    sans error-handling encapsulation.  */
 
@@ -1418,7 +1482,7 @@ command_loop_1 ()
   Lisp_Object keybuf[30];
   int i;
   int no_direct;
-  int prev_modiff;
+  int prev_modiff = 0;
   struct buffer *prev_buffer = NULL;
 #ifdef MULTI_KBOARD
   int was_locked = single_kboard;
@@ -1482,15 +1546,18 @@ command_loop_1 ()
 
       if (minibuf_level
          && !NILP (echo_area_buffer[0])
-         && EQ (minibuf_window, echo_area_window)
-         && NUMBERP (Vminibuffer_message_timeout))
+         && EQ (minibuf_window, echo_area_window))
        {
          /* Bind inhibit-quit to t so that C-g gets read in
             rather than quitting back to the minibuffer.  */
          int count = SPECPDL_INDEX ();
          specbind (Qinhibit_quit, Qt);
 
-         Fsit_for (Vminibuffer_message_timeout, Qnil, Qnil);
+         if (NUMBERP (Vminibuffer_message_timeout))
+           sit_for (Vminibuffer_message_timeout, 0, 2);
+         else
+           sit_for (Qt, 0, 2);
+
          /* Clear the echo area.  */
          message2 (0, 0, 0);
          safe_run_hooks (Qecho_area_clear_hook);
@@ -1609,7 +1676,7 @@ command_loop_1 ()
       if (SYMBOLP (cmd))
        {
          Lisp_Object cmd1;
-         if (cmd1 = Fcommand_remapping (cmd), !NILP (cmd1))
+         if (cmd1 = Fcommand_remapping (cmd, Qnil), !NILP (cmd1))
            cmd = cmd1;
        }
 
@@ -2033,6 +2100,8 @@ static Lisp_Object
 safe_run_hooks_1 (hook)
      Lisp_Object hook;
 {
+  if (NILP (Vrun_hooks))
+    return Qnil;
   return call1 (Vrun_hooks, Vinhibit_quit);
 }
 
@@ -2306,7 +2375,17 @@ show_help_echo (help, window, object, pos, ok_to_overwrite_keystroke_echo)
 
 #ifdef HAVE_MOUSE
   if (!noninteractive && STRINGP (help))
-    help = call1 (Qmouse_fixup_help_message, help);
+    {
+      /* The mouse-fixup-help-message Lisp function can call
+        mouse_position_hook, which resets the mouse_moved flags.
+        This causes trouble if we are trying to read a mouse motion
+        event (i.e., if we are inside a `track-mouse' form), so we
+        restore the mouse_moved flag.  */
+      FRAME_PTR f = NILP (do_mouse_tracking) ? NULL : some_mouse_moved ();
+      help = call1 (Qmouse_fixup_help_message, help);
+      if (f)
+       f->mouse_moved = 1;
+    }
 #endif
 
   if (STRINGP (help) || NILP (help))
@@ -2386,18 +2465,23 @@ do { if (polling_stopped_here) start_polling ();        \
    if we used a mouse menu to read the input, or zero otherwise.  If
    USED_MOUSE_MENU is null, we don't dereference it.
 
+   If END_TIME is non-null, it is a pointer to an EMACS_TIME
+   specifying the maximum time to wait until.  If no input arrives by
+   that time, stop waiting and return nil.
+
    Value is t if we showed a menu and the user rejected it.  */
 
 Lisp_Object
-read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
+read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu, end_time)
      int commandflag;
      int nmaps;
      Lisp_Object *maps;
      Lisp_Object prev_event;
      int *used_mouse_menu;
+     EMACS_TIME *end_time;
 {
   volatile Lisp_Object c;
-  int count;
+  int count, jmpcount;
   jmp_buf local_getcjmp;
   jmp_buf save_jump;
   volatile int key_already_recorded = 0;
@@ -2453,6 +2537,18 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
       c = XCAR (Vunread_command_events);
       Vunread_command_events = XCDR (Vunread_command_events);
 
+      reread = 1;
+
+      /* Undo what sit-for did when it unread additional keys
+        inside universal-argument.  */
+
+      if (CONSP (c)
+         && EQ (XCAR (c), Qt))
+       {
+         reread = 0;
+         c = XCDR (c);
+       }
+
       /* Undo what read_char_x_menu_prompt did when it unread
         additional keys returned by Fx_popup_menu.  */
       if (CONSP (c)
@@ -2466,7 +2562,6 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
          && (EQ (c, Qtool_bar) || EQ (c, Qmenu_bar)))
        *used_mouse_menu = 1;
 
-      reread = 1;
       goto reread_for_input_method;
     }
 
@@ -2623,11 +2718,13 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
      around any call to sit_for or kbd_buffer_get_event;
      it *must not* be in effect when we call redisplay.  */
 
+  jmpcount = SPECPDL_INDEX ();
   if (_setjmp (local_getcjmp))
     {
       /* We must have saved the outer value of getcjmp here,
         so restore it now.  */
       restore_getcjmp (save_jump);
+      unbind_to (jmpcount, Qnil);
       XSETINT (c, quit_char);
       internal_last_event_frame = selected_frame;
       Vlast_event_frame = internal_last_event_frame;
@@ -2668,12 +2765,18 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
       goto non_reread;
     }
 
-  timer_start_idle ();
+  /* Start idle timers if no time limit is supplied.  We don't do it
+     if a time limit is supplied to avoid an infinite recursion in the
+     situation where an idle timer calls `sit-for'.  */
+
+  if (!end_time)
+    timer_start_idle ();
 
   /* If in middle of key sequence and minibuffer not active,
      start echoing if enough time elapses.  */
 
   if (minibuf_level == 0
+      && !end_time
       && !current_kboard->immediate_echo
       && this_command_key_count > 0
       && ! noninteractive
@@ -2689,8 +2792,6 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
          /* Or not echoing before and echoing allowed.  */
          || (!echo_kboard && ok_to_echo_at_next_pause)))
     {
-      Lisp_Object tem0;
-
       /* After a mouse event, start echoing right away.
         This is because we are probably about to display a menu,
         and we don't want to delay before doing so.  */
@@ -2698,13 +2799,11 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
        echo_now ();
       else
        {
-         int sec, usec;
-         double duration = extract_float (Vecho_keystrokes);
-         sec = (int) duration;
-         usec = (duration - sec) * 1000000;
+         Lisp_Object tem0;
+
          save_getcjmp (save_jump);
          restore_getcjmp (local_getcjmp);
-         tem0 = sit_for (sec, usec, 1, 1, 0);
+         tem0 = sit_for (Vecho_keystrokes, 1, 1);
          restore_getcjmp (save_jump);
          if (EQ (tem0, Qt)
              && ! CONSP (Vunread_command_events))
@@ -2741,7 +2840,8 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
       c = read_char_x_menu_prompt (nmaps, maps, prev_event, used_mouse_menu);
 
       /* Now that we have read an event, Emacs is not idle.  */
-      timer_stop_idle ();
+      if (!end_time)
+       timer_stop_idle ();
 
       goto exit;
     }
@@ -2771,11 +2871,11 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
          && XINT (Vauto_save_timeout) > 0)
        {
          Lisp_Object tem0;
+         int timeout = delay_level * XFASTINT (Vauto_save_timeout) / 4;
 
          save_getcjmp (save_jump);
          restore_getcjmp (local_getcjmp);
-         tem0 = sit_for (delay_level * XFASTINT (Vauto_save_timeout) / 4,
-                         0, 1, 1, 0);
+         tem0 = sit_for (make_number (timeout), 1, 1);
          restore_getcjmp (save_jump);
 
          if (EQ (tem0, Qt)
@@ -2860,11 +2960,20 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
     {
       KBOARD *kb;
 
+      if (end_time)
+       {
+         EMACS_TIME now;
+         EMACS_GET_TIME (now);
+         if (EMACS_TIME_GE (now, *end_time))
+           goto exit;
+       }
+
       /* Actually read a character, waiting if necessary.  */
       save_getcjmp (save_jump);
       restore_getcjmp (local_getcjmp);
-      timer_start_idle ();
-      c = kbd_buffer_get_event (&kb, used_mouse_menu);
+      if (!end_time)
+       timer_start_idle ();
+      c = kbd_buffer_get_event (&kb, used_mouse_menu, end_time);
       restore_getcjmp (save_jump);
 
 #ifdef MULTI_KBOARD
@@ -2915,7 +3024,8 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
 
  non_reread:
 
-  timer_stop_idle ();
+  if (!end_time)
+    timer_stop_idle ();
   RESUME_POLLING;
 
   if (NILP (c))
@@ -2949,7 +3059,7 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
       last_input_char = c;
       Fcommand_execute (tem, Qnil, Fvector (1, &last_input_char), Qt);
 
-      if (CONSP (c) && EQ (XCAR (c), Qselect_window))
+      if (CONSP (c) && EQ (XCAR (c), Qselect_window) && !end_time)
        /* We stopped being idle for this event; undo that.  This
           prevents automatic window selection (under
           mouse_autoselect_window from acting as a real input event, for
@@ -3155,12 +3265,14 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
       show_help_echo (help, window, object, position, 0);
 
       /* We stopped being idle for this event; undo that.  */
-      timer_resume_idle ();
+      if (!end_time)
+       timer_resume_idle ();
       goto retry;
     }
 
-  if (! reread || this_command_key_count == 0
-      || this_command_key_count_reset)
+  if ((! reread || this_command_key_count == 0
+       || this_command_key_count_reset)
+      && !end_time)
     {
 
       /* Don't echo mouse motion events.  */
@@ -3201,7 +3313,7 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
 
       cancel_echoing ();
       do
-       c = read_char (0, 0, 0, Qnil, 0);
+       c = read_char (0, 0, 0, Qnil, 0, NULL);
       while (BUFFERP (c));
       /* Remove the help from the frame */
       unbind_to (count, Qnil);
@@ -3211,7 +3323,7 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
        {
          cancel_echoing ();
          do
-           c = read_char (0, 0, 0, Qnil, 0);
+           c = read_char (0, 0, 0, Qnil, 0, NULL);
          while (BUFFERP (c));
        }
     }
@@ -3439,72 +3551,6 @@ restore_getcjmp (temp)
   bcopy (temp, getcjmp, sizeof getcjmp);
 }
 \f
-#ifdef HAVE_MOUSE
-
-/* Restore mouse tracking enablement.  See Ftrack_mouse for the only use
-   of this function.  */
-
-static Lisp_Object
-tracking_off (old_value)
-     Lisp_Object old_value;
-{
-  do_mouse_tracking = old_value;
-  if (NILP (old_value))
-    {
-      /* Redisplay may have been preempted because there was input
-        available, and it assumes it will be called again after the
-        input has been processed.  If the only input available was
-        the sort that we have just disabled, then we need to call
-        redisplay.  */
-      if (!readable_events (READABLE_EVENTS_DO_TIMERS_NOW))
-       {
-         redisplay_preserve_echo_area (6);
-         get_input_pending (&input_pending,
-                            READABLE_EVENTS_DO_TIMERS_NOW);
-       }
-    }
-  return Qnil;
-}
-
-DEFUN ("track-mouse", Ftrack_mouse, Strack_mouse, 0, UNEVALLED, 0,
-       doc: /* Evaluate BODY with mouse movement events enabled.
-Within a `track-mouse' form, mouse motion generates input events that
-you can read with `read-event'.
-Normally, mouse motion is ignored.
-usage: (track-mouse BODY ...)  */)
-     (args)
-     Lisp_Object args;
-{
-  int count = SPECPDL_INDEX ();
-  Lisp_Object val;
-
-  record_unwind_protect (tracking_off, do_mouse_tracking);
-
-  do_mouse_tracking = Qt;
-
-  val = Fprogn (args);
-  return unbind_to (count, val);
-}
-
-/* If mouse has moved on some frame, return one of those frames.
-   Return 0 otherwise.  */
-
-static FRAME_PTR
-some_mouse_moved ()
-{
-  Lisp_Object tail, frame;
-
-  FOR_EACH_FRAME (tail, frame)
-    {
-      if (XFRAME (frame)->mouse_moved)
-       return XFRAME (frame);
-    }
-
-  return 0;
-}
-
-#endif /* HAVE_MOUSE */
-\f
 /* Low level keyboard/mouse input.
    kbd_buffer_store_event places events in kbd_buffer, and
    kbd_buffer_get_event retrieves them.  */
@@ -3890,9 +3936,10 @@ clear_event (event)
    We always read and discard one event.  */
 
 static Lisp_Object
-kbd_buffer_get_event (kbp, used_mouse_menu)
+kbd_buffer_get_event (kbp, used_mouse_menu, end_time)
      KBOARD **kbp;
      int *used_mouse_menu;
+     EMACS_TIME *end_time;
 {
   register int c;
   Lisp_Object obj;
@@ -3936,13 +3983,26 @@ kbd_buffer_get_event (kbp, used_mouse_menu)
       if (!NILP (do_mouse_tracking) && some_mouse_moved ())
        break;
 #endif
-      {
+      if (end_time)
+       {
+         EMACS_TIME duration;
+         EMACS_GET_TIME (duration);
+         if (EMACS_TIME_GE (duration, *end_time))
+           return Qnil;        /* finished waiting */
+         else
+           {
+             EMACS_SUB_TIME (duration, *end_time, duration);
+             wait_reading_process_output (EMACS_SECS (duration),
+                                          EMACS_USECS (duration),
+                                          -1, 1, Qnil, NULL, 0);
+           }
+       }
+      else
        wait_reading_process_output (0, 0, -1, 1, Qnil, NULL, 0);
 
-       if (!interrupt_input && kbd_fetch_ptr == kbd_store_ptr)
-         /* Pass 1 for EXPECT since we just waited to have input.  */
-         read_avail_input (1);
-      }
+      if (!interrupt_input && kbd_fetch_ptr == kbd_store_ptr)
+       /* Pass 1 for EXPECT since we just waited to have input.  */
+       read_avail_input (1);
 #endif /* not VMS */
     }
 
@@ -4504,6 +4564,32 @@ timer_check (do_it_now)
   UNGCPRO;
   return nexttime;
 }
+
+DEFUN ("current-idle-time", Fcurrent_idle_time, Scurrent_idle_time, 0, 0, 0,
+       doc: /* Return the current length of Emacs idleness.
+The value is returned as a list of three integers.  The first has the
+most significant 16 bits of the seconds, while the second has the
+least significant 16 bits.  The third integer gives the microsecond
+count.
+
+The microsecond count is zero on systems that do not provide
+resolution finer than a second.  */)
+  ()
+{
+  if (! EMACS_TIME_NEG_P (timer_idleness_start_time))
+    {
+      EMACS_TIME now, idleness_now;
+
+      EMACS_GET_TIME (now);
+      EMACS_SUB_TIME (idleness_now, now, timer_idleness_start_time);
+
+      return list3 (make_number ((EMACS_SECS (idleness_now) >> 16) & 0xffff),
+                   make_number ((EMACS_SECS (idleness_now) >> 0)  & 0xffff),
+                   make_number (EMACS_USECS (idleness_now)));
+    }
+
+  return Qnil;
+}
 \f
 /* Caches for modify_event_symbol.  */
 static Lisp_Object accent_key_syms;
@@ -5881,8 +5967,7 @@ make_lispy_event (event)
        spec[1] = event->y;
        return Fcons (Qmac_apple_event,
                      Fcons (Fvector (2, spec),
-                            Fcons (mac_make_lispy_event_code (event->code),
-                                   Qnil)));
+                            Fcons (event->arg, Qnil)));
       }
 #endif
 
@@ -7445,7 +7530,7 @@ parse_menu_item (item, notreal, inmenubar)
       Lisp_Object prefix;
 
       if (!NILP (tem))
-       tem = Fkey_binding (tem, Qnil, Qnil);
+       tem = Fkey_binding (tem, Qnil, Qnil, Qnil);
 
       prefix = AREF (item_properties, ITEM_PROPERTY_KEYEQ);
       if (CONSP (prefix))
@@ -7581,7 +7666,7 @@ Lisp_Object QCimage;
 /* Function prototypes.  */
 
 static void init_tool_bar_items P_ ((Lisp_Object));
-static void process_tool_bar_item P_ ((Lisp_Object, Lisp_Object));
+static void process_tool_bar_item P_ ((Lisp_Object, Lisp_Object, Lisp_Object, void*));
 static int parse_tool_bar_item P_ ((Lisp_Object, Lisp_Object));
 static void append_tool_bar_item P_ ((void));
 
@@ -7659,17 +7744,7 @@ tool_bar_items (reuse, nitems)
 
        keymap = get_keymap (access_keymap (maps[i], Qtool_bar, 1, 0, 1), 0, 1);
        if (CONSP (keymap))
-         {
-           Lisp_Object tail;
-
-           /* KEYMAP is a list `(keymap (KEY . BINDING) ...)'.  */
-           for (tail = keymap; CONSP (tail); tail = XCDR (tail))
-             {
-               Lisp_Object keydef = XCAR (tail);
-               if (CONSP (keydef))
-                 process_tool_bar_item (XCAR (keydef), XCDR (keydef));
-             }
-         }
+         map_keymap (keymap, process_tool_bar_item, Qnil, NULL, 1);
       }
 
   Vinhibit_quit = oquit;
@@ -7681,8 +7756,9 @@ tool_bar_items (reuse, nitems)
 /* Process the definition of KEY which is DEF.  */
 
 static void
-process_tool_bar_item (key, def)
-     Lisp_Object key, def;
+process_tool_bar_item (key, def, data, args)
+     Lisp_Object key, def, data;
+     void *args;
 {
   int i;
   extern Lisp_Object Qundefined;
@@ -8297,7 +8373,7 @@ read_char_minibuf_menu_prompt (commandflag, nmaps, maps)
       orig_defn_macro = current_kboard->defining_kbd_macro;
       current_kboard->defining_kbd_macro = Qnil;
       do
-       obj = read_char (commandflag, 0, 0, Qt, 0);
+       obj = read_char (commandflag, 0, 0, Qt, 0, NULL);
       while (BUFFERP (obj));
       current_kboard->defining_kbd_macro = orig_defn_macro;
 
@@ -8368,7 +8444,15 @@ follow_key (key, nmaps, current, defs, next)
    such as Vfunction_key_map and Vkey_translation_map.  */
 typedef struct keyremap
 {
-  Lisp_Object map, parent;
+  /* This is the map originally specified for this use.  */
+  Lisp_Object parent;
+  /* This is a submap reached by looking up, in PARENT,
+     the events from START to END.  */
+  Lisp_Object map;
+  /* Positions [START, END) in the key sequence buffer
+     are the key that we have scanned so far.
+     Those events are the ones that we will replace
+     if PAREHT maps them into a key sequence.  */
   int start, end;
 } keyremap;
 
@@ -8397,7 +8481,7 @@ access_keymap_keyremap (map, key, prompt, do_funcall)
   /* Handle a symbol whose function definition is a keymap
      or an array.  */
   if (SYMBOLP (next) && !NILP (Ffboundp (next))
-      && (!NILP (Farrayp (XSYMBOL (next)->function))
+      && (ARRAYP (XSYMBOL (next)->function)
          || KEYMAPP (XSYMBOL (next)->function)))
     next = XSYMBOL (next)->function;
 
@@ -8441,7 +8525,11 @@ keyremap_step (keybuf, bufsize, fkey, input, doit, diff, prompt)
   Lisp_Object next, key;
 
   key = keybuf[fkey->end++];
-  next = access_keymap_keyremap (fkey->map, key, prompt, doit);
+
+  if (KEYMAPP (fkey->parent))
+    next = access_keymap_keyremap (fkey->map, key, prompt, doit);
+  else
+    next = Qnil;
 
   /* If keybuf[fkey->start..fkey->end] is bound in the
      map and we're in a position to do the key remapping, replace it with
@@ -8639,9 +8727,8 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
   delayed_switch_frame = Qnil;
   fkey.map = fkey.parent = Vfunction_key_map;
   keytran.map = keytran.parent = Vkey_translation_map;
-  /* If there is no translation-map, turn off scanning.  */
-  fkey.start = fkey.end = KEYMAPP (fkey.map) ? 0 : bufsize + 1;
-  keytran.start = keytran.end = KEYMAPP (keytran.map) ? 0 : bufsize + 1;
+  fkey.start = fkey.end = 0;
+  keytran.start = keytran.end = 0;
 
   if (INTERACTIVE)
     {
@@ -8670,7 +8757,7 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
   /* Read the first char of the sequence specially, before setting
      up any keymaps, in case a filter runs and switches buffers on us.  */
   first_event = read_char (NILP (prompt), 0, submaps, last_nonmenu_event,
-                          &junk);
+                          &junk, NULL);
 #endif /* GOBBLE_FIRST_EVENT */
 
   orig_local_map = get_local_map (PT, current_buffer, Qlocal_map);
@@ -8692,17 +8779,25 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
      the initial keymaps from the current buffer.  */
   nmaps = 0;
 
-  if (!NILP (current_kboard->Voverriding_terminal_local_map)
-      || !NILP (Voverriding_local_map))
+  if (!NILP (current_kboard->Voverriding_terminal_local_map))
     {
-      if (3 > nmaps_allocated)
+      if (2 > nmaps_allocated)
        {
-         submaps = (Lisp_Object *) alloca (3 * sizeof (submaps[0]));
-         defs    = (Lisp_Object *) alloca (3 * sizeof (defs[0]));
-         nmaps_allocated = 3;
+         submaps = (Lisp_Object *) alloca (2 * sizeof (submaps[0]));
+         defs    = (Lisp_Object *) alloca (2 * sizeof (defs[0]));
+         nmaps_allocated = 2;
        }
       if (!NILP (current_kboard->Voverriding_terminal_local_map))
        submaps[nmaps++] = current_kboard->Voverriding_terminal_local_map;
+    }
+  else if (!NILP (Voverriding_local_map))
+    {
+      if (2 > nmaps_allocated)
+       {
+         submaps = (Lisp_Object *) alloca (2 * sizeof (submaps[0]));
+         defs    = (Lisp_Object *) alloca (2 * sizeof (defs[0]));
+         nmaps_allocated = 2;
+       }
       if (!NILP (Voverriding_local_map))
        submaps[nmaps++] = Voverriding_local_map;
     }
@@ -8873,7 +8968,7 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
 #endif
            key = read_char (NILP (prompt), nmaps,
                             (Lisp_Object *) submaps, last_nonmenu_event,
-                            &used_mouse_menu);
+                            &used_mouse_menu, NULL);
          }
 
          /* read_char returns t when it shows a menu and the user rejects it.
@@ -9052,16 +9147,19 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
                          if (!EQ (map_here, orig_local_map))
                            {
                              orig_local_map = map_here;
-                             keybuf[t] = key;
-                             mock_input = t + 1;
-
-                             goto replay_sequence;
+                             ++localized_local_map;
                            }
+
                          map_here = get_local_map (XINT (pos),
                                                     current_buffer, Qkeymap);
                          if (!EQ (map_here, orig_keymap))
                            {
                              orig_keymap = map_here;
+                             ++localized_local_map;
+                           }
+
+                         if (localized_local_map > 1)
+                           {
                              keybuf[t] = key;
                              mock_input = t + 1;
 
@@ -9469,8 +9567,8 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
 
              keybuf[t - 1] = new_key;
              mock_input = max (t, mock_input);
-             fkey.start = fkey.end = KEYMAPP (fkey.map) ? 0 : bufsize + 1;
-             keytran.start = keytran.end = KEYMAPP (keytran.map) ? 0 : bufsize + 1;
+             fkey.start = fkey.end = 0;
+             keytran.start = keytran.end = 0;
 
              goto replay_sequence;
            }
@@ -9488,6 +9586,7 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
   /* Don't downcase the last character if the caller says don't.
      Don't downcase it if the result is undefined, either.  */
   if ((dont_downcase_last || first_binding >= nmaps)
+      && t > 0
       && t - 1 == original_uppercase_position)
     keybuf[t - 1] = original_uppercase;
 
@@ -9777,7 +9876,13 @@ a special event, so ignore the prefix argument and don't clear it.  */)
 \f
 DEFUN ("execute-extended-command", Fexecute_extended_command, Sexecute_extended_command,
        1, 1, "P",
-       doc: /* Read function name, then read its arguments and call it.  */)
+       doc: /* Read function name, then read its arguments and call it.
+
+To pass a numeric argument to the command you are invoking with, specify
+the numeric argument to this command.
+
+Noninteractively, the argument PREFIXARG is the prefix argument to
+give to the command you invoke, if it asks for an argument.  */)
      (prefixarg)
      Lisp_Object prefixarg;
 {
@@ -9883,19 +9988,18 @@ DEFUN ("execute-extended-command", Fexecute_extended_command, Sexecute_extended_
                                      Qmouse_movement)))
     {
       /* But first wait, and skip the message if there is input.  */
-      int delay_time;
-      if (!NILP (echo_area_buffer[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);
+      Lisp_Object waited;
+
+      /* If this command displayed something in the echo area;
+        wait a few seconds, then display our suggestion message.  */
+      if (NILP (echo_area_buffer[0]))
+       waited = sit_for (make_number (0), 0, 2);
+      else if (NUMBERP (Vsuggest_key_bindings))
+       waited = sit_for (Vsuggest_key_bindings, 0, 2);
       else
-       /* This command left the echo area empty,
-          so display our message immediately.  */
-       delay_time = 0;
+       waited = sit_for (make_number (2), 0, 2);
 
-      if (!NILP (Fsit_for (make_number (delay_time), Qnil, Qnil))
-         && ! CONSP (Vunread_command_events))
+      if (!NILP (waited) && ! CONSP (Vunread_command_events))
        {
          Lisp_Object binding;
          char *newmessage;
@@ -9915,10 +10019,12 @@ DEFUN ("execute-extended-command", Fexecute_extended_command, Sexecute_extended_
          message2_nolog (newmessage,
                          strlen (newmessage),
                          STRING_MULTIBYTE (binding));
-         if (!NILP (Fsit_for ((NUMBERP (Vsuggest_key_bindings)
-                               ? Vsuggest_key_bindings : make_number (2)),
-                              Qnil, Qnil))
-             && message_p)
+         if (NUMBERP (Vsuggest_key_bindings))
+           waited = sit_for (Vsuggest_key_bindings, 0, 2);
+         else
+           waited = sit_for (make_number (2), 0, 2);
+
+         if (!NILP (waited) && message_p)
            restore_message ();
 
          unbind_to (count, Qnil);
@@ -10007,7 +10113,9 @@ Actually, the value is nil only if we can be sure that no input is available;
 if there is a doubt, the value is t.  */)
      ()
 {
-  if (!NILP (Vunread_command_events) || unread_command_char != -1)
+  if (!NILP (Vunread_command_events) || unread_command_char != -1
+      || !NILP (Vunread_post_input_method_events)
+      || !NILP (Vunread_input_method_events))
     return (Qt);
 
   get_input_pending (&input_pending,
@@ -11079,6 +11187,7 @@ syms_of_keyboard ()
   menu_bar_items_vector = Qnil;
   staticpro (&menu_bar_items_vector);
 
+  defsubr (&Scurrent_idle_time);
   defsubr (&Sevent_convert_list);
   defsubr (&Sread_key_sequence);
   defsubr (&Sread_key_sequence_vector);
@@ -11128,7 +11237,10 @@ so that you can determine whether the command was run by mouse or not.  */);
 
   DEFVAR_LISP ("unread-command-events", &Vunread_command_events,
               doc: /* List of events to be read as the command input.
-These events are processed first, before actual keyboard input.  */);
+These events are processed first, before actual keyboard input.
+Events read from this list are not normally added to `this-command-keys',
+as they will already have been added once as they were read for the first time.
+An element of the form (t . EVENT) forces EVENT to be added to that list.  */);
   Vunread_command_events = Qnil;
 
   DEFVAR_INT ("unread-command-char", &unread_command_char,
@@ -11136,14 +11248,16 @@ These events are processed first, before actual keyboard input.  */);
 
   DEFVAR_LISP ("unread-post-input-method-events", &Vunread_post_input_method_events,
               doc: /* List of events to be processed as input by input methods.
-These events are processed after `unread-command-events', but
-before actual keyboard input.  */);
+These events are processed before `unread-command-events'
+and actual keyboard input without given to `input-method-function'.  */);
   Vunread_post_input_method_events = Qnil;
 
   DEFVAR_LISP ("unread-input-method-events", &Vunread_input_method_events,
               doc: /* List of events to be processed as input by input methods.
 These events are processed after `unread-command-events', but
-before actual keyboard input.  */);
+before actual keyboard input.
+If there's an active input method, the events are given to
+`input-method-function'.  */);
   Vunread_input_method_events = Qnil;
 
   DEFVAR_LISP ("meta-prefix-char", &meta_prefix_char,
@@ -11489,6 +11603,15 @@ The value of that variable is passed to `quit-flag' and later causes a
 peculiar kind of quitting.  */);
   Vthrow_on_input = Qnil;
 
+  DEFVAR_LISP ("command-error-function", &Vcommand_error_function,
+              doc: /* If non-nil, function to output error messages.
+The arguments are the error data, a list of the form
+ (SIGNALED-CONDITIONS . SIGNAL-DATA)
+such as just as `condition-case' would bind its variable to,
+the context (a string which normally goes at the start of the message),
+and the Lisp function within which the error was signaled.  */);
+  Vcommand_error_function = Qnil;
+
   DEFVAR_LISP ("enable-disabled-menus-and-buttons",
               &Venable_disabled_menus_and_buttons,
               doc: /* If non-nil, don't ignore events produced by disabled menu items and tool-bar.