texinfo-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[5681] intermediate processing between input bytes and dispatching on ke


From: Gavin D. Smith
Subject: [5681] intermediate processing between input bytes and dispatching on keys
Date: Sat, 28 Jun 2014 15:54:03 +0000

Revision: 5681
          http://svn.sv.gnu.org/viewvc/?view=rev&root=texinfo&revision=5681
Author:   gavin
Date:     2014-06-28 15:54:00 +0000 (Sat, 28 Jun 2014)
Log Message:
-----------
intermediate processing between input bytes and dispatching on keys

Modified Paths:
--------------
    trunk/ChangeLog
    trunk/info/doc.h
    trunk/info/echo-area.c
    trunk/info/infodoc.c
    trunk/info/infokey.c
    trunk/info/infokey.h
    trunk/info/infomap.c
    trunk/info/infomap.h
    trunk/info/session.c
    trunk/info/session.h
    trunk/info/terminal.c

Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog     2014-06-20 17:27:15 UTC (rev 5680)
+++ trunk/ChangeLog     2014-06-28 15:54:00 UTC (rev 5681)
@@ -1,3 +1,80 @@
+2014-06-28  Gavin Smith  <address@hidden>
+
+       * info/infokey.h:
+       (SK_RIGHT_ARROW, SK_LEFT_ARROW, SK_UP_ARROW, SK_DOWN_ARROW, SK_PAGE_UP)
+       (SK_PAGE_DOWN SK_HOME, SK_END, SK_DELETE, SK_INSERT, SK_CTL_LEFT_ARROW)
+       (SK_CTL_RIGHT_ARROW, SK_CTL_DELETE, SK_BACK_TAB): Removed.
+       (struct sect): Removed.
+
+       * info/infomap.h (BYTEMAP_ENTRY): New typedef.
+       (BYTEMAP_NONE, BYTEMAP_KEY, BYTEMAP_MAP, BYTEMAP_ESC): New symbols.
+       * info/terminal.c (byte_seq_to_key): New variable.
+       (initialize_byte_map): New function.
+       (terminal_initialize_terminal): Call it.
+
+       * info/infomap.h
+       (KEY_RIGHT_ARROW, KEY_LEFT_ARROW, KEY_UP_ARROW, KEY_DOWN_ARROW)
+       (KEY_PAGE_UP, KEY_PAGE_DOWN, KEY_HOME, KEY_END, KEY_DELETE, KEY_INSERT)
+       (KEY_CTL_LEFT_ARROW, KEY_CTL_RIGHT_ARROW, KEY_CTL_DELETE)
+       (KEY_BACK_TAB): New symbols.
+       (KEYMAP_SIZE, KEYMAP_META_BASE, KEYMAP_META): New symbols.
+
+       * info/infomap.c (keymap_make_keymap, keymap_discard_keymap): Make
+       keymap as big as KEYMAP_SIZE.
+       (default_emacs_like_info_keys, default_emacs_like_ea_keys)
+       (default_vi_like_info_keys, default_vi_like_ea_keys):
+       Arrays of int instead of arrays of char.  Use KEY_* symbols instead of
+       SK_* sequences.  Use KEYMAP_META macro instead of Meta.  Avoid some
+       duplication where both a sequence with ESC Key and Meta-Key were
+       bound.  Don't specify sequences produced by special keys.
+       (section_to_keymaps): Process new format specifying key bindings.
+       (decode_keys): Removed.
+       (find_function_keyseq, add_function_keyseq, remove_function_keyseq):
+       Keys are represented with type int instead of char.
+       (keymap_copy_keymap): Removed.
+       (keymap_bind_keyseq): Don't override already bound key sequences.  No
+       longer static.
+       (keymap_make_keymap): Don't bind upper-case characters to
+       info_do_lowercase_version.
+       (read_init_file): Do it here instead.
+
+       * info/session.c (info_get_input_char, info_get_input_byte): Renamed.
+       (info_get_another_input_char, info_get_another_input_byte): Renamed.
+
+       (info_get_key_from_typeahead, get_byte_from_input_buffer): Renamed.
+       (info_gather_typeahead): Declared static.  New argument added saying
+       whether to wait for input.
+
+       (info_dispatch_on_key, dispatch_error, add_char_to_keyseq): Arguments
+       changed from char to int.
+       (info_keyseq): Type changed.
+       (info_dispatch_on_key) <info_do_lowercase_version>: Updated to match
+       new meaning of key numbers.
+
+       (get_another_input_key): New function based on
+       info_get_another_input_byte.
+       (info_dispatch_on_key): Call it.
+
+       (get_input_key): New function.
+       (read_and_dispatch): Call it.
+       * info/echo-area.c (read_and_dispatch_in_echo_area): Call get_input_key
+       instead of info_get_input_char.
+
+       * info/doc.h (FUNCTION_KEYSEQ): Type of keyseq field changed.
+
+       * info/infokey.c (compile): Arguments changed.  Apply key bindings from
+       init file directly instead of compiling into an intermediate
+       representation.
+       (add_to_section): Removed.
+
+       * info/infodoc.c (dump_map_to_text_buffer): Arguments changed.  Handle
+       arrays of int representing key sequences instead of arrays of char.
+       Keymap array has size KEYMAP_SIZE instead of 256.
+       (pretty_keyname, pretty_keyseq, pretty_keyseq_internal): Arguments
+       changed.  Callers updated.
+       (pretty_keyname): Handle named keys.
+       (pretty_keyseq_internal): Don't handle named keys specially.
+
 2014-06-20  Gavin Smith  <address@hidden>
 
        * info/echo-area.c (read_and_dispatch_in_echo_area): Copy of

Modified: trunk/info/doc.h
===================================================================
--- trunk/info/doc.h    2014-06-20 17:27:15 UTC (rev 5680)
+++ trunk/info/doc.h    2014-06-28 15:54:00 UTC (rev 5681)
@@ -40,7 +40,7 @@
 {
   struct function_keyseq *next;
   struct keymap_entry *map;
-  char *keyseq;
+  int *keyseq;
 } FUNCTION_KEYSEQ;
 
 /* An array of FUNCTION_DOC structures is defined in doc.c, which is
@@ -74,8 +74,8 @@
 extern InfoCommand *named_function (char *name);
 
 extern char *function_documentation (InfoCommand *cmd);
-extern char *pretty_keyname (unsigned char key);
-extern char *pretty_keyseq (char *keyseq);
+extern char *pretty_keyname (int key);
+extern char *pretty_keyseq (int *keyseq);
 extern char *where_is (Keymap map, InfoCommand *cmd);
 extern char *replace_in_documentation (const char *string,
     int help_is_only_window_p);

Modified: trunk/info/echo-area.c
===================================================================
--- trunk/info/echo-area.c      2014-06-20 17:27:15 UTC (rev 5680)
+++ trunk/info/echo-area.c      2014-06-28 15:54:00 UTC (rev 5681)
@@ -163,7 +163,7 @@
 static void
 read_and_dispatch_in_echo_area (void)
 {
-  unsigned char key;
+  int key;
 
   while (1)
     {
@@ -179,7 +179,7 @@
       info_initialize_numeric_arg ();
 
       initialize_keyseq ();
-      key = info_get_input_char ();
+      key = get_input_key ();
 
       info_error_was_printed = 0;
 
@@ -479,7 +479,7 @@
 {
   unsigned char character;
 
-  character = info_get_another_input_char ();
+  character = info_get_another_input_byte ();
   ea_insert (window, count, character);
 }
 

Modified: trunk/info/infodoc.c
===================================================================
--- trunk/info/infodoc.c        2014-06-20 17:27:15 UTC (rev 5680)
+++ trunk/info/infodoc.c        2014-06-28 15:54:00 UTC (rev 5681)
@@ -85,22 +85,28 @@
 
 static char *where_is_internal (Keymap map, InfoCommand *cmd);
 
-void
-dump_map_to_text_buffer (struct text_buffer *tb, char *prefix, Keymap map)
+static void
+dump_map_to_text_buffer (struct text_buffer *tb, int *prefix,
+                         int prefix_len, Keymap map)
 {
   register int i;
-  unsigned prefix_len = strlen (prefix);
-  char *new_prefix = xmalloc (prefix_len + 2);
+  int *new_prefix = xmalloc ((prefix_len + 2) * sizeof (int));
 
-  strncpy (new_prefix, prefix, prefix_len);
-  new_prefix[prefix_len + 1] = '\0';
+  memcpy (new_prefix, prefix, prefix_len * sizeof (int));
+  new_prefix[prefix_len + 1] = 0;
 
-  for (i = 0; i < 256; i++)
+  for (i = 0; i < KEYMAP_SIZE; i++)
     {
+      if (i == 128)
+        i = 256;
+      if (i == 128 + KEYMAP_META_BASE)
+        i = 256 + KEYMAP_META_BASE;
+
       new_prefix[prefix_len] = i;
       if (map[i].type == ISKMAP)
         {
-          dump_map_to_text_buffer (tb, new_prefix, (Keymap)map[i].function);
+          dump_map_to_text_buffer (tb, new_prefix, prefix_len + 1,
+                                   (Keymap)map[i].function);
         }
       else if (map[i].function)
         {
@@ -124,8 +130,8 @@
             continue;
 
           /* Find out if there is a series of identical functions, as in
-             ea_insert (). */
-          for (last = i + 1; last < 256; last++)
+             add-digit-to-numeric-arg. */
+          for (last = i + 1; last < KEYMAP_SIZE; last++)
             if ((map[last].type != ISFUNC) ||
                 (map[last].function != map[i].function))
               break;
@@ -210,10 +216,10 @@
       free (infopath_str);
 
       text_buffer_printf (&msg, _("Commands available in Info windows:\n\n"));
-      dump_map_to_text_buffer (&msg, "", info_keymap);
+      dump_map_to_text_buffer (&msg, 0, 0, info_keymap);
       text_buffer_printf (&msg, "---------------------\n\n");
       text_buffer_printf (&msg, _("Commands available in the echo area:\n\n"));
-      dump_map_to_text_buffer (&msg, "", echo_area_keymap);
+      dump_map_to_text_buffer (&msg, 0, 0, echo_area_keymap);
 
       /* Get a list of commands which have no keystroke equivs. */
       exec_keys = where_is (info_keymap, InfoCmd(info_execute_command));
@@ -468,9 +474,9 @@
 
 DECLARE_INFO_COMMAND (describe_key, _("Print documentation for KEY"))
 {
-  char keys[50];
+  int keys[50];
   unsigned char keystroke;
-  char *k = keys;
+  int *k = keys;
   Keymap map = info_keymap;
 
   *k = '\0';
@@ -478,7 +484,7 @@
   for (;;)
     {
       message_in_echo_area (_("Describe key: %s"), pretty_keyseq (keys));
-      keystroke = info_get_input_char ();
+      keystroke = info_get_input_byte ();
       unmessage_in_echo_area ();
 
       /* Add the KEYSTROKE to our list. */
@@ -540,16 +546,16 @@
 
 /* Return the pretty printable name of a single character. */
 char *
-pretty_keyname (unsigned char key)
+pretty_keyname (int key)
 {
   static char rep_buffer[30];
   char *rep;
 
-  if (Meta_p (key))
+  if (key >= KEYMAP_META_BASE)
     {
       char temp[20];
 
-      rep = pretty_keyname (UnMeta (key));
+      rep = pretty_keyname (key - KEYMAP_META_BASE);
 
       sprintf (temp, "M-%s", rep);
       strcpy (rep_buffer, temp);
@@ -569,6 +575,34 @@
           rep = rep_buffer;
         }
     }
+  else if (key >= 256)
+    switch (key)
+      {
+      case KEY_RIGHT_ARROW:
+        rep = "Right"; break;
+      case KEY_LEFT_ARROW:
+        rep = "Left"; break;
+      case KEY_UP_ARROW:
+        rep = "Up"; break;
+      case KEY_DOWN_ARROW:
+        rep = "Down"; break;
+      case KEY_PAGE_UP:
+        rep = "PgUp"; break;
+      case KEY_PAGE_DOWN:
+        rep = "PgDn"; break;
+      case KEY_HOME:
+        rep = "Home"; break;
+      case KEY_END:
+        rep = "End"; break;
+      case KEY_DELETE:
+        rep = "DEL"; break;
+      case KEY_INSERT:
+        rep = "INS"; break;
+      case KEY_BACK_TAB:
+        rep = "BackTab"; break;
+      default:
+        rep = "shouldn't see this"; break;
+      }
   else
     {
       switch (key)
@@ -586,10 +620,10 @@
 
 /* Return the pretty printable string which represents KEYSEQ. */
 
-static void pretty_keyseq_internal (char *keyseq, char *rep);
+static void pretty_keyseq_internal (int *keyseq, char *rep);
 
 char *
-pretty_keyseq (char *keyseq)
+pretty_keyseq (int *keyseq)
 {
   static char keyseq_rep[200];
 
@@ -600,72 +634,20 @@
 }
 
 static void
-pretty_keyseq_internal (char *keyseq, char *rep)
+pretty_keyseq_internal (int *keyseq, char *rep)
 {
-  if (term_kP && strncmp(keyseq, term_kP, strlen(term_kP)) == 0)
+  if (!*keyseq)
+    return;
+
+  while (1)
     {
-      strcpy(rep, "PgUp");
-      keyseq += strlen(term_kP);
-    }
-  else if (term_kN && strncmp(keyseq, term_kN, strlen(term_kN)) == 0)
-    {
-      strcpy(rep, "PgDn");
-      keyseq += strlen(term_kN);
-    }
-  else if (term_kh && strncmp(keyseq, term_kh, strlen(term_kh)) == 0)
-    {
-      strcpy(rep, "Home");
-      keyseq += strlen(term_kh);
-    }
-  else if (term_ke && strncmp(keyseq, term_ke, strlen(term_ke)) == 0)
-    {
-      strcpy(rep, "End");
-      keyseq += strlen(term_ke);
-    }
-  else if (term_ki && strncmp(keyseq, term_ki, strlen(term_ki)) == 0)
-    {
-      strcpy(rep, "INS");
-      keyseq += strlen(term_ki);
-    }
-  else if (term_kx && strncmp(keyseq, term_kx, strlen(term_kx)) == 0)
-    {
-      strcpy(rep, "DEL");
-      keyseq += strlen(term_kx);
-    }
-  else if (term_ku && strncmp(keyseq, term_ku, strlen(term_ku)) == 0)
-    {
-      strcpy(rep, "Up");
-      keyseq += strlen(term_ku);
-    }
-  else if (term_kd && strncmp(keyseq, term_kd, strlen(term_kd)) == 0)
-    {
-      strcpy(rep, "Down");
-      keyseq += strlen(term_kd);
-    }
-  else if (term_kl && strncmp(keyseq, term_kl, strlen(term_kl)) == 0)
-    {
-      strcpy(rep, "Left");
-      keyseq += strlen(term_kl);
-    }
-  else if (term_kr && strncmp(keyseq, term_kr, strlen(term_kr)) == 0)
-    {
-      strcpy(rep, "Right");
-      keyseq += strlen(term_kr);
-    }
-  else if (term_bt && strncmp(keyseq, term_bt, strlen(term_bt)) == 0)
-    {
-      strcpy(rep, "BackTab");
-      keyseq += strlen(term_kr);
-    }
-  else
-    {
-      strcpy (rep, pretty_keyname (keyseq[0]));
+      strcat (rep, pretty_keyname (keyseq[0]));
       keyseq++;
-    }
-  if (*keyseq)
-    {
+
+      if (!*keyseq)
+        break;
+
       strcat (rep, " ");
-      pretty_keyseq_internal (keyseq, rep + strlen(rep));
     }
 }
 

Modified: trunk/info/infokey.c
===================================================================
--- trunk/info/infokey.c        2014-06-20 17:27:15 UTC (rev 5680)
+++ trunk/info/infokey.c        2014-06-28 15:54:00 UTC (rev 5681)
@@ -35,8 +35,6 @@
     var = 2
   };
 
-/* Some "forward" declarations. */
-int compile (FILE *fp, const char *filename, struct sect *sections);
 static void syntax_error (const char *filename, unsigned int linenum,
                          const char *fmt, ...) TEXINFO_PRINTFLIKE(3,4);
 
@@ -155,14 +153,13 @@
        following the '=' is not ignored.
  */
 
-static int add_to_section (struct sect *s, const char *str, unsigned int len);
 static int lookup_action (const char *actname);
 
-/* Compile the input file into its various sections.  Return true if no
-   error was encountered.
- */
+/* Read the init file.  Return true if no error was encountered.  Set
+   SUPPRESS_INFO or SUPPRESS_EA to true if the init file specified to ignore
+   default key bindings. */
 int
-compile (FILE *fp, const char *filename, struct sect *sections)
+compile (FILE *fp, const char *filename, int *suppress_info, int *suppress_ea)
 {
   int error = 0;
   char rescan = 0;
@@ -212,7 +209,7 @@
   char oval = 0;
   char comment[10];
   unsigned int clen = 0;
-  char seq[20];
+  int seq[20];
   unsigned int slen = 0;
   char act[80];
   unsigned int alen = 0;
@@ -223,7 +220,7 @@
 
 #define        To_seq(c) \
                  do { \
-                   if (slen < sizeof seq) \
+                   if (slen < sizeof seq/sizeof(int)) \
                      seq[slen++] = meta ? Meta(c) : (c); \
                    else \
                      { \
@@ -234,12 +231,6 @@
                    meta = 0; \
                  } while (0)
 
-  sections[info].cur = 1;
-  sections[info].data[0] = 0;
-  sections[ea].cur = 1;
-  sections[ea].data[0] = 0;
-  sections[var].cur = 0;
-
   while (!error && (rescan || (c = fgetc (fp)) != EOF))
     {
       rescan = 0;
@@ -285,7 +276,12 @@
                section = var;
              else if (strcmp (comment, "stop") == 0
                       && (section == info || section == ea))
-               sections[section].data[0] = 1;
+                {
+                  if (section == info)
+                    *suppress_info == 1;
+                  else
+                    *suppress_ea == 1;
+                }
            }
          else if (clen < sizeof comment - 1)
            comment[clen++] = c;
@@ -393,19 +389,18 @@
              break;
 
            case special_key:
-             To_seq (SK_ESCAPE);
              switch (c)
                {
-               case 'u': To_seq (SK_UP_ARROW); break;
-               case 'd': To_seq (SK_DOWN_ARROW); break;
-               case 'r': To_seq (SK_RIGHT_ARROW); break;
-               case 'l': To_seq (SK_LEFT_ARROW); break;
-               case 'U': To_seq (SK_PAGE_UP); break;
-               case 'D': To_seq (SK_PAGE_DOWN); break;
-               case 'h': To_seq (SK_HOME); break;
-               case 'e': To_seq (SK_END); break;
-               case 'x': To_seq (SK_DELETE); break;
-               default:  To_seq (SK_LITERAL); rescan = 1; break;
+               case 'u': To_seq (KEY_UP_ARROW); break;
+               case 'd': To_seq (KEY_DOWN_ARROW); break;
+               case 'r': To_seq (KEY_RIGHT_ARROW); break;
+               case 'l': To_seq (KEY_LEFT_ARROW); break;
+               case 'U': To_seq (KEY_PAGE_UP); break;
+               case 'D': To_seq (KEY_PAGE_DOWN); break;
+               case 'h': To_seq (KEY_HOME); break;
+               case 'e': To_seq (KEY_END); break;
+               case 'x': To_seq (KEY_DELETE); break;
+               default:  To_seq (c); rescan = 1; break;
                }
              seqstate = normal;
              break;
@@ -449,14 +444,18 @@
                  if (a != -1)
                    {
                      char av = a;
+                      int keymap_bind_keyseq (Keymap, int *, KEYMAP_ENTRY *);
 
-                     if (!(add_to_section (&sections[section], seq, slen)
-                           && add_to_section (&sections[section], "", 1)
-                           && add_to_section (&sections[section], &av, 1)))
-                       {
-                         syntax_error (filename, lnum, _("section too long"));
-                         error = 1;
-                       }
+                      KEYMAP_ENTRY ke;
+                      
+                      ke.type = ISFUNC;
+                      ke.function = &function_doc_array[a];
+                      To_seq (0);
+
+                      if (section == info)
+                        keymap_bind_keyseq (info_keymap, seq, &ke);
+                      else /* section == ea */
+                        keymap_bind_keyseq (echo_area_keymap, seq, &ke);
                    }
                  else
                    {
@@ -528,7 +527,7 @@
                 info_error (_("%s: no such variable"), varn);
               else if (!set_variable_to_value (v, val, SET_IN_CONFIG_FILE))
                 info_error (_("value %s is not valid for variable %s"),
-                              val, var);
+                              val, varn);
            }
          else if (vallen < sizeof val - 1)
            val[vallen++] = c;
@@ -551,19 +550,6 @@
   return !error;
 }
 
-/* Add some characters to a section's data.  Return true if all the
-   characters fit, or false if the section's size limit was exceeded.
- */
-static int
-add_to_section (struct sect *s, const char *str, unsigned int len)
-{
-  if (s->cur + len > sizeof s->data)
-    return 0;
-  strncpy ((char *) s->data + s->cur, str, len);
-  s->cur += len;
-  return 1;
-}
-
 /* Return the numeric code of an Info command given its name.  If not found,
    return -1.  This uses the auto-generated array in doc.c. */
 static int

Modified: trunk/info/infokey.h
===================================================================
--- trunk/info/infokey.h        2014-06-20 17:27:15 UTC (rev 5680)
+++ trunk/info/infokey.h        2014-06-28 15:54:00 UTC (rev 5681)
@@ -68,29 +68,4 @@
 #define        UNMETA(c)               ((c) & ~0x80)
 #define        ISMETA(c)               (((c) & 0x80) != 0)
 
-/* Special keys (keys which output different strings on different terminals) */
 
-#define SK_ESCAPE              CONTROL('k')
-#define SK_RIGHT_ARROW         1
-#define SK_LEFT_ARROW          2
-#define SK_UP_ARROW            3
-#define SK_DOWN_ARROW          4
-#define SK_PAGE_UP             5
-#define SK_PAGE_DOWN           6
-#define SK_HOME                        7
-#define SK_END                 8
-#define SK_DELETE              9
-#define SK_INSERT              10
-#define SK_CTL_LEFT_ARROW      11
-#define SK_CTL_RIGHT_ARROW     12
-#define SK_CTL_DELETE          13
-#define SK_BACK_TAB            14
-#define SK_LITERAL             40
-
-/* Data for a section of a compiled .info file. */
-struct sect
-  {
-    unsigned int cur;
-    unsigned char data[INFOKEY_MAX_SECTIONLEN];
-  };
-

Modified: trunk/info/infomap.c
===================================================================
--- trunk/info/infomap.c        2014-06-20 17:27:15 UTC (rev 5680)
+++ trunk/info/infomap.c        2014-06-28 15:54:00 UTC (rev 5681)
@@ -27,8 +27,7 @@
 #include "infokey.h"
 #include "variables.h"
 
-static int keymap_bind_keyseq (Keymap map, const char *keyseq,
-    KEYMAP_ENTRY *keyentry);
+void keymap_bind_keyseq (Keymap map, int *keyseq, KEYMAP_ENTRY *keyentry);
 
 /* Return a new keymap which has all the uppercase letters mapped to run
    the function info_do_lowercase_version (). */
@@ -38,22 +37,14 @@
   int i;
   Keymap keymap;
 
-  keymap = (Keymap)xmalloc (256 * sizeof (KEYMAP_ENTRY));
+  keymap = (Keymap)xmalloc (KEYMAP_SIZE * sizeof (KEYMAP_ENTRY));
 
-  for (i = 0; i < 256; i++)
+  for (i = 0; i < KEYMAP_SIZE; i++)
     {
       keymap[i].type = ISFUNC;
       keymap[i].function = NULL;
     }
 
-  for (i = 'A'; i < ('Z' + 1); i++)
-    {
-      keymap[i].type = ISFUNC;
-      keymap[Meta(i)].type = ISFUNC;
-      keymap[Meta(i)].function =
-      keymap[i].function = InfoCmd (info_do_lowercase_version);
-    }
-
   return keymap;
 }
 
@@ -68,11 +59,11 @@
     return NULL;
   for (k = map[c].function->keys; k; k = k->next)
     {
-      const unsigned char *p;
+      int *p;
       Keymap m = rootmap;
       if (k->map != rootmap)
         continue;
-      for (p = (unsigned char *) k->keyseq; *p && m[*p].type == ISKMAP; p++)
+      for (p = k->keyseq; *p && m[*p].type == ISKMAP; p++)
         m = (Keymap)m[*p].function;
       if (*p != c || p[1])
         continue;
@@ -84,10 +75,10 @@
 }
 
 static void
-add_function_keyseq (InfoCommand *function,
-    const char *keyseq, Keymap rootmap)
+add_function_keyseq (InfoCommand *function, int *keyseq, Keymap rootmap)
 {
   FUNCTION_KEYSEQ *ks;
+  int len;
 
   if (function == NULL ||
       function == InfoCmd (info_do_lowercase_version) ||
@@ -96,13 +87,14 @@
   ks = xmalloc  (sizeof (FUNCTION_KEYSEQ));
   ks->next = function->keys;
   ks->map = rootmap;
-  ks->keyseq = xstrdup (keyseq);
+  for (len = 0; keyseq[len]; len++);
+  ks->keyseq = xmalloc ((len + 1) * sizeof (int));
+  memcpy (ks->keyseq, keyseq, (len + 1) * sizeof (int));
   function->keys = ks;
 }
 
 static void
-remove_function_keyseq (InfoCommand *function,
-    const char *keyseq, Keymap rootmap)
+remove_function_keyseq (InfoCommand *function, int *keyseq, Keymap rootmap)
 {
 
   FUNCTION_KEYSEQ *k, *kp;
@@ -112,8 +104,18 @@
       function == InfoCmd (ea_insert))
     return;
   for (kp = NULL, k = function->keys; k; kp = k, k = k->next)
-    if (k->map == rootmap && strcmp (k->keyseq, keyseq) == 0)
-      break;
+    if (k->map == rootmap)
+      {
+        int i = 0;
+        while (k->keyseq[i] && keyseq[i])
+          {
+            if (k->keyseq[i] != keyseq[i])
+              break;
+            i++;
+          }
+        if (!k->keyseq[i] && !keyseq[i])
+          break; /* Sequences are equal. */
+      }
   if (!k)
     abort ();
   if (kp)
@@ -122,41 +124,8 @@
     function->keys = k->next;
 }
 
-/* Return a new keymap which is a copy of MAP. */
-Keymap
-keymap_copy_keymap (Keymap map, Keymap rootmap, Keymap newroot)
-{
-  int i;
-  Keymap keymap;
-  FUNCTION_KEYSEQ *ks;
-
-  keymap = keymap_make_keymap ();
-  if (!newroot)
-    newroot = keymap;
-
-  for (i = 0; i < 256; i++)
-    {
-      keymap[i].type = map[i].type;
-      switch (map[i].type)
-        {
-        case ISFUNC:
-          keymap[i].function = map[i].function;
-          ks = find_function_keyseq (map, i, rootmap);
-          if (ks)
-            add_function_keyseq (map[i].function, ks->keyseq, newroot);
-          break;
-        case ISKMAP:
-          keymap[i].function =
-           (InfoCommand *)keymap_copy_keymap ((Keymap)map[i].function,
-                                              rootmap, NULL);
-          break;
-        }
-    }
-  return keymap;
-}
-
 /* Free the keymap and its descendants. */
-void
+static void
 keymap_discard_keymap (Keymap map, Keymap rootmap)
 {
   int i;
@@ -166,7 +135,7 @@
   if (!rootmap)
     rootmap = map;
 
-  for (i = 0; i < 256; i++)
+  for (i = 0; i < KEYMAP_SIZE; i++)
     {
       FUNCTION_KEYSEQ *ks;
       switch (map[i].type)
@@ -186,16 +155,16 @@
   free (map);
 }
 
-/* Conditionally bind key sequence. */
-static int
-keymap_bind_keyseq (Keymap map,
-                   const char *keyseq, KEYMAP_ENTRY *keyentry)
+/* Bind key sequence.  Don't override already bound key sequences. */
+void
+keymap_bind_keyseq (Keymap map, int *keyseq, KEYMAP_ENTRY *keyentry)
 {
   Keymap m = map;
-  const unsigned char *s = (unsigned char *) keyseq;
+  int *s = keyseq;
   int c;
 
-  if (s == NULL || *s == '\0') return 0;
+  if (!s || *s == 0)
+    return;
 
   while ((c = *s++) != '\0')
     {
@@ -203,26 +172,27 @@
       switch (m[c].type)
         {
         case ISFUNC:
+          if (m[c].function)
+            return; /* There is a function here already. */
+          /*
           ks = find_function_keyseq (m, c, map);
           if (ks)
             remove_function_keyseq (m[c].function, ks->keyseq, map);
+          */
 
           if (*s != '\0')
             {
               m[c].type = ISKMAP;
-              /* Here we are casting the Keymap pointer returned from
-                 keymap_make_keymap to an InfoCommand pointer.  Ugh.
-                 This makes the `function' structure garbage
-                 if it's actually interpreted as an InfoCommand.
-                 Should really be using a union, and taking steps to
-                 avoid the possible error.  */
               m[c].function = (InfoCommand *)keymap_make_keymap ();
             }
           break;
 
         case ISKMAP:
           if (*s == '\0')
-            keymap_discard_keymap ((Keymap)m[c].function, map);
+            return; /* The key sequence we were asked to bind is an initial
+                       subsequence of an already-bound sequence. */
+            /* keymap_discard_keymap ((Keymap)m[c].function, map); */
+
           break;
         }
       if (*s != '\0')
@@ -236,7 +206,7 @@
         }
     }
 
-  return 1;
+  return;
 }
 
 
@@ -255,7 +225,7 @@
 
 #define NUL     '\0'
 
-static unsigned char default_emacs_like_info_keys[] =
+static int default_emacs_like_info_keys[] =
 {
   0,      /* suppress-default-keybindings flag */
   TAB, NUL,                       A_info_move_to_next_xref,
@@ -312,50 +282,28 @@
   'S', NUL,                       A_info_search_case_sensitively,
   't', NUL,                       A_info_top_node,
   'u', NUL,                       A_info_up_node,
-  ESC, '0', NUL,                  A_info_add_digit_to_numeric_arg,
-  ESC, '1', NUL,                  A_info_add_digit_to_numeric_arg,
-  ESC, '2', NUL,                  A_info_add_digit_to_numeric_arg,
-  ESC, '3', NUL,                  A_info_add_digit_to_numeric_arg,
-  ESC, '4', NUL,                  A_info_add_digit_to_numeric_arg,
-  ESC, '5', NUL,                  A_info_add_digit_to_numeric_arg,
-  ESC, '6', NUL,                  A_info_add_digit_to_numeric_arg,
-  ESC, '7', NUL,                  A_info_add_digit_to_numeric_arg,
-  ESC, '8', NUL,                  A_info_add_digit_to_numeric_arg,
-  ESC, '9', NUL,                  A_info_add_digit_to_numeric_arg,
-  ESC, '-', NUL,                  A_info_add_digit_to_numeric_arg,
-  ESC, CONTROL('f'), NUL,         A_info_show_footnotes,
-  ESC, CONTROL('g'), NUL,         A_info_abort_key,
-  ESC, TAB, NUL,                  A_info_move_to_prev_xref,
-  ESC, CONTROL('v'), NUL,         A_info_scroll_other_window,
-  ESC, '<', NUL,                  A_info_beginning_of_node,
-  ESC, '>', NUL,                  A_info_end_of_node,
-  ESC, 'b', NUL,                  A_info_backward_word,
-  ESC, 'f', NUL,                  A_info_forward_word,
-  ESC, 'r', NUL,                  A_info_move_to_window_line,
-  ESC, 'v', NUL,                  A_info_scroll_backward_page_only,
-  Meta('0'), NUL,                 A_info_add_digit_to_numeric_arg,
-  Meta('1'), NUL,                 A_info_add_digit_to_numeric_arg,
-  Meta('2'), NUL,                 A_info_add_digit_to_numeric_arg,
-  Meta('3'), NUL,                 A_info_add_digit_to_numeric_arg,
-  Meta('4'), NUL,                 A_info_add_digit_to_numeric_arg,
-  Meta('5'), NUL,                 A_info_add_digit_to_numeric_arg,
-  Meta('6'), NUL,                 A_info_add_digit_to_numeric_arg,
-  Meta('7'), NUL,                 A_info_add_digit_to_numeric_arg,
-  Meta('8'), NUL,                 A_info_add_digit_to_numeric_arg,
-  Meta('9'), NUL,                 A_info_add_digit_to_numeric_arg,
-  Meta('-'), NUL,                 A_info_add_digit_to_numeric_arg,
-  Meta(CONTROL('f')), NUL,        A_info_show_footnotes,
-  Meta(CONTROL('g')), NUL,        A_info_abort_key,
-  Meta(TAB), NUL,                 A_info_move_to_prev_xref,
-  Meta(CONTROL('v')), NUL,        A_info_scroll_other_window,
-  Meta('<'), NUL,                 A_info_beginning_of_node,
-  Meta('>'), NUL,                 A_info_end_of_node,
-  Meta('b'), NUL,                 A_info_backward_word,
-  Meta('f'), NUL,                 A_info_forward_word,
-  Meta('r'), NUL,                 A_info_move_to_window_line,
-  Meta('v'), NUL,                 A_info_scroll_backward_page_only,
-  ESC, 'x', NUL,                  A_info_execute_command,
-  Meta('x'), NUL,                 A_info_execute_command,
+  KEYMAP_META('0'), NUL,                 A_info_add_digit_to_numeric_arg,
+  KEYMAP_META('1'), NUL,                 A_info_add_digit_to_numeric_arg,
+  KEYMAP_META('2'), NUL,                 A_info_add_digit_to_numeric_arg,
+  KEYMAP_META('3'), NUL,                 A_info_add_digit_to_numeric_arg,
+  KEYMAP_META('4'), NUL,                 A_info_add_digit_to_numeric_arg,
+  KEYMAP_META('5'), NUL,                 A_info_add_digit_to_numeric_arg,
+  KEYMAP_META('6'), NUL,                 A_info_add_digit_to_numeric_arg,
+  KEYMAP_META('7'), NUL,                 A_info_add_digit_to_numeric_arg,
+  KEYMAP_META('8'), NUL,                 A_info_add_digit_to_numeric_arg,
+  KEYMAP_META('9'), NUL,                 A_info_add_digit_to_numeric_arg,
+  KEYMAP_META('-'), NUL,                 A_info_add_digit_to_numeric_arg,
+  KEYMAP_META(CONTROL('f')), NUL,        A_info_show_footnotes,
+  KEYMAP_META(CONTROL('g')), NUL,        A_info_abort_key,
+  KEYMAP_META(TAB), NUL,                 A_info_move_to_prev_xref,
+  KEYMAP_META(CONTROL('v')), NUL,        A_info_scroll_other_window,
+  KEYMAP_META('<'), NUL,                 A_info_beginning_of_node,
+  KEYMAP_META('>'), NUL,                 A_info_end_of_node,
+  KEYMAP_META('b'), NUL,                 A_info_backward_word,
+  KEYMAP_META('f'), NUL,                 A_info_forward_word,
+  KEYMAP_META('r'), NUL,                 A_info_move_to_window_line,
+  KEYMAP_META('v'), NUL,                 A_info_scroll_backward_page_only,
+  KEYMAP_META('x'), NUL,                 A_info_execute_command,
 
   CONTROL('x'), CONTROL('b'), NUL,        A_list_visited_nodes,
   CONTROL('x'), CONTROL('c'), NUL,        A_info_quit,
@@ -373,42 +321,22 @@
   CONTROL('x'), 'o', NUL,         A_info_next_window,
   CONTROL('x'), 't', NUL,         A_info_tile_windows,
   CONTROL('x'), 'w', NUL,         A_info_toggle_wrap,
-  
-/*      Arrow key bindings for info keymaps.  It seems that some
-        terminals do not match their termcap entries, so it's best to just
-        define everything with both of the usual prefixes.  */
 
-  SK_ESCAPE, SK_PAGE_UP, NUL,             A_info_scroll_backward,
-  SK_ESCAPE, SK_PAGE_DOWN, NUL,           A_info_scroll_forward,
-  '\033', 'O', 'A', NUL,                  A_info_prev_line,
-  '\033', '[', 'A', NUL,                  A_info_prev_line,
-  '\033', 'O', 'B', NUL,                  A_info_next_line,
-  '\033', '[', 'B', NUL,                  A_info_next_line,
-  SK_ESCAPE, SK_RIGHT_ARROW, NUL,         A_info_forward_char,
-  '\033', 'O', 'C', NUL,                  A_info_forward_char,
-  '\033', '[', 'C', NUL,                  A_info_forward_char,
-  SK_ESCAPE, SK_LEFT_ARROW, NUL,          A_info_backward_char,
-  '\033', 'O', 'D', NUL,                  A_info_backward_char,
-  '\033', '[', 'D', NUL,                  A_info_backward_char,
-  SK_ESCAPE, SK_HOME, NUL,                A_info_beginning_of_node,
-  SK_ESCAPE, SK_END, NUL,                 A_info_end_of_node,
-  SK_ESCAPE, SK_DELETE, NUL,              A_info_scroll_backward,
+  KEY_PAGE_UP, NUL,             A_info_scroll_backward,
+  KEY_PAGE_DOWN, NUL,           A_info_scroll_forward,
+  KEY_RIGHT_ARROW, NUL,         A_info_forward_char,
+  KEY_LEFT_ARROW, NUL,          A_info_backward_char,
+  KEY_HOME, NUL,                A_info_beginning_of_node,
+  KEY_END, NUL,                 A_info_end_of_node,
+  KEY_DELETE, NUL,              A_info_scroll_backward,
   
-  ESC, SK_ESCAPE, SK_PAGE_UP, NUL,        A_info_scroll_other_window_backward,
-  ESC, SK_ESCAPE, SK_PAGE_DOWN, NUL,      A_info_scroll_other_window,
-  ESC, SK_ESCAPE, SK_UP_ARROW, NUL,       A_info_prev_line,
-  ESC, '\033', 'O', 'A', NUL,             A_info_prev_line,
-  ESC, '\033', '[', 'A', NUL,             A_info_prev_line,
-  ESC, SK_ESCAPE, SK_DOWN_ARROW, NUL,     A_info_next_line,
-  ESC, '\033', 'O', 'B', NUL,             A_info_next_line,
-  ESC, '\033', '[', 'B', NUL,             A_info_next_line,
-  ESC, SK_ESCAPE, SK_RIGHT_ARROW, NUL,    A_info_forward_word,
-  ESC, '\033', 'O', 'C', NUL,             A_info_forward_word,
-  ESC, '\033', '[', 'C', NUL,             A_info_forward_word,
-  ESC, SK_ESCAPE, SK_LEFT_ARROW, NUL,     A_info_backward_word,
-  ESC, '\033', 'O', 'D', NUL,             A_info_backward_word,
-  ESC, '\033', '[', 'D', NUL,             A_info_backward_word,
-  SK_ESCAPE, SK_BACK_TAB, NUL,            A_info_move_to_prev_xref,
+  ESC, KEY_PAGE_UP, NUL,        A_info_scroll_other_window_backward,
+  ESC, KEY_PAGE_DOWN, NUL,      A_info_scroll_other_window,
+  ESC, KEY_UP_ARROW, NUL,       A_info_prev_line,
+  ESC, KEY_DOWN_ARROW, NUL,     A_info_next_line,
+  ESC, KEY_RIGHT_ARROW, NUL,    A_info_forward_word,
+  ESC, KEY_LEFT_ARROW, NUL,     A_info_backward_word,
+  KEY_BACK_TAB, NUL,            A_info_move_to_prev_xref,
   
   /* We want help to report q, not C-x C-c, etc.  */
   'q', NUL,                       A_info_quit,
@@ -418,63 +346,43 @@
   '{', NUL,                       A_info_search_previous,
   '}', NUL,                       A_info_search_next,
   CONTROL('g'), NUL,              A_info_abort_key,
-  SK_ESCAPE, SK_UP_ARROW, NUL,    A_info_prev_line,
-  SK_ESCAPE, SK_DOWN_ARROW, NUL,  A_info_next_line,
+  KEY_UP_ARROW, NUL,    A_info_prev_line,
+  KEY_DOWN_ARROW, NUL,  A_info_next_line,
 };
 
 
-static unsigned char default_emacs_like_ea_keys[] =
+static int default_emacs_like_ea_keys[] =
 {
   0,      /* suppress-default-keybindings flag */
-  ESC, '0', NUL,                  A_info_add_digit_to_numeric_arg,
-  ESC, '1', NUL,                  A_info_add_digit_to_numeric_arg,
-  ESC, '2', NUL,                  A_info_add_digit_to_numeric_arg,
-  ESC, '3', NUL,                  A_info_add_digit_to_numeric_arg,
-  ESC, '4', NUL,                  A_info_add_digit_to_numeric_arg,
-  ESC, '5', NUL,                  A_info_add_digit_to_numeric_arg,
-  ESC, '6', NUL,                  A_info_add_digit_to_numeric_arg,
-  ESC, '7', NUL,                  A_info_add_digit_to_numeric_arg,
-  ESC, '8', NUL,                  A_info_add_digit_to_numeric_arg,
-  ESC, '9', NUL,                  A_info_add_digit_to_numeric_arg,
-  ESC, '-', NUL,                  A_info_add_digit_to_numeric_arg,
-  Meta('0'), NUL,                 A_info_add_digit_to_numeric_arg,
-  Meta('1'), NUL,                 A_info_add_digit_to_numeric_arg,
-  Meta('2'), NUL,                 A_info_add_digit_to_numeric_arg,
-  Meta('3'), NUL,                 A_info_add_digit_to_numeric_arg,
-  Meta('4'), NUL,                 A_info_add_digit_to_numeric_arg,
-  Meta('5'), NUL,                 A_info_add_digit_to_numeric_arg,
-  Meta('6'), NUL,                 A_info_add_digit_to_numeric_arg,
-  Meta('7'), NUL,                 A_info_add_digit_to_numeric_arg,
-  Meta('8'), NUL,                 A_info_add_digit_to_numeric_arg,
-  Meta('9'), NUL,                 A_info_add_digit_to_numeric_arg,
-  Meta('-'), NUL,                 A_info_add_digit_to_numeric_arg,
-  ESC, CONTROL('g'), NUL,         A_ea_abort,
-  ESC, CONTROL('v'), NUL,         A_ea_scroll_completions_window,
-  ESC, 'b', NUL,                  A_ea_backward_word,
-  ESC, 'd', NUL,                  A_ea_kill_word,
-  ESC, 'f', NUL,                  A_ea_forward_word,
-  ESC, 'y', NUL,                  A_ea_yank_pop,
-  ESC, '?', NUL,                  A_ea_possible_completions,
-  ESC, TAB, NUL,                  A_ea_tab_insert,
-  ESC, DEL, NUL,                  A_ea_backward_kill_word,
-  Meta(CONTROL('g')), NUL,        A_ea_abort,
-  Meta(CONTROL('v')), NUL,        A_ea_scroll_completions_window,
-  Meta('b'), NUL,                 A_ea_backward_word,
-  Meta('d'), NUL,                 A_ea_kill_word,
-  Meta('f'), NUL,                 A_ea_forward_word,
-  Meta('y'), NUL,                 A_ea_yank_pop,
-  Meta('?'), NUL,                 A_ea_possible_completions,
-  Meta(TAB), NUL,                 A_ea_tab_insert,
-  Meta(DEL), NUL,                 A_ea_backward_kill_word,
+  KEYMAP_META('0'), NUL,                 A_info_add_digit_to_numeric_arg,
+  KEYMAP_META('1'), NUL,                 A_info_add_digit_to_numeric_arg,
+  KEYMAP_META('2'), NUL,                 A_info_add_digit_to_numeric_arg,
+  KEYMAP_META('3'), NUL,                 A_info_add_digit_to_numeric_arg,
+  KEYMAP_META('4'), NUL,                 A_info_add_digit_to_numeric_arg,
+  KEYMAP_META('5'), NUL,                 A_info_add_digit_to_numeric_arg,
+  KEYMAP_META('6'), NUL,                 A_info_add_digit_to_numeric_arg,
+  KEYMAP_META('7'), NUL,                 A_info_add_digit_to_numeric_arg,
+  KEYMAP_META('8'), NUL,                 A_info_add_digit_to_numeric_arg,
+  KEYMAP_META('9'), NUL,                 A_info_add_digit_to_numeric_arg,
+  KEYMAP_META('-'), NUL,                 A_info_add_digit_to_numeric_arg,
+  KEYMAP_META(CONTROL('g')), NUL,        A_ea_abort,
+  KEYMAP_META(CONTROL('v')), NUL,        A_ea_scroll_completions_window,
+  KEYMAP_META('b'), NUL,                 A_ea_backward_word,
+  KEYMAP_META('d'), NUL,                 A_ea_kill_word,
+  KEYMAP_META('f'), NUL,                 A_ea_forward_word,
+  KEYMAP_META('y'), NUL,                 A_ea_yank_pop,
+  KEYMAP_META('?'), NUL,                 A_ea_possible_completions,
+  KEYMAP_META(TAB), NUL,                 A_ea_tab_insert,
+  KEYMAP_META(DEL), NUL,                 A_ea_backward_kill_word,
   CONTROL('a'), NUL,              A_ea_beg_of_line,
   CONTROL('b'), NUL,              A_ea_backward,
   CONTROL('d'), NUL,              A_ea_delete,
   CONTROL('e'), NUL,              A_ea_end_of_line,
   CONTROL('f'), NUL,              A_ea_forward,
   CONTROL('g'), NUL,              A_ea_abort,
+  ESC, NUL,                       A_ea_abort,
   CONTROL('h'), NUL,              A_ea_rubout,
-/*      CONTROL('k') */
-  SK_ESCAPE, SK_LITERAL, NUL,     A_ea_kill_line,
+  CONTROL('k'), NUL,              A_ea_kill_line,
   CONTROL('l'), NUL,              A_info_redraw_display,
   CONTROL('q'), NUL,              A_ea_quoted_insert,
   CONTROL('t'), NUL,              A_ea_transpose_chars,
@@ -495,35 +403,23 @@
   CONTROL('x'), 'o', NUL,         A_info_next_window,
   CONTROL('x'), DEL, NUL,         A_ea_backward_kill_line,
 
-/*      Arrow key bindings for echo area keymaps.  It seems that some
-        terminals do not match their termcap entries, so it's best to just
-        define everything with both of the usual prefixes.  */
-
-  SK_ESCAPE, SK_RIGHT_ARROW, NUL,         A_ea_forward,
-  '\033', 'O', 'C', NUL,                  A_ea_forward,
-  '\033', '[', 'C', NUL,                  A_ea_forward,
-  SK_ESCAPE, SK_LEFT_ARROW, NUL,          A_ea_backward,
-  '\033', 'O', 'D', NUL,                  A_ea_backward,
-  '\033', '[', 'D', NUL,                  A_ea_backward,
-  ESC, SK_ESCAPE, SK_RIGHT_ARROW, NUL,    A_ea_forward_word,
-  ESC, '\033', 'O', 'C', NUL,             A_ea_forward_word,
-  ESC, '\033', '[', 'C', NUL,             A_ea_forward_word,
-  ESC, SK_ESCAPE, SK_LEFT_ARROW, NUL,     A_ea_backward_word,
-  ESC, '\033', 'O', 'D', NUL,             A_ea_backward_word,
-  ESC, '\033', '[', 'D', NUL,             A_ea_backward_word,
+  KEY_RIGHT_ARROW, NUL,           A_ea_forward,
+  KEY_LEFT_ARROW, NUL,            A_ea_backward,
+  ESC, KEY_RIGHT_ARROW, NUL,   A_ea_forward_word,
+  ESC, KEY_LEFT_ARROW, NUL,    A_ea_backward_word,
 #ifdef __MSDOS__
-  SK_ESCAPE, SK_DELETE, NUL,              A_ea_delete,
+  KEY_DELETE, NUL,               A_ea_delete,
 #else
-  SK_ESCAPE, SK_DELETE, NUL,              A_ea_rubout,
+  KEY_DELETE, NUL,               A_ea_rubout,
 #endif
-  SK_ESCAPE, SK_HOME, NUL,                A_ea_beg_of_line,
-  SK_ESCAPE, SK_END, NUL,                 A_ea_end_of_line,
-  ESC, SK_ESCAPE, SK_DELETE, NUL,         A_ea_backward_kill_word,
-  CONTROL('x'), SK_ESCAPE, SK_DELETE, NUL,A_ea_backward_kill_line,
+  KEY_HOME, NUL,                 A_ea_beg_of_line,
+  KEY_END, NUL,                  A_ea_end_of_line,
+  ESC, KEY_DELETE, NUL,  A_ea_backward_kill_word,
+  CONTROL('x'), KEY_DELETE, NUL, A_ea_backward_kill_line,
 };
 
 
-static unsigned char default_vi_like_info_keys[] =
+static int default_vi_like_info_keys[] =
 {
   0,      /* suppress-default-keybindings flag */
   '0', NUL,                       A_info_add_digit_to_numeric_arg,
@@ -558,26 +454,16 @@
   CONTROL('y'), NUL,              A_info_up_line,
   ',', NUL,                       A_info_next_index_match,
   '/', NUL,                       A_info_search,
-  ESC, '0', NUL,                  A_info_last_menu_item,
-  ESC, '1', NUL,                  A_info_menu_digit,
-  ESC, '2', NUL,                  A_info_menu_digit,
-  ESC, '3', NUL,                  A_info_menu_digit,
-  ESC, '4', NUL,                  A_info_menu_digit,
-  ESC, '5', NUL,                  A_info_menu_digit,
-  ESC, '6', NUL,                  A_info_menu_digit,
-  ESC, '7', NUL,                  A_info_menu_digit,
-  ESC, '8', NUL,                  A_info_menu_digit,
-  ESC, '9', NUL,                  A_info_menu_digit,
-  Meta('0'), NUL,                 A_info_last_menu_item,
-  Meta('1'), NUL,                 A_info_menu_digit,
-  Meta('2'), NUL,                 A_info_menu_digit,
-  Meta('3'), NUL,                 A_info_menu_digit,
-  Meta('4'), NUL,                 A_info_menu_digit,
-  Meta('5'), NUL,                 A_info_menu_digit,
-  Meta('6'), NUL,                 A_info_menu_digit,
-  Meta('7'), NUL,                 A_info_menu_digit,
-  Meta('8'), NUL,                 A_info_menu_digit,
-  Meta('9'), NUL,                 A_info_menu_digit,
+  KEYMAP_META('0'), NUL,                 A_info_last_menu_item,
+  KEYMAP_META('1'), NUL,                 A_info_menu_digit,
+  KEYMAP_META('2'), NUL,                 A_info_menu_digit,
+  KEYMAP_META('3'), NUL,                 A_info_menu_digit,
+  KEYMAP_META('4'), NUL,                 A_info_menu_digit,
+  KEYMAP_META('5'), NUL,                 A_info_menu_digit,
+  KEYMAP_META('6'), NUL,                 A_info_menu_digit,
+  KEYMAP_META('7'), NUL,                 A_info_menu_digit,
+  KEYMAP_META('8'), NUL,                 A_info_menu_digit,
+  KEYMAP_META('9'), NUL,                 A_info_menu_digit,
   '<', NUL,                       A_info_first_node,
   '>', NUL,                       A_info_last_node,
   '?', NUL,                       A_info_search_backward,
@@ -643,7 +529,7 @@
   ESC, 't', NUL,                  A_info_top_node,
   ESC, 'v', NUL,                  A_info_scroll_backward_page_only,
   ESC, 'x', NUL,                  A_info_execute_command,
-  Meta('x'), NUL,                 A_info_execute_command,
+  KEYMAP_META('x'), NUL,                 A_info_execute_command,
   ESC, DEL, NUL,                  A_info_scroll_other_window_backward,
   CONTROL('x'), CONTROL('b'), NUL,        A_list_visited_nodes,
   CONTROL('x'), CONTROL('c'), NUL,        A_info_quit,
@@ -669,41 +555,21 @@
   CONTROL('x'), 'w', NUL,         A_info_toggle_wrap,
   CONTROL('x'), ',', NUL,         A_info_next_index_match,
 
-/*      Arrow key bindings for info keymaps.  It seems that some
-        terminals do not match their termcap entries, so it's best to just
-        define everything with both of the usual prefixes.  */
+  KEY_PAGE_UP, NUL,             A_info_scroll_backward,
+  KEY_PAGE_DOWN, NUL,           A_info_scroll_forward,
+  KEY_RIGHT_ARROW, NUL,         A_info_scroll_forward_page_only,
+  KEY_LEFT_ARROW, NUL,          A_info_scroll_backward_page_only,
+  KEY_HOME, NUL,                A_info_beginning_of_node,
+  KEY_END, NUL,                 A_info_end_of_node,
+  ESC, KEY_PAGE_DOWN, NUL,      A_info_scroll_other_window,
+  ESC, KEY_PAGE_UP, NUL,        A_info_scroll_other_window_backward,
+  ESC, KEY_DELETE, NUL,         A_info_scroll_other_window_backward,
+  ESC, KEY_UP_ARROW, NUL,       A_info_prev_node,
+  ESC, KEY_DOWN_ARROW, NUL,     A_info_next_node,
+  ESC, KEY_RIGHT_ARROW, NUL,    A_info_xref_item,
+  ESC, KEY_LEFT_ARROW, NUL,     A_info_beginning_of_node,
+  CONTROL('x'), KEY_DELETE, NUL,A_ea_backward_kill_line,
   
-  SK_ESCAPE, SK_PAGE_UP, NUL,             A_info_scroll_backward,
-  SK_ESCAPE, SK_PAGE_DOWN, NUL,           A_info_scroll_forward,
-  '\033', 'O', 'A', NUL,                  A_info_up_line,
-  '\033', '[', 'A', NUL,                  A_info_up_line,
-  '\033', 'O', 'B', NUL,                  A_info_down_line,
-  '\033', '[', 'B', NUL,                  A_info_down_line,
-  SK_ESCAPE, SK_RIGHT_ARROW, NUL,         A_info_scroll_forward_page_only,
-  '\033', 'O', 'C', NUL,                  A_info_scroll_forward_page_only,
-  '\033', '[', 'C', NUL,                  A_info_scroll_forward_page_only,
-  SK_ESCAPE, SK_LEFT_ARROW, NUL,          A_info_scroll_backward_page_only,
-  '\033', 'O', 'D', NUL,                  A_info_scroll_backward_page_only,
-  '\033', '[', 'D', NUL,                  A_info_scroll_backward_page_only,
-  SK_ESCAPE, SK_HOME, NUL,                A_info_beginning_of_node,
-  SK_ESCAPE, SK_END, NUL,                 A_info_end_of_node,
-  ESC, SK_ESCAPE, SK_PAGE_DOWN, NUL,      A_info_scroll_other_window,
-  ESC, SK_ESCAPE, SK_PAGE_UP, NUL,        A_info_scroll_other_window_backward,
-  ESC, SK_ESCAPE, SK_DELETE, NUL,         A_info_scroll_other_window_backward,
-  ESC, SK_ESCAPE, SK_UP_ARROW, NUL,       A_info_prev_node,
-  ESC, '\033', 'O', 'A', NUL,             A_info_prev_node,
-  ESC, '\033', '[', 'A', NUL,             A_info_prev_node,
-  ESC, SK_ESCAPE, SK_DOWN_ARROW, NUL,     A_info_next_node,
-  ESC, '\033', 'O', 'B', NUL,             A_info_next_node,
-  ESC, '\033', '[', 'B', NUL,             A_info_next_node,
-  ESC, SK_ESCAPE, SK_RIGHT_ARROW, NUL,    A_info_xref_item,
-  ESC, '\033', 'O', 'C', NUL,             A_info_xref_item,
-  ESC, '\033', '[', 'C', NUL,             A_info_xref_item,
-  ESC, SK_ESCAPE, SK_LEFT_ARROW, NUL,     A_info_beginning_of_node,
-  ESC, '\033', 'O', 'D', NUL,             A_info_beginning_of_node,
-  ESC, '\033', '[', 'D', NUL,             A_info_beginning_of_node,
-  CONTROL('x'), SK_ESCAPE, SK_DELETE, NUL,A_ea_backward_kill_line,
-  
   /* We want help to report q, not C-x C-c, etc.  */
   'q', NUL,                       A_info_quit,
   'x', NUL,                       A_info_delete_window,
@@ -711,12 +577,12 @@
   DEL, NUL,                       A_info_scroll_backward,
   '{', NUL,                       A_info_search_previous,
   '}', NUL,                       A_info_search_next,
-  SK_ESCAPE, SK_UP_ARROW, NUL,    A_info_up_line,
-  SK_ESCAPE, SK_DOWN_ARROW, NUL,  A_info_down_line,
+  KEY_UP_ARROW, NUL,    A_info_up_line,
+  KEY_DOWN_ARROW, NUL,  A_info_down_line,
 };
 
 
-static unsigned char default_vi_like_ea_keys[] =
+static int default_vi_like_ea_keys[] =
 {
   0,      /* suppress-default-keybindings flag */
   ESC, '1', NUL,                  A_info_add_digit_to_numeric_arg,
@@ -729,50 +595,33 @@
   ESC, '8', NUL,                  A_info_add_digit_to_numeric_arg,
   ESC, '9', NUL,                  A_info_add_digit_to_numeric_arg,
   ESC, '-', NUL,                  A_info_add_digit_to_numeric_arg,
-  Meta('1'), NUL,                 A_info_add_digit_to_numeric_arg,
-  Meta('2'), NUL,                 A_info_add_digit_to_numeric_arg,
-  Meta('3'), NUL,                 A_info_add_digit_to_numeric_arg,
-  Meta('4'), NUL,                 A_info_add_digit_to_numeric_arg,
-  Meta('5'), NUL,                 A_info_add_digit_to_numeric_arg,
-  Meta('6'), NUL,                 A_info_add_digit_to_numeric_arg,
-  Meta('7'), NUL,                 A_info_add_digit_to_numeric_arg,
-  Meta('8'), NUL,                 A_info_add_digit_to_numeric_arg,
-  Meta('9'), NUL,                 A_info_add_digit_to_numeric_arg,
-  Meta('-'), NUL,                 A_info_add_digit_to_numeric_arg,
-  ESC, CONTROL('g'), NUL,         A_ea_abort,
-  ESC, CONTROL('h'), NUL,         A_ea_backward_kill_word,
-  ESC, CONTROL('v'), NUL,         A_ea_scroll_completions_window,
-  ESC, '0', NUL,                  A_ea_beg_of_line,
-  ESC, '$', NUL,                  A_ea_end_of_line,
-  ESC, 'b', NUL,                  A_ea_backward_word,
-  ESC, 'd', NUL,                  A_ea_kill_word,
-  ESC, 'f', NUL,                  A_ea_forward_word,
-  ESC, 'h', NUL,                  A_ea_forward,
-  ESC, 'l', NUL,                  A_ea_backward,
-  ESC, 'w', NUL,                  A_ea_forward_word,
-  ESC, 'x', NUL,                  A_ea_delete,
-  ESC, 'X', NUL,                  A_ea_kill_word,
-  ESC, 'y', NUL,                  A_ea_yank_pop,
-  ESC, '?', NUL,                  A_ea_possible_completions,
-  ESC, TAB, NUL,                  A_ea_tab_insert,
-  ESC, DEL, NUL,                  A_ea_kill_word,
-  Meta(CONTROL('g')), NUL,        A_ea_abort,
-  Meta(CONTROL('h')), NUL,        A_ea_backward_kill_word,
-  Meta(CONTROL('v')), NUL,        A_ea_scroll_completions_window,
-  Meta('0'), NUL,                 A_ea_beg_of_line,
-  Meta('$'), NUL,                 A_ea_end_of_line,
-  Meta('b'), NUL,                 A_ea_backward_word,
-  Meta('d'), NUL,                 A_ea_kill_word,
-  Meta('f'), NUL,                 A_ea_forward_word,
-  Meta('h'), NUL,                 A_ea_forward,
-  Meta('l'), NUL,                 A_ea_backward,
-  Meta('w'), NUL,                 A_ea_forward_word,
-  Meta('x'), NUL,                 A_ea_delete,
-  Meta('X'), NUL,                 A_ea_kill_word,
-  Meta('y'), NUL,                 A_ea_yank_pop,
-  Meta('?'), NUL,                 A_ea_possible_completions,
-  Meta(TAB), NUL,                 A_ea_tab_insert,
-  Meta(DEL), NUL,                 A_ea_kill_word,
+  KEYMAP_META('1'), NUL,                 A_info_add_digit_to_numeric_arg,
+  KEYMAP_META('2'), NUL,                 A_info_add_digit_to_numeric_arg,
+  KEYMAP_META('3'), NUL,                 A_info_add_digit_to_numeric_arg,
+  KEYMAP_META('4'), NUL,                 A_info_add_digit_to_numeric_arg,
+  KEYMAP_META('5'), NUL,                 A_info_add_digit_to_numeric_arg,
+  KEYMAP_META('6'), NUL,                 A_info_add_digit_to_numeric_arg,
+  KEYMAP_META('7'), NUL,                 A_info_add_digit_to_numeric_arg,
+  KEYMAP_META('8'), NUL,                 A_info_add_digit_to_numeric_arg,
+  KEYMAP_META('9'), NUL,                 A_info_add_digit_to_numeric_arg,
+  KEYMAP_META('-'), NUL,                 A_info_add_digit_to_numeric_arg,
+  KEYMAP_META(CONTROL('g')), NUL,        A_ea_abort,
+  KEYMAP_META(CONTROL('h')), NUL,        A_ea_backward_kill_word,
+  KEYMAP_META(CONTROL('v')), NUL,        A_ea_scroll_completions_window,
+  KEYMAP_META('0'), NUL,                 A_ea_beg_of_line,
+  KEYMAP_META('$'), NUL,                 A_ea_end_of_line,
+  KEYMAP_META('b'), NUL,                 A_ea_backward_word,
+  KEYMAP_META('d'), NUL,                 A_ea_kill_word,
+  KEYMAP_META('f'), NUL,                 A_ea_forward_word,
+  KEYMAP_META('h'), NUL,                 A_ea_forward,
+  KEYMAP_META('l'), NUL,                 A_ea_backward,
+  KEYMAP_META('w'), NUL,                 A_ea_forward_word,
+  KEYMAP_META('x'), NUL,                 A_ea_delete,
+  KEYMAP_META('X'), NUL,                 A_ea_kill_word,
+  KEYMAP_META('y'), NUL,                 A_ea_yank_pop,
+  KEYMAP_META('?'), NUL,                 A_ea_possible_completions,
+  KEYMAP_META(TAB), NUL,                 A_ea_tab_insert,
+  KEYMAP_META(DEL), NUL,                 A_ea_kill_word,
   CONTROL('a'), NUL,              A_ea_beg_of_line,
   CONTROL('b'), NUL,              A_ea_backward,
   CONTROL('d'), NUL,              A_ea_delete,
@@ -780,8 +629,7 @@
   CONTROL('f'), NUL,              A_ea_forward,
   CONTROL('g'), NUL,              A_ea_abort,
   CONTROL('h'), NUL,              A_ea_rubout,
-  /*      CONTROL('k') */
-  SK_ESCAPE, SK_LITERAL, NUL,     A_ea_kill_line,
+  CONTROL('k'), NUL,              A_ea_kill_line,
   CONTROL('l'), NUL,              A_info_redraw_display,
   CONTROL('q'), NUL,              A_ea_quoted_insert,
   CONTROL('t'), NUL,              A_ea_transpose_chars,
@@ -803,42 +651,25 @@
   CONTROL('x'), 'o', NUL,         A_info_next_window,
   CONTROL('x'), DEL, NUL,         A_ea_backward_kill_line,
   
-  /* Arrow key bindings for echo area keymaps.  It seems that some
-     terminals do not match their termcap entries, so it's best to just
-     define everything with both of the usual prefixes.  */
-
-  SK_ESCAPE, SK_RIGHT_ARROW, NUL,         A_ea_forward,
-  '\033', 'O', 'C', NUL,                  A_ea_forward,
-  '\033', '[', 'C', NUL,                  A_ea_forward,
-  SK_ESCAPE, SK_LEFT_ARROW, NUL,          A_ea_backward,
-  '\033', 'O', 'D', NUL,                  A_ea_backward,
-  '\033', '[', 'D', NUL,                  A_ea_backward,
-  SK_ESCAPE, SK_HOME, NUL,                A_ea_beg_of_line,
-  SK_ESCAPE, SK_END, NUL,                 A_ea_end_of_line,
+  KEY_RIGHT_ARROW, NUL,         A_ea_forward,
+  KEY_LEFT_ARROW, NUL,          A_ea_backward,
+  KEY_HOME, NUL,                A_ea_beg_of_line,
+  KEY_END, NUL,                 A_ea_end_of_line,
 #ifdef __MSDOS__
-  SK_ESCAPE, SK_DELETE, NUL,              A_ea_delete,
+  KEY_DELETE, NUL,              A_ea_delete,
 #else
-  SK_DELETE, SK_DELETE, NUL,              A_ea_rubout,
+  KEY_DELETE, NUL,              A_ea_rubout,
 #endif
-  ESC, SK_ESCAPE, SK_RIGHT_ARROW, NUL,    A_ea_forward_word,
-  ESC, '\033', 'O', 'C', NUL,             A_ea_forward_word,
-  ESC, '\033', '[', 'C', NUL,             A_ea_forward_word,
-  ESC, SK_ESCAPE, SK_LEFT_ARROW, NUL,     A_ea_backward_word,
-  ESC, '\033', 'O', 'D', NUL,             A_ea_backward_word,
-  ESC, '\033', '[', 'D', NUL,             A_ea_backward_word,
-  ESC, SK_ESCAPE, SK_DELETE, NUL,         A_ea_kill_word,
-  CONTROL('x'), SK_ESCAPE, SK_DELETE, NUL,A_ea_backward_kill_line,
+  ESC, KEY_RIGHT_ARROW, NUL,    A_ea_forward_word,
+  ESC, KEY_LEFT_ARROW, NUL,     A_ea_backward_word,
+  ESC, KEY_DELETE, NUL,         A_ea_kill_word,
+  CONTROL('x'), KEY_DELETE, NUL,A_ea_backward_kill_line,
 };
 
 
-/* Used to hold output data from compile(). */
-struct sect sections[2];
+/* Whether to suppress the default key bindings. */
+static int sup_info, sup_ea;
 
-static unsigned char *user_info_keys;
-static unsigned int user_info_keys_len;
-static unsigned char *user_ea_keys;
-static unsigned int user_ea_keys_len;
-
 /* Fetch the contents of the init file at INIT_FILE, or the standard
    infokey file "$HOME/.info".  Return non-zero on success. */
 static int
@@ -854,7 +685,7 @@
   int n;
 
   /* In infokey.c */
-  int compile (FILE *fp, const char *filename, struct sect *sections);
+  int compile (FILE *fp, const char *filename, int *, int *);
 
   /* Find and open file. */
   if (init_file)
@@ -882,87 +713,21 @@
       return 0;
     }
 
-  compile (inf, filename, sections);
-  user_info_keys = sections[0].data;
-  user_info_keys_len = sections[0].cur;
-  user_ea_keys = sections[1].data;
-  user_ea_keys_len = sections[1].cur;
+  compile (inf, filename, &sup_info, &sup_ea);
 
   free (filename);
   return 1;
 }
 
-/* Decode special key sequences from the infokey file.  Return zero
-   if the key sequence includes special keys which the terminal
-   doesn't define.
- */
-static int
-decode_keys (unsigned char *src, unsigned int slen,
-           unsigned char *dst, unsigned int dlen)
-{
-  unsigned char *s = src;
-  unsigned char *d = dst;
 
-#define To_dst(c) do { \
-    if ((unsigned int) (d - dst) < dlen) *d++ = (c);   \
-} while (0)
-
-  while ((unsigned int) (s - src) < slen)
-    {
-      unsigned char c = ISMETA (*s) ? UNMETA (*s) : *s;
-      
-      if (c == SK_ESCAPE)
-       {
-         char *t;
-         static char lit[] = { SK_ESCAPE, NUL };
-         
-         switch ((unsigned int) (s + 1 - src) < slen ? s[1] : '\0')
-           {
-           case SK_RIGHT_ARROW:    t = term_kr; break;
-           case SK_LEFT_ARROW:     t = term_kl; break;
-           case SK_UP_ARROW:       t = term_ku; break;
-           case SK_DOWN_ARROW:     t = term_kd; break;
-           case SK_PAGE_UP:        t = term_kP; break;
-           case SK_PAGE_DOWN:      t = term_kN; break;
-           case SK_HOME:           t = term_kh; break;
-           case SK_END:            t = term_ke; break;
-           case SK_DELETE:         t = term_kx; break;
-           case SK_INSERT:         t = term_ki; break;
-           case SK_BACK_TAB:       t = term_bt; break;
-           case SK_LITERAL:
-           default:                t = lit; break;
-           }
-         if (t == NULL)
-           return 0;
-         while (*t)
-           To_dst (ISMETA (*s) ? Meta (*t++) : *t++);
-         s += 2;
-       }
-      else
-       {
-         if (ISMETA (*s))
-           To_dst (Meta (*s++));
-         else
-           To_dst (*s++);
-       }
-    }
-  
-  To_dst ('\0');
-  
-  return 1;
-  
-#undef To_dst
-
-}
-
 /* Convert an infokey file section to keymap bindings.  Return false if
    the default bindings are to be suppressed.  */
 static int
-section_to_keymaps (Keymap map, unsigned char *table, unsigned int len)
+section_to_keymaps (Keymap map, int *table, unsigned int len)
 {
   int stop;
-  unsigned char *p;
-  unsigned char *seq = NULL;
+  int *p;
+  int *seq;
   unsigned int seqlen = 0;
   enum { getseq, gotseq, getaction } state = getseq;
   
@@ -991,22 +756,16 @@
        case getaction:
          {
            unsigned int action = *p;
-           unsigned char keyseq[256];
+           unsigned int keyseq[256];
            KEYMAP_ENTRY ke;
            
            state = getseq;
-           /* If decode_keys returns zero, it means that seq includes keys
-              which the terminal doesn't support, like PageDown.  In that
-              case, don't bind the key sequence.  */
-           if (decode_keys (seq, seqlen, keyseq, sizeof keyseq))
-             {
-               keyseq[sizeof keyseq - 1] = '\0';
-               ke.type = ISFUNC;
-               ke.function = action < A_NCOMMANDS ?
-                                   &function_doc_array[action]
-                                   : NULL;
-               keymap_bind_keyseq (map, (const char *) keyseq, &ke);
-             }
+
+            ke.type = ISFUNC;
+            ke.function = action < A_NCOMMANDS ?
+                                &function_doc_array[action]
+                                : NULL;
+            keymap_bind_keyseq (map, seq, &ke);
          }
          break;
        }
@@ -1021,7 +780,7 @@
 void
 read_init_file (char *init_file)
 {
-  static unsigned char *info_keys, *ea_keys; /* Pointers to keymap tables. */
+  int *info_keys, *ea_keys; /* Pointers to keymap tables. */
   long info_keys_len, ea_keys_len; /* Sizes of keymap tables. */
 
   int i;
@@ -1040,40 +799,49 @@
   if (!vi_keys_p)
     {
       info_keys = default_emacs_like_info_keys;
-      info_keys_len = sizeof (default_emacs_like_info_keys);
+      info_keys_len = sizeof (default_emacs_like_info_keys)/sizeof (int);
       ea_keys = default_emacs_like_ea_keys;
-      ea_keys_len = sizeof (default_emacs_like_ea_keys);
+      ea_keys_len = sizeof (default_emacs_like_ea_keys)/sizeof (int);
     }
   else
     {
       info_keys = default_vi_like_info_keys;
-      info_keys_len = sizeof (default_vi_like_info_keys);
+      info_keys_len = sizeof (default_vi_like_info_keys)/sizeof(int);
       ea_keys = default_vi_like_ea_keys;
-      ea_keys_len = sizeof (default_vi_like_ea_keys);
+      ea_keys_len = sizeof (default_vi_like_ea_keys)/sizeof(int);
     }
 
   /* Get user-defined keys and variables.  */
   if (fetch_user_maps (init_file))
     {
-      if (user_info_keys_len && user_info_keys[0])
+      if (sup_info)
         info_keys = 0; /* Suppress default bindings. */
-      if (user_ea_keys_len && user_ea_keys[0])
+      if (sup_ea)
         ea_keys = 0;
     }
 
   /* Apply the default bindings, unless the user says to suppress
-     them.  */
+     them. */
   if (info_keys)
     section_to_keymaps (info_keymap, info_keys, info_keys_len);
   if (ea_keys)
     section_to_keymaps (echo_area_keymap, ea_keys, ea_keys_len);
 
-  /* If the user specified custom bindings, apply them on top of the
-     default ones.  */
-  if (user_info_keys_len)
-    section_to_keymaps (info_keymap, user_info_keys, user_info_keys_len);
-  if (user_ea_keys_len)
-    section_to_keymaps (echo_area_keymap, user_ea_keys, user_ea_keys_len);
+  for (i = 'A'; i < ('Z' + 1); i++)
+    {
+      if (!info_keymap[i].function)
+        {
+          info_keymap[i].type = ISFUNC;
+          info_keymap[i].function = InfoCmd (info_do_lowercase_version);
+        }
+
+      if (info_keymap[KEYMAP_META(i)].function)
+        {
+          info_keymap[KEYMAP_META(i)].type = ISFUNC;
+          info_keymap[KEYMAP_META(i)].function
+            = InfoCmd (info_do_lowercase_version);
+        }
+    }
 }
 
 /* vim: set sw=2 cino={1s>2sn-s^-se-s: */

Modified: trunk/info/infomap.h
===================================================================
--- trunk/info/infomap.h        2014-06-20 17:27:15 UTC (rev 5680)
+++ trunk/info/infomap.h        2014-06-28 15:54:00 UTC (rev 5681)
@@ -44,37 +44,65 @@
 #define Control(c) ((toupper (c)) & (~control_character_bit))
 #define UnControl(c) (tolower ((c) | control_character_bit))
 
-/* A keymap contains one entry for each key in the ASCII set.
-   Each entry consists of a type and a pointer.
-   FUNCTION is the address of a function to run, or the
-   address of a keymap to indirect through.
-   TYPE says which kind of thing FUNCTION is. */
+/* Structure used to map sequences of bytes to recognized keys. */
+typedef struct bytemap_entry
+{
+  char type;
+  int key;
+  struct bytemap_entry *next;
+} BYTEMAP_ENTRY;
+
+#define BYTEMAP_NONE 0
+#define BYTEMAP_KEY 1
+#define BYTEMAP_MAP 2
+#define BYTEMAP_ESC 3
+
+extern BYTEMAP_ENTRY *byte_seq_to_key;
+
 typedef struct keymap_entry
 {
   char type;
-  InfoCommand *function;
+  InfoCommand *function;  /* The address of a function or another keymap. */
 } KEYMAP_ENTRY;
 
-typedef KEYMAP_ENTRY *Keymap;
-
 /* The values that TYPE can have in a keymap entry. */
 #define ISFUNC 0
 #define ISKMAP 1
 
+typedef KEYMAP_ENTRY *Keymap;
+
 extern Keymap info_keymap;
 extern Keymap echo_area_keymap;
 
+#define KEY_RIGHT_ARROW                256
+#define KEY_LEFT_ARROW         257
+#define KEY_UP_ARROW           258
+#define KEY_DOWN_ARROW         259
+#define KEY_PAGE_UP            260
+#define KEY_PAGE_DOWN          261
+#define KEY_HOME               262
+#define KEY_END                        263
+#define KEY_DELETE             264
+#define KEY_INSERT             265
+#define KEY_CTL_LEFT_ARROW     266
+#define KEY_CTL_RIGHT_ARROW    267
+#define KEY_CTL_DELETE         268
+#define KEY_BACK_TAB           269
+
+/* Add this to get the offset of the key binding with the meta key. */
+#define KEYMAP_META_BASE 270
+
+/* Number of entries in a Keymap: 256 entries for plain byte values plus
+   mappings for special keys.  The bindings for the key chords with meta
+   follow. */
+#define KEYMAP_SIZE (270 * 2)
+
+#define KEYMAP_META(k) ((k) < KEYMAP_META_BASE ? (k) + KEYMAP_META_BASE : (k))
+
 /* Return a new keymap which has all the uppercase letters mapped to run
    the function info_do_lowercase_version (). */
 extern Keymap keymap_make_keymap (void);
 
-/* Return a new keymap which is a copy of MAP. */
-extern Keymap keymap_copy_keymap (Keymap map, Keymap rootmap,
-    Keymap newroot);
-
-/* Free MAP and it's descendents. */
-extern void keymap_discard_keymap (Keymap map, Keymap rootmap);
-
 /* Read init file and initialize the info keymaps. */
 extern void read_init_file (char *init_file);
 

Modified: trunk/info/session.c
===================================================================
--- trunk/info/session.c        2014-06-20 17:27:15 UTC (rev 5680)
+++ trunk/info/session.c        2014-06-28 15:54:00 UTC (rev 5681)
@@ -167,7 +167,7 @@
 static void
 info_read_and_dispatch (void)
 {
-  unsigned char key;
+  int key;
 
   for (quit_info_immediately = 0; !quit_info_immediately; )
     {
@@ -178,7 +178,9 @@
       info_initialize_numeric_arg ();
 
       initialize_keyseq ();
-      key = info_get_input_char ();
+      key = get_input_key ();
+      if (key == -1)
+        continue;
 
       window_clear_echo_area ();
 
@@ -260,11 +262,13 @@
 /*                                                                  */
 /* **************************************************************** */
 
+static void info_gather_typeahead (int);
+
 /* Largest number of characters that we can read in advance. */
 #define MAX_INFO_INPUT_BUFFERING 512
 
-static int pop_index = 0;
-static int push_index = 0;
+static int pop_index = 0; /* Where to remove bytes from input buffer. */
+static int push_index = 0; /* Where to add bytes to input buffer. */
 static unsigned char info_input_buffer[MAX_INFO_INPUT_BUFFERING];
 
 /* Put a byte back into the input buffer. */
@@ -282,7 +286,7 @@
    Return the key in KEY.
    Result is non-zero if there was a key, or 0 if there wasn't. */
 static int
-info_get_key_from_typeahead (unsigned char *key)
+get_byte_from_input_buffer (unsigned char *key)
 {
   if (push_index == pop_index)
     return 0;
@@ -298,14 +302,14 @@
 int
 info_any_buffered_input_p (void)
 {
-  info_gather_typeahead ();
+  info_gather_typeahead (0);
   return push_index != pop_index;
 }
 
-/* If characters are available to be read, then read them and stuff them into
-   info_input_buffer.  Otherwise, do nothing. */
-void
-info_gather_typeahead (void)
+/* Read bytes and stuff them into info_input_buffer.  If WAIT is true, wait
+   for input; otherwise don't do anything if there is no input waiting. */
+static void
+info_gather_typeahead (int wait)
 {
   register int i = 0;
   int tty, space_avail;
@@ -315,6 +319,21 @@
   tty = fileno (info_input_stream);
   chars_avail = 0;
 
+  /* There may be characters left over from last time, in which case we don't
+     want to wait for another key to be pressed. */
+  if (wait && pop_index == push_index)
+    {
+      char c;
+      /* Wait until there is a byte waiting, and then stuff it into the input
+         buffer. */
+      if (read (tty, &c, 1) != 1)
+        return; /* Read error.  TODO: Return some kind of error code. */
+      info_input_buffer[push_index++] = c;
+      if (push_index >= MAX_INFO_INPUT_BUFFERING)
+        push_index = 0;
+      /* Continue to see if there are more bytes waiting. */
+    }
+
   /* Get the amount of space available in INFO_INPUT_BUFFER for new chars. */
   if (pop_index > push_index)
     space_avail = pop_index - push_index;
@@ -406,15 +425,16 @@
     }
 }
 
-/* How to read a single character. */
+/* Get a single byte from the input stream.  This is limited because it does
+   not process multi-byte sequences corresponding to keys. */
 unsigned char
-info_get_input_char (void)
+info_get_input_byte (void)
 {
   unsigned char keystroke;
 
-  info_gather_typeahead ();
+  info_gather_typeahead (1);
 
-  if (info_get_key_from_typeahead (&keystroke) == 0)
+  if (get_byte_from_input_buffer (&keystroke) == 0)
     {
       int rawkey;
       unsigned char c;
@@ -470,6 +490,123 @@
 
   return keystroke;
 }
+
+/* Return number representing a key that has been pressed, which is an index
+   into info_keymap and echo_area_keymap.  Return -1 if no key has been
+   pressed. */
+int
+get_input_key (void)
+{
+  BYTEMAP_ENTRY *b;
+  unsigned char c;
+  int esc_seen;
+  int pop_start;
+  unsigned char first;
+  info_gather_typeahead (1);
+
+  if (pop_index == push_index)
+    return -1; /* No input waiting.  This shouldn't happen. */
+
+  /* Save the first byte waiting in the input buffer. */
+  first = info_input_buffer[pop_index];
+
+  b = byte_seq_to_key;
+
+  while (pop_index != push_index)
+    {
+      int in_map = 0;
+      if (!get_byte_from_input_buffer (&c))
+        break; /* Incomplete byte sequence. */
+
+      /* Would it be easier to dribble in info_gather_typeahead instead? */
+      if (info_dribble_file)
+        dribble (c);
+
+      switch (b[c].type)
+        {
+        case BYTEMAP_KEY:
+          return b[c].key;
+        case BYTEMAP_ESC:
+          esc_seen = 1;
+          pop_start = pop_index;
+          /* Fall through. */
+        case BYTEMAP_MAP:
+          in_map = 1;
+          b = b[c].next;
+          break;
+        case BYTEMAP_NONE:
+          break;
+        }
+
+      /* If we read an incomplete byte sequence, pause a short while to
+         see if more bytes follow.  We should probably allow the length
+         of this delay to be settable by the user. */
+      if (in_map && pop_index == push_index)
+        {
+          int ready = 0;
+#if defined (FD_SET)
+          struct timeval timer;
+          fd_set readfds;
+
+          FD_ZERO (&readfds);
+          FD_SET (fileno (info_input_stream), &readfds);
+          timer.tv_sec = 0;
+          timer.tv_usec = 10000;
+          ready = select (fileno(info_input_stream)+1, &readfds,
+                          NULL, NULL, &timer);
+#else
+              ready = 1;
+#endif /* FD_SET */
+          if (ready)
+            info_gather_typeahead (0);
+        }
+    }
+
+  if (esc_seen)
+    {
+      /* The sequence started with ESC, but wasn't recognized.  Treat it
+         as introducing a sequence produced by a key chord with the meta key
+         pressed. */
+
+      /* Start again with the first key after ESC. */
+      pop_index = pop_start;
+      b = byte_seq_to_key;
+
+      /* If there are no more characters, then decide that the escape key
+         itself has been pressed. */
+      if (pop_index == push_index)
+        return 033;
+
+      /* Save the first byte waiting in the input buffer. */
+      first = info_input_buffer[pop_index];
+
+      while (pop_index != push_index)
+        {
+          if (!get_byte_from_input_buffer (&c))
+            break; /* Incomplete byte sequence. */
+          switch (b[c].type)
+            {
+            case BYTEMAP_KEY:
+              return b[c].key + KEYMAP_META_BASE;
+            case BYTEMAP_MAP:
+              b = b[c].next;
+              break;
+            case BYTEMAP_ESC:
+              /* This could happen if there were two escapes in a row, or
+                 if the user types something like M-Left. */
+              b = b[c].next;
+              break;
+            case BYTEMAP_NONE:
+              break;
+            }
+        }
+      /* If the sequence was incomplete. */
+      return first + KEYMAP_META_BASE;
+    }
+
+  /* If the sequence was incomplete, return the first byte. */
+  return first;
+}
 
 /* **************************************************************** */
 /*                                                                  */
@@ -3421,7 +3558,7 @@
           NODE *node;
          
           /* Allow C-g to quit the search, failing it if pressed. */
-          info_gather_typeahead (); \
+          info_gather_typeahead (0); \
           if (info_input_buffer[pop_index] == Control ('g'))
             return -1;
 
@@ -3879,7 +4016,7 @@
         }
 
       /* Read a character and dispatch on it. */
-      key = info_get_input_char ();
+      key = info_get_input_byte ();
       window_get_state (window, &mystate);
 
       if (key == DEL || key == Control ('h'))
@@ -3902,7 +4039,7 @@
         }
       else if (key == Control ('q'))
         {
-          key = info_get_input_char ();
+          key = info_get_input_byte ();
           quoted = 1;
         }
 
@@ -4373,7 +4510,7 @@
 {}
 
 static void
-dispatch_error (char *keyseq)
+dispatch_error (int *keyseq)
 {
   char *rep;
 
@@ -4392,7 +4529,7 @@
 }
 
 /* Keeping track of key sequences. */
-static char *info_keyseq = NULL;
+static int *info_keyseq = NULL;
 static int info_keyseq_index = 0;
 static int info_keyseq_size = 0;
 static int info_keyseq_displayed_p = 0;
@@ -4407,10 +4544,11 @@
 
 /* Add CHARACTER to the current key sequence. */
 void
-add_char_to_keyseq (char character)
+add_char_to_keyseq (int character)
 {
   if (info_keyseq_index + 2 >= info_keyseq_size)
-    info_keyseq = (char *)xrealloc (info_keyseq, info_keyseq_size += 10);
+    info_keyseq = xrealloc (info_keyseq,
+                            sizeof (int) * (info_keyseq_size += 10));
 
   info_keyseq[info_keyseq_index++] = character;
   info_keyseq[info_keyseq_index] = '\0';
@@ -4438,9 +4576,13 @@
   info_keyseq_displayed_p = 1;
 }
 
-/* Called by interactive commands to read a keystroke. */
+/* Called by interactive commands to read another byte when bytes have already
+   been read as part of the current command (and possibly displayed in status
+   line with display_info_keyseq).
+   TODO: Replace calls to this function with calls to
+   get_another_input_key. */
 unsigned char
-info_get_another_input_char (void)
+info_get_another_input_byte (void)
 {
   int ready = !info_keyseq_displayed_p; /* ready if new and pending key */
 
@@ -4471,13 +4613,51 @@
   if (!ready)
     display_info_keyseq (1);
 
-  return info_get_input_char ();
+  return info_get_input_byte ();
 }
 
+/* Called by interactive commands to read another key when keys have already
+   been read as part of the current command (and possibly displayed in status
+   line with display_info_keyseq). */
+int
+get_another_input_key (void)
+{
+  int ready = !info_keyseq_displayed_p; /* ready if new and pending key */
+
+  /* If there isn't any input currently available, then wait a
+     moment looking for input.  If we don't get it fast enough,
+     prompt a little bit with the current key sequence. */
+  if (!info_keyseq_displayed_p)
+    {
+      ready = 1;
+      if (!info_any_buffered_input_p ())
+        {
+#if defined (FD_SET)
+          struct timeval timer;
+          fd_set readfds;
+
+          FD_ZERO (&readfds);
+          FD_SET (fileno (info_input_stream), &readfds);
+          timer.tv_sec = 1;
+          timer.tv_usec = 750;
+          ready = select (fileno(info_input_stream)+1, &readfds,
+                         NULL, NULL, &timer);
+#else
+          ready = 0;
+#endif /* FD_SET */
+      }
+    }
+
+  if (!ready)
+    display_info_keyseq (1);
+
+  return get_input_key ();
+}
+
 /* Do the command associated with KEY in MAP.  If the associated command is
    really a keymap, then read another key, and dispatch into that map. */
 void
-info_dispatch_on_key (unsigned char key, Keymap map)
+info_dispatch_on_key (int key, Keymap map)
 {
   switch (map[key].type)
     {
@@ -4491,10 +4671,18 @@
             /* Special case info_do_lowercase_version (). */
             if (func == (VFunction *) info_do_lowercase_version)
               {
-                unsigned char lowerkey;
+                int lowerkey;
 
-                lowerkey = Meta_p(key) ? Meta (tolower (UnMeta (key)))
-                  : tolower (key);
+                if (key >= KEYMAP_META_BASE)
+                  {
+                    lowerkey = key;
+                    lowerkey -= KEYMAP_META_BASE;
+                    lowerkey = towlower (lowerkey);
+                    lowerkey += KEYMAP_META_BASE;
+                  }
+                else
+                  lowerkey = towlower (key);
+
                 if (lowerkey == key)
                   {
                     add_char_to_keyseq (key);
@@ -4542,9 +4730,9 @@
       add_char_to_keyseq (key);
       if (map[key].function != NULL)
         {
-          unsigned char newkey;
+          int newkey;
 
-          newkey = info_get_another_input_char ();
+          newkey = get_another_input_key ();
           info_dispatch_on_key (newkey, (Keymap)map[key].function);
         }
       else
@@ -4654,7 +4842,7 @@
           if (active_window != the_echo_area)
             display_cursor_at_point (active_window);
 
-          pure_key = key = info_get_another_input_char ();
+          pure_key = key = info_get_another_input_byte ();
 
           add_char_to_keyseq (key);
         }

Modified: trunk/info/session.h
===================================================================
--- trunk/info/session.h        2014-06-20 17:27:15 UTC (rev 5680)
+++ trunk/info/session.h        2014-06-28 15:54:00 UTC (rev 5681)
@@ -74,14 +74,13 @@
 extern int scroll_last_node;
 
 /* Utility functions found in session.c */
-extern void info_dispatch_on_key (unsigned char key, Keymap map);
-extern unsigned char info_get_input_char (void);
-extern unsigned char info_get_another_input_char (void);
+extern void info_dispatch_on_key (int key, Keymap map);
+extern unsigned char info_get_input_byte (void);
+extern unsigned char info_get_another_input_byte (void);
 extern unsigned char info_input_pending_p (void);
 extern void info_set_node_of_window (WINDOW *window, NODE *node);
 extern void initialize_keyseq (void);
-extern void add_char_to_keyseq (char character);
-extern void info_gather_typeahead (void);
+extern void add_char_to_keyseq (int character);
 extern FILE_BUFFER *file_buffer_of_window (WINDOW *window);
 extern long info_search_in_node (char *string, NODE *node,
     long int start, WINDOW *window, int dir, int case_sensitive,

Modified: trunk/info/terminal.c
===================================================================
--- trunk/info/terminal.c       2014-06-20 17:27:15 UTC (rev 5680)
+++ trunk/info/terminal.c       2014-06-28 15:54:00 UTC (rev 5681)
@@ -23,6 +23,7 @@
 #include "info.h"
 #include "terminal.h"
 #include "termdep.h"
+#include "infomap.h"
 
 #include <sys/types.h>
 #include <signal.h>
@@ -500,6 +501,83 @@
     }
 }
 
+/* Root of structure representing a mapping from sequences of bytes to named
+   keys. */
+BYTEMAP_ENTRY *byte_seq_to_key;
+
+/* Initialize byte map read in get_input_key. */
+static void
+initialize_byte_map (void)
+{
+  int i;
+
+  static struct special_keys {
+      int key_id;
+      char **byte_seq;
+  } keys[] = {
+      KEY_RIGHT_ARROW, &term_kr,
+      KEY_LEFT_ARROW, &term_kl,
+      KEY_UP_ARROW, &term_ku,
+      KEY_DOWN_ARROW, &term_kd,
+      KEY_PAGE_UP, &term_kP,
+      KEY_PAGE_DOWN, &term_kN,
+      KEY_HOME, &term_kh,
+      KEY_END, &term_ke,
+      KEY_DELETE, &term_kD,
+      KEY_INSERT, &term_ki,
+      KEY_BACK_TAB, &term_bt
+  };
+
+  byte_seq_to_key = xmalloc (256 * sizeof (BYTEMAP_ENTRY));
+
+  /* Make each byte represent itself by default. */
+  for (i = 0; i < 128; i++)
+    {
+      byte_seq_to_key[i].type = BYTEMAP_KEY;
+      byte_seq_to_key[i].key = i;
+      byte_seq_to_key[i].next = 0;
+    }
+
+  /* Map each byte to the meta key. */
+  for (i = 128; i < 256; i++)
+    {
+      byte_seq_to_key[i].type = BYTEMAP_KEY;
+      byte_seq_to_key[i].key = (i - 128) + KEYMAP_META_BASE;
+      byte_seq_to_key[i].next = 0;
+    }
+
+  /* For each special key, record its byte sequence. */
+  for (i = 0; i < sizeof (keys) / sizeof (*keys); i++)
+    {
+      unsigned char *c;
+      BYTEMAP_ENTRY *b = byte_seq_to_key;
+
+      if (!*keys[i].byte_seq)
+        continue; /* No byte sequence known for this key. */
+      c = *keys[i].byte_seq;
+      for (; *c; c++)
+        {
+          if (c[1] == '\0') /* Last character. */
+            {
+              b[*c].type = BYTEMAP_KEY;
+              b[*c].key = keys[i].key_id;
+            }
+          else
+            {
+              b[*c].type = BYTEMAP_MAP;
+              b[*c].key = 0;
+              if (!b[*c].next)
+                b[*c].next = xzalloc (256 * sizeof (BYTEMAP_ENTRY));
+              b = b[*c].next;
+            }
+        }
+    }
+
+  /* Special case for ESC: Can introduce special key sequences, represent the
+     Meta key being pressed, or be a key on its own. */
+  byte_seq_to_key['\033'].type = BYTEMAP_ESC;
+}
+
 /* Initialize the terminal which is known as TERMINAL_NAME.  If this
    terminal doesn't have cursor addressability, `terminal_is_dumb_p'
    becomes nonzero.  The variables SCREENHEIGHT and SCREENWIDTH are set
@@ -645,6 +723,8 @@
   term_kD = tgetstr ("kD", &buffer);
   term_bt = tgetstr ("bt", &buffer);
 
+  initialize_byte_map ();
+
   /* If this terminal is not cursor addressable, then it is really dumb. */
   if (!term_goto)
     terminal_is_dumb_p = 1;




reply via email to

[Prev in Thread] Current Thread [Next in Thread]