Handle system default font and changing font parameters.
[bpt/emacs.git] / src / keyboard.c
index 6e7bcca..f15b797 100644 (file)
@@ -1,14 +1,14 @@
 /* Keyboard and mouse input; editor command loop.
    Copyright (C) 1985, 1986, 1987, 1988, 1989, 1993, 1994, 1995,
                  1996, 1997, 1999, 2000, 2001, 2002, 2003, 2004,
-                 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+                 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
-GNU Emacs is free software; you can redistribute it and/or modify
+GNU Emacs is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -16,13 +16,12 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 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
-the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA.  */
+along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include <config.h>
 #include <signal.h>
 #include <stdio.h>
+#include <setjmp.h>
 #include "lisp.h"
 #include "termchar.h"
 #include "termopts.h"
@@ -53,9 +52,7 @@ Boston, MA 02110-1301, USA.  */
 #include "msdos.h"
 #include <time.h>
 #else /* not MSDOS */
-#ifndef VMS
 #include <sys/ioctl.h>
-#endif
 #endif /* not MSDOS */
 
 #include "syssignal.h"
@@ -78,8 +75,8 @@ Boston, MA 02110-1301, USA.  */
 #include "w32term.h"
 #endif /* HAVE_NTGUI */
 
-#ifdef MAC_OS
-#include "macterm.h"
+#ifdef HAVE_NS
+#include "nsterm.h"
 #endif
 
 #ifndef USE_CRT_DLL
@@ -95,16 +92,21 @@ volatile int interrupt_input_blocked;
    during the current critical section.  */
 int interrupt_input_pending;
 
+/* This var should be (interrupt_input_pending || pending_atimers).
+   The QUIT macro checks this instead of interrupt_input_pending and
+   pending_atimers separately, to reduce code size.  So, any code that
+   changes interrupt_input_pending or pending_atimers should update
+   this too.  */
+#ifdef SYNC_INPUT
+int pending_signals;
+#endif
+
 #define KBD_BUFFER_SIZE 4096
 
-#ifdef MULTI_KBOARD
 KBOARD *initial_kboard;
 KBOARD *current_kboard;
 KBOARD *all_kboards;
 int single_kboard;
-#else
-KBOARD the_only_kboard;
-#endif
 
 /* Non-nil disable property on a command means
    do not execute it; call disabled-command-function's value instead.  */
@@ -267,15 +269,15 @@ int command_loop_level;
 /* Total number of times command_loop has read a key sequence.  */
 EMACS_INT num_input_keys;
 
-/* Last input character read as a command.  */
-Lisp_Object last_command_char;
+/* Last input event read as a command.  */
+Lisp_Object last_command_event;
 
 /* Last input character read as a command, not counting menus
    reached by the mouse.  */
 Lisp_Object last_nonmenu_event;
 
-/* Last input character read for any purpose.  */
-Lisp_Object last_input_char;
+/* Last input event read for any purpose.  */
+Lisp_Object last_input_event;
 
 /* If not Qnil, a list of objects to be read as subsequent command input.  */
 Lisp_Object Vunread_command_events;
@@ -470,6 +472,8 @@ Lisp_Object Qmake_frame_visible;
 Lisp_Object Qselect_window;
 Lisp_Object Qhelp_echo;
 
+extern Lisp_Object Qremap;
+
 #if defined (HAVE_MOUSE) || defined (HAVE_GPM)
 Lisp_Object Qmouse_fixup_help_message;
 #endif
@@ -477,17 +481,16 @@ Lisp_Object Qmouse_fixup_help_message;
 /* Symbols to denote kinds of events.  */
 Lisp_Object Qfunction_key;
 Lisp_Object Qmouse_click;
-#if defined (WINDOWSNT) || defined (MAC_OS)
+#if defined (WINDOWSNT)
 Lisp_Object Qlanguage_change;
 #endif
 Lisp_Object Qdrag_n_drop;
 Lisp_Object Qsave_session;
-#ifdef MAC_OS
-Lisp_Object Qmac_apple_event;
-#endif
 #ifdef HAVE_DBUS
 Lisp_Object Qdbus_event;
 #endif
+Lisp_Object Qconfig_changed_event;
+
 /* Lisp_Object Qmouse_movement; - also an event header */
 
 /* Properties of event headers.  */
@@ -495,11 +498,9 @@ Lisp_Object Qevent_kind;
 Lisp_Object Qevent_symbol_elements;
 
 /* menu item parts */
-Lisp_Object Qmenu_alias;
 Lisp_Object Qmenu_enable;
 Lisp_Object QCenable, QCvisible, QChelp, QCfilter, QCkeys, QCkey_sequence;
 Lisp_Object QCbutton, QCtoggle, QCradio;
-extern Lisp_Object Vdefine_key_rebound_commands;
 extern Lisp_Object Qmenu_item;
 
 /* An event header symbol HEAD may have a property named
@@ -635,16 +636,12 @@ static Lisp_Object modify_event_symbol P_ ((int, unsigned, Lisp_Object,
                                            Lisp_Object, char **,
                                            Lisp_Object *, unsigned));
 static Lisp_Object make_lispy_switch_frame P_ ((Lisp_Object));
-static int parse_solitary_modifier P_ ((Lisp_Object));
-static int parse_solitary_modifier ();
 static void save_getcjmp P_ ((jmp_buf));
 static void save_getcjmp ();
 static void restore_getcjmp P_ ((jmp_buf));
 static Lisp_Object apply_modifiers P_ ((int, Lisp_Object));
 static void clear_event P_ ((struct input_event *));
-#ifdef MULTI_KBOARD
 static Lisp_Object restore_kboard_configuration P_ ((Lisp_Object));
-#endif
 static SIGTYPE interrupt_signal P_ ((int signalnum));
 static void handle_interrupt P_ ((void));
 static void timer_start_idle P_ ((void));
@@ -1038,7 +1035,6 @@ recursive_edit_unwind (buffer)
 static void
 any_kboard_state ()
 {
-#ifdef MULTI_KBOARD
 #if 0 /* Theory: if there's anything in Vunread_command_events,
         it will right away be read by read_key_sequence,
         and then if we do switch KBOARDS, it will go into the side
@@ -1052,7 +1048,6 @@ any_kboard_state ()
   Vunread_command_events = Qnil;
 #endif
   single_kboard = 0;
-#endif
 }
 
 /* Switch to the single-kboard state, making current_kboard
@@ -1061,9 +1056,7 @@ any_kboard_state ()
 void
 single_kboard_state ()
 {
-#ifdef MULTI_KBOARD
   single_kboard = 1;
-#endif
 }
 #endif
 
@@ -1074,10 +1067,8 @@ void
 not_single_kboard_state (kboard)
      KBOARD *kboard;
 {
-#ifdef MULTI_KBOARD
   if (kboard == current_kboard)
     single_kboard = 0;
-#endif
 }
 
 /* Maintain a stack of kboards, so other parts of Emacs
@@ -1096,7 +1087,6 @@ void
 push_kboard (k)
      struct kboard *k;
 {
-#ifdef MULTI_KBOARD
   struct kboard_stack *p
     = (struct kboard_stack *) xmalloc (sizeof (struct kboard_stack));
 
@@ -1105,13 +1095,11 @@ push_kboard (k)
   kboard_stack = p;
 
   current_kboard = k;
-#endif
 }
 
 void
 pop_kboard ()
 {
-#ifdef MULTI_KBOARD
   struct terminal *t;
   struct kboard_stack *p = kboard_stack;
   int found = 0;
@@ -1132,7 +1120,6 @@ pop_kboard ()
     }
   kboard_stack = p->next;
   xfree (p);
-#endif
 }
 
 /* Switch to single_kboard mode, making current_kboard the only KBOARD
@@ -1149,7 +1136,6 @@ void
 temporarily_switch_to_single_kboard (f)
      struct frame *f;
 {
-#ifdef MULTI_KBOARD
   int was_locked = single_kboard;
   if (was_locked)
     {
@@ -1174,7 +1160,6 @@ temporarily_switch_to_single_kboard (f)
   single_kboard = 1;
   record_unwind_protect (restore_kboard_configuration,
                          (was_locked ? Qt : Qnil));
-#endif
 }
 
 #if 0 /* This function is not needed anymore.  */
@@ -1188,7 +1173,6 @@ record_single_kboard_state ()
 }
 #endif
 
-#ifdef MULTI_KBOARD
 static Lisp_Object
 restore_kboard_configuration (was_locked)
      Lisp_Object was_locked;
@@ -1206,7 +1190,6 @@ restore_kboard_configuration (was_locked)
     }
   return Qnil;
 }
-#endif
 
 \f
 /* Handle errors that are not handled at inner levels
@@ -1256,10 +1239,8 @@ cmd_error (data)
 
   Vinhibit_quit = Qnil;
 #if 0 /* This shouldn't be necessary anymore. --lorentey */
-#ifdef MULTI_KBOARD
   if (command_loop_level == 0 && minibuf_level == 0)
     any_kboard_state ();
-#endif
 #endif
 
   return make_number (0);
@@ -1296,7 +1277,17 @@ cmd_error_internal (data, context)
   /* If the window system or terminal frame hasn't been initialized
      yet, or we're not interactive, write the message to stderr and exit.  */
   else if (!sf->glyphs_initialized_p
-          || FRAME_INITIAL_P (sf)
+          /* The initial frame is a special non-displaying frame. It
+             will be current in daemon mode when there are no frames
+             to display, and in non-daemon mode before the real frame
+             has finished initializing.  If an error is thrown in the
+             latter case while creating the frame, then the frame
+             will never be displayed, so the safest thing to do is
+             write to stderr and quit.  In daemon mode, there are
+             many other potential errors that do not prevent frames
+             from being created, so continuing as normal is better in
+             that case.  */
+          || (!IS_DAEMON && FRAME_INITIAL_P (sf))
           || noninteractive)
     {
       print_error_message (data, Qexternal_debugging_output,
@@ -1392,7 +1383,8 @@ top_level_1 ()
 }
 
 DEFUN ("top-level", Ftop_level, Stop_level, 0, 0, "",
-       doc: /* Exit all recursive editing levels.  */)
+       doc: /* Exit all recursive editing levels.
+This also exits all active minibuffers.  */)
      ()
 {
 #ifdef HAVE_WINDOW_SYSTEM
@@ -1528,20 +1520,19 @@ cancel_hourglass_unwind (arg)
 }
 #endif
 
+extern int nonundocount;       /* Declared in cmds.c.  */
+
 Lisp_Object
 command_loop_1 ()
 {
   Lisp_Object cmd;
   int lose;
-  int nonundocount;
   Lisp_Object keybuf[30];
   int i;
   int prev_modiff = 0;
   struct buffer *prev_buffer = NULL;
 #if 0 /* This shouldn't be necessary anymore.  --lorentey  */
-#ifdef MULTI_KBOARD
   int was_locked = single_kboard;
-#endif
 #endif
   int already_adjusted = 0;
 
@@ -1551,7 +1542,6 @@ command_loop_1 ()
   waiting_for_input = 0;
   cancel_echoing ();
 
-  nonundocount = 0;
   this_command_key_count = 0;
   this_command_key_count_reset = 0;
   this_single_command_key_start = 0;
@@ -1577,7 +1567,7 @@ command_loop_1 ()
   /* Do this after running Vpost_command_hook, for consistency.  */
   current_kboard->Vlast_command = Vthis_command;
   current_kboard->Vreal_last_command = real_this_command;
-  if (!CONSP (last_command_char))
+  if (!CONSP (last_command_event))
     current_kboard->Vlast_repeatable_command = real_this_command;
 
   while (1)
@@ -1633,7 +1623,7 @@ command_loop_1 ()
         Is this a good idea?  */
       if (FRAMEP (internal_last_event_frame)
          && !EQ (internal_last_event_frame, selected_frame))
-       Fselect_frame (internal_last_event_frame);
+       Fselect_frame (internal_last_event_frame, Qnil);
 #endif
       /* If it has changed current-menubar from previous value,
         really recompute the menubar from the value.  */
@@ -1677,7 +1667,7 @@ command_loop_1 ()
          goto finalize;
        }
 
-      last_command_char = keybuf[i - 1];
+      last_command_event = keybuf[i - 1];
 
       /* If the previous command tried to force a specific window-start,
         forget about that, in case this command moves point far away
@@ -1842,12 +1832,12 @@ command_loop_1 ()
                }
              else if (EQ (Vthis_command, Qself_insert_command)
                       /* Try this optimization only on char keystrokes.  */
-                      && NATNUMP (last_command_char)
-                      && CHAR_VALID_P (XFASTINT (last_command_char), 0))
+                      && NATNUMP (last_command_event)
+                      && CHAR_VALID_P (XFASTINT (last_command_event), 0))
                {
                  unsigned int c
                    = translate_char (Vtranslation_table_for_input,
-                                     XFASTINT (last_command_char));
+                                     XFASTINT (last_command_event));
                  int value;
                  if (NILP (Vexecuting_kbd_macro)
                      && !EQ (minibuf_window, selected_window))
@@ -1878,6 +1868,8 @@ command_loop_1 ()
                  if (value == 2)
                    nonundocount = 0;
 
+                  frame_make_pointer_invisible ();
+
                  if (! NILP (Vpost_command_hook))
                    /* Put this before calling adjust_point_for_property
                       so it will only get called once in any case.  */
@@ -1907,7 +1899,7 @@ command_loop_1 ()
 #endif
 
             nonundocount = 0;
-            if (NILP (current_kboard->Vprefix_arg))
+            if (NILP (current_kboard->Vprefix_arg)) /* FIXME: Why?  --Stef  */
               Fundo_boundary ();
             Fcommand_execute (Vthis_command, Qnil, Qnil, Qnil);
 
@@ -1951,11 +1943,11 @@ command_loop_1 ()
         If the command didn't actually create a prefix arg,
         but is merely a frame event that is transparent to prefix args,
         then the above doesn't apply.  */
-      if (NILP (current_kboard->Vprefix_arg) || CONSP (last_command_char))
+      if (NILP (current_kboard->Vprefix_arg) || CONSP (last_command_event))
        {
          current_kboard->Vlast_command = Vthis_command;
          current_kboard->Vreal_last_command = real_this_command;
-         if (!CONSP (last_command_char))
+         if (!CONSP (last_command_event))
            current_kboard->Vlast_repeatable_command = real_this_command;
          cancel_echoing ();
          this_command_key_count = 0;
@@ -1994,10 +1986,8 @@ command_loop_1 ()
          && NILP (current_kboard->Vprefix_arg))
        finalize_kbd_macro_chars ();
 #if 0 /* This shouldn't be necessary anymore.  --lorentey  */
-#ifdef MULTI_KBOARD
       if (!was_locked)
         any_kboard_state ();
-#endif
 #endif
     }
 }
@@ -2029,13 +2019,9 @@ adjust_point_for_property (last_pt, modified)
       /* FIXME: check `intangible'.  */
       if (check_composition
          && PT > BEGV && PT < ZV
-         && get_property_and_range (PT, Qcomposition, &val, &beg, &end, Qnil)
-         && COMPOSITION_VALID_P (beg, end, val)
-         && beg < PT /* && end > PT   <- It's always the case.  */
-         && (last_pt <= beg || last_pt >= end))
+         && (beg = composition_adjust_point (last_pt)) != PT)
        {
-         xassert (end > PT);
-         SET_PT (PT < last_pt ? beg : end);
+         SET_PT (beg);
          check_display = check_invisible = 1;
        }
       check_composition = 0;
@@ -2065,6 +2051,20 @@ adjust_point_for_property (last_pt, modified)
 
          /* Find boundaries `beg' and `end' of the invisible area, if any.  */
          while (end < ZV
+#if 0
+                /* FIXME: We should stop if we find a spot between
+                   two runs of `invisible' where inserted text would
+                   be visible.  This is important when we have two
+                   invisible boundaries that enclose an area: if the
+                   area is empty, we need this test in order to make
+                   it possible to place point in the middle rather
+                   than skip both boundaries.  However, this code
+                   also stops anywhere in a non-sticky text-property,
+                   which breaks (e.g.) Org mode.  */
+                && (val = get_pos_property (make_number (end),
+                                            Qinvisible, Qnil),
+                    TEXT_PROP_MEANS_INVISIBLE (val))
+#endif
                 && !NILP (val = get_char_property_and_overlay
                           (make_number (end), Qinvisible, Qnil, &overlay))
                 && (inv = TEXT_PROP_MEANS_INVISIBLE (val)))
@@ -2078,6 +2078,11 @@ adjust_point_for_property (last_pt, modified)
              end = NATNUMP (tmp) ? XFASTINT (tmp) : ZV;
            }
          while (beg > BEGV
+#if 0
+                && (val = get_pos_property (make_number (beg),
+                                            Qinvisible, Qnil),
+                    TEXT_PROP_MEANS_INVISIBLE (val))
+#endif
                 && !NILP (val = get_char_property_and_overlay
                           (make_number (beg - 1), Qinvisible, Qnil, &overlay))
                 && (inv = TEXT_PROP_MEANS_INVISIBLE (val)))
@@ -2201,16 +2206,24 @@ struct atimer *poll_timer;
 
 #ifdef POLL_FOR_INPUT
 
-/* Poll for input, so what we catch a C-g if it comes in.  This
+/* Poll for input, so that we catch a C-g if it comes in.  This
    function is called from x_make_frame_visible, see comment
    there.  */
 
 void
 poll_for_input_1 ()
 {
+/* Tell ns_read_socket() it is being called asynchronously so it can avoid
+   doing anything dangerous. */
+#ifdef HAVE_NS
+  ++handling_signal;
+#endif
   if (interrupt_input_blocked == 0
       && !waiting_for_input)
     read_avail_input (0);
+#ifdef HAVE_NS
+  --handling_signal;
+#endif
 }
 
 /* Timer callback function for poll_timer.  TIMER is equal to
@@ -2221,11 +2234,14 @@ poll_for_input (timer)
      struct atimer *timer;
 {
   if (poll_suppress_count == 0)
+    {
 #ifdef SYNC_INPUT
-    interrupt_input_pending = 1;
+      interrupt_input_pending = 1;
+      pending_signals = 1;
 #else
-    poll_for_input_1 ();
+      poll_for_input_1 ();
 #endif
+    }
 }
 
 #endif /* POLL_FOR_INPUT */
@@ -2467,7 +2483,7 @@ static void record_char ();
 
 static Lisp_Object help_form_saved_window_configs;
 static Lisp_Object
-read_char_help_form_unwind (arg)
+read_char_help_form_unwind (Lisp_Object arg)
 {
   Lisp_Object window_config = XCAR (help_form_saved_window_configs);
   help_form_saved_window_configs = XCDR (help_form_saved_window_configs);
@@ -2575,6 +2591,8 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu, end_time)
 
   if (CONSP (Vunread_command_events))
     {
+      int was_disabled = 0;
+
       c = XCAR (Vunread_command_events);
       Vunread_command_events = XCDR (Vunread_command_events);
 
@@ -2595,12 +2613,17 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu, end_time)
       if (CONSP (c)
          && EQ (XCDR (c), Qdisabled)
          && (SYMBOLP (XCAR (c)) || INTEGERP (XCAR (c))))
-       c = XCAR (c);
+       {
+         was_disabled = 1;
+         c = XCAR (c);
+       }
 
       /* If the queued event is something that used the mouse,
          set used_mouse_menu accordingly.  */
       if (used_mouse_menu
-         && (EQ (c, Qtool_bar) || EQ (c, Qmenu_bar)))
+         /* Also check was_disabled so last-nonmenu-event won't return
+            a bad value when submenus are involved.  (Bug#447)  */
+         && (EQ (c, Qtool_bar) || EQ (c, Qmenu_bar) || was_disabled))
        *used_mouse_menu = 1;
 
       goto reread_for_input_method;
@@ -2787,7 +2810,6 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu, end_time)
       if (!NILP (Vinhibit_quit))
        Vquit_flag = Qnil;
 
-#ifdef MULTI_KBOARD
       {
        KBOARD *kb = FRAME_KBOARD (XFRAME (selected_frame));
        if (kb != current_kboard)
@@ -2815,7 +2837,6 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu, end_time)
             return make_number (-2); /* wrong_kboard_jmpbuf */
          }
       }
-#endif
       goto non_reread;
     }
 
@@ -2991,7 +3012,6 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu, end_time)
        }
     }
 
-#ifdef MULTI_KBOARD
   /* If current_kboard's side queue is empty check the other kboards.
      If one of them has data that we have not yet seen here,
      switch to it and process the data waiting for it.
@@ -3013,7 +3033,6 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu, end_time)
             return make_number (-2); /* wrong_kboard_jmpbuf */
          }
     }
-#endif
 
  wrong_kboard:
 
@@ -3043,7 +3062,6 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu, end_time)
       c = kbd_buffer_get_event (&kb, used_mouse_menu, end_time);
       restore_getcjmp (save_jump);
 
-#ifdef MULTI_KBOARD
       if (! NILP (c) && (kb != current_kboard))
        {
          Lisp_Object link = kb->kbd_queue;
@@ -3068,7 +3086,6 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu, end_time)
          UNGCPRO;
           return make_number (-2);
        }
-#endif
     }
 
   /* Terminate Emacs in batch mode if at eof.  */
@@ -3127,8 +3144,8 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu, end_time)
       record_single_kboard_state ();
 #endif
 
-      last_input_char = c;
-      Fcommand_execute (tem, Qnil, Fvector (1, &last_input_char), Qt);
+      last_input_event = c;
+      Fcommand_execute (tem, Qnil, Fvector (1, &last_input_event), Qt);
 
       if (CONSP (c) && EQ (XCAR (c), Qselect_window) && !end_time)
        /* We stopped being idle for this event; undo that.  This
@@ -3369,7 +3386,7 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu, end_time)
        add_command_key (also_record);
     }
 
-  last_input_char = c;
+  last_input_event = c;
   num_input_events++;
 
   /* Process the help character specially if enabled */
@@ -3446,7 +3463,7 @@ record_menu_key (c)
   add_command_key (c);
 
   /* Re-reading in the middle of a command */
-  last_input_char = c;
+  last_input_event = c;
   num_input_events++;
 }
 
@@ -3644,6 +3661,12 @@ static int
 readable_events (flags)
      int flags;
 {
+#ifdef HAVE_DBUS
+  /* Check whether a D-Bus message has arrived.  */
+  if (xd_pending_messages () > 0)
+    return 1;
+#endif /* HAVE_DBUS */
+
   if (flags & READABLE_EVENTS_DO_TIMERS_NOW)
     timer_check (1);
 
@@ -3711,7 +3734,6 @@ readable_events (flags)
 /* Set this for debugging, to have a way to get out */
 int stop_character;
 
-#ifdef MULTI_KBOARD
 static KBOARD *
 event_to_kboard (event)
      struct input_event *event;
@@ -3731,7 +3753,6 @@ event_to_kboard (event)
   else
     return FRAME_KBOARD (XFRAME (frame));
 }
-#endif
 
 
 Lisp_Object Vthrow_on_input;
@@ -3781,7 +3802,6 @@ kbd_buffer_store_event_hold (event, hold_quit)
 
       if (c == quit_char)
        {
-#ifdef MULTI_KBOARD
          KBOARD *kb = FRAME_KBOARD (XFRAME (event->frame_or_window));
          struct input_event *sp;
 
@@ -3805,7 +3825,6 @@ kbd_buffer_store_event_hold (event, hold_quit)
                }
              return;
            }
-#endif
 
          if (hold_quit)
            {
@@ -4026,7 +4045,10 @@ kbd_buffer_get_event (kbp, used_mouse_menu, end_time)
   register int c;
   Lisp_Object obj;
 
-  if (noninteractive)
+  if (noninteractive
+      /* In case we are running as a daemon, only do this before
+        detaching from the terminal.  */
+      || (IS_DAEMON && daemon_pipe[1] >= 0))
     {
       c = getchar ();
       XSETINT (obj, c);
@@ -4058,9 +4080,6 @@ kbd_buffer_get_event (kbp, used_mouse_menu, end_time)
       /* One way or another, wait until input is available; then, if
         interrupt handlers have not read it, read it now.  */
 
-#ifdef OLDVMS
-      wait_for_kbd_input ();
-#else
 /* Note SIGIO has been undef'd if FIONREAD is missing.  */
 #ifdef SIGIO
       gobble_input (0);
@@ -4091,7 +4110,6 @@ kbd_buffer_get_event (kbp, used_mouse_menu, end_time)
       if (!interrupt_input && kbd_fetch_ptr == kbd_store_ptr)
        /* Pass 1 for EXPECT since we just waited to have input.  */
        read_avail_input (1);
-#endif /* not VMS */
     }
 
   if (CONSP (Vunread_command_events))
@@ -4116,13 +4134,9 @@ kbd_buffer_get_event (kbp, used_mouse_menu, end_time)
 
       last_event_timestamp = event->timestamp;
 
-#ifdef MULTI_KBOARD
       *kbp = event_to_kboard (event);
       if (*kbp == 0)
        *kbp = current_kboard;  /* Better than returning null ptr?  */
-#else
-      *kbp = &the_only_kboard;
-#endif
 
       obj = Qnil;
 
@@ -4149,7 +4163,21 @@ kbd_buffer_get_event (kbp, used_mouse_menu, end_time)
 #endif
        }
 
-#if defined (HAVE_X11) || defined (HAVE_NTGUI) || defined (MAC_OS)
+#if defined (HAVE_NS)
+      else if (event->kind == NS_TEXT_EVENT)
+        {
+          if (event->code == KEY_NS_PUT_WORKING_TEXT)
+            obj = Fcons (intern ("ns-put-working-text"), Qnil);
+          else
+            obj = Fcons (intern ("ns-unput-working-text"), Qnil);
+         kbd_fetch_ptr = event + 1;
+          if (used_mouse_menu)
+            *used_mouse_menu = 1;
+        }
+#endif
+
+#if defined (HAVE_X11) || defined (HAVE_NTGUI) \
+    || defined (HAVE_NS)
       else if (event->kind == DELETE_WINDOW_EVENT)
        {
          /* Make an event (delete-frame (FRAME)).  */
@@ -4158,7 +4186,8 @@ kbd_buffer_get_event (kbp, used_mouse_menu, end_time)
          kbd_fetch_ptr = event + 1;
        }
 #endif
-#if defined (HAVE_X11) || defined (HAVE_NTGUI) || defined (MAC_OS)
+#if defined (HAVE_X11) || defined (HAVE_NTGUI) \
+    || defined (HAVE_NS)
       else if (event->kind == ICONIFY_EVENT)
        {
          /* Make an event (iconify-frame (FRAME)).  */
@@ -4180,8 +4209,8 @@ kbd_buffer_get_event (kbp, used_mouse_menu, end_time)
          XSETBUFFER (obj, current_buffer);
          kbd_fetch_ptr = event + 1;
        }
-#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \
-    || defined (USE_GTK)
+#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) \
+    || defined(HAVE_NS) || defined (USE_GTK)
       else if (event->kind == MENU_BAR_ACTIVATE_EVENT)
        {
          kbd_fetch_ptr = event + 1;
@@ -4190,16 +4219,11 @@ kbd_buffer_get_event (kbp, used_mouse_menu, end_time)
            x_activate_menubar (XFRAME (event->frame_or_window));
        }
 #endif
-#if defined (WINDOWSNT) || defined (MAC_OS)
+#if defined (WINDOWSNT)
       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);
-#endif
          obj = Fcons (Qlanguage_change, Fcons (obj, Qnil));
          kbd_fetch_ptr = event + 1;
        }
@@ -4261,6 +4285,11 @@ kbd_buffer_get_event (kbp, used_mouse_menu, end_time)
          kbd_fetch_ptr = event + 1;
        }
 #endif
+      else if (event->kind == CONFIG_CHANGED_EVENT)
+       {
+         obj = make_lispy_event (event);
+         kbd_fetch_ptr = event + 1;
+       }
       else
        {
          /* If this event is on a different frame, return a switch-frame this
@@ -4290,8 +4319,8 @@ kbd_buffer_get_event (kbp, used_mouse_menu, end_time)
            {
              obj = make_lispy_event (event);
 
-#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined(MAC_OS) \
-    || defined (USE_GTK)
+#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) \
+    || defined(HAVE_NS) || defined (USE_GTK)
              /* If this was a menu selection, then set the flag to inhibit
                 writing to last_nonmenu_event.  Don't do this if the event
                 we're returning is (menu-bar), though; that indicates the
@@ -4303,6 +4332,12 @@ kbd_buffer_get_event (kbp, used_mouse_menu, end_time)
                      || event->kind == TOOL_BAR_EVENT))
                *used_mouse_menu = 1;
 #endif
+#ifdef HAVE_NS
+             /* certain system events are non-key events */
+             if (used_mouse_menu
+                  && event->kind == NS_NONKEY_EVENT)
+               *used_mouse_menu = 1;
+#endif
 
              /* Wipe out this event, to catch bugs.  */
              clear_event (event);
@@ -4472,7 +4507,7 @@ struct input_event last_timer_event;
 
 /* List of elisp functions to call, delayed because they were generated in
    a context where Elisp could not be safely run (e.g. redisplay, signal,
-   ...).  Each lement has the form (FUN . ARGS).  */
+   ...).  Each element has the form (FUN . ARGS).  */
 Lisp_Object pending_funcalls;
 
 extern Lisp_Object Qapply;
@@ -4481,19 +4516,16 @@ extern Lisp_Object Qapply;
    disregard elements that are not proper timers.  Do not make a circular
    timer list for the time being.
 
-   Returns the number of seconds to wait until the next timer fires.  If a
-   timer is triggering now, return zero seconds.
-   If no timer is active, return -1 seconds.
+   Returns the time to wait until the next timer fires.  If a
+   timer is triggering now, return zero.
+   If no timer is active, return -1.
 
    If a timer is ripe, we run it, with quitting turned off.
+   In that case we return 0 to indicate that a new timer_check_2 call
+   should be done.  */
 
-   DO_IT_NOW is now ignored.  It used to mean that we should
-   run the timer directly instead of queueing a timer-event.
-   Now we always run timers directly.  */
-
-EMACS_TIME
-timer_check (do_it_now)
-     int do_it_now;
+static EMACS_TIME
+timer_check_2 ()
 {
   EMACS_TIME nexttime;
   EMACS_TIME now, idleness_now;
@@ -4644,11 +4676,6 @@ timer_check (do_it_now)
              int count = SPECPDL_INDEX ();
              Lisp_Object old_deactivate_mark = Vdeactivate_mark;
 
-#if 0 /* This shouldn't be necessary anymore.  --lorentey  */
-             /* On unbind_to, resume allowing input from any kboard, if that
-                 was true before.  */
-              record_single_kboard_state ();
-#endif
              /* Mark the timer as triggered to prevent problems if the lisp
                 code fails to reschedule it right.  */
              vector[0] = Qt;
@@ -4662,7 +4689,12 @@ timer_check (do_it_now)
 
              /* Since we have handled the event,
                 we don't need to tell the caller to wake up and do it.  */
+              /* But the caller must still wait for the next timer, so
+                 return 0 to indicate that.  */
            }
+
+          EMACS_SET_SECS (nexttime, 0);
+          EMACS_SET_USECS (nexttime, 0);
        }
       else
        /* When we encounter a timer that is still waiting,
@@ -4679,12 +4711,40 @@ timer_check (do_it_now)
   return nexttime;
 }
 
+
+/* Check whether a timer has fired.  To prevent larger problems we simply
+   disregard elements that are not proper timers.  Do not make a circular
+   timer list for the time being.
+
+   Returns the time to wait until the next timer fires.
+   If no timer is active, return -1.
+
+   As long as any timer is ripe, we run it.
+
+   DO_IT_NOW is now ignored.  It used to mean that we should
+   run the timer directly instead of queueing a timer-event.
+   Now we always run timers directly.  */
+
+EMACS_TIME
+timer_check (do_it_now)
+     int do_it_now;
+{
+  EMACS_TIME nexttime;
+
+  do 
+    {
+      nexttime = timer_check_2 ();
+    }
+  while (EMACS_SECS (nexttime) == 0 && EMACS_USECS (nexttime) == 0);
+
+  return nexttime;
+}
+
 DEFUN ("current-idle-time", Fcurrent_idle_time, Scurrent_idle_time, 0, 0, 0,
        doc: /* Return the current length of Emacs idleness, or nil.
-The value when Emacs is idle is a list of three integers.  The first has the
-most significant 16 bits of the seconds, while the second has the
-least significant 16 bits.  The third integer gives the microsecond
-count.
+The value when Emacs is idle is a list of three integers.  The first has
+the most significant 16 bits of the seconds, while the second has the least
+significant 16 bits.  The third integer gives the microsecond count.
 
 The value when Emacs is not idle is nil.
 
@@ -4717,7 +4777,7 @@ static Lisp_Object drag_n_drop_syms;
 /* This is a list of keysym codes for special "accent" characters.
    It parallels lispy_accent_keys.  */
 
-static int lispy_accent_codes[] =
+static const int lispy_accent_codes[] =
 {
 #ifdef XK_dead_circumflex
   XK_dead_circumflex,
@@ -5368,7 +5428,8 @@ make_lispy_position (f, x, y, time)
                                     &object, &dx, &dy, &width, &height);
          if (STRINGP (string))
            string_info = Fcons (string, make_number (charpos));
-         if (w == XWINDOW (selected_window))
+         if (w == XWINDOW (selected_window)
+             && current_buffer == XBUFFER (w->buffer))
            textpos = PT;
          else
            textpos = XMARKER (w->pointm)->charpos;
@@ -5547,6 +5608,12 @@ make_lispy_event (event)
        return lispy_c;
       }
 
+#ifdef HAVE_NS
+      /* NS_NONKEY_EVENTs are just like NON_ASCII_KEYSTROKE_EVENTs,
+        except that they are non-key events (last-nonmenu-event is nil). */
+    case NS_NONKEY_EVENT:
+#endif
+
       /* A function key.  The symbol may need to have modifier prefixes
         tacked onto it.  */
     case NON_ASCII_KEYSTROKE_EVENT:
@@ -5645,7 +5712,7 @@ make_lispy_event (event)
        if (event->kind == MOUSE_CLICK_EVENT)
          {
            struct frame *f = XFRAME (event->frame_or_window);
-#if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
+#if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK) && ! defined (HAVE_NS)
            int row, column;
 #endif
 
@@ -5654,7 +5721,7 @@ make_lispy_event (event)
            if (! FRAME_LIVE_P (f))
              return Qnil;
 
-#if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
+#if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK) && ! defined (HAVE_NS)
            /* EVENT->x and EVENT->y are frame-relative pixel
               coordinates at this place.  Under old redisplay, COLUMN
               and ROW are set to frame relative glyph coordinates
@@ -5714,7 +5781,7 @@ make_lispy_event (event)
 
                return Fcons (item, Fcons (position, Qnil));
              }
-#endif /* not USE_X_TOOLKIT && not USE_GTK */
+#endif /* not USE_X_TOOLKIT && not USE_GTK && not HAVE_NS */
 
            position = make_lispy_position (f, &event->x, &event->y,
                                            event->timestamp);
@@ -5925,6 +5992,7 @@ make_lispy_event (event)
             as a multiple of 1/8 characters.  */
          struct frame *f;
          int fuzz;
+         int symbol_num;
          int is_double;
 
          if (WINDOWP (event->frame_or_window))
@@ -5939,7 +6007,27 @@ make_lispy_event (event)
          else
            fuzz = double_click_fuzz / 8;
 
-         is_double = (last_mouse_button < 0
+         if (event->modifiers & up_modifier)
+           {
+             /* Emit a wheel-up event.  */
+             event->modifiers &= ~up_modifier;
+             symbol_num = 0;
+           }
+         else if (event->modifiers & down_modifier)
+           {
+             /* Emit a wheel-down event.  */
+             event->modifiers &= ~down_modifier;
+             symbol_num = 1;
+           }
+         else
+           /* Every wheel event should either have the down_modifier or
+              the up_modifier set.  */
+           abort ();
+
+          if (event->kind == HORIZ_WHEEL_EVENT)
+            symbol_num += 2;
+
+         is_double = (last_mouse_button == - (1 + symbol_num)
                       && (eabs (XINT (event->x) - last_mouse_x) <= fuzz)
                       && (eabs (XINT (event->y) - last_mouse_y) <= fuzz)
                       && button_down_time != 0
@@ -5962,33 +6050,9 @@ make_lispy_event (event)
 
          button_down_time = event->timestamp;
          /* Use a negative value to distinguish wheel from mouse button.  */
-         last_mouse_button = -1;
+         last_mouse_button = - (1 + symbol_num);
          last_mouse_x = XINT (event->x);
          last_mouse_y = XINT (event->y);
-       }
-
-       {
-         int symbol_num;
-
-         if (event->modifiers & up_modifier)
-           {
-             /* Emit a wheel-up event.  */
-             event->modifiers &= ~up_modifier;
-             symbol_num = 0;
-           }
-         else if (event->modifiers & down_modifier)
-           {
-             /* Emit a wheel-down event.  */
-             event->modifiers &= ~down_modifier;
-             symbol_num = 1;
-           }
-         else
-           /* Every wheel event should either have the down_modifier or
-              the up_modifier set.  */
-           abort ();
-
-          if (event->kind == HORIZ_WHEEL_EVENT)
-            symbol_num += 2;
 
          /* Get the symbol we should use for the wheel event.  */
          head = modify_event_symbol (symbol_num,
@@ -6093,8 +6157,8 @@ make_lispy_event (event)
       }
 #endif /* HAVE_MOUSE */
 
-#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \
-    || defined (USE_GTK)
+#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) \
+    || defined(HAVE_NS) || defined (USE_GTK)
     case MENU_BAR_EVENT:
       if (EQ (event->arg, event->frame_or_window))
        /* This is the prefix key.  We translate this to
@@ -6132,19 +6196,6 @@ make_lispy_event (event)
     case SAVE_SESSION_EVENT:
       return Qsave_session;
 
-#ifdef MAC_OS
-    case MAC_APPLE_EVENT:
-      {
-       Lisp_Object spec[2];
-
-       spec[0] = event->x;
-       spec[1] = event->y;
-       return Fcons (Qmac_apple_event,
-                     Fcons (Fvector (2, spec),
-                            Fcons (event->arg, Qnil)));
-      }
-#endif
-
 #ifdef HAVE_DBUS
     case DBUS_EVENT:
       {
@@ -6152,6 +6203,10 @@ make_lispy_event (event)
       }
 #endif /* HAVE_DBUS */
 
+    case CONFIG_CHANGED_EVENT:
+       return Fcons (Qconfig_changed_event,
+                      Fcons (event->arg,
+                             Fcons (event->frame_or_window, Qnil)));
 #ifdef HAVE_GPM
     case GPM_CLICK_EVENT:
       {
@@ -6375,6 +6430,11 @@ parse_modifiers_uncached (symbol, modifier_end)
       && ('0' <= SREF (name, i + 6) && SREF (name, i + 6) <= '9'))
     modifiers |= click_modifier;
 
+  if (! (modifiers & (double_modifier | triple_modifier))
+      && i + 6 < SBYTES (name)
+      && strncmp (SDATA (name) + i, "wheel-", 6) == 0)
+    modifiers |= click_modifier;
+
   if (modifier_end)
     *modifier_end = i;
 
@@ -6435,7 +6495,7 @@ apply_modifiers_uncached (modifiers, base, base_len, base_len_byte)
 }
 
 
-static char *modifier_names[] =
+static const char *modifier_names[] =
 {
   "up", "down", "drag", "click", "double", "triple", 0, 0,
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -6824,9 +6884,8 @@ has the same base event type and all the specified modifiers.  */)
 /* Try to recognize SYMBOL as a modifier name.
    Return the modifier flag bit, or 0 if not recognized.  */
 
-static int
-parse_solitary_modifier (symbol)
-     Lisp_Object symbol;
+int
+parse_solitary_modifier (Lisp_Object symbol)
 {
   Lisp_Object name = SYMBOL_NAME (symbol);
 
@@ -6967,11 +7026,10 @@ gobble_input (expected)
      int expected;
 {
 #ifdef HAVE_DBUS
-  /* Check whether a D-Bus message has arrived.  */
+  /* Read D-Bus messages.  */
   xd_read_queued_messages ();
 #endif /* HAVE_DBUS */
 
-#ifndef VMS
 #ifdef SIGIO
   if (interrupt_input)
     {
@@ -6996,7 +7054,6 @@ gobble_input (expected)
 #endif
 #endif
     read_avail_input (expected);
-#endif
 }
 
 /* Put a BUFFER_SWITCH_EVENT in the buffer
@@ -7044,17 +7101,11 @@ record_asynch_buffer_change ()
     }
 }
 \f
-#ifndef VMS
-
 /* Read any terminal input already buffered up by the system
    into the kbd_buffer, but do not wait.
 
    EXPECTED should be nonzero if the caller knows there is some input.
 
-   Except on VMS, all input is read by this function.
-   If interrupt_input is nonzero, this function MUST be called
-   only when SIGIO is blocked.
-
    Returns the number of keyboard chars read, or -1 meaning
    this is a bad time to try to read input.  */
 
@@ -7111,7 +7162,7 @@ read_avail_input (expected)
                    alone in its group.  */
                 kill (getpid (), SIGHUP);
 
-              /* XXX Is calling delete_terminal safe here?  It calls Fdelete_frame. */
+              /* XXX Is calling delete_terminal safe here?  It calls delete_frame. */
              {
                Lisp_Object tmp;
                XSETTERMINAL (tmp, t);
@@ -7129,9 +7180,52 @@ read_avail_input (expected)
   if (err && !nread)
     nread = -1;
 
+  frame_make_pointer_visible ();
+
   return nread;
 }
 
+static void
+decode_keyboard_code (struct tty_display_info *tty,
+                     struct coding_system *coding,
+                     unsigned char *buf, int nbytes)
+{
+  unsigned char *src = buf;
+  const unsigned char *p;
+  int i;
+
+  if (nbytes == 0)
+    return;
+  if (tty->meta_key != 2)
+    for (i = 0; i < nbytes; i++)
+      buf[i] &= ~0x80;
+  if (coding->carryover_bytes > 0)
+    {
+      src = alloca (coding->carryover_bytes + nbytes);
+      memcpy (src, coding->carryover, coding->carryover_bytes);
+      memcpy (src + coding->carryover_bytes, buf, nbytes);
+      nbytes += coding->carryover_bytes;
+    }
+  coding->destination = alloca (nbytes * 4);
+  coding->dst_bytes = nbytes * 4;
+  decode_coding_c_string (coding, src, nbytes, Qnil);
+  if (coding->produced_char == 0)
+    return;
+  for (i = 0, p = coding->destination; i < coding->produced_char; i++)
+    {
+      struct input_event buf;
+
+      EVENT_INIT (buf);
+      buf.code = STRING_CHAR_ADVANCE (p);
+      buf.kind = (ASCII_CHAR_P (buf.code)
+                 ? ASCII_KEYSTROKE_EVENT : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
+      /* See the comment in tty_read_avail_input.  */
+      buf.frame_or_window = tty->top_frame;
+      buf.arg = Qnil;
+      kbd_buffer_store_event (&buf);
+    }
+}
+
 /* This is the tty way of reading available input.
 
    Note that each terminal device has its own `struct terminal' object,
@@ -7154,7 +7248,8 @@ tty_read_avail_input (struct terminal *terminal,
   if (!terminal->name)         /* Don't read from a dead terminal. */
     return 0;
 
-  if (terminal->type != output_termcap)
+  if (terminal->type != output_termcap
+      && terminal->type != output_msdos_raw)
     abort ();
 
   /* XXX I think the following code should be moved to separate hook
@@ -7162,6 +7257,12 @@ tty_read_avail_input (struct terminal *terminal,
 #ifdef WINDOWSNT
   return 0;
 #else /* not WINDOWSNT */
+  if (! tty->term_initted)      /* In case we get called during bootstrap. */
+    return 0;
+
+  if (! tty->input)
+    return 0;                   /* The terminal is suspended. */
+
 #ifdef MSDOS
   n_to_read = dos_keysns ();
   if (n_to_read == 0)
@@ -7171,26 +7272,28 @@ tty_read_avail_input (struct terminal *terminal,
   nread = 1;
 
 #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. */
-
 #ifdef HAVE_GPM
   if (gpm_tty == tty)
   {
       Gpm_Event event;
       struct input_event hold_quit;
-      int gpm;
+      int gpm, fd = gpm_fd;
 
       EVENT_INIT (hold_quit);
       hold_quit.kind = NO_EVENT;
 
+      /* gpm==1 if event received.
+         gpm==0 if the GPM daemon has closed the connection, in which case
+                Gpm_GetEvent closes gpm_fd and clears it to -1, which is why
+               we save it in `fd' so close_gpm can remove it from the
+               select masks.
+         gpm==-1 if a protocol error or EWOULDBLOCK; the latter is normal. */
       while (gpm = Gpm_GetEvent (&event), gpm == 1) {
          nread += handle_one_term_event (tty, &event, &hold_quit);
       }
+      if (gpm == 0)
+       /* Presumably the GPM daemon has closed the connection.  */
+       close_gpm (fd);
       if (hold_quit.kind != NO_EVENT)
          kbd_buffer_store_event (&hold_quit);
       if (nread)
@@ -7274,6 +7377,36 @@ tty_read_avail_input (struct terminal *terminal,
 #endif /* not MSDOS */
 #endif /* not WINDOWSNT */
 
+  if (TERMINAL_KEYBOARD_CODING (terminal)->common_flags
+      & CODING_REQUIRE_DECODING_MASK)
+    {
+      struct coding_system *coding = TERMINAL_KEYBOARD_CODING (terminal);
+      int from;
+
+      /* Decode the key sequence except for those with meta
+        modifiers.  */
+      for (i = from = 0; ; i++)
+       if (i == nread || (tty->meta_key == 1 && (cbuf[i] & 0x80)))
+         {
+           struct input_event buf;
+
+           decode_keyboard_code (tty, coding, cbuf + from, i - from);
+           if (i == nread)
+             break;
+
+           EVENT_INIT (buf);
+           buf.kind = ASCII_KEYSTROKE_EVENT;
+           buf.modifiers = meta_modifier;
+           buf.code = cbuf[i] & ~0x80;
+           /* See the comment below.  */
+           buf.frame_or_window = tty->top_frame;
+           buf.arg = Qnil;
+           kbd_buffer_store_event (&buf);
+           from = i + 1;
+         }
+      return nread;
+    }
+
   for (i = 0; i < nread; i++)
     {
       struct input_event buf;
@@ -7302,17 +7435,19 @@ tty_read_avail_input (struct terminal *terminal,
 
   return nread;
 }
-#endif /* not VMS */
 \f
 void
 handle_async_input ()
 {
-#ifdef BSD4_1
-  extern int select_alarmed;
-#endif
-
   interrupt_input_pending = 0;
-
+#ifdef SYNC_INPUT
+  pending_signals = pending_atimers;
+#endif
+/* Tell ns_read_socket() it is being called asynchronously so it can avoid
+   doing anything dangerous. */
+#ifdef HAVE_NS
+  ++handling_signal;
+#endif
   while (1)
     {
       int nread;
@@ -7322,11 +7457,18 @@ handle_async_input ()
         0 means there was no keyboard input available.  */
       if (nread <= 0)
        break;
-
-#ifdef BSD4_1
-      select_alarmed = 1;  /* Force the select emulator back to life */
-#endif
     }
+#ifdef HAVE_NS
+  --handling_signal;
+#endif
+}
+
+void
+process_pending_signals ()
+{
+  if (interrupt_input_pending)
+    handle_async_input ();
+  do_pending_atimers ();
 }
 
 #ifdef SIGIO   /* for entire page */
@@ -7344,12 +7486,9 @@ input_available_signal (signo)
   signal (signo, input_available_signal);
 #endif /* USG */
 
-#ifdef BSD4_1
-  sigisheld (SIGIO);
-#endif
-
 #ifdef SYNC_INPUT
   interrupt_input_pending = 1;
+  pending_signals = 1;
 #else
   SIGNAL_THREAD_CHECK (signo);
 #endif
@@ -7361,9 +7500,6 @@ input_available_signal (signo)
   handle_async_input ();
 #endif
 
-#ifdef BSD4_1
-  sigfree ();
-#endif
   errno = old_errno;
 }
 #endif /* SIGIO */
@@ -7703,7 +7839,7 @@ menu_bar_item (key, item, dummy1, dummy2)
      parse_menu_item, so that if it turns out it wasn't a menu item,
      it still correctly hides any further menu item.  */
   GCPRO1 (key);
-  i = parse_menu_item (item, 0, 1);
+  i = parse_menu_item (item, 1);
   UNGCPRO;
   if (!i)
     return;
@@ -7771,8 +7907,6 @@ menu_item_eval_property (sexpr)
 /* This function parses a menu item and leaves the result in the
    vector item_properties.
    ITEM is a key binding, a possible menu item.
-   If NOTREAL is nonzero, only check for equivalent key bindings, don't
-   evaluate dynamic expressions in the menu item.
    INMENUBAR is > 0 when this is considered for an entry in a menu bar
    top level.
    INMENUBAR is < 0 when this is considered for an entry in a keyboard menu.
@@ -7780,18 +7914,15 @@ menu_item_eval_property (sexpr)
    otherwise.  */
 
 int
-parse_menu_item (item, notreal, inmenubar)
+parse_menu_item (item, inmenubar)
      Lisp_Object item;
-     int notreal, inmenubar;
+     int inmenubar;
 {
   Lisp_Object def, tem, item_string, start;
-  Lisp_Object cachelist;
   Lisp_Object filter;
   Lisp_Object keyhint;
   int i;
-  int newcache = 0;
 
-  cachelist = Qnil;
   filter = Qnil;
   keyhint = Qnil;
 
@@ -7828,14 +7959,11 @@ parse_menu_item (item, notreal, inmenubar)
          item = XCDR (item);
        }
 
-      /* Maybe key binding cache.  */
+      /* Maybe an obsolete key binding cache.  */
       if (CONSP (item) && CONSP (XCAR (item))
          && (NILP (XCAR (XCAR (item)))
              || VECTORP (XCAR (XCAR (item)))))
-       {
-         cachelist = XCAR (item);
-         item = XCDR (item);
-       }
+       item = XCDR (item);
 
       /* This is the real definition--the function to run.  */
       ASET (item_properties, ITEM_PROPERTY_DEF, item);
@@ -7861,12 +7989,9 @@ parse_menu_item (item, notreal, inmenubar)
          ASET (item_properties, ITEM_PROPERTY_DEF, XCAR (start));
 
          item = XCDR (start);
-         /* Is there a cache list with key equivalences. */
+         /* Is there an obsolete cache list with key equivalences.  */
          if (CONSP (item) && CONSP (XCAR (item)))
-           {
-             cachelist = XCAR (item);
-             item = XCDR (item);
-           }
+           item = XCDR (item);
 
          /* Parse properties.  */
          while (CONSP (item) && CONSP (XCDR (item)))
@@ -7881,7 +8006,7 @@ parse_menu_item (item, notreal, inmenubar)
                  else
                    ASET (item_properties, ITEM_PROPERTY_ENABLE, XCAR (item));
                }
-             else if (EQ (tem, QCvisible) && !notreal)
+             else if (EQ (tem, QCvisible))
                {
                  /* If got a visible property and that evaluates to nil
                     then ignore this item.  */
@@ -7896,15 +8021,14 @@ parse_menu_item (item, notreal, inmenubar)
              else if (EQ (tem, QCkey_sequence))
                {
                  tem = XCAR (item);
-                 if (NILP (cachelist)
-                     && (SYMBOLP (tem) || STRINGP (tem) || VECTORP (tem)))
+                 if (SYMBOLP (tem) || STRINGP (tem) || VECTORP (tem))
                    /* Be GC protected. Set keyhint to item instead of tem. */
                    keyhint = item;
                }
              else if (EQ (tem, QCkeys))
                {
                  tem = XCAR (item);
-                 if (CONSP (tem) || (STRINGP (tem) && NILP (cachelist)))
+                 if (CONSP (tem) || STRINGP (tem))
                    ASET (item_properties, ITEM_PROPERTY_KEYEQ, tem);
                }
              else if (EQ (tem, QCbutton) && CONSP (XCAR (item)))
@@ -7931,7 +8055,7 @@ parse_menu_item (item, notreal, inmenubar)
   /* If item string is not a string, evaluate it to get string.
      If we don't get a string, skip this item.  */
   item_string = AREF (item_properties, ITEM_PROPERTY_NAME);
-  if (!(STRINGP (item_string) || notreal))
+  if (!(STRINGP (item_string)))
     {
       item_string = menu_item_eval_property (item_string);
       if (!STRINGP (item_string))
@@ -7953,10 +8077,7 @@ parse_menu_item (item, notreal, inmenubar)
   tem = AREF (item_properties, ITEM_PROPERTY_ENABLE);
   if (!EQ (tem, Qt))
     {
-      if (notreal)
-       tem = Qt;
-      else
-       tem = menu_item_eval_property (tem);
+      tem = menu_item_eval_property (tem);
       if (inmenubar && NILP (tem))
        return 0;               /* Ignore disabled items in menu bar.  */
       ASET (item_properties, ITEM_PROPERTY_ENABLE, tem);
@@ -7984,121 +8105,64 @@ parse_menu_item (item, notreal, inmenubar)
   if (inmenubar > 0)
     return 1;
 
-  /* This is a command.  See if there is an equivalent key binding. */
-  if (NILP (cachelist))
-    {
-      /* We have to create a cachelist.  */
-      CHECK_IMPURE (start);
-      XSETCDR (start, Fcons (Fcons (Qnil, Qnil), XCDR (start)));
-      cachelist = XCAR (XCDR (start));
-      newcache = 1;
-      tem = AREF (item_properties, ITEM_PROPERTY_KEYEQ);
-      if (!NILP (keyhint))
-       {
-         XSETCAR (cachelist, XCAR (keyhint));
-         newcache = 0;
-       }
-      else if (STRINGP (tem))
-       {
-         XSETCDR (cachelist, Fsubstitute_command_keys (tem));
-         XSETCAR (cachelist, Qt);
-       }
-    }
-
-  tem = XCAR (cachelist);
-  if (!EQ (tem, Qt))
-    {
-      int chkcache = 0;
-      Lisp_Object prefix;
+  { /* This is a command.  See if there is an equivalent key binding. */
+    Lisp_Object keyeq = AREF (item_properties, ITEM_PROPERTY_KEYEQ);
 
-      if (!NILP (tem))
-       tem = Fkey_binding (tem, Qnil, Qnil, Qnil);
-
-      prefix = AREF (item_properties, ITEM_PROPERTY_KEYEQ);
-      if (CONSP (prefix))
-       {
-         def = XCAR (prefix);
-         prefix = XCDR (prefix);
-       }
-      else
-       def = AREF (item_properties, ITEM_PROPERTY_DEF);
+    /* The previous code preferred :key-sequence to :keys, so we
+       preserve this behavior.  */
+    if (STRINGP (keyeq) && !CONSP (keyhint))
+      keyeq = Fsubstitute_command_keys (keyeq);
+    else
+      {
+       Lisp_Object prefix = keyeq;
+       Lisp_Object keys = Qnil;
 
-      if (NILP (XCAR (cachelist))) /* Have no saved key.  */
-       {
-         if (newcache          /* Always check first time.  */
-             /* Should we check everything when precomputing key
-                bindings?  */
-             /* If something had no key binding before, don't recheck it
-                because that is too slow--except if we have a list of
-                rebound commands in Vdefine_key_rebound_commands, do
-                recheck any command that appears in that list. */
-             || (CONSP (Vdefine_key_rebound_commands)
-                 && !NILP (Fmemq (def, Vdefine_key_rebound_commands))))
-           chkcache = 1;
-       }
-      /* We had a saved key. Is it still bound to the command?  */
-      else if (NILP (tem)
-              || (!EQ (tem, def)
-                  /* If the command is an alias for another
-                     (such as lmenu.el set it up), check if the
-                     original command matches the cached command.  */
-                  && !(SYMBOLP (def) && EQ (tem, XSYMBOL (def)->function))))
-       chkcache = 1;           /* Need to recompute key binding.  */
-
-      if (chkcache)
-       {
-         /* Recompute equivalent key binding.  If the command is an alias
-            for another (such as lmenu.el set it up), see if the original
-            command name has equivalent keys.  Otherwise look up the
-            specified command itself.  We don't try both, because that
-            makes lmenu menus slow. */
-         if (SYMBOLP (def)
-             && SYMBOLP (XSYMBOL (def)->function)
-             && ! NILP (Fget (def, Qmenu_alias)))
-           def = XSYMBOL (def)->function;
-         tem = Fwhere_is_internal (def, Qnil, Qt, Qnil, Qt);
-         XSETCAR (cachelist, tem);
-         if (NILP (tem))
-           {
-             XSETCDR (cachelist, Qnil);
-             chkcache = 0;
-           }
-       }
-      else if (!NILP (keyhint) && !NILP (XCAR (cachelist)))
-       {
-         tem = XCAR (cachelist);
-         chkcache = 1;
-       }
+       if (CONSP (prefix))
+         {
+           def = XCAR (prefix);
+           prefix = XCDR (prefix);
+         }
+       else
+         def = AREF (item_properties, ITEM_PROPERTY_DEF);
 
-      newcache = chkcache;
-      if (chkcache)
-       {
-         tem = Fkey_description (tem, Qnil);
-         if (CONSP (prefix))
-           {
-             if (STRINGP (XCAR (prefix)))
-               tem = concat2 (XCAR (prefix), tem);
-             if (STRINGP (XCDR (prefix)))
-               tem = concat2 (tem, XCDR (prefix));
-           }
-         XSETCDR (cachelist, tem);
-       }
-    }
+       if (CONSP (keyhint) && !NILP (XCAR (keyhint)))
+         {
+           keys = XCAR (keyhint);
+           tem = Fkey_binding (keys, Qnil, Qnil, Qnil);
+
+           /* We have a suggested key.  Is it bound to the command?  */
+           if (NILP (tem)
+               || (!EQ (tem, def)
+                   /* If the command is an alias for another
+                      (such as lmenu.el set it up), check if the
+                      original command matches the cached command.  */
+                   && !(SYMBOLP (def) && EQ (tem, XSYMBOL (def)->function))))
+             keys = Qnil;
+         }
 
-  tem = XCDR (cachelist);
-  if (newcache && !NILP (tem))
-    {
-      tem = concat2 (build_string ("  "), tem);
-      // tem = concat3 (build_string ("  ("), tem, build_string (")"));
-      XSETCDR (cachelist, tem);
-    }
+       if (NILP (keys))
+         keys = Fwhere_is_internal (def, Qnil, Qt, Qnil, Qnil);
 
-  /* If we only want to precompute equivalent key bindings, stop here. */
-  if (notreal)
-    return 1;
+       if (!NILP (keys))
+         {
+           tem = Fkey_description (keys, Qnil);
+           if (CONSP (prefix))
+             {
+               if (STRINGP (XCAR (prefix)))
+                 tem = concat2 (XCAR (prefix), tem);
+               if (STRINGP (XCDR (prefix)))
+                 tem = concat2 (tem, XCDR (prefix));
+             }
+           keyeq = concat2 (build_string ("  "), tem);
+           /* keyeq = concat3(build_string("  ("),tem,build_string(")")); */
+         }
+       else
+         keyeq = Qnil;
+      }
 
-  /* If we have an equivalent key binding, use that.  */
-  ASET (item_properties, ITEM_PROPERTY_KEYEQ, tem);
+    /* If we have an equivalent key binding, use that.  */
+    ASET (item_properties, ITEM_PROPERTY_KEYEQ, keyeq);
+  }
 
   /* Include this when menu help is implemented.
   tem = XVECTOR (item_properties)->contents[ITEM_PROPERTY_HELP];
@@ -8533,7 +8597,6 @@ read_char_x_menu_prompt (nmaps, maps, prev_event, used_mouse_menu)
      int *used_mouse_menu;
 {
   int mapno;
-  register Lisp_Object name = Qnil;
 
   if (used_mouse_menu)
     *used_mouse_menu = 0;
@@ -8550,18 +8613,6 @@ read_char_x_menu_prompt (nmaps, maps, prev_event, used_mouse_menu)
       nmaps = 1;
     }
 
-  /* Get the menu name from the first map that has one (a prompt string).  */
-  for (mapno = 0; mapno < nmaps; mapno++)
-    {
-      name = Fkeymap_prompt (maps[mapno]);
-      if (!NILP (name))
-       break;
-    }
-
-  /* If we don't have any menus, just read a character normally.  */
-  if (!STRINGP (name))
-    return Qnil;
-
 #ifdef HAVE_MENUS
   /* If we got to this point via a mouse click,
      use a real menu for mouse selection.  */
@@ -8648,7 +8699,20 @@ read_char_minibuf_menu_prompt (commandflag, nmaps, maps)
   if (! menu_prompting)
     return Qnil;
 
+  /* Get the menu name from the first map that has one (a prompt string).  */
+  for (mapno = 0; mapno < nmaps; mapno++)
+    {
+      name = Fkeymap_prompt (maps[mapno]);
+      if (!NILP (name))
+       break;
+    }
+
+  /* If we don't have any menus, just read a character normally.  */
+  if (!STRINGP (name))
+    return Qnil;
+
   /* Make sure we have a big enough buffer for the menu text.  */
+  width = max (width, SBYTES (name));
   if (read_char_minibuf_menu_text == 0)
     {
       read_char_minibuf_menu_width = width + 4;
@@ -8662,18 +8726,6 @@ read_char_minibuf_menu_prompt (commandflag, nmaps, maps)
     }
   menu = read_char_minibuf_menu_text;
 
-  /* Get the menu name from the first map that has one (a prompt string).  */
-  for (mapno = 0; mapno < nmaps; mapno++)
-    {
-      name = Fkeymap_prompt (maps[mapno]);
-      if (!NILP (name))
-       break;
-    }
-
-  /* If we don't have any menus, just read a character normally.  */
-  if (!STRINGP (name))
-    return Qnil;
-
   /* Prompt string always starts with map's prompt, and a space.  */
   strcpy (menu, SDATA (name));
   nlength = SBYTES (name);
@@ -8743,7 +8795,7 @@ read_char_minibuf_menu_prompt (commandflag, nmaps, maps)
                }
 
              /* Ignore the element if it has no prompt string.  */
-             if (INTEGERP (event) && parse_menu_item (elt, 0, -1))
+             if (INTEGERP (event) && parse_menu_item (elt, -1))
                {
                  /* 1 if the char to type matches the string.  */
                  int char_matches;
@@ -9247,16 +9299,10 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
   orig_keymap = get_local_map (PT, current_buffer, Qkeymap);
   from_string = Qnil;
 
-  /* The multi-tty merge moved the code below to right after
-   `replay_sequence' which caused all these translation maps to be applied
-   repeatedly, even tho their doc says very clearly they are not applied to
-   their own output.
-   The reason for this move was: "We may switch keyboards between rescans,
-   so we need to reinitialize fkey and keytran before each replay".
-   This move was wrong (even if we switch keyboards, keybuf still holds the
-   keys we've read already from the original keyboard and some of those keys
-   may have already been translated).  So there may still be a bug out there
-   lurking.  */
+  /* We jump here when we need to reinitialize fkey and keytran; this
+     happens if we switch keyboards between rescans.  */
+ replay_entire_sequence:
+
   indec.map = indec.parent = current_kboard->Vinput_decode_map;
   fkey.map = fkey.parent = current_kboard->Vlocal_function_key_map;
   keytran.map = keytran.parent = Vkey_translation_map;
@@ -9434,14 +9480,11 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
       else
        {
          {
-#ifdef MULTI_KBOARD
            KBOARD *interrupted_kboard = current_kboard;
            struct frame *interrupted_frame = SELECTED_FRAME ();
-#endif
            key = read_char (NILP (prompt), nmaps,
                             (Lisp_Object *) submaps, last_nonmenu_event,
                             &used_mouse_menu, NULL);
-#ifdef MULTI_KBOARD
            if (INTEGERP (key) && XINT (key) == -2) /* wrong_kboard_jmpbuf */
              {
                int found = 0;
@@ -9456,7 +9499,7 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
                    /* Don't touch interrupted_kboard when it's been
                       deleted. */
                    delayed_switch_frame = Qnil;
-                   goto replay_sequence;
+                   goto replay_entire_sequence;
                  }
 
                if (!NILP (delayed_switch_frame))
@@ -9488,9 +9531,8 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
                mock_input = 0;
                orig_local_map = get_local_map (PT, current_buffer, Qlocal_map);
                orig_keymap = get_local_map (PT, current_buffer, Qkeymap);
-               goto replay_sequence;
+               goto replay_entire_sequence;
              }
-#endif
          }
 
          /* read_char returns t when it shows a menu and the user rejects it.
@@ -11066,11 +11108,7 @@ handle_interrupt ()
   cancel_echoing ();
 
   /* XXX This code needs to be revised for multi-tty support. */
-  if (!NILP (Vquit_flag)
-#ifndef MSDOS
-      && get_named_tty ("/dev/tty")
-#endif
-      )
+  if (!NILP (Vquit_flag) && get_named_tty ("/dev/tty"))
     {
       /* If SIGINT isn't blocked, don't let us be interrupted by
         another SIGINT, it might be harmful due to non-reentrancy
@@ -11090,24 +11128,16 @@ handle_interrupt ()
  */
       sys_suspend ();
 #else
-#ifdef VMS
-      if (sys_suspend () == -1)
-       {
-         printf ("Not running as a subprocess;\n");
-         printf ("you can continue or abort.\n");
-       }
-#else /* not VMS */
       /* Perhaps should really fork an inferior shell?
         But that would not provide any way to get back
         to the original shell, ever.  */
       printf ("No support for stopping a process on this operating system;\n");
       printf ("you can continue or abort.\n");
-#endif /* not VMS */
 #endif /* not SIGTSTP */
 #ifdef MSDOS
       /* We must remain inside the screen area when the internal terminal
         is used.  Note that [Enter] is not echoed by dos.  */
-      cursor_to (0, 0);
+      cursor_to (SELECTED_FRAME (), 0, 0);
 #endif
       /* It doesn't work to autosave while GC is in progress;
         the code used for auto-saving doesn't cope with the mark bit.  */
@@ -11141,11 +11171,7 @@ handle_interrupt ()
 #ifdef MSDOS
       printf ("\r\nAbort?  (y or n) ");
 #else /* not MSDOS */
-#ifdef VMS
-      printf ("Abort (and enter debugger)? (y or n) ");
-#else /* not VMS */
       printf ("Abort (and dump core)? (y or n) ");
-#endif /* not VMS */
 #endif /* not MSDOS */
       fflush (stdout);
       if (((c = getchar ()) & ~040) == 'Y')
@@ -11184,8 +11210,17 @@ handle_interrupt ()
        Vquit_flag = Qt;
     }
 
+/* TODO: The longjmp in this call throws the NS event loop integration off,
+         and it seems to do fine without this.  Probably some attention
+        needs to be paid to the setting of waiting_for_input in
+         wait_reading_process_output() under HAVE_NS because of the call
+         to ns_select there (needed because otherwise events aren't picked up
+         outside of polling since we don't get SIGIO like X and we don't have a
+         separate event loop thread like W32. */
+#ifndef HAVE_NS
   if (waiting_for_input && !echoing)
       quit_throw_to_read_char ();
+#endif
 }
 
 /* Handle a C-g by making read_char return C-g.  */
@@ -11213,7 +11248,7 @@ quit_throw_to_read_char ()
   if (FRAMEP (internal_last_event_frame)
       && !EQ (internal_last_event_frame, selected_frame))
     do_switch_frame (make_lispy_switch_frame (internal_last_event_frame),
-                    0, 0);
+                    0, 0, Qnil);
 
   _longjmp (getcjmp, 1);
 }
@@ -11242,17 +11277,12 @@ See also `current-input-mode'.  */)
 #endif /* NO_SOCK_SIGIO */
     }
   else
-#endif
+#endif /* HAVE_X_WINDOWS */
     new_interrupt_input = !NILP (interrupt);
 #else /* not SIGIO */
   new_interrupt_input = 0;
 #endif /* not SIGIO */
 
-/* Our VMS input only works by interrupts, as of now.  */
-#ifdef VMS
-  new_interrupt_input = 1;
-#endif
-
   if (new_interrupt_input != interrupt_input)
     {
 #ifdef POLL_FOR_INPUT
@@ -11289,7 +11319,7 @@ See also `current-input-mode'.  */)
 {
   struct terminal *t = get_terminal (terminal, 1);
   struct tty_display_info *tty;
-  if (t == NULL || t->type != output_termcap)
+  if (t == NULL || (t->type != output_termcap && t->type != output_msdos_raw))
     return Qnil;
   tty = t->display_info.tty;
 
@@ -11323,8 +11353,8 @@ specially interpreting the top bit.
 This setting only has an effect on tty terminal devices.
 
 Optional parameter TERMINAL specifies the tty terminal device to use.
-It may be a terminal id, a frame, or nil for the terminal used by the
-currently selected frame.
+It may be a terminal object, a frame, or nil for the terminal used by
+the currently selected frame.
 
 See also `current-input-mode'.  */)
        (meta, terminal)
@@ -11334,7 +11364,7 @@ See also `current-input-mode'.  */)
   struct tty_display_info *tty;
   int new_meta;
 
-  if (t == NULL || t->type != output_termcap)
+  if (t == NULL || (t->type != output_termcap && t->type != output_msdos_raw))
     return Qnil;
   tty = t->display_info.tty;
 
@@ -11374,7 +11404,7 @@ See also `current-input-mode'.  */)
 {
   struct terminal *t = get_named_tty ("/dev/tty");
   struct tty_display_info *tty;
-  if (t == NULL || t->type != output_termcap)
+  if (t == NULL || (t->type != output_termcap && t->type != output_msdos_raw))
     return Qnil;
   tty = t->display_info.tty;
 
@@ -11438,7 +11468,7 @@ The elements of this list correspond to the arguments of
   struct frame *sf = XFRAME (selected_frame);
 
   val[0] = interrupt_input ? Qt : Qnil;
-  if (FRAME_TERMCAP_P (sf))
+  if (FRAME_TERMCAP_P (sf) || FRAME_MSDOS_P (sf))
     {
       val[1] = FRAME_TTY (sf)->flow_control ? Qt : Qnil;
       val[2] = (FRAME_TTY (sf)->meta_key == 2
@@ -11573,12 +11603,9 @@ static void
 wipe_kboard (kb)
      KBOARD *kb;
 {
-  if (kb->kbd_macro_buffer)
-    xfree (kb->kbd_macro_buffer);
+  xfree (kb->kbd_macro_buffer);
 }
 
-#ifdef MULTI_KBOARD
-
 /* Free KB and memory referenced from it.  */
 
 void
@@ -11607,8 +11634,6 @@ delete_kboard (kb)
   xfree (kb);
 }
 
-#endif /* MULTI_KBOARD */
-
 void
 init_keyboard ()
 {
@@ -11629,15 +11654,16 @@ init_keyboard ()
   input_pending = 0;
   interrupt_input_blocked = 0;
   interrupt_input_pending = 0;
+#ifdef SYNC_INPUT
+  pending_signals = 0;
+#endif
 
   /* This means that command_loop_1 won't try to select anything the first
      time through.  */
   internal_last_event_frame = Qnil;
   Vlast_event_frame = internal_last_event_frame;
 
-#ifdef MULTI_KBOARD
   current_kboard = initial_kboard;
-#endif
   /* Re-initialize the keyboard again.  */
   wipe_kboard (current_kboard);
   init_kboard (current_kboard);
@@ -11675,11 +11701,6 @@ init_keyboard ()
   interrupt_input = 0;
 #endif
 
-/* Our VMS input only works by interrupts, as of now.  */
-#ifdef VMS
-  interrupt_input = 1;
-#endif
-
   sigfree ();
   dribble = 0;
 
@@ -11687,6 +11708,7 @@ init_keyboard ()
     (*keyboard_init_hook) ();
 
 #ifdef POLL_FOR_INPUT
+  poll_timer = NULL;
   poll_suppress_count = 1;
   start_polling ();
 #endif
@@ -11716,19 +11738,20 @@ void
 syms_of_keyboard ()
 {
   pending_funcalls = Qnil;
+  staticpro (&pending_funcalls);
 
-  Vlispy_mouse_stem = build_string ("mouse");
+  Vlispy_mouse_stem = make_pure_c_string ("mouse");
   staticpro (&Vlispy_mouse_stem);
 
   /* Tool-bars.  */
-  QCimage = intern (":image");
+  QCimage = intern_c_string (":image");
   staticpro (&QCimage);
 
   staticpro (&Qhelp_echo);
-  Qhelp_echo = intern ("help-echo");
+  Qhelp_echo = intern_c_string ("help-echo");
 
   staticpro (&Qrtl);
-  Qrtl = intern (":rtl");
+  Qrtl = intern_c_string (":rtl");
 
   staticpro (&item_properties);
   item_properties = Qnil;
@@ -11741,142 +11764,138 @@ syms_of_keyboard ()
   staticpro (&real_this_command);
   real_this_command = Qnil;
 
-  Qtimer_event_handler = intern ("timer-event-handler");
+  Qtimer_event_handler = intern_c_string ("timer-event-handler");
   staticpro (&Qtimer_event_handler);
 
-  Qdisabled_command_function = intern ("disabled-command-function");
+  Qdisabled_command_function = intern_c_string ("disabled-command-function");
   staticpro (&Qdisabled_command_function);
 
-  Qself_insert_command = intern ("self-insert-command");
+  Qself_insert_command = intern_c_string ("self-insert-command");
   staticpro (&Qself_insert_command);
 
-  Qforward_char = intern ("forward-char");
+  Qforward_char = intern_c_string ("forward-char");
   staticpro (&Qforward_char);
 
-  Qbackward_char = intern ("backward-char");
+  Qbackward_char = intern_c_string ("backward-char");
   staticpro (&Qbackward_char);
 
-  Qdisabled = intern ("disabled");
+  Qdisabled = intern_c_string ("disabled");
   staticpro (&Qdisabled);
 
-  Qundefined = intern ("undefined");
+  Qundefined = intern_c_string ("undefined");
   staticpro (&Qundefined);
 
-  Qpre_command_hook = intern ("pre-command-hook");
+  Qpre_command_hook = intern_c_string ("pre-command-hook");
   staticpro (&Qpre_command_hook);
 
-  Qpost_command_hook = intern ("post-command-hook");
+  Qpost_command_hook = intern_c_string ("post-command-hook");
   staticpro (&Qpost_command_hook);
 
-  Qdeferred_action_function = intern ("deferred-action-function");
+  Qdeferred_action_function = intern_c_string ("deferred-action-function");
   staticpro (&Qdeferred_action_function);
 
-  Qcommand_hook_internal = intern ("command-hook-internal");
+  Qcommand_hook_internal = intern_c_string ("command-hook-internal");
   staticpro (&Qcommand_hook_internal);
 
-  Qfunction_key = intern ("function-key");
+  Qfunction_key = intern_c_string ("function-key");
   staticpro (&Qfunction_key);
-  Qmouse_click = intern ("mouse-click");
+  Qmouse_click = intern_c_string ("mouse-click");
   staticpro (&Qmouse_click);
-#if defined (WINDOWSNT) || defined (MAC_OS)
-  Qlanguage_change = intern ("language-change");
+#if defined (WINDOWSNT)
+  Qlanguage_change = intern_c_string ("language-change");
   staticpro (&Qlanguage_change);
 #endif
-  Qdrag_n_drop = intern ("drag-n-drop");
+  Qdrag_n_drop = intern_c_string ("drag-n-drop");
   staticpro (&Qdrag_n_drop);
 
-  Qsave_session = intern ("save-session");
+  Qsave_session = intern_c_string ("save-session");
   staticpro (&Qsave_session);
 
-#ifdef MAC_OS
-  Qmac_apple_event = intern ("mac-apple-event");
-  staticpro (&Qmac_apple_event);
-#endif
-
 #ifdef HAVE_DBUS
-  Qdbus_event = intern ("dbus-event");
+  Qdbus_event = intern_c_string ("dbus-event");
   staticpro (&Qdbus_event);
 #endif
 
-  Qmenu_enable = intern ("menu-enable");
+  Qconfig_changed_event = intern_c_string ("config-changed-event");
+  staticpro (&Qconfig_changed_event);
+
+  Qmenu_enable = intern_c_string ("menu-enable");
   staticpro (&Qmenu_enable);
-  Qmenu_alias = intern ("menu-alias");
-  staticpro (&Qmenu_alias);
-  QCenable = intern (":enable");
+  QCenable = intern_c_string (":enable");
   staticpro (&QCenable);
-  QCvisible = intern (":visible");
+  QCvisible = intern_c_string (":visible");
   staticpro (&QCvisible);
-  QChelp = intern (":help");
+  QChelp = intern_c_string (":help");
   staticpro (&QChelp);
-  QCfilter = intern (":filter");
+  QCfilter = intern_c_string (":filter");
   staticpro (&QCfilter);
-  QCbutton = intern (":button");
+  QCbutton = intern_c_string (":button");
   staticpro (&QCbutton);
-  QCkeys = intern (":keys");
+  QCkeys = intern_c_string (":keys");
   staticpro (&QCkeys);
-  QCkey_sequence = intern (":key-sequence");
+  QCkey_sequence = intern_c_string (":key-sequence");
   staticpro (&QCkey_sequence);
-  QCtoggle = intern (":toggle");
+  QCtoggle = intern_c_string (":toggle");
   staticpro (&QCtoggle);
-  QCradio = intern (":radio");
+  QCradio = intern_c_string (":radio");
   staticpro (&QCradio);
 
-  Qmode_line = intern ("mode-line");
+  Qmode_line = intern_c_string ("mode-line");
   staticpro (&Qmode_line);
-  Qvertical_line = intern ("vertical-line");
+  Qvertical_line = intern_c_string ("vertical-line");
   staticpro (&Qvertical_line);
-  Qvertical_scroll_bar = intern ("vertical-scroll-bar");
+  Qvertical_scroll_bar = intern_c_string ("vertical-scroll-bar");
   staticpro (&Qvertical_scroll_bar);
-  Qmenu_bar = intern ("menu-bar");
+  Qmenu_bar = intern_c_string ("menu-bar");
   staticpro (&Qmenu_bar);
 
 #if defined (HAVE_MOUSE) || defined (HAVE_GPM)
-  Qmouse_fixup_help_message = intern ("mouse-fixup-help-message");
+  Qmouse_fixup_help_message = intern_c_string ("mouse-fixup-help-message");
   staticpro (&Qmouse_fixup_help_message);
 #endif
 
-  Qabove_handle = intern ("above-handle");
+  Qabove_handle = intern_c_string ("above-handle");
   staticpro (&Qabove_handle);
-  Qhandle = intern ("handle");
+  Qhandle = intern_c_string ("handle");
   staticpro (&Qhandle);
-  Qbelow_handle = intern ("below-handle");
+  Qbelow_handle = intern_c_string ("below-handle");
   staticpro (&Qbelow_handle);
-  Qup = intern ("up");
+  Qup = intern_c_string ("up");
   staticpro (&Qup);
-  Qdown = intern ("down");
+  Qdown = intern_c_string ("down");
   staticpro (&Qdown);
-  Qtop = intern ("top");
+  Qtop = intern_c_string ("top");
   staticpro (&Qtop);
-  Qbottom = intern ("bottom");
+  Qbottom = intern_c_string ("bottom");
   staticpro (&Qbottom);
-  Qend_scroll = intern ("end-scroll");
+  Qend_scroll = intern_c_string ("end-scroll");
   staticpro (&Qend_scroll);
-  Qratio = intern ("ratio");
+  Qratio = intern_c_string ("ratio");
   staticpro (&Qratio);
 
-  Qevent_kind = intern ("event-kind");
+  Qevent_kind = intern_c_string ("event-kind");
   staticpro (&Qevent_kind);
-  Qevent_symbol_elements = intern ("event-symbol-elements");
+  Qevent_symbol_elements = intern_c_string ("event-symbol-elements");
   staticpro (&Qevent_symbol_elements);
-  Qevent_symbol_element_mask = intern ("event-symbol-element-mask");
+  Qevent_symbol_element_mask = intern_c_string ("event-symbol-element-mask");
   staticpro (&Qevent_symbol_element_mask);
-  Qmodifier_cache = intern ("modifier-cache");
+  Qmodifier_cache = intern_c_string ("modifier-cache");
   staticpro (&Qmodifier_cache);
 
-  Qrecompute_lucid_menubar = intern ("recompute-lucid-menubar");
+  Qrecompute_lucid_menubar = intern_c_string ("recompute-lucid-menubar");
   staticpro (&Qrecompute_lucid_menubar);
-  Qactivate_menubar_hook = intern ("activate-menubar-hook");
+  Qactivate_menubar_hook = intern_c_string ("activate-menubar-hook");
   staticpro (&Qactivate_menubar_hook);
 
-  Qpolling_period = intern ("polling-period");
+  Qpolling_period = intern_c_string ("polling-period");
   staticpro (&Qpolling_period);
 
-  Qinput_method_function = intern ("input-method-function");
+  Qinput_method_function = intern_c_string ("input-method-function");
   staticpro (&Qinput_method_function);
 
-  Qinput_method_exit_on_first_char = intern ("input-method-exit-on-first-char");
+  Qinput_method_exit_on_first_char = intern_c_string ("input-method-exit-on-first-char");
   staticpro (&Qinput_method_exit_on_first_char);
-  Qinput_method_use_echo_area = intern ("input-method-use-echo-area");
+  Qinput_method_use_echo_area = intern_c_string ("input-method-use-echo-area");
   staticpro (&Qinput_method_use_echo_area);
 
   Fset (Qinput_method_exit_on_first_char, Qnil);
@@ -11892,18 +11911,20 @@ syms_of_keyboard ()
         p < head_table + (sizeof (head_table) / sizeof (head_table[0]));
         p++)
       {
-       *p->var = intern (p->name);
+       *p->var = intern_c_string (p->name);
        staticpro (p->var);
        Fput (*p->var, Qevent_kind, *p->kind);
        Fput (*p->var, Qevent_symbol_elements, Fcons (*p->var, Qnil));
       }
   }
 
-  button_down_location = Fmake_vector (make_number (1), Qnil);
+  button_down_location = Fmake_vector (make_number (5), Qnil);
   staticpro (&button_down_location);
-  mouse_syms = Fmake_vector (make_number (1), Qnil);
+  mouse_syms = Fmake_vector (make_number (5), Qnil);
   staticpro (&mouse_syms);
-  wheel_syms = Fmake_vector (make_number (4), Qnil);
+  wheel_syms = Fmake_vector (make_number (sizeof (lispy_wheel_names)
+                                         / sizeof (lispy_wheel_names[0])),
+                            Qnil);
   staticpro (&wheel_syms);
 
   {
@@ -11913,7 +11934,7 @@ syms_of_keyboard ()
     modifier_symbols = Fmake_vector (make_number (len), Qnil);
     for (i = 0; i < len; i++)
       if (modifier_names[i])
-       XVECTOR (modifier_symbols)->contents[i] = intern (modifier_names[i]);
+       XVECTOR (modifier_symbols)->contents[i] = intern_c_string (modifier_names[i]);
     staticpro (&modifier_symbols);
   }
 
@@ -11926,7 +11947,7 @@ syms_of_keyboard ()
   raw_keybuf = Fmake_vector (make_number (30), Qnil);
   staticpro (&raw_keybuf);
 
-  Qextended_command_history = intern ("extended-command-history");
+  Qextended_command_history = intern_c_string ("extended-command-history");
   Fset (Qextended_command_history, Qnil);
   staticpro (&Qextended_command_history);
 
@@ -11992,10 +12013,7 @@ syms_of_keyboard ()
   defsubr (&Sposn_at_point);
   defsubr (&Sposn_at_x_y);
 
-  DEFVAR_LISP ("last-command-char", &last_command_char,
-              doc: /* Last input event that was part of a command.  */);
-
-  DEFVAR_LISP_NOPRO ("last-command-event", &last_command_char,
+  DEFVAR_LISP ("last-command-event", &last_command_event,
                     doc: /* Last input event that was part of a command.  */);
 
   DEFVAR_LISP ("last-nonmenu-event", &last_nonmenu_event,
@@ -12004,12 +12022,9 @@ Mouse menus give back keys that don't look like mouse events;
 this variable holds the actual mouse event that led to the menu,
 so that you can determine whether the command was run by mouse or not.  */);
 
-  DEFVAR_LISP ("last-input-char", &last_input_char,
+  DEFVAR_LISP ("last-input-event", &last_input_event,
               doc: /* Last input event.  */);
 
-  DEFVAR_LISP_NOPRO ("last-input-event", &last_input_char,
-                    doc: /* Last input event.  */);
-
   DEFVAR_LISP ("unread-command-events", &Vunread_command_events,
               doc: /* List of events to be read as the command input.
 These events are processed first, before actual keyboard input.
@@ -12235,11 +12250,11 @@ The command loop sets this to nil before each command,
 and tests the value when the command returns.
 Buffer modification stores t in this variable.  */);
   Vdeactivate_mark = Qnil;
-  Qdeactivate_mark = intern ("deactivate-mark");
+  Qdeactivate_mark = intern_c_string ("deactivate-mark");
   staticpro (&Qdeactivate_mark);
 
   DEFVAR_LISP ("command-hook-internal", &Vcommand_hook_internal,
-              doc: /* Temporary storage of pre-command-hook or post-command-hook.  */);
+              doc: /* Temporary storage of `pre-command-hook' or `post-command-hook'.  */);
   Vcommand_hook_internal = Qnil;
 
   DEFVAR_LISP ("pre-command-hook", &Vpre_command_hook,
@@ -12260,9 +12275,9 @@ might happen repeatedly and make Emacs nonfunctional.  */);
   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");
+  Qecho_area_clear_hook = intern_c_string ("echo-area-clear-hook");
   staticpro (&Qecho_area_clear_hook);
-  SET_SYMBOL_VALUE (Qecho_area_clear_hook, Qnil);
+  Fset (Qecho_area_clear_hook, Qnil);
 
   DEFVAR_LISP ("lucid-menu-bar-dirty-flag", &Vlucid_menu_bar_dirty_flag,
               doc: /* Non-nil means menu bar, specified Lucid style, needs to be recomputed.  */);
@@ -12301,7 +12316,7 @@ and the minor mode maps regardless of `overriding-local-map'.  */);
 
   DEFVAR_LISP ("special-event-map", &Vspecial_event_map,
               doc: /* Keymap defining bindings for special events to execute at low level.  */);
-  Vspecial_event_map = Fcons (intern ("keymap"), Qnil);
+  Vspecial_event_map = Fcons (intern_c_string ("keymap"), Qnil);
 
   DEFVAR_LISP ("track-mouse", &do_mouse_tracking,
               doc: /* *Non-nil means generate motion events for mouse motion.  */);
@@ -12350,7 +12365,7 @@ This is used mainly for mapping ASCII function key sequences into
 real Emacs function key events (symbols).
 
 The `read-key-sequence' function replaces any subsequence bound by
-`local-function-key-map' with its binding.  Contrary to `function-key-map',
+`input-decode-map' with its binding.  Contrary to `function-key-map',
 this map applies its rebinding regardless of the presence of an ordinary
 binding.  So it is more like `key-translation-map' except that it applies
 before `function-key-map' rather than after.
@@ -12416,7 +12431,7 @@ to be used as input.  If it wants to put back some events
 to be reconsidered, separately, by the input method,
 it can add them to the beginning of `unread-command-events'.
 
-The input method function can find in `input-method-previous-method'
+The input method function can find in `input-method-previous-message'
 the previous echo area message.
 
 The input method function should refer to the variables
@@ -12485,14 +12500,12 @@ Help functions bind this to allow help on disabled menu items
 and tool-bar buttons.  */);
   Venable_disabled_menus_and_buttons = Qnil;
 
-#ifdef MULTI_KBOARD
   /* Create the initial keyboard. */
   initial_kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
   init_kboard (initial_kboard);
   /* Vwindow_system is left at t for now.  */
   initial_kboard->next_kboard = all_kboards;
   all_kboards = initial_kboard;
-#endif
 }
 
 void
@@ -12506,6 +12519,10 @@ keys_of_keyboard ()
 
   initial_define_lispy_key (Vspecial_event_map, "delete-frame",
                            "handle-delete-frame");
+  initial_define_lispy_key (Vspecial_event_map, "ns-put-working-text",
+                           "ns-put-working-text");
+  initial_define_lispy_key (Vspecial_event_map, "ns-unput-working-text",
+                           "ns-unput-working-text");
   /* 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.
@@ -12544,6 +12561,9 @@ keys_of_keyboard ()
   initial_define_lispy_key (Vspecial_event_map, "dbus-event",
                            "dbus-handle-event");
 #endif
+
+  initial_define_lispy_key (Vspecial_event_map, "config-changed-event",
+                           "ignore");
 }
 
 /* Mark the pointers in the kboard objects.