(detect_coding_iso2022): Do not exclude posibility of
[bpt/emacs.git] / src / keyboard.c
index 19f8dbb..39629ae 100644 (file)
@@ -1,5 +1,5 @@
 /* Keyboard and mouse input; editor command loop.
-   Copyright (C) 1985,86,87,88,89,93,94,95,96 Free Software Foundation, Inc.
+   Copyright (C) 1985,86,87,88,89,93,94,95,96,97 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -32,6 +32,7 @@ Boston, MA 02111-1307, USA.  */
 #include "window.h"
 #include "commands.h"
 #include "buffer.h"
+#include "charset.h"
 #include "disptab.h"
 #include "dispextern.h"
 #include "keyboard.h"
@@ -170,6 +171,9 @@ static int inhibit_local_menu_bar_menus;
 /* Nonzero means C-g should cause immediate error-signal.  */
 int immediate_quit;
 
+/* The user's ERASE setting.  */
+Lisp_Object Vtty_erase_char;
+
 /* Character to recognize as the help char.  */
 Lisp_Object Vhelp_char;
 
@@ -268,17 +272,17 @@ static int last_non_minibuf_size;
 static Lisp_Object Vauto_save_timeout;
 
 /* Total number of times read_char has returned.  */
-int num_input_chars;
+int num_input_events;
 
 /* Total number of times read_char has returned, outside of macros.  */
-int num_nonmacro_input_chars;
+int num_nonmacro_input_events;
 
 /* Auto-save automatically when this many characters have been typed
    since the last time.  */
 
 static int auto_save_interval;
 
-/* Value of num_nonmacro_input_chars as of last auto save.  */
+/* Value of num_nonmacro_input_events as of last auto save.  */
 
 int last_auto_save;
 
@@ -313,6 +317,7 @@ Lisp_Object Qself_insert_command;
 Lisp_Object Qforward_char;
 Lisp_Object Qbackward_char;
 Lisp_Object Qundefined;
+Lisp_Object Qtimer_event_handler;
 
 /* read_key_sequence stores here the command definition of the
    key sequence that it reads.  */
@@ -339,6 +344,8 @@ Lisp_Object Vdeactivate_mark;
 Lisp_Object Vlucid_menu_bar_dirty_flag;
 Lisp_Object Qrecompute_lucid_menubar, Qactivate_menubar_hook;
 
+Lisp_Object Qecho_area_clear_hook;
+
 /* Hooks to run before and after each command.  */
 Lisp_Object Qpre_command_hook, Vpre_command_hook;
 Lisp_Object Qpost_command_hook, Vpost_command_hook;
@@ -437,7 +444,6 @@ Lisp_Object Qmake_frame_visible;
 /* Symbols to denote kinds of events.  */
 Lisp_Object Qfunction_key;
 Lisp_Object Qmouse_click;
-Lisp_Object Qtimer_event;
 /* Lisp_Object Qmouse_movement; - also an event header */
 
 /* Properties of event headers.  */
@@ -474,6 +480,10 @@ EMACS_TIME timer_check ();
 
 extern char *x_get_keysym_name ();
 
+static void record_menu_key ();
+
+void swallow_events ();
+
 Lisp_Object Qpolling_period;
 
 /* List of absolute timers.  Appears in order of next scheduled event.  */
@@ -750,6 +760,10 @@ recursive_edit_1 ()
   val = command_loop ();
   if (EQ (val, Qt))
     Fsignal (Qquit, Qnil);
+  /* Handle throw from read_minibuf when using minibuffer
+     while it's active but we're in another window.  */
+  if (STRINGP (val))
+    Fsignal (Qerror, Fcons (val, Qnil));
 
   return unbind_to (count, Qnil);
 }
@@ -758,7 +772,7 @@ recursive_edit_1 ()
 
 record_auto_save ()
 {
-  last_auto_save = num_nonmacro_input_chars;
+  last_auto_save = num_nonmacro_input_events;
 }
 
 /* Make an auto save happen as soon as possible at command level.  */
@@ -1062,7 +1076,7 @@ Lisp_Object
 command_loop_1 ()
 {
   Lisp_Object cmd, tem;
-  int lose;
+  int lose, lose2;
   int nonundocount;
   Lisp_Object keybuf[30];
   int i;
@@ -1098,7 +1112,7 @@ command_loop_1 ()
     {
       if (NILP (Vunread_command_events)
          && NILP (Vexecuting_macro)
-         && !NILP (sit_for (0, post_command_idle_delay, 0, 1)))
+         && !NILP (sit_for (0, post_command_idle_delay, 0, 1, 1)))
        safe_run_hooks (Qpost_command_idle_hook);
     }
 
@@ -1134,7 +1148,8 @@ command_loop_1 ()
 
          Fsit_for (make_number (2), Qnil, Qnil);
          /* Clear the echo area.  */
-         message2 (0);
+         message2 (0, 0);
+         safe_run_hooks (Qecho_area_clear_hook);
 
          unbind_to (count, Qnil);
 
@@ -1173,7 +1188,11 @@ command_loop_1 ()
 
       /* Read next key sequence; i gets its length.  */
       i = read_key_sequence (keybuf, sizeof keybuf / sizeof keybuf[0],
-                            Qnil, 0, 1);
+                            Qnil, 0, 1, 1);
+
+      /* A filter may have run while we were reading the input.  */
+      if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
+       set_buffer_internal (XBUFFER (XWINDOW (selected_window)->buffer));
 
       ++num_input_keys;
 
@@ -1254,16 +1273,21 @@ command_loop_1 ()
                {
                   struct Lisp_Char_Table *dp
                    = window_display_table (XWINDOW (selected_window));
-                 lose = FETCH_CHAR (PT);
-                 SET_PT (PT + 1);
+                 lose = FETCH_BYTE (PT);
+                 SET_PT (forward_point (1));
                  if ((dp
                       ? (VECTORP (DISP_CHAR_VECTOR (dp, lose))
                          ? XVECTOR (DISP_CHAR_VECTOR (dp, lose))->size == 1
                           : (NILP (DISP_CHAR_VECTOR (dp, lose))
                              && (lose >= 0x20 && lose < 0x7f)))
                       : (lose >= 0x20 && lose < 0x7f))
+                     /* To extract the case of continuation on
+                         wide-column characters.  */
+                     && (WIDTH_BY_CHAR_HEAD (FETCH_BYTE (PT)) == 1)
                      && (XFASTINT (XWINDOW (selected_window)->last_modified)
                          >= MODIFF)
+                     && (XFASTINT (XWINDOW (selected_window)->last_overlay_modified)
+                         >= OVERLAY_MODIFF)
                      && (XFASTINT (XWINDOW (selected_window)->last_point)
                          == PT - 1)
                      && !windows_or_buffers_changed
@@ -1278,8 +1302,8 @@ command_loop_1 ()
                {
                   struct Lisp_Char_Table *dp
                    = window_display_table (XWINDOW (selected_window));
-                 SET_PT (PT - 1);
-                 lose = FETCH_CHAR (PT);
+                 SET_PT (forward_point (-1));
+                 lose = FETCH_BYTE (PT);
                  if ((dp
                       ? (VECTORP (DISP_CHAR_VECTOR (dp, lose))
                          ? XVECTOR (DISP_CHAR_VECTOR (dp, lose))->size == 1
@@ -1288,6 +1312,8 @@ command_loop_1 ()
                       : (lose >= 0x20 && lose < 0x7f))
                      && (XFASTINT (XWINDOW (selected_window)->last_modified)
                          >= MODIFF)
+                     && (XFASTINT (XWINDOW (selected_window)->last_overlay_modified)
+                         >= OVERLAY_MODIFF)
                      && (XFASTINT (XWINDOW (selected_window)->last_point)
                          == PT + 1)
                      && !windows_or_buffers_changed
@@ -1302,7 +1328,7 @@ command_loop_1 ()
                       /* Try this optimization only on ascii keystrokes.  */
                       && INTEGERP (last_command_char))
                {
-                 unsigned char c = XINT (last_command_char);
+                 unsigned int c = XINT (last_command_char);
                  int value;
 
                  if (NILP (Vexecuting_macro)
@@ -1317,6 +1343,8 @@ command_loop_1 ()
                    }
                  lose = ((XFASTINT (XWINDOW (selected_window)->last_modified)
                           < MODIFF)
+                         || (XFASTINT (XWINDOW (selected_window)->last_overlay_modified)
+                             < OVERLAY_MODIFF)
                          || (XFASTINT (XWINDOW (selected_window)->last_point)
                              != PT)
                          || MODIFF <= SAVE_MODIFF
@@ -1332,7 +1360,7 @@ command_loop_1 ()
                    nonundocount = 0;
 
                  if (!lose
-                     && (PT == ZV || FETCH_CHAR (PT) == '\n'))
+                     && (PT == ZV || FETCH_BYTE (PT) == '\n'))
                    {
                      struct Lisp_Char_Table *dp
                        = window_display_table (XWINDOW (selected_window));
@@ -1412,7 +1440,7 @@ command_loop_1 ()
        {
          if (NILP (Vunread_command_events)
              && NILP (Vexecuting_macro)
-             && !NILP (sit_for (0, post_command_idle_delay, 0, 1)))
+             && !NILP (sit_for (0, post_command_idle_delay, 0, 1, 1)))
            safe_run_hooks (Qpost_command_idle_hook);
        }
 
@@ -1670,17 +1698,22 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
      Lisp_Object prev_event;
      int *used_mouse_menu;
 {
-  register Lisp_Object c;
+  Lisp_Object c;
   int count;
   jmp_buf local_getcjmp;
   jmp_buf save_jump;
   int key_already_recorded = 0;
   Lisp_Object tem, save;
   Lisp_Object also_record;
+  struct gcpro gcpro1;
+
   also_record = Qnil;
 
   before_command_key_count = this_command_key_count;
   before_command_echo_length = echo_length ();
+  c = Qnil;
+
+  GCPRO1 (c);
 
  retry:
 
@@ -1738,7 +1771,7 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
          || executing_macro_index >= XFASTINT (Flength (Vexecuting_macro)))
        {
          XSETINT (c, -1);
-         return c;
+         RETURN_UNGCPRO (c);
        }
 
       c = Faref (Vexecuting_macro, make_number (executing_macro_index));
@@ -1761,9 +1794,15 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
       goto reread_first;
     }
 
-  if (commandflag >= 0 && !input_pending
-      && !detect_input_pending_run_timers (0))
-    redisplay ();
+  if (commandflag >= 0)
+    {
+      if (input_pending
+         || detect_input_pending_run_timers (0))
+       swallow_events (0);
+
+      if (!input_pending)
+       redisplay ();
+    }
 
   /* Message turns off echoing unless more keystrokes turn it on again. */
   if (echo_area_glyphs && *echo_area_glyphs
@@ -1827,6 +1866,9 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
            *tailp = Fcons (c, Qnil);
            kb->kbd_queue_has_data = 1;
            current_kboard = kb;
+           /* This is going to exit from read_char
+              so we had better get rid of this frame's stuff.  */
+           UNGCPRO;
            longjmp (wrong_kboard_jmpbuf, 1);
          }
       }
@@ -1857,9 +1899,10 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
        {
          save_getcjmp (save_jump);
          restore_getcjmp (local_getcjmp);
-         tem0 = sit_for (echo_keystrokes, 0, 1, 1);
+         tem0 = sit_for (echo_keystrokes, 0, 1, 1, 0);
          restore_getcjmp (save_jump);
-         if (EQ (tem0, Qt))
+         if (EQ (tem0, Qt)
+             && ! CONSP (Vunread_command_events))
            echo_now ();
        }
     }
@@ -1868,7 +1911,7 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
 
   if (commandflag != 0
       && auto_save_interval > 0
-      && num_nonmacro_input_chars - last_auto_save > max (auto_save_interval, 20)
+      && num_nonmacro_input_events - last_auto_save > max (auto_save_interval, 20)
       && !detect_input_pending_run_timers (0))
     {
       Fdo_auto_save (Qnil, Qnil);
@@ -1888,7 +1931,14 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
       /* Don't bring up a menu if we already have another event.  */
       && NILP (Vunread_command_events)
       && unread_command_char < 0)
-    c = read_char_x_menu_prompt (nmaps, maps, prev_event, used_mouse_menu);
+    {
+      c = read_char_x_menu_prompt (nmaps, maps, prev_event, used_mouse_menu);
+
+      /* Now that we have read an event, Emacs is not idle.  */
+      timer_stop_idle ();
+
+      RETURN_UNGCPRO (c);
+    }
 
   /* Maybe autosave and/or garbage collect due to idleness.  */
 
@@ -1910,7 +1960,7 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
 
       /* Auto save if enough time goes by without input.  */
       if (commandflag != 0
-         && num_nonmacro_input_chars > last_auto_save
+         && num_nonmacro_input_events > last_auto_save
          && INTEGERP (Vauto_save_timeout)
          && XINT (Vauto_save_timeout) > 0)
        {
@@ -1919,10 +1969,11 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
          save_getcjmp (save_jump);
          restore_getcjmp (local_getcjmp);
          tem0 = sit_for (delay_level * XFASTINT (Vauto_save_timeout) / 4,
-                         0, 1, 1);
+                         0, 1, 1, 0);
          restore_getcjmp (save_jump);
 
-         if (EQ (tem0, Qt))
+         if (EQ (tem0, Qt)
+             && ! CONSP (Vunread_command_events))
            {
              Fdo_auto_save (Qnil, Qnil);
 
@@ -1938,6 +1989,14 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
        }
     }
 
+  /* If this has become non-nil here, it has been set by a timer
+     or sentinel or filter.  */
+  if (CONSP (Vunread_command_events))
+    {
+      c = XCONS (Vunread_command_events)->car;
+      Vunread_command_events = XCONS (Vunread_command_events)->cdr;
+    }
+
   /* Read something from current KBOARD's side queue, if possible.  */
 
   if (NILP (c))
@@ -1975,6 +2034,9 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
        if (kb->kbd_queue_has_data)
          {
            current_kboard = kb;
+           /* This is going to exit from read_char
+              so we had better get rid of this frame's stuff.  */
+           UNGCPRO;
            longjmp (wrong_kboard_jmpbuf, 1);
          }
     }
@@ -2012,6 +2074,9 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
          if (single_kboard)
            goto wrong_kboard;
          current_kboard = kb;
+         /* This is going to exit from read_char
+            so we had better get rid of this frame's stuff.  */
+         UNGCPRO;
          longjmp (wrong_kboard_jmpbuf, 1);
        }
 #endif
@@ -2037,10 +2102,7 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
 
  non_reread:
 
-  /* Now that we have read an event, Emacs is not idle--
-     unless the event was a timer event (not used now).  */
-  if (! (CONSP (c) && EQ (XCONS (c)->car, Qtimer_event)))
-    timer_stop_idle ();
+  timer_stop_idle ();
 
   start_polling ();
 
@@ -2056,12 +2118,10 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
  non_reread_1:
 
   /* Buffer switch events are only for internal wakeups
-     so don't show them to the user.  */
-  if (BUFFERP (c))
-    return c;
-
-  if (key_already_recorded)
-    return c;
+     so don't show them to the user.
+     Also, don't record a key if we already did.  */
+  if (BUFFERP (c) || key_already_recorded)
+    RETURN_UNGCPRO (c);
 
   /* Process special events within read_char
      and loop around to read another event.  */
@@ -2086,6 +2146,8 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
     }
 
   /* Wipe the echo area.  */
+  if (echo_area_glyphs)
+    safe_run_hooks (Qecho_area_clear_hook);
   echo_area_glyphs = 0;
 
   /* Handle things that only apply to characters.  */
@@ -2093,7 +2155,7 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
     {
       /* If kbd_buffer_get_event gave us an EOF, return that.  */
       if (XINT (c) == -1)
-       return c;
+       RETURN_UNGCPRO (c);
 
       if (STRINGP (Vkeyboard_translate_table)
          && XSTRING (Vkeyboard_translate_table)->size > (unsigned) XFASTINT (c))
@@ -2141,6 +2203,7 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
 
  from_macro:
  reread_first:
+
   before_command_key_count = this_command_key_count;
   before_command_echo_length = echo_length ();
 
@@ -2165,7 +2228,7 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
   /* Re-reading in the middle of a command */
  reread:
   last_input_char = c;
-  num_input_chars++;
+  num_input_events++;
 
   /* Process the help character specially if enabled */
   if (!NILP (Vhelp_form) && help_char_p (c))
@@ -2197,7 +2260,40 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
        }
     }
 
-  return c;
+  RETURN_UNGCPRO (c);
+}
+
+/* Record a key that came from a mouse menu.
+   Record it for echoing, for this-command-keys, and so on.  */
+
+static void
+record_menu_key (c)
+     Lisp_Object c;
+{
+  /* Wipe the echo area.  */
+  echo_area_glyphs = 0;
+
+  record_char (c);
+
+  before_command_key_count = this_command_key_count;
+  before_command_echo_length = echo_length ();
+
+  /* Don't echo mouse motion events.  */
+  if (echo_keystrokes)
+    {
+      echo_char (c);
+
+      /* Once we reread a character, echoing can happen
+        the next time we pause to read a new one.  */
+      ok_to_echo_at_next_pause = 0;
+    }
+
+  /* Record this character as part of the current key.  */
+  add_command_key (c);
+
+  /* Re-reading in the middle of a command */
+  last_input_char = c;
+  num_input_events++;
 }
 
 /* Return 1 if should recognize C as "the help character".  */
@@ -2261,7 +2357,7 @@ record_char (c)
 
   store_kbd_macro_char (c);
 
-  num_nonmacro_input_chars++;
+  num_nonmacro_input_events++;
 }
 
 Lisp_Object
@@ -2600,6 +2696,15 @@ kbd_buffer_get_event (kbp, used_mouse_menu)
 #endif /* not VMS */
     }
 
+  if (CONSP (Vunread_command_events))
+    {
+      Lisp_Object first;
+      first = XCONS (Vunread_command_events)->car;
+      Vunread_command_events = XCONS (Vunread_command_events)->cdr;
+      *kbp = current_kboard;
+      return first;
+    }
+
   /* At this point, we know that there is a readable event available
      somewhere.  If the event queue is empty, then there must be a
      mouse movement enabled and available.  */
@@ -2867,29 +2972,6 @@ swallow_events (do_display)
          abort ();
 #endif
        }
-      /* Note that timer_event is currently never used.  */
-      else if (event->kind == timer_event)
-       {
-         Lisp_Object tem, lisp_event;
-         int was_locked = single_kboard;
-
-         tem = get_keymap_1 (Vspecial_event_map, 0, 0);
-         tem = get_keyelt (access_keymap (tem, Qtimer_event, 0, 0),
-                           1);
-         lisp_event = Fcons (Qtimer_event,
-                             Fcons (Fcdr (event->frame_or_window), Qnil));
-         kbd_fetch_ptr = event + 1;
-         if (kbd_fetch_ptr == kbd_store_ptr)
-           input_pending = 0;
-         Fcommand_execute (tem, Qnil, Fvector (1, &lisp_event), Qt);
-         timers_run++;
-         if (do_display)
-           redisplay_preserve_echo_area ();
-
-         /* Resume allowing input from any kboard, if that was true before.  */
-         if (!was_locked)
-           any_kboard_state ();
-       }
       else
        break;
     }
@@ -2960,8 +3042,6 @@ timer_check (do_it_now)
   EMACS_TIME nexttime;
   EMACS_TIME now, idleness_now;
   Lisp_Object timers, idle_timers, chosen_timer;
-  /* Nonzero if we generate some events.  */
-  int events_generated = 0;
   struct gcpro gcpro1, gcpro2, gcpro3;
 
   EMACS_SET_SECS (nexttime, -1);
@@ -3098,64 +3178,27 @@ timer_check (do_it_now)
        {
          if (NILP (vector[0]))
            {
+             Lisp_Object tem;
+             int was_locked = single_kboard;
+             int count = specpdl_ptr - specpdl;
+
              /* Mark the timer as triggered to prevent problems if the lisp
                 code fails to reschedule it right.  */
              vector[0] = Qt;
 
-             /* Run the timer or queue a timer event.  */
-             if (1)
-               {
-                 Lisp_Object tem, event;
-                 int was_locked = single_kboard;
-                 int count = specpdl_ptr - specpdl;
-
-                 specbind (Qinhibit_quit, Qt);
+             specbind (Qinhibit_quit, Qt);
 
-                 tem = get_keymap_1 (Vspecial_event_map, 0, 0);
-                 tem = get_keyelt (access_keymap (tem, Qtimer_event, 0, 0),
-                                   1);
-                 event = Fcons (Qtimer_event, Fcons (chosen_timer, Qnil));
-                 Fcommand_execute (tem, Qnil, Fvector (1, &event), Qt);
-                 timers_run++;
+             call1 (Qtimer_event_handler, chosen_timer);
+             timers_run++;
 
-                 unbind_to (count, Qnil);
+             unbind_to (count, Qnil);
 
-                 /* Resume allowing input from any kboard, if that was true before.  */
-                 if (!was_locked)
-                   any_kboard_state ();
+             /* Resume allowing input from any kboard, if that was true before.  */
+             if (!was_locked)
+               any_kboard_state ();
 
-                 /* Since we have handled the event,
-                    we don't need to tell the caller to wake up and do it.  */
-               }
-#if 0
-             else
-               {
-                 /* Generate a timer event so the caller will handle it.  */
-                 struct input_event event;
-
-                 event.kind = timer_event;
-                 event.modifiers = 0;
-                 event.x = event.y = Qnil;
-                 event.timestamp = triggertime;
-                 /* Store the timer in the frame slot.  */
-                 event.frame_or_window
-                   = Fcons (Fselected_frame (), chosen_timer);
-                 kbd_buffer_store_event (&event);
-
-                 last_timer_event = event;
-
-                 /* Tell caller to handle this event right away.  */
-                 events_generated = 1;
-                 EMACS_SET_SECS (nexttime, 0);
-                 EMACS_SET_USECS (nexttime, 0);
-
-                 /* Don't queue more than one event at once.
-                    When Emacs is ready for another, it will
-                    queue the next one.  */
-                 UNGCPRO;
-                 return nexttime;
-               }
-#endif /* 0 */
+             /* Since we have handled the event,
+                we don't need to tell the caller to wake up and do it.  */
            }
        }
       else
@@ -3163,10 +3206,6 @@ timer_check (do_it_now)
           return the amount of time to wait before it is ripe.  */
        {
          UNGCPRO;
-         /* But if we generated an event,
-            tell the caller to handle it now.  */
-         if (events_generated)
-           return nexttime;
          return difference;
        }
     }
@@ -3435,7 +3474,42 @@ char *lispy_function_keys[] =
     "oem_clear",     /* VK_OEM_CLEAR      0xFE */
   };
 
-#else
+#else /* not HAVE_NTGUI */
+
+#ifdef XK_kana_A
+static char *lispy_kana_keys[] =
+  {
+    /* X Keysym value */
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,   /* 0x400 .. 0x40f */
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,   /* 0x410 .. 0x41f */
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,   /* 0x420 .. 0x42f */
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,   /* 0x430 .. 0x43f */
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,   /* 0x440 .. 0x44f */
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,   /* 0x450 .. 0x45f */
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,   /* 0x460 .. 0x46f */
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,"overline",0,
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,   /* 0x480 .. 0x48f */
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,   /* 0x490 .. 0x49f */
+    0, "kana-fullstop", "kana-openingbracket", "kana-closingbracket", 
+    "kana-comma", "kana-conjunctive", "kana-WO", "kana-a",
+    "kana-i", "kana-u", "kana-e", "kana-o",
+    "kana-ya", "kana-yu", "kana-yo", "kana-tsu",
+    "prolongedsound", "kana-A", "kana-I", "kana-U",
+    "kana-E", "kana-O", "kana-KA", "kana-KI",
+    "kana-KU", "kana-KE", "kana-KO", "kana-SA",
+    "kana-SHI", "kana-SU", "kana-SE", "kana-SO",
+    "kana-TA", "kana-CHI", "kana-TSU", "kana-TE",
+    "kana-TO", "kana-NA", "kana-NI", "kana-NU",
+    "kana-NE", "kana-NO", "kana-HA", "kana-HI",
+    "kana-FU", "kana-HE", "kana-HO", "kana-MA",
+    "kana-MI", "kana-MU", "kana-ME", "kana-MO",
+    "kana-YA", "kana-YU", "kana-YO", "kana-RA",
+    "kana-RI", "kana-RU", "kana-RE", "kana-RO",
+    "kana-WA", "kana-N", "voicedsound", "semivoicedsound",
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,   /* 0x4e0 .. 0x4ef */
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,   /* 0x4f0 .. 0x4ff */
+  };
+#endif /* XK_kana_A */
 
 #define FUNCTION_KEY_OFFSET 0xff00
 
@@ -3458,7 +3532,8 @@ static char *lispy_function_keys[] =
     0, 0, 0, 0, 0, 0, 0,
     "escape",
     0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   /* 0xff20...2f */
+    0, "kanji", "muhenkan", 
+             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   /* 0xff20...2f */
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   /* 0xff30...3f */
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   /* 0xff40...4f */
 
@@ -3533,9 +3608,31 @@ static char *lispy_function_keys[] =
     0, 0, 0, 0, 0, 0, 0, 0,
     0, 0, 0, 0, 0, 0, 0, 0,     /* 0xfff0 */
     0, 0, 0, 0, 0, 0, 0, "delete"
-    };
+  };
 
-#endif /* HAVE_NTGUI */
+/* ISO 9995 Function and Modifier Keys; the first byte is 0xFE.  */
+#define ISO_FUNCTION_KEY_OFFSET 0xfe00
+
+static char *iso_lispy_function_keys[] =
+  {
+    0, 0, 0, 0, 0, 0, 0, 0,    /* 0xfe00 */
+    0, 0, 0, 0, 0, 0, 0, 0,    /* 0xfe08 */
+    0, 0, 0, 0, 0, 0, 0, 0,    /* 0xfe10 */
+    0, 0, 0, 0, 0, 0, 0, 0,    /* 0xfe18 */
+    "iso-lefttab",             /* 0xfe20 */
+    "iso-move-line-up", "iso-move-line-down", 
+    "iso-partial-line-up", "iso-partial-line-down", 
+    "iso-partial-space-left", "iso-partial-space-right", 
+    "iso-set-margin-left", "iso-set-margin-right", /* 0xffe27, 28 */
+    "iso-release-margin-left", "iso-release-margin-right",
+    "iso-release-both-margins",
+    "iso-fast-cursor-left", "iso-fast-cursor-right",
+    "iso-fast-cursor-up", "iso-fast-cursor-down",
+    "iso-continuous-underline", "iso-discontinuous-underline", /* 0xfe30, 31 */
+    "iso-emphasize", "iso-center-object", "iso-enter", /* ... 0xfe34 */
+  };
+
+#endif /* not HAVE_NTGUI */
 
 static char *lispy_mouse_names[] =
 {
@@ -3615,6 +3712,10 @@ make_lispy_event (event)
        c |= (event->modifiers
              & (meta_modifier | alt_modifier
                 | hyper_modifier | super_modifier));
+       /* Distinguish Shift-SPC from SPC.  */
+       if ((event->code & 0377) == 040
+           && event->modifiers & shift_modifier)
+         c |= shift_modifier;
        button_down_time = 0;
        XSETFASTINT (lispy_c, c);
        return lispy_c;
@@ -3649,17 +3750,33 @@ make_lispy_event (event)
                                      (unsigned)-1);
        }
 
-      return modify_event_symbol (event->code - FUNCTION_KEY_OFFSET,
-                                 event->modifiers,
-                                 Qfunction_key, Qnil,
-                                 lispy_function_keys, &func_key_syms,
-                                 (sizeof (lispy_function_keys)
-                                  / sizeof (lispy_function_keys[0])));
-      break;
-
-      /* Note that timer_event is currently never used.  */
-    case timer_event:
-      return Fcons (Qtimer_event, Fcons (Fcdr (event->frame_or_window), Qnil));
+#ifdef XK_kana_A
+      if (event->code >= 0x400 && event->code < 0x500)
+       return modify_event_symbol (event->code - 0x400,
+                                   event->modifiers & ~shift_modifier,
+                                   Qfunction_key, Qnil,
+                                   lispy_kana_keys, &func_key_syms,
+                                   (sizeof (lispy_kana_keys)
+                                    / sizeof (lispy_kana_keys[0])));
+#endif /* XK_kana_A */
+
+#ifdef ISO_FUNCTION_KEY_OFFSET
+      if (event->code < FUNCTION_KEY_OFFSET
+         && event->code >= ISO_FUNCTION_KEY_OFFSET)
+       return modify_event_symbol (event->code - ISO_FUNCTION_KEY_OFFSET,
+                                   event->modifiers,
+                                   Qfunction_key, Qnil,
+                                   iso_lispy_function_keys, &func_key_syms,
+                                   (sizeof (iso_lispy_function_keys)
+                                    / sizeof (iso_lispy_function_keys[0])));
+      else
+#endif
+       return modify_event_symbol (event->code - FUNCTION_KEY_OFFSET,
+                                   event->modifiers,
+                                   Qfunction_key, Qnil,
+                                   lispy_function_keys, &func_key_syms,
+                                   (sizeof (lispy_function_keys)
+                                    / sizeof (lispy_function_keys[0])));
 
 #ifdef HAVE_MOUSE
       /* A mouse click.  Figure out where it is, decide whether it's
@@ -3754,7 +3871,7 @@ make_lispy_event (event)
            else
              {
                int pixcolumn, pixrow;
-               column -= XINT (XWINDOW (window)->left);
+               column -= WINDOW_LEFT_MARGIN (XWINDOW (window));
                row -= XINT (XWINDOW (window)->top);
                glyph_to_pixel_coords (f, column, row, &pixcolumn, &pixrow);
                XSETINT (event->x, pixcolumn);
@@ -3906,7 +4023,7 @@ make_lispy_event (event)
       }
 
 #ifdef WINDOWSNT
-    case win32_scroll_bar_click:
+    case w32_scroll_bar_click:
       {
        int button = event->code;
        int is_double;
@@ -3934,7 +4051,7 @@ make_lispy_event (event)
                                        Fcons (part, Qnil)))));
        }
 
-       /* Always treat Win32 scroll bar events as clicks. */
+       /* Always treat W32 scroll bar events as clicks. */
        event->modifiers |= click_modifier;
 
        {
@@ -4017,7 +4134,7 @@ make_lispy_movement (frame, bar_window, part, x, y, time)
       if (WINDOWP (window))
        {
          int pixcolumn, pixrow;
-         column -= XINT (XWINDOW (window)->left);
+         column -= WINDOW_LEFT_MARGIN (XWINDOW (window));
          row -= XINT (XWINDOW (window)->top);
          glyph_to_pixel_coords (frame, column, row, &pixcolumn, &pixrow);
          XSETINT (x, pixcolumn);
@@ -4449,7 +4566,7 @@ modify_event_symbol (symbol_num, modifiers, symbol_kind, name_alist,
       /* No; let's create it.  */
       if (!NILP (name_alist))
        value = Fcdr_safe (Fassq (symbol_int, name_alist));
-      else if (name_table[symbol_num])
+      else if (name_table != 0 && name_table[symbol_num])
        value = intern (name_table[symbol_num]);
 
 #ifdef HAVE_WINDOW_SYSTEM
@@ -4777,8 +4894,7 @@ read_avail_input (expected)
 
   if (read_socket_hook)
     /* No need for FIONREAD or fcntl; just say don't wait.  */
-    nread = (*read_socket_hook) (input_fd, buf, KBD_BUFFER_SIZE,
-                                expected, expected);
+    nread = (*read_socket_hook) (input_fd, buf, KBD_BUFFER_SIZE, expected);
   else
     {
       /* Using KBD_BUFFER_SIZE - 1 here avoids reading more than
@@ -4832,6 +4948,13 @@ read_avail_input (expected)
 #else
          nread = read (input_fd, cbuf, n_to_read);
 #endif
+         /* POSIX infers that processes which are not in the session leader's
+            process group won't get SIGHUP's at logout time.  BSDI adheres to
+            this part standard and returns -1 from read(0) with errno==EIO
+            when the control tty is taken away.
+            Jeffrey Honig <jch@bsdi.com> says this is generally safe.  */
+         if (nread == -1 && errno == EIO)
+           kill (0, SIGHUP);
 #if defined (AIX) && (! defined (aix386) && defined (_BSD))
          /* The kernel sometimes fails to deliver SIGHUP for ptys.
             This looks incorrect, but it isn't, because _BSD causes
@@ -5073,7 +5196,7 @@ menu_bar_items (old)
   for (mapno = nmaps - 1; mapno >= 0; mapno--)
     {
       if (! NILP (maps[mapno]))
-       def = get_keyelt (access_keymap (maps[mapno], Qmenu_bar, 1, 0));
+       def = get_keyelt (access_keymap (maps[mapno], Qmenu_bar, 1, 0), 0);
       else
        def = Qnil;
 
@@ -5361,6 +5484,8 @@ read_char_x_menu_prompt (nmaps, maps, prev_event, used_mouse_menu)
        {
          Lisp_Object tem;
 
+         record_menu_key (XCONS (value)->car);
+
          /* If we got multiple events, unread all but
             the first.
             There is no way to prevent those unread events
@@ -5371,10 +5496,13 @@ read_char_x_menu_prompt (nmaps, maps, prev_event, used_mouse_menu)
             they won't confuse things.  */
          for (tem = XCONS (value)->cdr; !NILP (tem);
               tem = XCONS (tem)->cdr)
-           if (SYMBOLP (XCONS (tem)->car)
-               || INTEGERP (XCONS (tem)->car))
-             XCONS (tem)->car
-               = Fcons (XCONS (tem)->car, Qnil);
+           {
+             record_menu_key (XCONS (tem)->car);
+             if (SYMBOLP (XCONS (tem)->car)
+                 || INTEGERP (XCONS (tem)->car))
+               XCONS (tem)->car
+                 = Fcons (XCONS (tem)->car, Qnil);
+           }
 
          /* If we got more than one event, put all but the first
             onto this list to be read later.
@@ -5655,7 +5783,7 @@ follow_key (key, nmaps, current, defs, next)
          {
            Lisp_Object def;
            def = get_keyelt (access_keymap (current[i],
-                                            meta_prefix_char, 1, 0));
+                                            meta_prefix_char, 1, 0), 0);
 
            /* Note that since we pass the resulting bindings through
               get_keymap_1, non-prefix bindings for meta-prefix-char
@@ -5680,7 +5808,7 @@ follow_key (key, nmaps, current, defs, next)
          else
            map = current[i];
 
-         defs[i] = get_keyelt (access_keymap (map, key, 1, 0));
+         defs[i] = get_keyelt (access_keymap (map, key, 1, 0), 0);
          if (! NILP (defs[i]))
            first_binding = i;
        }
@@ -5728,16 +5856,20 @@ follow_key (key, nmaps, current, defs, next)
 
    If the user switches frames in the midst of a key sequence, we put
    off the switch-frame event until later; the next call to
-   read_char will return it.  */
+   read_char will return it.
+
+   If FIX_CURRENT_BUFFER is nonzero, we restore current_buffer
+   from the selected window's buffer.  */
 
 static int
 read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
-                  can_return_switch_frame)
+                  can_return_switch_frame, fix_current_buffer)
      Lisp_Object *keybuf;
      int bufsize;
      Lisp_Object prompt;
      int dont_downcase_last;
      int can_return_switch_frame;
+     int fix_current_buffer;
 {
   int count = specpdl_ptr - specpdl;
 
@@ -5829,12 +5961,12 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
   /* Save the status of key translation before each step,
      so that we can restore this after downcasing.  */
   Lisp_Object prev_fkey_map;
-  Lisp_Object prev_fkey_start;
-  Lisp_Object prev_fkey_end;
+  int prev_fkey_start;
+  int prev_fkey_end;
 
   Lisp_Object prev_keytran_map;
-  Lisp_Object prev_keytran_start;
-  Lisp_Object prev_keytran_end;
+  int prev_keytran_start;
+  int prev_keytran_end;
 
   int junk;
 
@@ -6077,6 +6209,14 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
          if (BUFFERP (key))
            {
              mock_input = t;
+             /* Reset the current buffer from the selected window
+                in case something changed the former and not the latter.
+                This is to be more consistent with the behavior
+                of the command_loop_1.  */
+             if (fix_current_buffer)
+               if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
+                 Fset_buffer (XWINDOW (selected_window)->buffer);
+
              orig_local_map = get_local_map (PT, current_buffer);
              goto replay_sequence;
            }
@@ -6420,7 +6560,7 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
                  fkey_next
                    = get_keymap_1
                      (get_keyelt
-                      (access_keymap (fkey_map, meta_prefix_char, 1, 0)),
+                      (access_keymap (fkey_map, meta_prefix_char, 1, 0), 0),
                       0, 1);
                  XSETFASTINT (key, XFASTINT (key) & ~meta_modifier);
                }
@@ -6428,7 +6568,7 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
                fkey_next = fkey_map;
 
              fkey_next
-               = get_keyelt (access_keymap (fkey_next, key, 1, 0));
+               = get_keyelt (access_keymap (fkey_next, key, 1, 0), 0);
 
 #if 0 /* I didn't turn this on, because it might cause trouble
         for the mapping of return into C-m and tab into C-i.  */
@@ -6528,7 +6668,7 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
                keytran_next
                  = get_keymap_1
                    (get_keyelt
-                    (access_keymap (keytran_map, meta_prefix_char, 1, 0)),
+                    (access_keymap (keytran_map, meta_prefix_char, 1, 0), 0),
                     0, 1);
                XSETFASTINT (key, XFASTINT (key) & ~meta_modifier);
              }
@@ -6536,7 +6676,7 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
              keytran_next = keytran_map;
 
            keytran_next
-             = get_keyelt (access_keymap (keytran_next, key, 1, 0));
+             = get_keyelt (access_keymap (keytran_next, key, 1, 0), 0);
 
            /* If the key translation map gives a function, not an
               array, then call the function with no args and use
@@ -6797,7 +6937,7 @@ DEFUN ("read-key-sequence", Fread_key_sequence, Sread_key_sequence, 1, 4, 0,
 
   i = read_key_sequence (keybuf, (sizeof keybuf/sizeof (keybuf[0])),
                         prompt, ! NILP (dont_downcase_last),
-                        ! NILP (can_return_switch_frame));
+                        ! NILP (can_return_switch_frame), 0);
 
   if (i == -1)
     {
@@ -6946,7 +7086,7 @@ DEFUN ("execute-extended-command", Fexecute_extended_command, Sexecute_extended_
      history list. */
   function = Fcompleting_read (build_string (buf),
                               Vobarray, Qcommandp,
-                              Qt, Qnil, Qextended_command_history);
+                              Qt, Qnil, Qextended_command_history, Qnil);
 
   if (STRINGP (function) && XSTRING (function)->size == 0)
     error ("No command name given");
@@ -7002,7 +7142,8 @@ DEFUN ("execute-extended-command", Fexecute_extended_command, Sexecute_extended_
       /* But first wait, and skip the message if there is input.  */
       if (!NILP (Fsit_for ((NUMBERP (Vsuggest_key_bindings)
                            ? Vsuggest_key_bindings : make_number (2)),
-                          Qnil, Qnil)))
+                          Qnil, Qnil))
+         && ! CONSP (Vunread_command_events))
        {
          Lisp_Object binding;
          char *newmessage;
@@ -7311,7 +7452,7 @@ stuff_buffered_input (stuffstring)
      Lisp_Object stuffstring;
 {
 /* stuff_char works only in BSD, versions 4.2 and up.  */
-#ifdef BSD
+#ifdef BSD_SYSTEM
 #ifndef BSD4_1
   register unsigned char *p;
 
@@ -7341,7 +7482,7 @@ stuff_buffered_input (stuffstring)
     }
   input_pending = 0;
 #endif
-#endif /* BSD and not BSD4_1 */
+#endif /* BSD_SYSTEM and not BSD4_1 */
 }
 \f
 set_waiting_for_input (time_to_clear)
@@ -7397,11 +7538,17 @@ interrupt_signal (signalnum)    /* If we don't have an argument, */
 
   cancel_echoing ();
 
-  if (!NILP (Vquit_flag) && FRAME_TERMCAP_P (selected_frame))
+  if (!NILP (Vquit_flag)
+      && (FRAME_TERMCAP_P (selected_frame) || FRAME_MSDOS_P (selected_frame)))
     {
+      /* If SIGINT isn't blocked, don't let us be interrupted by
+        another SIGINT, it might be harmful due to non-reentrancy
+        in I/O functions.  */
+      sigblock (sigmask (SIGINT));
+
       fflush (stdout);
       reset_sys_modes ();
-      sigfree ();
+
 #ifdef SIGTSTP                 /* Support possible in later USG versions */
 /*
  * On systems which can suspend the current process and return to the original
@@ -7480,6 +7627,7 @@ interrupt_signal (signalnum)      /* If we don't have an argument, */
 #endif /* not MSDOS */
       fflush (stdout);
       init_sys_modes ();
+      sigfree ();
     }
   else
     {
@@ -7781,6 +7929,9 @@ struct event_head head_table[] = {
 
 syms_of_keyboard ()
 {
+  Qtimer_event_handler = intern ("timer-event-handler");
+  staticpro (&Qtimer_event_handler);
+
   Qdisabled_command_hook = intern ("disabled-command-hook");
   staticpro (&Qdisabled_command_hook);
 
@@ -7818,8 +7969,6 @@ syms_of_keyboard ()
   staticpro (&Qfunction_key);
   Qmouse_click = intern ("mouse-click");
   staticpro (&Qmouse_click);
-  Qtimer_event = intern ("timer-event");
-  staticpro (&Qtimer_event);
 
   Qmenu_enable = intern ("menu-enable");
   staticpro (&Qmenu_enable);
@@ -7915,6 +8064,12 @@ syms_of_keyboard ()
   unread_switch_frame = Qnil;
   staticpro (&unread_switch_frame);
 
+  internal_last_event_frame = Qnil;
+  staticpro (&internal_last_event_frame);
+
+  read_key_sequence_cmd = Qnil;
+  staticpro (&read_key_sequence_cmd);
+
   defsubr (&Sevent_convert_list);
   defsubr (&Sread_key_sequence);
   defsubr (&Srecursive_edit);
@@ -8021,14 +8176,25 @@ by position only.");
   inhibit_local_menu_bar_menus = 0;
 
   DEFVAR_INT ("num-input-keys", &num_input_keys,
-    "Number of complete keys read from the keyboard so far.");
+    "Number of complete key sequences read as input so far.\n\
+This includes key sequences read from keyboard macros.\n\
+The number is effectively the number of interactive command invocations.");
   num_input_keys = 0;
 
+  DEFVAR_INT ("num-nonmacro-input-events", &num_nonmacro_input_events,
+    "Number of input events read from the keyboard so far.\n\
+This does not include events generated by keyboard macros.");
+  num_nonmacro_input_events = 0;
+
   DEFVAR_LISP ("last-event-frame", &Vlast_event_frame,
     "The frame in which the most recently read event occurred.\n\
 If the last event came from a keyboard macro, this is set to `macro'.");
   Vlast_event_frame = Qnil;
 
+  /* This variable is set up in sysdep.c.  */
+  DEFVAR_LISP ("tty-erase-char", &Vtty_erase_char,
+    "The ERASE character as set by the user with stty.");
+
   DEFVAR_LISP ("help-char", &Vhelp_char,
     "Character to recognize as meaning Help.\n\
 When it is read, do `(eval help-form)', and display result if it's a string.\n\
@@ -8131,6 +8297,13 @@ This feature is obsolete; use idle timers instead.  See `etc/NEWS'.");
 This is measured in microseconds.");
   post_command_idle_delay = 100000;
 
+#if 0
+  DEFVAR_LISP ("echo-area-clear-hook", ...,
+    "Normal hook run when clearing the echo area.");
+#endif
+  Qecho_area_clear_hook = intern ("echo-area-clear-hook");
+  XSYMBOL (Qecho_area_clear_hook)->value = Qnil;
+
   DEFVAR_LISP ("lucid-menu-bar-dirty-flag", &Vlucid_menu_bar_dirty_flag,
     "t means menu bar, specified Lucid style, needs to be recomputed.");
   Vlucid_menu_bar_dirty_flag = Qnil;
@@ -8142,9 +8315,11 @@ The elements of the list are event types that may have menu bar bindings.");
 
   DEFVAR_KBOARD ("overriding-terminal-local-map",
                 Voverriding_terminal_local_map,
-    "Keymap that overrides all other local keymaps.\n\
+    "Per-terminal keymap that overrides all other local keymaps.\n\
 If this variable is non-nil, it is used as a keymap instead of the\n\
-buffer's local map, and the minor mode keymaps and text property keymaps.");
+buffer's local map, and the minor mode keymaps and text property keymaps.\n\
+This variable is intended to let commands such as `universal-argumemnt'\n\
+set up a different keymap for reading the next command.");
 
   DEFVAR_LISP ("overriding-local-map", &Voverriding_local_map,
     "Keymap that overrides all other local keymaps.\n\