]> code.delx.au - gnu-emacs/blobdiff - src/keyboard.c
* xterm.c (toolkit_scroll_bar_interaction): Use bool for boolean.
[gnu-emacs] / src / keyboard.c
index 9cb9dd0b47b4bcd5894384fdf00b6adbf708c9e2..020c88599417d5f97b552d99c322e3349fe37849 100644 (file)
@@ -23,7 +23,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #define BLOCKINPUT_INLINE EXTERN_INLINE
 #define KEYBOARD_INLINE EXTERN_INLINE
 
 #define BLOCKINPUT_INLINE EXTERN_INLINE
 #define KEYBOARD_INLINE EXTERN_INLINE
 
-#include <stdio.h>
+#include "sysstdio.h"
 
 #include "lisp.h"
 #include "termchar.h"
 
 #include "lisp.h"
 #include "termchar.h"
@@ -72,7 +72,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include TERM_HEADER
 #endif /* HAVE_WINDOW_SYSTEM */
 
 #include TERM_HEADER
 #endif /* HAVE_WINDOW_SYSTEM */
 
-/* Variables for blockinput.h: */
+/* Variables for blockinput.h:  */
 
 /* Positive if interrupt input is blocked right now.  */
 volatile int interrupt_input_blocked;
 
 /* Positive if interrupt input is blocked right now.  */
 volatile int interrupt_input_blocked;
@@ -210,12 +210,6 @@ static EMACS_INT last_auto_save;
 /* The value of point when the last command was started.  */
 static ptrdiff_t last_point_position;
 
 /* The value of point when the last command was started.  */
 static ptrdiff_t last_point_position;
 
-/* The buffer that was current when the last command was started.  */
-static Lisp_Object last_point_position_buffer;
-
-/* The window that was selected when the last command was started.  */
-static Lisp_Object last_point_position_window;
-
 /* The frame in which the last input event occurred, or Qmacro if the
    last event came from a macro.  We use this to determine when to
    generate switch-frame events.  This may be cleared by functions
 /* The frame in which the last input event occurred, or Qmacro if the
    last event came from a macro.  We use this to determine when to
    generate switch-frame events.  This may be cleared by functions
@@ -301,6 +295,7 @@ static struct input_event * volatile kbd_store_ptr;
 static Lisp_Object Qmouse_movement;
 static Lisp_Object Qscroll_bar_movement;
 Lisp_Object Qswitch_frame;
 static Lisp_Object Qmouse_movement;
 static Lisp_Object Qscroll_bar_movement;
 Lisp_Object Qswitch_frame;
+static Lisp_Object Qfocus_in, Qfocus_out;
 static Lisp_Object Qdelete_frame;
 static Lisp_Object Qiconify_frame;
 static Lisp_Object Qmake_frame_visible;
 static Lisp_Object Qdelete_frame;
 static Lisp_Object Qiconify_frame;
 static Lisp_Object Qmake_frame_visible;
@@ -314,18 +309,15 @@ static Lisp_Object Qfunction_key;
 Lisp_Object Qmouse_click;
 #ifdef HAVE_NTGUI
 Lisp_Object Qlanguage_change;
 Lisp_Object Qmouse_click;
 #ifdef HAVE_NTGUI
 Lisp_Object Qlanguage_change;
-#ifdef WINDOWSNT
-Lisp_Object Qfile_w32notify;
-#endif
 #endif
 static Lisp_Object Qdrag_n_drop;
 static Lisp_Object Qsave_session;
 #ifdef HAVE_DBUS
 static Lisp_Object Qdbus_event;
 #endif
 #endif
 static Lisp_Object Qdrag_n_drop;
 static Lisp_Object Qsave_session;
 #ifdef HAVE_DBUS
 static Lisp_Object Qdbus_event;
 #endif
-#ifdef HAVE_INOTIFY
-static Lisp_Object Qfile_inotify;
-#endif /* HAVE_INOTIFY */
+#ifdef USE_FILE_NOTIFY
+static Lisp_Object Qfile_notify;
+#endif /* USE_FILE_NOTIFY */
 static Lisp_Object Qconfig_changed_event;
 
 /* Lisp_Object Qmouse_movement; - also an event header */
 static Lisp_Object Qconfig_changed_event;
 
 /* Lisp_Object Qmouse_movement; - also an event header */
@@ -365,10 +357,10 @@ Lisp_Object Qvertical_line;
 static Lisp_Object Qvertical_scroll_bar;
 Lisp_Object Qmenu_bar;
 
 static Lisp_Object Qvertical_scroll_bar;
 Lisp_Object Qmenu_bar;
 
-static Lisp_Object recursive_edit_unwind (Lisp_Object buffer);
+static void recursive_edit_unwind (Lisp_Object buffer);
 static Lisp_Object command_loop (void);
 static Lisp_Object Qcommand_execute;
 static Lisp_Object command_loop (void);
 static Lisp_Object Qcommand_execute;
-EMACS_TIME timer_check (void);
+struct timespec timer_check (void);
 
 static void echo_now (void);
 static ptrdiff_t echo_length (void);
 
 static void echo_now (void);
 static ptrdiff_t echo_length (void);
@@ -378,9 +370,9 @@ static Lisp_Object Qpolling_period;
 /* Incremented whenever a timer is run.  */
 unsigned timers_run;
 
 /* Incremented whenever a timer is run.  */
 unsigned timers_run;
 
-/* Address (if not 0) of EMACS_TIME to zero out if a SIGIO interrupt
+/* Address (if not 0) of struct timespec to zero out if a SIGIO interrupt
    happens.  */
    happens.  */
-EMACS_TIME *input_available_clear_time;
+struct timespec *input_available_clear_time;
 
 /* True means use SIGIO interrupts; false means use CBREAK mode.
    Default is true if INTERRUPT_INPUT is defined.  */
 
 /* True means use SIGIO interrupts; false means use CBREAK mode.
    Default is true if INTERRUPT_INPUT is defined.  */
@@ -397,12 +389,12 @@ bool interrupts_deferred;
 
 /* The time when Emacs started being idle.  */
 
 
 /* The time when Emacs started being idle.  */
 
-static EMACS_TIME timer_idleness_start_time;
+static struct timespec timer_idleness_start_time;
 
 /* After Emacs stops being idle, this saves the last value
    of timer_idleness_start_time from when it was idle.  */
 
 
 /* After Emacs stops being idle, this saves the last value
    of timer_idleness_start_time from when it was idle.  */
 
-static EMACS_TIME timer_last_idleness_start_time;
+static struct timespec timer_last_idleness_start_time;
 
 \f
 /* Global variable declarations.  */
 
 \f
 /* Global variable declarations.  */
@@ -429,12 +421,16 @@ static Lisp_Object modify_event_symbol (ptrdiff_t, int, Lisp_Object,
                                         Lisp_Object, const char *const *,
                                         Lisp_Object *, ptrdiff_t);
 static Lisp_Object make_lispy_switch_frame (Lisp_Object);
                                         Lisp_Object, const char *const *,
                                         Lisp_Object *, ptrdiff_t);
 static Lisp_Object make_lispy_switch_frame (Lisp_Object);
+static Lisp_Object make_lispy_focus_in (Lisp_Object);
+#ifdef HAVE_WINDOW_SYSTEM
+static Lisp_Object make_lispy_focus_out (Lisp_Object);
+#endif /* HAVE_WINDOW_SYSTEM */
 static bool help_char_p (Lisp_Object);
 static void save_getcjmp (sys_jmp_buf);
 static void restore_getcjmp (sys_jmp_buf);
 static Lisp_Object apply_modifiers (int, Lisp_Object);
 static void clear_event (struct input_event *);
 static bool help_char_p (Lisp_Object);
 static void save_getcjmp (sys_jmp_buf);
 static void restore_getcjmp (sys_jmp_buf);
 static Lisp_Object apply_modifiers (int, Lisp_Object);
 static void clear_event (struct input_event *);
-static Lisp_Object restore_kboard_configuration (Lisp_Object);
+static void restore_kboard_configuration (int);
 #ifdef USABLE_SIGIO
 static void deliver_input_available_signal (int signo);
 #endif
 #ifdef USABLE_SIGIO
 static void deliver_input_available_signal (int signo);
 #endif
@@ -833,7 +829,7 @@ This function is called by the editor initialization to begin editing.  */)
   update_mode_lines = 1;
 
   if (command_loop_level
   update_mode_lines = 1;
 
   if (command_loop_level
-      && current_buffer != XBUFFER (XWINDOW (selected_window)->buffer))
+      && current_buffer != XBUFFER (XWINDOW (selected_window)->contents))
     buffer = Fcurrent_buffer ();
   else
     buffer = Qnil;
     buffer = Fcurrent_buffer ();
   else
     buffer = Qnil;
@@ -850,7 +846,7 @@ This function is called by the editor initialization to begin editing.  */)
   return unbind_to (count, Qnil);
 }
 
   return unbind_to (count, Qnil);
 }
 
-Lisp_Object
+void
 recursive_edit_unwind (Lisp_Object buffer)
 {
   if (BUFFERP (buffer))
 recursive_edit_unwind (Lisp_Object buffer)
 {
   if (BUFFERP (buffer))
@@ -858,7 +854,6 @@ recursive_edit_unwind (Lisp_Object buffer)
 
   command_loop_level--;
   update_mode_lines = 1;
 
   command_loop_level--;
   update_mode_lines = 1;
-  return Qnil;
 }
 
 \f
 }
 
 \f
@@ -955,7 +950,7 @@ pop_kboard (void)
   from which further input is accepted.  If F is non-nil, set its
   KBOARD as the current keyboard.
 
   from which further input is accepted.  If F is non-nil, set its
   KBOARD as the current keyboard.
 
-  This function uses record_unwind_protect to return to the previous
+  This function uses record_unwind_protect_int to return to the previous
   state later.
 
   If Emacs is already in single_kboard mode, and F's keyboard is
   state later.
 
   If Emacs is already in single_kboard mode, and F's keyboard is
@@ -986,8 +981,7 @@ temporarily_switch_to_single_kboard (struct frame *f)
   else if (f != NULL)
     current_kboard = FRAME_KBOARD (f);
   single_kboard = 1;
   else if (f != NULL)
     current_kboard = FRAME_KBOARD (f);
   single_kboard = 1;
-  record_unwind_protect (restore_kboard_configuration,
-                         (was_locked ? Qt : Qnil));
+  record_unwind_protect_int (restore_kboard_configuration, was_locked);
 }
 
 #if 0 /* This function is not needed anymore.  */
 }
 
 #if 0 /* This function is not needed anymore.  */
@@ -996,26 +990,22 @@ record_single_kboard_state ()
 {
   if (single_kboard)
     push_kboard (current_kboard);
 {
   if (single_kboard)
     push_kboard (current_kboard);
-  record_unwind_protect (restore_kboard_configuration,
-                         (single_kboard ? Qt : Qnil));
+  record_unwind_protect_int (restore_kboard_configuration, single_kboard);
 }
 #endif
 
 }
 #endif
 
-static Lisp_Object
-restore_kboard_configuration (Lisp_Object was_locked)
+static void
+restore_kboard_configuration (int was_locked)
 {
 {
-  if (NILP (was_locked))
-    single_kboard = 0;
-  else
+  single_kboard = was_locked;
+  if (was_locked)
     {
       struct kboard *prev = current_kboard;
     {
       struct kboard *prev = current_kboard;
-      single_kboard = 1;
       pop_kboard ();
       /* The pop should not change the kboard.  */
       if (single_kboard && current_kboard != prev)
         emacs_abort ();
     }
       pop_kboard ();
       /* The pop should not change the kboard.  */
       if (single_kboard && current_kboard != prev)
         emacs_abort ();
     }
-  return Qnil;
 }
 
 \f
 }
 
 \f
@@ -1243,7 +1233,7 @@ DEFUN ("abort-recursive-edit", Fabort_recursive_edit, Sabort_recursive_edit, 0,
 /* Restore mouse tracking enablement.  See Ftrack_mouse for the only use
    of this function.  */
 
 /* Restore mouse tracking enablement.  See Ftrack_mouse for the only use
    of this function.  */
 
-static Lisp_Object
+static void
 tracking_off (Lisp_Object old_value)
 {
   do_mouse_tracking = old_value;
 tracking_off (Lisp_Object old_value)
 {
   do_mouse_tracking = old_value;
@@ -1260,7 +1250,6 @@ tracking_off (Lisp_Object old_value)
          get_input_pending (READABLE_EVENTS_DO_TIMERS_NOW);
        }
     }
          get_input_pending (READABLE_EVENTS_DO_TIMERS_NOW);
        }
     }
-  return Qnil;
 }
 
 DEFUN ("track-mouse", Ftrack_mouse, Strack_mouse, 0, UNEVALLED, 0,
 }
 
 DEFUN ("track-mouse", Ftrack_mouse, Strack_mouse, 0, UNEVALLED, 0,
@@ -1294,7 +1283,7 @@ static
 #endif
 bool ignore_mouse_drag_p;
 
 #endif
 bool ignore_mouse_drag_p;
 
-static FRAME_PTR
+static struct frame *
 some_mouse_moved (void)
 {
   Lisp_Object tail, frame;
 some_mouse_moved (void)
 {
   Lisp_Object tail, frame;
@@ -1323,17 +1312,6 @@ static int read_key_sequence (Lisp_Object *, int, Lisp_Object,
 void safe_run_hooks (Lisp_Object);
 static void adjust_point_for_property (ptrdiff_t, bool);
 
 void safe_run_hooks (Lisp_Object);
 static void adjust_point_for_property (ptrdiff_t, bool);
 
-/* Cancel hourglass from protect_unwind.
-   ARG is not used.  */
-#ifdef HAVE_WINDOW_SYSTEM
-static Lisp_Object
-cancel_hourglass_unwind (Lisp_Object arg)
-{
-  cancel_hourglass ();
-  return Qnil;
-}
-#endif
-
 /* The last boundary auto-added to buffer-undo-list.  */
 Lisp_Object last_undo_boundary;
 
 /* The last boundary auto-added to buffer-undo-list.  */
 Lisp_Object last_undo_boundary;
 
@@ -1395,7 +1373,7 @@ command_loop_1 (void)
        Fkill_emacs (Qnil);
 
       /* Make sure the current window's buffer is selected.  */
        Fkill_emacs (Qnil);
 
       /* Make sure the current window's buffer is selected.  */
-      set_buffer_internal (XBUFFER (XWINDOW (selected_window)->buffer));
+      set_buffer_internal (XBUFFER (XWINDOW (selected_window)->contents));
 
       /* Display any malloc warning that just came out.  Use while because
         displaying one warning can cause another.  */
 
       /* Display any malloc warning that just came out.  Use while because
         displaying one warning can cause another.  */
@@ -1436,7 +1414,7 @@ command_loop_1 (void)
          if (!NILP (Vquit_flag))
            {
              Vquit_flag = Qnil;
          if (!NILP (Vquit_flag))
            {
              Vquit_flag = Qnil;
-             Vunread_command_events = Fcons (make_number (quit_char), Qnil);
+             Vunread_command_events = list1 (make_number (quit_char));
            }
        }
 
            }
        }
 
@@ -1461,7 +1439,7 @@ command_loop_1 (void)
       /* A filter may have run while we were reading the input.  */
       if (! FRAME_LIVE_P (XFRAME (selected_frame)))
        Fkill_emacs (Qnil);
       /* A filter may have run while we were reading the input.  */
       if (! FRAME_LIVE_P (XFRAME (selected_frame)))
        Fkill_emacs (Qnil);
-      set_buffer_internal (XBUFFER (XWINDOW (selected_window)->buffer));
+      set_buffer_internal (XBUFFER (XWINDOW (selected_window)->contents));
 
       ++num_input_keys;
 
 
       ++num_input_keys;
 
@@ -1492,7 +1470,7 @@ command_loop_1 (void)
        {
          struct buffer *b;
          XWINDOW (selected_window)->force_start = 0;
        {
          struct buffer *b;
          XWINDOW (selected_window)->force_start = 0;
-         b = XBUFFER (XWINDOW (selected_window)->buffer);
+         b = XBUFFER (XWINDOW (selected_window)->contents);
          BUF_BEG_UNCHANGED (b) = BUF_END_UNCHANGED (b) = 0;
        }
 
          BUF_BEG_UNCHANGED (b) = BUF_END_UNCHANGED (b) = 0;
        }
 
@@ -1512,8 +1490,6 @@ command_loop_1 (void)
       prev_buffer = current_buffer;
       prev_modiff = MODIFF;
       last_point_position = PT;
       prev_buffer = current_buffer;
       prev_modiff = MODIFF;
       last_point_position = PT;
-      last_point_position_window = selected_window;
-      XSETBUFFER (last_point_position_buffer, prev_buffer);
 
       /* By default, we adjust point to a boundary of a region that
          has such a property that should be treated intangible
 
       /* By default, we adjust point to a boundary of a region that
          has such a property that should be treated intangible
@@ -1570,7 +1546,7 @@ command_loop_1 (void)
             if (display_hourglass_p
                 && NILP (Vexecuting_kbd_macro))
               {
             if (display_hourglass_p
                 && NILP (Vexecuting_kbd_macro))
               {
-                record_unwind_protect (cancel_hourglass_unwind, Qnil);
+                record_unwind_protect_void (cancel_hourglass);
                 start_hourglass ();
               }
 #endif
                 start_hourglass ();
               }
 #endif
@@ -1893,7 +1869,7 @@ safe_run_hooks_error (Lisp_Object error_data)
     = CONSP (Vinhibit_quit) ? XCAR (Vinhibit_quit) : Vinhibit_quit;
   Lisp_Object fun = CONSP (Vinhibit_quit) ? XCDR (Vinhibit_quit) : Qnil;
   Lisp_Object args[4];
     = CONSP (Vinhibit_quit) ? XCAR (Vinhibit_quit) : Vinhibit_quit;
   Lisp_Object fun = CONSP (Vinhibit_quit) ? XCDR (Vinhibit_quit) : Qnil;
   Lisp_Object args[4];
-  args[0] = build_string ("Error in %s (%s): %S");
+  args[0] = build_string ("Error in %s (%S): %S");
   args[1] = hook;
   args[2] = fun;
   args[3] = error_data;
   args[1] = hook;
   args[2] = fun;
   args[3] = error_data;
@@ -2012,10 +1988,10 @@ start_polling (void)
       /* If poll timer doesn't exist, are we need one with
         a different interval, start a new one.  */
       if (poll_timer == NULL
       /* If poll timer doesn't exist, are we need one with
         a different interval, start a new one.  */
       if (poll_timer == NULL
-         || EMACS_SECS (poll_timer->interval) != polling_period)
+         || poll_timer->interval.tv_sec != polling_period)
        {
          time_t period = max (1, min (polling_period, TYPE_MAXIMUM (time_t)));
        {
          time_t period = max (1, min (polling_period, TYPE_MAXIMUM (time_t)));
-         EMACS_TIME interval = make_emacs_time (period, 0);
+         struct timespec interval = make_timespec (period, 0);
 
          if (poll_timer)
            cancel_atimer (poll_timer);
 
          if (poll_timer)
            cancel_atimer (poll_timer);
@@ -2189,7 +2165,7 @@ show_help_echo (Lisp_Object help, Lisp_Object window, Lisp_Object object,
         This causes trouble if we are trying to read a mouse motion
         event (i.e., if we are inside a `track-mouse' form), so we
         restore the mouse_moved flag.  */
         This causes trouble if we are trying to read a mouse motion
         event (i.e., if we are inside a `track-mouse' form), so we
         restore the mouse_moved flag.  */
-      FRAME_PTR f = NILP (do_mouse_tracking) ? NULL : some_mouse_moved ();
+      struct frame *f = NILP (do_mouse_tracking) ? NULL : some_mouse_moved ();
       help = call1 (Qmouse_fixup_help_message, help);
       if (f)
        f->mouse_moved = 1;
       help = call1 (Qmouse_fixup_help_message, help);
       if (f)
        f->mouse_moved = 1;
@@ -2208,18 +2184,17 @@ show_help_echo (Lisp_Object help, Lisp_Object window, Lisp_Object object,
 /* Input of single characters from keyboard */
 
 static Lisp_Object kbd_buffer_get_event (KBOARD **kbp, bool *used_mouse_menu,
 /* Input of single characters from keyboard */
 
 static Lisp_Object kbd_buffer_get_event (KBOARD **kbp, bool *used_mouse_menu,
-                                        EMACS_TIME *end_time);
+                                        struct timespec *end_time);
 static void record_char (Lisp_Object c);
 
 static Lisp_Object help_form_saved_window_configs;
 static void record_char (Lisp_Object c);
 
 static Lisp_Object help_form_saved_window_configs;
-static Lisp_Object
-read_char_help_form_unwind (Lisp_Object arg)
+static void
+read_char_help_form_unwind (void)
 {
   Lisp_Object window_config = XCAR (help_form_saved_window_configs);
   help_form_saved_window_configs = XCDR (help_form_saved_window_configs);
   if (!NILP (window_config))
     Fset_window_configuration (window_config);
 {
   Lisp_Object window_config = XCAR (help_form_saved_window_configs);
   help_form_saved_window_configs = XCDR (help_form_saved_window_configs);
   if (!NILP (window_config))
     Fset_window_configuration (window_config);
-  return Qnil;
 }
 
 #define STOP_POLLING                                   \
 }
 
 #define STOP_POLLING                                   \
@@ -2230,6 +2205,159 @@ do { if (! polling_stopped_here) stop_polling ();       \
 do { if (polling_stopped_here) start_polling ();       \
        polling_stopped_here = 0; } while (0)
 
 do { if (polling_stopped_here) start_polling ();       \
        polling_stopped_here = 0; } while (0)
 
+static Lisp_Object
+read_event_from_main_queue (struct timespec *end_time,
+                            sys_jmp_buf local_getcjmp,
+                            bool *used_mouse_menu)
+{
+  Lisp_Object c = Qnil;
+  sys_jmp_buf save_jump;
+  KBOARD *kb IF_LINT (= NULL);
+
+ start:
+
+  /* Read from the main queue, and if that gives us something we can't use yet,
+     we put it on the appropriate side queue and try again.  */
+
+  if (end_time && timespec_cmp (*end_time, current_timespec ()) <= 0)
+    return c;
+
+  /* Actually read a character, waiting if necessary.  */
+  save_getcjmp (save_jump);
+  restore_getcjmp (local_getcjmp);
+  if (!end_time)
+       timer_start_idle ();
+  c = kbd_buffer_get_event (&kb, used_mouse_menu, end_time);
+  restore_getcjmp (save_jump);
+
+  if (! NILP (c) && (kb != current_kboard))
+    {
+      Lisp_Object last = KVAR (kb, kbd_queue);
+      if (CONSP (last))
+        {
+          while (CONSP (XCDR (last)))
+       last = XCDR (last);
+          if (!NILP (XCDR (last)))
+       emacs_abort ();
+        }
+      if (!CONSP (last))
+        kset_kbd_queue (kb, list1 (c));
+      else
+        XSETCDR (last, list1 (c));
+      kb->kbd_queue_has_data = 1;
+      c = Qnil;
+      if (single_kboard)
+        goto start;
+      current_kboard = kb;
+      /* This is going to exit from read_char
+         so we had better get rid of this frame's stuff.  */
+      return make_number (-2);
+    }
+
+  /* Terminate Emacs in batch mode if at eof.  */
+  if (noninteractive && INTEGERP (c) && XINT (c) < 0)
+    Fkill_emacs (make_number (1));
+
+  if (INTEGERP (c))
+    {
+      /* Add in any extra modifiers, where appropriate.  */
+      if ((extra_keyboard_modifiers & CHAR_CTL)
+         || ((extra_keyboard_modifiers & 0177) < ' '
+             && (extra_keyboard_modifiers & 0177) != 0))
+       XSETINT (c, make_ctrl_char (XINT (c)));
+
+      /* Transfer any other modifier bits directly from
+        extra_keyboard_modifiers to c.  Ignore the actual character code
+        in the low 16 bits of extra_keyboard_modifiers.  */
+      XSETINT (c, XINT (c) | (extra_keyboard_modifiers & ~0xff7f & ~CHAR_CTL));
+    }
+
+  return c;
+}
+
+
+
+/* Like `read_event_from_main_queue' but applies keyboard-coding-system
+   to tty input.  */
+static Lisp_Object
+read_decoded_event_from_main_queue (struct timespec *end_time,
+                                    sys_jmp_buf local_getcjmp,
+                                    Lisp_Object prev_event,
+                                    bool *used_mouse_menu)
+{
+#define MAX_ENCODED_BYTES 16
+  Lisp_Object events[MAX_ENCODED_BYTES];
+  int n = 0;
+  while (true)
+    {
+      Lisp_Object nextevt
+        = read_event_from_main_queue (end_time, local_getcjmp,
+                                      used_mouse_menu);
+#ifdef WINDOWSNT
+      /* w32_console already returns decoded events.  It either reads
+        Unicode characters from the Windows keyboard input, or
+        converts characters encoded in the current codepage into
+        Unicode.  See w32inevt.c:key_event, near its end.  */
+      return nextevt;
+#else
+      struct frame *frame = XFRAME (selected_frame);
+      struct terminal *terminal = frame->terminal;
+      if (!((FRAME_TERMCAP_P (frame) || FRAME_MSDOS_P (frame))
+            /* Don't apply decoding if we're just reading a raw event
+               (e.g. reading bytes sent by the xterm to specify the position
+               of a mouse click).  */
+            && (!EQ (prev_event, Qt))
+           && (TERMINAL_KEYBOARD_CODING (terminal)->common_flags
+               & CODING_REQUIRE_DECODING_MASK)))
+       return nextevt;         /* No decoding needed.  */
+      else
+       {
+         int meta_key = terminal->display_info.tty->meta_key;
+         eassert (n < MAX_ENCODED_BYTES);
+         events[n++] = nextevt;
+         if (NATNUMP (nextevt)
+             && XINT (nextevt) < (meta_key == 1 ? 0x80 : 0x100))
+           { /* An encoded byte sequence, let's try to decode it.  */
+             struct coding_system *coding
+               = TERMINAL_KEYBOARD_CODING (terminal);
+             unsigned char *src = alloca (n);
+             int i;
+             for (i = 0; i < n; i++)
+               src[i] = XINT (events[i]);
+             if (meta_key != 2)
+               for (i = 0; i < n; i++)
+                 src[i] &= ~0x80;
+             coding->destination = alloca (n * 4);
+             coding->dst_bytes = n * 4;
+             decode_coding_c_string (coding, src, n, Qnil);
+             eassert (coding->produced_char <= n);
+             if (coding->produced_char == 0)
+               { /* The encoded sequence is incomplete.  */
+                 if (n < MAX_ENCODED_BYTES) /* Avoid buffer overflow.  */
+                   continue;                /* Read on!  */
+               }
+             else
+               {
+                 const unsigned char *p = coding->destination;
+                 eassert (coding->carryover_bytes == 0);
+                 n = 0;
+                 while (n < coding->produced_char)
+                   events[n++] = make_number (STRING_CHAR_ADVANCE (p));
+               }
+           }
+         /* Now `events' should hold decoded events.
+            Normally, n should be equal to 1, but better not rely on it.
+            We can only return one event here, so return the first we
+            had and keep the others (if any) for later.  */
+         while (n > 1)
+           Vunread_command_events
+             = Fcons (events[--n], Vunread_command_events);
+         return events[0];
+       }
+#endif
+    }
+}
+
 /* Read a character from the keyboard; call the redisplay if needed.  */
 /* commandflag 0 means do not autosave, but do redisplay.
    -1 means do not redisplay, but do autosave.
 /* Read a character from the keyboard; call the redisplay if needed.  */
 /* commandflag 0 means do not autosave, but do redisplay.
    -1 means do not redisplay, but do autosave.
@@ -2250,7 +2378,7 @@ do { if (polling_stopped_here) start_polling ();  \
    Value is -2 when we find input on another keyboard.  A second call
    to read_char will read it.
 
    Value is -2 when we find input on another keyboard.  A second call
    to read_char will read it.
 
-   If END_TIME is non-null, it is a pointer to an EMACS_TIME
+   If END_TIME is non-null, it is a pointer to a struct timespec
    specifying the maximum time to wait until.  If no input arrives by
    that time, stop waiting and return nil.
 
    specifying the maximum time to wait until.  If no input arrives by
    that time, stop waiting and return nil.
 
@@ -2259,7 +2387,7 @@ do { if (polling_stopped_here) start_polling ();  \
 Lisp_Object
 read_char (int commandflag, Lisp_Object map,
           Lisp_Object prev_event,
 Lisp_Object
 read_char (int commandflag, Lisp_Object map,
           Lisp_Object prev_event,
-          bool *used_mouse_menu, EMACS_TIME *end_time)
+          bool *used_mouse_menu, struct timespec *end_time)
 {
   Lisp_Object c;
   ptrdiff_t jmpcount;
 {
   Lisp_Object c;
   ptrdiff_t jmpcount;
@@ -2468,10 +2596,8 @@ read_char (int commandflag, Lisp_Object map,
 
   if (/* There currently is something in the echo area.  */
       !NILP (echo_area_buffer[0])
 
   if (/* There currently is something in the echo area.  */
       !NILP (echo_area_buffer[0])
-      && (/* And it's either not from echoing.  */
-         !EQ (echo_area_buffer[0], echo_message_buffer)
-         /* Or it's an echo from a different kboard.  */
-         || echo_kboard != current_kboard
+      && (/* It's an echo from a different kboard.  */
+         echo_kboard != current_kboard
          /* Or we explicitly allow overwriting whatever there is.  */
          || ok_to_echo_at_next_pause == NULL))
     cancel_echoing ();
          /* Or we explicitly allow overwriting whatever there is.  */
          || ok_to_echo_at_next_pause == NULL))
     cancel_echoing ();
@@ -2537,9 +2663,9 @@ read_char (int commandflag, Lisp_Object map,
                  emacs_abort ();
              }
            if (!CONSP (last))
                  emacs_abort ();
              }
            if (!CONSP (last))
-             kset_kbd_queue (kb, Fcons (c, Qnil));
+             kset_kbd_queue (kb, list1 (c));
            else
            else
-             XSETCDR (last, Fcons (c, Qnil));
+             XSETCDR (last, list1 (c));
            kb->kbd_queue_has_data = 1;
            current_kboard = kb;
            /* This is going to exit from read_char
            kb->kbd_queue_has_data = 1;
            current_kboard = kb;
            /* This is going to exit from read_char
@@ -2747,68 +2873,20 @@ read_char (int commandflag, Lisp_Object map,
 
   STOP_POLLING;
 
 
   STOP_POLLING;
 
-  /* Finally, we read from the main queue,
-     and if that gives us something we can't use yet, we put it on the
-     appropriate side queue and try again.  */
-
   if (NILP (c))
     {
   if (NILP (c))
     {
-      KBOARD *kb IF_LINT (= NULL);
-
-      if (end_time && EMACS_TIME_LE (*end_time, current_emacs_time ()))
-       goto exit;
-
-      /* Actually read a character, waiting if necessary.  */
-      save_getcjmp (save_jump);
-      restore_getcjmp (local_getcjmp);
-      if (!end_time)
-       timer_start_idle ();
-      c = kbd_buffer_get_event (&kb, used_mouse_menu, end_time);
-      restore_getcjmp (save_jump);
-
-      if (! NILP (c) && (kb != current_kboard))
-       {
-         Lisp_Object last = KVAR (kb, kbd_queue);
-         if (CONSP (last))
-           {
-             while (CONSP (XCDR (last)))
-               last = XCDR (last);
-             if (!NILP (XCDR (last)))
-               emacs_abort ();
-           }
-         if (!CONSP (last))
-           kset_kbd_queue (kb, Fcons (c, Qnil));
-         else
-           XSETCDR (last, Fcons (c, Qnil));
-         kb->kbd_queue_has_data = 1;
-         c = Qnil;
-         if (single_kboard)
-           goto wrong_kboard;
-         current_kboard = kb;
+      c = read_decoded_event_from_main_queue (end_time, local_getcjmp,
+                                              prev_event, used_mouse_menu);
+      if (end_time && timespec_cmp (*end_time, current_timespec ()) <= 0)
+        goto exit;
+      if (EQ (c, make_number (-2)))
+        {
          /* This is going to exit from read_char
             so we had better get rid of this frame's stuff.  */
          UNGCPRO;
          /* This is going to exit from read_char
             so we had better get rid of this frame's stuff.  */
          UNGCPRO;
-          return make_number (-2);
-       }
-    }
-
-  /* Terminate Emacs in batch mode if at eof.  */
-  if (noninteractive && INTEGERP (c) && XINT (c) < 0)
-    Fkill_emacs (make_number (1));
-
-  if (INTEGERP (c))
-    {
-      /* Add in any extra modifiers, where appropriate.  */
-      if ((extra_keyboard_modifiers & CHAR_CTL)
-         || ((extra_keyboard_modifiers & 0177) < ' '
-             && (extra_keyboard_modifiers & 0177) != 0))
-       XSETINT (c, make_ctrl_char (XINT (c)));
-
-      /* Transfer any other modifier bits directly from
-        extra_keyboard_modifiers to c.  Ignore the actual character code
-        in the low 16 bits of extra_keyboard_modifiers.  */
-      XSETINT (c, XINT (c) | (extra_keyboard_modifiers & ~0xff7f & ~CHAR_CTL));
-    }
+          return c;
+        }
+  }
 
  non_reread:
 
 
  non_reread:
 
@@ -2905,7 +2983,7 @@ read_char (int commandflag, Lisp_Object map,
       if (EQ (posn, Qmenu_bar) || EQ (posn, Qtool_bar))
        {
          /* Change menu-bar to (menu-bar) as the event "position".  */
       if (EQ (posn, Qmenu_bar) || EQ (posn, Qtool_bar))
        {
          /* Change menu-bar to (menu-bar) as the event "position".  */
-         POSN_SET_POSN (EVENT_START (c), Fcons (posn, Qnil));
+         POSN_SET_POSN (EVENT_START (c), list1 (posn));
 
          also_record = c;
          Vunread_command_events = Fcons (c, Vunread_command_events);
 
          also_record = c;
          Vunread_command_events = Fcons (c, Vunread_command_events);
@@ -3102,7 +3180,7 @@ read_char (int commandflag, Lisp_Object map,
       help_form_saved_window_configs
        = Fcons (Fcurrent_window_configuration (Qnil),
                 help_form_saved_window_configs);
       help_form_saved_window_configs
        = Fcons (Fcurrent_window_configuration (Qnil),
                 help_form_saved_window_configs);
-      record_unwind_protect (read_char_help_form_unwind, Qnil);
+      record_unwind_protect_void (read_char_help_form_unwind);
       call0 (Qhelp_form_show);
 
       cancel_echoing ();
       call0 (Qhelp_form_show);
 
       cancel_echoing ();
@@ -3132,6 +3210,8 @@ read_char (int commandflag, Lisp_Object map,
   RETURN_UNGCPRO (c);
 }
 
   RETURN_UNGCPRO (c);
 }
 
+#ifdef HAVE_MENUS
+
 /* Record a key that came from a mouse menu.
    Record it for echoing, for this-command-keys, and so on.  */
 
 /* Record a key that came from a mouse menu.
    Record it for echoing, for this-command-keys, and so on.  */
 
@@ -3167,6 +3247,8 @@ record_menu_key (Lisp_Object c)
   num_input_events++;
 }
 
   num_input_events++;
 }
 
+#endif /* HAVE_MENUS */
+
 /* Return true if should recognize C as "the help character".  */
 
 static bool
 /* Return true if should recognize C as "the help character".  */
 
 static bool
@@ -3488,8 +3570,8 @@ kbd_buffer_store_event_hold (register struct input_event *event,
          if (single_kboard && kb != current_kboard)
            {
              kset_kbd_queue
          if (single_kboard && kb != current_kboard)
            {
              kset_kbd_queue
-               (kb, Fcons (make_lispy_switch_frame (event->frame_or_window),
-                           Fcons (make_number (c), Qnil)));
+               (kb, list2 (make_lispy_switch_frame (event->frame_or_window),
+                           make_number (c)));
              kb->kbd_queue_has_data = 1;
              for (sp = kbd_fetch_ptr; sp != kbd_store_ptr; sp++)
                {
              kb->kbd_queue_has_data = 1;
              for (sp = kbd_fetch_ptr; sp != kbd_store_ptr; sp++)
                {
@@ -3720,7 +3802,7 @@ clear_event (struct input_event *event)
 static Lisp_Object
 kbd_buffer_get_event (KBOARD **kbp,
                       bool *used_mouse_menu,
 static Lisp_Object
 kbd_buffer_get_event (KBOARD **kbp,
                       bool *used_mouse_menu,
-                      EMACS_TIME *end_time)
+                      struct timespec *end_time)
 {
   Lisp_Object obj;
 
 {
   Lisp_Object obj;
 
@@ -3778,15 +3860,15 @@ kbd_buffer_get_event (KBOARD **kbp,
        break;
       if (end_time)
        {
        break;
       if (end_time)
        {
-         EMACS_TIME now = current_emacs_time ();
-         if (EMACS_TIME_LE (*end_time, now))
+         struct timespec now = current_timespec ();
+         if (timespec_cmp (*end_time, now) <= 0)
            return Qnil;        /* Finished waiting.  */
          else
            {
            return Qnil;        /* Finished waiting.  */
          else
            {
-             EMACS_TIME duration = sub_emacs_time (*end_time, now);
-             wait_reading_process_output (min (EMACS_SECS (duration),
+             struct timespec duration = timespec_sub (*end_time, now);
+             wait_reading_process_output (min (duration.tv_sec,
                                                WAIT_READING_MAX),
                                                WAIT_READING_MAX),
-                                          EMACS_NSECS (duration),
+                                          duration.tv_nsec,
                                           -1, 1, Qnil, NULL, 0);
            }
        }
                                           -1, 1, Qnil, NULL, 0);
            }
        }
@@ -3852,9 +3934,9 @@ kbd_buffer_get_event (KBOARD **kbp,
       else if (event->kind == NS_TEXT_EVENT)
         {
           if (event->code == KEY_NS_PUT_WORKING_TEXT)
       else if (event->kind == NS_TEXT_EVENT)
         {
           if (event->code == KEY_NS_PUT_WORKING_TEXT)
-            obj = Fcons (intern ("ns-put-working-text"), Qnil);
+            obj = list1 (intern ("ns-put-working-text"));
           else
           else
-            obj = Fcons (intern ("ns-unput-working-text"), Qnil);
+            obj = list1 (intern ("ns-unput-working-text"));
          kbd_fetch_ptr = event + 1;
           if (used_mouse_menu)
             *used_mouse_menu = 1;
          kbd_fetch_ptr = event + 1;
           if (used_mouse_menu)
             *used_mouse_menu = 1;
@@ -3866,8 +3948,7 @@ kbd_buffer_get_event (KBOARD **kbp,
       else if (event->kind == DELETE_WINDOW_EVENT)
        {
          /* Make an event (delete-frame (FRAME)).  */
       else if (event->kind == DELETE_WINDOW_EVENT)
        {
          /* Make an event (delete-frame (FRAME)).  */
-         obj = Fcons (event->frame_or_window, Qnil);
-         obj = Fcons (Qdelete_frame, Fcons (obj, Qnil));
+         obj = list2 (Qdelete_frame, list1 (event->frame_or_window));
          kbd_fetch_ptr = event + 1;
        }
 #endif
          kbd_fetch_ptr = event + 1;
        }
 #endif
@@ -3876,15 +3957,13 @@ kbd_buffer_get_event (KBOARD **kbp,
       else if (event->kind == ICONIFY_EVENT)
        {
          /* Make an event (iconify-frame (FRAME)).  */
       else if (event->kind == ICONIFY_EVENT)
        {
          /* Make an event (iconify-frame (FRAME)).  */
-         obj = Fcons (event->frame_or_window, Qnil);
-         obj = Fcons (Qiconify_frame, Fcons (obj, Qnil));
+         obj = list2 (Qiconify_frame, list1 (event->frame_or_window));
          kbd_fetch_ptr = event + 1;
        }
       else if (event->kind == DEICONIFY_EVENT)
        {
          /* Make an event (make-frame-visible (FRAME)).  */
          kbd_fetch_ptr = event + 1;
        }
       else if (event->kind == DEICONIFY_EVENT)
        {
          /* Make an event (make-frame-visible (FRAME)).  */
-         obj = Fcons (event->frame_or_window, Qnil);
-         obj = Fcons (Qmake_frame_visible, Fcons (obj, Qnil));
+         obj = list2 (Qmake_frame_visible, list1 (event->frame_or_window));
          kbd_fetch_ptr = event + 1;
        }
 #endif
          kbd_fetch_ptr = event + 1;
        }
 #endif
@@ -3907,29 +3986,33 @@ kbd_buffer_get_event (KBOARD **kbp,
 #ifdef HAVE_NTGUI
       else if (event->kind == LANGUAGE_CHANGE_EVENT)
        {
 #ifdef HAVE_NTGUI
       else if (event->kind == LANGUAGE_CHANGE_EVENT)
        {
-         /* Make an event (language-change (FRAME CODEPAGE LANGUAGE-ID)).  */
-         obj = Fcons (Qlanguage_change,
-                      list3 (event->frame_or_window,
-                             make_number (event->code),
-                             make_number (event->modifiers)));
+         /* Make an event (language-change FRAME CODEPAGE LANGUAGE-ID).  */
+         obj = list4 (Qlanguage_change,
+                      event->frame_or_window,
+                      make_number (event->code),
+                      make_number (event->modifiers));
          kbd_fetch_ptr = event + 1;
        }
 #endif
          kbd_fetch_ptr = event + 1;
        }
 #endif
-#ifdef WINDOWSNT
+#ifdef USE_FILE_NOTIFY
       else if (event->kind == FILE_NOTIFY_EVENT)
        {
       else if (event->kind == FILE_NOTIFY_EVENT)
        {
+#ifdef HAVE_W32NOTIFY
          /* Make an event (file-notify (DESCRIPTOR ACTION FILE) CALLBACK).  */
          /* Make an event (file-notify (DESCRIPTOR ACTION FILE) CALLBACK).  */
-         obj = Fcons (Qfile_w32notify,
-                      list2 (list3 (make_number (event->code),
-                                    XCAR (event->arg),
-                                    XCDR (event->arg)),
-                             event->frame_or_window));
+         obj = list3 (Qfile_notify,
+                      list3 (make_number (event->code),
+                             XCAR (event->arg),
+                             XCDR (event->arg)),
+                      event->frame_or_window);
+#else
+          obj = make_lispy_event (event);
+#endif
          kbd_fetch_ptr = event + 1;
        }
          kbd_fetch_ptr = event + 1;
        }
-#endif
+#endif /* USE_FILE_NOTIFY */
       else if (event->kind == SAVE_SESSION_EVENT)
         {
       else if (event->kind == SAVE_SESSION_EVENT)
         {
-          obj = Fcons (Qsave_session, Fcons (event->arg, Qnil));
+          obj = list2 (Qsave_session, event->arg);
          kbd_fetch_ptr = event + 1;
         }
       /* Just discard these, by returning nil.
          kbd_fetch_ptr = event + 1;
         }
       /* Just discard these, by returning nil.
@@ -3966,30 +4049,49 @@ kbd_buffer_get_event (KBOARD **kbp,
             switch-frame event if necessary.  */
          Lisp_Object frame, focus;
 
             switch-frame event if necessary.  */
          Lisp_Object frame, focus;
 
-         frame = event->frame_or_window;
-         focus = FRAME_FOCUS_FRAME (XFRAME (frame));
-         if (FRAMEP (focus))
-           frame = focus;
+          frame = event->frame_or_window;
+          focus = FRAME_FOCUS_FRAME (XFRAME (frame));
+          if (FRAMEP (focus))
+            frame = focus;
 
 
-         if (!EQ (frame, internal_last_event_frame)
-             && !EQ (frame, selected_frame))
-           obj = make_lispy_switch_frame (frame);
-         internal_last_event_frame = frame;
-         kbd_fetch_ptr = event + 1;
-       }
+          if (
+#ifdef HAVE_X11
+              ! NILP (event->arg)
+              &&
+#endif
+              !EQ (frame, internal_last_event_frame)
+              && !EQ (frame, selected_frame))
+            obj = make_lispy_switch_frame (frame);
+          else
+            obj = make_lispy_focus_in (frame);
+
+          internal_last_event_frame = frame;
+          kbd_fetch_ptr = event + 1;
+        }
+      else if (event->kind == FOCUS_OUT_EVENT)
+        {
+#ifdef HAVE_WINDOW_SYSTEM
+
+          Display_Info *di;
+          Lisp_Object frame = event->frame_or_window;
+          bool focused = false;
+
+          for (di = x_display_list; di && ! focused; di = di->next)
+            focused = di->x_highlight_frame != 0;
+
+          if (!focused)
+           obj = make_lispy_focus_out (frame);
+
+#endif /* HAVE_WINDOW_SYSTEM */
+
+          kbd_fetch_ptr = event + 1;
+        }
 #ifdef HAVE_DBUS
       else if (event->kind == DBUS_EVENT)
        {
          obj = make_lispy_event (event);
          kbd_fetch_ptr = event + 1;
        }
 #ifdef HAVE_DBUS
       else if (event->kind == DBUS_EVENT)
        {
          obj = make_lispy_event (event);
          kbd_fetch_ptr = event + 1;
        }
-#endif
-#ifdef HAVE_INOTIFY
-      else if (event->kind == FILE_NOTIFY_EVENT)
-        {
-          obj = make_lispy_event (event);
-          kbd_fetch_ptr = event + 1;
-        }
 #endif
       else if (event->kind == CONFIG_CHANGED_EVENT)
        {
 #endif
       else if (event->kind == CONFIG_CHANGED_EVENT)
        {
@@ -4054,7 +4156,7 @@ kbd_buffer_get_event (KBOARD **kbp,
   /* Try generating a mouse motion event.  */
   else if (!NILP (do_mouse_tracking) && some_mouse_moved ())
     {
   /* Try generating a mouse motion event.  */
   else if (!NILP (do_mouse_tracking) && some_mouse_moved ())
     {
-      FRAME_PTR f = some_mouse_moved ();
+      struct frame *f = some_mouse_moved ();
       Lisp_Object bar_window;
       enum scroll_bar_part part;
       Lisp_Object x, y;
       Lisp_Object bar_window;
       enum scroll_bar_part part;
       Lisp_Object x, y;
@@ -4196,26 +4298,15 @@ swallow_events (bool do_display)
 static void
 timer_start_idle (void)
 {
 static void
 timer_start_idle (void)
 {
-  Lisp_Object timers;
-
   /* If we are already in the idle state, do nothing.  */
   /* If we are already in the idle state, do nothing.  */
-  if (EMACS_TIME_VALID_P (timer_idleness_start_time))
+  if (timespec_valid_p (timer_idleness_start_time))
     return;
 
     return;
 
-  timer_idleness_start_time = current_emacs_time ();
+  timer_idleness_start_time = current_timespec ();
   timer_last_idleness_start_time = timer_idleness_start_time;
 
   /* Mark all idle-time timers as once again candidates for running.  */
   timer_last_idleness_start_time = timer_idleness_start_time;
 
   /* Mark all idle-time timers as once again candidates for running.  */
-  for (timers = Vtimer_idle_list; CONSP (timers); timers = XCDR (timers))
-    {
-      Lisp_Object timer;
-
-      timer = XCAR (timers);
-
-      if (!VECTORP (timer) || ASIZE (timer) != 9)
-       continue;
-      ASET (timer, 0, Qnil);
-    }
+  call0 (intern ("internal-timer-start-idle"));
 }
 
 /* Record that Emacs is no longer idle, so stop running idle-time timers.  */
 }
 
 /* Record that Emacs is no longer idle, so stop running idle-time timers.  */
@@ -4223,7 +4314,7 @@ timer_start_idle (void)
 static void
 timer_stop_idle (void)
 {
 static void
 timer_stop_idle (void)
 {
-  timer_idleness_start_time = invalid_emacs_time ();
+  timer_idleness_start_time = invalid_timespec ();
 }
 
 /* Resume idle timer from last idle start time.  */
 }
 
 /* Resume idle timer from last idle start time.  */
@@ -4231,7 +4322,7 @@ timer_stop_idle (void)
 static void
 timer_resume_idle (void)
 {
 static void
 timer_resume_idle (void)
 {
-  if (EMACS_TIME_VALID_P (timer_idleness_start_time))
+  if (timespec_valid_p (timer_idleness_start_time))
     return;
 
   timer_idleness_start_time = timer_last_idleness_start_time;
     return;
 
   timer_idleness_start_time = timer_last_idleness_start_time;
@@ -4247,7 +4338,7 @@ Lisp_Object pending_funcalls;
 
 /* Return true if TIMER is a valid timer, placing its value into *RESULT.  */
 static bool
 
 /* Return true if TIMER is a valid timer, placing its value into *RESULT.  */
 static bool
-decode_timer (Lisp_Object timer, EMACS_TIME *result)
+decode_timer (Lisp_Object timer, struct timespec *result)
 {
   Lisp_Object *vector;
 
 {
   Lisp_Object *vector;
 
@@ -4274,16 +4365,16 @@ decode_timer (Lisp_Object timer, EMACS_TIME *result)
    In that case we return 0 to indicate that a new timer_check_2 call
    should be done.  */
 
    In that case we return 0 to indicate that a new timer_check_2 call
    should be done.  */
 
-static EMACS_TIME
+static struct timespec
 timer_check_2 (Lisp_Object timers, Lisp_Object idle_timers)
 {
 timer_check_2 (Lisp_Object timers, Lisp_Object idle_timers)
 {
-  EMACS_TIME nexttime;
-  EMACS_TIME now;
-  EMACS_TIME idleness_now;
+  struct timespec nexttime;
+  struct timespec now;
+  struct timespec idleness_now;
   Lisp_Object chosen_timer;
   struct gcpro gcpro1;
 
   Lisp_Object chosen_timer;
   struct gcpro gcpro1;
 
-  nexttime = invalid_emacs_time ();
+  nexttime = invalid_timespec ();
 
   chosen_timer = Qnil;
   GCPRO1 (chosen_timer);
 
   chosen_timer = Qnil;
   GCPRO1 (chosen_timer);
@@ -4298,19 +4389,19 @@ timer_check_2 (Lisp_Object timers, Lisp_Object idle_timers)
 
   if (CONSP (timers) || CONSP (idle_timers))
     {
 
   if (CONSP (timers) || CONSP (idle_timers))
     {
-      now = current_emacs_time ();
-      idleness_now = (EMACS_TIME_VALID_P (timer_idleness_start_time)
-                     ? sub_emacs_time (now, timer_idleness_start_time)
-                     : make_emacs_time (0, 0));
+      now = current_timespec ();
+      idleness_now = (timespec_valid_p (timer_idleness_start_time)
+                     ? timespec_sub (now, timer_idleness_start_time)
+                     : make_timespec (0, 0));
     }
 
   while (CONSP (timers) || CONSP (idle_timers))
     {
       Lisp_Object timer = Qnil, idle_timer = Qnil;
     }
 
   while (CONSP (timers) || CONSP (idle_timers))
     {
       Lisp_Object timer = Qnil, idle_timer = Qnil;
-      EMACS_TIME timer_time, idle_timer_time;
-      EMACS_TIME difference;
-      EMACS_TIME timer_difference = invalid_emacs_time ();
-      EMACS_TIME idle_timer_difference = invalid_emacs_time ();
+      struct timespec timer_time, idle_timer_time;
+      struct timespec difference;
+      struct timespec timer_difference = invalid_timespec ();
+      struct timespec idle_timer_difference = invalid_timespec ();
       bool ripe, timer_ripe = 0, idle_timer_ripe = 0;
 
       /* Set TIMER and TIMER_DIFFERENCE
       bool ripe, timer_ripe = 0, idle_timer_ripe = 0;
 
       /* Set TIMER and TIMER_DIFFERENCE
@@ -4327,10 +4418,10 @@ timer_check_2 (Lisp_Object timers, Lisp_Object idle_timers)
              continue;
            }
 
              continue;
            }
 
-         timer_ripe = EMACS_TIME_LE (timer_time, now);
+         timer_ripe = timespec_cmp (timer_time, now) <= 0;
          timer_difference = (timer_ripe
          timer_difference = (timer_ripe
-                             ? sub_emacs_time (now, timer_time)
-                             : sub_emacs_time (timer_time, now));
+                             ? timespec_sub (now, timer_time)
+                             : timespec_sub (timer_time, now));
        }
 
       /* Likewise for IDLE_TIMER and IDLE_TIMER_DIFFERENCE
        }
 
       /* Likewise for IDLE_TIMER and IDLE_TIMER_DIFFERENCE
@@ -4344,26 +4435,27 @@ timer_check_2 (Lisp_Object timers, Lisp_Object idle_timers)
              continue;
            }
 
              continue;
            }
 
-         idle_timer_ripe = EMACS_TIME_LE (idle_timer_time, idleness_now);
-         idle_timer_difference =
-           (idle_timer_ripe
-            ? sub_emacs_time (idleness_now, idle_timer_time)
-            : sub_emacs_time (idle_timer_time, idleness_now));
+         idle_timer_ripe = timespec_cmp (idle_timer_time, idleness_now) <= 0;
+         idle_timer_difference
+           (idle_timer_ripe
+              ? timespec_sub (idleness_now, idle_timer_time)
+              : timespec_sub (idle_timer_time, idleness_now));
        }
 
       /* Decide which timer is the next timer,
         and set CHOSEN_TIMER, DIFFERENCE, and RIPE accordingly.
         Also step down the list where we found that timer.  */
 
        }
 
       /* Decide which timer is the next timer,
         and set CHOSEN_TIMER, DIFFERENCE, and RIPE accordingly.
         Also step down the list where we found that timer.  */
 
-      if (EMACS_TIME_VALID_P (timer_difference)
-         && (! EMACS_TIME_VALID_P (idle_timer_difference)
+      if (timespec_valid_p (timer_difference)
+         && (! timespec_valid_p (idle_timer_difference)
              || idle_timer_ripe < timer_ripe
              || (idle_timer_ripe == timer_ripe
              || idle_timer_ripe < timer_ripe
              || (idle_timer_ripe == timer_ripe
-                 && (timer_ripe
-                     ? EMACS_TIME_LT (idle_timer_difference,
+                 && ((timer_ripe
+                      ? timespec_cmp (idle_timer_difference,
                                       timer_difference)
                                       timer_difference)
-                     : EMACS_TIME_LT (timer_difference,
-                                      idle_timer_difference)))))
+                      : timespec_cmp (timer_difference,
+                                      idle_timer_difference))
+                     < 0))))
        {
          chosen_timer = timer;
          timers = XCDR (timers);
        {
          chosen_timer = timer;
          timers = XCDR (timers);
@@ -4403,7 +4495,7 @@ timer_check_2 (Lisp_Object timers, Lisp_Object idle_timers)
                  return 0 to indicate that.  */
            }
 
                  return 0 to indicate that.  */
            }
 
-         nexttime = make_emacs_time (0, 0);
+         nexttime = make_timespec (0, 0);
           break;
        }
       else
           break;
        }
       else
@@ -4431,10 +4523,10 @@ timer_check_2 (Lisp_Object timers, Lisp_Object idle_timers)
 
    As long as any timer is ripe, we run it.  */
 
 
    As long as any timer is ripe, we run it.  */
 
-EMACS_TIME
+struct timespec
 timer_check (void)
 {
 timer_check (void)
 {
-  EMACS_TIME nexttime;
+  struct timespec nexttime;
   Lisp_Object timers, idle_timers;
   struct gcpro gcpro1, gcpro2;
 
   Lisp_Object timers, idle_timers;
   struct gcpro gcpro1, gcpro2;
 
@@ -4448,7 +4540,7 @@ timer_check (void)
   /* Always consider the ordinary timers.  */
   timers = Fcopy_sequence (Vtimer_list);
   /* Consider the idle timers only if Emacs is idle.  */
   /* Always consider the ordinary timers.  */
   timers = Fcopy_sequence (Vtimer_list);
   /* Consider the idle timers only if Emacs is idle.  */
-  if (EMACS_TIME_VALID_P (timer_idleness_start_time))
+  if (timespec_valid_p (timer_idleness_start_time))
     idle_timers = Fcopy_sequence (Vtimer_idle_list);
   else
     idle_timers = Qnil;
     idle_timers = Fcopy_sequence (Vtimer_idle_list);
   else
     idle_timers = Qnil;
@@ -4461,7 +4553,7 @@ timer_check (void)
     {
       nexttime = timer_check_2 (timers, idle_timers);
     }
     {
       nexttime = timer_check_2 (timers, idle_timers);
     }
-  while (EMACS_SECS (nexttime) == 0 && EMACS_NSECS (nexttime) == 0);
+  while (nexttime.tv_sec == 0 && nexttime.tv_nsec == 0);
 
   UNGCPRO;
   return nexttime;
 
   UNGCPRO;
   return nexttime;
@@ -4477,9 +4569,9 @@ The value when Emacs is not idle is nil.
 PSEC is a multiple of the system clock resolution.  */)
   (void)
 {
 PSEC is a multiple of the system clock resolution.  */)
   (void)
 {
-  if (EMACS_TIME_VALID_P (timer_idleness_start_time))
-    return make_lisp_time (sub_emacs_time (current_emacs_time (),
-                                          timer_idleness_start_time));
+  if (timespec_valid_p (timer_idleness_start_time))
+    return make_lisp_time (timespec_sub (current_timespec (),
+                                        timer_idleness_start_time));
 
   return Qnil;
 }
 
   return Qnil;
 }
@@ -5142,7 +5234,7 @@ make_lispy_position (struct frame *f, Lisp_Object x, Lisp_Object y,
          if (STRINGP (string))
            string_info = Fcons (string, make_number (charpos));
          textpos = (w == XWINDOW (selected_window)
          if (STRINGP (string))
            string_info = Fcons (string, make_number (charpos));
          textpos = (w == XWINDOW (selected_window)
-                    && current_buffer == XBUFFER (w->buffer))
+                    && current_buffer == XBUFFER (w->contents))
            ? PT : marker_position (w->pointm);
 
          xret = wx;
            ? PT : marker_position (w->pointm);
 
          xret = wx;
@@ -5475,14 +5567,12 @@ make_lispy_event (struct input_event *event)
 
                /* ELisp manual 2.4b says (x y) are window relative but
                   code says they are frame-relative.  */
 
                /* ELisp manual 2.4b says (x y) are window relative but
                   code says they are frame-relative.  */
-               position
-                 = Fcons (event->frame_or_window,
-                          Fcons (Qmenu_bar,
-                                 Fcons (Fcons (event->x, event->y),
-                                        Fcons (make_number (event->timestamp),
-                                               Qnil))));
-
-               return Fcons (item, Fcons (position, Qnil));
+               position = list4 (event->frame_or_window,
+                                 Qmenu_bar,
+                                 Fcons (event->x, event->y),
+                                 make_number (event->timestamp));
+
+               return list2 (item, position);
              }
 #endif /* not USE_X_TOOLKIT && not USE_GTK && not HAVE_NS */
 
              }
 #endif /* not USE_X_TOOLKIT && not USE_GTK && not HAVE_NS */
 
@@ -5501,12 +5591,9 @@ make_lispy_event (struct input_event *event)
            portion_whole = Fcons (event->x, event->y);
            part = *scroll_bar_parts[(int) event->part];
 
            portion_whole = Fcons (event->x, event->y);
            part = *scroll_bar_parts[(int) event->part];
 
-           position
-             = Fcons (window,
-                      Fcons (Qvertical_scroll_bar,
-                             Fcons (portion_whole,
-                                    Fcons (make_number (event->timestamp),
-                                           Fcons (part, Qnil)))));
+           position = list5 (window, Qvertical_scroll_bar,
+                             portion_whole, make_number (event->timestamp),
+                             part);
          }
 #endif /* not USE_TOOLKIT_SCROLL_BARS */
 
          }
 #endif /* not USE_TOOLKIT_SCROLL_BARS */
 
@@ -5654,19 +5741,11 @@ make_lispy_event (struct input_event *event)
                                      &mouse_syms,
                                      ASIZE (mouse_syms));
          if (event->modifiers & drag_modifier)
                                      &mouse_syms,
                                      ASIZE (mouse_syms));
          if (event->modifiers & drag_modifier)
-           return Fcons (head,
-                         Fcons (start_pos,
-                                Fcons (position,
-                                       Qnil)));
+           return list3 (head, start_pos, position);
          else if (event->modifiers & (double_modifier | triple_modifier))
          else if (event->modifiers & (double_modifier | triple_modifier))
-           return Fcons (head,
-                         Fcons (position,
-                                Fcons (make_number (double_click_count),
-                                       Qnil)));
+           return list3 (head, position, make_number (double_click_count));
          else
          else
-           return Fcons (head,
-                         Fcons (position,
-                                Qnil));
+           return list2 (head, position);
        }
       }
 
        }
       }
 
@@ -5765,14 +5844,9 @@ make_lispy_event (struct input_event *event)
        }
 
        if (event->modifiers & (double_modifier | triple_modifier))
        }
 
        if (event->modifiers & (double_modifier | triple_modifier))
-         return Fcons (head,
-                       Fcons (position,
-                              Fcons (make_number (double_click_count),
-                                     Qnil)));
+         return list3 (head, position, make_number (double_click_count));
        else
        else
-         return Fcons (head,
-                       Fcons (position,
-                              Qnil));
+         return list2 (head, position);
       }
 
 
       }
 
 
@@ -5803,12 +5877,8 @@ make_lispy_event (struct input_event *event)
        portion_whole = Fcons (event->x, event->y);
        part = *scroll_bar_parts[(int) event->part];
 
        portion_whole = Fcons (event->x, event->y);
        part = *scroll_bar_parts[(int) event->part];
 
-       position
-         = Fcons (window,
-                  Fcons (Qvertical_scroll_bar,
-                         Fcons (portion_whole,
-                                Fcons (make_number (event->timestamp),
-                                       Fcons (part, Qnil)))));
+       position = list5 (window, Qvertical_scroll_bar, portion_whole,
+                         make_number (event->timestamp), part);
 
        /* Always treat scroll bar events as clicks.  */
        event->modifiers |= click_modifier;
 
        /* Always treat scroll bar events as clicks.  */
        event->modifiers |= click_modifier;
@@ -5826,14 +5896,14 @@ make_lispy_event (struct input_event *event)
                                    Vlispy_mouse_stem,
                                    NULL, &mouse_syms,
                                    ASIZE (mouse_syms));
                                    Vlispy_mouse_stem,
                                    NULL, &mouse_syms,
                                    ASIZE (mouse_syms));
-       return Fcons (head, Fcons (position, Qnil));
+       return list2 (head, position);
       }
 
 #endif /* USE_TOOLKIT_SCROLL_BARS */
 
     case DRAG_N_DROP_EVENT:
       {
       }
 
 #endif /* USE_TOOLKIT_SCROLL_BARS */
 
     case DRAG_N_DROP_EVENT:
       {
-       FRAME_PTR f;
+       struct frame *f;
        Lisp_Object head, position;
        Lisp_Object files;
 
        Lisp_Object head, position;
        Lisp_Object files;
 
@@ -5852,10 +5922,7 @@ make_lispy_event (struct input_event *event)
                                    Qdrag_n_drop, Qnil,
                                    lispy_drag_n_drop_names,
                                    &drag_n_drop_syms, 1);
                                    Qdrag_n_drop, Qnil,
                                    lispy_drag_n_drop_names,
                                    &drag_n_drop_syms, 1);
-       return Fcons (head,
-                     Fcons (position,
-                            Fcons (files,
-                                   Qnil)));
+       return list3 (head, position, files);
       }
 
 #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) \
       }
 
 #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) \
@@ -5865,22 +5932,20 @@ make_lispy_event (struct input_event *event)
        /* This is the prefix key.  We translate this to
           `(menu_bar)' because the code in keyboard.c for menu
           events, which we use, relies on this.  */
        /* This is the prefix key.  We translate this to
           `(menu_bar)' because the code in keyboard.c for menu
           events, which we use, relies on this.  */
-       return Fcons (Qmenu_bar, Qnil);
+       return list1 (Qmenu_bar);
       return event->arg;
 #endif
 
     case SELECT_WINDOW_EVENT:
       /* Make an event (select-window (WINDOW)).  */
       return event->arg;
 #endif
 
     case SELECT_WINDOW_EVENT:
       /* Make an event (select-window (WINDOW)).  */
-      return Fcons (Qselect_window,
-                   Fcons (Fcons (event->frame_or_window, Qnil),
-                          Qnil));
+      return list2 (Qselect_window, list1 (event->frame_or_window));
 
     case TOOL_BAR_EVENT:
       if (EQ (event->arg, event->frame_or_window))
        /* This is the prefix key.  We translate this to
           `(tool_bar)' because the code in keyboard.c for tool bar
           events, which we use, relies on this.  */
 
     case TOOL_BAR_EVENT:
       if (EQ (event->arg, event->frame_or_window))
        /* This is the prefix key.  We translate this to
           `(tool_bar)' because the code in keyboard.c for tool bar
           events, which we use, relies on this.  */
-       return Fcons (Qtool_bar, Qnil);
+       return list1 (Qtool_bar);
       else if (SYMBOLP (event->arg))
        return apply_modifiers (event->modifiers, event->arg);
       return event->arg;
       else if (SYMBOLP (event->arg))
        return apply_modifiers (event->modifiers, event->arg);
       return event->arg;
@@ -5904,21 +5969,20 @@ make_lispy_event (struct input_event *event)
       }
 #endif /* HAVE_DBUS */
 
       }
 #endif /* HAVE_DBUS */
 
-#ifdef HAVE_INOTIFY
+#if defined HAVE_GFILENOTIFY || defined HAVE_INOTIFY
     case FILE_NOTIFY_EVENT:
       {
     case FILE_NOTIFY_EVENT:
       {
-        return Fcons (Qfile_inotify, event->arg);
+        return Fcons (Qfile_notify, event->arg);
       }
       }
-#endif /* HAVE_INOTIFY */
+#endif /* defined HAVE_GFILENOTIFY || defined HAVE_INOTIFY */
 
     case CONFIG_CHANGED_EVENT:
 
     case CONFIG_CHANGED_EVENT:
-       return Fcons (Qconfig_changed_event,
-                      Fcons (event->arg,
-                             Fcons (event->frame_or_window, Qnil)));
+       return list3 (Qconfig_changed_event,
+                     event->arg, event->frame_or_window);
 #ifdef HAVE_GPM
     case GPM_CLICK_EVENT:
       {
 #ifdef HAVE_GPM
     case GPM_CLICK_EVENT:
       {
-       FRAME_PTR f = XFRAME (event->frame_or_window);
+       struct frame *f = XFRAME (event->frame_or_window);
        Lisp_Object head, position;
        Lisp_Object *start_pos_ptr;
        Lisp_Object start_pos;
        Lisp_Object head, position;
        Lisp_Object *start_pos_ptr;
        Lisp_Object start_pos;
@@ -5955,24 +6019,13 @@ make_lispy_event (struct input_event *event)
                                    ASIZE (mouse_syms));
 
        if (event->modifiers & drag_modifier)
                                    ASIZE (mouse_syms));
 
        if (event->modifiers & drag_modifier)
-         return Fcons (head,
-                       Fcons (start_pos,
-                              Fcons (position,
-                                     Qnil)));
+         return list3 (head, start_pos, position);
        else if (event->modifiers & double_modifier)
        else if (event->modifiers & double_modifier)
-         return Fcons (head,
-                       Fcons (position,
-                              Fcons (make_number (2),
-                                     Qnil)));
+         return list3 (head, position, make_number (2));
        else if (event->modifiers & triple_modifier)
        else if (event->modifiers & triple_modifier)
-         return Fcons (head,
-                       Fcons (position,
-                              Fcons (make_number (3),
-                                     Qnil)));
+         return list3 (head, position, make_number (3));
        else
        else
-         return Fcons (head,
-                       Fcons (position,
-                              Qnil));
+         return list2 (head, position);
        }
 #endif /* HAVE_GPM */
 
        }
 #endif /* HAVE_GPM */
 
@@ -5983,7 +6036,7 @@ make_lispy_event (struct input_event *event)
 }
 
 static Lisp_Object
 }
 
 static Lisp_Object
-make_lispy_movement (FRAME_PTR frame, Lisp_Object bar_window, enum scroll_bar_part part,
+make_lispy_movement (struct frame *frame, Lisp_Object bar_window, enum scroll_bar_part part,
                     Lisp_Object x, Lisp_Object y, Time t)
 {
   /* Is it a scroll bar movement?  */
                     Lisp_Object x, Lisp_Object y, Time t)
 {
   /* Is it a scroll bar movement?  */
@@ -5992,13 +6045,12 @@ make_lispy_movement (FRAME_PTR frame, Lisp_Object bar_window, enum scroll_bar_pa
       Lisp_Object part_sym;
 
       part_sym = *scroll_bar_parts[(int) part];
       Lisp_Object part_sym;
 
       part_sym = *scroll_bar_parts[(int) part];
-      return Fcons (Qscroll_bar_movement,
-                   Fcons (list5 (bar_window,
-                                 Qvertical_scroll_bar,
-                                 Fcons (x, y),
-                                 make_number (t),
-                                 part_sym),
-                          Qnil));
+      return list2 (Qscroll_bar_movement,
+                   list5 (bar_window,
+                          Qvertical_scroll_bar,
+                          Fcons (x, y),
+                          make_number (t),
+                          part_sym));
     }
   /* Or is it an ordinary mouse movement?  */
   else
     }
   /* Or is it an ordinary mouse movement?  */
   else
@@ -6013,9 +6065,25 @@ make_lispy_movement (FRAME_PTR frame, Lisp_Object bar_window, enum scroll_bar_pa
 static Lisp_Object
 make_lispy_switch_frame (Lisp_Object frame)
 {
 static Lisp_Object
 make_lispy_switch_frame (Lisp_Object frame)
 {
-  return Fcons (Qswitch_frame, Fcons (frame, Qnil));
+  return list2 (Qswitch_frame, frame);
 }
 }
-\f
+
+static Lisp_Object
+make_lispy_focus_in (Lisp_Object frame)
+{
+  return list2 (Qfocus_in, frame);
+}
+
+#ifdef HAVE_WINDOW_SYSTEM
+
+static Lisp_Object
+make_lispy_focus_out (Lisp_Object frame)
+{
+  return list2 (Qfocus_out, frame);
+}
+
+#endif /* HAVE_WINDOW_SYSTEM */
+
 /* Manipulating modifiers.  */
 
 /* Parse the name of SYMBOL, and return the set of modifiers it contains.
 /* Manipulating modifiers.  */
 
 /* Parse the name of SYMBOL, and return the set of modifiers it contains.
@@ -6225,9 +6293,7 @@ parse_modifiers (Lisp_Object symbol)
   Lisp_Object elements;
 
   if (INTEGERP (symbol))
   Lisp_Object elements;
 
   if (INTEGERP (symbol))
-    return (Fcons (make_number (KEY_TO_CHAR (symbol)),
-                  Fcons (make_number (XINT (symbol) & CHAR_MODIFIER_MASK),
-                         Qnil)));
+    return list2i (KEY_TO_CHAR (symbol), XINT (symbol) & CHAR_MODIFIER_MASK);
   else if (!SYMBOLP (symbol))
     return Qnil;
 
   else if (!SYMBOLP (symbol))
     return Qnil;
 
@@ -6248,7 +6314,7 @@ parse_modifiers (Lisp_Object symbol)
       if (modifiers & ~INTMASK)
        emacs_abort ();
       XSETFASTINT (mask, modifiers);
       if (modifiers & ~INTMASK)
        emacs_abort ();
       XSETFASTINT (mask, modifiers);
-      elements = Fcons (unmodified, Fcons (mask, Qnil));
+      elements = list2 (unmodified, mask);
 
       /* Cache the parsing results on SYMBOL.  */
       Fput (symbol, Qevent_symbol_element_mask,
 
       /* Cache the parsing results on SYMBOL.  */
       Fput (symbol, Qevent_symbol_element_mask,
@@ -6321,7 +6387,7 @@ apply_modifiers (int modifiers, Lisp_Object base)
         the caches:
          XSETFASTINT (idx, modifiers);
          Fput (new_symbol, Qevent_symbol_element_mask,
         the caches:
          XSETFASTINT (idx, modifiers);
          Fput (new_symbol, Qevent_symbol_element_mask,
-               Fcons (base, Fcons (idx, Qnil)));
+               list2 (base, idx));
          Fput (new_symbol, Qevent_symbol_elements,
                Fcons (base, lispy_modifier_list (modifiers)));
         Sadly, this is only correct if `base' is indeed a base event,
          Fput (new_symbol, Qevent_symbol_elements,
                Fcons (base, lispy_modifier_list (modifiers)));
         Sadly, this is only correct if `base' is indeed a base event,
@@ -6554,10 +6620,7 @@ has the same base event type and all the specified modifiers.  */)
   else if (SYMBOLP (base))
     return apply_modifiers (modifiers, base);
   else
   else if (SYMBOLP (base))
     return apply_modifiers (modifiers, base);
   else
-    {
-      error ("Invalid base event");
-      return Qnil;
-    }
+    error ("Invalid base event");
 }
 
 /* Try to recognize SYMBOL as a modifier name.
 }
 
 /* Try to recognize SYMBOL as a modifier name.
@@ -6771,7 +6834,7 @@ gobble_input (void)
           hold_quit.kind = NO_EVENT;
 
           /* No need for FIONREAD or fcntl; just say don't wait.  */
           hold_quit.kind = NO_EVENT;
 
           /* No need for FIONREAD or fcntl; just say don't wait.  */
-         while (0 < (nr = (*t->read_socket_hook) (t, &hold_quit)))
+         while ((nr = (*t->read_socket_hook) (t, &hold_quit)) > 0)
            nread += nr;
 
           if (nr == -1)          /* Not OK to read input now.  */
            nread += nr;
 
           if (nr == -1)          /* Not OK to read input now.  */
@@ -6817,48 +6880,6 @@ gobble_input (void)
   return nread;
 }
 
   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 event_buf;
-
-      EVENT_INIT (event_buf);
-      event_buf.code = STRING_CHAR_ADVANCE (p);
-      event_buf.kind =
-       (ASCII_CHAR_P (event_buf.code)
-        ? ASCII_KEYSTROKE_EVENT : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
-      /* See the comment in tty_read_avail_input.  */
-      event_buf.frame_or_window = tty->top_frame;
-      event_buf.arg = Qnil;
-      kbd_buffer_store_event (&event_buf);
-    }
-}
-
 /* This is the tty way of reading available input.
 
    Note that each terminal device has its own `struct terminal' object,
 /* This is the tty way of reading available input.
 
    Note that each terminal device has its own `struct terminal' object,
@@ -6893,6 +6914,8 @@ tty_read_avail_input (struct terminal *terminal,
   /* XXX I think the following code should be moved to separate hook
      functions in system-dependent files.  */
 #ifdef WINDOWSNT
   /* XXX I think the following code should be moved to separate hook
      functions in system-dependent files.  */
 #ifdef WINDOWSNT
+  /* FIXME: AFAIK, tty_read_avail_input is not used under w32 since the non-GUI
+     code sets read_socket_hook to w32_console_read_socket instead!  */
   return 0;
 #else /* not WINDOWSNT */
   if (! tty->term_initted)      /* In case we get called during bootstrap.  */
   return 0;
 #else /* not WINDOWSNT */
   if (! tty->term_initted)      /* In case we get called during bootstrap.  */
@@ -6973,7 +6996,7 @@ tty_read_avail_input (struct terminal *terminal,
     {
       nread = emacs_read (fileno (tty->input), (char *) cbuf, n_to_read);
       /* POSIX infers that processes which are not in the session leader's
     {
       nread = emacs_read (fileno (tty->input), (char *) 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
+         process group won't get SIGHUPs 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.  */
          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.  */
@@ -7016,36 +7039,6 @@ tty_read_avail_input (struct terminal *terminal,
 #endif /* not MSDOS */
 #endif /* not WINDOWSNT */
 
 #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;
   for (i = 0; i < nread; i++)
     {
       struct input_event buf;
@@ -7143,7 +7136,7 @@ handle_input_available_signal (int sig)
   pending_signals = 1;
 
   if (input_available_clear_time)
   pending_signals = 1;
 
   if (input_available_clear_time)
-    *input_available_clear_time = make_emacs_time (0, 0);
+    *input_available_clear_time = make_timespec (0, 0);
 }
 
 static void
 }
 
 static void
@@ -7230,7 +7223,7 @@ handle_user_signal (int sig)
            /* Tell wait_reading_process_output that it needs to wake
               up and look around.  */
            if (input_available_clear_time)
            /* Tell wait_reading_process_output that it needs to wake
               up and look around.  */
            if (input_available_clear_time)
-             *input_available_clear_time = make_emacs_time (0, 0);
+             *input_available_clear_time = make_timespec (0, 0);
          }
        break;
       }
          }
        break;
       }
@@ -7386,7 +7379,8 @@ menu_bar_items (Lisp_Object old)
     Lisp_Object *tmaps;
 
     /* Should overriding-terminal-local-map and overriding-local-map apply?  */
     Lisp_Object *tmaps;
 
     /* Should overriding-terminal-local-map and overriding-local-map apply?  */
-    if (!NILP (Voverriding_local_map_menu_flag))
+    if (!NILP (Voverriding_local_map_menu_flag)
+       && !NILP (Voverriding_local_map))
       {
        /* Yes, use them (if non-nil) as well as the global map.  */
        maps = alloca (3 * sizeof (maps[0]));
       {
        /* Yes, use them (if non-nil) as well as the global map.  */
        maps = alloca (3 * sizeof (maps[0]));
@@ -7406,8 +7400,11 @@ menu_bar_items (Lisp_Object old)
        Lisp_Object tem;
        ptrdiff_t nminor;
        nminor = current_minor_maps (NULL, &tmaps);
        Lisp_Object tem;
        ptrdiff_t nminor;
        nminor = current_minor_maps (NULL, &tmaps);
-       maps = alloca ((nminor + 3) * sizeof *maps);
+       maps = alloca ((nminor + 4) * sizeof *maps);
        nmaps = 0;
        nmaps = 0;
+       tem = KVAR (current_kboard, Voverriding_terminal_local_map);
+       if (!NILP (tem) && !NILP (Voverriding_local_map_menu_flag))
+         maps[nmaps++] = tem;
        if (tem = get_local_map (PT, current_buffer, Qkeymap), !NILP (tem))
          maps[nmaps++] = tem;
        memcpy (maps + nmaps, tmaps, nminor * sizeof (maps[0]));
        if (tem = get_local_map (PT, current_buffer, Qkeymap), !NILP (tem))
          maps[nmaps++] = tem;
        memcpy (maps + nmaps, tmaps, nminor * sizeof (maps[0]));
@@ -7542,7 +7539,7 @@ menu_bar_item (Lisp_Object key, Lisp_Object item, Lisp_Object dummy1, void *dumm
       ASET (menu_bar_items_vector, i, key); i++;
       ASET (menu_bar_items_vector, i,
            AREF (item_properties, ITEM_PROPERTY_NAME)); i++;
       ASET (menu_bar_items_vector, i, key); i++;
       ASET (menu_bar_items_vector, i,
            AREF (item_properties, ITEM_PROPERTY_NAME)); i++;
-      ASET (menu_bar_items_vector, i, Fcons (item, Qnil)); i++;
+      ASET (menu_bar_items_vector, i, list1 (item)); i++;
       ASET (menu_bar_items_vector, i, make_number (0)); i++;
       menu_bar_items_index = i;
     }
       ASET (menu_bar_items_vector, i, make_number (0)); i++;
       menu_bar_items_index = i;
     }
@@ -7932,7 +7929,8 @@ tool_bar_items (Lisp_Object reuse, int *nitems)
      to process.  */
 
   /* Should overriding-terminal-local-map and overriding-local-map apply?  */
      to process.  */
 
   /* Should overriding-terminal-local-map and overriding-local-map apply?  */
-  if (!NILP (Voverriding_local_map_menu_flag))
+  if (!NILP (Voverriding_local_map_menu_flag)
+      && !NILP (Voverriding_local_map))
     {
       /* Yes, use them (if non-nil) as well as the global map.  */
       maps = alloca (3 * sizeof *maps);
     {
       /* Yes, use them (if non-nil) as well as the global map.  */
       maps = alloca (3 * sizeof *maps);
@@ -7952,8 +7950,11 @@ tool_bar_items (Lisp_Object reuse, int *nitems)
       Lisp_Object tem;
       ptrdiff_t nminor;
       nminor = current_minor_maps (NULL, &tmaps);
       Lisp_Object tem;
       ptrdiff_t nminor;
       nminor = current_minor_maps (NULL, &tmaps);
-      maps = alloca ((nminor + 3) * sizeof *maps);
+      maps = alloca ((nminor + 4) * sizeof *maps);
       nmaps = 0;
       nmaps = 0;
+      tem = KVAR (current_kboard, Voverriding_terminal_local_map);
+      if (!NILP (tem) && !NILP (Voverriding_local_map_menu_flag))
+       maps[nmaps++] = tem;
       if (tem = get_local_map (PT, current_buffer, Qkeymap), !NILP (tem))
        maps[nmaps++] = tem;
       memcpy (maps + nmaps, tmaps, nminor * sizeof (maps[0]));
       if (tem = get_local_map (PT, current_buffer, Qkeymap), !NILP (tem))
        maps[nmaps++] = tem;
       memcpy (maps + nmaps, tmaps, nminor * sizeof (maps[0]));
@@ -8093,7 +8094,7 @@ parse_tool_bar_item (Lisp_Object key, Lisp_Object item)
 
   /* As an exception, allow old-style menu separators.  */
   if (STRINGP (XCAR (item)))
 
   /* As an exception, allow old-style menu separators.  */
   if (STRINGP (XCAR (item)))
-    item = Fcons (XCAR (item), Qnil);
+    item = list1 (XCAR (item));
   else if (!EQ (XCAR (item), Qmenu_item)
           || (item = XCDR (item), !CONSP (item)))
     return 0;
   else if (!EQ (XCAR (item), Qmenu_item)
           || (item = XCDR (item), !CONSP (item)))
     return 0;
@@ -8136,11 +8137,12 @@ parse_tool_bar_item (Lisp_Object key, Lisp_Object item)
 #if !defined (USE_GTK) && !defined (HAVE_NS)
          /* If we use build_desired_tool_bar_string to render the
             tool bar, the separator is rendered as an image.  */
 #if !defined (USE_GTK) && !defined (HAVE_NS)
          /* If we use build_desired_tool_bar_string to render the
             tool bar, the separator is rendered as an image.  */
-         PROP (TOOL_BAR_ITEM_IMAGES)
-           = menu_item_eval_property (Vtool_bar_separator_image_expression);
-         PROP (TOOL_BAR_ITEM_ENABLED_P) = Qnil;
-         PROP (TOOL_BAR_ITEM_SELECTED_P) = Qnil;
-         PROP (TOOL_BAR_ITEM_CAPTION) = Qnil;
+         set_prop (TOOL_BAR_ITEM_IMAGES,
+                   (menu_item_eval_property
+                    (Vtool_bar_separator_image_expression)));
+         set_prop (TOOL_BAR_ITEM_ENABLED_P, Qnil);
+         set_prop (TOOL_BAR_ITEM_SELECTED_P, Qnil);
+         set_prop (TOOL_BAR_ITEM_CAPTION, Qnil);
 #endif
          return 1;
        }
 #endif
          return 1;
        }
@@ -8317,9 +8319,8 @@ append_tool_bar_item (void)
        - (ASIZE (tool_bar_items_vector) - TOOL_BAR_ITEM_NSLOTS));
 
   /* Enlarge tool_bar_items_vector if necessary.  */
        - (ASIZE (tool_bar_items_vector) - TOOL_BAR_ITEM_NSLOTS));
 
   /* Enlarge tool_bar_items_vector if necessary.  */
-  if (0 < incr)
-    tool_bar_items_vector
-      = larger_vector (tool_bar_items_vector, incr, -1);
+  if (incr > 0)
+    tool_bar_items_vector = larger_vector (tool_bar_items_vector, incr, -1);
 
   /* Append entries from tool_bar_item_properties to the end of
      tool_bar_items_vector.  */
 
   /* Append entries from tool_bar_item_properties to the end of
      tool_bar_items_vector.  */
@@ -8440,7 +8441,7 @@ read_char_minibuf_menu_prompt (int commandflag,
     return Qnil;
 
 #define PUSH_C_STR(str, listvar) \
     return Qnil;
 
 #define PUSH_C_STR(str, listvar) \
-  listvar = Fcons (make_unibyte_string (str, strlen (str)), listvar)
+  listvar = Fcons (build_unibyte_string (str), listvar)
 
   /* Prompt string always starts with map's prompt, and a space.  */
   prompt_strings = Fcons (name, prompt_strings);
 
   /* Prompt string always starts with map's prompt, and a space.  */
   prompt_strings = Fcons (name, prompt_strings);
@@ -8701,7 +8702,7 @@ access_keymap_keyremap (Lisp_Object map, Lisp_Object key, Lisp_Object prompt,
         barf--don't ignore it.
         (To ignore it safely, we would need to gcpro a bunch of
         other variables.)  */
         barf--don't ignore it.
         (To ignore it safely, we would need to gcpro a bunch of
         other variables.)  */
-      if (! (VECTORP (next) || STRINGP (next)))
+      if (! (NILP (next) || VECTORP (next) || STRINGP (next)))
        error ("Function %s returns invalid key sequence",
               SSDATA (SYMBOL_NAME (tem)));
     }
        error ("Function %s returns invalid key sequence",
               SSDATA (SYMBOL_NAME (tem)));
     }
@@ -9063,8 +9064,8 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
            KBOARD *interrupted_kboard = current_kboard;
            struct frame *interrupted_frame = SELECTED_FRAME ();
            key = read_char (NILP (prompt),
            KBOARD *interrupted_kboard = current_kboard;
            struct frame *interrupted_frame = SELECTED_FRAME ();
            key = read_char (NILP (prompt),
-                            current_binding, last_nonmenu_event,
-                            &used_mouse_menu, NULL);
+                            current_binding, last_nonmenu_event,
+                             &used_mouse_menu, NULL);
            if ((INTEGERP (key) && XINT (key) == -2) /* wrong_kboard_jmpbuf */
                /* When switching to a new tty (with a new keyboard),
                   read_char returns the new buffer, rather than -2
            if ((INTEGERP (key) && XINT (key) == -2) /* wrong_kboard_jmpbuf */
                /* When switching to a new tty (with a new keyboard),
                   read_char returns the new buffer, rather than -2
@@ -9158,9 +9159,9 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
                {
                  if (! FRAME_LIVE_P (XFRAME (selected_frame)))
                    Fkill_emacs (Qnil);
                {
                  if (! FRAME_LIVE_P (XFRAME (selected_frame)))
                    Fkill_emacs (Qnil);
-                 if (XBUFFER (XWINDOW (selected_window)->buffer)
+                 if (XBUFFER (XWINDOW (selected_window)->contents)
                      != current_buffer)
                      != current_buffer)
-                   Fset_buffer (XWINDOW (selected_window)->buffer);
+                   Fset_buffer (XWINDOW (selected_window)->contents);
                }
 
              goto replay_sequence;
                }
 
              goto replay_sequence;
@@ -9208,9 +9209,9 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
                 special-event-map, ...) might have switched the current buffer
                 or the selected window from under us in the mean time.  */
              if (fix_current_buffer
                 special-event-map, ...) might have switched the current buffer
                 or the selected window from under us in the mean time.  */
              if (fix_current_buffer
-                 && (XBUFFER (XWINDOW (selected_window)->buffer)
+                 && (XBUFFER (XWINDOW (selected_window)->contents)
                      != current_buffer))
                      != current_buffer))
-               Fset_buffer (XWINDOW (selected_window)->buffer);
+               Fset_buffer (XWINDOW (selected_window)->contents);
              current_binding = active_maps (first_event);
            }
 
              current_binding = active_maps (first_event);
            }
 
@@ -9259,8 +9260,8 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
                     not the current buffer.  If we're at the
                     beginning of a key sequence, switch buffers.  */
                  if (WINDOWP (window)
                     not the current buffer.  If we're at the
                     beginning of a key sequence, switch buffers.  */
                  if (WINDOWP (window)
-                     && BUFFERP (XWINDOW (window)->buffer)
-                     && XBUFFER (XWINDOW (window)->buffer) != current_buffer)
+                     && BUFFERP (XWINDOW (window)->contents)
+                     && XBUFFER (XWINDOW (window)->contents) != current_buffer)
                    {
                      ASET (raw_keybuf, raw_keybuf_count, key);
                      raw_keybuf_count++;
                    {
                      ASET (raw_keybuf, raw_keybuf_count, key);
                      raw_keybuf_count++;
@@ -9281,7 +9282,7 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
 
                      if (! FRAME_LIVE_P (XFRAME (selected_frame)))
                        Fkill_emacs (Qnil);
 
                      if (! FRAME_LIVE_P (XFRAME (selected_frame)))
                        Fkill_emacs (Qnil);
-                     set_buffer_internal (XBUFFER (XWINDOW (window)->buffer));
+                     set_buffer_internal (XBUFFER (XWINDOW (window)->contents));
                      goto replay_sequence;
                    }
                }
                      goto replay_sequence;
                    }
                }
@@ -9325,8 +9326,7 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
 
                  /* Zap the position in key, so we know that we've
                     expanded it, and don't try to do so again.  */
 
                  /* Zap the position in key, so we know that we've
                     expanded it, and don't try to do so again.  */
-                 POSN_SET_POSN (EVENT_START (key),
-                                Fcons (posn, Qnil));
+                 POSN_SET_POSN (EVENT_START (key), list1 (posn));
 
                  mock_input = t + 2;
                  goto replay_sequence;
 
                  mock_input = t + 2;
                  goto replay_sequence;
@@ -9481,8 +9481,7 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
 
                      new_head
                        = apply_modifiers (modifiers, XCAR (breakdown));
 
                      new_head
                        = apply_modifiers (modifiers, XCAR (breakdown));
-                     new_click
-                       = Fcons (new_head, Fcons (EVENT_START (key), Qnil));
+                     new_click = list2 (new_head, EVENT_START (key));
 
                      /* Look for a binding for this new key.  */
                      new_binding = follow_key (current_binding, new_click);
 
                      /* Look for a binding for this new key.  */
                      new_binding = follow_key (current_binding, new_click);
@@ -9722,54 +9721,11 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
   return t;
 }
 
   return t;
 }
 
-DEFUN ("read-key-sequence", Fread_key_sequence, Sread_key_sequence, 1, 5, 0,
-       doc: /* Read a sequence of keystrokes and return as a string or vector.
-The sequence is sufficient to specify a non-prefix command in the
-current local and global maps.
-
-First arg PROMPT is a prompt string.  If nil, do not prompt specially.
-Second (optional) arg CONTINUE-ECHO, if non-nil, means this key echos
-as a continuation of the previous key.
-
-The third (optional) arg DONT-DOWNCASE-LAST, if non-nil, means do not
-convert the last event to lower case.  (Normally any upper case event
-is converted to lower case if the original event is undefined and the lower
-case equivalent is defined.)  A non-nil value is appropriate for reading
-a key sequence to be defined.
-
-A C-g typed while in this function is treated like any other character,
-and `quit-flag' is not set.
-
-If the key sequence starts with a mouse click, then the sequence is read
-using the keymaps of the buffer of the window clicked in, not the buffer
-of the selected window as normal.
-
-`read-key-sequence' drops unbound button-down events, since you normally
-only care about the click or drag events which follow them.  If a drag
-or multi-click event is unbound, but the corresponding click event would
-be bound, `read-key-sequence' turns the event into a click event at the
-drag's starting position.  This means that you don't have to distinguish
-between click and drag, double, or triple events unless you want to.
-
-`read-key-sequence' prefixes mouse events on mode lines, the vertical
-lines separating windows, and scroll bars with imaginary keys
-`mode-line', `vertical-line', and `vertical-scroll-bar'.
-
-Optional fourth argument CAN-RETURN-SWITCH-FRAME non-nil means that this
-function will process a switch-frame event if the user switches frames
-before typing anything.  If the user switches frames in the middle of a
-key sequence, or at the start of the sequence but CAN-RETURN-SWITCH-FRAME
-is nil, then the event will be put off until after the current key sequence.
-
-`read-key-sequence' checks `function-key-map' for function key
-sequences, where they wouldn't conflict with ordinary bindings.  See
-`function-key-map' for more details.
-
-The optional fifth argument CMD-LOOP, if non-nil, means
-that this key sequence is being read by something that will
-read commands one after another.  It should be nil if the caller
-will read just one key sequence.  */)
-  (Lisp_Object prompt, Lisp_Object continue_echo, Lisp_Object dont_downcase_last, Lisp_Object can_return_switch_frame, Lisp_Object cmd_loop)
+static Lisp_Object
+read_key_sequence_vs (Lisp_Object prompt, Lisp_Object continue_echo,
+                     Lisp_Object dont_downcase_last,
+                     Lisp_Object can_return_switch_frame,
+                     Lisp_Object cmd_loop, bool allow_string)
 {
   Lisp_Object keybuf[30];
   register int i;
 {
   Lisp_Object keybuf[30];
   register int i;
@@ -9820,60 +9776,71 @@ will read just one key sequence.  */)
       QUIT;
     }
   UNGCPRO;
       QUIT;
     }
   UNGCPRO;
-  return unbind_to (count, make_event_array (i, keybuf));
+  return unbind_to (count,
+                   ((allow_string ? make_event_array : Fvector)
+                    (i, keybuf)));
 }
 
 }
 
-DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,
-       Sread_key_sequence_vector, 1, 5, 0,
-       doc: /* Like `read-key-sequence' but always return a vector.  */)
-  (Lisp_Object prompt, Lisp_Object continue_echo, Lisp_Object dont_downcase_last, Lisp_Object can_return_switch_frame, Lisp_Object cmd_loop)
-{
-  Lisp_Object keybuf[30];
-  register int i;
-  struct gcpro gcpro1;
-  ptrdiff_t count = SPECPDL_INDEX ();
+DEFUN ("read-key-sequence", Fread_key_sequence, Sread_key_sequence, 1, 5, 0,
+       doc: /* Read a sequence of keystrokes and return as a string or vector.
+The sequence is sufficient to specify a non-prefix command in the
+current local and global maps.
 
 
-  if (!NILP (prompt))
-    CHECK_STRING (prompt);
-  QUIT;
+First arg PROMPT is a prompt string.  If nil, do not prompt specially.
+Second (optional) arg CONTINUE-ECHO, if non-nil, means this key echos
+as a continuation of the previous key.
 
 
-  specbind (Qinput_method_exit_on_first_char,
-           (NILP (cmd_loop) ? Qt : Qnil));
-  specbind (Qinput_method_use_echo_area,
-           (NILP (cmd_loop) ? Qt : Qnil));
+The third (optional) arg DONT-DOWNCASE-LAST, if non-nil, means do not
+convert the last event to lower case.  (Normally any upper case event
+is converted to lower case if the original event is undefined and the lower
+case equivalent is defined.)  A non-nil value is appropriate for reading
+a key sequence to be defined.
 
 
-  memset (keybuf, 0, sizeof keybuf);
-  GCPRO1 (keybuf[0]);
-  gcpro1.nvars = (sizeof keybuf / sizeof (keybuf[0]));
+A C-g typed while in this function is treated like any other character,
+and `quit-flag' is not set.
 
 
-  if (NILP (continue_echo))
-    {
-      this_command_key_count = 0;
-      this_command_key_count_reset = 0;
-      this_single_command_key_start = 0;
-    }
+If the key sequence starts with a mouse click, then the sequence is read
+using the keymaps of the buffer of the window clicked in, not the buffer
+of the selected window as normal.
 
 
-#ifdef HAVE_WINDOW_SYSTEM
-  if (display_hourglass_p)
-    cancel_hourglass ();
-#endif
+`read-key-sequence' drops unbound button-down events, since you normally
+only care about the click or drag events which follow them.  If a drag
+or multi-click event is unbound, but the corresponding click event would
+be bound, `read-key-sequence' turns the event into a click event at the
+drag's starting position.  This means that you don't have to distinguish
+between click and drag, double, or triple events unless you want to.
 
 
-  i = read_key_sequence (keybuf, (sizeof keybuf / sizeof (keybuf[0])),
-                        prompt, ! NILP (dont_downcase_last),
-                        ! NILP (can_return_switch_frame), 0);
+`read-key-sequence' prefixes mouse events on mode lines, the vertical
+lines separating windows, and scroll bars with imaginary keys
+`mode-line', `vertical-line', and `vertical-scroll-bar'.
 
 
-#ifdef HAVE_WINDOW_SYSTEM
-  if (display_hourglass_p)
-    start_hourglass ();
-#endif
+Optional fourth argument CAN-RETURN-SWITCH-FRAME non-nil means that this
+function will process a switch-frame event if the user switches frames
+before typing anything.  If the user switches frames in the middle of a
+key sequence, or at the start of the sequence but CAN-RETURN-SWITCH-FRAME
+is nil, then the event will be put off until after the current key sequence.
 
 
-  if (i == -1)
-    {
-      Vquit_flag = Qt;
-      QUIT;
-    }
-  UNGCPRO;
-  return unbind_to (count, Fvector (i, keybuf));
+`read-key-sequence' checks `function-key-map' for function key
+sequences, where they wouldn't conflict with ordinary bindings.  See
+`function-key-map' for more details.
+
+The optional fifth argument CMD-LOOP, if non-nil, means
+that this key sequence is being read by something that will
+read commands one after another.  It should be nil if the caller
+will read just one key sequence.  */)
+  (Lisp_Object prompt, Lisp_Object continue_echo, Lisp_Object dont_downcase_last, Lisp_Object can_return_switch_frame, Lisp_Object cmd_loop)
+{
+  return read_key_sequence_vs (prompt, continue_echo, dont_downcase_last,
+                              can_return_switch_frame, cmd_loop, true);
+}
+
+DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,
+       Sread_key_sequence_vector, 1, 5, 0,
+       doc: /* Like `read-key-sequence' but always return a vector.  */)
+  (Lisp_Object prompt, Lisp_Object continue_echo, Lisp_Object dont_downcase_last, Lisp_Object can_return_switch_frame, Lisp_Object cmd_loop)
+{
+  return read_key_sequence_vs (prompt, continue_echo, dont_downcase_last,
+                              can_return_switch_frame, cmd_loop, false);
 }
 \f
 /* Return true if input events are pending.  */
 }
 \f
 /* Return true if input events are pending.  */
@@ -9904,20 +9871,7 @@ detect_input_pending_run_timers (bool do_display)
     get_input_pending (READABLE_EVENTS_DO_TIMERS_NOW);
 
   if (old_timers_run != timers_run && do_display)
     get_input_pending (READABLE_EVENTS_DO_TIMERS_NOW);
 
   if (old_timers_run != timers_run && do_display)
-    {
-      redisplay_preserve_echo_area (8);
-      /* The following fixes a bug when using lazy-lock with
-        lazy-lock-defer-on-the-fly set to t, i.e.  when fontifying
-        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.  */
-      {
-        Lisp_Object tail, frame;
-        FOR_EACH_FRAME (tail, frame)
-          if (FRAME_RIF (XFRAME (frame)))
-            FRAME_RIF (XFRAME (frame))->flush_display (XFRAME (frame));
-      }
-    }
+    redisplay_preserve_echo_area (8);
 
   return input_pending;
 }
 
   return input_pending;
 }
@@ -10116,9 +10070,9 @@ The file will be closed when Emacs exits.  */)
   if (!NILP (file))
     {
       file = Fexpand_file_name (file, Qnil);
   if (!NILP (file))
     {
       file = Fexpand_file_name (file, Qnil);
-      dribble = fopen (SSDATA (file), "w");
+      dribble = emacs_fopen (SSDATA (file), "w");
       if (dribble == 0)
       if (dribble == 0)
-       report_file_error ("Opening dribble", Fcons (file, Qnil));
+       report_file_error ("Opening dribble", file);
     }
   return Qnil;
 }
     }
   return Qnil;
 }
@@ -10135,8 +10089,6 @@ Also end any kbd macro being defined.  */)
       end_kbd_macro ();
     }
 
       end_kbd_macro ();
     }
 
-  update_mode_lines++;
-
   Vunread_command_events = Qnil;
 
   discard_tty_input ();
   Vunread_command_events = Qnil;
 
   discard_tty_input ();
@@ -10183,8 +10135,7 @@ On such systems, Emacs starts a subshell instead of suspending.  */)
   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.  */
   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.  */
-  record_unwind_protect ((Lisp_Object (*) (Lisp_Object)) init_all_sys_modes,
-                        Qnil);
+  record_unwind_protect_void (init_all_sys_modes);
   stuff_buffered_input (stuffstring);
   if (cannot_suspend)
     sys_subshell ();
   stuff_buffered_input (stuffstring);
   if (cannot_suspend)
     sys_subshell ();
@@ -10249,7 +10200,7 @@ stuff_buffered_input (Lisp_Object stuffstring)
 }
 \f
 void
 }
 \f
 void
-set_waiting_for_input (EMACS_TIME *time_to_clear)
+set_waiting_for_input (struct timespec *time_to_clear)
 {
   input_available_clear_time = time_to_clear;
 
 {
   input_available_clear_time = time_to_clear;
 
@@ -10555,7 +10506,7 @@ See also `current-input-mode'.  */)
   if (tty->flow_control != !NILP (flow))
     {
 #ifndef DOS_NT
   if (tty->flow_control != !NILP (flow))
     {
 #ifndef DOS_NT
-      /* this causes startup screen to be restored and messes with the mouse */
+      /* This causes startup screen to be restored and messes with the mouse.  */
       reset_sys_modes (tty);
 #endif
 
       reset_sys_modes (tty);
 #endif
 
@@ -10860,7 +10811,7 @@ init_keyboard (void)
   immediate_quit = 0;
   quit_char = Ctl ('g');
   Vunread_command_events = Qnil;
   immediate_quit = 0;
   quit_char = Ctl ('g');
   Vunread_command_events = Qnil;
-  timer_idleness_start_time = invalid_emacs_time ();
+  timer_idleness_start_time = invalid_timespec ();
   total_keys = 0;
   recent_keys_index = 0;
   kbd_fetch_ptr = kbd_buffer;
   total_keys = 0;
   recent_keys_index = 0;
   kbd_fetch_ptr = kbd_buffer;
@@ -10943,6 +10894,8 @@ static const struct event_head head_table[] = {
   {&Qmouse_movement,      "mouse-movement",      &Qmouse_movement},
   {&Qscroll_bar_movement, "scroll-bar-movement", &Qmouse_movement},
   {&Qswitch_frame,        "switch-frame",        &Qswitch_frame},
   {&Qmouse_movement,      "mouse-movement",      &Qmouse_movement},
   {&Qscroll_bar_movement, "scroll-bar-movement", &Qmouse_movement},
   {&Qswitch_frame,        "switch-frame",        &Qswitch_frame},
+  {&Qfocus_in,            "focus-in",            &Qfocus_in},
+  {&Qfocus_out,           "focus-out",          &Qfocus_out},
   {&Qdelete_frame,        "delete-frame",        &Qdelete_frame},
   {&Qiconify_frame,       "iconify-frame",       &Qiconify_frame},
   {&Qmake_frame_visible,  "make-frame-visible",  &Qmake_frame_visible},
   {&Qdelete_frame,        "delete-frame",        &Qdelete_frame},
   {&Qiconify_frame,       "iconify-frame",       &Qiconify_frame},
   {&Qmake_frame_visible,  "make-frame-visible",  &Qmake_frame_visible},
@@ -10995,17 +10948,13 @@ syms_of_keyboard (void)
   DEFSYM (Qlanguage_change, "language-change");
 #endif
 
   DEFSYM (Qlanguage_change, "language-change");
 #endif
 
-#ifdef WINDOWSNT
-  DEFSYM (Qfile_w32notify, "file-w32notify");
-#endif
-
 #ifdef HAVE_DBUS
   DEFSYM (Qdbus_event, "dbus-event");
 #endif
 
 #ifdef HAVE_DBUS
   DEFSYM (Qdbus_event, "dbus-event");
 #endif
 
-#ifdef HAVE_INOTIFY
-  DEFSYM (Qfile_inotify, "file-inotify");
-#endif /* HAVE_INOTIFY */
+#ifdef USE_FILE_NOTIFY
+  DEFSYM (Qfile_notify, "file-notify");
+#endif /* USE_FILE_NOTIFY */
 
   DEFSYM (QCenable, ":enable");
   DEFSYM (QCvisible, ":visible");
 
   DEFSYM (QCenable, ":enable");
   DEFSYM (QCvisible, ":visible");
@@ -11060,9 +11009,6 @@ syms_of_keyboard (void)
   Fset (Qinput_method_exit_on_first_char, Qnil);
   Fset (Qinput_method_use_echo_area, Qnil);
 
   Fset (Qinput_method_exit_on_first_char, Qnil);
   Fset (Qinput_method_use_echo_area, Qnil);
 
-  last_point_position_buffer = Qnil;
-  last_point_position_window = Qnil;
-
   {
     int i;
     int len = sizeof (head_table) / sizeof (head_table[0]);
   {
     int i;
     int len = sizeof (head_table) / sizeof (head_table[0]);
@@ -11073,7 +11019,7 @@ syms_of_keyboard (void)
        *p->var = intern_c_string (p->name);
        staticpro (p->var);
        Fput (*p->var, Qevent_kind, *p->kind);
        *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));
+       Fput (*p->var, Qevent_symbol_elements, list1 (*p->var));
       }
   }
 
       }
   }
 
@@ -11445,10 +11391,7 @@ tool-bar separators natively.  Otherwise it is unused (e.g. on GTK).  */);
 
   DEFVAR_KBOARD ("overriding-terminal-local-map",
                 Voverriding_terminal_local_map,
 
   DEFVAR_KBOARD ("overriding-terminal-local-map",
                 Voverriding_terminal_local_map,
-                doc: /* Per-terminal keymap that overrides all other local keymaps.
-If this variable is non-nil, it is used as a keymap instead of the
-buffer's local map, and the minor mode keymaps and text property keymaps.
-It also replaces `overriding-local-map'.
+                doc: /* Per-terminal keymap that takes precedence over all other keymaps.
 
 This variable is intended to let commands such as `universal-argument'
 set up a different keymap for reading the next command.
 
 This variable is intended to let commands such as `universal-argument'
 set up a different keymap for reading the next command.
@@ -11458,7 +11401,7 @@ terminal device.
 See Info node `(elisp)Multiple Terminals'.  */);
 
   DEFVAR_LISP ("overriding-local-map", Voverriding_local_map,
 See Info node `(elisp)Multiple Terminals'.  */);
 
   DEFVAR_LISP ("overriding-local-map", Voverriding_local_map,
-              doc: /* Keymap that overrides all other local keymaps.
+              doc: /* Keymap that overrides almost all other local keymaps.
 If this variable is non-nil, it is used as a keymap--replacing the
 buffer's local map, the minor mode keymaps, and char property keymaps.  */);
   Voverriding_local_map = Qnil;
 If this variable is non-nil, it is used as a keymap--replacing the
 buffer's local map, the minor mode keymaps, and char property keymaps.  */);
   Voverriding_local_map = Qnil;
@@ -11471,7 +11414,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.  */);
 
   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_c_string ("keymap"), Qnil);
+  Vspecial_event_map = list1 (intern_c_string ("keymap"));
 
   DEFVAR_LISP ("track-mouse", do_mouse_tracking,
               doc: /* Non-nil means generate motion events for mouse motion.  */);
 
   DEFVAR_LISP ("track-mouse", do_mouse_tracking,
               doc: /* Non-nil means generate motion events for mouse motion.  */);
@@ -11754,21 +11697,23 @@ keys_of_keyboard (void)
                            "dbus-handle-event");
 #endif
 
                            "dbus-handle-event");
 #endif
 
-#ifdef HAVE_INOTIFY
-  /* Define a special event which is raised for inotify callback
+#ifdef USE_FILE_NOTIFY
+  /* Define a special event which is raised for notification callback
      functions.  */
      functions.  */
-  initial_define_lispy_key (Vspecial_event_map, "file-inotify",
-                            "inotify-handle-event");
-#endif /* HAVE_INOTIFY */
+  initial_define_lispy_key (Vspecial_event_map, "file-notify",
+                            "file-notify-handle-event");
+#endif /* USE_FILE_NOTIFY */
 
   initial_define_lispy_key (Vspecial_event_map, "config-changed-event",
                            "ignore");
 #if defined (WINDOWSNT)
   initial_define_lispy_key (Vspecial_event_map, "language-change",
                            "ignore");
 
   initial_define_lispy_key (Vspecial_event_map, "config-changed-event",
                            "ignore");
 #if defined (WINDOWSNT)
   initial_define_lispy_key (Vspecial_event_map, "language-change",
                            "ignore");
-  initial_define_lispy_key (Vspecial_event_map, "file-w32notify",
-                           "w32notify-handle-event");
 #endif
 #endif
+  initial_define_lispy_key (Vspecial_event_map, "focus-in",
+                           "handle-focus-in");
+  initial_define_lispy_key (Vspecial_event_map, "focus-out",
+                           "handle-focus-out");
 }
 
 /* Mark the pointers in the kboard objects.
 }
 
 /* Mark the pointers in the kboard objects.