]> code.delx.au - gnu-emacs/blobdiff - src/keyboard.c
Auto-commit of generated files.
[gnu-emacs] / src / keyboard.c
index bf7c44aeeda132b9f1b82c5532b2c83b06bdd22b..0ff4cda034ac6e0a1e52f76df24f0b95e05e71ea 100644 (file)
@@ -20,9 +20,6 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include <config.h>
 
-#define BLOCKINPUT_INLINE EXTERN_INLINE
-#define KEYBOARD_INLINE EXTERN_INLINE
-
 #include "sysstdio.h"
 
 #include "lisp.h"
@@ -85,7 +82,7 @@ volatile bool pending_signals;
 
 KBOARD *initial_kboard;
 KBOARD *current_kboard;
-KBOARD *all_kboards;
+static KBOARD *all_kboards;
 
 /* True in the single-kboard state, false in the any-kboard state.  */
 static bool single_kboard;
@@ -221,10 +218,6 @@ static ptrdiff_t last_point_position;
    'volatile' here.  */
 Lisp_Object internal_last_event_frame;
 
-/* The timestamp of the last input event we received from the X server.
-   X Windows wants this for selection ownership.  */
-Time last_event_timestamp;
-
 static Lisp_Object Qx_set_selection, Qhandle_switch_frame;
 static Lisp_Object Qhandle_select_window;
 Lisp_Object QPRIMARY;
@@ -357,6 +350,8 @@ Lisp_Object Qvertical_line;
 static Lisp_Object Qvertical_scroll_bar;
 Lisp_Object Qmenu_bar;
 
+static Lisp_Object Qecho_keystrokes;
+
 static void recursive_edit_unwind (Lisp_Object buffer);
 static Lisp_Object command_loop (void);
 static Lisp_Object Qcommand_execute;
@@ -422,7 +417,9 @@ static Lisp_Object modify_event_symbol (ptrdiff_t, int, Lisp_Object,
                                         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);
@@ -1306,7 +1303,7 @@ some_mouse_moved (void)
    sans error-handling encapsulation.  */
 
 static int read_key_sequence (Lisp_Object *, int, Lisp_Object,
-                              bool, bool, bool);
+                              bool, bool, bool, bool);
 void safe_run_hooks (Lisp_Object);
 static void adjust_point_for_property (ptrdiff_t, bool);
 
@@ -1432,7 +1429,7 @@ command_loop_1 (void)
 
       /* Read next key sequence; i gets its length.  */
       i = read_key_sequence (keybuf, sizeof keybuf / sizeof keybuf[0],
-                            Qnil, 0, 1, 1);
+                            Qnil, 0, 1, 1, 0);
 
       /* A filter may have run while we were reading the input.  */
       if (! FRAME_LIVE_P (XFRAME (selected_frame)))
@@ -1692,6 +1689,30 @@ command_loop_1 (void)
     }
 }
 
+Lisp_Object
+read_menu_command (void)
+{
+  Lisp_Object keybuf[30];
+  ptrdiff_t count = SPECPDL_INDEX ();
+  int i;
+
+  /* We don't want to echo the keystrokes while navigating the
+     menus.  */
+  specbind (Qecho_keystrokes, make_number (0));
+
+  i = read_key_sequence (keybuf, sizeof keybuf / sizeof keybuf[0],
+                        Qnil, 0, 1, 1, 1);
+
+  unbind_to (count, Qnil);
+
+  if (! FRAME_LIVE_P (XFRAME (selected_frame)))
+    Fkill_emacs (Qnil);
+  if (i == 0 || i == -1)
+    return Qt;
+
+  return read_key_sequence_cmd;
+}
+
 /* Adjust point to a boundary of a region that has such a property
    that should be treated intangible.  For the moment, we check
    `composition', `display' and `invisible' properties.
@@ -2076,6 +2097,9 @@ bind_polling_period (int n)
 \f
 /* Apply the control modifier to CHARACTER.  */
 
+#ifndef WINDOWSNT
+static
+#endif
 int
 make_ctrl_char (int c)
 {
@@ -2359,6 +2383,7 @@ read_decoded_event_from_main_queue (struct timespec *end_time,
 /* 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.
+   -2 means do neither.
    1 means do both.  */
 
 /* The arguments MAP is for menu prompting.  MAP is a keymap.
@@ -2594,10 +2619,8 @@ read_char (int commandflag, Lisp_Object map,
 
   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 ();
@@ -2725,7 +2748,7 @@ read_char (int commandflag, Lisp_Object map,
 
   /* Maybe auto save due to number of keystrokes.  */
 
-  if (commandflag != 0
+  if (commandflag != 0 && commandflag != -2
       && auto_save_interval > 0
       && num_nonmacro_input_events - last_auto_save > max (auto_save_interval, 20)
       && !detect_input_pending_run_timers (0))
@@ -2777,7 +2800,7 @@ read_char (int commandflag, Lisp_Object map,
         9 at 200k, 11 at 300k, and 12 at 500k.  It is 15 at 1 meg.  */
 
       /* Auto save if enough time goes by without input.  */
-      if (commandflag != 0
+      if (commandflag != 0 && commandflag != -2
          && num_nonmacro_input_events > last_auto_save
          && INTEGERP (Vauto_save_timeout)
          && XINT (Vauto_save_timeout) > 0)
@@ -3210,6 +3233,8 @@ read_char (int commandflag, Lisp_Object map,
   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.  */
 
@@ -3245,6 +3270,8 @@ record_menu_key (Lisp_Object c)
   num_input_events++;
 }
 
+#endif /* HAVE_MENUS */
+
 /* Return true if should recognize C as "the help character".  */
 
 static bool
@@ -3604,8 +3631,6 @@ kbd_buffer_store_event_hold (register struct input_event *event,
            Vlast_event_frame = focus;
          }
 
-         last_event_timestamp = event->timestamp;
-
          handle_interrupt (0);
          return;
        }
@@ -3869,7 +3894,22 @@ kbd_buffer_get_event (KBOARD **kbp,
            }
        }
       else
-       wait_reading_process_output (0, 0, -1, 1, Qnil, NULL, 0);
+       {
+         bool do_display = true;
+
+         if (FRAME_TERMCAP_P (SELECTED_FRAME ()))
+           {
+             struct tty_display_info *tty = CURTTY ();
+
+             /* When this TTY is displaying a menu, we must prevent
+                any redisplay, because we modify the frame's glyph
+                matrix behind the back of the display engine.  */
+             if (tty->showing_menu)
+               do_display = false;
+           }
+
+         wait_reading_process_output (0, 0, -1, do_display, Qnil, NULL, 0);
+       }
 
       if (!interrupt_input && kbd_fetch_ptr == kbd_store_ptr)
        gobble_input ();
@@ -3895,8 +3935,6 @@ kbd_buffer_get_event (KBOARD **kbp,
               ? kbd_fetch_ptr
               : kbd_buffer);
 
-      last_event_timestamp = event->timestamp;
-
       *kbp = event_to_kboard (event);
       if (*kbp == 0)
        *kbp = current_kboard;  /* Better than returning null ptr?  */
@@ -4258,8 +4296,6 @@ process_special_events (void)
          else
            kbd_fetch_ptr++;
 
-         /* X wants last_event_timestamp for selection ownership.  */
-         last_event_timestamp = copy.timestamp;
          input_pending = readable_events (0);
          x_handle_selection_event (&copy);
 #else
@@ -4340,7 +4376,7 @@ decode_timer (Lisp_Object timer, struct timespec *result)
 
   if (! (VECTORP (timer) && ASIZE (timer) == 9))
     return 0;
-  vector = XVECTOR (timer)->contents;
+  vector = XVECTOR (timer)->u.contents;
   if (! NILP (vector[0]))
     return 0;
 
@@ -5362,6 +5398,20 @@ make_lispy_position (struct frame *f, Lisp_Object x, Lisp_Object y,
                                     extra_info))));
 }
 
+/* Return non-zero if F is a GUI frame that uses some toolkit-managed
+   menu bar.  This really means that Emacs draws and manages the menu
+   bar as part of its normal display, and therefore can compute its
+   geometry.  */
+static bool
+toolkit_menubar_in_use (struct frame *f)
+{
+#if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NS) || defined (HAVE_NTGUI)
+  return !(!FRAME_WINDOW_P (f));
+#else
+  return false;
+#endif
+}
+
 /* Given a struct input_event, build the lisp event which represents
    it.  If EVENT is 0, build a mouse movement event from the mouse
    movement buffer, which should have a movement event in it.
@@ -5497,6 +5547,9 @@ make_lispy_event (struct input_event *event)
       /* A mouse click.  Figure out where it is, decide whether it's
          a press, click or drag, and build the appropriate structure.  */
     case MOUSE_CLICK_EVENT:
+#ifdef HAVE_GPM
+    case GPM_CLICK_EVENT:
+#endif
 #ifndef USE_TOOLKIT_SCROLL_BARS
     case SCROLL_BAR_CLICK_EVENT:
 #endif
@@ -5510,67 +5563,71 @@ make_lispy_event (struct input_event *event)
        position = Qnil;
 
        /* Build the position as appropriate for this mouse click.  */
-       if (event->kind == MOUSE_CLICK_EVENT)
+       if (event->kind == MOUSE_CLICK_EVENT
+#ifdef HAVE_GPM
+           || event->kind == GPM_CLICK_EVENT
+#endif
+           )
          {
            struct frame *f = XFRAME (event->frame_or_window);
-#if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK) && ! defined (HAVE_NS)
            int row, column;
-#endif
 
            /* Ignore mouse events that were made on frame that
               have been deleted.  */
            if (! FRAME_LIVE_P (f))
              return Qnil;
 
-#if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK) && ! defined (HAVE_NS)
            /* EVENT->x and EVENT->y are frame-relative pixel
               coordinates at this place.  Under old redisplay, COLUMN
               and ROW are set to frame relative glyph coordinates
               which are then used to determine whether this click is
               in a menu (non-toolkit version).  */
-           pixel_to_glyph_coords (f, XINT (event->x), XINT (event->y),
-                                  &column, &row, NULL, 1);
-
-           /* In the non-toolkit version, clicks on the menu bar
-              are ordinary button events in the event buffer.
-              Distinguish them, and invoke the menu.
-
-              (In the toolkit version, the toolkit handles the menu bar
-              and Emacs doesn't know about it until after the user
-              makes a selection.)  */
-           if (row >= 0 && row < FRAME_MENU_BAR_LINES (f)
-               && (event->modifiers & down_modifier))
+           if (!toolkit_menubar_in_use (f))
              {
-               Lisp_Object items, item;
-
-               /* Find the menu bar item under `column'.  */
-               item = Qnil;
-               items = FRAME_MENU_BAR_ITEMS (f);
-               for (i = 0; i < ASIZE (items); i += 4)
+               pixel_to_glyph_coords (f, XINT (event->x), XINT (event->y),
+                                      &column, &row, NULL, 1);
+
+               /* In the non-toolkit version, clicks on the menu bar
+                  are ordinary button events in the event buffer.
+                  Distinguish them, and invoke the menu.
+
+                  (In the toolkit version, the toolkit handles the
+                  menu bar and Emacs doesn't know about it until
+                  after the user makes a selection.)  */
+               if (row >= 0 && row < FRAME_MENU_BAR_LINES (f)
+                 && (event->modifiers & down_modifier))
                  {
-                   Lisp_Object pos, string;
-                   string = AREF (items, i + 1);
-                   pos = AREF (items, i + 3);
-                   if (NILP (string))
-                     break;
-                   if (column >= XINT (pos)
-                       && column < XINT (pos) + SCHARS (string))
+                   Lisp_Object items, item;
+
+                   /* Find the menu bar item under `column'.  */
+                   item = Qnil;
+                   items = FRAME_MENU_BAR_ITEMS (f);
+                   for (i = 0; i < ASIZE (items); i += 4)
                      {
-                       item = AREF (items, i);
-                       break;
+                       Lisp_Object pos, string;
+                       string = AREF (items, i + 1);
+                       pos = AREF (items, i + 3);
+                       if (NILP (string))
+                         break;
+                       if (column >= XINT (pos)
+                           && column < XINT (pos) + SCHARS (string))
+                         {
+                           item = AREF (items, i);
+                           break;
+                         }
                      }
-                 }
 
-               /* ELisp manual 2.4b says (x y) are window relative but
-                  code says they are frame-relative.  */
-               position = list4 (event->frame_or_window,
-                                 Qmenu_bar,
-                                 Fcons (event->x, event->y),
-                                 make_number (event->timestamp));
+                   /* ELisp manual 2.4b says (x y) are window
+                      relative but code says they are
+                      frame-relative.  */
+                   position = list4 (event->frame_or_window,
+                                     Qmenu_bar,
+                                     Fcons (event->x, event->y),
+                                     make_number (event->timestamp));
 
-               return list2 (item, position);
+                   return list2 (item, position);
+                 }
              }
-#endif /* not USE_X_TOOLKIT && not USE_GTK && not HAVE_NS */
 
            position = make_lispy_position (f, event->x, event->y,
                                            event->timestamp);
@@ -5975,55 +6032,6 @@ make_lispy_event (struct input_event *event)
     case CONFIG_CHANGED_EVENT:
        return list3 (Qconfig_changed_event,
                      event->arg, event->frame_or_window);
-#ifdef HAVE_GPM
-    case GPM_CLICK_EVENT:
-      {
-       struct frame *f = XFRAME (event->frame_or_window);
-       Lisp_Object head, position;
-       Lisp_Object *start_pos_ptr;
-       Lisp_Object start_pos;
-       int button = event->code;
-
-       if (button >= ASIZE (button_down_location))
-         {
-           ptrdiff_t incr = button - ASIZE (button_down_location) + 1;
-           button_down_location = larger_vector (button_down_location,
-                                                 incr, -1);
-           mouse_syms = larger_vector (mouse_syms, incr, -1);
-         }
-
-       start_pos_ptr = aref_addr (button_down_location, button);
-       start_pos = *start_pos_ptr;
-
-       position = make_lispy_position (f, event->x, event->y,
-                                       event->timestamp);
-
-       if (event->modifiers & down_modifier)
-         *start_pos_ptr = Fcopy_alist (position);
-       else if (event->modifiers & (up_modifier | drag_modifier))
-         {
-           if (!CONSP (start_pos))
-             return Qnil;
-           event->modifiers &= ~up_modifier;
-         }
-
-       head = modify_event_symbol (button,
-                                   event->modifiers,
-                                   Qmouse_click, Vlispy_mouse_stem,
-                                   NULL,
-                                   &mouse_syms,
-                                   ASIZE (mouse_syms));
-
-       if (event->modifiers & drag_modifier)
-         return list3 (head, start_pos, position);
-       else if (event->modifiers & double_modifier)
-         return list3 (head, position, make_number (2));
-       else if (event->modifiers & triple_modifier)
-         return list3 (head, position, make_number (3));
-       else
-         return list2 (head, position);
-       }
-#endif /* HAVE_GPM */
 
       /* The 'kind' field of the event is something we don't recognize.  */
     default:
@@ -6069,12 +6077,17 @@ 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);
 }
-\f
+
+#endif /* HAVE_WINDOW_SYSTEM */
+
 /* Manipulating modifiers.  */
 
 /* Parse the name of SYMBOL, and return the set of modifiers it contains.
@@ -7084,7 +7097,8 @@ process_pending_signals (void)
 }
 
 /* Undo any number of BLOCK_INPUT calls down to level LEVEL,
-   and also (if the level is now 0) reinvoke any pending signal.  */
+   and reinvoke any pending signal if the level is now 0 and
+   a fatal error is not already in progress.  */
 
 void
 unblock_input_to (int level)
@@ -7092,7 +7106,7 @@ unblock_input_to (int level)
   interrupt_input_blocked = level;
   if (level == 0)
     {
-      if (pending_signals)
+      if (pending_signals && !fatal_error_in_progress)
        process_pending_signals ();
     }
   else if (level < 0)
@@ -7992,7 +8006,7 @@ process_tool_bar_item (Lisp_Object key, Lisp_Object def, Lisp_Object data, void
         discard any previously made item.  */
       for (i = 0; i < ntool_bar_items; i += TOOL_BAR_ITEM_NSLOTS)
        {
-         Lisp_Object *v = XVECTOR (tool_bar_items_vector)->contents + i;
+         Lisp_Object *v = XVECTOR (tool_bar_items_vector)->u.contents + i;
 
          if (EQ (key, v[TOOL_BAR_ITEM_KEY]))
            {
@@ -8316,7 +8330,7 @@ append_tool_bar_item (void)
   /* Append entries from tool_bar_item_properties to the end of
      tool_bar_items_vector.  */
   vcopy (tool_bar_items_vector, ntool_bar_items,
-        XVECTOR (tool_bar_item_properties)->contents, TOOL_BAR_ITEM_NSLOTS);
+        XVECTOR (tool_bar_item_properties)->u.contents, TOOL_BAR_ITEM_NSLOTS);
   ntool_bar_items += TOOL_BAR_ITEM_NSLOTS;
 }
 
@@ -8785,6 +8799,9 @@ test_undefined (Lisp_Object binding)
 
    Echo starting immediately unless `prompt' is 0.
 
+   If PREVENT_REDISPLAY is non-zero, avoid redisplay by calling
+   read_char with a suitable COMMANDFLAG argument.
+
    Where a key sequence ends depends on the currently active keymaps.
    These include any minor mode keymaps active in the current buffer,
    the current buffer's local map, and the global map.
@@ -8817,7 +8834,7 @@ test_undefined (Lisp_Object binding)
 static int
 read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
                   bool dont_downcase_last, bool can_return_switch_frame,
-                  bool fix_current_buffer)
+                  bool fix_current_buffer, bool prevent_redisplay)
 {
   ptrdiff_t count = SPECPDL_INDEX ();
 
@@ -8898,8 +8915,8 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt,
     {
       if (!NILP (prompt))
        {
-         /* Install the string STR as the beginning of the string of
-            echoing, so that it serves as a prompt for the next
+         /* Install the string PROMPT as the beginning of the string
+            of echoing, so that it serves as a prompt for the next
             character.  */
          kset_echo_string (current_kboard, prompt);
          current_kboard->echo_after_prompt = SCHARS (prompt);
@@ -9054,7 +9071,9 @@ 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),
+           /* Calling read_char with COMMANDFLAG = -2 avoids
+              redisplay in read_char and its subroutines.  */
+           key = read_char (prevent_redisplay ? -2 : NILP (prompt),
                             current_binding, last_nonmenu_event,
                              &used_mouse_menu, NULL);
            if ((INTEGERP (key) && XINT (key) == -2) /* wrong_kboard_jmpbuf */
@@ -9750,7 +9769,7 @@ read_key_sequence_vs (Lisp_Object prompt, Lisp_Object continue_echo,
 
   i = read_key_sequence (keybuf, (sizeof keybuf / sizeof (keybuf[0])),
                         prompt, ! NILP (dont_downcase_last),
-                        ! NILP (can_return_switch_frame), 0);
+                        ! NILP (can_return_switch_frame), 0, 0);
 
 #if 0  /* The following is fine for code reading a key sequence and
          then proceeding with a lengthy computation, but it's not good
@@ -9862,20 +9881,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)
-    {
-      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;
 }
@@ -9902,12 +9908,13 @@ requeued_events_pending_p (void)
   return (!NILP (Vunread_command_events));
 }
 
-
-DEFUN ("input-pending-p", Finput_pending_p, Sinput_pending_p, 0, 0, 0,
+DEFUN ("input-pending-p", Finput_pending_p, Sinput_pending_p, 0, 1, 0,
        doc: /* Return t if command input is currently available with no wait.
 Actually, the value is nil only if we can be sure that no input is available;
-if there is a doubt, the value is t.  */)
-  (void)
+if there is a doubt, the value is t.
+
+If CHECK-TIMERS is non-nil, timers that are ready to run will do so.  */)
+  (Lisp_Object check_timers)
 {
   if (!NILP (Vunread_command_events)
       || !NILP (Vunread_post_input_method_events)
@@ -9917,7 +9924,8 @@ if there is a doubt, the value is t.  */)
   /* Process non-user-visible events (Bug#10195).  */
   process_special_events ();
 
-  return (get_input_pending (READABLE_EVENTS_DO_TIMERS_NOW
+  return (get_input_pending ((NILP (check_timers)
+                              ? 0 : READABLE_EVENTS_DO_TIMERS_NOW)
                             | READABLE_EVENTS_FILTER_EVENTS)
          ? Qt : Qnil);
 }
@@ -9926,7 +9934,7 @@ DEFUN ("recent-keys", Frecent_keys, Srecent_keys, 0, 0, 0,
        doc: /* Return vector of last 300 events, not counting those from keyboard macros.  */)
   (void)
 {
-  Lisp_Object *keys = XVECTOR (recent_keys)->contents;
+  Lisp_Object *keys = XVECTOR (recent_keys)->u.contents;
   Lisp_Object val;
 
   if (total_keys < NUM_RECENT_KEYS)
@@ -9952,7 +9960,7 @@ See also `this-command-keys-vector'.  */)
   (void)
 {
   return make_event_array (this_command_key_count,
-                          XVECTOR (this_command_keys)->contents);
+                          XVECTOR (this_command_keys)->u.contents);
 }
 
 DEFUN ("this-command-keys-vector", Fthis_command_keys_vector, Sthis_command_keys_vector, 0, 0, 0,
@@ -9964,7 +9972,7 @@ See also `this-command-keys'.  */)
   (void)
 {
   return Fvector (this_command_key_count,
-                 XVECTOR (this_command_keys)->contents);
+                 XVECTOR (this_command_keys)->u.contents);
 }
 
 DEFUN ("this-single-command-keys", Fthis_single_command_keys,
@@ -9979,7 +9987,7 @@ The value is always a vector.  */)
 {
   return Fvector (this_command_key_count
                  - this_single_command_key_start,
-                 (XVECTOR (this_command_keys)->contents
+                 (XVECTOR (this_command_keys)->u.contents
                   + this_single_command_key_start));
 }
 
@@ -9993,8 +10001,7 @@ shows the events before all translations (except for input methods).
 The value is always a vector.  */)
   (void)
 {
-  return Fvector (raw_keybuf_count,
-                 (XVECTOR (raw_keybuf)->contents));
+  return Fvector (raw_keybuf_count, XVECTOR (raw_keybuf)->u.contents);
 }
 
 DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,
@@ -10736,12 +10743,11 @@ The `posn-' functions access elements of such lists.  */)
   return tem;
 }
 
-\f
-/*
- * Set up a new kboard object with reasonable initial values.
- */
-void
-init_kboard (KBOARD *kb)
+/* Set up a new kboard object with reasonable initial values.
+   TYPE is a window system for which this keyboard is used.  */
+
+static void
+init_kboard (KBOARD *kb, Lisp_Object type)
 {
   kset_overriding_terminal_local_map (kb, Qnil);
   kset_last_command (kb, Qnil);
@@ -10762,13 +10768,27 @@ init_kboard (KBOARD *kb)
   kb->reference_count = 0;
   kset_system_key_alist (kb, Qnil);
   kset_system_key_syms (kb, Qnil);
-  kset_window_system (kb, Qt); /* Unset.  */
+  kset_window_system (kb, type);
   kset_input_decode_map (kb, Fmake_sparse_keymap (Qnil));
   kset_local_function_key_map (kb, Fmake_sparse_keymap (Qnil));
   Fset_keymap_parent (KVAR (kb, Vlocal_function_key_map), Vfunction_key_map);
   kset_default_minibuffer_frame (kb, Qnil);
 }
 
+/* Allocate and basically initialize keyboard
+   object to use with window system TYPE.  */
+
+KBOARD *
+allocate_kboard (Lisp_Object type)
+{
+  KBOARD *kb = xmalloc (sizeof *kb);
+
+  init_kboard (kb, type);
+  kb->next_kboard = all_kboards;
+  all_kboards = kb;
+  return kb;
+}
+
 /*
  * Destroy the contents of a kboard object, but not the object itself.
  * We use this just before deleting it, or if we're going to initialize
@@ -10833,10 +10853,9 @@ init_keyboard (void)
   current_kboard = initial_kboard;
   /* Re-initialize the keyboard again.  */
   wipe_kboard (current_kboard);
-  init_kboard (current_kboard);
   /* A value of nil for Vwindow_system normally means a tty, but we also use
      it for the initial terminal since there is no window system there.  */
-  kset_window_system (current_kboard, Qnil);
+  init_kboard (current_kboard, Qnil);
 
   if (!noninteractive)
     {
@@ -11010,6 +11029,8 @@ syms_of_keyboard (void)
 
   DEFSYM (Qhelp_form_show, "help-form-show");
 
+  DEFSYM (Qecho_keystrokes, "echo-keystrokes");
+
   Fset (Qinput_method_exit_on_first_char, Qnil);
   Fset (Qinput_method_use_echo_area, Qnil);
 
@@ -11639,12 +11660,8 @@ Currently, the only supported values for this
 variable are `sigusr1' and `sigusr2'.  */);
   Vdebug_on_event = intern_c_string ("sigusr2");
 
-  /* Create the initial keyboard.  */
-  initial_kboard = xmalloc (sizeof *initial_kboard);
-  init_kboard (initial_kboard);
-  /* Vwindow_system is left at t for now.  */
-  initial_kboard->next_kboard = all_kboards;
-  all_kboards = initial_kboard;
+  /* Create the initial keyboard.  Qt means 'unset'.  */
+  initial_kboard = allocate_kboard (Qt);
 }
 
 void