Convert safe_call to use variable number of arguments.
[bpt/emacs.git] / src / keyboard.c
index 9ff19d6..00e6f4c 100644 (file)
@@ -30,8 +30,8 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include "keyboard.h"
 #include "window.h"
 #include "commands.h"
-#include "buffer.h"
 #include "character.h"
+#include "buffer.h"
 #include "disptab.h"
 #include "dispextern.h"
 #include "syntax.h"
@@ -122,7 +122,7 @@ static Lisp_Object recent_keys;
    actually mean something.
    It's easier to staticpro a single Lisp_Object than an array.  */
 Lisp_Object this_command_keys;
-int this_command_key_count;
+ptrdiff_t this_command_key_count;
 
 /* 1 after calling Freset_this_command_lengths.
    Usually it is 0.  */
@@ -135,16 +135,16 @@ static int raw_keybuf_count;
 
 #define GROW_RAW_KEYBUF                                                        \
  if (raw_keybuf_count == ASIZE (raw_keybuf))                           \
-   raw_keybuf = larger_vector (raw_keybuf, raw_keybuf_count * 2, Qnil)  \
+   raw_keybuf = larger_vector (raw_keybuf, 1, -1)
 
 /* Number of elements of this_command_keys
    that precede this key sequence.  */
-static int this_single_command_key_start;
+static ptrdiff_t this_single_command_key_start;
 
 /* Record values of this_command_key_count and echo_length ()
    before this command was read.  */
-static int before_command_key_count;
-static int before_command_echo_length;
+static ptrdiff_t before_command_key_count;
+static ptrdiff_t before_command_echo_length;
 
 /* For longjmp to where kbd input is being done.  */
 
@@ -208,20 +208,17 @@ EMACS_INT command_loop_level;
 Lisp_Object unread_switch_frame;
 
 /* Last size recorded for a current buffer which is not a minibuffer.  */
-static EMACS_INT last_non_minibuf_size;
+static ptrdiff_t last_non_minibuf_size;
 
 /* Total number of times read_char has returned, modulo UINTMAX_MAX + 1.  */
 uintmax_t num_input_events;
 
 /* Value of num_nonmacro_input_events as of last auto save.  */
 
-static int last_auto_save;
-
-/* This is like Vthis_command, except that commands never set it.  */
-Lisp_Object real_this_command;
+static EMACS_INT last_auto_save;
 
 /* The value of point when the last command was started.  */
-static EMACS_INT last_point_position;
+static ptrdiff_t last_point_position;
 
 /* The buffer that was current when the last command was started.  */
 static Lisp_Object last_point_position_buffer;
@@ -377,7 +374,7 @@ EMACS_TIME timer_check (void);
 
 static void record_menu_key (Lisp_Object c);
 static void echo_now (void);
-static int echo_length (void);
+static ptrdiff_t echo_length (void);
 
 static Lisp_Object Qpolling_period;
 
@@ -448,9 +445,9 @@ static Lisp_Object make_lispy_movement (struct frame *, Lisp_Object,
                                         Lisp_Object, Lisp_Object,
                                        Time);
 #endif
-static Lisp_Object modify_event_symbol (EMACS_INT, unsigned, Lisp_Object,
+static Lisp_Object modify_event_symbol (ptrdiff_t, int, Lisp_Object,
                                         Lisp_Object, const char *const *,
-                                        Lisp_Object *, EMACS_INT);
+                                        Lisp_Object *, ptrdiff_t);
 static Lisp_Object make_lispy_switch_frame (Lisp_Object);
 static int help_char_p (Lisp_Object);
 static void save_getcjmp (jmp_buf);
@@ -462,10 +459,8 @@ static void interrupt_signal (int signalnum);
 #ifdef SIGIO
 static void input_available_signal (int signo);
 #endif
-static Lisp_Object (Fcommand_execute) (Lisp_Object, Lisp_Object, Lisp_Object,
-                                      Lisp_Object);
 static void handle_interrupt (void);
-static void quit_throw_to_read_char (int) NO_RETURN;
+static _Noreturn void quit_throw_to_read_char (int);
 static void process_special_events (void);
 static void timer_start_idle (void);
 static void timer_stop_idle (void);
@@ -485,7 +480,7 @@ echo_char (Lisp_Object c)
   if (current_kboard->immediate_echo)
     {
       int size = KEY_DESCRIPTION_SIZE + 100;
-      char *buffer = (char *) alloca (size);
+      char *buffer = alloca (size);
       char *ptr = buffer;
       Lisp_Object echo_string;
 
@@ -507,7 +502,7 @@ echo_char (Lisp_Object c)
            {
              int offset = ptr - buffer;
              size = max (2 * size, size + nbytes);
-             buffer = (char *) alloca (size);
+             buffer = alloca (size);
              ptr = buffer + offset;
            }
 
@@ -525,7 +520,7 @@ echo_char (Lisp_Object c)
            {
              int offset = ptr - buffer;
              size += len;
-             buffer = (char *) alloca (size);
+             buffer = alloca (size);
              ptr = buffer + offset;
            }
 
@@ -615,7 +610,7 @@ echo_now (void)
 {
   if (!current_kboard->immediate_echo)
     {
-      int i;
+      ptrdiff_t i;
       current_kboard->immediate_echo = 1;
 
       for (i = 0; i < this_command_key_count; i++)
@@ -628,7 +623,7 @@ echo_now (void)
          if (i == this_single_command_key_start)
            before_command_echo_length = echo_length ();
 
-         c = XVECTOR (this_command_keys)->contents[i];
+         c = AREF (this_command_keys, i);
          if (! (EVENT_HAS_PARAMETERS (c)
                 && EQ (EVENT_HEAD_KIND (EVENT_HEAD (c)), Qmouse_movement)))
            echo_char (c);
@@ -673,7 +668,7 @@ cancel_echoing (void)
 
 /* Return the length of the current echo string.  */
 
-static int
+static ptrdiff_t
 echo_length (void)
 {
   return (STRINGP (KVAR (current_kboard, echo_string))
@@ -686,7 +681,7 @@ echo_length (void)
    switches frames while entering a key sequence.  */
 
 static void
-echo_truncate (EMACS_INT nchars)
+echo_truncate (ptrdiff_t nchars)
 {
   if (STRINGP (KVAR (current_kboard, echo_string)))
     KVAR (current_kboard, echo_string)
@@ -715,9 +710,7 @@ add_command_key (Lisp_Object key)
 #endif
 
   if (this_command_key_count >= ASIZE (this_command_keys))
-    this_command_keys = larger_vector (this_command_keys,
-                                      2 * ASIZE (this_command_keys),
-                                      Qnil);
+    this_command_keys = larger_vector (this_command_keys, 1, -1);
 
   ASET (this_command_keys, this_command_key_count, key);
   ++this_command_key_count;
@@ -727,7 +720,7 @@ add_command_key (Lisp_Object key)
 Lisp_Object
 recursive_edit_1 (void)
 {
-  int count = SPECPDL_INDEX ();
+  ptrdiff_t count = SPECPDL_INDEX ();
   Lisp_Object val;
 
   if (command_loop_level > 0)
@@ -795,7 +788,7 @@ Alternatively, `(throw 'exit t)' makes this function signal an error.
 This function is called by the editor initialization to begin editing.  */)
   (void)
 {
-  int count = SPECPDL_INDEX ();
+  ptrdiff_t count = SPECPDL_INDEX ();
   Lisp_Object buffer;
 
   /* If we enter while input is blocked, don't lock up here.
@@ -891,8 +884,7 @@ static struct kboard_stack *kboard_stack;
 void
 push_kboard (struct kboard *k)
 {
-  struct kboard_stack *p
-    = (struct kboard_stack *) xmalloc (sizeof (struct kboard_stack));
+  struct kboard_stack *p = xmalloc (sizeof *p);
 
   p->next = kboard_stack;
   p->kboard = current_kboard;
@@ -1200,7 +1192,13 @@ This also exits all active minibuffers.  */)
   Fthrow (Qtop_level, Qnil);
 }
 
-static Lisp_Object Fexit_recursive_edit (void) NO_RETURN;
+static _Noreturn void
+user_error (const char *msg)
+{
+  xsignal1 (Quser_error, build_string (msg));
+}
+
+_Noreturn
 DEFUN ("exit-recursive-edit", Fexit_recursive_edit, Sexit_recursive_edit, 0, 0, "",
        doc: /* Exit from the innermost recursive edit or minibuffer.  */)
   (void)
@@ -1208,10 +1206,10 @@ DEFUN ("exit-recursive-edit", Fexit_recursive_edit, Sexit_recursive_edit, 0, 0,
   if (command_loop_level > 0 || minibuf_level > 0)
     Fthrow (Qexit, Qnil);
 
-  error ("No recursive edit is in progress");
+  user_error ("No recursive edit is in progress");
 }
 
-static Lisp_Object Fabort_recursive_edit (void) NO_RETURN;
+_Noreturn
 DEFUN ("abort-recursive-edit", Fabort_recursive_edit, Sabort_recursive_edit, 0, 0, "",
        doc: /* Abort the command that requested this recursive edit or minibuffer input.  */)
   (void)
@@ -1219,7 +1217,7 @@ DEFUN ("abort-recursive-edit", Fabort_recursive_edit, Sabort_recursive_edit, 0,
   if (command_loop_level > 0 || minibuf_level > 0)
     Fthrow (Qexit, Qt);
 
-  error ("No recursive edit is in progress");
+  user_error ("No recursive edit is in progress");
 }
 \f
 #if defined (HAVE_MOUSE) || defined (HAVE_GPM)
@@ -1256,7 +1254,7 @@ Normally, mouse motion is ignored.
 usage: (track-mouse BODY...)  */)
   (Lisp_Object args)
 {
-  int count = SPECPDL_INDEX ();
+  ptrdiff_t count = SPECPDL_INDEX ();
   Lisp_Object val;
 
   record_unwind_protect (tracking_off, do_mouse_tracking);
@@ -1307,7 +1305,7 @@ some_mouse_moved (void)
 static int read_key_sequence (Lisp_Object *, int, Lisp_Object,
                               int, int, int);
 void safe_run_hooks (Lisp_Object);
-static void adjust_point_for_property (EMACS_INT, int);
+static void adjust_point_for_property (ptrdiff_t, int);
 
 /* Cancel hourglass from protect_unwind.
    ARG is not used.  */
@@ -1320,10 +1318,12 @@ cancel_hourglass_unwind (Lisp_Object arg)
 }
 #endif
 
+/* The last boundary auto-added to buffer-undo-list.  */
+Lisp_Object last_undo_boundary;
+
 /* FIXME: This is wrong rather than test window-system, we should call
    a new set-selection, which will then dispatch to x-set-selection, or
    tty-set-selection, or w32-set-selection, ...  */
-EXFUN (Fwindow_system, 1);
 
 Lisp_Object
 command_loop_1 (void)
@@ -1331,7 +1331,7 @@ command_loop_1 (void)
   Lisp_Object cmd;
   Lisp_Object keybuf[30];
   int i;
-  int prev_modiff = 0;
+  EMACS_INT prev_modiff = 0;
   struct buffer *prev_buffer = NULL;
 #if 0 /* This shouldn't be necessary anymore.  --lorentey  */
   int was_locked = single_kboard;
@@ -1372,9 +1372,9 @@ command_loop_1 (void)
 
   /* Do this after running Vpost_command_hook, for consistency.  */
   KVAR (current_kboard, Vlast_command) = Vthis_command;
-  KVAR (current_kboard, Vreal_last_command) = real_this_command;
+  KVAR (current_kboard, Vreal_last_command) = Vreal_this_command;
   if (!CONSP (last_command_event))
-    KVAR (current_kboard, Vlast_repeatable_command) = real_this_command;
+    KVAR (current_kboard, Vlast_repeatable_command) = Vreal_this_command;
 
   while (1)
     {
@@ -1403,7 +1403,7 @@ command_loop_1 (void)
        {
          /* Bind inhibit-quit to t so that C-g gets read in
             rather than quitting back to the minibuffer.  */
-         int count = SPECPDL_INDEX ();
+         ptrdiff_t count = SPECPDL_INDEX ();
          specbind (Qinhibit_quit, Qt);
 
          sit_for (Vminibuffer_message_timeout, 0, 2);
@@ -1441,7 +1441,7 @@ command_loop_1 (void)
       before_command_echo_length = echo_length ();
 
       Vthis_command = Qnil;
-      real_this_command = Qnil;
+      Vreal_this_command = Qnil;
       Vthis_original_command = Qnil;
       Vthis_command_keys_shift_translated = Qnil;
 
@@ -1480,10 +1480,10 @@ command_loop_1 (void)
         from that position.  But also throw away beg_unchanged and
         end_unchanged information in that case, so that redisplay will
         update the whole window properly.  */
-      if (!NILP (XWINDOW (selected_window)->force_start))
+      if (XWINDOW (selected_window)->force_start)
        {
          struct buffer *b;
-         XWINDOW (selected_window)->force_start = Qnil;
+         XWINDOW (selected_window)->force_start = 0;
          b = XBUFFER (XWINDOW (selected_window)->buffer);
          BUF_BEG_UNCHANGED (b) = BUF_END_UNCHANGED (b) = 0;
        }
@@ -1525,7 +1525,7 @@ command_loop_1 (void)
       /* Execute the command.  */
 
       Vthis_command = cmd;
-      real_this_command = cmd;
+      Vreal_this_command = cmd;
       safe_run_hooks (Qpre_command_hook);
 
       already_adjusted = 0;
@@ -1557,7 +1557,7 @@ command_loop_1 (void)
          /* Here for a command that isn't executed directly.  */
 
 #ifdef HAVE_WINDOW_SYSTEM
-            int scount = SPECPDL_INDEX ();
+            ptrdiff_t scount = SPECPDL_INDEX ();
 
             if (display_hourglass_p
                 && NILP (Vexecuting_kbd_macro))
@@ -1568,7 +1568,13 @@ command_loop_1 (void)
 #endif
 
             if (NILP (KVAR (current_kboard, Vprefix_arg))) /* FIXME: Why?  --Stef  */
-              Fundo_boundary ();
+              {
+               Lisp_Object undo = BVAR (current_buffer, undo_list);
+               Fundo_boundary ();
+               last_undo_boundary
+                 = (EQ (undo, BVAR (current_buffer, undo_list))
+                    ? Qnil : BVAR (current_buffer, undo_list));
+             }
             Fcommand_execute (Vthis_command, Qnil, Qnil, Qnil);
 
 #ifdef HAVE_WINDOW_SYSTEM
@@ -1609,12 +1615,14 @@ command_loop_1 (void)
         If the command didn't actually create a prefix arg,
         but is merely a frame event that is transparent to prefix args,
         then the above doesn't apply.  */
-      if (NILP (KVAR (current_kboard, Vprefix_arg)) || CONSP (last_command_event))
+      if (NILP (KVAR (current_kboard, Vprefix_arg))
+         || CONSP (last_command_event))
        {
          KVAR (current_kboard, Vlast_command) = Vthis_command;
-         KVAR (current_kboard, Vreal_last_command) = real_this_command;
+         KVAR (current_kboard, Vreal_last_command) = Vreal_this_command;
          if (!CONSP (last_command_event))
-           KVAR (current_kboard, Vlast_repeatable_command) = real_this_command;
+           KVAR (current_kboard, Vlast_repeatable_command)
+             = Vreal_this_command;
          cancel_echoing ();
          this_command_key_count = 0;
          this_command_key_count_reset = 0;
@@ -1651,9 +1659,9 @@ command_loop_1 (void)
                  && NILP (Fmemq (Vthis_command,
                                  Vselection_inhibit_update_commands)))
                {
-                 EMACS_INT beg =
+                 ptrdiff_t beg =
                    XINT (Fmarker_position (BVAR (current_buffer, mark)));
-                 EMACS_INT end = PT;
+                 ptrdiff_t end = PT;
                  if (beg < end)
                    call2 (Qx_set_selection, QPRIMARY,
                           make_buffer_string (beg, end, 0));
@@ -1713,16 +1721,16 @@ command_loop_1 (void)
    LAST_PT is the last position of point.  */
 
 static void
-adjust_point_for_property (EMACS_INT last_pt, int modified)
+adjust_point_for_property (ptrdiff_t last_pt, int modified)
 {
-  EMACS_INT beg, end;
+  ptrdiff_t beg, end;
   Lisp_Object val, overlay, tmp;
   /* When called after buffer modification, we should temporarily
      suppress the point adjustment for automatic composition so that a
      user can keep inserting another character at point or keep
      deleting characters around point.  */
   int check_composition = ! modified, check_display = 1, check_invisible = 1;
-  EMACS_INT orig_pt = PT;
+  ptrdiff_t orig_pt = PT;
 
   /* FIXME: cycling is probably not necessary because these properties
      can't be usefully combined anyway.  */
@@ -1749,7 +1757,7 @@ adjust_point_for_property (EMACS_INT last_pt, int modified)
          && (beg < PT /* && end > PT   <- It's always the case.  */
              || (beg <= PT && STRINGP (val) && SCHARS (val) == 0)))
        {
-         xassert (end > PT);
+         eassert (end > PT);
          SET_PT (PT < last_pt
                  ? (STRINGP (val) && SCHARS (val) == 0
                     ? max (beg - 1, BEGV)
@@ -1831,7 +1839,7 @@ adjust_point_for_property (EMACS_INT last_pt, int modified)
 #if 0 /* This assertion isn't correct, because SET_PT may end up setting
         the point to something other than its argument, due to
         point-motion hooks, intangibility, etc.  */
-         xassert (PT == beg || PT == end);
+         eassert (PT == beg || PT == end);
 #endif
 
          /* Pretend the area doesn't exist if the buffer is not
@@ -1937,7 +1945,7 @@ safe_run_hooks (Lisp_Object hook)
   /* FIXME: our `internal_condition_case' does not provide any way to pass data
      to its body or to its handlers other than via globals such as
      dynamically-bound variables ;-)  */
-  int count = SPECPDL_INDEX ();
+  ptrdiff_t count = SPECPDL_INDEX ();
   specbind (Qinhibit_quit, hook);
 
   run_hook_with_args (1, &hook, safe_run_hook_funcall);
@@ -2017,12 +2025,12 @@ start_polling (void)
       if (poll_timer == NULL
          || EMACS_SECS (poll_timer->interval) != polling_period)
        {
-         EMACS_TIME interval;
+         time_t period = max (1, min (polling_period, TYPE_MAXIMUM (time_t)));
+         EMACS_TIME interval = make_emacs_time (period, 0);
 
          if (poll_timer)
            cancel_atimer (poll_timer);
 
-         EMACS_SET_SECS_USECS (interval, polling_period, 0);
          poll_timer = start_atimer (ATIMER_CONTINUOUS, interval,
                                     poll_for_input, NULL);
        }
@@ -2090,7 +2098,7 @@ void
 bind_polling_period (int n)
 {
 #ifdef POLL_FOR_INPUT
-  int new = polling_period;
+  EMACS_INT new = polling_period;
 
   if (n > new)
     new = n;
@@ -2177,14 +2185,7 @@ show_help_echo (Lisp_Object help, Lisp_Object window, Lisp_Object object,
   if (!NILP (help) && !STRINGP (help))
     {
       if (FUNCTIONP (help))
-       {
-         Lisp_Object args[4];
-         args[0] = help;
-         args[1] = window;
-         args[2] = object;
-         args[3] = pos;
-         help = safe_call (4, args);
-       }
+       help = safe_call (4, help, window, object, pos);
       else
        help = safe_eval (help);
 
@@ -2220,7 +2221,7 @@ 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, int *used_mouse_menu,
-                                        struct timeval *end_time);
+                                        EMACS_TIME *end_time);
 static void record_char (Lisp_Object c);
 
 static Lisp_Object help_form_saved_window_configs;
@@ -2272,10 +2273,10 @@ do { if (polling_stopped_here) start_polling ();        \
 Lisp_Object
 read_char (int commandflag, ptrdiff_t nmaps, Lisp_Object *maps,
           Lisp_Object prev_event,
-          int *used_mouse_menu, struct timeval *end_time)
+          int *used_mouse_menu, EMACS_TIME *end_time)
 {
   volatile Lisp_Object c;
-  int jmpcount;
+  ptrdiff_t jmpcount;
   jmp_buf local_getcjmp;
   jmp_buf save_jump;
   volatile int key_already_recorded = 0;
@@ -2664,7 +2665,7 @@ read_char (int commandflag, ptrdiff_t nmaps, Lisp_Object *maps,
   if (INTERACTIVE && NILP (c))
     {
       int delay_level;
-      EMACS_INT buffer_size;
+      ptrdiff_t buffer_size;
 
       /* Slow down auto saves logarithmically in size of current buffer,
         and garbage collect while we're at it.  */
@@ -2685,8 +2686,9 @@ read_char (int commandflag, ptrdiff_t nmaps, Lisp_Object *maps,
          && XINT (Vauto_save_timeout) > 0)
        {
          Lisp_Object tem0;
-         int timeout = delay_level * XFASTINT (Vauto_save_timeout) / 4;
-
+         EMACS_INT timeout = (delay_level
+                              * min (XFASTINT (Vauto_save_timeout) / 4,
+                                     MOST_POSITIVE_FIXNUM / delay_level));
          save_getcjmp (save_jump);
          restore_getcjmp (local_getcjmp);
          tem0 = sit_for (make_number (timeout), 1, 1);
@@ -2696,17 +2698,13 @@ read_char (int commandflag, ptrdiff_t nmaps, Lisp_Object *maps,
              && ! CONSP (Vunread_command_events))
            {
              Fdo_auto_save (Qnil, Qnil);
-
-             /* If we have auto-saved and there is still no input
-                available, garbage collect if there has been enough
-                consing going on to make it worthwhile.  */
-             if (!detect_input_pending_run_timers (0)
-                 && consing_since_gc > gc_cons_threshold / 2)
-               Fgarbage_collect ();
-
              redisplay ();
            }
        }
+
+      /* If there is still no input available, ask for GC.  */
+      if (!detect_input_pending_run_timers (0))
+       maybe_gc ();
     }
 
   /* Notify the caller if an autosave hook, or a timer, sentinel or
@@ -2785,13 +2783,8 @@ read_char (int commandflag, ptrdiff_t nmaps, Lisp_Object *maps,
     {
       KBOARD *kb IF_LINT (= NULL);
 
-      if (end_time)
-       {
-         EMACS_TIME now;
-         EMACS_GET_TIME (now);
-         if (EMACS_TIME_GE (now, *end_time))
-           goto exit;
-       }
+      if (end_time && EMACS_TIME_LE (*end_time, current_emacs_time ()))
+       goto exit;
 
       /* Actually read a character, waiting if necessary.  */
       save_getcjmp (save_jump);
@@ -2880,7 +2873,7 @@ read_char (int commandflag, ptrdiff_t nmaps, Lisp_Object *maps,
       struct buffer *prev_buffer = current_buffer;
 #if 0 /* This shouldn't be necessary anymore. --lorentey  */
       int was_locked = single_kboard;
-      int count = SPECPDL_INDEX ();
+      ptrdiff_t count = SPECPDL_INDEX ();
       record_single_kboard_state ();
 #endif
 
@@ -2984,11 +2977,16 @@ read_char (int commandflag, ptrdiff_t nmaps, Lisp_Object *maps,
      own stuff with the echo area.  */
   if (!CONSP (c)
       || (!(EQ (Qhelp_echo, XCAR (c)))
-         && !(EQ (Qswitch_frame, XCAR (c)))))
+         && !(EQ (Qswitch_frame, XCAR (c)))
+         /* Don't wipe echo area for select window events: These might
+            get delayed via `mouse-autoselect-window' (Bug#11304).  */
+         && !(EQ (Qselect_window, XCAR (c)))))
     {
       if (!NILP (echo_area_buffer[0]))
-       safe_run_hooks (Qecho_area_clear_hook);
-      clear_message (1, 0);
+       {
+         safe_run_hooks (Qecho_area_clear_hook);
+         clear_message (1, 0);
+       }
     }
 
  reread_for_input_method:
@@ -3002,9 +3000,10 @@ read_char (int commandflag, ptrdiff_t nmaps, Lisp_Object *maps,
       && ' ' <= XINT (c) && XINT (c) < 256 && XINT (c) != 127)
     {
       Lisp_Object keys;
-      int key_count, key_count_reset;
+      ptrdiff_t key_count;
+      int key_count_reset;
       struct gcpro gcpro1;
-      int count = SPECPDL_INDEX ();
+      ptrdiff_t count = SPECPDL_INDEX ();
 
       /* Save the echo status.  */
       int saved_immediate_echo = current_kboard->immediate_echo;
@@ -3141,7 +3140,7 @@ read_char (int commandflag, ptrdiff_t nmaps, Lisp_Object *maps,
   /* Process the help character specially if enabled */
   if (!NILP (Vhelp_form) && help_char_p (c))
     {
-      int count = SPECPDL_INDEX ();
+      ptrdiff_t count = SPECPDL_INDEX ();
 
       help_form_saved_window_configs
        = Fcons (Fcurrent_window_configuration (Qnil),
@@ -3301,7 +3300,7 @@ record_char (Lisp_Object c)
 
   if (!recorded)
     {
-      total_keys++;
+      total_keys += total_keys < NUM_RECENT_KEYS;
       ASET (recent_keys, recent_keys_index, c);
       if (++recent_keys_index >= NUM_RECENT_KEYS)
        recent_keys_index = 0;
@@ -3670,7 +3669,7 @@ kbd_buffer_unget_event (register struct input_event *event)
 
 void
 gen_help_event (Lisp_Object help, Lisp_Object frame, Lisp_Object window,
-               Lisp_Object object, EMACS_INT pos)
+               Lisp_Object object, ptrdiff_t pos)
 {
   struct input_event event;
 
@@ -3773,9 +3772,8 @@ clear_event (struct input_event *event)
 static Lisp_Object
 kbd_buffer_get_event (KBOARD **kbp,
                       int *used_mouse_menu,
-                      struct timeval *end_time)
+                      EMACS_TIME *end_time)
 {
-  register int c;
   Lisp_Object obj;
 
 #ifdef subprocesses
@@ -3792,16 +3790,18 @@ kbd_buffer_get_event (KBOARD **kbp,
     }
 #endif /* subprocesses */
 
+#ifndef HAVE_DBUS  /* We want to read D-Bus events in batch mode.  */
   if (noninteractive
       /* In case we are running as a daemon, only do this before
         detaching from the terminal.  */
       || (IS_DAEMON && daemon_pipe[1] >= 0))
     {
-      c = getchar ();
+      int c = getchar ();
       XSETINT (obj, c);
       *kbp = current_kboard;
       return obj;
     }
+#endif /* ! HAVE_DBUS  */
 
   /* Wait until there is input available.  */
   for (;;)
@@ -3839,15 +3839,15 @@ kbd_buffer_get_event (KBOARD **kbp,
 #endif
       if (end_time)
        {
-         EMACS_TIME duration;
-         EMACS_GET_TIME (duration);
-         if (EMACS_TIME_GE (duration, *end_time))
-           return Qnil;        /* finished waiting */
+         EMACS_TIME now = current_emacs_time ();
+         if (EMACS_TIME_LE (*end_time, now))
+           return Qnil;        /* Finished waiting.  */
          else
            {
-             EMACS_SUB_TIME (duration, *end_time, duration);
-             wait_reading_process_output (EMACS_SECS (duration),
-                                          EMACS_USECS (duration),
+             EMACS_TIME duration = sub_emacs_time (*end_time, now);
+             wait_reading_process_output (min (EMACS_SECS (duration),
+                                               WAIT_READING_MAX),
+                                          EMACS_NSECS (duration),
                                           -1, 1, Qnil, NULL, 0);
            }
        }
@@ -3969,9 +3969,11 @@ kbd_buffer_get_event (KBOARD **kbp,
 #if defined (WINDOWSNT)
       else if (event->kind == LANGUAGE_CHANGE_EVENT)
        {
-         /* Make an event (language-change (FRAME CHARSET LCID)).  */
-         obj = Fcons (event->frame_or_window, Qnil);
-         obj = Fcons (Qlanguage_change, Fcons (obj, Qnil));
+         /* 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)));
          kbd_fetch_ptr = event + 1;
        }
 #endif
@@ -4242,11 +4244,10 @@ timer_start_idle (void)
   Lisp_Object timers;
 
   /* If we are already in the idle state, do nothing.  */
-  if (! EMACS_TIME_NEG_P (timer_idleness_start_time))
+  if (EMACS_TIME_VALID_P (timer_idleness_start_time))
     return;
 
-  EMACS_GET_TIME (timer_idleness_start_time);
-
+  timer_idleness_start_time = current_emacs_time ();
   timer_last_idleness_start_time = timer_idleness_start_time;
 
   /* Mark all idle-time timers as once again candidates for running.  */
@@ -4256,9 +4257,9 @@ timer_start_idle (void)
 
       timer = XCAR (timers);
 
-      if (!VECTORP (timer) || ASIZE (timer) != 8)
+      if (!VECTORP (timer) || ASIZE (timer) != 9)
        continue;
-      XVECTOR (timer)->contents[0] = Qnil;
+      ASET (timer, 0, Qnil);
     }
 }
 
@@ -4267,7 +4268,7 @@ timer_start_idle (void)
 static void
 timer_stop_idle (void)
 {
-  EMACS_SET_SECS_USECS (timer_idleness_start_time, -1, -1);
+  timer_idleness_start_time = invalid_emacs_time ();
 }
 
 /* Resume idle timer from last idle start time.  */
@@ -4275,7 +4276,7 @@ timer_stop_idle (void)
 static void
 timer_resume_idle (void)
 {
-  if (! EMACS_TIME_NEG_P (timer_idleness_start_time))
+  if (EMACS_TIME_VALID_P (timer_idleness_start_time))
     return;
 
   timer_idleness_start_time = timer_last_idleness_start_time;
@@ -4289,6 +4290,24 @@ struct input_event last_timer_event EXTERNALLY_VISIBLE;
    ...).  Each element has the form (FUN . ARGS).  */
 Lisp_Object pending_funcalls;
 
+/* If TIMER is a valid timer, return nonzero and place its value into
+   *RESULT.  Otherwise return zero.  */
+static int
+decode_timer (Lisp_Object timer, EMACS_TIME *result)
+{
+  Lisp_Object *vector;
+
+  if (! (VECTORP (timer) && ASIZE (timer) == 9))
+    return 0;
+  vector = XVECTOR (timer)->contents;
+  if (! NILP (vector[0]))
+    return 0;
+
+  return decode_time_components (vector[1], vector[2], vector[3], vector[4],
+                                result, 0);
+}
+
+
 /* Check whether a timer has fired.  To prevent larger problems we simply
    disregard elements that are not proper timers.  Do not make a circular
    timer list for the time being.
@@ -4306,17 +4325,16 @@ timer_check_2 (void)
 {
   EMACS_TIME nexttime;
   EMACS_TIME now;
-  EMACS_TIME idleness_now IF_LINT (= {0});
+  EMACS_TIME idleness_now;
   Lisp_Object timers, idle_timers, chosen_timer;
   struct gcpro gcpro1, gcpro2, gcpro3;
 
-  EMACS_SET_SECS (nexttime, -1);
-  EMACS_SET_USECS (nexttime, -1);
+  nexttime = invalid_emacs_time ();
 
   /* Always consider the ordinary timers.  */
   timers = Vtimer_list;
   /* Consider the idle timers only if Emacs is idle.  */
-  if (! EMACS_TIME_NEG_P (timer_idleness_start_time))
+  if (EMACS_TIME_VALID_P (timer_idleness_start_time))
     idle_timers = Vtimer_idle_list;
   else
     idle_timers = Qnil;
@@ -4333,9 +4351,10 @@ timer_check_2 (void)
 
   if (CONSP (timers) || CONSP (idle_timers))
     {
-      EMACS_GET_TIME (now);
-      if (! EMACS_TIME_NEG_P (timer_idleness_start_time))
-       EMACS_SUB_TIME (idleness_now, now, timer_idleness_start_time);
+      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));
     }
 
   while (CONSP (timers) || CONSP (idle_timers))
@@ -4344,116 +4363,82 @@ timer_check_2 (void)
       Lisp_Object timer = Qnil, idle_timer = Qnil;
       EMACS_TIME timer_time, idle_timer_time;
       EMACS_TIME difference;
-      EMACS_TIME timer_difference IF_LINT (= {0});
-      EMACS_TIME idle_timer_difference IF_LINT (= {0});
+      EMACS_TIME timer_difference = invalid_emacs_time ();
+      EMACS_TIME idle_timer_difference = invalid_emacs_time ();
+      int ripe, timer_ripe = 0, idle_timer_ripe = 0;
 
-      /* Skip past invalid timers and timers already handled.  */
+      /* Set TIMER and TIMER_DIFFERENCE
+        based on the next ordinary timer.
+        TIMER_DIFFERENCE is the distance in time from NOW to when
+        this timer becomes ripe (negative if it's already ripe).
+         Skip past invalid timers and timers already handled.  */
       if (CONSP (timers))
        {
          timer = XCAR (timers);
-         if (!VECTORP (timer) || ASIZE (timer) != 8)
+         if (! decode_timer (timer, &timer_time))
            {
              timers = XCDR (timers);
              continue;
            }
-         vector = XVECTOR (timer)->contents;
 
-         if (!INTEGERP (vector[1]) || !INTEGERP (vector[2])
-             || !INTEGERP (vector[3])
-             || ! NILP (vector[0]))
-           {
-             timers = XCDR (timers);
-             continue;
-           }
+         timer_ripe = EMACS_TIME_LE (timer_time, now);
+         timer_difference = (timer_ripe
+                             ? sub_emacs_time (now, timer_time)
+                             : sub_emacs_time (timer_time, now));
        }
+
+      /* Likewise for IDLE_TIMER and IDLE_TIMER_DIFFERENCE
+        based on the next idle timer.  */
       if (CONSP (idle_timers))
        {
-         timer = XCAR (idle_timers);
-         if (!VECTORP (timer) || ASIZE (timer) != 8)
-           {
-             idle_timers = XCDR (idle_timers);
-             continue;
-           }
-         vector = XVECTOR (timer)->contents;
-
-         if (!INTEGERP (vector[1]) || !INTEGERP (vector[2])
-             || !INTEGERP (vector[3])
-             || ! NILP (vector[0]))
+         idle_timer = XCAR (idle_timers);
+         if (! decode_timer (idle_timer, &idle_timer_time))
            {
              idle_timers = XCDR (idle_timers);
              continue;
            }
-       }
-
-      /* Set TIMER, TIMER_TIME and TIMER_DIFFERENCE
-        based on the next ordinary timer.
-        TIMER_DIFFERENCE is the distance in time from NOW to when
-        this timer becomes ripe (negative if it's already ripe).  */
-      if (CONSP (timers))
-       {
-         timer = XCAR (timers);
-         vector = XVECTOR (timer)->contents;
-         EMACS_SET_SECS (timer_time,
-                         (XINT (vector[1]) << 16) | (XINT (vector[2])));
-         EMACS_SET_USECS (timer_time, XINT (vector[3]));
-         EMACS_SUB_TIME (timer_difference, timer_time, now);
-       }
 
-      /* Set IDLE_TIMER, IDLE_TIMER_TIME and IDLE_TIMER_DIFFERENCE
-        based on the next idle timer.  */
-      if (CONSP (idle_timers))
-       {
-         idle_timer = XCAR (idle_timers);
-         vector = XVECTOR (idle_timer)->contents;
-         EMACS_SET_SECS (idle_timer_time,
-                         (XINT (vector[1]) << 16) | (XINT (vector[2])));
-         EMACS_SET_USECS (idle_timer_time, XINT (vector[3]));
-         EMACS_SUB_TIME (idle_timer_difference, idle_timer_time, idleness_now);
+         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));
        }
 
       /* Decide which timer is the next timer,
-        and set CHOSEN_TIMER, VECTOR and DIFFERENCE accordingly.
+        and set CHOSEN_TIMER, DIFFERENCE, and RIPE accordingly.
         Also step down the list where we found that timer.  */
 
-      if (CONSP (timers) && CONSP (idle_timers))
-       {
-         EMACS_TIME temp;
-         EMACS_SUB_TIME (temp, timer_difference, idle_timer_difference);
-         if (EMACS_TIME_NEG_P (temp))
-           {
-             chosen_timer = timer;
-             timers = XCDR (timers);
-             difference = timer_difference;
-           }
-         else
-           {
-             chosen_timer = idle_timer;
-             idle_timers = XCDR (idle_timers);
-             difference = idle_timer_difference;
-           }
-       }
-      else if (CONSP (timers))
+      if (EMACS_TIME_VALID_P (timer_difference)
+         && (! EMACS_TIME_VALID_P (idle_timer_difference)
+             || idle_timer_ripe < timer_ripe
+             || (idle_timer_ripe == timer_ripe
+                 && (timer_ripe
+                     ? EMACS_TIME_LT (idle_timer_difference,
+                                      timer_difference)
+                     : EMACS_TIME_LT (timer_difference,
+                                      idle_timer_difference)))))
        {
          chosen_timer = timer;
          timers = XCDR (timers);
          difference = timer_difference;
+         ripe = timer_ripe;
        }
       else
        {
          chosen_timer = idle_timer;
          idle_timers = XCDR (idle_timers);
          difference = idle_timer_difference;
+         ripe = idle_timer_ripe;
        }
-      vector = XVECTOR (chosen_timer)->contents;
 
       /* If timer is ripe, run it if it hasn't been run.  */
-      if (EMACS_TIME_NEG_P (difference)
-         || (EMACS_SECS (difference) == 0
-             && EMACS_USECS (difference) == 0))
+      if (ripe)
        {
+         vector = XVECTOR (chosen_timer)->contents;
          if (NILP (vector[0]))
            {
-             int count = SPECPDL_INDEX ();
+             ptrdiff_t count = SPECPDL_INDEX ();
              Lisp_Object old_deactivate_mark = Vdeactivate_mark;
 
              /* Mark the timer as triggered to prevent problems if the lisp
@@ -4473,8 +4458,7 @@ timer_check_2 (void)
                  return 0 to indicate that.  */
            }
 
-          EMACS_SET_SECS (nexttime, 0);
-          EMACS_SET_USECS (nexttime, 0);
+         nexttime = make_emacs_time (0, 0);
        }
       else
        /* When we encounter a timer that is still waiting,
@@ -4497,7 +4481,7 @@ timer_check_2 (void)
    timer list for the time being.
 
    Returns the time to wait until the next timer fires.
-   If no timer is active, return -1.
+   If no timer is active, return an invalid value.
 
    As long as any timer is ripe, we run it.  */
 
@@ -4510,34 +4494,24 @@ timer_check (void)
     {
       nexttime = timer_check_2 ();
     }
-  while (EMACS_SECS (nexttime) == 0 && EMACS_USECS (nexttime) == 0);
+  while (EMACS_SECS (nexttime) == 0 && EMACS_NSECS (nexttime) == 0);
 
   return nexttime;
 }
 
 DEFUN ("current-idle-time", Fcurrent_idle_time, Scurrent_idle_time, 0, 0, 0,
        doc: /* Return the current length of Emacs idleness, or nil.
-The value when Emacs is idle is a list of three integers.  The first has
-the most significant 16 bits of the seconds, while the second has the least
-significant 16 bits.  The third integer gives the microsecond count.
+The value when Emacs is idle is a list of four integers (HIGH LOW USEC PSEC)
+in the same style as (current-time).
 
 The value when Emacs is not idle is nil.
 
-The microsecond count is zero on systems that do not provide
-resolution finer than a second.  */)
+NSEC is a multiple of the system clock resolution.  */)
   (void)
 {
-  if (! EMACS_TIME_NEG_P (timer_idleness_start_time))
-    {
-      EMACS_TIME now, idleness_now;
-
-      EMACS_GET_TIME (now);
-      EMACS_SUB_TIME (idleness_now, now, timer_idleness_start_time);
-
-      return list3 (make_number ((EMACS_SECS (idleness_now) >> 16) & 0xffff),
-                   make_number ((EMACS_SECS (idleness_now) >> 0)  & 0xffff),
-                   make_number (EMACS_USECS (idleness_now)));
-    }
+  if (EMACS_TIME_VALID_P (timer_idleness_start_time))
+    return make_lisp_time (sub_emacs_time (current_emacs_time (),
+                                          timer_idleness_start_time));
 
   return Qnil;
 }
@@ -5164,7 +5138,7 @@ make_lispy_position (struct frame *f, Lisp_Object x, Lisp_Object y,
       /* It's a click in window WINDOW at frame coordinates (X,Y)  */
       struct window *w = XWINDOW (window);
       Lisp_Object string_info = Qnil;
-      EMACS_INT textpos = -1;
+      ptrdiff_t textpos = -1;
       int col = -1, row = -1;
       int dx  = -1, dy  = -1;
       int width = -1, height = -1;
@@ -5188,7 +5162,7 @@ make_lispy_position (struct frame *f, Lisp_Object x, Lisp_Object y,
       else if (part == ON_MODE_LINE || part == ON_HEADER_LINE)
        {
          Lisp_Object string;
-         EMACS_INT charpos;
+         ptrdiff_t charpos;
 
          posn = (part == ON_MODE_LINE) ? Qmode_line : Qheader_line;
          /* Note that mode_line_string takes COL, ROW as pixels and
@@ -5211,7 +5185,7 @@ make_lispy_position (struct frame *f, Lisp_Object x, Lisp_Object y,
       else if (part == ON_LEFT_MARGIN || part == ON_RIGHT_MARGIN)
        {
          Lisp_Object string;
-         EMACS_INT charpos;
+         ptrdiff_t charpos;
 
          posn = (part == ON_LEFT_MARGIN) ? Qleft_margin : Qright_margin;
          col = wx;
@@ -5439,7 +5413,7 @@ make_lispy_event (struct input_event *event)
                                      Qfunction_key,
                                      KVAR (current_kboard, Vsystem_key_alist),
                                      0, &KVAR (current_kboard, system_key_syms),
-                                     TYPE_MAXIMUM (EMACS_INT));
+                                     PTRDIFF_MAX);
        }
 
       return modify_event_symbol (event->code - FUNCTION_KEY_OFFSET,
@@ -5571,9 +5545,10 @@ make_lispy_event (struct input_event *event)
 
        if (button >= ASIZE (button_down_location))
          {
+           ptrdiff_t incr = button - ASIZE (button_down_location) + 1;
            button_down_location = larger_vector (button_down_location,
-                                                 button + 1, Qnil);
-           mouse_syms = larger_vector (mouse_syms, button + 1, Qnil);
+                                                 incr, -1);
+           mouse_syms = larger_vector (mouse_syms, incr, -1);
          }
 
        start_pos_ptr = &AREF (button_down_location, button);
@@ -5873,7 +5848,9 @@ make_lispy_event (struct input_event *event)
        event->modifiers &= ~up_modifier;
 
        if (event->code >= ASIZE (mouse_syms))
-          mouse_syms = larger_vector (mouse_syms, event->code + 1, Qnil);
+          mouse_syms = larger_vector (mouse_syms,
+                                     event->code - ASIZE (mouse_syms) + 1,
+                                     -1);
 
        /* Get the symbol we should use for the mouse click.  */
        head = modify_event_symbol (event->code,
@@ -5976,9 +5953,10 @@ make_lispy_event (struct input_event *event)
 
        if (button >= ASIZE (button_down_location))
          {
+           ptrdiff_t incr = button - ASIZE (button_down_location) + 1;
            button_down_location = larger_vector (button_down_location,
-                                                 button + 1, Qnil);
-           mouse_syms = larger_vector (mouse_syms, button + 1, Qnil);
+                                                 incr, -1);
+           mouse_syms = larger_vector (mouse_syms, incr, -1);
          }
 
        start_pos_ptr = &AREF (button_down_location, button);
@@ -6080,10 +6058,10 @@ make_lispy_switch_frame (Lisp_Object frame)
    This doesn't use any caches.  */
 
 static int
-parse_modifiers_uncached (Lisp_Object symbol, EMACS_INT *modifier_end)
+parse_modifiers_uncached (Lisp_Object symbol, ptrdiff_t *modifier_end)
 {
   Lisp_Object name;
-  EMACS_INT i;
+  ptrdiff_t i;
   int modifiers;
 
   CHECK_SYMBOL (symbol);
@@ -6091,9 +6069,9 @@ parse_modifiers_uncached (Lisp_Object symbol, EMACS_INT *modifier_end)
   modifiers = 0;
   name = SYMBOL_NAME (symbol);
 
-  for (i = 0; i+2 <= SBYTES (name); )
+  for (i = 0; i < SBYTES (name) - 1; )
     {
-      EMACS_INT this_mod_end = 0;
+      ptrdiff_t this_mod_end = 0;
       int this_mod = 0;
 
       /* See if the name continues with a modifier word.
@@ -6133,7 +6111,7 @@ parse_modifiers_uncached (Lisp_Object symbol, EMACS_INT *modifier_end)
 
 #define MULTI_LETTER_MOD(BIT, NAME, LEN)                       \
          if (i + LEN + 1 <= SBYTES (name)                      \
-             && ! strncmp (SSDATA (name) + i, NAME, LEN))      \
+             && ! memcmp (SDATA (name) + i, NAME, LEN))        \
            {                                                   \
              this_mod_end = i + LEN;                           \
              this_mod = BIT;                                   \
@@ -6171,13 +6149,13 @@ parse_modifiers_uncached (Lisp_Object symbol, EMACS_INT *modifier_end)
   if (! (modifiers & (down_modifier | drag_modifier
                      | double_modifier | triple_modifier))
       && i + 7 == SBYTES (name)
-      && strncmp (SSDATA (name) + i, "mouse-", 6) == 0
+      && memcmp (SDATA (name) + i, "mouse-", 6) == 0
       && ('0' <= SREF (name, i + 6) && SREF (name, i + 6) <= '9'))
     modifiers |= click_modifier;
 
   if (! (modifiers & (double_modifier | triple_modifier))
       && i + 6 < SBYTES (name)
-      && strncmp (SSDATA (name) + i, "wheel-", 6) == 0)
+      && memcmp (SDATA (name) + i, "wheel-", 6) == 0)
     modifiers |= click_modifier;
 
   if (modifier_end)
@@ -6195,8 +6173,7 @@ apply_modifiers_uncached (int modifiers, char *base, int base_len, int base_len_
   /* Since BASE could contain nulls, we can't use intern here; we have
      to use Fintern, which expects a genuine Lisp_String, and keeps a
      reference to it.  */
-  char *new_mods
-    = (char *) alloca (sizeof ("A-C-H-M-S-s-down-drag-double-triple-"));
+  char new_mods[sizeof "A-C-H-M-S-s-down-drag-double-triple-"];
   int mod_len;
 
   {
@@ -6257,7 +6234,7 @@ lispy_modifier_list (int modifiers)
   modifier_list = Qnil;
   for (i = 0; (1<<i) <= modifiers && i < NUM_MOD_NAMES; i++)
     if (modifiers & (1<<i))
-      modifier_list = Fcons (XVECTOR (modifier_symbols)->contents[i],
+      modifier_list = Fcons (AREF (modifier_symbols, i),
                             modifier_list);
 
   return modifier_list;
@@ -6290,7 +6267,7 @@ parse_modifiers (Lisp_Object symbol)
     return elements;
   else
     {
-      EMACS_INT end;
+      ptrdiff_t end;
       int modifiers = parse_modifiers_uncached (symbol, &end);
       Lisp_Object unmodified;
       Lisp_Object mask;
@@ -6456,9 +6433,9 @@ reorder_modifiers (Lisp_Object symbol)
    in the symbol's name.  */
 
 static Lisp_Object
-modify_event_symbol (EMACS_INT symbol_num, unsigned int modifiers, Lisp_Object symbol_kind,
+modify_event_symbol (ptrdiff_t symbol_num, int modifiers, Lisp_Object symbol_kind,
                     Lisp_Object name_alist_or_stem, const char *const *name_table,
-                    Lisp_Object *symbol_table, EMACS_INT table_size)
+                    Lisp_Object *symbol_table, ptrdiff_t table_size)
 {
   Lisp_Object value;
   Lisp_Object symbol_int;
@@ -6488,7 +6465,7 @@ modify_event_symbol (EMACS_INT symbol_num, unsigned int modifiers, Lisp_Object s
          *symbol_table = Fmake_vector (size, Qnil);
        }
 
-      value = XVECTOR (*symbol_table)->contents[symbol_num];
+      value = AREF (*symbol_table, symbol_num);
     }
 
   /* Have we already used this symbol before?  */
@@ -6524,14 +6501,14 @@ modify_event_symbol (EMACS_INT symbol_num, unsigned int modifiers, Lisp_Object s
       if (NILP (value))
        {
          char buf[sizeof "key-" + INT_STRLEN_BOUND (EMACS_INT)];
-         sprintf (buf, "key-%"pI"d", symbol_num);
+         sprintf (buf, "key-%"pD"d", symbol_num);
          value = intern (buf);
        }
 
       if (CONSP (*symbol_table))
         *symbol_table = Fcons (Fcons (symbol_int, value), *symbol_table);
       else
-       XVECTOR (*symbol_table)->contents[symbol_num] = value;
+       ASET (*symbol_table, symbol_num, value);
 
       /* Fill in the cache entries for this symbol; this also
         builds the Qevent_symbol_elements property, which the user
@@ -6630,7 +6607,7 @@ parse_solitary_modifier (Lisp_Object symbol)
 
 #define MULTI_LETTER_MOD(BIT, NAME, LEN)               \
       if (LEN == SBYTES (name)                         \
-         && ! strncmp (SSDATA (name), NAME, LEN))      \
+         && ! memcmp (SDATA (name), NAME, LEN))        \
        return BIT;
 
     case 'A':
@@ -7169,6 +7146,7 @@ tty_read_avail_input (struct terminal *terminal,
   return nread;
 }
 \f
+#if defined SYNC_INPUT || defined SIGIO
 static void
 handle_async_input (void)
 {
@@ -7195,7 +7173,9 @@ handle_async_input (void)
   --handling_signal;
 #endif
 }
+#endif /* SYNC_INPUT || SIGIO */
 
+#ifdef SYNC_INPUT
 void
 process_pending_signals (void)
 {
@@ -7203,6 +7183,7 @@ process_pending_signals (void)
     handle_async_input ();
   do_pending_atimers ();
 }
+#endif
 
 #ifdef SIGIO   /* for entire page */
 /* Note SIGIO has been undef'd if FIONREAD is missing.  */
@@ -7220,7 +7201,7 @@ input_available_signal (int signo)
 #endif
 
   if (input_available_clear_time)
-    EMACS_SET_SECS_USECS (*input_available_clear_time, 0, 0);
+    *input_available_clear_time = make_emacs_time (0, 0);
 
 #ifndef SYNC_INPUT
   handle_async_input ();
@@ -7275,7 +7256,7 @@ add_user_signal (int sig, const char *name)
       /* Already added.  */
       return;
 
-  p = xmalloc (sizeof (struct user_signal_info));
+  p = xmalloc (sizeof *p);
   p->sig = sig;
   p->name = xstrdup (name);
   p->npending = 0;
@@ -7300,8 +7281,8 @@ handle_user_signal (int sig)
   for (p = user_signals; p; p = p->next)
     if (p->sig == sig)
       {
-        if (special_event_name &&
-            strcmp (special_event_name, p->name) == 0)
+        if (special_event_name
+           && strcmp (special_event_name, p->name) == 0)
           {
             /* Enter the debugger in many ways.  */
             debug_on_next_call = 1;
@@ -7323,7 +7304,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)
-             EMACS_SET_SECS_USECS (*input_available_clear_time, 0, 0);
+             *input_available_clear_time = make_emacs_time (0, 0);
          }
        break;
       }
@@ -7414,7 +7395,7 @@ menu_separator_name_p (const char *label)
   if (!label)
     return 0;
   else if (strlen (label) > 3
-          && strncmp (label, "--", 2) == 0
+          && memcmp (label, "--", 2) == 0
           && label[2] != '-')
     {
       int i;
@@ -7501,7 +7482,7 @@ menu_bar_items (Lisp_Object old)
        Lisp_Object tem;
        ptrdiff_t nminor;
        nminor = current_minor_maps (NULL, &tmaps);
-       maps = (Lisp_Object *) alloca ((nminor + 3) * sizeof (maps[0]));
+       maps = alloca ((nminor + 3) * sizeof *maps);
        nmaps = 0;
        if (tem = get_local_map (PT, current_buffer, Qkeymap), !NILP (tem))
          maps[nmaps++] = tem;
@@ -7534,23 +7515,23 @@ menu_bar_items (Lisp_Object old)
       int end = menu_bar_items_index;
 
       for (i = 0; i < end; i += 4)
-       if (EQ (XCAR (tail), XVECTOR (menu_bar_items_vector)->contents[i]))
+       if (EQ (XCAR (tail), AREF (menu_bar_items_vector, i)))
          {
            Lisp_Object tem0, tem1, tem2, tem3;
            /* Move the item at index I to the end,
               shifting all the others forward.  */
-           tem0 = XVECTOR (menu_bar_items_vector)->contents[i + 0];
-           tem1 = XVECTOR (menu_bar_items_vector)->contents[i + 1];
-           tem2 = XVECTOR (menu_bar_items_vector)->contents[i + 2];
-           tem3 = XVECTOR (menu_bar_items_vector)->contents[i + 3];
+           tem0 = AREF (menu_bar_items_vector, i + 0);
+           tem1 = AREF (menu_bar_items_vector, i + 1);
+           tem2 = AREF (menu_bar_items_vector, i + 2);
+           tem3 = AREF (menu_bar_items_vector, i + 3);
            if (end > i + 4)
-             memmove (&XVECTOR (menu_bar_items_vector)->contents[i],
-                      &XVECTOR (menu_bar_items_vector)->contents[i + 4],
+             memmove (&AREF (menu_bar_items_vector, i),
+                      &AREF (menu_bar_items_vector, i + 4),
                       (end - i - 4) * sizeof (Lisp_Object));
-           XVECTOR (menu_bar_items_vector)->contents[end - 4] = tem0;
-           XVECTOR (menu_bar_items_vector)->contents[end - 3] = tem1;
-           XVECTOR (menu_bar_items_vector)->contents[end - 2] = tem2;
-           XVECTOR (menu_bar_items_vector)->contents[end - 1] = tem3;
+           ASET (menu_bar_items_vector, end - 4, tem0);
+           ASET (menu_bar_items_vector, end - 3, tem1);
+           ASET (menu_bar_items_vector, end - 2, tem2);
+           ASET (menu_bar_items_vector, end - 1, tem3);
            break;
          }
     }
@@ -7560,12 +7541,12 @@ menu_bar_items (Lisp_Object old)
     int i = menu_bar_items_index;
     if (i + 4 > ASIZE (menu_bar_items_vector))
       menu_bar_items_vector =
-       larger_vector (menu_bar_items_vector, 2 * i, Qnil);
+       larger_vector (menu_bar_items_vector, 4, -1);
     /* Add this item.  */
-    XVECTOR (menu_bar_items_vector)->contents[i++] = Qnil;
-    XVECTOR (menu_bar_items_vector)->contents[i++] = Qnil;
-    XVECTOR (menu_bar_items_vector)->contents[i++] = Qnil;
-    XVECTOR (menu_bar_items_vector)->contents[i++] = Qnil;
+    ASET (menu_bar_items_vector, i, Qnil); i++;
+    ASET (menu_bar_items_vector, i, Qnil); i++;
+    ASET (menu_bar_items_vector, i, Qnil); i++;
+    ASET (menu_bar_items_vector, i, Qnil); i++;
     menu_bar_items_index = i;
   }
 
@@ -7591,11 +7572,11 @@ menu_bar_item (Lisp_Object key, Lisp_Object item, Lisp_Object dummy1, void *dumm
         discard any previously made menu bar item.  */
 
       for (i = 0; i < menu_bar_items_index; i += 4)
-       if (EQ (key, XVECTOR (menu_bar_items_vector)->contents[i]))
+       if (EQ (key, AREF (menu_bar_items_vector, i)))
          {
            if (menu_bar_items_index > i + 4)
-             memmove (&XVECTOR (menu_bar_items_vector)->contents[i],
-                      &XVECTOR (menu_bar_items_vector)->contents[i + 4],
+             memmove (&AREF (menu_bar_items_vector, i),
+                      &AREF (menu_bar_items_vector, i + 4),
                       (menu_bar_items_index - i - 4) * sizeof (Lisp_Object));
            menu_bar_items_index -= 4;
          }
@@ -7619,11 +7600,11 @@ menu_bar_item (Lisp_Object key, Lisp_Object item, Lisp_Object dummy1, void *dumm
   if (!i)
     return;
 
-  item = XVECTOR (item_properties)->contents[ITEM_PROPERTY_DEF];
+  item = AREF (item_properties, ITEM_PROPERTY_DEF);
 
   /* Find any existing item for this KEY.  */
   for (i = 0; i < menu_bar_items_index; i += 4)
-    if (EQ (key, XVECTOR (menu_bar_items_vector)->contents[i]))
+    if (EQ (key, AREF (menu_bar_items_vector, i)))
       break;
 
   /* If we did not find this KEY, add it at the end.  */
@@ -7631,24 +7612,24 @@ menu_bar_item (Lisp_Object key, Lisp_Object item, Lisp_Object dummy1, void *dumm
     {
       /* If vector is too small, get a bigger one.  */
       if (i + 4 > ASIZE (menu_bar_items_vector))
-       menu_bar_items_vector = larger_vector (menu_bar_items_vector, 2 * i, Qnil);
+       menu_bar_items_vector = larger_vector (menu_bar_items_vector, 4, -1);
       /* Add this item.  */
-      XVECTOR (menu_bar_items_vector)->contents[i++] = key;
-      XVECTOR (menu_bar_items_vector)->contents[i++]
-       = XVECTOR (item_properties)->contents[ITEM_PROPERTY_NAME];
-      XVECTOR (menu_bar_items_vector)->contents[i++] = Fcons (item, Qnil);
-      XVECTOR (menu_bar_items_vector)->contents[i++] = make_number (0);
+      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, make_number (0)); i++;
       menu_bar_items_index = i;
     }
   /* We did find an item for this KEY.  Add ITEM to its list of maps.  */
   else
     {
       Lisp_Object old;
-      old = XVECTOR (menu_bar_items_vector)->contents[i + 2];
+      old = AREF (menu_bar_items_vector, i + 2);
       /* If the new and the old items are not both keymaps,
         the lookup will only find `item'.  */
       item = Fcons (item, KEYMAPP (item) && KEYMAPP (XCAR (old)) ? old : Qnil);
-      XVECTOR (menu_bar_items_vector)->contents[i + 2] = item;
+      ASET (menu_bar_items_vector, i + 2, item);
     }
 }
 \f
@@ -7675,7 +7656,7 @@ eval_dyn (Lisp_Object form)
 Lisp_Object
 menu_item_eval_property (Lisp_Object sexpr)
 {
-  int count = SPECPDL_INDEX ();
+  ptrdiff_t count = SPECPDL_INDEX ();
   Lisp_Object val;
   specbind (Qinhibit_redisplay, Qt);
   val = internal_condition_case_1 (eval_dyn, sexpr, Qerror,
@@ -8028,7 +8009,7 @@ tool_bar_items (Lisp_Object reuse, int *nitems)
   if (!NILP (Voverriding_local_map_menu_flag))
     {
       /* Yes, use them (if non-nil) as well as the global map.  */
-      maps = (Lisp_Object *) alloca (3 * sizeof (maps[0]));
+      maps = alloca (3 * sizeof *maps);
       nmaps = 0;
       if (!NILP (KVAR (current_kboard, Voverriding_terminal_local_map)))
        maps[nmaps++] = KVAR (current_kboard, Voverriding_terminal_local_map);
@@ -8045,7 +8026,7 @@ tool_bar_items (Lisp_Object reuse, int *nitems)
       Lisp_Object tem;
       ptrdiff_t nminor;
       nminor = current_minor_maps (NULL, &tmaps);
-      maps = (Lisp_Object *) alloca ((nminor + 3) * sizeof (maps[0]));
+      maps = alloca ((nminor + 3) * sizeof *maps);
       nmaps = 0;
       if (tem = get_local_map (PT, current_buffer, Qkeymap), !NILP (tem))
        maps[nmaps++] = tem;
@@ -8165,7 +8146,7 @@ static int
 parse_tool_bar_item (Lisp_Object key, Lisp_Object item)
 {
   /* Access slot with index IDX of vector tool_bar_item_properties.  */
-#define PROP(IDX) XVECTOR (tool_bar_item_properties)->contents[IDX]
+#define PROP(IDX) AREF (tool_bar_item_properties, (IDX))
 
   Lisp_Object filter = Qnil;
   Lisp_Object caption;
@@ -8317,7 +8298,7 @@ parse_tool_bar_item (Lisp_Object key, Lisp_Object item)
       const char *capt = STRINGP (tcapt) ? SSDATA (tcapt) : "";
       ptrdiff_t max_lbl =
        2 * max (0, min (tool_bar_max_label_size, STRING_BYTES_BOUND / 2));
-      char *buf = (char *) xmalloc (max_lbl + 1);
+      char *buf = xmalloc (max_lbl + 1);
       Lisp_Object new_lbl;
       ptrdiff_t caption_len = strlen (capt);
 
@@ -8348,7 +8329,7 @@ parse_tool_bar_item (Lisp_Object key, Lisp_Object item)
       if (SCHARS (new_lbl) <= tool_bar_max_label_size)
         PROP (TOOL_BAR_ITEM_LABEL) = new_lbl;
       else
-        PROP (TOOL_BAR_ITEM_LABEL) = make_string ("", 0);
+        PROP (TOOL_BAR_ITEM_LABEL) = empty_unibyte_string;
       xfree (buf);
     }
 
@@ -8400,13 +8381,14 @@ static void
 append_tool_bar_item (void)
 {
   Lisp_Object *to, *from;
+  ptrdiff_t incr =
+    (ntool_bar_items
+     - (ASIZE (tool_bar_items_vector) - TOOL_BAR_ITEM_NSLOTS));
 
   /* Enlarge tool_bar_items_vector if necessary.  */
-  if (ntool_bar_items + TOOL_BAR_ITEM_NSLOTS
-      >= ASIZE (tool_bar_items_vector))
+  if (0 < incr)
     tool_bar_items_vector
-      = larger_vector (tool_bar_items_vector,
-                      2 * ASIZE (tool_bar_items_vector), Qnil);
+      = larger_vector (tool_bar_items_vector, incr, -1);
 
   /* Append entries from tool_bar_item_properties to the end of
      tool_bar_items_vector.  */
@@ -8469,8 +8451,7 @@ read_char_x_menu_prompt (ptrdiff_t nmaps, Lisp_Object *maps,
       && !EQ (XCAR (prev_event), Qtool_bar))
     {
       /* Display the menu and get the selection.  */
-      Lisp_Object *realmaps
-       = (Lisp_Object *) alloca (nmaps * sizeof (Lisp_Object));
+      Lisp_Object *realmaps = alloca (nmaps * sizeof *realmaps);
       Lisp_Object value;
       ptrdiff_t nmaps1 = 0;
 
@@ -8564,7 +8545,7 @@ read_char_minibuf_menu_prompt (int commandflag,
   if (width + 4 > read_char_minibuf_menu_width)
     {
       read_char_minibuf_menu_text
-       = (char *) xrealloc (read_char_minibuf_menu_text, width + 4);
+       = xrealloc (read_char_minibuf_menu_text, width + 4);
       read_char_minibuf_menu_width = width + 4;
     }
   menu = read_char_minibuf_menu_text;
@@ -8609,7 +8590,7 @@ read_char_minibuf_menu_prompt (int commandflag,
 
          /* Look at the next element of the map.  */
          if (idx >= 0)
-           elt = XVECTOR (vector)->contents[idx];
+           elt = AREF (vector, idx);
          else
            elt = Fcar_safe (rest);
 
@@ -8644,7 +8625,7 @@ read_char_minibuf_menu_prompt (int commandflag,
                  Lisp_Object upcased_event, downcased_event;
                  Lisp_Object desc = Qnil;
                  Lisp_Object s
-                   = XVECTOR (item_properties)->contents[ITEM_PROPERTY_NAME];
+                   = AREF (item_properties, ITEM_PROPERTY_NAME);
 
                  upcased_event = Fupcase (event);
                  downcased_event = Fdowncase (event);
@@ -8662,12 +8643,12 @@ read_char_minibuf_menu_prompt (int commandflag,
                    s = concat2 (s, tem);
 #endif
                  tem
-                   = XVECTOR (item_properties)->contents[ITEM_PROPERTY_TYPE];
+                   = AREF (item_properties, ITEM_PROPERTY_TYPE);
                  if (EQ (tem, QCradio) || EQ (tem, QCtoggle))
                    {
                      /* Insert button prefix.  */
                      Lisp_Object selected
-                       = XVECTOR (item_properties)->contents[ITEM_PROPERTY_SELECTED];
+                       = AREF (item_properties, ITEM_PROPERTY_SELECTED);
                      if (EQ (tem, QCradio))
                        tem = build_string (NILP (selected) ? "(*) " : "( ) ");
                      else
@@ -8839,18 +8820,12 @@ access_keymap_keyremap (Lisp_Object map, Lisp_Object key, Lisp_Object prompt,
 
   next = access_keymap (map, key, 1, 0, 1);
 
-  /* Handle symbol with autoload definition.  */
-  if (SYMBOLP (next) && !NILP (Ffboundp (next))
-      && CONSP (XSYMBOL (next)->function)
-      && EQ (XCAR (XSYMBOL (next)->function), Qautoload))
-    do_autoload (XSYMBOL (next)->function, next);
-
   /* Handle a symbol whose function definition is a keymap
      or an array.  */
   if (SYMBOLP (next) && !NILP (Ffboundp (next))
       && (ARRAYP (XSYMBOL (next)->function)
          || KEYMAPP (XSYMBOL (next)->function)))
-    next = XSYMBOL (next)->function;
+    next = Fautoload_do_load (XSYMBOL (next)->function, next, Qnil);
 
   /* If the keymap gives a function, not an
      array, then call the function with one arg and use
@@ -8991,15 +8966,15 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
                   int fix_current_buffer)
 {
   Lisp_Object from_string;
-  int count = SPECPDL_INDEX ();
+  ptrdiff_t count = SPECPDL_INDEX ();
 
   /* How many keys there are in the current key sequence.  */
   int t;
 
   /* The length of the echo buffer when we started reading, and
      the length of this_command_keys when we started reading.  */
-  int echo_start IF_LINT (= 0);
-  int keys_start;
+  ptrdiff_t echo_start IF_LINT (= 0);
+  ptrdiff_t keys_start;
 
   /* The number of keymaps we're scanning right now, and the number of
      keymaps we have allocated space for.  */
@@ -9171,8 +9146,8 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
     {
       if (2 > nmaps_allocated)
        {
-         submaps = (Lisp_Object *) alloca (2 * sizeof (submaps[0]));
-         defs    = (Lisp_Object *) alloca (2 * sizeof (defs[0]));
+         submaps = alloca (2 * sizeof *submaps);
+         defs    = alloca (2 * sizeof *defs);
          nmaps_allocated = 2;
        }
       submaps[nmaps++] = KVAR (current_kboard, Voverriding_terminal_local_map);
@@ -9181,8 +9156,8 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
     {
       if (2 > nmaps_allocated)
        {
-         submaps = (Lisp_Object *) alloca (2 * sizeof (submaps[0]));
-         defs    = (Lisp_Object *) alloca (2 * sizeof (defs[0]));
+         submaps = alloca (2 * sizeof *submaps);
+         defs    = alloca (2 * sizeof *defs);
          nmaps_allocated = 2;
        }
       submaps[nmaps++] = Voverriding_local_map;
@@ -9198,8 +9173,8 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
 
       if (total > nmaps_allocated)
        {
-         submaps = (Lisp_Object *) alloca (total * sizeof (submaps[0]));
-         defs    = (Lisp_Object *) alloca (total * sizeof (defs[0]));
+         submaps = alloca (total * sizeof *submaps);
+         defs    = alloca (total * sizeof *defs);
          nmaps_allocated = total;
        }
 
@@ -9255,7 +9230,7 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
         while those allow us to restart the entire key sequence,
         echo_local_start and keys_local_start allow us to throw away
         just one key.  */
-      int echo_local_start IF_LINT (= 0);
+      ptrdiff_t echo_local_start IF_LINT (= 0);
       int keys_local_start;
       ptrdiff_t local_first_binding;
 
@@ -9437,7 +9412,8 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
              && current_buffer != starting_buffer)
            {
              GROW_RAW_KEYBUF;
-             XVECTOR (raw_keybuf)->contents[raw_keybuf_count++] = key;
+             ASET (raw_keybuf, raw_keybuf_count, key);
+             raw_keybuf_count++;
              keybuf[t++] = key;
              mock_input = t;
              Vquit_flag = Qnil;
@@ -9515,7 +9491,8 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
                      && BUFFERP (XWINDOW (window)->buffer)
                      && XBUFFER (XWINDOW (window)->buffer) != current_buffer)
                    {
-                     XVECTOR (raw_keybuf)->contents[raw_keybuf_count++] = key;
+                     ASET (raw_keybuf, raw_keybuf_count, key);
+                     raw_keybuf_count++;
                      keybuf[t] = key;
                      mock_input = t + 1;
 
@@ -10143,7 +10120,7 @@ will read just one key sequence.  */)
   Lisp_Object keybuf[30];
   register int i;
   struct gcpro gcpro1;
-  int count = SPECPDL_INDEX ();
+  ptrdiff_t count = SPECPDL_INDEX ();
 
   if (!NILP (prompt))
     CHECK_STRING (prompt);
@@ -10200,7 +10177,7 @@ DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,
   Lisp_Object keybuf[30];
   register int i;
   struct gcpro gcpro1;
-  int count = SPECPDL_INDEX ();
+  ptrdiff_t count = SPECPDL_INDEX ();
 
   if (!NILP (prompt))
     CHECK_STRING (prompt);
@@ -10292,7 +10269,7 @@ a special event, so ignore the prefix argument and don't clear it.  */)
          struct gcpro gcpro1, gcpro2;
 
          GCPRO2 (cmd, prefixarg);
-         do_autoload (final, cmd);
+         Fautoload_do_load (final, cmd, Qnil);
          UNGCPRO;
        }
       else
@@ -10334,146 +10311,6 @@ a special event, so ignore the prefix argument and don't clear it.  */)
 
 
 \f
-DEFUN ("execute-extended-command", Fexecute_extended_command, Sexecute_extended_command,
-       1, 1, "P",
-       doc: /* Read function name, then read its arguments and call it.
-
-To pass a numeric argument to the command you are invoking with, specify
-the numeric argument to this command.
-
-Noninteractively, the argument PREFIXARG is the prefix argument to
-give to the command you invoke, if it asks for an argument.  */)
-  (Lisp_Object prefixarg)
-{
-  Lisp_Object function;
-  EMACS_INT saved_last_point_position;
-  Lisp_Object saved_keys, saved_last_point_position_buffer;
-  Lisp_Object bindings, value;
-  struct gcpro gcpro1, gcpro2, gcpro3;
-#ifdef HAVE_WINDOW_SYSTEM
-  /* The call to Fcompleting_read will start and cancel the hourglass,
-     but if the hourglass was already scheduled, this means that no
-     hourglass will be shown for the actual M-x command itself.
-     So we restart it if it is already scheduled.  Note that checking
-     hourglass_shown_p is not enough,  normally the hourglass is not shown,
-     just scheduled to be shown.  */
-  int hstarted = hourglass_started ();
-#endif
-
-  saved_keys = Fvector (this_command_key_count,
-                       XVECTOR (this_command_keys)->contents);
-  saved_last_point_position_buffer = last_point_position_buffer;
-  saved_last_point_position = last_point_position;
-  GCPRO3 (saved_keys, prefixarg, saved_last_point_position_buffer);
-
-  function = call0 (intern ("read-extended-command"));
-
-#ifdef HAVE_WINDOW_SYSTEM
-  if (hstarted) start_hourglass ();
-#endif
-
-  if (STRINGP (function) && SCHARS (function) == 0)
-    error ("No command name given");
-
-  /* Set this_command_keys to the concatenation of saved_keys and
-     function, followed by a RET.  */
-  {
-    Lisp_Object *keys;
-    int i;
-
-    this_command_key_count = 0;
-    this_command_key_count_reset = 0;
-    this_single_command_key_start = 0;
-
-    keys = XVECTOR (saved_keys)->contents;
-    for (i = 0; i < ASIZE (saved_keys); i++)
-      add_command_key (keys[i]);
-
-    for (i = 0; i < SCHARS (function); i++)
-      add_command_key (Faref (function, make_number (i)));
-
-    add_command_key (make_number ('\015'));
-  }
-
-  last_point_position = saved_last_point_position;
-  last_point_position_buffer = saved_last_point_position_buffer;
-
-  UNGCPRO;
-
-  function = Fintern (function, Qnil);
-  KVAR (current_kboard, Vprefix_arg) = prefixarg;
-  Vthis_command = function;
-  real_this_command = function;
-
-  /* If enabled, show which key runs this command.  */
-  if (!NILP (Vsuggest_key_bindings)
-      && NILP (Vexecuting_kbd_macro)
-      && SYMBOLP (function))
-    bindings = Fwhere_is_internal (function, Voverriding_local_map,
-                                  Qt, Qnil, Qnil);
-  else
-    bindings = Qnil;
-
-  value = Qnil;
-  GCPRO3 (bindings, value, function);
-  value = Fcommand_execute (function, Qt, Qnil, Qnil);
-
-  /* If the command has a key binding, print it now.  */
-  if (!NILP (bindings)
-      && ! (VECTORP (bindings) && EQ (Faref (bindings, make_number (0)),
-                                     Qmouse_movement)))
-    {
-      /* But first wait, and skip the message if there is input.  */
-      Lisp_Object waited;
-
-      /* If this command displayed something in the echo area;
-        wait a few seconds, then display our suggestion message.  */
-      if (NILP (echo_area_buffer[0]))
-       waited = sit_for (make_number (0), 0, 2);
-      else if (NUMBERP (Vsuggest_key_bindings))
-       waited = sit_for (Vsuggest_key_bindings, 0, 2);
-      else
-       waited = sit_for (make_number (2), 0, 2);
-
-      if (!NILP (waited) && ! CONSP (Vunread_command_events))
-       {
-         Lisp_Object binding;
-         char *newmessage;
-         int message_p = push_message ();
-         int count = SPECPDL_INDEX ();
-         ptrdiff_t newmessage_len, newmessage_alloc;
-         USE_SAFE_ALLOCA;
-
-         record_unwind_protect (pop_message_unwind, Qnil);
-         binding = Fkey_description (bindings, Qnil);
-         newmessage_alloc =
-           (sizeof "You can run the command `' with "
-            + SBYTES (SYMBOL_NAME (function)) + SBYTES (binding));
-         SAFE_ALLOCA (newmessage, char *, newmessage_alloc);
-         newmessage_len =
-           esprintf (newmessage, "You can run the command `%s' with %s",
-                     SDATA (SYMBOL_NAME (function)),
-                     SDATA (binding));
-         message2 (newmessage,
-                   newmessage_len,
-                   STRING_MULTIBYTE (binding));
-         if (NUMBERP (Vsuggest_key_bindings))
-           waited = sit_for (Vsuggest_key_bindings, 0, 2);
-         else
-           waited = sit_for (make_number (2), 0, 2);
-
-         if (!NILP (waited) && message_p)
-           restore_message ();
-
-         SAFE_FREE ();
-         unbind_to (count, Qnil);
-       }
-    }
-
-  RETURN_UNGCPRO (value);
-}
-
-\f
 /* Return nonzero if input events are pending.  */
 
 int
@@ -10686,7 +10523,7 @@ KEEP-RECORD is non-nil.  */)
   if (NILP (keep_record))
     {
       for (i = 0; i < ASIZE (recent_keys); ++i)
-       XVECTOR (recent_keys)->contents[i] = Qnil;
+       ASET (recent_keys, i, Qnil);
       total_keys = 0;
       recent_keys_index = 0;
     }
@@ -10768,7 +10605,7 @@ Some operating systems cannot stop the Emacs process and resume it later.
 On such systems, Emacs starts a subshell instead of suspending.  */)
   (Lisp_Object stuffstring)
 {
-  int count = SPECPDL_INDEX ();
+  ptrdiff_t count = SPECPDL_INDEX ();
   int old_height, old_width;
   int width, height;
   struct gcpro gcpro1;
@@ -10824,7 +10661,7 @@ stuff_buffered_input (Lisp_Object stuffstring)
 
   if (STRINGP (stuffstring))
     {
-      register EMACS_INT count;
+      register ptrdiff_t count;
 
       p = SDATA (stuffstring);
       count = SBYTES (stuffstring);
@@ -10855,7 +10692,7 @@ stuff_buffered_input (Lisp_Object stuffstring)
 }
 \f
 void
-set_waiting_for_input (struct timeval *time_to_clear)
+set_waiting_for_input (EMACS_TIME *time_to_clear)
 {
   input_available_clear_time = time_to_clear;
 
@@ -11478,7 +11315,7 @@ init_keyboard (void)
   quit_char = Ctl ('g');
   Vunread_command_events = Qnil;
   unread_command_char = -1;
-  EMACS_SET_SECS_USECS (timer_idleness_start_time, -1, -1);
+  timer_idleness_start_time = invalid_emacs_time ();
   total_keys = 0;
   recent_keys_index = 0;
   kbd_fetch_ptr = kbd_buffer;
@@ -11575,7 +11412,7 @@ syms_of_keyboard (void)
   pending_funcalls = Qnil;
   staticpro (&pending_funcalls);
 
-  Vlispy_mouse_stem = make_pure_c_string ("mouse");
+  Vlispy_mouse_stem = build_pure_c_string ("mouse");
   staticpro (&Vlispy_mouse_stem);
 
   /* Tool-bars.  */
@@ -11591,9 +11428,6 @@ syms_of_keyboard (void)
   staticpro (&tool_bar_items_vector);
   tool_bar_items_vector = Qnil;
 
-  staticpro (&real_this_command);
-  real_this_command = Qnil;
-
   DEFSYM (Qtimer_event_handler, "timer-event-handler");
   DEFSYM (Qdisabled_command_function, "disabled-command-function");
   DEFSYM (Qself_insert_command, "self-insert-command");
@@ -11708,7 +11542,7 @@ syms_of_keyboard (void)
     modifier_symbols = Fmake_vector (make_number (len), Qnil);
     for (i = 0; i < len; i++)
       if (modifier_names[i])
-       XVECTOR (modifier_symbols)->contents[i] = intern_c_string (modifier_names[i]);
+       ASET (modifier_symbols, i, intern_c_string (modifier_names[i]));
     staticpro (&modifier_symbols);
   }
 
@@ -11784,7 +11618,6 @@ syms_of_keyboard (void)
   defsubr (&Sset_quit_char);
   defsubr (&Sset_input_mode);
   defsubr (&Scurrent_input_mode);
-  defsubr (&Sexecute_extended_command);
   defsubr (&Sposn_at_point);
   defsubr (&Sposn_at_x_y);
 
@@ -11848,12 +11681,14 @@ was a kill command.
 See Info node `(elisp)Multiple Terminals'.  */);
 
   DEFVAR_KBOARD ("real-last-command", Vreal_last_command,
-                doc: /* Same as `last-command', but never altered by Lisp code.  */);
+                doc: /* Same as `last-command', but never altered by Lisp code.
+Taken from the previous value of `real-this-command'.  */);
 
   DEFVAR_KBOARD ("last-repeatable-command", Vlast_repeatable_command,
                 doc: /* Last command that may be repeated.
 The last command executed that was not bound to an input event.
-This is the command `repeat' will try to repeat.  */);
+This is the command `repeat' will try to repeat.
+Taken from a previous value of `real-this-command'.  */);
 
   DEFVAR_LISP ("this-command", Vthis_command,
               doc: /* The command now being executed.
@@ -11861,6 +11696,10 @@ The command can set this variable; whatever is put here
 will be in `last-command' during the following command.  */);
   Vthis_command = Qnil;
 
+  DEFVAR_LISP ("real-this-command", Vreal_this_command,
+              doc: /* This is like `this-command', except that commands should never modify it.  */);
+  Vreal_this_command = Qnil;
+
   DEFVAR_LISP ("this-command-keys-shift-translated",
               Vthis_command_keys_shift_translated,
               doc: /* Non-nil if the key sequence activating this command was shift-translated.
@@ -12188,12 +12027,6 @@ If this variable is non-nil, `delayed-warnings-hook' will be run
 immediately after running `post-command-hook'.  */);
   Vdelayed_warnings_list = Qnil;
 
-  DEFVAR_LISP ("suggest-key-bindings", Vsuggest_key_bindings,
-              doc: /* Non-nil means show the equivalent key-binding when M-x command has one.
-The value can be a length of time to show the message for.
-If the value is non-nil and not a number, we wait 2 seconds.  */);
-  Vsuggest_key_bindings = Qt;
-
   DEFVAR_LISP ("timer-list", Vtimer_list,
               doc: /* List of active absolute time timers in order of increasing time.  */);
   Vtimer_list = Qnil;
@@ -12323,7 +12156,7 @@ variable are `sigusr1' and `sigusr2'.  */);
   Vdebug_on_event = intern_c_string ("sigusr2");
 
   /* Create the initial keyboard.  */
-  initial_kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
+  initial_kboard = xmalloc (sizeof *initial_kboard);
   init_kboard (initial_kboard);
   /* Vwindow_system is left at t for now.  */
   initial_kboard->next_kboard = all_kboards;
@@ -12386,10 +12219,14 @@ keys_of_keyboard (void)
 
   initial_define_lispy_key (Vspecial_event_map, "config-changed-event",
                            "ignore");
+#if defined (WINDOWSNT)
+  initial_define_lispy_key (Vspecial_event_map, "language-change",
+                           "ignore");
+#endif
 }
 
 /* Mark the pointers in the kboard objects.
-   Called by the Fgarbage_collector.  */
+   Called by Fgarbage_collect.  */
 void
 mark_kboards (void)
 {