]> code.delx.au - gnu-emacs/blobdiff - src/keyboard.c
* makefile.w32-in (obj): Remove sunfns.o.
[gnu-emacs] / src / keyboard.c
index 8999dd057599fe67bbe577bb1adaf9c20afcb03a..23f2e6d53ff0a8f9fb52eb59f400ad395356a038 100644 (file)
@@ -108,8 +108,6 @@ int interrupt_input_pending;
 #define KBD_BUFFER_SIZE 4096
 #endif /* No X-windows */
 
-#define abs(x)         ((x) >= 0 ? (x) : -(x))
-
 /* Following definition copied from eval.c */
 
 struct backtrace
@@ -162,14 +160,7 @@ int raw_keybuf_count;
 
 #define GROW_RAW_KEYBUF                                                        \
  if (raw_keybuf_count == XVECTOR (raw_keybuf)->size)                   \
-  {                                                                    \
-    int newsize = 2 * XVECTOR (raw_keybuf)->size;                      \
-    Lisp_Object new;                                                   \
-    new = Fmake_vector (make_number (newsize), Qnil);                  \
-    bcopy (XVECTOR (raw_keybuf)->contents, XVECTOR (new)->contents,    \
-          raw_keybuf_count * sizeof (Lisp_Object));                    \
-    raw_keybuf = new;                                                  \
-  }
+   raw_keybuf = larger_vector (raw_keybuf, raw_keybuf_count * 2, Qnil)  \
 
 /* Number of elements of this_command_keys
    that precede this key sequence.  */
@@ -447,7 +438,7 @@ Lisp_Object Qcommand_hook_internal, Vcommand_hook_internal;
 /* Parent keymap of terminal-local function-key-map instances.  */
 Lisp_Object Vfunction_key_map;
 
-/* Parent keymap of terminal-local key-translation-map instances.  */
+/* Keymap of key translations that can override keymaps.  */
 Lisp_Object Vkey_translation_map;
 
 /* List of deferred actions to be performed at a later time.
@@ -487,7 +478,7 @@ static struct input_event * volatile kbd_store_ptr;
 /* The above pair of variables forms a "queue empty" flag.  When we
    enqueue a non-hook event, we increment kbd_store_ptr.  When we
    dequeue a non-hook event, we increment kbd_fetch_ptr.  We say that
-   there is input available iff the two pointers are not equal.
+   there is input available if the two pointers are not equal.
 
    Why not just have a flag set and cleared by the enqueuing and
    dequeuing functions?  Such a flag could be screwed up by interrupts
@@ -1614,6 +1605,8 @@ command_loop_1 ()
   /* Do this after running Vpost_command_hook, for consistency.  */
   current_kboard->Vlast_command = Vthis_command;
   current_kboard->Vreal_last_command = real_this_command;
+  if (!CONSP (last_command_char))
+    current_kboard->Vlast_repeatable_command = real_this_command;
 
   while (1)
     {
@@ -1665,11 +1658,6 @@ command_loop_1 ()
            }
        }
 
-#ifdef C_ALLOCA
-      alloca (0);              /* Cause a garbage collection now */
-                               /* Since we can free the most stuff here.  */
-#endif /* C_ALLOCA */
-
 #if 0
       /* Select the frame that the last event came from.  Usually,
         switch-frame events will take care of this, but if some lisp
@@ -1994,6 +1982,8 @@ command_loop_1 ()
        {
          current_kboard->Vlast_command = Vthis_command;
          current_kboard->Vreal_last_command = real_this_command;
+         if (!CONSP (last_command_char))
+           current_kboard->Vlast_repeatable_command = real_this_command;
          cancel_echoing ();
          this_command_key_count = 0;
          this_command_key_count_reset = 0;
@@ -3703,7 +3693,7 @@ restore_getcjmp (temp)
    kbd_buffer_store_event places events in kbd_buffer, and
    kbd_buffer_get_event retrieves them.  */
 
-/* Return true iff there are any events in the queue that read-char
+/* Return true if there are any events in the queue that read-char
    would return.  If this returns false, a read-char would block.  */
 static int
 readable_events (flags)
@@ -4026,6 +4016,7 @@ discard_mouse_events ()
 
       if (sp->kind == MOUSE_CLICK_EVENT
          || sp->kind == WHEEL_EVENT
+          || sp->kind == HORIZ_WHEEL_EVENT
 #ifdef WINDOWSNT
          || sp->kind == W32_SCROLL_BAR_CLICK_EVENT
 #endif
@@ -4104,6 +4095,12 @@ kbd_buffer_get_event (kbp, used_mouse_menu, end_time)
   /* Wait until there is input available.  */
   for (;;)
     {
+      /* Break loop if there's an unread command event.  Needed in
+        moused window autoselection which uses a timer to insert such
+        events.  */
+      if (CONSP (Vunread_command_events))
+       break;
+      
       if (kbd_fetch_ptr != kbd_store_ptr)
        break;
 #if defined (HAVE_MOUSE) || defined (HAVE_GPM)
@@ -4719,12 +4716,14 @@ timer_check (do_it_now)
 }
 
 DEFUN ("current-idle-time", Fcurrent_idle_time, Scurrent_idle_time, 0, 0, 0,
-       doc: /* Return the current length of Emacs idleness.
-The value is returned as a list of three integers.  The first has the
+       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 not idle is nil.
+
 The microsecond count is zero on systems that do not provide
 resolution finer than a second.  */)
   ()
@@ -5204,7 +5203,7 @@ Lisp_Object Vlispy_mouse_stem;
 
 static char *lispy_wheel_names[] =
 {
-  "wheel-up", "wheel-down"
+  "wheel-up", "wheel-down", "wheel-left", "wheel-right"
 };
 
 /* drag-n-drop events are generated when a set of selected files are
@@ -5710,8 +5709,8 @@ make_lispy_event (event)
            fuzz = double_click_fuzz / 8;
 
          is_double = (button == last_mouse_button
-                      && (abs (XINT (event->x) - last_mouse_x) <= fuzz)
-                      && (abs (XINT (event->y) - last_mouse_y) <= fuzz)
+                      && (eabs (XINT (event->x) - last_mouse_x) <= fuzz)
+                      && (eabs (XINT (event->y) - last_mouse_y) <= fuzz)
                       && button_down_time != 0
                       && (EQ (Vdouble_click_time, Qt)
                           || (INTEGERP (Vdouble_click_time)
@@ -5841,6 +5840,7 @@ make_lispy_event (event)
       }
 
     case WHEEL_EVENT:
+    case HORIZ_WHEEL_EVENT:
       {
        Lisp_Object position;
        Lisp_Object head;
@@ -5878,8 +5878,8 @@ make_lispy_event (event)
            fuzz = double_click_fuzz / 8;
 
          is_double = (last_mouse_button < 0
-                      && (abs (XINT (event->x) - last_mouse_x) <= fuzz)
-                      && (abs (XINT (event->y) - last_mouse_y) <= fuzz)
+                      && (eabs (XINT (event->x) - last_mouse_x) <= fuzz)
+                      && (eabs (XINT (event->y) - last_mouse_y) <= fuzz)
                       && button_down_time != 0
                       && (EQ (Vdouble_click_time, Qt)
                           || (INTEGERP (Vdouble_click_time)
@@ -5925,6 +5925,9 @@ make_lispy_event (event)
               the up_modifier set.  */
            abort ();
 
+          if (event->kind == HORIZ_WHEEL_EVENT)
+            symbol_num += 2;
+
          /* Get the symbol we should use for the wheel event.  */
          head = modify_event_symbol (symbol_num,
                                      event->modifiers,
@@ -7093,8 +7096,8 @@ tty_read_avail_input (struct terminal *terminal,
   struct tty_display_info *tty = terminal->display_info.tty;
   int nread = 0;
 
-  if (terminal->deleted)        /* Don't read from a deleted terminal. */
-    return;
+  if (!terminal->name)         /* Don't read from a dead terminal. */
+    return 0;
 
   if (terminal->type != output_termcap)
     abort ();
@@ -7121,7 +7124,7 @@ tty_read_avail_input (struct terminal *terminal,
     return 0;                   /* The terminal is suspended. */
 
 #ifdef HAVE_GPM
-  if (term_gpm && gpm_tty == tty->terminal->id)
+  if (gpm_tty == tty)
   {
       Gpm_Event event;
       struct input_event hold_quit;
@@ -7590,13 +7593,7 @@ menu_bar_items (old)
   /* Add nil, nil, nil, nil at the end.  */
   i = menu_bar_items_index;
   if (i + 4 > XVECTOR (menu_bar_items_vector)->size)
-    {
-      Lisp_Object tem;
-      tem = Fmake_vector (make_number (2 * i), Qnil);
-      bcopy (XVECTOR (menu_bar_items_vector)->contents,
-            XVECTOR (tem)->contents, i * sizeof (Lisp_Object));
-      menu_bar_items_vector = tem;
-    }
+    menu_bar_items_vector = larger_vector (menu_bar_items_vector, 2 * i, Qnil);
   /* Add this item.  */
   XVECTOR (menu_bar_items_vector)->contents[i++] = Qnil;
   XVECTOR (menu_bar_items_vector)->contents[i++] = Qnil;
@@ -7668,14 +7665,7 @@ menu_bar_item (key, item, dummy1, dummy2)
     {
       /* If vector is too small, get a bigger one.  */
       if (i + 4 > XVECTOR (menu_bar_items_vector)->size)
-       {
-         Lisp_Object tem;
-         tem = Fmake_vector (make_number (2 * i), Qnil);
-         bcopy (XVECTOR (menu_bar_items_vector)->contents,
-                XVECTOR (tem)->contents, i * sizeof (Lisp_Object));
-         menu_bar_items_vector = tem;
-       }
-
+       menu_bar_items_vector = larger_vector (menu_bar_items_vector, 2 * i, Qnil);
       /* Add this item.  */
       XVECTOR (menu_bar_items_vector)->contents[i++] = key;
       XVECTOR (menu_bar_items_vector)->contents[i++]
@@ -8096,10 +8086,11 @@ static Lisp_Object tool_bar_item_properties;
 
 static int ntool_bar_items;
 
-/* The symbols `tool-bar', and `:image'.  */
+/* The symbols `tool-bar', `:image' and `:rtl'.  */
 
 extern Lisp_Object Qtool_bar;
 Lisp_Object QCimage;
+Lisp_Object Qrtl;
 
 /* Function prototypes.  */
 
@@ -8385,6 +8376,9 @@ parse_tool_bar_item (key, item)
        /* Value is either a single image specification or a vector
           of 4 such specifications for the different button states.  */
        PROP (TOOL_BAR_ITEM_IMAGES) = value;
+      else if (EQ (key, Qrtl))
+        /* ':rtl STRING' */
+       PROP (TOOL_BAR_ITEM_RTL_IMAGE) = value;
     }
 
   /* If got a filter apply it on binding.  */
@@ -8440,16 +8434,9 @@ append_tool_bar_item ()
   /* Enlarge tool_bar_items_vector if necessary.  */
   if (ntool_bar_items + TOOL_BAR_ITEM_NSLOTS
       >= XVECTOR (tool_bar_items_vector)->size)
-    {
-      Lisp_Object new_vector;
-      int old_size = XVECTOR (tool_bar_items_vector)->size;
-
-      new_vector = Fmake_vector (make_number (2 * old_size), Qnil);
-      bcopy (XVECTOR (tool_bar_items_vector)->contents,
-            XVECTOR (new_vector)->contents,
-            old_size * sizeof (Lisp_Object));
-      tool_bar_items_vector = new_vector;
-    }
+    tool_bar_items_vector
+      = larger_vector (tool_bar_items_vector,
+                      2 * XVECTOR (tool_bar_items_vector)->size, Qnil);
 
   /* Append entries from tool_bar_item_properties to the end of
      tool_bar_items_vector.  */
@@ -8553,7 +8540,7 @@ read_char_x_menu_prompt (nmaps, maps, prev_event, used_mouse_menu)
             to indicate that they came from a mouse menu,
             so that when present in last_nonmenu_event
             they won't confuse things.  */
-         for (tem = XCDR (value); !NILP (tem); tem = XCDR (tem))
+         for (tem = XCDR (value); CONSP (tem); tem = XCDR (tem))
            {
              record_menu_key (XCAR (tem));
              if (SYMBOLP (XCAR (tem))
@@ -9129,8 +9116,8 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
      key's again in Vfunction_key_map.  */
   volatile keyremap fkey;
 
-  /* Likewise, for key_translation_map.  */
-  volatile keyremap keytran;
+  /* Likewise, for key_translation_map and input-decode-map.  */
+  volatile keyremap keytran, indec;
 
   /* If we receive a `switch-frame' or `select-window' event in the middle of
      a key sequence, we put it off for later.
@@ -9200,18 +9187,28 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
   orig_keymap = get_local_map (PT, current_buffer, Qkeymap);
   from_string = Qnil;
 
+  /* The multi-tty merge moved the code below to right after
+   `replay_sequence' which caused all these translation maps to be applied
+   repeatedly, even tho their doc says very clearly they are not applied to
+   their own output.
+   The reason for this move was: "We may switch keyboards between rescans,
+   so we need to reinitialize fkey and keytran before each replay".
+   This move was wrong (even if we switch keyboards, keybuf still holds the
+   keys we've read already from the original keyboard and some of those keys
+   may have already been translated).  So there may still be a bug out there
+   lurking.  */
+  indec.map = indec.parent = current_kboard->Vinput_decode_map;
+  fkey.map = fkey.parent = current_kboard->Vlocal_function_key_map;
+  keytran.map = keytran.parent = Vkey_translation_map;
+  indec.start = indec.end = 0;
+  fkey.start = fkey.end = 0;
+  keytran.start = keytran.end = 0;
+
   /* We jump here when the key sequence has been thoroughly changed, and
      we need to rescan it starting from the beginning.  When we jump here,
      keybuf[0..mock_input] holds the sequence we should reread.  */
  replay_sequence:
 
-  /* We may switch keyboards between rescans, so we need to
-     reinitialize fkey and keytran before each replay.  */
-  fkey.map = fkey.parent = current_kboard->Vlocal_function_key_map;
-  keytran.map = keytran.parent = current_kboard->Vlocal_key_translation_map;
-  fkey.start = fkey.end = 0;
-  keytran.start = keytran.end = 0;
-
   starting_buffer = current_buffer;
   first_unbound = bufsize + 1;
 
@@ -9297,7 +9294,7 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
            Thus, if ESC O a has a function-key-map translation
            and ESC o has a binding, don't return after ESC O,
            so that we can translate ESC O plus the next character.  */
-        : (fkey.start < t || keytran.start < t))
+        : (/* indec.start < t || fkey.start < t || */ keytran.start < t))
     {
       Lisp_Object key;
       int used_mouse_menu = 0;
@@ -9315,13 +9312,17 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
         just one key.  */
       volatile int echo_local_start, keys_local_start, local_first_binding;
 
-      eassert (fkey.end == t || (fkey.end > t && fkey.end <= mock_input));
+      eassert (indec.end == t || (indec.end > t && indec.end <= mock_input));
+      eassert (indec.start <= indec.end);
       eassert (fkey.start <= fkey.end);
       eassert (keytran.start <= keytran.end);
-      /* key-translation-map is applied *after* function-key-map.  */
+      /* key-translation-map is applied *after* function-key-map
+        which is itself applied *after* input-decode-map.  */
+      eassert (fkey.end <= indec.start);
       eassert (keytran.end <= fkey.start);
 
-      if (first_unbound < fkey.start && first_unbound < keytran.start)
+      if (/* first_unbound < indec.start && first_unbound < fkey.start && */
+         first_unbound < keytran.start)
        { /* The prefix upto first_unbound has no binding and has
             no translation left to do either, so we know it's unbound.
             If we don't stop now, we risk staying here indefinitely
@@ -9331,6 +9332,8 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
          for (i = first_unbound + 1; i < t; i++)
            keybuf[i - first_unbound - 1] = keybuf[i];
          mock_input = t - first_unbound - 1;
+         indec.end = indec.start -= first_unbound + 1;
+         indec.map = indec.parent;
          fkey.end = fkey.start -= first_unbound + 1;
          fkey.map = fkey.parent;
          keytran.end = keytran.start -= first_unbound + 1;
@@ -9756,15 +9759,15 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
        /* This is needed for the following scenario:
           event 0: a down-event that gets dropped by calling replay_key.
           event 1: some normal prefix like C-h.
-          After event 0, first_unbound is 0, after event 1 fkey.start
-          and keytran.start are both 1, so when we see that C-h is bound,
-          we need to update first_unbound.  */
+          After event 0, first_unbound is 0, after event 1 indec.start,
+          fkey.start, and keytran.start are all 1, so when we see that
+          C-h is bound, we need to update first_unbound.  */
        first_unbound = max (t + 1, first_unbound);
       else
        {
          Lisp_Object head;
 
-         /* Remember the position to put an upper bound on fkey.start.  */
+         /* Remember the position to put an upper bound on indec.start.  */
          first_unbound = min (t, first_unbound);
 
          head = EVENT_HEAD (key);
@@ -9849,21 +9852,27 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
                          /* If mock_input > t + 1, the above simplification
                             will actually end up dropping keys on the floor.
                             This is probably OK for now, but even
-                            if mock_input <= t + 1, we need to adjust fkey
-                            and keytran.
+                            if mock_input <= t + 1, we need to adjust indec,
+                            fkey, and keytran.
                             Typical case [header-line down-mouse-N]:
                             mock_input = 2, t = 1, fkey.end = 1,
                             last_real_key_start = 0.  */
-                         if (fkey.end > last_real_key_start)
+                         if (indec.end > last_real_key_start)
                            {
-                             fkey.end = fkey.start
-                               = min (last_real_key_start, fkey.start);
-                             fkey.map = fkey.parent;
-                             if (keytran.end > last_real_key_start)
+                             indec.end = indec.start
+                               = min (last_real_key_start, indec.start);
+                             indec.map = indec.parent;
+                             if (fkey.end > last_real_key_start)
                                {
-                                 keytran.end = keytran.start
-                                   = min (last_real_key_start, keytran.start);
-                                 keytran.map = keytran.parent;
+                                 fkey.end = fkey.start
+                                   = min (last_real_key_start, fkey.start);
+                                 fkey.map = fkey.parent;
+                                 if (keytran.end > last_real_key_start)
+                                   {
+                                     keytran.end = keytran.start
+                                       = min (last_real_key_start, keytran.start);
+                                     keytran.map = keytran.parent;
+                                   }
                                }
                            }
                          if (t == last_real_key_start)
@@ -9917,8 +9926,28 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
       /* Record what part of this_command_keys is the current key sequence.  */
       this_single_command_key_start = this_command_key_count - t;
 
-      if (first_binding < nmaps && NILP (submaps[first_binding]))
+      /* Look for this sequence in input-decode-map.
+        Scan from indec.end until we find a bound suffix.  */
+      while (indec.end < t)
+       {
+         struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
+         int done, diff;
+
+         GCPRO4 (indec.map, fkey.map, keytran.map, delayed_switch_frame);
+         done = keyremap_step (keybuf, bufsize, &indec, max (t, mock_input),
+                               1, &diff, prompt);
+         UNGCPRO;
+         if (done)
+           {
+             mock_input = diff + max (t, mock_input);
+             goto replay_sequence;
+           }
+       }
+
+      if (first_binding < nmaps && NILP (submaps[first_binding])
+         && indec.start >= t)
        /* There is a binding and it's not a prefix.
+          (and it doesn't have any input-decode-map translation pending).
           There is thus no function-key in this sequence.
           Moving fkey.start is important in this case to allow keytran.start
           to go over the sequence before we return (since we keep the
@@ -9931,12 +9960,12 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
        /* If the sequence is unbound, see if we can hang a function key
           off the end of it.  */
        /* Continue scan from fkey.end until we find a bound suffix.  */
-       while (fkey.end < t)
+       while (fkey.end < indec.start)
          {
-           struct gcpro gcpro1, gcpro2, gcpro3;
+           struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
            int done, diff;
 
-           GCPRO3 (fkey.map, keytran.map, delayed_switch_frame);
+           GCPRO4 (indec.map, fkey.map, keytran.map, delayed_switch_frame);
            done = keyremap_step (keybuf, bufsize, &fkey,
                                  max (t, mock_input),
                                  /* If there's a binding (i.e.
@@ -9948,6 +9977,10 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
            if (done)
              {
                mock_input = diff + max (t, mock_input);
+               /* Adjust the input-decode-map counters.  */
+               indec.end += diff;
+               indec.start += diff;
+
                goto replay_sequence;
              }
          }
@@ -9956,17 +9989,19 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
         Scan from keytran.end until we find a bound suffix.  */
       while (keytran.end < fkey.start)
        {
-         struct gcpro gcpro1, gcpro2, gcpro3;
+         struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
          int done, diff;
 
-         GCPRO3 (fkey.map, keytran.map, delayed_switch_frame);
+         GCPRO4 (indec.map, fkey.map, keytran.map, delayed_switch_frame);
          done = keyremap_step (keybuf, bufsize, &keytran, max (t, mock_input),
                                1, &diff, prompt);
          UNGCPRO;
          if (done)
            {
              mock_input = diff + max (t, mock_input);
-             /* Adjust the function-key-map counters.  */
+             /* Adjust the function-key-map and input-decode-map counters.  */
+             indec.end += diff;
+             indec.start += diff;
              fkey.end += diff;
              fkey.start += diff;
 
@@ -9979,7 +10014,7 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
         and is an upper case letter
         use the corresponding lower-case letter instead.  */
       if (first_binding >= nmaps
-         && fkey.start >= t && keytran.start >= t
+         && /* indec.start >= t && fkey.start >= t && */ keytran.start >= t
          && INTEGERP (key)
          && ((((XINT (key) & 0x3ffff)
                < XCHAR_TABLE (current_buffer->downcase_table)->size)
@@ -10010,7 +10045,7 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
         and is a shifted function key,
         use the corresponding unshifted function key instead.  */
       if (first_binding >= nmaps
-         && fkey.start >= t && keytran.start >= t
+         && /* indec.start >= t && fkey.start >= t && */ keytran.start >= t
          && SYMBOLP (key))
        {
          Lisp_Object breakdown;
@@ -10031,9 +10066,6 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
 
              keybuf[t - 1] = new_key;
              mock_input = max (t, mock_input);
-             fkey.start = fkey.end = 0;
-             keytran.start = keytran.end = 0;
-
              goto replay_sequence;
            }
        }
@@ -11315,7 +11347,8 @@ See also `current-input-mode'.  */)
   Fset_input_interrupt_mode (interrupt);
   Fset_output_flow_control (flow, Qnil);
   Fset_input_meta_mode (meta, Qnil);
-  Fset_quit_char (quit);
+  if (!NILP (quit))
+    Fset_quit_char (quit);
   return Qnil;
 }
 
@@ -11443,6 +11476,7 @@ init_kboard (kb)
   kb->Vlast_command = Qnil;
   kb->Vreal_last_command = Qnil;
   kb->Vkeyboard_translate_table = Qnil;
+  kb->Vlast_repeatable_command = Qnil;
   kb->Vprefix_arg = Qnil;
   kb->Vlast_prefix_arg = Qnil;
   kb->kbd_queue = Qnil;
@@ -11457,10 +11491,10 @@ init_kboard (kb)
   kb->reference_count = 0;
   kb->Vsystem_key_alist = Qnil;
   kb->system_key_syms = Qnil;
+  kb->Vwindow_system = Qt;     /* Unset.  */
+  kb->Vinput_decode_map = Fmake_sparse_keymap (Qnil);
   kb->Vlocal_function_key_map = Fmake_sparse_keymap (Qnil);
   Fset_keymap_parent (kb->Vlocal_function_key_map, Vfunction_key_map);
-  kb->Vlocal_key_translation_map = Fmake_sparse_keymap (Qnil);
-  Fset_keymap_parent (kb->Vlocal_key_translation_map, Vkey_translation_map);
   kb->Vdefault_minibuffer_frame = Qnil;
 }
 
@@ -11538,8 +11572,12 @@ init_keyboard ()
 #ifdef MULTI_KBOARD
   current_kboard = initial_kboard;
 #endif
+  /* 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.  */
+  current_kboard->Vwindow_system = Qnil;
 
   if (!noninteractive)
     {
@@ -11624,6 +11662,9 @@ syms_of_keyboard ()
   staticpro (&Qhelp_echo);
   Qhelp_echo = intern ("help-echo");
 
+  staticpro (&Qrtl);
+  Qrtl = intern (":rtl");
+
   staticpro (&item_properties);
   item_properties = Qnil;
 
@@ -11792,7 +11833,7 @@ syms_of_keyboard ()
   staticpro (&button_down_location);
   mouse_syms = Fmake_vector (make_number (1), Qnil);
   staticpro (&mouse_syms);
-  wheel_syms = Fmake_vector (make_number (2), Qnil);
+  wheel_syms = Fmake_vector (make_number (4), Qnil);
   staticpro (&wheel_syms);
 
   {
@@ -11948,6 +11989,11 @@ See Info node `(elisp)Multiple displays'.  */);
   DEFVAR_KBOARD ("real-last-command", Vreal_last_command,
                 doc: /* Same as `last-command', but never altered by Lisp code.  */);
 
+  DEFVAR_KBOARD ("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.  */);
+
   DEFVAR_LISP ("this-command", &Vthis_command,
               doc: /* The command now being executed.
 The command can set this variable; whatever is put here
@@ -12190,8 +12236,8 @@ See Info node `(elisp)Multiple displays'.  */);
 
   DEFVAR_KBOARD ("local-function-key-map", Vlocal_function_key_map,
                  doc: /* Keymap that translates key sequences to key sequences during input.
-This is used mainly for mapping ASCII function key sequences into
-real Emacs function key events (symbols).
+This is used mainly for mapping key sequences into some preferred
+key events (symbols).
 
 The `read-key-sequence' function replaces any subsequence bound by
 `local-function-key-map' with its binding.  More precisely, when the
@@ -12217,6 +12263,25 @@ define a binding on all terminals, change `function-key-map'
 instead.  Initially, `local-function-key-map' is an empty keymap that
 has `function-key-map' as its parent on all terminal devices.  */);
 
+  DEFVAR_KBOARD ("input-decode-map", Vinput_decode_map,
+                doc: /* Keymap that decodes input escape sequences.
+This is used mainly for mapping ASCII function key sequences into
+real Emacs function key events (symbols).
+
+The `read-key-sequence' function replaces any subsequence bound by
+`local-function-key-map' with its binding.  Contrary to `function-key-map',
+this map applies its rebinding regardless of the presence of an ordinary
+binding.  So it is more like `key-translation-map' except that it applies
+before `function-key-map' rather than after.
+
+If the binding is a function, it is called with one argument (the prompt)
+and its return value (a key sequence) is used.
+
+The events that come from bindings in `input-decode-map' are not
+themselves looked up in `input-decode-map'.
+
+This variable is keyboard-local.  */);
+
   DEFVAR_LISP ("function-key-map", &Vfunction_key_map,
                doc: /* The parent keymap of all `local-function-key-map' instances.
 Function key definitions that apply to all terminal devices should go
@@ -12225,18 +12290,11 @@ here.  If a mapping is defined in both the current
 definition will take precendence.  */);
   Vfunction_key_map = Fmake_sparse_keymap (Qnil);
                     
-  DEFVAR_KBOARD ("local-key-translation-map", Vlocal_key_translation_map,
-              doc: /* Keymap of key translations that can override keymaps.
+  DEFVAR_LISP ("key-translation-map", &Vkey_translation_map,
+               doc: /* Keymap of key translations that can override keymaps.
 This keymap works like `function-key-map', but comes after that,
 and its non-prefix bindings override ordinary bindings.
-
-`key-translation-map' has a separate binding for each terminal device.
-(See Info node `(elisp)Multiple displays'.)  If you need to set a key
-translation on all terminals, change `global-key-translation-map' instead.  */);
-
-  DEFVAR_LISP ("key-translation-map", &Vkey_translation_map,
-               doc: /* The parent keymap of all `local-key-translation-map' instances.
-Key translations that apply to all terminal devices should go here.  */);
+Another difference is that it is global rather than keyboard-local.  */);
   Vkey_translation_map = Fmake_sparse_keymap (Qnil);
 
   DEFVAR_LISP ("deferred-action-list", &Vdeferred_action_list,
@@ -12345,6 +12403,15 @@ and the Lisp function within which the error was signaled.  */);
 Help functions bind this to allow help on disabled menu items
 and tool-bar buttons.  */);
   Venable_disabled_menus_and_buttons = Qnil;
+
+#ifdef MULTI_KBOARD
+  /* Create the initial keyboard. */
+  initial_kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
+  init_kboard (initial_kboard);
+  /* Vwindow_system is left at t for now.  */
+  initial_kboard->next_kboard = all_kboards;
+  all_kboards = initial_kboard;
+#endif  
 }
 
 void
@@ -12407,6 +12474,7 @@ mark_kboards ()
       mark_object (kb->Vlast_command);
       mark_object (kb->Vreal_last_command);
       mark_object (kb->Vkeyboard_translate_table);
+      mark_object (kb->Vlast_repeatable_command);
       mark_object (kb->Vprefix_arg);
       mark_object (kb->Vlast_prefix_arg);
       mark_object (kb->kbd_queue);
@@ -12414,8 +12482,9 @@ mark_kboards ()
       mark_object (kb->Vlast_kbd_macro);
       mark_object (kb->Vsystem_key_alist);
       mark_object (kb->system_key_syms);
+      mark_object (kb->Vwindow_system);
+      mark_object (kb->Vinput_decode_map);
       mark_object (kb->Vlocal_function_key_map);
-      mark_object (kb->Vlocal_key_translation_map);
       mark_object (kb->Vdefault_minibuffer_frame);
       mark_object (kb->echo_string);
     }