]> code.delx.au - gnu-emacs/blobdiff - src/keyboard.c
(xic_defaut_fontset): New constant.
[gnu-emacs] / src / keyboard.c
index 268d782e47822985332b669789c39ec46a855d95..a1c3334bbb85a4e36e7d4c0f8b234aaa9398cf8b 100644 (file)
@@ -1,6 +1,6 @@
 /* Keyboard and mouse input; editor command loop.
-   Copyright (C) 1985,86,87,88,89,93,94,95,96,97,99,2000,01,02,03,04
-     Free Software Foundation, Inc.
+   Copyright (C) 1985, 1986, 1987, 1988, 1989, 1993, 1994, 1995, 1996, 1997,
+     1999, 2000, 2001, 2002, 2003, 2004, 2005  Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -45,6 +45,9 @@ Boston, MA 02111-1307, USA.  */
 #include <setjmp.h>
 #include <errno.h>
 
+#ifdef HAVE_GTK_AND_PTHREAD
+#include <pthread.h>
+#endif
 #ifdef MSDOS
 #include "msdos.h"
 #include <time.h>
@@ -62,6 +65,10 @@ Boston, MA 02111-1307, USA.  */
 #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"
@@ -607,7 +614,7 @@ int flow_control;
 
 /* We are unable to use interrupts if FIONREAD is not available,
    so flush SIGIO so we won't try.  */
-#if !defined (FIONREAD) || defined(HAVE_CARBON)
+#if !defined (FIONREAD)
 #ifdef SIGIO
 #undef SIGIO
 #endif
@@ -643,14 +650,17 @@ static EMACS_TIME timer_last_idleness_start_time;
 \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));
-static void get_filtered_input_pending P_ ((int *, int, 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 ();
@@ -676,6 +686,9 @@ 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 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.  */
@@ -1429,7 +1442,7 @@ command_loop_1 ()
        resize_echo_area_exactly ();
 
       if (!NILP (Vdeferred_action_list))
-       call0 (Vdeferred_action_function);
+       safe_run_hooks (Qdeferred_action_function);
 
       if (!NILP (Vpost_command_idle_hook) && !NILP (Vrun_hooks))
        {
@@ -1615,7 +1628,10 @@ command_loop_1 ()
       if (NILP (Vthis_command))
        {
          /* nil means key is undefined.  */
+         Lisp_Object keys = Fvector (i, keybuf);
+         keys = Fkey_description (keys, Qnil);
          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;
@@ -1837,6 +1853,14 @@ command_loop_1 ()
 
       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'.  */
@@ -1852,16 +1876,6 @@ command_loop_1 ()
            call1 (Vrun_hooks, intern ("activate-mark-hook"));
        }
 
-      /* Setting transient-mark-mode to `only' is a way of
-        turning it on for just one command.  */
-      if (!NILP (current_buffer->mark_active) && !NILP (Vrun_hooks))
-       {
-         if (EQ (Vtransient_mark_mode, Qidentity))
-           Vtransient_mark_mode = Qnil;
-         if (EQ (Vtransient_mark_mode, Qonly))
-           Vtransient_mark_mode = Qidentity;
-       }
-
     finalize:
 
       if (current_buffer == prev_buffer
@@ -2387,7 +2401,6 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
   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;
@@ -2894,9 +2907,6 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
 
  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;
 
@@ -2936,7 +2946,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.  */
-       timer_idleness_start_time = last_idle_start;
+       timer_resume_idle ();
 
       /* Resume allowing input from any kboard, if that was true before.  */
       if (!was_locked)
@@ -3041,6 +3051,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;
+      Lisp_Object saved_echo_string = current_kboard->echo_string;
       int saved_echo_after_prompt = current_kboard->echo_after_prompt;
 
 #if 0
@@ -3095,6 +3106,7 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
 
       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 ();
@@ -3135,7 +3147,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.  */
-      timer_idleness_start_time = last_idle_start;
+      timer_resume_idle ();
       goto retry;
     }
 
@@ -3436,10 +3448,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.  */
-      if (!readable_events (1))
+      if (!readable_events (READABLE_EVENTS_DO_TIMERS_NOW))
        {
          redisplay_preserve_echo_area (6);
-         get_input_pending (&input_pending, 1);
+         get_input_pending (&input_pending,
+                            READABLE_EVENTS_DO_TIMERS_NOW);
        }
     }
   return Qnil;
@@ -3491,20 +3504,19 @@ 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
-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)
     {
       int have_live_event = 1;
 
-      if (filter_events)
+      if (flags & READABLE_EVENTS_FILTER_EVENTS)
         {
           struct input_event *event;
 
@@ -3525,7 +3537,8 @@ readable_filtered_events (do_timers_now, filter_events)
     }
 
 #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)
@@ -3543,15 +3556,6 @@ readable_filtered_events (do_timers_now, filter_events)
   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;
 
@@ -3577,6 +3581,9 @@ event_to_kboard (event)
 }
 #endif
 
+
+Lisp_Object Vthrow_on_input;
+
 /* Store an event obtained at interrupt level into kbd_buffer, fifo */
 
 void
@@ -3699,36 +3706,44 @@ kbd_buffer_store_event_hold (event, hold_quit)
      Discard the event if it would fill the last slot.  */
   if (kbd_fetch_ptr - 1 != kbd_store_ptr)
     {
+      *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
 
-      ++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;
     }
 }
 
@@ -3899,10 +3914,7 @@ kbd_buffer_get_event (kbp, used_mouse_menu)
        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.  */
@@ -3946,7 +3958,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.  */
-      if (event->kind == SELECTION_REQUEST_EVENT)
+      if (event->kind == SELECTION_REQUEST_EVENT
+         || event->kind == SELECTION_CLEAR_EVENT)
        {
 #ifdef HAVE_X11
          struct input_event copy;
@@ -3957,7 +3970,7 @@ kbd_buffer_get_event (kbp, used_mouse_menu)
          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.  */
@@ -3965,22 +3978,6 @@ kbd_buffer_get_event (kbp, used_mouse_menu)
 #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)
        {
@@ -4205,7 +4202,8 @@ swallow_events (do_display)
 
       /* 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;
@@ -4216,25 +4214,7 @@ swallow_events (do_display)
          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.  */
@@ -4246,7 +4226,7 @@ swallow_events (do_display)
     }
 
   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);
@@ -4255,7 +4235,7 @@ swallow_events (do_display)
 /* 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;
@@ -4283,12 +4263,23 @@ timer_start_idle ()
 
 /* 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);
 }
 
+/* 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;
 
@@ -6527,18 +6518,20 @@ lucid_event_type_list_p (object)
    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. */
 
 static void
-get_filtered_input_pending (addr, do_timers_now, filter_events)
+get_input_pending (addr, flags)
      int *addr;
-     int do_timers_now;
-     int filter_events;
+     int flags;
 {
   /* 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))
@@ -6546,23 +6539,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);
-  *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.  */
@@ -6664,7 +6641,6 @@ read_avail_input (expected)
 
   if (read_socket_hook)
     {
-      int discard = 0;
       int nr;
       struct input_event hold_quit;
 
@@ -6812,6 +6788,7 @@ handle_async_input ()
 #ifdef BSD4_1
   extern int select_alarmed;
 #endif
+
   interrupt_input_pending = 0;
 
   while (1)
@@ -6839,7 +6816,6 @@ input_available_signal (signo)
 {
   /* Must preserve main program's value of errno.  */
   int old_errno = errno;
-
 #if defined (USG) && !defined (POSIX_SIGNALS)
   /* USG systems forget handlers when they are used;
      must reestablish each time */
@@ -6850,12 +6826,16 @@ input_available_signal (signo)
   sigisheld (SIGIO);
 #endif
 
-  if (input_available_clear_time)
-    EMACS_SET_SECS_USECS (*input_available_clear_time, 0, 0);
-
 #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);
+
+#ifndef SYNC_INPUT
   handle_async_input ();
 #endif
 
@@ -8850,14 +8830,7 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
             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
@@ -9743,6 +9716,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;
+#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);
@@ -9774,6 +9756,10 @@ DEFUN ("execute-extended-command", Fexecute_extended_command, Sexecute_extended_
                               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");
 
@@ -9883,6 +9869,18 @@ detect_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
@@ -9892,7 +9890,7 @@ detect_input_pending_run_timers (do_display)
   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)
     {
@@ -9920,7 +9918,7 @@ clear_input_pending ()
 }
 
 /* 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.  */
@@ -9941,7 +9939,9 @@ if there is a doubt, the value is t.  */)
   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;
 }
 
@@ -10278,6 +10278,7 @@ interrupt_signal (signalnum)    /* If we don't have an argument, */
     }
 #endif /* USG */
 
+  SIGNAL_THREAD_CHECK (signalnum);
   cancel_echoing ();
 
   if (!NILP (Vquit_flag)
@@ -10529,18 +10530,23 @@ The elements of this list correspond to the arguments of
   return Flist (sizeof (val) / sizeof (val[0]), val);
 }
 
-DEFUN ("posn-at-x-y", Fposn_at_x_y, Sposn_at_x_y, 2, 3, 0,
+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)
-     Lisp_Object x, y, frame_or_window;
+  (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;
 
@@ -10552,7 +10558,10 @@ The `posn-' functions access elements of such lists.  */)
 
       w = XWINDOW (frame_or_window);
       XSETINT (x, (WINDOW_TO_FRAME_PIXEL_X (w, XINT (x))
-                  + window_box_left_offset (w, TEXT_AREA)));
+                  + (NILP (whole)
+                     ? window_box_left_offset (w, TEXT_AREA)
+                     : - (WINDOW_LEFT_SCROLL_BAR_COLS (w)
+                          * WINDOW_FRAME_COLUMN_WIDTH (w)))));
       XSETINT (y, WINDOW_TO_FRAME_PIXEL_Y (w, XINT (y)));
       frame_or_window = w->frame;
     }
@@ -10572,7 +10581,7 @@ 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.  */*/)
+The `posn-' functions access elements of such lists.  */)
   (pos, window)
      Lisp_Object pos, window;
 {
@@ -10580,7 +10589,7 @@ The `posn-' functions access elements of such lists.  */*/)
 
   tem = Fpos_visible_in_window_p (pos, window, Qt);
   if (!NILP (tem))
-    tem = Fposn_at_x_y (XCAR (tem), XCAR (XCDR (tem)), window);
+    tem = Fposn_at_x_y (XCAR (tem), XCAR (XCDR (tem)), window, Qnil);
   return tem;
 }
 
@@ -11280,14 +11289,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.
-It also overrides `overriding-local-map'.
+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.
-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,
@@ -11398,6 +11408,12 @@ Used during Emacs' startup.  */);
               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;
 }
 
 void
@@ -11456,7 +11472,8 @@ mark_kboards ()
       {
        if (event == kbd_buffer + KBD_BUFFER_SIZE)
          event = kbd_buffer;
-       if (event->kind != SELECTION_REQUEST_EVENT)
+       if (event->kind != SELECTION_REQUEST_EVENT
+           && event->kind != SELECTION_CLEAR_EVENT)
          {
            mark_object (event->x);
            mark_object (event->y);