]> code.delx.au - gnu-emacs/blobdiff - src/keyboard.c
Merged in changes from CVS trunk.
[gnu-emacs] / src / keyboard.c
index fb52c7e9f61b8a4826b1a8e2da7ff712f301e7d8..74f8d7d51e0763a1a516dfc4e4154585fef6c47b 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,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.
 
 
 This file is part of GNU Emacs.
 
@@ -16,19 +17,19 @@ 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 <stdio.h>
 
 #include <config.h>
 #include <signal.h>
 #include <stdio.h>
+#include "lisp.h"
 #include "termchar.h"
 #include "termopts.h"
 #include "termchar.h"
 #include "termopts.h"
-#include "lisp.h"
+#include "frame.h"
 #include "termhooks.h"
 #include "macros.h"
 #include "keyboard.h"
 #include "termhooks.h"
 #include "macros.h"
 #include "keyboard.h"
-#include "frame.h"
 #include "window.h"
 #include "commands.h"
 #include "buffer.h"
 #include "window.h"
 #include "commands.h"
 #include "buffer.h"
@@ -58,13 +59,16 @@ Boston, MA 02111-1307, USA.  */
 #endif /* not MSDOS */
 
 #include "syssignal.h"
 #endif /* not MSDOS */
 
 #include "syssignal.h"
-#include "systty.h"
 
 #include <sys/types.h>
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>
 #endif
 
 
 #include <sys/types.h>
 #ifdef HAVE_UNISTD_H
 #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"
@@ -92,9 +96,6 @@ int interrupt_input_blocked;
 int interrupt_input_pending;
 
 
 int interrupt_input_pending;
 
 
-/* File descriptor to use for input.  */
-extern int input_fd;
-
 #ifdef HAVE_WINDOW_SYSTEM
 /* Make all keyboard buffers much bigger when using X windows.  */
 #ifdef MAC_OS8
 #ifdef HAVE_WINDOW_SYSTEM
 /* Make all keyboard buffers much bigger when using X windows.  */
 #ifdef MAC_OS8
@@ -417,13 +418,6 @@ Lisp_Object Vtop_level;
 /* User-supplied table to translate input characters.  */
 Lisp_Object Vkeyboard_translate_table;
 
 /* User-supplied table to translate input characters.  */
 Lisp_Object Vkeyboard_translate_table;
 
-/* Keymap mapping ASCII function key sequences onto their preferred forms.  */
-extern Lisp_Object Vfunction_key_map;
-
-/* Another keymap that maps key sequences into key sequences.
-   This one takes precedence over ordinary definitions.  */
-extern Lisp_Object Vkey_translation_map;
-
 /* If non-nil, this implements the current input method.  */
 Lisp_Object Vinput_method_function;
 Lisp_Object Qinput_method_function;
 /* If non-nil, this implements the current input method.  */
 Lisp_Object Vinput_method_function;
 Lisp_Object Qinput_method_function;
@@ -446,11 +440,12 @@ 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;
+/* Parent keymap of terminal-local function-key-map instances.  */
+Lisp_Object Vfunction_key_map;
+
+/* Parent keymap of terminal-local key-translation-map instances.  */
+Lisp_Object Vkey_translation_map;
 
 /* 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,11 +464,6 @@ FILE *dribble;
 /* Nonzero if input is available.  */
 int input_pending;
 
 /* Nonzero if input is available.  */
 int input_pending;
 
-/* 1 if should obey 0200 bit in input chars as "Meta", 2 if should
-   keep 0200 bit in input chars.  0 to ignore the 0200 bit.  */
-
-int meta_key;
-
 /* Non-zero means force key bindings update in parse_menu_item.  */
 
 int update_menu_bindings;
 /* Non-zero means force key bindings update in parse_menu_item.  */
 
 int update_menu_bindings;
@@ -519,10 +509,14 @@ 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 Qlanguage_change;
 #endif
 Lisp_Object Qdrag_n_drop;
@@ -600,9 +594,6 @@ int interrupt_input;
 /* Nonzero while interrupts are temporarily deferred during redisplay.  */
 int interrupts_deferred;
 
 /* Nonzero while interrupts are temporarily deferred during redisplay.  */
 int interrupts_deferred;
 
-/* Nonzero means use ^S/^Q for flow control.  */
-int flow_control;
-
 /* Allow m- file to inhibit use of FIONREAD.  */
 #ifdef BROKEN_FIONREAD
 #undef FIONREAD
 /* Allow m- file to inhibit use of FIONREAD.  */
 #ifdef BROKEN_FIONREAD
 #undef FIONREAD
@@ -646,14 +637,17 @@ static EMACS_TIME timer_last_idleness_start_time;
 \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 ();
@@ -679,6 +673,7 @@ 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 handle_interrupt P_ ((void));
 static void timer_start_idle P_ ((void));
 static void timer_stop_idle P_ ((void));
 static void timer_resume_idle P_ ((void));
 static void timer_start_idle P_ ((void));
 static void timer_stop_idle P_ ((void));
 static void timer_resume_idle P_ ((void));
@@ -1014,7 +1009,7 @@ 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.  */)
      ()
 {
 This function is called by the editor initialization to begin editing.  */)
      ()
 {
@@ -1120,6 +1115,22 @@ struct kboard_stack
 
 static struct kboard_stack *kboard_stack;
 
 
 static struct kboard_stack *kboard_stack;
 
+void
+push_device_kboard (d)
+     struct device *d;
+{
+#ifdef MULTI_KBOARD
+  struct kboard_stack *p
+    = (struct kboard_stack *) xmalloc (sizeof (struct kboard_stack));
+
+  p->next = kboard_stack;
+  p->kboard = current_kboard;
+  kboard_stack = p;
+
+  current_kboard = d->kboard;
+#endif
+}
+
 void
 push_frame_kboard (f)
      FRAME_PTR f;
 void
 push_frame_kboard (f)
      FRAME_PTR f;
@@ -1162,21 +1173,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 ();
@@ -1226,11 +1237,7 @@ cmd_error_internal (data, context)
      yet, or we're not interactive, it's best to dump this message out
      to stderr and exit.  */
   if (!sf->glyphs_initialized_p
      yet, or we're not interactive, it's best to dump this message out
      to stderr and exit.  */
   if (!sf->glyphs_initialized_p
-      /* This is the case of the frame dumped with Emacs, when we're
-        running under a window system.  */
-      || (!NILP (Vwindow_system)
-         && !inhibit_window_system
-         && FRAME_TERMCAP_P (sf))
+      || FRAME_INITIAL_P (sf)
       || noninteractive)
     {
       stream = Qexternal_debugging_output;
       || noninteractive)
     {
       stream = Qexternal_debugging_output;
@@ -1277,19 +1284,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 ();
+        /* 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)
@@ -1402,12 +1409,12 @@ 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;
 #endif
   struct buffer *prev_buffer = NULL;
 #ifdef MULTI_KBOARD
   int was_locked = single_kboard;
 #endif
-  int already_adjusted;
+  int already_adjusted = 0;
 
   current_kboard->Vprefix_arg = Qnil;
   current_kboard->Vlast_prefix_arg = Qnil;
 
   current_kboard->Vprefix_arg = Qnil;
   current_kboard->Vlast_prefix_arg = Qnil;
@@ -1435,17 +1442,7 @@ 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;
     }
 
   Vmemory_full = Qnil;
@@ -1513,7 +1510,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.  */
@@ -1526,6 +1523,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],
@@ -1571,11 +1569,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. */
            }
@@ -1674,7 +1672,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;
                }
@@ -1709,7 +1707,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;
                }
@@ -1722,7 +1720,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)
@@ -1744,7 +1742,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);
 
@@ -1772,7 +1770,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 ();
@@ -1790,7 +1788,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
           }
@@ -1811,16 +1809,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,
@@ -1936,10 +1924,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;
@@ -2104,7 +2095,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 */
@@ -2116,7 +2111,10 @@ void
 start_polling ()
 {
 #ifdef POLL_FOR_INPUT
 start_polling ()
 {
 #ifdef POLL_FOR_INPUT
-  if (read_socket_hook && !interrupt_input)
+  /* XXX This condition was (read_socket_hook && !interrupt_input),
+     but read_socket_hook is not global anymore.  Let's pretend that
+     it's always set. */
+  if (!interrupt_input)
     {
       /* Turn alarm handling on unconditionally.  It might have
         been turned off in process.c.  */
     {
       /* Turn alarm handling on unconditionally.  It might have
         been turned off in process.c.  */
@@ -2150,7 +2148,10 @@ int
 input_polling_used ()
 {
 #ifdef POLL_FOR_INPUT
 input_polling_used ()
 {
 #ifdef POLL_FOR_INPUT
-  return read_socket_hook && !interrupt_input;
+  /* XXX This condition was (read_socket_hook && !interrupt_input),
+     but read_socket_hook is not global anymore.  Let's pretend that
+     it's always set. */
+  return !interrupt_input;
 #else
   return 0;
 #endif
 #else
   return 0;
 #endif
@@ -2162,7 +2163,10 @@ void
 stop_polling ()
 {
 #ifdef POLL_FOR_INPUT
 stop_polling ()
 {
 #ifdef POLL_FOR_INPUT
-  if (read_socket_hook && !interrupt_input)
+  /* XXX This condition was (read_socket_hook && !interrupt_input),
+     but read_socket_hook is not global anymore.  Let's pretend that
+     it's always set. */
+  if (!interrupt_input)
     ++poll_suppress_count;
 #endif
 }
     ++poll_suppress_count;
 #endif
 }
@@ -2247,12 +2251,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.
@@ -2297,6 +2305,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))
@@ -2475,7 +2488,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
@@ -2492,19 +2505,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;
     }
@@ -2613,6 +2626,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;
@@ -3441,10 +3457,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;
@@ -3496,20 +3513,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;
 
@@ -3517,20 +3535,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)
@@ -3548,15 +3580,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;
 
@@ -3679,7 +3702,7 @@ kbd_buffer_store_event_hold (event, hold_quit)
          }
 
          last_event_timestamp = event->timestamp;
          }
 
          last_event_timestamp = event->timestamp;
-         interrupt_signal (0 /* dummy */);
+         handle_interrupt ();
          return;
        }
 
          return;
        }
 
@@ -3988,7 +4011,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)).  */
@@ -4020,11 +4043,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)).  */
          obj = Fcons (event->frame_or_window, Qnil);
          /* Make an event (language-change (FRAME CHARSET LCID)).  */
          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;
        }
@@ -4143,7 +4171,11 @@ kbd_buffer_get_event (kbp, used_mouse_menu)
         If there is no valid info, it does not store anything
         so x remains nil.  */
       x = Qnil;
         If there is no valid info, it does not store anything
         so x remains nil.  */
       x = Qnil;
-      (*mouse_position_hook) (&f, 0, &bar_window, &part, &x, &y, &time);
+
+      /* XXX Can f or mouse_position_hook be NULL here? */
+      if (f && FRAME_DEVICE (f)->mouse_position_hook)
+        (*FRAME_DEVICE (f)->mouse_position_hook) (&f, 0, &bar_window,
+                                                  &part, &x, &y, &time);
 
       obj = Qnil;
 
 
       obj = Qnil;
 
@@ -4227,7 +4259,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);
@@ -6294,8 +6326,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);
-         sprintf (buf, "%s-%ld", SDATA (name_alist_or_stem),
-                  (long) 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])
@@ -6519,18 +6551,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))
@@ -6538,23 +6572,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.  */
@@ -6574,7 +6592,10 @@ gobble_input (expected)
     }
   else
 #ifdef POLL_FOR_INPUT
     }
   else
 #ifdef POLL_FOR_INPUT
-  if (read_socket_hook && !interrupt_input && poll_suppress_count == 0)
+  /* XXX This condition was (read_socket_hook && !interrupt_input),
+     but read_socket_hook is not global anymore.  Let's pretend that
+     it's always set. */
+  if (!interrupt_input && poll_suppress_count == 0)
     {
       SIGMASKTYPE mask;
       mask = sigblock (sigmask (SIGALRM));
     {
       SIGMASKTYPE mask;
       mask = sigblock (sigmask (SIGALRM));
@@ -6651,146 +6672,214 @@ static int
 read_avail_input (expected)
      int expected;
 {
 read_avail_input (expected)
      int expected;
 {
-  register int i;
   int nread = 0;
   int nread = 0;
+  int err = 0;
+  struct device *d;
 
 
-  if (read_socket_hook)
+  /* Loop through the available devices, and call their input hooks. */
+  d = device_list;
+  while (d)
     {
     {
-      int nr;
-      struct input_event hold_quit;
+      struct device *next = d->next_device;
 
 
-      EVENT_INIT (hold_quit);
-      hold_quit.kind = NO_EVENT;
+      if (d->read_socket_hook)
+        {
+          int nr;
+          struct input_event hold_quit;
 
 
-      /* 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);
+          EVENT_INIT (hold_quit);
+          hold_quit.kind = NO_EVENT;
+
+          /* No need for FIONREAD or fcntl; just say don't wait.  */
+          while (nr = (*d->read_socket_hook) (d, expected, &hold_quit), nr > 0)
+            {
+              nread += nr;
+              expected = 0;
+            }
+          
+          if (nr == -1)          /* Not OK to read input now. */
+            {
+              err = 1;
+            }
+          else if (nr == -2)          /* Non-transient error. */
+            {
+              /* The display device terminated; it should be closed. */
+              
+              /* Kill Emacs if this was our last display. */
+              if (! device_list->next_device)
+                /* Formerly simply reported no input, but that
+                   sometimes led to a failure of Emacs to terminate.
+                   SIGHUP seems appropriate if we can't reach the
+                   terminal.  */
+                /* ??? Is it really right to send the signal just to
+                   this process rather than to the whole process
+                   group?  Perhaps on systems with FIONREAD Emacs is
+                   alone in its group.  */
+                kill (getpid (), SIGHUP);
+              
+              /* XXX Is calling delete_device safe here?  It calls Fdelete_frame. */
+              if (d->delete_device_hook)
+                (*d->delete_device_hook) (d);
+              else
+                delete_device (d);
+            }
+
+          if (hold_quit.kind != NO_EVENT)
+            kbd_buffer_store_event (&hold_quit);
+        }
+
+      d = next;
     }
     }
-  else
-    {
-      /* Using KBD_BUFFER_SIZE - 1 here avoids reading more than
-        the kbd_buffer can really hold.  That may prevent loss
-        of characters on some systems when input is stuffed at us.  */
-      unsigned char cbuf[KBD_BUFFER_SIZE - 1];
-      int n_to_read;
 
 
-      /* Determine how many characters we should *try* to read.  */
+  if (err && !nread)
+    nread = -1;
+
+  return nread;
+}
+
+/* This is the tty way of reading available input.
+
+   Note that each terminal device has its own `struct device' object,
+   and so this function is called once for each individual termcap
+   display.  The first parameter indicates which device to read from.  */
+
+int
+tty_read_avail_input (struct device *device,
+                      int expected,
+                      struct input_event *hold_quit)
+{
+  /* Using KBD_BUFFER_SIZE - 1 here avoids reading more than
+     the kbd_buffer can really hold.  That may prevent loss
+     of characters on some systems when input is stuffed at us.  */
+  unsigned char cbuf[KBD_BUFFER_SIZE - 1];
+  int n_to_read, i;
+  struct tty_display_info *tty = device->display_info.tty;
+  int nread = 0;
+
+  if (device->type != output_termcap)
+    abort ();
+
+  /* XXX I think the following code should be moved to separate hook
+     functions in system-dependent files. */
 #ifdef WINDOWSNT
 #ifdef WINDOWSNT
-      return 0;
+  return 0;
 #else /* not WINDOWSNT */
 #ifdef MSDOS
 #else /* not WINDOWSNT */
 #ifdef MSDOS
-      n_to_read = dos_keysns ();
-      if (n_to_read == 0)
-       return 0;
+  n_to_read = dos_keysns ();
+  if (n_to_read == 0)
+    return 0;
+
+  cbuf[0] = dos_keyread ();
+  nread = 1;
+
 #else /* not MSDOS */
 #else /* not MSDOS */
+
+  if (! tty->term_initted)      /* In case we get called during bootstrap. */
+    return 0;
+
+  if (! tty->input)
+    return 0;                   /* The terminal is suspended. */
+
+  /* Determine how many characters we should *try* to read.  */
 #ifdef FIONREAD
 #ifdef FIONREAD
-      /* Find out how much input is available.  */
-      if (ioctl (input_fd, FIONREAD, &n_to_read) < 0)
-       /* Formerly simply reported no input, but that sometimes led to
-          a failure of Emacs to terminate.
-          SIGHUP seems appropriate if we can't reach the terminal.  */
-       /* ??? Is it really right to send the signal just to this process
-          rather than to the whole process group?
-          Perhaps on systems with FIONREAD Emacs is alone in its group.  */
-       {
-         if (! noninteractive)
-           kill (getpid (), SIGHUP);
-         else
-           n_to_read = 0;
-       }
-      if (n_to_read == 0)
-       return 0;
-      if (n_to_read > sizeof cbuf)
-       n_to_read = sizeof cbuf;
+  /* Find out how much input is available.  */
+  if (ioctl (fileno (tty->input), FIONREAD, &n_to_read) < 0)
+    {
+      if (! noninteractive)
+        return -2;          /* Close this device. */
+      else
+        n_to_read = 0;
+    }
+  if (n_to_read == 0)
+    return 0;
+  if (n_to_read > sizeof cbuf)
+    n_to_read = sizeof cbuf;
 #else /* no FIONREAD */
 #if defined (USG) || defined (DGUX) || defined(CYGWIN)
 #else /* no FIONREAD */
 #if defined (USG) || defined (DGUX) || defined(CYGWIN)
-      /* Read some input if available, but don't wait.  */
-      n_to_read = sizeof cbuf;
-      fcntl (input_fd, F_SETFL, O_NDELAY);
+  /* Read some input if available, but don't wait.  */
+  n_to_read = sizeof cbuf;
+  fcntl (fileno (tty->input), F_SETFL, O_NDELAY);
 #else
 #else
-      you lose;
+  you lose;
 #endif
 #endif
 #endif
 #endif
-#endif /* not MSDOS */
-#endif /* not WINDOWSNT */
 
 
-      /* Now read; for one reason or another, this will not block.
-        NREAD is set to the number of chars read.  */
-      do
-       {
-#ifdef MSDOS
-         cbuf[0] = dos_keyread ();
-         nread = 1;
-#else
-         nread = emacs_read (input_fd, cbuf, n_to_read);
-#endif
-         /* POSIX infers that processes which are not in the session leader's
-            process group won't get SIGHUP's at logout time.  BSDI adheres to
-            this part standard and returns -1 from read (0) with errno==EIO
-            when the control tty is taken away.
-            Jeffrey Honig <jch@bsdi.com> says this is generally safe.  */
-         if (nread == -1 && errno == EIO)
-           kill (0, SIGHUP);
+  /* Now read; for one reason or another, this will not block.
+     NREAD is set to the number of chars read.  */
+  do
+    {
+      nread = emacs_read (fileno (tty->input), cbuf, n_to_read);
+      /* POSIX infers that processes which are not in the session leader's
+         process group won't get SIGHUP's at logout time.  BSDI adheres to
+         this part standard and returns -1 from read (0) with errno==EIO
+         when the control tty is taken away.
+         Jeffrey Honig <jch@bsdi.com> says this is generally safe. */
+      if (nread == -1 && errno == EIO)
+        return -2;          /* Close this device. */
 #if defined (AIX) && (! defined (aix386) && defined (_BSD))
 #if defined (AIX) && (! defined (aix386) && defined (_BSD))
-         /* The kernel sometimes fails to deliver SIGHUP for ptys.
-            This looks incorrect, but it isn't, because _BSD causes
-            O_NDELAY to be defined in fcntl.h as O_NONBLOCK,
-            and that causes a value other than 0 when there is no input.  */
-         if (nread == 0)
-           kill (0, SIGHUP);
-#endif
-       }
-      while (
-            /* We used to retry the read if it was interrupted.
-               But this does the wrong thing when O_NDELAY causes
-               an EAGAIN error.  Does anybody know of a situation
-               where a retry is actually needed?  */
+      /* The kernel sometimes fails to deliver SIGHUP for ptys.
+         This looks incorrect, but it isn't, because _BSD causes
+         O_NDELAY to be defined in fcntl.h as O_NONBLOCK,
+         and that causes a value other than 0 when there is no input.  */
+      if (nread == 0)
+        return -2;          /* Close this device. */
+#endif
+    }
+  while (
+         /* We used to retry the read if it was interrupted.
+            But this does the wrong thing when O_NDELAY causes
+            an EAGAIN error.  Does anybody know of a situation
+            where a retry is actually needed?  */
 #if 0
 #if 0
-            nread < 0 && (errno == EAGAIN
+         nread < 0 && (errno == EAGAIN
 #ifdef EFAULT
 #ifdef EFAULT
-                          || errno == EFAULT
+                       || errno == EFAULT
 #endif
 #ifdef EBADSLT
 #endif
 #ifdef EBADSLT
-                          || errno == EBADSLT
+                       || errno == EBADSLT
 #endif
 #endif
-                          )
+                       )
 #else
 #else
-            0
+         0
 #endif
 #endif
-            );
+         );
 
 #ifndef FIONREAD
 #if defined (USG) || defined (DGUX) || defined (CYGWIN)
 
 #ifndef FIONREAD
 #if defined (USG) || defined (DGUX) || defined (CYGWIN)
-      fcntl (input_fd, F_SETFL, 0);
+  fcntl (fileno (tty->input), F_SETFL, 0);
 #endif /* USG or DGUX or CYGWIN */
 #endif /* no FIONREAD */
 #endif /* USG or DGUX or CYGWIN */
 #endif /* no FIONREAD */
-      for (i = 0; i < nread; i++)
-       {
-         struct input_event buf;
-         EVENT_INIT (buf);
-         buf.kind = ASCII_KEYSTROKE_EVENT;
-         buf.modifiers = 0;
-         if (meta_key == 1 && (cbuf[i] & 0x80))
-           buf.modifiers = meta_modifier;
-         if (meta_key != 2)
-           cbuf[i] &= ~0x80;
-
-         buf.code = cbuf[i];
-         buf.frame_or_window = selected_frame;
-         buf.arg = Qnil;
-
-         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;
-       }
+
+  if (nread <= 0)
+    return nread;
+
+#endif /* not MSDOS */
+#endif /* not WINDOWSNT */
+
+  for (i = 0; i < nread; i++)
+    {
+      struct input_event buf;
+      EVENT_INIT (buf);
+      buf.kind = ASCII_KEYSTROKE_EVENT;
+      buf.modifiers = 0;
+      if (tty->meta_key == 1 && (cbuf[i] & 0x80))
+        buf.modifiers = meta_modifier;
+      if (tty->meta_key != 2)
+        cbuf[i] &= ~0x80;
+      
+      buf.code = cbuf[i];
+      /* Set the frame corresponding to the active tty.  Note that the
+         value of selected_frame is not reliable here, redisplay tends
+         to temporarily change it. */
+      buf.frame_or_window = tty->top_frame;
+      buf.arg = Qnil;
+      
+      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;
     }
 
   return nread;
@@ -6913,8 +7002,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
@@ -6930,8 +7017,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
@@ -7035,7 +7120,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
@@ -8581,8 +8665,8 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
   last_nonmenu_event = Qnil;
 
   delayed_switch_frame = Qnil;
   last_nonmenu_event = Qnil;
 
   delayed_switch_frame = Qnil;
-  fkey.map = fkey.parent = Vfunction_key_map;
-  keytran.map = keytran.parent = Vkey_translation_map;
+  fkey.map = fkey.parent = current_kboard->Vlocal_function_key_map;
+  keytran.map = keytran.parent = current_kboard->Vlocal_key_translation_map;
   /* If there is no translation-map, turn off scanning.  */
   fkey.start = fkey.end = KEYMAPP (fkey.map) ? 0 : bufsize + 1;
   keytran.start = keytran.end = KEYMAPP (keytran.map) ? 0 : bufsize + 1;
   /* If there is no translation-map, turn off scanning.  */
   fkey.start = fkey.end = KEYMAPP (fkey.map) ? 0 : bufsize + 1;
   keytran.start = keytran.end = KEYMAPP (keytran.map) ? 0 : bufsize + 1;
@@ -9731,6 +9815,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);
@@ -9762,6 +9855,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");
 
@@ -9797,7 +9894,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);
@@ -9871,6 +9968,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
@@ -9880,7 +9989,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)
     {
@@ -9890,8 +9999,12 @@ detect_input_pending_run_timers (do_display)
         from an idle timer function.  The symptom of the bug is that
         the cursor sometimes doesn't become visible until the next X
         event is processed.  --gerd.  */
         from an idle timer function.  The symptom of the bug is that
         the cursor sometimes doesn't become visible until the next X
         event is processed.  --gerd.  */
-      if (rif)
-       rif->flush_display (NULL);
+      {
+        Lisp_Object tail, frame;
+        FOR_EACH_FRAME (tail, frame)
+          if (FRAME_RIF (XFRAME (frame)))
+            FRAME_RIF (XFRAME (frame))->flush_display (XFRAME (frame));
+      }
     }
 
   return input_pending;
     }
 
   return input_pending;
@@ -9929,7 +10042,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;
 }
 
@@ -10133,6 +10248,9 @@ On such systems, Emacs starts a subshell instead of suspending.  */)
   int width, height;
   struct gcpro gcpro1;
 
   int width, height;
   struct gcpro gcpro1;
 
+  if (tty_list && tty_list->next)
+    error ("There are other tty frames open; close them before suspending Emacs");
+
   if (!NILP (stuffstring))
     CHECK_STRING (stuffstring);
 
   if (!NILP (stuffstring))
     CHECK_STRING (stuffstring);
 
@@ -10141,11 +10259,11 @@ On such systems, Emacs starts a subshell instead of suspending.  */)
     call1 (Vrun_hooks, intern ("suspend-hook"));
 
   GCPRO1 (stuffstring);
     call1 (Vrun_hooks, intern ("suspend-hook"));
 
   GCPRO1 (stuffstring);
-  get_frame_size (&old_width, &old_height);
-  reset_sys_modes ();
+  get_tty_size (fileno (CURTTY ()->input), &old_width, &old_height);
+  reset_all_sys_modes ();
   /* sys_suspend can get an error if it tries to fork a subshell
      and the system resources aren't available for that.  */
   /* sys_suspend can get an error if it tries to fork a subshell
      and the system resources aren't available for that.  */
-  record_unwind_protect ((Lisp_Object (*) P_ ((Lisp_Object))) init_sys_modes,
+  record_unwind_protect ((Lisp_Object (*) P_ ((Lisp_Object))) init_all_sys_modes,
                         Qnil);
   stuff_buffered_input (stuffstring);
   if (cannot_suspend)
                         Qnil);
   stuff_buffered_input (stuffstring);
   if (cannot_suspend)
@@ -10157,7 +10275,7 @@ On such systems, Emacs starts a subshell instead of suspending.  */)
   /* Check if terminal/window size has changed.
      Note that this is not useful when we are running directly
      with a window system; but suspend should be disabled in that case.  */
   /* Check if terminal/window size has changed.
      Note that this is not useful when we are running directly
      with a window system; but suspend should be disabled in that case.  */
-  get_frame_size (&width, &height);
+  get_tty_size (fileno (CURTTY ()->input), &width, &height);
   if (width != old_width || height != old_height)
     change_frame_size (SELECTED_FRAME (), height, width, 0, 0, 0);
 
   if (width != old_width || height != old_height)
     change_frame_size (SELECTED_FRAME (), height, width, 0, 0, 0);
 
@@ -10217,10 +10335,10 @@ set_waiting_for_input (time_to_clear)
 {
   input_available_clear_time = time_to_clear;
 
 {
   input_available_clear_time = time_to_clear;
 
-  /* Tell interrupt_signal to throw back to read_char,  */
+  /* Tell handle_interrupt to throw back to read_char,  */
   waiting_for_input = 1;
 
   waiting_for_input = 1;
 
-  /* If interrupt_signal was called before and buffered a C-g,
+  /* If handle_interrupt was called before and buffered a C-g,
      make it run again now, to avoid timing error. */
   if (!NILP (Vquit_flag))
     quit_throw_to_read_char ();
      make it run again now, to avoid timing error. */
   if (!NILP (Vquit_flag))
     quit_throw_to_read_char ();
@@ -10229,48 +10347,82 @@ set_waiting_for_input (time_to_clear)
 void
 clear_waiting_for_input ()
 {
 void
 clear_waiting_for_input ()
 {
-  /* Tell interrupt_signal not to throw back to read_char,  */
+  /* Tell handle_interrupt not to throw back to read_char,  */
   waiting_for_input = 0;
   input_available_clear_time = 0;
 }
 
   waiting_for_input = 0;
   input_available_clear_time = 0;
 }
 
-/* This routine is called at interrupt level in response to C-g.
-
-   If interrupt_input, this is the handler for SIGINT.  Otherwise, it
-   is called from kbd_buffer_store_event, in handling SIGIO or
-   SIGTINT.
-
-   If `waiting_for_input' is non zero, then unless `echoing' is
-   nonzero, immediately throw back to read_char.
+/* The SIGINT handler.
 
 
-   Otherwise it sets the Lisp variable quit-flag not-nil.  This causes
-   eval to throw, when it gets a chance.  If quit-flag is already
-   non-nil, it stops the job right away.  */
+   If we have a frame on the controlling tty, we assume that the
+   SIGINT was generated by C-g, so we call handle_interrupt.
+   Otherwise, the handler kills Emacs.  */
 
 static SIGTYPE
 interrupt_signal (signalnum)   /* If we don't have an argument, */
      int signalnum;            /* some compilers complain in signal calls. */
 {
 
 static SIGTYPE
 interrupt_signal (signalnum)   /* If we don't have an argument, */
      int signalnum;            /* some compilers complain in signal calls. */
 {
-  char c;
   /* Must preserve main program's value of errno.  */
   int old_errno = errno;
   /* Must preserve main program's value of errno.  */
   int old_errno = errno;
-  struct frame *sf = SELECTED_FRAME ();
+  struct device *device;
 
 #if defined (USG) && !defined (POSIX_SIGNALS)
 
 #if defined (USG) && !defined (POSIX_SIGNALS)
-  if (!read_socket_hook && NILP (Vwindow_system))
-    {
-      /* USG systems forget handlers when they are used;
-        must reestablish each time */
-      signal (SIGINT, interrupt_signal);
-      signal (SIGQUIT, interrupt_signal);
-    }
+  /* USG systems forget handlers when they are used;
+     must reestablish each time */
+  signal (SIGINT, interrupt_signal);
+  signal (SIGQUIT, interrupt_signal);
 #endif /* USG */
 
   SIGNAL_THREAD_CHECK (signalnum);
 #endif /* USG */
 
   SIGNAL_THREAD_CHECK (signalnum);
+
+  /* See if we have an active display on our controlling terminal. */
+  device = get_named_tty (NULL);
+  if (!device)
+    {
+      /* If there are no frames there, let's pretend that we are a
+         well-behaving UN*X program and quit. */
+      fatal_error_signal (SIGTERM);
+    }
+  else
+    {
+      /* Otherwise, the SIGINT was probably generated by C-g.  */
+
+      /* Set internal_last_event_frame to the top frame of the
+         controlling tty, if we have a frame there.  We disable the
+         interrupt key on secondary ttys, so the SIGINT must have come
+         from the controlling tty.  */
+      internal_last_event_frame = device->display_info.tty->top_frame;
+
+      handle_interrupt ();
+    }
+
+  errno = old_errno;
+}
+
+/* This routine is called at interrupt level in response to C-g.
+
+   It is called from the SIGINT handler or kbd_buffer_store_event.
+
+   If `waiting_for_input' is non zero, then unless `echoing' is
+   nonzero, immediately throw back to read_char.
+
+   Otherwise it sets the Lisp variable quit-flag not-nil.  This causes
+   eval to throw, when it gets a chance.  If quit-flag is already
+   non-nil, it stops the job right away. */
+
+static void
+handle_interrupt ()
+{
+  char c;
+
   cancel_echoing ();
 
   cancel_echoing ();
 
+  /* XXX This code needs to be revised for multi-tty support. */
   if (!NILP (Vquit_flag)
   if (!NILP (Vquit_flag)
-      && (FRAME_TERMCAP_P (sf) || FRAME_MSDOS_P (sf)))
+#ifndef MSDOS
+      && get_named_tty (NULL)
+#endif
+      )
     {
       /* If SIGINT isn't blocked, don't let us be interrupted by
         another SIGINT, it might be harmful due to non-reentrancy
     {
       /* If SIGINT isn't blocked, don't let us be interrupted by
         another SIGINT, it might be harmful due to non-reentrancy
@@ -10278,7 +10430,7 @@ interrupt_signal (signalnum)    /* If we don't have an argument, */
       sigblock (sigmask (SIGINT));
 
       fflush (stdout);
       sigblock (sigmask (SIGINT));
 
       fflush (stdout);
-      reset_sys_modes ();
+      reset_all_sys_modes ();
 
 #ifdef SIGTSTP                 /* Support possible in later USG versions */
 /*
 
 #ifdef SIGTSTP                 /* Support possible in later USG versions */
 /*
@@ -10357,7 +10509,7 @@ interrupt_signal (signalnum)    /* If we don't have an argument, */
       printf ("Continuing...\n");
 #endif /* not MSDOS */
       fflush (stdout);
       printf ("Continuing...\n");
 #endif /* not MSDOS */
       fflush (stdout);
-      init_sys_modes ();
+      init_all_sys_modes ();
       sigfree ();
     }
   else
       sigfree ();
     }
   else
@@ -10385,9 +10537,7 @@ interrupt_signal (signalnum)    /* If we don't have an argument, */
     }
 
   if (waiting_for_input && !echoing)
     }
 
   if (waiting_for_input && !echoing)
-    quit_throw_to_read_char ();
-
-  errno = old_errno;
+      quit_throw_to_read_char ();
 }
 
 /* Handle a C-g by making read_char return C-g.  */
 }
 
 /* Handle a C-g by making read_char return C-g.  */
@@ -10434,6 +10584,11 @@ See also `current-input-mode'.  */)
      (interrupt, flow, meta, quit)
      Lisp_Object interrupt, flow, meta, quit;
 {
      (interrupt, flow, meta, quit)
      Lisp_Object interrupt, flow, meta, quit;
 {
+  /* XXX This function needs to be revised for multi-device support.
+     Currently it compiles fine, but its semantics are wrong.  It sets
+     global parameters (e.g. interrupt_input) based on only the
+     current frame's device. */
+
   if (!NILP (quit)
       && (!INTEGERP (quit) || XINT (quit) < 0 || XINT (quit) > 0400))
     error ("set-input-mode: QUIT must be an ASCII character");
   if (!NILP (quit)
       && (!INTEGERP (quit) || XINT (quit) < 0 || XINT (quit) > 0400))
     error ("set-input-mode: QUIT must be an ASCII character");
@@ -10443,13 +10598,14 @@ See also `current-input-mode'.  */)
 #endif
 
 #ifndef DOS_NT
 #endif
 
 #ifndef DOS_NT
-  /* this causes startup screen to be restored and messes with the mouse */
-  reset_sys_modes ();
+  if (FRAME_TERMCAP_P (XFRAME (selected_frame)))
+    /* this causes startup screen to be restored and messes with the mouse */
+    reset_sys_modes (CURTTY ());
 #endif
 
 #ifdef SIGIO
 /* Note SIGIO has been undef'd if FIONREAD is missing.  */
 #endif
 
 #ifdef SIGIO
 /* Note SIGIO has been undef'd if FIONREAD is missing.  */
-  if (read_socket_hook)
+  if (FRAME_DEVICE (SELECTED_FRAME ())->read_socket_hook)
     {
       /* When using X, don't give the user a real choice,
         because we haven't implemented the mechanisms to support it.  */
     {
       /* When using X, don't give the user a real choice,
         because we haven't implemented the mechanisms to support it.  */
@@ -10470,19 +10626,25 @@ See also `current-input-mode'.  */)
   interrupt_input = 1;
 #endif
 
   interrupt_input = 1;
 #endif
 
-  flow_control = !NILP (flow);
-  if (NILP (meta))
-    meta_key = 0;
-  else if (EQ (meta, Qt))
-    meta_key = 1;
-  else
-    meta_key = 2;
+  if (FRAME_TERMCAP_P (XFRAME (selected_frame)))
+    {
+      struct tty_display_info *tty = CURTTY ();
+      tty->flow_control = !NILP (flow);
+      if (NILP (meta))
+        tty->meta_key = 0;
+      else if (EQ (meta, Qt))
+        tty->meta_key = 1;
+      else
+        tty->meta_key = 2;
+    }
+
   if (!NILP (quit))
     /* Don't let this value be out of range.  */
   if (!NILP (quit))
     /* Don't let this value be out of range.  */
-    quit_char = XINT (quit) & (meta_key ? 0377 : 0177);
+    quit_char = XINT (quit) & (NILP (meta) ? 0177 : 0377);
 
 #ifndef DOS_NT
 
 #ifndef DOS_NT
-  init_sys_modes ();
+  if (FRAME_TERMCAP_P (XFRAME (selected_frame)))
+    init_sys_modes (CURTTY ());
 #endif
 
 #ifdef POLL_FOR_INPUT
 #endif
 
 #ifdef POLL_FOR_INPUT
@@ -10509,10 +10671,21 @@ The elements of this list correspond to the arguments of
      ()
 {
   Lisp_Object val[4];
      ()
 {
   Lisp_Object val[4];
+  struct frame *sf = XFRAME (selected_frame);
 
   val[0] = interrupt_input ? Qt : Qnil;
 
   val[0] = interrupt_input ? Qt : Qnil;
-  val[1] = flow_control ? Qt : Qnil;
-  val[2] = meta_key == 2 ? make_number (0) : meta_key == 1 ? Qt : Qnil;
+  if (FRAME_TERMCAP_P (sf))
+    {
+      val[1] = FRAME_TTY (sf)->flow_control ? Qt : Qnil;
+      val[2] = (FRAME_TTY (sf)->meta_key == 2
+                ? make_number (0)
+                : (CURTTY ()->meta_key == 1 ? Qt : Qnil));
+    }
+  else
+    {
+      val[1] = Qnil;
+      val[2] = Qt;
+    }
   XSETFASTINT (val[3], quit_char);
 
   return Flist (sizeof (val) / sizeof (val[0]), val);
   XSETFASTINT (val[3], quit_char);
 
   return Flist (sizeof (val) / sizeof (val[0]), val);
@@ -10521,7 +10694,7 @@ The elements of this list correspond to the arguments of
 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.
 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.
+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.
 
 If optional fourth arg WHOLE is non-nil, X is relative to the left
 edge of the window.
 
@@ -10532,6 +10705,9 @@ The `posn-' functions access elements of such lists.  */)
   (x, y, frame_or_window, whole)
      Lisp_Object x, y, frame_or_window, whole;
 {
   (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 (NILP (frame_or_window))
     frame_or_window = selected_window;
 
@@ -10603,6 +10779,10 @@ init_kboard (kb)
   kb->reference_count = 0;
   kb->Vsystem_key_alist = Qnil;
   kb->system_key_syms = Qnil;
   kb->reference_count = 0;
   kb->Vsystem_key_alist = Qnil;
   kb->system_key_syms = Qnil;
+  kb->Vlocal_function_key_map = Fmake_sparse_keymap (Qnil);
+  Fset_keymap_parent (kb->Vlocal_function_key_map, Vfunction_key_map);
+  kb->Vlocal_key_translation_map = Fmake_sparse_keymap (Qnil);
+  Fset_keymap_parent (kb->Vlocal_key_translation_map, Vkey_translation_map);
   kb->Vdefault_minibuffer_frame = Qnil;
 }
 
   kb->Vdefault_minibuffer_frame = Qnil;
 }
 
@@ -10639,7 +10819,7 @@ delete_kboard (kb)
       && FRAMEP (selected_frame)
       && FRAME_LIVE_P (XFRAME (selected_frame)))
     {
       && FRAMEP (selected_frame)
       && FRAME_LIVE_P (XFRAME (selected_frame)))
     {
-      current_kboard = XFRAME (selected_frame)->kboard;
+      current_kboard = XFRAME (selected_frame)->device->kboard;
       if (current_kboard == kb)
        abort ();
     }
       if (current_kboard == kb)
        abort ();
     }
@@ -10680,8 +10860,14 @@ init_keyboard ()
   wipe_kboard (current_kboard);
   init_kboard (current_kboard);
 
   wipe_kboard (current_kboard);
   init_kboard (current_kboard);
 
-  if (!noninteractive && !read_socket_hook && NILP (Vwindow_system))
+  if (!noninteractive)
     {
     {
+      /* Before multi-tty support, these handlers used to be installed
+         only if the current session was a tty session.  Now an Emacs
+         session may have multiple display types, so we always handle
+         SIGINT.  There is special code in interrupt_signal to exit
+         Emacs on SIGINT when there are no termcap frames on the
+         controlling terminal. */
       signal (SIGINT, interrupt_signal);
 #if defined (HAVE_TERMIO) || defined (HAVE_TERMIOS)
       /* For systems with SysV TERMIO, C-g is set up for both SIGINT and
       signal (SIGINT, interrupt_signal);
 #if defined (HAVE_TERMIO) || defined (HAVE_TERMIOS)
       /* For systems with SysV TERMIO, C-g is set up for both SIGINT and
@@ -10800,9 +10986,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);
 
@@ -10813,7 +10996,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
@@ -10821,7 +11004,7 @@ 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);
 
   Qusr1_signal = intern ("usr1-signal");
   staticpro (&Qusr1_signal);
 
   Qusr1_signal = intern ("usr1-signal");
   staticpro (&Qusr1_signal);
@@ -10860,6 +11043,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");
@@ -10975,6 +11163,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);
@@ -11059,7 +11250,10 @@ In other words, the present command is the event that made the previous
 command exit.
 
 The value `kill-region' is special; it means that the previous command
 command exit.
 
 The value `kill-region' is special; it means that the previous command
-was a kill command.  */);
+was a kill command.
+
+`last-command' has a separate binding for each display device.
+See Info node `(elisp)Multiple displays'.  */);
 
   DEFVAR_KBOARD ("real-last-command", Vreal_last_command,
                 doc: /* Same as `last-command', but never altered by Lisp code.  */);
 
   DEFVAR_KBOARD ("real-last-command", Vreal_last_command,
                 doc: /* Same as `last-command', but never altered by Lisp code.  */);
@@ -11243,21 +11437,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,
@@ -11277,7 +11462,10 @@ 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'
 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.  */);
+set up a different keymap for reading the next command.
+
+`overriding-terminal-local-map' has a separate binding for each display device.
+See Info node `(elisp)Multiple displays'.  */);
 
   DEFVAR_LISP ("overriding-local-map", &Voverriding_local_map,
               doc: /* Keymap that overrides all other local keymaps.
 
   DEFVAR_LISP ("overriding-local-map", &Voverriding_local_map,
               doc: /* Keymap that overrides all other local keymaps.
@@ -11302,7 +11490,70 @@ and the minor mode maps regardless of `overriding-local-map'.  */);
                 doc: /* Alist of system-specific X windows key symbols.
 Each element should have the form (N . SYMBOL) where N is the
 numeric keysym code (sans the \"system-specific\" bit 1<<28)
                 doc: /* Alist of system-specific X windows key symbols.
 Each element should have the form (N . SYMBOL) where N is the
 numeric keysym code (sans the \"system-specific\" bit 1<<28)
-and SYMBOL is its name.  */);
+and SYMBOL is its name.
+
+`system-key-alist' has a separate binding for each display device.
+See Info node `(elisp)Multiple displays'.
+
+Note that the currently selected frame has very little to do with
+which binding of this variable is active at any given moment.  If you
+need set or get the binding on a specific display, use
+`terminal-local-value' and `set-terminal-local-value'.  */);
+
+  DEFVAR_KBOARD ("local-function-key-map", Vlocal_function_key_map,
+                 doc: /* Keymap mapping ASCII function key sequences onto their preferred forms.
+This allows Emacs to recognize function keys sent from ASCII
+terminals at any point in a key sequence.
+
+The `read-key-sequence' function replaces any subsequence bound by
+`function-key-map' with its binding.  More precisely, when the active
+keymaps have no binding for the current key sequence but
+`function-key-map' binds a suffix of the sequence to a vector or string,
+`read-key-sequence' replaces the matching suffix with its binding, and
+continues with the new sequence.
+
+The events that come from bindings in `function-key-map' are not
+themselves looked up in `function-key-map'.
+
+For example, suppose `function-key-map' binds `ESC O P' to [f1].
+Typing `ESC O P' to `read-key-sequence' would return [f1].  Typing
+`C-x ESC O P' would return [?\\C-x f1].  If [f1] were a prefix
+key, typing `ESC O P x' would return [f1 x].
+
+`function-key-map' has a separate binding for each display device.
+See Info node `(elisp)Multiple displays'.  If you need to define a
+binding on all display devices, change `global-function-key-map'
+instead.
+
+Note that the currently selected frame has very little to do with
+which binding of this variable is active at any given moment.  If you
+need set or get the binding on a specific display, use
+`terminal-local-value' and `set-terminal-local-value'.  */);
+
+  DEFVAR_LISP ("function-key-map", &Vfunction_key_map,
+               doc: /* The parent keymap of all `local-function-key-map' instances.
+Function key definitions that apply to all display devices should go
+here.  */);
+  Vfunction_key_map = Fmake_sparse_keymap (Qnil);
+                    
+  DEFVAR_KBOARD ("local-key-translation-map", Vlocal_key_translation_map,
+              doc: /* Keymap of key translations that can override keymaps.
+This keymap works like `function-key-map', but comes after that,
+and its non-prefix bindings override ordinary bindings.
+
+`key-translation-map' has a separate binding for each display device.
+(See Info node `(elisp)Multiple displays'.)  If you need to set a key
+translation on all devices, change `global-key-translation-map' instead.
+
+Note that the currently selected frame has very little to do with
+which binding of this variable is active at any given moment.  If you
+need set or get the binding on a specific display, use
+`terminal-local-value' and `set-terminal-local-value'.  */);
+
+  DEFVAR_LISP ("key-translation-map", &Vkey_translation_map,
+               doc: /* The parent keymap of all `local-key-translation-map' instances.
+Key translations that apply to all display devices should go here.  */);
+  Vkey_translation_map = Fmake_sparse_keymap (Qnil);
 
   DEFVAR_LISP ("deferred-action-list", &Vdeferred_action_list,
               doc: /* List of deferred actions to be performed at a later time.
 
   DEFVAR_LISP ("deferred-action-list", &Vdeferred_action_list,
               doc: /* List of deferred actions to be performed at a later time.
@@ -11412,10 +11663,29 @@ 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.
@@ -11448,6 +11718,8 @@ mark_kboards ()
       mark_object (kb->Vlast_kbd_macro);
       mark_object (kb->Vsystem_key_alist);
       mark_object (kb->system_key_syms);
       mark_object (kb->Vlast_kbd_macro);
       mark_object (kb->Vsystem_key_alist);
       mark_object (kb->system_key_syms);
+      mark_object (kb->Vlocal_function_key_map);
+      mark_object (kb->Vlocal_key_translation_map);
       mark_object (kb->Vdefault_minibuffer_frame);
       mark_object (kb->echo_string);
     }
       mark_object (kb->Vdefault_minibuffer_frame);
       mark_object (kb->echo_string);
     }