(redisplay_window): Fix last change. Don't recenter if
[bpt/emacs.git] / src / keyboard.c
index 6148a25..1aca012 100644 (file)
@@ -1,6 +1,7 @@
 /* Keyboard and mouse input; editor command loop.
 /* Keyboard and mouse input; editor command loop.
-   Copyright (C) 1985,86,87,88,89,93,94,95,96,97,99,2000,01,02,03
-     Free Software Foundation, Inc.
+   Copyright (C) 1985, 1986, 1987, 1988, 1989, 1993, 1994, 1995,
+                 1996, 1997, 1999, 2000, 2001, 2002, 2003, 2004,
+                 2005, 2006 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
 
 This file is part of GNU Emacs.
 
@@ -16,8 +17,8 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with GNU Emacs; see the file COPYING.  If not, write to
 
 You should have received a copy of the GNU General Public License
 along with GNU Emacs; see the file COPYING.  If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.  */
 
 #include <config.h>
 #include <signal.h>
 
 #include <config.h>
 #include <signal.h>
@@ -45,6 +46,9 @@ Boston, MA 02111-1307, USA.  */
 #include <setjmp.h>
 #include <errno.h>
 
 #include <setjmp.h>
 #include <errno.h>
 
+#ifdef HAVE_GTK_AND_PTHREAD
+#include <pthread.h>
+#endif
 #ifdef MSDOS
 #include "msdos.h"
 #include <time.h>
 #ifdef MSDOS
 #include "msdos.h"
 #include <time.h>
@@ -62,6 +66,10 @@ Boston, MA 02111-1307, USA.  */
 #include <unistd.h>
 #endif
 
 #include <unistd.h>
 #endif
 
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+
 /* This is to get the definitions of the XK_ symbols.  */
 #ifdef HAVE_X_WINDOWS
 #include "xterm.h"
 /* This is to get the definitions of the XK_ symbols.  */
 #ifdef HAVE_X_WINDOWS
 #include "xterm.h"
@@ -117,6 +125,8 @@ struct backtrace
                           args points to slot holding list of
                           unevalled args */
     char evalargs;
                           args points to slot holding list of
                           unevalled args */
     char evalargs;
+    /* Nonzero means call value of debugger when done with this operation. */
+    char debug_on_exit;
   };
 
 #ifdef MULTI_KBOARD
   };
 
 #ifdef MULTI_KBOARD
@@ -129,8 +139,8 @@ KBOARD the_only_kboard;
 #endif
 
 /* Non-nil disable property on a command means
 #endif
 
 /* Non-nil disable property on a command means
-   do not execute it; call disabled-command-hook's value instead.  */
-Lisp_Object Qdisabled, Qdisabled_command_hook;
+   do not execute it; call disabled-command-function's value instead.  */
+Lisp_Object Qdisabled, Qdisabled_command_function;
 
 #define NUM_RECENT_KEYS (100)
 int recent_keys_index; /* Index for storing next element into recent_keys */
 
 #define NUM_RECENT_KEYS (100)
 int recent_keys_index; /* Index for storing next element into recent_keys */
@@ -371,12 +381,15 @@ Lisp_Object real_this_command;
    command is stored in this-original-command.  It is nil otherwise.  */
 Lisp_Object Vthis_original_command;
 
    command is stored in this-original-command.  It is nil otherwise.  */
 Lisp_Object Vthis_original_command;
 
-/* The value of point when the last command was executed.  */
+/* The value of point when the last command was started.  */
 int last_point_position;
 
 /* The buffer that was current when the last command was started.  */
 Lisp_Object last_point_position_buffer;
 
 int last_point_position;
 
 /* The buffer that was current when the last command was started.  */
 Lisp_Object last_point_position_buffer;
 
+/* The window that was selected when the last command was started.  */
+Lisp_Object last_point_position_window;
+
 /* The frame in which the last input event occurred, or Qmacro if the
    last event came from a macro.  We use this to determine when to
    generate switch-frame events.  This may be cleared by functions
 /* The frame in which the last input event occurred, or Qmacro if the
    last event came from a macro.  We use this to determine when to
    generate switch-frame events.  This may be cleared by functions
@@ -441,11 +454,6 @@ Lisp_Object Qecho_area_clear_hook;
 Lisp_Object Qpre_command_hook, Vpre_command_hook;
 Lisp_Object Qpost_command_hook, Vpost_command_hook;
 Lisp_Object Qcommand_hook_internal, Vcommand_hook_internal;
 Lisp_Object Qpre_command_hook, Vpre_command_hook;
 Lisp_Object Qpost_command_hook, Vpost_command_hook;
 Lisp_Object Qcommand_hook_internal, Vcommand_hook_internal;
-/* Hook run after a command if there's no more input soon.  */
-Lisp_Object Qpost_command_idle_hook, Vpost_command_idle_hook;
-
-/* Delay time in microseconds before running post-command-idle-hook.  */
-EMACS_INT post_command_idle_delay;
 
 /* List of deferred actions to be performed at a later time.
    The precise format isn't relevant here; we just check whether it is nil.  */
 
 /* List of deferred actions to be performed at a later time.
    The precise format isn't relevant here; we just check whether it is nil.  */
@@ -469,46 +477,12 @@ int input_pending;
 
 int meta_key;
 
 
 int meta_key;
 
-/* Non-zero means force key bindings update in parse_menu_item.  */
-
-int update_menu_bindings;
-
 extern char *pending_malloc_warning;
 
 /* Circular buffer for pre-read keyboard input.  */
 
 static struct input_event kbd_buffer[KBD_BUFFER_SIZE];
 
 extern char *pending_malloc_warning;
 
 /* Circular buffer for pre-read keyboard input.  */
 
 static struct input_event kbd_buffer[KBD_BUFFER_SIZE];
 
-/* Vector to GCPRO the Lisp objects referenced from kbd_buffer.
-
-   The interrupt-level event handlers will never enqueue an event on a
-   frame which is not in Vframe_list, and once an event is dequeued,
-   internal_last_event_frame or the event itself points to the frame.
-   So that's all fine.
-
-   But while the event is sitting in the queue, it's completely
-   unprotected.  Suppose the user types one command which will run for
-   a while and then delete a frame, and then types another event at
-   the frame that will be deleted, before the command gets around to
-   it.  Suppose there are no references to this frame elsewhere in
-   Emacs, and a GC occurs before the second event is dequeued.  Now we
-   have an event referring to a freed frame, which will crash Emacs
-   when it is dequeued.
-
-   Similar things happen when an event on a scroll bar is enqueued; the
-   window may be deleted while the event is in the queue.
-
-   So, we use this vector to protect the Lisp_Objects in the event
-   queue.  That way, they'll be dequeued as dead frames or windows,
-   but still valid Lisp objects.
-
-   If kbd_buffer[i].kind != NO_EVENT, then
-
-   AREF (kbd_buffer_gcpro, 2 * i) == kbd_buffer[i].frame_or_window.
-   AREF (kbd_buffer_gcpro, 2 * i + 1) == kbd_buffer[i].arg.  */
-
-static Lisp_Object kbd_buffer_gcpro;
-
 /* Pointer to next available character in kbd_buffer.
    If kbd_fetch_ptr == kbd_store_ptr, the buffer is empty.
    This may be kbd_buffer + KBD_BUFFER_SIZE, meaning that the
 /* Pointer to next available character in kbd_buffer.
    If kbd_fetch_ptr == kbd_store_ptr, the buffer is empty.
    This may be kbd_buffer + KBD_BUFFER_SIZE, meaning that the
@@ -544,14 +518,21 @@ Lisp_Object Qmake_frame_visible;
 Lisp_Object Qselect_window;
 Lisp_Object Qhelp_echo;
 
 Lisp_Object Qselect_window;
 Lisp_Object Qhelp_echo;
 
+#ifdef HAVE_MOUSE
+Lisp_Object Qmouse_fixup_help_message;
+#endif
+
 /* Symbols to denote kinds of events.  */
 Lisp_Object Qfunction_key;
 Lisp_Object Qmouse_click;
 /* Symbols to denote kinds of events.  */
 Lisp_Object Qfunction_key;
 Lisp_Object Qmouse_click;
-#ifdef WINDOWSNT
+#if defined (WINDOWSNT) || defined (MAC_OS)
 Lisp_Object Qlanguage_change;
 #endif
 Lisp_Object Qdrag_n_drop;
 Lisp_Object Qsave_session;
 Lisp_Object Qlanguage_change;
 #endif
 Lisp_Object Qdrag_n_drop;
 Lisp_Object Qsave_session;
+#ifdef MAC_OS
+Lisp_Object Qmac_apple_event;
+#endif
 
 /* Lisp_Object Qmouse_movement; - also an event header */
 
 
 /* Lisp_Object Qmouse_movement; - also an event header */
 
@@ -587,7 +568,7 @@ Lisp_Object Qvertical_scroll_bar;
 Lisp_Object Qmenu_bar;
 extern Lisp_Object Qleft_margin, Qright_margin;
 extern Lisp_Object Qleft_fringe, Qright_fringe;
 Lisp_Object Qmenu_bar;
 extern Lisp_Object Qleft_margin, Qright_margin;
 extern Lisp_Object Qleft_fringe, Qright_fringe;
-extern Lisp_Object Qimage;
+extern Lisp_Object QCmap;
 
 Lisp_Object recursive_edit_unwind (), command_loop ();
 Lisp_Object Fthis_command_keys ();
 
 Lisp_Object recursive_edit_unwind (), command_loop ();
 Lisp_Object Fthis_command_keys ();
@@ -635,7 +616,7 @@ int flow_control;
 
 /* We are unable to use interrupts if FIONREAD is not available,
    so flush SIGIO so we won't try.  */
 
 /* We are unable to use interrupts if FIONREAD is not available,
    so flush SIGIO so we won't try.  */
-#ifndef FIONREAD
+#if !defined (FIONREAD)
 #ifdef SIGIO
 #undef SIGIO
 #endif
 #ifdef SIGIO
 #undef SIGIO
 #endif
@@ -668,17 +649,25 @@ static EMACS_TIME timer_idleness_start_time;
 
 static EMACS_TIME timer_last_idleness_start_time;
 
 
 static EMACS_TIME timer_last_idleness_start_time;
 
+/* If non-nil, events produced by disabled menu items and tool-bar
+   buttons are not ignored.  Help functions bind this to allow help on
+   those items and buttons.  */
+Lisp_Object Venable_disabled_menus_and_buttons;
+
 \f
 /* Global variable declarations.  */
 
 \f
 /* Global variable declarations.  */
 
+/* Flags for readable_events.  */
+#define READABLE_EVENTS_DO_TIMERS_NOW          (1 << 0)
+#define READABLE_EVENTS_FILTER_EVENTS          (1 << 1)
+#define READABLE_EVENTS_IGNORE_SQUEEZABLES     (1 << 2)
+
 /* Function for init_keyboard to call with no args (if nonzero).  */
 void (*keyboard_init_hook) ();
 
 static int read_avail_input P_ ((int));
 static void get_input_pending P_ ((int *, int));
 /* Function for init_keyboard to call with no args (if nonzero).  */
 void (*keyboard_init_hook) ();
 
 static int read_avail_input P_ ((int));
 static void get_input_pending P_ ((int *, int));
-static void get_filtered_input_pending P_ ((int *, int, int));
 static int readable_events P_ ((int));
 static int readable_events P_ ((int));
-static int readable_filtered_events P_ ((int, int));
 static Lisp_Object read_char_x_menu_prompt P_ ((int, Lisp_Object *,
                                                Lisp_Object, int *));
 static Lisp_Object read_char_x_menu_prompt ();
 static Lisp_Object read_char_x_menu_prompt P_ ((int, Lisp_Object *,
                                                Lisp_Object, int *));
 static Lisp_Object read_char_x_menu_prompt ();
@@ -704,11 +693,16 @@ static Lisp_Object apply_modifiers P_ ((int, Lisp_Object));
 static void clear_event P_ ((struct input_event *));
 static void any_kboard_state P_ ((void));
 static SIGTYPE interrupt_signal P_ ((int signalnum));
 static void clear_event P_ ((struct input_event *));
 static void any_kboard_state P_ ((void));
 static SIGTYPE interrupt_signal P_ ((int signalnum));
+static void timer_start_idle P_ ((void));
+static void timer_stop_idle P_ ((void));
+static void timer_resume_idle P_ ((void));
 
 /* Nonzero means don't try to suspend even if the operating system seems
    to support it.  */
 static int cannot_suspend;
 
 
 /* Nonzero means don't try to suspend even if the operating system seems
    to support it.  */
 static int cannot_suspend;
 
+extern Lisp_Object Qidentity, Qonly;
+\f
 /* Install the string STR as the beginning of the string of echoing,
    so that it serves as a prompt for the next character.
    Also start echoing.  */
 /* Install the string STR as the beginning of the string of echoing,
    so that it serves as a prompt for the next character.
    Also start echoing.  */
@@ -801,6 +795,8 @@ echo_char (c)
          else
            echo_string = concat2 (echo_string, build_string (" "));
        }
          else
            echo_string = concat2 (echo_string, build_string (" "));
        }
+      else if (STRINGP (echo_string))
+       echo_string = concat2 (echo_string, build_string (" "));
 
       current_kboard->echo_string
        = concat2 (echo_string, make_string (buffer, ptr - buffer));
 
       current_kboard->echo_string
        = concat2 (echo_string, make_string (buffer, ptr - buffer));
@@ -828,6 +824,21 @@ echo_dash ()
       == SCHARS (current_kboard->echo_string))
     return;
 
       == SCHARS (current_kboard->echo_string))
     return;
 
+  /* Do nothing if we have already put a dash at the end.  */
+  if (SCHARS (current_kboard->echo_string) > 1)
+    {
+      Lisp_Object last_char, prev_char, idx;
+
+      idx = make_number (SCHARS (current_kboard->echo_string) - 2);
+      prev_char = Faref (current_kboard->echo_string, idx);
+
+      idx = make_number (SCHARS (current_kboard->echo_string) - 1);
+      last_char = Faref (current_kboard->echo_string, idx);
+
+      if (XINT (last_char) == '-' && XINT (prev_char) != ' ')
+       return;
+    }
+
   /* Put a dash at the end of the buffer temporarily,
      but make it go away when the next character is added.  */
   current_kboard->echo_string = concat2 (current_kboard->echo_string,
   /* Put a dash at the end of the buffer temporarily,
      but make it go away when the next character is added.  */
   current_kboard->echo_string = concat2 (current_kboard->echo_string,
@@ -1019,13 +1030,18 @@ DEFUN ("recursive-edit", Frecursive_edit, Srecursive_edit, 0, 0, "",
        doc: /* Invoke the editor command loop recursively.
 To get out of the recursive edit, a command can do `(throw 'exit nil)';
 that tells this function to return.
        doc: /* Invoke the editor command loop recursively.
 To get out of the recursive edit, a command can do `(throw 'exit nil)';
 that tells this function to return.
-Alternately, `(throw 'exit t)' makes this function signal an error.
+Alternatively, `(throw 'exit t)' makes this function signal an error.
 This function is called by the editor initialization to begin editing.  */)
      ()
 {
   int count = SPECPDL_INDEX ();
   Lisp_Object buffer;
 
 This function is called by the editor initialization to begin editing.  */)
      ()
 {
   int count = SPECPDL_INDEX ();
   Lisp_Object buffer;
 
+  /* If we enter while input is blocked, don't lock up here.
+     This may happen through the debugger during redisplay.  */
+  if (INPUT_BLOCKED_P)
+    return Qnil;
+
   command_loop_level++;
   update_mode_lines = 1;
 
   command_loop_level++;
   update_mode_lines = 1;
 
@@ -1095,6 +1111,19 @@ single_kboard_state ()
 #endif
 }
 
 #endif
 }
 
+/* If we're in single_kboard state for kboard KBOARD,
+   get out of it.  */
+
+void
+not_single_kboard_state (kboard)
+     KBOARD *kboard;
+{
+#ifdef MULTI_KBOARD
+  if (kboard == current_kboard)
+    single_kboard = 0;
+#endif
+}
+
 /* Maintain a stack of kboards, so other parts of Emacs
    can switch temporarily to the kboard of a given frame
    and then revert to the previous status.  */
 /* Maintain a stack of kboards, so other parts of Emacs
    can switch temporarily to the kboard of a given frame
    and then revert to the previous status.  */
@@ -1149,21 +1178,21 @@ cmd_error (data)
     cancel_hourglass ();
 #endif
 
     cancel_hourglass ();
 #endif
 
-  if (!NILP (executing_macro))
+  if (!NILP (executing_kbd_macro))
     {
     {
-      if (executing_macro_iterations == 1)
+      if (executing_kbd_macro_iterations == 1)
        sprintf (macroerror, "After 1 kbd macro iteration: ");
       else
        sprintf (macroerror, "After %d kbd macro iterations: ",
        sprintf (macroerror, "After 1 kbd macro iteration: ");
       else
        sprintf (macroerror, "After %d kbd macro iterations: ",
-                executing_macro_iterations);
+                executing_kbd_macro_iterations);
     }
   else
     *macroerror = 0;
 
   Vstandard_output = Qt;
   Vstandard_input = Qt;
     }
   else
     *macroerror = 0;
 
   Vstandard_output = Qt;
   Vstandard_input = Qt;
-  Vexecuting_macro = Qnil;
-  executing_macro = Qnil;
+  Vexecuting_kbd_macro = Qnil;
+  executing_kbd_macro = Qnil;
   current_kboard->Vprefix_arg = Qnil;
   current_kboard->Vlast_prefix_arg = Qnil;
   cancel_echoing ();
   current_kboard->Vprefix_arg = Qnil;
   current_kboard->Vlast_prefix_arg = Qnil;
   cancel_echoing ();
@@ -1181,7 +1210,8 @@ cmd_error (data)
 
   Vinhibit_quit = Qnil;
 #ifdef MULTI_KBOARD
 
   Vinhibit_quit = Qnil;
 #ifdef MULTI_KBOARD
-  any_kboard_state ();
+  if (command_loop_level == 0 && minibuf_level == 0)
+    any_kboard_state ();
 #endif
 
   return make_number (0);
 #endif
 
   return make_number (0);
@@ -1263,15 +1293,19 @@ command_loop ()
     {
       Lisp_Object val;
       val = internal_catch (Qexit, command_loop_2, Qnil);
     {
       Lisp_Object val;
       val = internal_catch (Qexit, command_loop_2, Qnil);
-      executing_macro = Qnil;
+      executing_kbd_macro = Qnil;
       return val;
     }
   else
     while (1)
       {
        internal_catch (Qtop_level, top_level_1, Qnil);
       return val;
     }
   else
     while (1)
       {
        internal_catch (Qtop_level, top_level_1, Qnil);
+       /* Reset single_kboard in case top-level set it while
+          evaluating an -f option, or we are stuck there for some
+          other reason.  */
+       any_kboard_state ();
        internal_catch (Qtop_level, command_loop_2, Qnil);
        internal_catch (Qtop_level, command_loop_2, Qnil);
-       executing_macro = Qnil;
+       executing_kbd_macro = Qnil;
 
        /* End of file in -batch run causes exit here.  */
        if (noninteractive)
 
        /* End of file in -batch run causes exit here.  */
        if (noninteractive)
@@ -1324,6 +1358,12 @@ DEFUN ("top-level", Ftop_level, Stop_level, 0, 0, "",
   if (display_hourglass_p)
     cancel_hourglass ();
 #endif
   if (display_hourglass_p)
     cancel_hourglass ();
 #endif
+
+  /* Unblock input if we enter with input blocked.  This may happen if
+     redisplay traps e.g. during tool-bar update with input blocked.  */
+  while (INPUT_BLOCKED_P)
+    UNBLOCK_INPUT;
+
   return Fthrow (Qtop_level, Qnil);
 }
 
   return Fthrow (Qtop_level, Qnil);
 }
 
@@ -1365,6 +1405,7 @@ cancel_hourglass_unwind (arg)
      Lisp_Object arg;
 {
   cancel_hourglass ();
      Lisp_Object arg;
 {
   cancel_hourglass ();
+  return Qnil;
 }
 #endif
 
 }
 #endif
 
@@ -1377,7 +1418,7 @@ command_loop_1 ()
   Lisp_Object keybuf[30];
   int i;
   int no_direct;
   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;
   struct buffer *prev_buffer = NULL;
 #ifdef MULTI_KBOARD
   int was_locked = single_kboard;
@@ -1410,21 +1451,9 @@ command_loop_1 ()
        resize_echo_area_exactly ();
 
       if (!NILP (Vdeferred_action_list))
        resize_echo_area_exactly ();
 
       if (!NILP (Vdeferred_action_list))
-       call0 (Vdeferred_action_function);
-
-      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);
-       }
+       safe_run_hooks (Qdeferred_action_function);
     }
 
     }
 
-  Vmemory_full = Qnil;
-
   /* Do this after running Vpost_command_hook, for consistency.  */
   current_kboard->Vlast_command = Vthis_command;
   current_kboard->Vreal_last_command = real_this_command;
   /* Do this after running Vpost_command_hook, for consistency.  */
   current_kboard->Vlast_command = Vthis_command;
   current_kboard->Vreal_last_command = real_this_command;
@@ -1488,7 +1517,7 @@ command_loop_1 ()
         Is this a good idea?  */
       if (FRAMEP (internal_last_event_frame)
          && !EQ (internal_last_event_frame, selected_frame))
         Is this a good idea?  */
       if (FRAMEP (internal_last_event_frame)
          && !EQ (internal_last_event_frame, selected_frame))
-       Fselect_frame (internal_last_event_frame, Qnil);
+       Fselect_frame (internal_last_event_frame);
 #endif
       /* If it has changed current-menubar from previous value,
         really recompute the menubar from the value.  */
 #endif
       /* If it has changed current-menubar from previous value,
         really recompute the menubar from the value.  */
@@ -1501,6 +1530,7 @@ command_loop_1 ()
 
       Vthis_command = Qnil;
       real_this_command = Qnil;
 
       Vthis_command = Qnil;
       real_this_command = Qnil;
+      Vthis_original_command = Qnil;
 
       /* Read next key sequence; i gets its length.  */
       i = read_key_sequence (keybuf, sizeof keybuf / sizeof keybuf[0],
 
       /* Read next key sequence; i gets its length.  */
       i = read_key_sequence (keybuf, sizeof keybuf / sizeof keybuf[0],
@@ -1546,11 +1576,11 @@ command_loop_1 ()
        }
 
       cmd = read_key_sequence_cmd;
        }
 
       cmd = read_key_sequence_cmd;
-      if (!NILP (Vexecuting_macro))
+      if (!NILP (Vexecuting_kbd_macro))
        {
          if (!NILP (Vquit_flag))
            {
        {
          if (!NILP (Vquit_flag))
            {
-             Vexecuting_macro = Qt;
+             Vexecuting_kbd_macro = Qt;
              QUIT;             /* Make some noise. */
                                /* Will return since macro now empty. */
            }
              QUIT;             /* Make some noise. */
                                /* Will return since macro now empty. */
            }
@@ -1561,6 +1591,7 @@ command_loop_1 ()
       prev_buffer = current_buffer;
       prev_modiff = MODIFF;
       last_point_position = PT;
       prev_buffer = current_buffer;
       prev_modiff = MODIFF;
       last_point_position = PT;
+      last_point_position_window = selected_window;
       XSETBUFFER (last_point_position_buffer, prev_buffer);
 
       /* By default, we adjust point to a boundary of a region that
       XSETBUFFER (last_point_position_buffer, prev_buffer);
 
       /* By default, we adjust point to a boundary of a region that
@@ -1596,7 +1627,10 @@ command_loop_1 ()
       if (NILP (Vthis_command))
        {
          /* nil means key is undefined.  */
       if (NILP (Vthis_command))
        {
          /* nil means key is undefined.  */
+         Lisp_Object keys = Fvector (i, keybuf);
+         keys = Fkey_description (keys, Qnil);
          bitch_at_user ();
          bitch_at_user ();
+         message_with_string ("%s is undefined", keys, 0);
          current_kboard->defining_kbd_macro = Qnil;
          update_mode_lines = 1;
          current_kboard->Vprefix_arg = Qnil;
          current_kboard->defining_kbd_macro = Qnil;
          update_mode_lines = 1;
          current_kboard->Vprefix_arg = Qnil;
@@ -1646,7 +1680,7 @@ command_loop_1 ()
                      && EQ (current_buffer->selective_display, Qnil)
                      && !detect_input_pending ()
                      && NILP (XWINDOW (selected_window)->column_number_displayed)
                      && EQ (current_buffer->selective_display, Qnil)
                      && !detect_input_pending ()
                      && NILP (XWINDOW (selected_window)->column_number_displayed)
-                     && NILP (Vexecuting_macro))
+                     && NILP (Vexecuting_kbd_macro))
                    direct_output_forward_char (1);
                  goto directly_done;
                }
                    direct_output_forward_char (1);
                  goto directly_done;
                }
@@ -1681,7 +1715,7 @@ command_loop_1 ()
                      && EQ (current_buffer->selective_display, Qnil)
                      && !detect_input_pending ()
                      && NILP (XWINDOW (selected_window)->column_number_displayed)
                      && EQ (current_buffer->selective_display, Qnil)
                      && !detect_input_pending ()
                      && NILP (XWINDOW (selected_window)->column_number_displayed)
-                     && NILP (Vexecuting_macro))
+                     && NILP (Vexecuting_kbd_macro))
                    direct_output_forward_char (-1);
                  goto directly_done;
                }
                    direct_output_forward_char (-1);
                  goto directly_done;
                }
@@ -1694,7 +1728,7 @@ command_loop_1 ()
                    = translate_char (Vtranslation_table_for_input,
                                      XFASTINT (last_command_char), 0, 0, 0);
                  int value;
                    = translate_char (Vtranslation_table_for_input,
                                      XFASTINT (last_command_char), 0, 0, 0);
                  int value;
-                 if (NILP (Vexecuting_macro)
+                 if (NILP (Vexecuting_kbd_macro)
                      && !EQ (minibuf_window, selected_window))
                    {
                      if (!nonundocount || nonundocount >= 20)
                      && !EQ (minibuf_window, selected_window))
                    {
                      if (!nonundocount || nonundocount >= 20)
@@ -1716,7 +1750,7 @@ command_loop_1 ()
                          || !EQ (current_buffer->selective_display, Qnil)
                          || detect_input_pending ()
                          || !NILP (XWINDOW (selected_window)->column_number_displayed)
                          || !EQ (current_buffer->selective_display, Qnil)
                          || detect_input_pending ()
                          || !NILP (XWINDOW (selected_window)->column_number_displayed)
-                         || !NILP (Vexecuting_macro));
+                         || !NILP (Vexecuting_kbd_macro));
 
                  value = internal_self_insert (c, 0);
 
 
                  value = internal_self_insert (c, 0);
 
@@ -1744,7 +1778,7 @@ command_loop_1 ()
             int scount = SPECPDL_INDEX ();
 
             if (display_hourglass_p
             int scount = SPECPDL_INDEX ();
 
             if (display_hourglass_p
-                && NILP (Vexecuting_macro))
+                && NILP (Vexecuting_kbd_macro))
               {
                 record_unwind_protect (cancel_hourglass_unwind, Qnil);
                 start_hourglass ();
               {
                 record_unwind_protect (cancel_hourglass_unwind, Qnil);
                 start_hourglass ();
@@ -1762,7 +1796,7 @@ command_loop_1 ()
             hourglass cursor anyway.
             But don't cancel the hourglass within a macro
             just because a command in the macro finishes.  */
             hourglass cursor anyway.
             But don't cancel the hourglass within a macro
             just because a command in the macro finishes.  */
-         if (NILP (Vexecuting_macro))
+         if (NILP (Vexecuting_kbd_macro))
             unbind_to (scount, Qnil);
 #endif
           }
             unbind_to (scount, Qnil);
 #endif
           }
@@ -1783,16 +1817,6 @@ command_loop_1 ()
       if (!NILP (Vdeferred_action_list))
        safe_run_hooks (Qdeferred_action_function);
 
       if (!NILP (Vdeferred_action_list))
        safe_run_hooks (Qdeferred_action_function);
 
-      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);
-       }
-
       /* If there is a prefix argument,
         1) We don't want Vlast_command to be ``universal-argument''
         (that would be dumb), so don't set Vlast_command,
       /* If there is a prefix argument,
         1) We don't want Vlast_command to be ``universal-argument''
         (that would be dumb), so don't set Vlast_command,
@@ -1818,6 +1842,14 @@ command_loop_1 ()
 
       if (!NILP (current_buffer->mark_active) && !NILP (Vrun_hooks))
        {
 
       if (!NILP (current_buffer->mark_active) && !NILP (Vrun_hooks))
        {
+         /* Setting transient-mark-mode to `only' is a way of
+            turning it on for just one command.  */
+
+         if (EQ (Vtransient_mark_mode, Qidentity))
+           Vtransient_mark_mode = Qnil;
+         if (EQ (Vtransient_mark_mode, Qonly))
+           Vtransient_mark_mode = Qidentity;
+
          if (!NILP (Vdeactivate_mark) && !NILP (Vtransient_mark_mode))
            {
              /* We could also call `deactivate'mark'.  */
          if (!NILP (Vdeactivate_mark) && !NILP (Vtransient_mark_mode))
            {
              /* We could also call `deactivate'mark'.  */
@@ -1900,10 +1932,13 @@ adjust_point_for_property (last_pt, modified)
              ? get_property_and_range (PT, Qdisplay, &val, &beg, &end, Qnil)
              : (beg = OVERLAY_POSITION (OVERLAY_START (overlay)),
                 end = OVERLAY_POSITION (OVERLAY_END (overlay))))
              ? get_property_and_range (PT, Qdisplay, &val, &beg, &end, Qnil)
              : (beg = OVERLAY_POSITION (OVERLAY_START (overlay)),
                 end = OVERLAY_POSITION (OVERLAY_END (overlay))))
-         && beg < PT) /* && end > PT   <- It's always the case.  */
+         && (beg < PT /* && end > PT   <- It's always the case.  */
+             || (beg <= PT && STRINGP (val) && SCHARS (val) == 0)))
        {
          xassert (end > PT);
        {
          xassert (end > PT);
-         SET_PT (PT < last_pt ? beg : end);
+         SET_PT (PT < last_pt
+                 ? (STRINGP (val) && SCHARS (val) == 0 ? beg - 1 : beg)
+                 : end);
          check_composition = check_invisible = 1;
        }
       check_display = 0;
          check_composition = check_invisible = 1;
        }
       check_display = 0;
@@ -1958,7 +1993,12 @@ adjust_point_for_property (last_pt, modified)
                      : (PT < last_pt ? beg : end));
              check_composition = check_display = 1;
            }
                      : (PT < last_pt ? beg : end));
              check_composition = check_display = 1;
            }
+#if 0 /* This assertion isn't correct, because SET_PT may end up setting
+        the point to something other than its argument, due to
+        point-motion hooks, intangibility, etc.  */
          xassert (PT == beg || PT == end);
          xassert (PT == beg || PT == end);
+#endif
+
          /* Pretend the area doesn't exist if the buffer is not
             modified.  */
          if (!modified && !ellipsis && beg < end)
          /* Pretend the area doesn't exist if the buffer is not
             modified.  */
          if (!modified && !ellipsis && beg < end)
@@ -2063,7 +2103,11 @@ poll_for_input (timer)
      struct atimer *timer;
 {
   if (poll_suppress_count == 0)
      struct atimer *timer;
 {
   if (poll_suppress_count == 0)
+#ifdef SYNC_INPUT
+    interrupt_input_pending = 1;
+#else
     poll_for_input_1 ();
     poll_for_input_1 ();
+#endif
 }
 
 #endif /* POLL_FOR_INPUT */
 }
 
 #endif /* POLL_FOR_INPUT */
@@ -2206,12 +2250,16 @@ make_ctrl_char (c)
   return c;
 }
 
   return c;
 }
 
-/* Display help echo in the echo area.
+/* Display the help-echo property of the character after the mouse pointer.
+   Either show it in the echo area, or call show-help-function to display
+   it by other means (maybe in a tooltip).
+
+   If HELP is nil, that means clear the previous help echo.
 
 
-   HELP a string means display that string, HELP nil means clear the
-   help echo.  If HELP is a function, call it with OBJECT and POS as
-   arguments; the function should return a help string or nil for
-   none.  For all other types of HELP evaluate it to obtain a string.
+   If HELP is a string, display that string.  If HELP is a function,
+   call it with OBJECT and POS as arguments; the function should
+   return a help string or nil for none.  For all other types of HELP,
+   evaluate it to obtain a string.
 
    WINDOW is the window in which the help was generated, if any.
    It is nil if not in a window.
 
    WINDOW is the window in which the help was generated, if any.
    It is nil if not in a window.
@@ -2256,6 +2304,11 @@ show_help_echo (help, window, object, pos, ok_to_overwrite_keystroke_echo)
        return;
     }
 
        return;
     }
 
+#ifdef HAVE_MOUSE
+  if (!noninteractive && STRINGP (help))
+    help = call1 (Qmouse_fixup_help_message, help);
+#endif
+
   if (STRINGP (help) || NILP (help))
     {
       if (!NILP (Vshow_help_function))
   if (STRINGP (help) || NILP (help))
     {
       if (!NILP (Vshow_help_function))
@@ -2353,7 +2406,6 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
   volatile Lisp_Object also_record;
   volatile int reread;
   struct gcpro gcpro1, gcpro2;
   volatile Lisp_Object also_record;
   volatile int reread;
   struct gcpro gcpro1, gcpro2;
-  EMACS_TIME last_idle_start;
   int polling_stopped_here = 0;
 
   also_record = Qnil;
   int polling_stopped_here = 0;
 
   also_record = Qnil;
@@ -2435,7 +2487,7 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
 
   this_command_key_count_reset = 0;
 
 
   this_command_key_count_reset = 0;
 
-  if (!NILP (Vexecuting_macro))
+  if (!NILP (Vexecuting_kbd_macro))
     {
       /* We set this to Qmacro; since that's not a frame, nobody will
         try to switch frames on us, and the selected window will
     {
       /* We set this to Qmacro; since that's not a frame, nobody will
         try to switch frames on us, and the selected window will
@@ -2452,19 +2504,19 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
       /* Exit the macro if we are at the end.
         Also, some things replace the macro with t
         to force an early exit.  */
       /* Exit the macro if we are at the end.
         Also, some things replace the macro with t
         to force an early exit.  */
-      if (EQ (Vexecuting_macro, Qt)
-         || executing_macro_index >= XFASTINT (Flength (Vexecuting_macro)))
+      if (EQ (Vexecuting_kbd_macro, Qt)
+         || executing_kbd_macro_index >= XFASTINT (Flength (Vexecuting_kbd_macro)))
        {
          XSETINT (c, -1);
          goto exit;
        }
 
        {
          XSETINT (c, -1);
          goto exit;
        }
 
-      c = Faref (Vexecuting_macro, make_number (executing_macro_index));
-      if (STRINGP (Vexecuting_macro)
-         && (XINT (c) & 0x80))
+      c = Faref (Vexecuting_kbd_macro, make_number (executing_kbd_macro_index));
+      if (STRINGP (Vexecuting_kbd_macro)
+         && (XINT (c) & 0x80) && (XUINT (c) <= 0xff))
        XSETFASTINT (c, CHAR_META | (XINT (c) & ~0x80));
 
        XSETFASTINT (c, CHAR_META | (XINT (c) & ~0x80));
 
-      executing_macro_index++;
+      executing_kbd_macro_index++;
 
       goto from_macro;
     }
 
       goto from_macro;
     }
@@ -2573,6 +2625,9 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
 
   if (_setjmp (local_getcjmp))
     {
 
   if (_setjmp (local_getcjmp))
     {
+      /* We must have saved the outer value of getcjmp here,
+        so restore it now.  */
+      restore_getcjmp (save_jump);
       XSETINT (c, quit_char);
       internal_last_event_frame = selected_frame;
       Vlast_event_frame = internal_last_event_frame;
       XSETINT (c, quit_char);
       internal_last_event_frame = selected_frame;
       Vlast_event_frame = internal_last_event_frame;
@@ -2860,9 +2915,6 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
 
  non_reread:
 
 
  non_reread:
 
-  /* Record the last idle start time so that we can reset it
-     should the next event read be a help-echo.  */
-  last_idle_start = timer_idleness_start_time;
   timer_stop_idle ();
   RESUME_POLLING;
 
   timer_stop_idle ();
   RESUME_POLLING;
 
@@ -2902,7 +2954,7 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
           prevents automatic window selection (under
           mouse_autoselect_window from acting as a real input event, for
           example banishing the mouse under mouse-avoidance-mode.  */
           prevents automatic window selection (under
           mouse_autoselect_window from acting as a real input event, for
           example banishing the mouse under mouse-avoidance-mode.  */
-       timer_idleness_start_time = last_idle_start;
+       timer_resume_idle ();
 
       /* Resume allowing input from any kboard, if that was true before.  */
       if (!was_locked)
 
       /* Resume allowing input from any kboard, if that was true before.  */
       if (!was_locked)
@@ -2943,13 +2995,13 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
     {
       Lisp_Object posn;
 
     {
       Lisp_Object posn;
 
-      posn = POSN_BUFFER_POSN (EVENT_START (c));
+      posn = POSN_POSN (EVENT_START (c));
       /* Handle menu-bar events:
         insert the dummy prefix event `menu-bar'.  */
       if (EQ (posn, Qmenu_bar) || EQ (posn, Qtool_bar))
        {
          /* Change menu-bar to (menu-bar) as the event "position".  */
       /* Handle menu-bar events:
         insert the dummy prefix event `menu-bar'.  */
       if (EQ (posn, Qmenu_bar) || EQ (posn, Qtool_bar))
        {
          /* Change menu-bar to (menu-bar) as the event "position".  */
-         POSN_BUFFER_SET_POSN (EVENT_START (c), Fcons (posn, Qnil));
+         POSN_SET_POSN (EVENT_START (c), Fcons (posn, Qnil));
 
          also_record = c;
          Vunread_command_events = Fcons (c, Vunread_command_events);
 
          also_record = c;
          Vunread_command_events = Fcons (c, Vunread_command_events);
@@ -3007,6 +3059,7 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
       /* Save the echo status.  */
       int saved_immediate_echo = current_kboard->immediate_echo;
       struct kboard *saved_ok_to_echo = ok_to_echo_at_next_pause;
       /* Save the echo status.  */
       int saved_immediate_echo = current_kboard->immediate_echo;
       struct kboard *saved_ok_to_echo = ok_to_echo_at_next_pause;
+      Lisp_Object saved_echo_string = current_kboard->echo_string;
       int saved_echo_after_prompt = current_kboard->echo_after_prompt;
 
 #if 0
       int saved_echo_after_prompt = current_kboard->echo_after_prompt;
 
 #if 0
@@ -3061,6 +3114,7 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
 
       cancel_echoing ();
       ok_to_echo_at_next_pause = saved_ok_to_echo;
 
       cancel_echoing ();
       ok_to_echo_at_next_pause = saved_ok_to_echo;
+      current_kboard->echo_string = saved_echo_string;
       current_kboard->echo_after_prompt = saved_echo_after_prompt;
       if (saved_immediate_echo)
        echo_now ();
       current_kboard->echo_after_prompt = saved_echo_after_prompt;
       if (saved_immediate_echo)
        echo_now ();
@@ -3101,7 +3155,7 @@ 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.  */
       show_help_echo (help, window, object, position, 0);
 
       /* We stopped being idle for this event; undo that.  */
-      timer_idleness_start_time = last_idle_start;
+      timer_resume_idle ();
       goto retry;
     }
 
       goto retry;
     }
 
@@ -3402,10 +3456,11 @@ tracking_off (old_value)
         input has been processed.  If the only input available was
         the sort that we have just disabled, then we need to call
         redisplay.  */
         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 (1))
+      if (!readable_events (READABLE_EVENTS_DO_TIMERS_NOW))
        {
          redisplay_preserve_echo_area (6);
        {
          redisplay_preserve_echo_area (6);
-         get_input_pending (&input_pending, 1);
+         get_input_pending (&input_pending,
+                            READABLE_EVENTS_DO_TIMERS_NOW);
        }
     }
   return Qnil;
        }
     }
   return Qnil;
@@ -3457,20 +3512,21 @@ some_mouse_moved ()
 /* Return true iff there are any events in the queue that read-char
    would return.  If this returns false, a read-char would block.  */
 static int
 /* Return true iff there are any events in the queue that read-char
    would return.  If this returns false, a read-char would block.  */
 static int
-readable_filtered_events (do_timers_now, filter_events)
-     int do_timers_now;
-     int filter_events;
+readable_events (flags)
+     int flags;
 {
 {
-  if (do_timers_now)
-    timer_check (do_timers_now);
+  if (flags & READABLE_EVENTS_DO_TIMERS_NOW)
+    timer_check (1);
 
 
-  /* If the buffer contains only FOCUS_IN_EVENT events,
-     and FILTER_EVENTS is nonzero, report it as empty.  */
+  /* If the buffer contains only FOCUS_IN_EVENT events, and
+     READABLE_EVENTS_FILTER_EVENTS is set, report it as empty.  */
   if (kbd_fetch_ptr != kbd_store_ptr)
     {
   if (kbd_fetch_ptr != kbd_store_ptr)
     {
-      int have_live_event = 1;
-
-      if (filter_events)
+      if (flags & (READABLE_EVENTS_FILTER_EVENTS
+#ifdef USE_TOOLKIT_SCROLL_BARS
+                  | READABLE_EVENTS_IGNORE_SQUEEZABLES
+#endif
+                  ))
         {
           struct input_event *event;
 
         {
           struct input_event *event;
 
@@ -3478,20 +3534,34 @@ readable_filtered_events (do_timers_now, filter_events)
                    ? kbd_fetch_ptr
                    : kbd_buffer);
 
                    ? kbd_fetch_ptr
                    : kbd_buffer);
 
-          while (have_live_event && event->kind == FOCUS_IN_EVENT)
-            {
-              event++;
+         do
+           {
+             if (!(
+#ifdef USE_TOOLKIT_SCROLL_BARS
+                   (flags & READABLE_EVENTS_FILTER_EVENTS) &&
+#endif
+                   event->kind == FOCUS_IN_EVENT)
+#ifdef USE_TOOLKIT_SCROLL_BARS
+                 && !((flags & READABLE_EVENTS_IGNORE_SQUEEZABLES)
+                      && event->kind == SCROLL_BAR_CLICK_EVENT
+                      && event->part == scroll_bar_handle
+                      && event->modifiers == 0)
+#endif
+                 )
+               return 1;
+             event++;
               if (event == kbd_buffer + KBD_BUFFER_SIZE)
                 event = kbd_buffer;
               if (event == kbd_buffer + KBD_BUFFER_SIZE)
                 event = kbd_buffer;
-              if (event == kbd_store_ptr)
-                have_live_event = 0;
-            }
+           }
+         while (event != kbd_store_ptr);
         }
         }
-      if (have_live_event) return 1;
+      else
+       return 1;
     }
 
 #ifdef HAVE_MOUSE
     }
 
 #ifdef HAVE_MOUSE
-  if (!NILP (do_mouse_tracking) && some_mouse_moved ())
+  if (!(flags & READABLE_EVENTS_IGNORE_SQUEEZABLES)
+      && !NILP (do_mouse_tracking) && some_mouse_moved ())
     return 1;
 #endif
   if (single_kboard)
     return 1;
 #endif
   if (single_kboard)
@@ -3509,15 +3579,6 @@ readable_filtered_events (do_timers_now, filter_events)
   return 0;
 }
 
   return 0;
 }
 
-/* Return true iff there are any events in the queue that read-char
-   would return.  If this returns false, a read-char would block.  */
-static int
-readable_events (do_timers_now)
-     int do_timers_now;
-{
-  return readable_filtered_events (do_timers_now, 0);
-}
-
 /* Set this for debugging, to have a way to get out */
 int stop_character;
 
 /* Set this for debugging, to have a way to get out */
 int stop_character;
 
@@ -3543,15 +3604,41 @@ event_to_kboard (event)
 }
 #endif
 
 }
 #endif
 
+
+Lisp_Object Vthrow_on_input;
+
 /* Store an event obtained at interrupt level into kbd_buffer, fifo */
 
 void
 kbd_buffer_store_event (event)
      register struct input_event *event;
 /* Store an event obtained at interrupt level into kbd_buffer, fifo */
 
 void
 kbd_buffer_store_event (event)
      register struct input_event *event;
+{
+  kbd_buffer_store_event_hold (event, 0);
+}
+
+/* Store EVENT obtained at interrupt level into kbd_buffer, fifo.
+
+   If HOLD_QUIT is 0, just stuff EVENT into the fifo.
+   Else, if HOLD_QUIT.kind != NO_EVENT, discard EVENT.
+   Else, if EVENT is a quit event, store the quit event
+   in HOLD_QUIT, and return (thus ignoring further events).
+
+   This is used in read_avail_input to postpone the processing
+   of the quit event until all subsequent input events have been
+   parsed (and discarded).
+ */
+
+void
+kbd_buffer_store_event_hold (event, hold_quit)
+     register struct input_event *event;
+     struct input_event *hold_quit;
 {
   if (event->kind == NO_EVENT)
     abort ();
 
 {
   if (event->kind == NO_EVENT)
     abort ();
 
+  if (hold_quit && hold_quit->kind != NO_EVENT)
+    return;
+
   if (event->kind == ASCII_KEYSTROKE_EVENT)
     {
       register int c = event->code & 0377;
   if (event->kind == ASCII_KEYSTROKE_EVENT)
     {
       register int c = event->code & 0377;
@@ -3593,6 +3680,12 @@ kbd_buffer_store_event (event)
            }
 #endif
 
            }
 #endif
 
+         if (hold_quit)
+           {
+             bcopy (event, (char *) hold_quit, sizeof (*event));
+             return;
+           }
+
          /* If this results in a quit_char being returned to Emacs as
             input, set Vlast_event_frame properly.  If this doesn't
             get returned to Emacs as an event, the next event read
          /* If this results in a quit_char being returned to Emacs as
             input, set Vlast_event_frame properly.  If this doesn't
             get returned to Emacs as an event, the next event read
@@ -3622,7 +3715,9 @@ kbd_buffer_store_event (event)
      Just ignore the second one.  */
   else if (event->kind == BUFFER_SWITCH_EVENT
           && kbd_fetch_ptr != kbd_store_ptr
      Just ignore the second one.  */
   else if (event->kind == BUFFER_SWITCH_EVENT
           && kbd_fetch_ptr != kbd_store_ptr
-          && kbd_store_ptr->kind == BUFFER_SWITCH_EVENT)
+          && ((kbd_store_ptr == kbd_buffer
+               ? kbd_buffer + KBD_BUFFER_SIZE - 1
+               : kbd_store_ptr - 1)->kind) == BUFFER_SWITCH_EVENT)
     return;
 
   if (kbd_store_ptr - kbd_buffer == KBD_BUFFER_SIZE)
     return;
 
   if (kbd_store_ptr - kbd_buffer == KBD_BUFFER_SIZE)
@@ -3634,40 +3729,44 @@ kbd_buffer_store_event (event)
      Discard the event if it would fill the last slot.  */
   if (kbd_fetch_ptr - 1 != kbd_store_ptr)
     {
      Discard the event if it would fill the last slot.  */
   if (kbd_fetch_ptr - 1 != kbd_store_ptr)
     {
-      int idx;
+      *kbd_store_ptr = *event;
+      ++kbd_store_ptr;
+    }
 
 
-#if 0 /* The SELECTION_REQUEST_EVENT case looks bogus, and it's error
-        prone to assign individual members for other events, in case
-        the input_event structure is changed.  --2000-07-13, gerd.  */
-      struct input_event *sp = kbd_store_ptr;
-      sp->kind = event->kind;
-      if (event->kind == SELECTION_REQUEST_EVENT)
+  /* If we're inside while-no-input, and this event qualifies
+     as input, set quit-flag to cause an interrupt.  */
+  if (!NILP (Vthrow_on_input)
+      && event->kind != FOCUS_IN_EVENT
+      && event->kind != HELP_EVENT
+      && event->kind != DEICONIFY_EVENT)
+    {
+      Vquit_flag = Vthrow_on_input;
+      /* If we're inside a function that wants immediate quits,
+        do it now.  */
+      if (immediate_quit && NILP (Vinhibit_quit))
        {
        {
-         /* We must not use the ordinary copying code for this case,
-            since `part' is an enum and copying it might not copy enough
-            in this case.  */
-         bcopy (event, (char *) sp, sizeof (*event));
+         immediate_quit = 0;
+         sigfree ();
+         QUIT;
        }
        }
-      else
+    }
+}
 
 
-       {
-         sp->code = event->code;
-         sp->part = event->part;
-         sp->frame_or_window = event->frame_or_window;
-         sp->arg = event->arg;
-         sp->modifiers = event->modifiers;
-         sp->x = event->x;
-         sp->y = event->y;
-         sp->timestamp = event->timestamp;
-       }
-#else
-      *kbd_store_ptr = *event;
-#endif
 
 
-      idx = 2 * (kbd_store_ptr - kbd_buffer);
-      ASET (kbd_buffer_gcpro, idx, event->frame_or_window);
-      ASET (kbd_buffer_gcpro, idx + 1, event->arg);
-      ++kbd_store_ptr;
+/* Put an input event back in the head of the event queue.  */
+
+void
+kbd_buffer_unget_event (event)
+     register struct input_event *event;
+{
+  if (kbd_fetch_ptr == kbd_buffer)
+    kbd_fetch_ptr = kbd_buffer + KBD_BUFFER_SIZE;
+
+  /* Don't let the very last slot in the buffer become full,  */
+  if (kbd_fetch_ptr - 1 != kbd_store_ptr)
+    {
+      --kbd_fetch_ptr;
+      *kbd_fetch_ptr = *event;
     }
 }
 
     }
 }
 
@@ -3685,24 +3784,22 @@ kbd_buffer_store_event (event)
 
    Value is the number of input_events generated.  */
 
 
    Value is the number of input_events generated.  */
 
-int
-gen_help_event (bufp, size, help, frame, window, object, pos)
-     struct input_event *bufp;
-     int size;
+void
+gen_help_event (help, frame, window, object, pos)
      Lisp_Object help, frame, object, window;
      int pos;
 {
      Lisp_Object help, frame, object, window;
      int pos;
 {
-  if (size >= 1)
-    {
-      bufp->kind = HELP_EVENT;
-      bufp->frame_or_window = frame;
-      bufp->arg = object;
-      bufp->x = WINDOWP (window) ? window : frame;
-      bufp->y = help;
-      bufp->code = pos;
-      return 1;
-    }
-  return 0;
+  struct input_event event;
+
+  EVENT_INIT (event);
+
+  event.kind = HELP_EVENT;
+  event.frame_or_window = frame;
+  event.arg = object;
+  event.x = WINDOWP (window) ? window : frame;
+  event.y = help;
+  event.code = pos;
+  kbd_buffer_store_event (&event);
 }
 
 
 }
 
 
@@ -3782,9 +3879,6 @@ static INLINE void
 clear_event (event)
      struct input_event *event;
 {
 clear_event (event)
      struct input_event *event;
 {
-  int idx = 2 * (event - kbd_buffer);
-  ASET (kbd_buffer_gcpro, idx, Qnil);
-  ASET (kbd_buffer_gcpro, idx + 1, Qnil);
   event->kind = NO_EVENT;
 }
 
   event->kind = NO_EVENT;
 }
 
@@ -3843,10 +3937,7 @@ kbd_buffer_get_event (kbp, used_mouse_menu)
        break;
 #endif
       {
        break;
 #endif
       {
-       Lisp_Object minus_one;
-
-       XSETINT (minus_one, -1);
-       wait_reading_process_input (0, 0, minus_one, 1);
+       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.  */
 
        if (!interrupt_input && kbd_fetch_ptr == kbd_store_ptr)
          /* Pass 1 for EXPECT since we just waited to have input.  */
@@ -3890,7 +3981,8 @@ kbd_buffer_get_event (kbp, used_mouse_menu)
       /* These two kinds of events get special handling
         and don't actually appear to the command loop.
         We return nil for them.  */
       /* These two kinds of events get special handling
         and don't actually appear to the command loop.
         We return nil for them.  */
-      if (event->kind == SELECTION_REQUEST_EVENT)
+      if (event->kind == SELECTION_REQUEST_EVENT
+         || event->kind == SELECTION_CLEAR_EVENT)
        {
 #ifdef HAVE_X11
          struct input_event copy;
        {
 #ifdef HAVE_X11
          struct input_event copy;
@@ -3901,7 +3993,7 @@ kbd_buffer_get_event (kbp, used_mouse_menu)
          copy = *event;
          kbd_fetch_ptr = event + 1;
          input_pending = readable_events (0);
          copy = *event;
          kbd_fetch_ptr = event + 1;
          input_pending = readable_events (0);
-         x_handle_selection_request (&copy);
+         x_handle_selection_event (&copy);
 #else
          /* We're getting selection request events, but we don't have
              a window system.  */
 #else
          /* We're getting selection request events, but we don't have
              a window system.  */
@@ -3909,22 +4001,6 @@ kbd_buffer_get_event (kbp, used_mouse_menu)
 #endif
        }
 
 #endif
        }
 
-      else if (event->kind == SELECTION_CLEAR_EVENT)
-       {
-#ifdef HAVE_X11
-         struct input_event copy;
-
-         /* Remove it from the buffer before processing it.  */
-         copy = *event;
-         kbd_fetch_ptr = event + 1;
-         input_pending = readable_events (0);
-         x_handle_selection_clear (&copy);
-#else
-         /* We're getting selection request events, but we don't have
-             a window system.  */
-         abort ();
-#endif
-       }
 #if defined (HAVE_X11) || defined (HAVE_NTGUI) || defined (MAC_OS)
       else if (event->kind == DELETE_WINDOW_EVENT)
        {
 #if defined (HAVE_X11) || defined (HAVE_NTGUI) || defined (MAC_OS)
       else if (event->kind == DELETE_WINDOW_EVENT)
        {
@@ -3934,7 +4010,7 @@ kbd_buffer_get_event (kbp, used_mouse_menu)
          kbd_fetch_ptr = event + 1;
        }
 #endif
          kbd_fetch_ptr = event + 1;
        }
 #endif
-#if defined (HAVE_X11) || defined (HAVE_NTGUI)
+#if defined (HAVE_X11) || defined (HAVE_NTGUI) || defined (MAC_OS)
       else if (event->kind == ICONIFY_EVENT)
        {
          /* Make an event (iconify-frame (FRAME)).  */
       else if (event->kind == ICONIFY_EVENT)
        {
          /* Make an event (iconify-frame (FRAME)).  */
@@ -3966,13 +4042,16 @@ kbd_buffer_get_event (kbp, used_mouse_menu)
            x_activate_menubar (XFRAME (event->frame_or_window));
        }
 #endif
            x_activate_menubar (XFRAME (event->frame_or_window));
        }
 #endif
-#ifdef WINDOWSNT
+#if defined (WINDOWSNT) || defined (MAC_OS)
       else if (event->kind == LANGUAGE_CHANGE_EVENT)
        {
       else if (event->kind == LANGUAGE_CHANGE_EVENT)
        {
+#ifdef MAC_OS
+         /* Make an event (language-change (KEY_SCRIPT)).  */
+         obj = Fcons (make_number (event->code), Qnil);
+#else
          /* Make an event (language-change (FRAME CHARSET LCID)).  */
          /* Make an event (language-change (FRAME CHARSET LCID)).  */
-         obj = Fcons (event->modifiers, Qnil);
-         obj = Fcons (event->code, obj);
-         obj = Fcons (event->frame_or_window, obj);
+         obj = Fcons (event->frame_or_window, Qnil);
+#endif
          obj = Fcons (Qlanguage_change, Fcons (obj, Qnil));
          kbd_fetch_ptr = event + 1;
        }
          obj = Fcons (Qlanguage_change, Fcons (obj, Qnil));
          kbd_fetch_ptr = event + 1;
        }
@@ -4151,7 +4230,8 @@ swallow_events (do_display)
 
       /* These two kinds of events get special handling
         and don't actually appear to the command loop.  */
 
       /* These two kinds of events get special handling
         and don't actually appear to the command loop.  */
-      if (event->kind == SELECTION_REQUEST_EVENT)
+      if (event->kind == SELECTION_REQUEST_EVENT
+         || event->kind == SELECTION_CLEAR_EVENT)
        {
 #ifdef HAVE_X11
          struct input_event copy;
        {
 #ifdef HAVE_X11
          struct input_event copy;
@@ -4162,25 +4242,7 @@ swallow_events (do_display)
          copy = *event;
          kbd_fetch_ptr = event + 1;
          input_pending = readable_events (0);
          copy = *event;
          kbd_fetch_ptr = event + 1;
          input_pending = readable_events (0);
-         x_handle_selection_request (&copy);
-#else
-         /* We're getting selection request events, but we don't have
-             a window system.  */
-         abort ();
-#endif
-       }
-
-      else if (event->kind == SELECTION_CLEAR_EVENT)
-       {
-#ifdef HAVE_X11
-         struct input_event copy;
-
-         /* Remove it from the buffer before processing it,  */
-         copy = *event;
-
-         kbd_fetch_ptr = event + 1;
-         input_pending = readable_events (0);
-         x_handle_selection_clear (&copy);
+         x_handle_selection_event (&copy);
 #else
          /* We're getting selection request events, but we don't have
              a window system.  */
 #else
          /* We're getting selection request events, but we don't have
              a window system.  */
@@ -4192,7 +4254,7 @@ swallow_events (do_display)
     }
 
   old_timers_run = timers_run;
     }
 
   old_timers_run = timers_run;
-  get_input_pending (&input_pending, 1);
+  get_input_pending (&input_pending, READABLE_EVENTS_DO_TIMERS_NOW);
 
   if (timers_run != old_timers_run && do_display)
     redisplay_preserve_echo_area (7);
 
   if (timers_run != old_timers_run && do_display)
     redisplay_preserve_echo_area (7);
@@ -4201,7 +4263,7 @@ swallow_events (do_display)
 /* Record the start of when Emacs is idle,
    for the sake of running idle-time timers.  */
 
 /* Record the start of when Emacs is idle,
    for the sake of running idle-time timers.  */
 
-void
+static void
 timer_start_idle ()
 {
   Lisp_Object timers;
 timer_start_idle ()
 {
   Lisp_Object timers;
@@ -4229,12 +4291,23 @@ timer_start_idle ()
 
 /* Record that Emacs is no longer idle, so stop running idle-time timers.  */
 
 
 /* Record that Emacs is no longer idle, so stop running idle-time timers.  */
 
-void
+static void
 timer_stop_idle ()
 {
   EMACS_SET_SECS_USECS (timer_idleness_start_time, -1, -1);
 }
 
 timer_stop_idle ()
 {
   EMACS_SET_SECS_USECS (timer_idleness_start_time, -1, -1);
 }
 
+/* Resume idle timer from last idle start time.  */
+
+static void
+timer_resume_idle ()
+{
+  if (! EMACS_TIME_NEG_P (timer_idleness_start_time))
+    return;
+
+  timer_idleness_start_time = timer_last_idleness_start_time;
+}
+
 /* This is only for debugging.  */
 struct input_event last_timer_event;
 
 /* This is only for debugging.  */
 struct input_event last_timer_event;
 
@@ -4982,16 +5055,22 @@ make_lispy_position (f, x, y, time)
     {
       /* It's a click in window window at frame coordinates (x,y)  */
       struct window *w = XWINDOW (window);
     {
       /* It's a click in window window at frame coordinates (x,y)  */
       struct window *w = XWINDOW (window);
-      Lisp_Object object = Qnil;
+      Lisp_Object string_info = Qnil;
       int textpos = -1, rx = -1, ry = -1;
       int dx = -1, dy = -1;
       int textpos = -1, rx = -1, ry = -1;
       int dx = -1, dy = -1;
+      int width = -1, height = -1;
+      Lisp_Object object = Qnil;
 
       /* Set event coordinates to window-relative coordinates
         for constructing the Lisp event below.  */
       XSETINT (*x, wx);
       XSETINT (*y, wy);
 
 
       /* Set event coordinates to window-relative coordinates
         for constructing the Lisp event below.  */
       XSETINT (*x, wx);
       XSETINT (*y, wy);
 
-      if (part == ON_MODE_LINE || part == ON_HEADER_LINE)
+      if (part == ON_TEXT)
+       {
+         wx += WINDOW_LEFT_MARGIN_WIDTH (w);
+       }
+      else if (part == ON_MODE_LINE || part == ON_HEADER_LINE)
        {
          /* Mode line or header line.  Look for a string under
             the mouse that may have a `local-map' property.  */
        {
          /* Mode line or header line.  Look for a string under
             the mouse that may have a `local-map' property.  */
@@ -5000,9 +5079,10 @@ make_lispy_position (f, x, y, time)
 
          posn = part == ON_MODE_LINE ? Qmode_line : Qheader_line;
          rx = wx, ry = wy;
 
          posn = part == ON_MODE_LINE ? Qmode_line : Qheader_line;
          rx = wx, ry = wy;
-         string = mode_line_string (w, &rx, &ry, &dx, &dy, part, &charpos);
+         string = mode_line_string (w, part, &rx, &ry, &charpos,
+                                    &object, &dx, &dy, &width, &height);
          if (STRINGP (string))
          if (STRINGP (string))
-           object = Fcons (string, make_number (charpos));
+           string_info = Fcons (string, make_number (charpos));
          if (w == XWINDOW (selected_window))
            textpos = PT;
          else
          if (w == XWINDOW (selected_window))
            textpos = PT;
          else
@@ -5013,64 +5093,107 @@ make_lispy_position (f, x, y, time)
          posn = Qvertical_line;
          wx = -1;
          dx = 0;
          posn = Qvertical_line;
          wx = -1;
          dx = 0;
+         width = 1;
        }
       else if (part == ON_LEFT_MARGIN || part == ON_RIGHT_MARGIN)
        {
          Lisp_Object string;
          int charpos;
        }
       else if (part == ON_LEFT_MARGIN || part == ON_RIGHT_MARGIN)
        {
          Lisp_Object string;
          int charpos;
-         
+
          posn = (part == ON_LEFT_MARGIN) ? Qleft_margin : Qright_margin;
          rx = wx, ry = wy;
          posn = (part == ON_LEFT_MARGIN) ? Qleft_margin : Qright_margin;
          rx = wx, ry = wy;
-         string = marginal_area_string (w, &rx, &ry, &dx, &dy, part, &charpos);
+         string = marginal_area_string (w, part, &rx, &ry, &charpos,
+                                        &object, &dx, &dy, &width, &height);
          if (STRINGP (string))
          if (STRINGP (string))
-           object = Fcons (string, make_number (charpos));
+           string_info = Fcons (string, make_number (charpos));
+         if (part == ON_LEFT_MARGIN)
+           wx = 0;
+         else
+           wx = window_box_right_offset (w, TEXT_AREA) - 1;
+       }
+      else if (part == ON_LEFT_FRINGE)
+       {
+         posn = Qleft_fringe;
+         rx = 0;
+         dx = wx;
+         wx = (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
+               ? 0
+               : window_box_width (w, LEFT_MARGIN_AREA));
+         dx -= wx;
        }
        }
-      else if (part == ON_LEFT_FRINGE || part == ON_RIGHT_FRINGE)
+      else if (part == ON_RIGHT_FRINGE)
        {
        {
-         posn = (part == ON_LEFT_FRINGE) ? Qleft_fringe : Qright_fringe;
+         posn = Qright_fringe;
          rx = 0;
          dx = wx;
          rx = 0;
          dx = wx;
-         if (part == ON_RIGHT_FRINGE)
-           dx -= (window_box_width (w, LEFT_MARGIN_AREA)
-                  + window_box_width (w, TEXT_AREA)
-                  + (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
-                     ? window_box_width (w, RIGHT_MARGIN_AREA)
-                     : 0));
-         else if (!WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
-           dx -= window_box_width (w, LEFT_MARGIN_AREA);
+         wx = (window_box_width (w, LEFT_MARGIN_AREA)
+               + window_box_width (w, TEXT_AREA)
+               + (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
+                  ? window_box_width (w, RIGHT_MARGIN_AREA)
+                  : 0));
+         dx -= wx;
+       }
+      else
+       {
+         /* Note: We have no special posn for part == ON_SCROLL_BAR.  */
+         wx = max (WINDOW_LEFT_MARGIN_WIDTH (w), wx);
        }
 
       if (textpos < 0)
        {
        }
 
       if (textpos < 0)
        {
-         Lisp_Object string;
+         Lisp_Object string2, object2 = Qnil;
          struct display_pos p;
          int dx2, dy2;
          struct display_pos p;
          int dx2, dy2;
-         wx = max (WINDOW_LEFT_MARGIN_WIDTH (w), wx);
-         buffer_posn_from_coords (w, &wx, &wy, &dx2, &dy2, &string, &p);
+         int width2, height2;
+         string2 = buffer_posn_from_coords (w, &wx, &wy, &p,
+                                            &object2, &dx2, &dy2,
+                                            &width2, &height2);
          textpos = CHARPOS (p.pos);
          if (rx < 0) rx = wx;
          if (ry < 0) ry = wy;
          if (dx < 0) dx = dx2;
          if (dy < 0) dy = dy2;
          textpos = CHARPOS (p.pos);
          if (rx < 0) rx = wx;
          if (ry < 0) ry = wy;
          if (dx < 0) dx = dx2;
          if (dy < 0) dy = dy2;
+         if (width < 0) width = width2;
+         if (height < 0) height = height2;
 
          if (NILP (posn))
            {
              posn = make_number (textpos);
 
          if (NILP (posn))
            {
              posn = make_number (textpos);
-             if (STRINGP (string))
-               object = Fcons (string,
-                               make_number (CHARPOS (p.string_pos)));
-             else if (CONSP (string) && EQ (XCAR (string), Qimage))
-               object = string;
+             if (STRINGP (string2))
+               string_info = Fcons (string2,
+                                    make_number (CHARPOS (p.string_pos)));
            }
            }
+         if (NILP (object))
+           object = object2;
        }
 
        }
 
+#ifdef HAVE_WINDOW_SYSTEM
+      if (IMAGEP (object))
+       {
+         Lisp_Object image_map, hotspot;
+         if ((image_map = Fplist_get (XCDR (object), QCmap),
+              !NILP (image_map))
+             && (hotspot = find_hot_spot (image_map, dx, dy),
+                 CONSP (hotspot))
+             && (hotspot = XCDR (hotspot), CONSP (hotspot)))
+           posn = XCAR (hotspot);
+       }
+#endif
+
+      /* Object info */
       extra_info = Fcons (object,
       extra_info = Fcons (object,
+                         Fcons (Fcons (make_number (dx),
+                                       make_number (dy)),
+                                Fcons (Fcons (make_number (width),
+                                              make_number (height)),
+                                       Qnil)));
+
+      /* String info */
+      extra_info = Fcons (string_info,
                          Fcons (make_number (textpos),
                                 Fcons (Fcons (make_number (rx),
                                               make_number (ry)),
                          Fcons (make_number (textpos),
                                 Fcons (Fcons (make_number (rx),
                                               make_number (ry)),
-                                       Fcons (Fcons (make_number (dx),
-                                                     make_number (dy)),
-                                              Qnil))));
+                                       extra_info)));
     }
   else if (f != 0)
     {
     }
   else if (f != 0)
     {
@@ -5416,13 +5539,23 @@ make_lispy_event (event)
                if (CONSP (down)
                    && INTEGERP (XCAR (down)) && INTEGERP (XCDR (down)))
                  {
                if (CONSP (down)
                    && INTEGERP (XCAR (down)) && INTEGERP (XCDR (down)))
                  {
-                   xdiff = XFASTINT (event->x) - XFASTINT (XCAR (down));
-                   ydiff = XFASTINT (event->y) - XFASTINT (XCDR (down));
+                   xdiff = XINT (event->x) - XINT (XCAR (down));
+                   ydiff = XINT (event->y) - XINT (XCDR (down));
                  }
 
                if (xdiff < double_click_fuzz && xdiff > - double_click_fuzz
                  }
 
                if (xdiff < double_click_fuzz && xdiff > - double_click_fuzz
-                   && ydiff < double_click_fuzz
-                   && ydiff > - double_click_fuzz)
+                   && ydiff < double_click_fuzz && ydiff > - double_click_fuzz
+                 /* Maybe the mouse has moved a lot, caused scrolling, and
+                    eventually ended up at the same screen position (but
+                    not buffer position) in which case it is a drag, not
+                    a click.  */
+                   /* FIXME: OTOH if the buffer position has changed
+                      because of a timer or process filter rather than
+                      because of mouse movement, it should be considered as
+                      a click.  But mouse-drag-region completely ignores
+                      this case and it hasn't caused any real problem, so
+                      it's probably OK to ignore it as well.  */
+                   && EQ (Fcar (Fcdr (start_pos)), Fcar (Fcdr (position))))
                  /* Mouse hasn't moved (much).  */
                  event->modifiers |= click_modifier;
                else
                  /* Mouse hasn't moved (much).  */
                  event->modifiers |= click_modifier;
                else
@@ -5475,7 +5608,7 @@ make_lispy_event (event)
       {
        Lisp_Object position;
        Lisp_Object head;
       {
        Lisp_Object position;
        Lisp_Object head;
-       
+
        /* Build the position as appropriate for this mouse click.  */
        struct frame *f = XFRAME (event->frame_or_window);
 
        /* Build the position as appropriate for this mouse click.  */
        struct frame *f = XFRAME (event->frame_or_window);
 
@@ -5683,14 +5816,8 @@ make_lispy_event (event)
        Lisp_Object head, position;
        Lisp_Object files;
 
        Lisp_Object head, position;
        Lisp_Object files;
 
-       /* The frame_or_window field should be a cons of the frame in
-          which the event occurred and a list of the filenames
-          dropped.  */
-       if (! CONSP (event->frame_or_window))
-         abort ();
-
-       f = XFRAME (XCAR (event->frame_or_window));
-       files = XCDR (event->frame_or_window);
+       f = XFRAME (event->frame_or_window);
+       files = event->arg;
 
        /* Ignore mouse events that were made on frames that
           have been deleted.  */
 
        /* Ignore mouse events that were made on frames that
           have been deleted.  */
@@ -5745,6 +5872,20 @@ make_lispy_event (event)
     case SAVE_SESSION_EVENT:
       return Qsave_session;
 
     case SAVE_SESSION_EVENT:
       return Qsave_session;
 
+#ifdef MAC_OS
+    case MAC_APPLE_EVENT:
+      {
+       Lisp_Object spec[2];
+
+       spec[0] = event->x;
+       spec[1] = event->y;
+       return Fcons (Qmac_apple_event,
+                     Fcons (Fvector (2, spec),
+                            Fcons (mac_make_lispy_event_code (event->code),
+                                   Qnil)));
+      }
+#endif
+
       /* The 'kind' field of the event is something we don't recognize.  */
     default:
       abort ();
       /* The 'kind' field of the event is something we don't recognize.  */
     default:
       abort ();
@@ -6218,12 +6359,8 @@ modify_event_symbol (symbol_num, modifiers, symbol_kind, name_alist_or_stem,
        {
          int len = SBYTES (name_alist_or_stem);
          char *buf = (char *) alloca (len + 50);
        {
          int len = SBYTES (name_alist_or_stem);
          char *buf = (char *) alloca (len + 50);
-         if (sizeof (int) == sizeof (EMACS_INT))
-           sprintf (buf, "%s-%d", SDATA (name_alist_or_stem),
-                    XINT (symbol_int) + 1);
-         else if (sizeof (long) == sizeof (EMACS_INT))
-           sprintf (buf, "%s-%ld", SDATA (name_alist_or_stem),
-                    XINT (symbol_int) + 1);
+         sprintf (buf, "%s-%ld", SDATA (name_alist_or_stem),
+                  (long) XINT (symbol_int) + 1);
          value = intern (buf);
        }
       else if (name_table != 0 && name_table[symbol_num])
          value = intern (buf);
        }
       else if (name_table != 0 && name_table[symbol_num])
@@ -6447,18 +6584,20 @@ lucid_event_type_list_p (object)
    but works even if FIONREAD does not exist.
    (In fact, this may actually read some input.)
 
    but works even if FIONREAD does not exist.
    (In fact, this may actually read some input.)
 
-   If DO_TIMERS_NOW is nonzero, actually run timer events that are ripe.
-   If FILTER_EVENTS is nonzero, ignore internal events (FOCUS_IN_EVENT). */
+   If READABLE_EVENTS_DO_TIMERS_NOW is set in FLAGS, actually run
+   timer events that are ripe.
+   If READABLE_EVENTS_FILTER_EVENTS is set in FLAGS, ignore internal
+   events (FOCUS_IN_EVENT).
+   If READABLE_EVENTS_IGNORE_SQUEEZABLES is set in FLAGS, ignore mouse
+   movements and toolkit scroll bar thumb drags. */
 
 static void
 
 static void
-get_filtered_input_pending (addr, do_timers_now, filter_events)
+get_input_pending (addr, flags)
      int *addr;
      int *addr;
-     int do_timers_now;
-     int filter_events;
+     int flags;
 {
   /* First of all, have we already counted some input?  */
 {
   /* First of all, have we already counted some input?  */
-  *addr = (!NILP (Vquit_flag)
-           || readable_filtered_events (do_timers_now, filter_events));
+  *addr = (!NILP (Vquit_flag) || readable_events (flags));
 
   /* If input is being read as it arrives, and we have none, there is none.  */
   if (*addr > 0 || (interrupt_input && ! interrupts_deferred))
 
   /* If input is being read as it arrives, and we have none, there is none.  */
   if (*addr > 0 || (interrupt_input && ! interrupts_deferred))
@@ -6466,23 +6605,7 @@ get_filtered_input_pending (addr, do_timers_now, filter_events)
 
   /* Try to read some input and see how much we get.  */
   gobble_input (0);
 
   /* Try to read some input and see how much we get.  */
   gobble_input (0);
-  *addr = (!NILP (Vquit_flag)
-           || readable_filtered_events (do_timers_now, filter_events));
-}
-
-/* Store into *addr a value nonzero if terminal input chars are available.
-   Serves the purpose of ioctl (0, FIONREAD, addr)
-   but works even if FIONREAD does not exist.
-   (In fact, this may actually read some input.)
-
-   If DO_TIMERS_NOW is nonzero, actually run timer events that are ripe.  */
-
-static void
-get_input_pending (addr, do_timers_now)
-     int *addr;
-     int do_timers_now;
-{
-  get_filtered_input_pending (addr, do_timers_now, 0);
+  *addr = (!NILP (Vquit_flag) || readable_events (flags));
 }
 
 /* Interface to read_avail_input, blocking SIGIO or SIGALRM if necessary.  */
 }
 
 /* Interface to read_avail_input, blocking SIGIO or SIGALRM if necessary.  */
@@ -6579,16 +6702,26 @@ static int
 read_avail_input (expected)
      int expected;
 {
 read_avail_input (expected)
      int expected;
 {
-  struct input_event buf[KBD_BUFFER_SIZE];
   register int i;
   register int i;
-  int nread;
-
-  for (i = 0; i < KBD_BUFFER_SIZE; i++)
-    EVENT_INIT (buf[i]);
+  int nread = 0;
 
   if (read_socket_hook)
 
   if (read_socket_hook)
-    /* No need for FIONREAD or fcntl; just say don't wait.  */
-    nread = (*read_socket_hook) (input_fd, buf, KBD_BUFFER_SIZE, expected);
+    {
+      int nr;
+      struct input_event hold_quit;
+
+      EVENT_INIT (hold_quit);
+      hold_quit.kind = NO_EVENT;
+
+      /* No need for FIONREAD or fcntl; just say don't wait.  */
+      while (nr = (*read_socket_hook) (input_fd, expected, &hold_quit), nr > 0)
+       {
+         nread += nr;
+         expected = 0;
+       }
+      if (hold_quit.kind != NO_EVENT)
+       kbd_buffer_store_event (&hold_quit);
+    }
   else
     {
       /* Using KBD_BUFFER_SIZE - 1 here avoids reading more than
   else
     {
       /* Using KBD_BUFFER_SIZE - 1 here avoids reading more than
@@ -6689,34 +6822,57 @@ read_avail_input (expected)
 #endif /* no FIONREAD */
       for (i = 0; i < nread; i++)
        {
 #endif /* no FIONREAD */
       for (i = 0; i < nread; i++)
        {
-         buf[i].kind = ASCII_KEYSTROKE_EVENT;
-         buf[i].modifiers = 0;
+         struct input_event buf;
+         EVENT_INIT (buf);
+         buf.kind = ASCII_KEYSTROKE_EVENT;
+         buf.modifiers = 0;
          if (meta_key == 1 && (cbuf[i] & 0x80))
          if (meta_key == 1 && (cbuf[i] & 0x80))
-           buf[i].modifiers = meta_modifier;
+           buf.modifiers = meta_modifier;
          if (meta_key != 2)
            cbuf[i] &= ~0x80;
 
          if (meta_key != 2)
            cbuf[i] &= ~0x80;
 
-         buf[i].code = cbuf[i];
-         buf[i].frame_or_window = selected_frame;
-         buf[i].arg = Qnil;
-       }
-    }
+         buf.code = cbuf[i];
+         buf.frame_or_window = selected_frame;
+         buf.arg = Qnil;
 
 
-  /* Scan the chars for C-g and store them in kbd_buffer.  */
-  for (i = 0; i < nread; i++)
-    {
-      kbd_buffer_store_event (&buf[i]);
-      /* Don't look at input that follows a C-g too closely.
-        This reduces lossage due to autorepeat on C-g.  */
-      if (buf[i].kind == ASCII_KEYSTROKE_EVENT
-         && buf[i].code == quit_char)
-       break;
+         kbd_buffer_store_event (&buf);
+         /* Don't look at input that follows a C-g too closely.
+            This reduces lossage due to autorepeat on C-g.  */
+         if (buf.kind == ASCII_KEYSTROKE_EVENT
+             && buf.code == quit_char)
+           break;
+       }
     }
 
   return nread;
 }
 #endif /* not VMS */
 \f
     }
 
   return nread;
 }
 #endif /* not VMS */
 \f
+void
+handle_async_input ()
+{
+#ifdef BSD4_1
+  extern int select_alarmed;
+#endif
+
+  interrupt_input_pending = 0;
+
+  while (1)
+    {
+      int nread;
+      nread = read_avail_input (1);
+      /* -1 means it's not ok to read the input now.
+        UNBLOCK_INPUT will read it later; now, avoid infinite loop.
+        0 means there was no keyboard input available.  */
+      if (nread <= 0)
+       break;
+
+#ifdef BSD4_1
+      select_alarmed = 1;  /* Force the select emulator back to life */
+#endif
+    }
+}
+
 #ifdef SIGIO   /* for entire page */
 /* Note SIGIO has been undef'd if FIONREAD is missing.  */
 
 #ifdef SIGIO   /* for entire page */
 /* Note SIGIO has been undef'd if FIONREAD is missing.  */
 
@@ -6726,10 +6882,6 @@ input_available_signal (signo)
 {
   /* Must preserve main program's value of errno.  */
   int old_errno = errno;
 {
   /* Must preserve main program's value of errno.  */
   int old_errno = errno;
-#ifdef BSD4_1
-  extern int select_alarmed;
-#endif
-
 #if defined (USG) && !defined (POSIX_SIGNALS)
   /* USG systems forget handlers when they are used;
      must reestablish each time */
 #if defined (USG) && !defined (POSIX_SIGNALS)
   /* USG systems forget handlers when they are used;
      must reestablish each time */
@@ -6740,23 +6892,18 @@ input_available_signal (signo)
   sigisheld (SIGIO);
 #endif
 
   sigisheld (SIGIO);
 #endif
 
+#ifdef SYNC_INPUT
+  interrupt_input_pending = 1;
+#else
+  SIGNAL_THREAD_CHECK (signo);
+#endif
+
   if (input_available_clear_time)
     EMACS_SET_SECS_USECS (*input_available_clear_time, 0, 0);
 
   if (input_available_clear_time)
     EMACS_SET_SECS_USECS (*input_available_clear_time, 0, 0);
 
-  while (1)
-    {
-      int nread;
-      nread = read_avail_input (1);
-      /* -1 means it's not ok to read the input now.
-        UNBLOCK_INPUT will read it later; now, avoid infinite loop.
-        0 means there was no keyboard input available.  */
-      if (nread <= 0)
-       break;
-
-#ifdef BSD4_1
-      select_alarmed = 1;  /* Force the select emulator back to life */
+#ifndef SYNC_INPUT
+  handle_async_input ();
 #endif
 #endif
-    }
 
 #ifdef BSD4_1
   sigfree ();
 
 #ifdef BSD4_1
   sigfree ();
@@ -6775,7 +6922,7 @@ void
 reinvoke_input_signal ()
 {
 #ifdef SIGIO
 reinvoke_input_signal ()
 {
 #ifdef SIGIO
-  kill (getpid (), SIGIO);
+  handle_async_input ();
 #endif
 }
 
 #endif
 }
 
@@ -6817,8 +6964,6 @@ menu_bar_items (old)
 
   int i;
 
 
   int i;
 
-  struct gcpro gcpro1;
-
   /* In order to build the menus, we need to call the keymap
      accessors.  They all call QUIT.  But this function is called
      during redisplay, during which a quit is fatal.  So inhibit
   /* In order to build the menus, we need to call the keymap
      accessors.  They all call QUIT.  But this function is called
      during redisplay, during which a quit is fatal.  So inhibit
@@ -6834,8 +6979,6 @@ menu_bar_items (old)
     menu_bar_items_vector = Fmake_vector (make_number (24), Qnil);
   menu_bar_items_index = 0;
 
     menu_bar_items_vector = Fmake_vector (make_number (24), Qnil);
   menu_bar_items_index = 0;
 
-  GCPRO1 (menu_bar_items_vector);
-
   /* Build our list of keymaps.
      If we recognize a function key and replace its escape sequence in
      keybuf with its symbol, or if the sequence starts with a mouse
   /* Build our list of keymaps.
      If we recognize a function key and replace its escape sequence in
      keybuf with its symbol, or if the sequence starts with a mouse
@@ -6939,7 +7082,6 @@ menu_bar_items (old)
   menu_bar_items_index = i;
 
   Vinhibit_quit = oquit;
   menu_bar_items_index = i;
 
   Vinhibit_quit = oquit;
-  UNGCPRO;
   return menu_bar_items_vector;
 }
 \f
   return menu_bar_items_vector;
 }
 \f
@@ -7134,7 +7276,9 @@ parse_menu_item (item, notreal, inmenubar)
       if (SYMBOLP (item))
        {
          tem = Fget (item, Qmenu_enable);
       if (SYMBOLP (item))
        {
          tem = Fget (item, Qmenu_enable);
-         if (!NILP (tem))
+         if (!NILP (Venable_disabled_menus_and_buttons))
+           AREF (item_properties, ITEM_PROPERTY_ENABLE) = Qt;
+         else if (!NILP (tem))
            AREF (item_properties, ITEM_PROPERTY_ENABLE) = tem;
        }
     }
            AREF (item_properties, ITEM_PROPERTY_ENABLE) = tem;
        }
     }
@@ -7163,7 +7307,12 @@ parse_menu_item (item, notreal, inmenubar)
              item = XCDR (item);
 
              if (EQ (tem, QCenable))
              item = XCDR (item);
 
              if (EQ (tem, QCenable))
-               AREF (item_properties, ITEM_PROPERTY_ENABLE) = XCAR (item);
+               {
+                 if (!NILP (Venable_disabled_menus_and_buttons))
+                   AREF (item_properties, ITEM_PROPERTY_ENABLE) = Qt;
+                 else
+                   AREF (item_properties, ITEM_PROPERTY_ENABLE) = XCAR (item);
+               }
              else if (EQ (tem, QCvisible) && !notreal)
                {
                  /* If got a visible property and that evaluates to nil
              else if (EQ (tem, QCvisible) && !notreal)
                {
                  /* If got a visible property and that evaluates to nil
@@ -7307,9 +7456,7 @@ parse_menu_item (item, notreal, inmenubar)
       else
        def = AREF (item_properties, ITEM_PROPERTY_DEF);
 
       else
        def = AREF (item_properties, ITEM_PROPERTY_DEF);
 
-      if (!update_menu_bindings)
-       chkcache = 0;
-      else if (NILP (XCAR (cachelist))) /* Have no saved key.  */
+      if (NILP (XCAR (cachelist))) /* Have no saved key.  */
        {
          if (newcache          /* Always check first time.  */
              /* Should we check everything when precomputing key
        {
          if (newcache          /* Always check first time.  */
              /* Should we check everything when precomputing key
@@ -7359,7 +7506,7 @@ parse_menu_item (item, notreal, inmenubar)
       newcache = chkcache;
       if (chkcache)
        {
       newcache = chkcache;
       if (chkcache)
        {
-         tem = Fkey_description (tem);
+         tem = Fkey_description (tem, Qnil);
          if (CONSP (prefix))
            {
              if (STRINGP (XCAR (prefix)))
          if (CONSP (prefix))
            {
              if (STRINGP (XCAR (prefix)))
@@ -7434,7 +7581,7 @@ Lisp_Object QCimage;
 /* Function prototypes.  */
 
 static void init_tool_bar_items P_ ((Lisp_Object));
 /* 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));
 
 static int parse_tool_bar_item P_ ((Lisp_Object, Lisp_Object));
 static void append_tool_bar_item P_ ((void));
 
@@ -7512,17 +7659,7 @@ tool_bar_items (reuse, nitems)
 
        keymap = get_keymap (access_keymap (maps[i], Qtool_bar, 1, 0, 1), 0, 1);
        if (CONSP (keymap))
 
        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;
       }
 
   Vinhibit_quit = oquit;
@@ -7534,8 +7671,9 @@ tool_bar_items (reuse, nitems)
 /* Process the definition of KEY which is DEF.  */
 
 static void
 /* 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;
 {
   int i;
   extern Lisp_Object Qundefined;
@@ -7685,8 +7823,13 @@ parse_tool_bar_item (key, item)
       value = XCAR (XCDR (item));
 
       if (EQ (key, QCenable))
       value = XCAR (XCDR (item));
 
       if (EQ (key, QCenable))
-       /* `:enable FORM'.  */
-       PROP (TOOL_BAR_ITEM_ENABLED_P) = value;
+       {
+         /* `:enable FORM'.  */
+         if (!NILP (Venable_disabled_menus_and_buttons))
+           PROP (TOOL_BAR_ITEM_ENABLED_P) = Qt;
+         else
+           PROP (TOOL_BAR_ITEM_ENABLED_P) = value;
+       }
       else if (EQ (key, QCvisible))
        {
          /* `:visible FORM'.  If got a visible property and that
       else if (EQ (key, QCvisible))
        {
          /* `:visible FORM'.  If got a visible property and that
@@ -8233,7 +8376,7 @@ access_keymap_keyremap (map, key, prompt, do_funcall)
      int do_funcall;
 {
   Lisp_Object next;
      int do_funcall;
 {
   Lisp_Object next;
-  
+
   next = access_keymap (map, key, 1, 0, 1);
 
   /* Handle symbol with autoload definition.  */
   next = access_keymap (map, key, 1, 0, 1);
 
   /* Handle symbol with autoload definition.  */
@@ -8248,7 +8391,7 @@ access_keymap_keyremap (map, key, prompt, do_funcall)
       && (!NILP (Farrayp (XSYMBOL (next)->function))
          || KEYMAPP (XSYMBOL (next)->function)))
     next = XSYMBOL (next)->function;
       && (!NILP (Farrayp (XSYMBOL (next)->function))
          || KEYMAPP (XSYMBOL (next)->function)))
     next = XSYMBOL (next)->function;
-           
+
   /* If the keymap gives a function, not an
      array, then call the function with one arg and use
      its value instead.  */
   /* If the keymap gives a function, not an
      array, then call the function with one arg and use
      its value instead.  */
@@ -8749,14 +8892,7 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
             keymap may have changed, so replay the sequence.  */
          if (BUFFERP (key))
            {
             keymap may have changed, so replay the sequence.  */
          if (BUFFERP (key))
            {
-             EMACS_TIME initial_idleness_start_time;
-             EMACS_SET_SECS_USECS (initial_idleness_start_time,
-                                   EMACS_SECS (timer_last_idleness_start_time),
-                                   EMACS_USECS (timer_last_idleness_start_time));
-
-             /* Resume idle state, using the same start-time as before.  */
-             timer_start_idle ();
-             timer_idleness_start_time = initial_idleness_start_time;
+             timer_resume_idle ();
 
              mock_input = t;
              /* Reset the current buffer from the selected window
 
              mock_input = t;
              /* Reset the current buffer from the selected window
@@ -8838,7 +8974,7 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
              Lisp_Object window, posn;
 
              window = POSN_WINDOW      (EVENT_START (key));
              Lisp_Object window, posn;
 
              window = POSN_WINDOW      (EVENT_START (key));
-             posn   = POSN_BUFFER_POSN (EVENT_START (key));
+             posn   = POSN_POSN (EVENT_START (key));
 
              if (CONSP (posn)
                  || (!NILP (fake_prefixed_keys)
 
              if (CONSP (posn)
                  || (!NILP (fake_prefixed_keys)
@@ -8896,7 +9032,7 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
                  localized_local_map = 1;
                  start = EVENT_START (key);
 
                  localized_local_map = 1;
                  start = EVENT_START (key);
 
-                 if (CONSP (start) && CONSP (XCDR (start)))
+                 if (CONSP (start) && POSN_INBUFFER_P (start))
                    {
                      pos = POSN_BUFFER_POSN (start);
                      if (INTEGERP (pos)
                    {
                      pos = POSN_BUFFER_POSN (start);
                      if (INTEGERP (pos)
@@ -9006,7 +9142,7 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
            {
              Lisp_Object posn;
 
            {
              Lisp_Object posn;
 
-             posn = POSN_BUFFER_POSN (EVENT_START (key));
+             posn = POSN_POSN (EVENT_START (key));
              /* Handle menu-bar events:
                 insert the dummy prefix event `menu-bar'.  */
              if (EQ (posn, Qmenu_bar) || EQ (posn, Qtool_bar))
              /* Handle menu-bar events:
                 insert the dummy prefix event `menu-bar'.  */
              if (EQ (posn, Qmenu_bar) || EQ (posn, Qtool_bar))
@@ -9018,8 +9154,8 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
 
                  /* Zap the position in key, so we know that we've
                     expanded it, and don't try to do so again.  */
 
                  /* Zap the position in key, so we know that we've
                     expanded it, and don't try to do so again.  */
-                 POSN_BUFFER_SET_POSN (EVENT_START (key),
-                                       Fcons (posn, Qnil));
+                 POSN_SET_POSN (EVENT_START (key),
+                                Fcons (posn, Qnil));
 
                  mock_input = t + 2;
                  goto replay_sequence;
 
                  mock_input = t + 2;
                  goto replay_sequence;
@@ -9262,7 +9398,7 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
              /* Adjust the function-key-map counters.  */
              fkey.end += diff;
              fkey.start += diff;
              /* Adjust the function-key-map counters.  */
              fkey.end += diff;
              fkey.start += diff;
-             
+
              goto replay_sequence;
            }
        }
              goto replay_sequence;
            }
        }
@@ -9343,6 +9479,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)
   /* 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;
 
       && t - 1 == original_uppercase_position)
     keybuf[t - 1] = original_uppercase;
 
@@ -9564,15 +9701,15 @@ a special event, so ignore the prefix argument and don't clear it.  */)
       tem = Fget (cmd, Qdisabled);
       if (!NILP (tem) && !NILP (Vrun_hooks))
        {
       tem = Fget (cmd, Qdisabled);
       if (!NILP (tem) && !NILP (Vrun_hooks))
        {
-         tem = Fsymbol_value (Qdisabled_command_hook);
+         tem = Fsymbol_value (Qdisabled_command_function);
          if (!NILP (tem))
          if (!NILP (tem))
-           return call1 (Vrun_hooks, Qdisabled_command_hook);
+           return call1 (Vrun_hooks, Qdisabled_command_function);
        }
     }
 
   while (1)
     {
        }
     }
 
   while (1)
     {
-      final = Findirect_function (cmd);
+      final = Findirect_function (cmd, Qnil);
 
       if (CONSP (final) && (tem = Fcar (final), EQ (tem, Qautoload)))
        {
 
       if (CONSP (final) && (tem = Fcar (final), EQ (tem, Qautoload)))
        {
@@ -9618,6 +9755,7 @@ a special event, so ignore the prefix argument and don't clear it.  */)
       backtrace.args = &cmd;
       backtrace.nargs = 1;
       backtrace.evalargs = 0;
       backtrace.args = &cmd;
       backtrace.nargs = 1;
       backtrace.evalargs = 0;
+      backtrace.debug_on_exit = 0;
 
       tem = Fcall_interactively (cmd, record_flag, keys);
 
 
       tem = Fcall_interactively (cmd, record_flag, keys);
 
@@ -9641,6 +9779,15 @@ DEFUN ("execute-extended-command", Fexecute_extended_command, Sexecute_extended_
   Lisp_Object saved_keys, saved_last_point_position_buffer;
   Lisp_Object bindings, value;
   struct gcpro gcpro1, gcpro2, gcpro3;
   Lisp_Object saved_keys, saved_last_point_position_buffer;
   Lisp_Object bindings, value;
   struct gcpro gcpro1, gcpro2, gcpro3;
+#ifdef HAVE_X_WINDOWS
+  /* The call to Fcompleting_read wil start and cancel the hourglass,
+     but if the hourglass was already scheduled, this means that no
+     hourglass will be shown for the actual M-x command itself.
+     So we restart it if it is already scheduled.  Note that checking
+     hourglass_shown_p is not enough,  normally the hourglass is not shown,
+     just scheduled to be shown.  */
+  int hstarted = hourglass_started ();
+#endif
 
   saved_keys = Fvector (this_command_key_count,
                        XVECTOR (this_command_keys)->contents);
 
   saved_keys = Fvector (this_command_key_count,
                        XVECTOR (this_command_keys)->contents);
@@ -9654,23 +9801,9 @@ DEFUN ("execute-extended-command", Fexecute_extended_command, Sexecute_extended_
   else if (CONSP (prefixarg) && XINT (XCAR (prefixarg)) == 4)
     strcpy (buf, "C-u ");
   else if (CONSP (prefixarg) && INTEGERP (XCAR (prefixarg)))
   else if (CONSP (prefixarg) && XINT (XCAR (prefixarg)) == 4)
     strcpy (buf, "C-u ");
   else if (CONSP (prefixarg) && INTEGERP (XCAR (prefixarg)))
-    {
-      if (sizeof (int) == sizeof (EMACS_INT))
-       sprintf (buf, "%d ", XINT (XCAR (prefixarg)));
-      else if (sizeof (long) == sizeof (EMACS_INT))
-       sprintf (buf, "%ld ", (long) XINT (XCAR (prefixarg)));
-      else
-       abort ();
-    }
+    sprintf (buf, "%ld ", (long) XINT (XCAR (prefixarg)));
   else if (INTEGERP (prefixarg))
   else if (INTEGERP (prefixarg))
-    {
-      if (sizeof (int) == sizeof (EMACS_INT))
-       sprintf (buf, "%d ", XINT (prefixarg));
-      else if (sizeof (long) == sizeof (EMACS_INT))
-       sprintf (buf, "%ld ", (long) XINT (prefixarg));
-      else
-       abort ();
-    }
+    sprintf (buf, "%ld ", (long) XINT (prefixarg));
 
   /* This isn't strictly correct if execute-extended-command
      is bound to anything else.  Perhaps it should use
 
   /* This isn't strictly correct if execute-extended-command
      is bound to anything else.  Perhaps it should use
@@ -9686,6 +9819,10 @@ DEFUN ("execute-extended-command", Fexecute_extended_command, Sexecute_extended_
                               Qt, Qnil, Qextended_command_history, Qnil,
                               Qnil);
 
                               Qt, Qnil, Qextended_command_history, Qnil,
                               Qnil);
 
+#ifdef HAVE_X_WINDOWS
+  if (hstarted) start_hourglass ();
+#endif
+
   if (STRINGP (function) && SCHARS (function) == 0)
     error ("No command name given");
 
   if (STRINGP (function) && SCHARS (function) == 0)
     error ("No command name given");
 
@@ -9721,7 +9858,7 @@ DEFUN ("execute-extended-command", Fexecute_extended_command, Sexecute_extended_
 
   /* If enabled, show which key runs this command.  */
   if (!NILP (Vsuggest_key_bindings)
 
   /* If enabled, show which key runs this command.  */
   if (!NILP (Vsuggest_key_bindings)
-      && NILP (Vexecuting_macro)
+      && NILP (Vexecuting_kbd_macro)
       && SYMBOLP (function))
     bindings = Fwhere_is_internal (function, Voverriding_local_map,
                                   Qt, Qnil, Qnil);
       && SYMBOLP (function))
     bindings = Fwhere_is_internal (function, Voverriding_local_map,
                                   Qt, Qnil, Qnil);
@@ -9758,7 +9895,7 @@ DEFUN ("execute-extended-command", Fexecute_extended_command, Sexecute_extended_
          int count = SPECPDL_INDEX ();
 
          record_unwind_protect (pop_message_unwind, Qnil);
          int count = SPECPDL_INDEX ();
 
          record_unwind_protect (pop_message_unwind, Qnil);
-         binding = Fkey_description (bindings);
+         binding = Fkey_description (bindings, Qnil);
 
          newmessage
            = (char *) alloca (SCHARS (SYMBOL_NAME (function))
 
          newmessage
            = (char *) alloca (SCHARS (SYMBOL_NAME (function))
@@ -9795,6 +9932,18 @@ detect_input_pending ()
   return input_pending;
 }
 
   return input_pending;
 }
 
+/* Return nonzero if input events other than mouse movements are
+   pending.  */
+
+int
+detect_input_pending_ignore_squeezables ()
+{
+  if (!input_pending)
+    get_input_pending (&input_pending, READABLE_EVENTS_IGNORE_SQUEEZABLES);
+
+  return input_pending;
+}
+
 /* Return nonzero if input events are pending, and run any pending timers.  */
 
 int
 /* Return nonzero if input events are pending, and run any pending timers.  */
 
 int
@@ -9804,7 +9953,7 @@ detect_input_pending_run_timers (do_display)
   int old_timers_run = timers_run;
 
   if (!input_pending)
   int old_timers_run = timers_run;
 
   if (!input_pending)
-    get_input_pending (&input_pending, 1);
+    get_input_pending (&input_pending, READABLE_EVENTS_DO_TIMERS_NOW);
 
   if (old_timers_run != timers_run && do_display)
     {
 
   if (old_timers_run != timers_run && do_display)
     {
@@ -9832,7 +9981,7 @@ clear_input_pending ()
 }
 
 /* Return nonzero if there are pending requeued events.
 }
 
 /* Return nonzero if there are pending requeued events.
-   This isn't used yet.  The hope is to make wait_reading_process_input
+   This isn't used yet.  The hope is to make wait_reading_process_output
    call it, and return if it runs Lisp code that unreads something.
    The problem is, kbd_buffer_get_event needs to be fixed to know what
    to do in that case.  It isn't trivial.  */
    call it, and return if it runs Lisp code that unreads something.
    The problem is, kbd_buffer_get_event needs to be fixed to know what
    to do in that case.  It isn't trivial.  */
@@ -9853,7 +10002,9 @@ if there is a doubt, the value is t.  */)
   if (!NILP (Vunread_command_events) || unread_command_char != -1)
     return (Qt);
 
   if (!NILP (Vunread_command_events) || unread_command_char != -1)
     return (Qt);
 
-  get_filtered_input_pending (&input_pending, 1, 1);
+  get_input_pending (&input_pending,
+                    READABLE_EVENTS_DO_TIMERS_NOW
+                    | READABLE_EVENTS_FILTER_EVENTS);
   return input_pending > 0 ? Qt : Qnil;
 }
 
   return input_pending > 0 ? Qt : Qnil;
 }
 
@@ -10031,7 +10182,6 @@ Also end any kbd macro being defined.  */)
   discard_tty_input ();
 
   kbd_fetch_ptr =  kbd_store_ptr;
   discard_tty_input ();
 
   kbd_fetch_ptr =  kbd_store_ptr;
-  Ffillarray (kbd_buffer_gcpro, Qnil);
   input_pending = 0;
 
   return Qnil;
   input_pending = 0;
 
   return Qnil;
@@ -10101,9 +10251,7 @@ void
 stuff_buffered_input (stuffstring)
      Lisp_Object stuffstring;
 {
 stuff_buffered_input (stuffstring)
      Lisp_Object stuffstring;
 {
-/* stuff_char works only in BSD, versions 4.2 and up.  */
-#ifdef BSD_SYSTEM
-#ifndef BSD4_1
+#ifdef SIGTSTP  /* stuff_char is defined if SIGTSTP.  */
   register unsigned char *p;
 
   if (STRINGP (stuffstring))
   register unsigned char *p;
 
   if (STRINGP (stuffstring))
@@ -10119,25 +10267,23 @@ stuff_buffered_input (stuffstring)
 
   /* Anything we have read ahead, put back for the shell to read.  */
   /* ?? What should this do when we have multiple keyboards??
 
   /* Anything we have read ahead, put back for the shell to read.  */
   /* ?? What should this do when we have multiple keyboards??
-     Should we ignore anything that was typed in at the "wrong" kboard?  */
+     Should we ignore anything that was typed in at the "wrong" kboard?
+
+     rms: we should stuff everything back into the kboard
+     it came from.  */
   for (; kbd_fetch_ptr != kbd_store_ptr; kbd_fetch_ptr++)
     {
   for (; kbd_fetch_ptr != kbd_store_ptr; kbd_fetch_ptr++)
     {
-      int idx;
 
       if (kbd_fetch_ptr == kbd_buffer + KBD_BUFFER_SIZE)
        kbd_fetch_ptr = kbd_buffer;
       if (kbd_fetch_ptr->kind == ASCII_KEYSTROKE_EVENT)
        stuff_char (kbd_fetch_ptr->code);
 
 
       if (kbd_fetch_ptr == kbd_buffer + KBD_BUFFER_SIZE)
        kbd_fetch_ptr = kbd_buffer;
       if (kbd_fetch_ptr->kind == ASCII_KEYSTROKE_EVENT)
        stuff_char (kbd_fetch_ptr->code);
 
-      kbd_fetch_ptr->kind = NO_EVENT;
-      idx = 2 * (kbd_fetch_ptr - kbd_buffer);
-      ASET (kbd_buffer_gcpro, idx, Qnil);
-      ASET (kbd_buffer_gcpro, idx + 1, Qnil);
+      clear_event (kbd_fetch_ptr);
     }
 
   input_pending = 0;
     }
 
   input_pending = 0;
-#endif
-#endif /* BSD_SYSTEM and not BSD4_1 */
+#endif /* SIGTSTP */
 }
 \f
 void
 }
 \f
 void
@@ -10195,6 +10341,7 @@ interrupt_signal (signalnum)    /* If we don't have an argument, */
     }
 #endif /* USG */
 
     }
 #endif /* USG */
 
+  SIGNAL_THREAD_CHECK (signalnum);
   cancel_echoing ();
 
   if (!NILP (Vquit_flag)
   cancel_echoing ();
 
   if (!NILP (Vquit_flag)
@@ -10446,6 +10593,81 @@ The elements of this list correspond to the arguments of
   return Flist (sizeof (val) / sizeof (val[0]), val);
 }
 
   return Flist (sizeof (val) / sizeof (val[0]), val);
 }
 
+DEFUN ("posn-at-x-y", Fposn_at_x_y, Sposn_at_x_y, 2, 4, 0,
+       doc: /* Return position information for pixel coordinates X and Y.
+By default, X and Y are relative to text area of the selected window.
+Optional third arg FRAME-OR-WINDOW non-nil specifies frame or window.
+If optional fourth arg WHOLE is non-nil, X is relative to the left
+edge of the window.
+
+The return value is similar to a mouse click position:
+   (WINDOW AREA-OR-POS (X . Y) TIMESTAMP OBJECT POS (COL . ROW)
+    IMAGE (DX . DY) (WIDTH . HEIGHT))
+The `posn-' functions access elements of such lists.  */)
+  (x, y, frame_or_window, whole)
+     Lisp_Object x, y, frame_or_window, whole;
+{
+  CHECK_NATNUM (x);
+  CHECK_NATNUM (y);
+
+  if (NILP (frame_or_window))
+    frame_or_window = selected_window;
+
+  if (WINDOWP (frame_or_window))
+    {
+      struct window *w;
+
+      CHECK_LIVE_WINDOW (frame_or_window);
+
+      w = XWINDOW (frame_or_window);
+      XSETINT (x, (XINT (x)
+                  + WINDOW_LEFT_EDGE_X (w)
+                  + (NILP (whole)
+                     ? window_box_left_offset (w, TEXT_AREA)
+                     : 0)));
+      XSETINT (y, WINDOW_TO_FRAME_PIXEL_Y (w, XINT (y)));
+      frame_or_window = w->frame;
+    }
+
+  CHECK_LIVE_FRAME (frame_or_window);
+
+  return make_lispy_position (XFRAME (frame_or_window), &x, &y, 0);
+}
+
+DEFUN ("posn-at-point", Fposn_at_point, Sposn_at_point, 0, 2, 0,
+       doc: /* Return position information for buffer POS in WINDOW.
+POS defaults to point in WINDOW; WINDOW defaults to the selected window.
+
+Return nil if position is not visible in window.  Otherwise,
+the return value is similar to that returned by `event-start' for
+a mouse click at the upper left corner of the glyph corresponding
+to the given buffer position:
+   (WINDOW AREA-OR-POS (X . Y) TIMESTAMP OBJECT POS (COL . ROW)
+    IMAGE (DX . DY) (WIDTH . HEIGHT))
+The `posn-' functions access elements of such lists.  */)
+  (pos, window)
+     Lisp_Object pos, window;
+{
+  Lisp_Object tem;
+
+  if (NILP (window))
+    window = selected_window;
+
+  tem = Fpos_visible_in_window_p (pos, window, Qt);
+  if (!NILP (tem))
+    {
+      Lisp_Object x = XCAR (tem);
+      Lisp_Object y = XCAR (XCDR (tem));
+
+      /* Point invisible due to hscrolling?  */
+      if (XINT (x) < 0)
+       return Qnil;
+      tem = Fposn_at_x_y (x, y, window, Qnil);
+    }
+
+  return tem;
+}
+
 \f
 /*
  * Set up a new kboard object with reasonable initial values.
 \f
 /*
  * Set up a new kboard object with reasonable initial values.
@@ -10532,7 +10754,6 @@ init_keyboard ()
   recent_keys_index = 0;
   kbd_fetch_ptr = kbd_buffer;
   kbd_store_ptr = kbd_buffer;
   recent_keys_index = 0;
   kbd_fetch_ptr = kbd_buffer;
   kbd_store_ptr = kbd_buffer;
-  kbd_buffer_gcpro = Fmake_vector (make_number (2 * KBD_BUFFER_SIZE), Qnil);
 #ifdef HAVE_MOUSE
   do_mouse_tracking = Qnil;
 #endif
 #ifdef HAVE_MOUSE
   do_mouse_tracking = Qnil;
 #endif
@@ -10588,11 +10809,6 @@ init_keyboard ()
   poll_suppress_count = 1;
   start_polling ();
 #endif
   poll_suppress_count = 1;
   start_polling ();
 #endif
-
-#ifdef MAC_OSX
-  /* At least provide an escape route since C-g doesn't work.  */
-  signal (SIGINT, interrupt_signal);
-#endif
 }
 
 /* This type's only use is in syms_of_keyboard, to initialize the
 }
 
 /* This type's only use is in syms_of_keyboard, to initialize the
@@ -10645,8 +10861,8 @@ syms_of_keyboard ()
   Qtimer_event_handler = intern ("timer-event-handler");
   staticpro (&Qtimer_event_handler);
 
   Qtimer_event_handler = intern ("timer-event-handler");
   staticpro (&Qtimer_event_handler);
 
-  Qdisabled_command_hook = intern ("disabled-command-hook");
-  staticpro (&Qdisabled_command_hook);
+  Qdisabled_command_function = intern ("disabled-command-function");
+  staticpro (&Qdisabled_command_function);
 
   Qself_insert_command = intern ("self-insert-command");
   staticpro (&Qself_insert_command);
 
   Qself_insert_command = intern ("self-insert-command");
   staticpro (&Qself_insert_command);
@@ -10669,9 +10885,6 @@ syms_of_keyboard ()
   Qpost_command_hook = intern ("post-command-hook");
   staticpro (&Qpost_command_hook);
 
   Qpost_command_hook = intern ("post-command-hook");
   staticpro (&Qpost_command_hook);
 
-  Qpost_command_idle_hook = intern ("post-command-idle-hook");
-  staticpro (&Qpost_command_idle_hook);
-
   Qdeferred_action_function = intern ("deferred-action-function");
   staticpro (&Qdeferred_action_function);
 
   Qdeferred_action_function = intern ("deferred-action-function");
   staticpro (&Qdeferred_action_function);
 
@@ -10682,7 +10895,7 @@ syms_of_keyboard ()
   staticpro (&Qfunction_key);
   Qmouse_click = intern ("mouse-click");
   staticpro (&Qmouse_click);
   staticpro (&Qfunction_key);
   Qmouse_click = intern ("mouse-click");
   staticpro (&Qmouse_click);
-#ifdef WINDOWSNT
+#if defined (WINDOWSNT) || defined (MAC_OS)
   Qlanguage_change = intern ("language-change");
   staticpro (&Qlanguage_change);
 #endif
   Qlanguage_change = intern ("language-change");
   staticpro (&Qlanguage_change);
 #endif
@@ -10690,7 +10903,12 @@ syms_of_keyboard ()
   staticpro (&Qdrag_n_drop);
 
   Qsave_session = intern ("save-session");
   staticpro (&Qdrag_n_drop);
 
   Qsave_session = intern ("save-session");
-  staticpro(&Qsave_session);
+  staticpro (&Qsave_session);
+
+#ifdef MAC_OS
+  Qmac_apple_event = intern ("mac-apple-event");
+  staticpro (&Qmac_apple_event);
+#endif
 
   Qusr1_signal = intern ("usr1-signal");
   staticpro (&Qusr1_signal);
 
   Qusr1_signal = intern ("usr1-signal");
   staticpro (&Qusr1_signal);
@@ -10729,6 +10947,11 @@ syms_of_keyboard ()
   Qmenu_bar = intern ("menu-bar");
   staticpro (&Qmenu_bar);
 
   Qmenu_bar = intern ("menu-bar");
   staticpro (&Qmenu_bar);
 
+#ifdef HAVE_MOUSE
+  Qmouse_fixup_help_message = intern ("mouse-fixup-help-message");
+  staticpro (&Qmouse_fixup_help_message);
+#endif
+
   Qabove_handle = intern ("above-handle");
   staticpro (&Qabove_handle);
   Qhandle = intern ("handle");
   Qabove_handle = intern ("above-handle");
   staticpro (&Qabove_handle);
   Qhandle = intern ("handle");
@@ -10777,6 +11000,7 @@ syms_of_keyboard ()
   Fset (Qinput_method_use_echo_area, Qnil);
 
   last_point_position_buffer = Qnil;
   Fset (Qinput_method_use_echo_area, Qnil);
 
   last_point_position_buffer = Qnil;
+  last_point_position_window = Qnil;
 
   {
     struct event_head *p;
 
   {
     struct event_head *p;
@@ -10823,9 +11047,6 @@ syms_of_keyboard ()
   Fset (Qextended_command_history, Qnil);
   staticpro (&Qextended_command_history);
 
   Fset (Qextended_command_history, Qnil);
   staticpro (&Qextended_command_history);
 
-  kbd_buffer_gcpro = Fmake_vector (make_number (2 * KBD_BUFFER_SIZE), Qnil);
-  staticpro (&kbd_buffer_gcpro);
-
   accent_key_syms = Qnil;
   staticpro (&accent_key_syms);
 
   accent_key_syms = Qnil;
   staticpro (&accent_key_syms);
 
@@ -10847,6 +11068,9 @@ syms_of_keyboard ()
   menu_bar_one_keymap_changed_items = Qnil;
   staticpro (&menu_bar_one_keymap_changed_items);
 
   menu_bar_one_keymap_changed_items = Qnil;
   staticpro (&menu_bar_one_keymap_changed_items);
 
+  menu_bar_items_vector = Qnil;
+  staticpro (&menu_bar_items_vector);
+
   defsubr (&Sevent_convert_list);
   defsubr (&Sread_key_sequence);
   defsubr (&Sread_key_sequence_vector);
   defsubr (&Sevent_convert_list);
   defsubr (&Sread_key_sequence);
   defsubr (&Sread_key_sequence_vector);
@@ -10873,6 +11097,8 @@ syms_of_keyboard ()
   defsubr (&Sset_input_mode);
   defsubr (&Scurrent_input_mode);
   defsubr (&Sexecute_extended_command);
   defsubr (&Sset_input_mode);
   defsubr (&Scurrent_input_mode);
   defsubr (&Sexecute_extended_command);
+  defsubr (&Sposn_at_point);
+  defsubr (&Sposn_at_x_y);
 
   DEFVAR_LISP ("last-command-char", &last_command_char,
               doc: /* Last input event that was part of a command.  */);
 
   DEFVAR_LISP ("last-command-char", &last_command_char,
               doc: /* Last input event that was part of a command.  */);
@@ -11043,11 +11269,13 @@ Useful to set before you dump a modified Emacs.  */);
 
   DEFVAR_LISP ("keyboard-translate-table", &Vkeyboard_translate_table,
               doc: /* Translate table for keyboard input, or nil.
 
   DEFVAR_LISP ("keyboard-translate-table", &Vkeyboard_translate_table,
               doc: /* Translate table for keyboard input, or nil.
-Each character is looked up in this string and the contents used instead.
-The value may be a string, a vector, or a char-table.
-If it is a string or vector of length N,
-character codes N and up are untranslated.
-In a vector or a char-table, an element which is nil means "no translation".
+If non-nil, the value should be a char-table.  Each character read
+from the keyboard is looked up in this char-table.  If the value found
+there is non-nil, then it is used instead of the actual input character.
+
+The value can also be a string or vector, but this is considered obsolete.
+If it is a string or vector of length N, character codes N and up are left
+untranslated.  In a vector, an element which is nil means "no translation".
 
 This is applied to the characters supplied to input methods, not their
 output.  See also `translation-table-for-input'.  */);
 
 This is applied to the characters supplied to input methods, not their
 output.  See also `translation-table-for-input'.  */);
@@ -11111,21 +11339,12 @@ the hook value is set to nil, since otherwise the error
 might happen repeatedly and make Emacs nonfunctional.  */);
   Vpost_command_hook = Qnil;
 
 might happen repeatedly and make Emacs nonfunctional.  */);
   Vpost_command_hook = Qnil;
 
-  DEFVAR_LISP ("post-command-idle-hook", &Vpost_command_idle_hook,
-              doc: /* Normal hook run after each command is executed, if idle.
-Errors running the hook are caught and ignored.  */);
-  Vpost_command_idle_hook = Qnil;
-
-  DEFVAR_INT ("post-command-idle-delay", &post_command_idle_delay,
-             doc: /* Delay time before running `post-command-idle-hook'.
-This is measured in microseconds.  */);
-  post_command_idle_delay = 100000;
-
 #if 0
   DEFVAR_LISP ("echo-area-clear-hook", ...,
               doc: /* Normal hook run when clearing the echo area.  */);
 #endif
   Qecho_area_clear_hook = intern ("echo-area-clear-hook");
 #if 0
   DEFVAR_LISP ("echo-area-clear-hook", ...,
               doc: /* Normal hook run when clearing the echo area.  */);
 #endif
   Qecho_area_clear_hook = intern ("echo-area-clear-hook");
+  staticpro (&Qecho_area_clear_hook);
   SET_SYMBOL_VALUE (Qecho_area_clear_hook, Qnil);
 
   DEFVAR_LISP ("lucid-menu-bar-dirty-flag", &Vlucid_menu_bar_dirty_flag,
   SET_SYMBOL_VALUE (Qecho_area_clear_hook, Qnil);
 
   DEFVAR_LISP ("lucid-menu-bar-dirty-flag", &Vlucid_menu_bar_dirty_flag,
@@ -11142,13 +11361,15 @@ The elements of the list are event types that may have menu bar bindings.  */);
                 doc: /* Per-terminal keymap that overrides all other local keymaps.
 If this variable is non-nil, it is used as a keymap instead of the
 buffer's local map, and the minor mode keymaps and text property keymaps.
                 doc: /* Per-terminal keymap that overrides all other local keymaps.
 If this variable is non-nil, it is used as a keymap instead of the
 buffer's local map, and the minor mode keymaps and text property keymaps.
+It also replaces `overriding-local-map'.
+
 This variable is intended to let commands such as `universal-argument'
 set up a different keymap for reading the next command.  */);
 
   DEFVAR_LISP ("overriding-local-map", &Voverriding_local_map,
               doc: /* Keymap that overrides all other local keymaps.
 This variable is intended to let commands such as `universal-argument'
 set up a different keymap for reading the next command.  */);
 
   DEFVAR_LISP ("overriding-local-map", &Voverriding_local_map,
               doc: /* Keymap that overrides all other local keymaps.
-If this variable is non-nil, it is used as a keymap instead of the
-buffer's local map, and the minor mode keymaps and text property keymaps.  */);
+If this variable is non-nil, it is used as a keymap--replacing the
+buffer's local map, the minor mode keymaps, and char property keymaps.  */);
   Voverriding_local_map = Qnil;
 
   DEFVAR_LISP ("overriding-local-map-menu-flag", &Voverriding_local_map_menu_flag,
   Voverriding_local_map = Qnil;
 
   DEFVAR_LISP ("overriding-local-map-menu-flag", &Voverriding_local_map_menu_flag,
@@ -11233,8 +11454,8 @@ It's called with one argument, the help string to display.  */);
 
 After a command is executed, if point is moved into a region that has
 special properties (e.g. composition, display), we adjust point to
 
 After a command is executed, if point is moved into a region that has
 special properties (e.g. composition, display), we adjust point to
-the boundary of the region.  But, several special commands sets this
-variable to non-nil, then we suppress the point adjustment.
+the boundary of the region.  But, when a command sets this variable to
+non-nil, we suppress the point adjustment.
 
 This variable is set to nil before reading a command, and is checked
 just after executing the command.  */);
 
 This variable is set to nil before reading a command, and is checked
 just after executing the command.  */);
@@ -11249,16 +11470,24 @@ suppressed only after special commands that set
 `disable-point-adjustment' (which see) to non-nil.  */);
   Vglobal_disable_point_adjustment = Qnil;
 
 `disable-point-adjustment' (which see) to non-nil.  */);
   Vglobal_disable_point_adjustment = Qnil;
 
-  DEFVAR_BOOL ("update-menu-bindings", &update_menu_bindings,
-              doc: /* Non-nil means updating menu bindings is allowed.
-A value of nil means menu bindings should not be updated.
-Used during Emacs' startup.  */);
-  update_menu_bindings = 1;
-
   DEFVAR_LISP ("minibuffer-message-timeout", &Vminibuffer_message_timeout,
               doc: /* *How long to display an echo-area message when the minibuffer is active.
 If the value is not a number, such messages don't time out.  */);
   Vminibuffer_message_timeout = make_number (2);
   DEFVAR_LISP ("minibuffer-message-timeout", &Vminibuffer_message_timeout,
               doc: /* *How long to display an echo-area message when the minibuffer is active.
 If the value is not a number, such messages don't time out.  */);
   Vminibuffer_message_timeout = make_number (2);
+
+  DEFVAR_LISP ("throw-on-input", &Vthrow_on_input,
+              doc: /* If non-nil, any keyboard input throws to this symbol.
+The value of that variable is passed to `quit-flag' and later causes a
+peculiar kind of quitting.  */);
+  Vthrow_on_input = 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.
+
+Help functions bind this to allow help on disabled menu items
+and tool-bar buttons.  */);
+  Venable_disabled_menus_and_buttons = Qnil;
 }
 
 void
 }
 
 void
@@ -11272,14 +11501,33 @@ keys_of_keyboard ()
 
   initial_define_lispy_key (Vspecial_event_map, "delete-frame",
                            "handle-delete-frame");
 
   initial_define_lispy_key (Vspecial_event_map, "delete-frame",
                            "handle-delete-frame");
+  /* Here we used to use `ignore-event' which would simple set prefix-arg to
+     current-prefix-arg, as is done in `handle-switch-frame'.
+     But `handle-switch-frame is not run from the special-map.
+     Commands from that map are run in a special way that automatically
+     preserves the prefix-arg.  Restoring the prefix arg here is not just
+     redundant but harmful:
+     - C-u C-x v =
+     - current-prefix-arg is set to non-nil, prefix-arg is set to nil.
+     - after the first prompt, the exit-minibuffer-hook is run which may
+       iconify a frame and thus push a `iconify-frame' event.
+     - after running exit-minibuffer-hook, current-prefix-arg is
+       restored to the non-nil value it had before the prompt.
+     - we enter the second prompt.
+       current-prefix-arg is non-nil, prefix-arg is nil.
+     - before running the first real event, we run the special iconify-frame
+       event, but we pass the `special' arg to execute-command so
+       current-prefix-arg and prefix-arg are left untouched.
+     - here we foolishly copy the non-nil current-prefix-arg to prefix-arg.
+     - the next key event will have a spuriously non-nil current-prefix-arg.  */
   initial_define_lispy_key (Vspecial_event_map, "iconify-frame",
   initial_define_lispy_key (Vspecial_event_map, "iconify-frame",
-                           "ignore-event");
+                           "ignore");
   initial_define_lispy_key (Vspecial_event_map, "make-frame-visible",
   initial_define_lispy_key (Vspecial_event_map, "make-frame-visible",
-                           "ignore-event");
+                           "ignore");
   /* Handling it at such a low-level causes read_key_sequence to get
    * confused because it doesn't realize that the current_buffer was
    * changed by read_char.
   /* Handling it at such a low-level causes read_key_sequence to get
    * confused because it doesn't realize that the current_buffer was
    * changed by read_char.
-   * 
+   *
    * initial_define_lispy_key (Vspecial_event_map, "select-window",
    *                       "handle-select-window"); */
   initial_define_lispy_key (Vspecial_event_map, "save-session",
    * initial_define_lispy_key (Vspecial_event_map, "select-window",
    *                       "handle-select-window"); */
   initial_define_lispy_key (Vspecial_event_map, "save-session",
@@ -11317,8 +11565,12 @@ mark_kboards ()
       {
        if (event == kbd_buffer + KBD_BUFFER_SIZE)
          event = kbd_buffer;
       {
        if (event == kbd_buffer + KBD_BUFFER_SIZE)
          event = kbd_buffer;
-       mark_object (event->x);
-       mark_object (event->y);
+       if (event->kind != SELECTION_REQUEST_EVENT
+           && event->kind != SELECTION_CLEAR_EVENT)
+         {
+           mark_object (event->x);
+           mark_object (event->y);
+         }
        mark_object (event->frame_or_window);
        mark_object (event->arg);
       }
        mark_object (event->frame_or_window);
        mark_object (event->arg);
       }