Back to index

tetex-bin  3.0
infomap.c
Go to the documentation of this file.
00001 /* infomap.c -- keymaps for Info.
00002    $Id: infomap.c,v 1.10 2004/07/30 20:43:40 karl Exp $
00003 
00004    Copyright (C) 1993, 1997, 1998, 1999, 2001, 2002, 2003, 2004 Free Software
00005    Foundation, Inc.
00006 
00007    This program is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU General Public License as published by
00009    the Free Software Foundation; either version 2, or (at your option)
00010    any later version.
00011 
00012    This program is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015    GNU General Public License for more details.
00016 
00017    You should have received a copy of the GNU General Public License
00018    along with this program; if not, write to the Free Software
00019    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00020 
00021    Written by Brian Fox (bfox@ai.mit.edu). */
00022 
00023 #include "info.h"
00024 #include "infomap.h"
00025 #include "funs.h"
00026 #include "terminal.h"
00027 
00028 #if defined(INFOKEY)
00029 #include "infokey.h"
00030 #include "variables.h"
00031 #endif /* INFOKEY */
00032 
00033 static int keymap_bind_keyseq (Keymap map, const char *keyseq,
00034     KEYMAP_ENTRY *keyentry);
00035 
00036 /* Return a new keymap which has all the uppercase letters mapped to run
00037    the function info_do_lowercase_version (). */
00038 Keymap
00039 keymap_make_keymap (void)
00040 {
00041   int i;
00042   Keymap keymap;
00043 
00044   keymap = (Keymap)xmalloc (256 * sizeof (KEYMAP_ENTRY));
00045 
00046   for (i = 0; i < 256; i++)
00047     {
00048       keymap[i].type = ISFUNC;
00049       keymap[i].function = (InfoCommand *)NULL;
00050     }
00051 
00052   for (i = 'A'; i < ('Z' + 1); i++)
00053     {
00054       keymap[i].type = ISFUNC;
00055 #if defined(INFOKEY)
00056       keymap[Meta(i)].type = ISFUNC;
00057       keymap[Meta(i)].function =
00058 #endif /* INFOKEY */
00059       keymap[i].function = InfoCmd(info_do_lowercase_version);
00060     }
00061 
00062   return (keymap);
00063 }
00064 
00065 #if defined(INFOKEY)
00066 static FUNCTION_KEYSEQ *
00067 find_function_keyseq (Keymap map, int c, Keymap rootmap)
00068 {
00069   FUNCTION_KEYSEQ *k;
00070 
00071   if (map[c].type != ISFUNC)
00072     abort();
00073   if (map[c].function == NULL)
00074     return NULL;
00075   for (k = map[c].function->keys; k; k = k->next)
00076     {
00077       const unsigned char *p;
00078       Keymap m = rootmap;
00079       if (k->map != rootmap)
00080        continue;
00081       for (p = (unsigned char *) k->keyseq; *p && m[*p].type == ISKMAP; p++)
00082        m = (Keymap)m[*p].function;
00083       if (*p != c || p[1])
00084        continue;
00085       if (m[*p].type != ISFUNC)
00086        abort ();
00087       break;
00088     }
00089   return k;
00090 }
00091 
00092 static void
00093 add_function_keyseq (InfoCommand *function,
00094     const char *keyseq, Keymap rootmap)
00095 {
00096   FUNCTION_KEYSEQ *ks;
00097 
00098   if (function == NULL ||
00099       function == InfoCmd(info_do_lowercase_version) ||
00100       function == InfoCmd(ea_insert))
00101     return;
00102   ks = (FUNCTION_KEYSEQ *)xmalloc (sizeof(FUNCTION_KEYSEQ));
00103   ks->next = function->keys;
00104   ks->map = rootmap;
00105   ks->keyseq = xstrdup(keyseq);
00106   function->keys = ks;
00107 }
00108 
00109 static void
00110 remove_function_keyseq (InfoCommand *function,
00111     const char *keyseq, Keymap rootmap)
00112 {
00113 
00114   FUNCTION_KEYSEQ *k, *kp;
00115 
00116   if (function == NULL ||
00117       function == InfoCmd(info_do_lowercase_version) ||
00118       function == InfoCmd(ea_insert))
00119     return;
00120   for (kp = NULL, k = function->keys; k; kp = k, k = k->next)
00121     if (k->map == rootmap && strcmp(k->keyseq, keyseq) == 0)
00122       break;
00123   if (!k)
00124     abort ();
00125   if (kp)
00126     kp->next = k->next;
00127   else
00128     function->keys = k->next;
00129 }
00130 #endif /* INFOKEY */
00131 
00132 /* Return a new keymap which is a copy of MAP. */
00133 Keymap
00134 keymap_copy_keymap (Keymap map, Keymap rootmap, Keymap newroot)
00135 {
00136   int i;
00137   Keymap keymap;
00138 #if defined(INFOKEY)
00139   FUNCTION_KEYSEQ *ks;
00140 #endif /* INFOKEY */
00141 
00142   keymap = keymap_make_keymap ();
00143   if (!newroot)
00144     newroot = keymap;
00145 
00146   for (i = 0; i < 256; i++)
00147     {
00148       keymap[i].type = map[i].type;
00149       switch (map[i].type)
00150        {
00151        case ISFUNC:
00152          keymap[i].function = map[i].function;
00153 #if defined(INFOKEY)
00154          ks = find_function_keyseq (map, i, rootmap);
00155          if (ks)
00156            add_function_keyseq(map[i].function, ks->keyseq, newroot);
00157 #endif /* INFOKEY */
00158          break;
00159        case ISKMAP:
00160          keymap[i].function = (InfoCommand *)keymap_copy_keymap
00161             ((Keymap)map[i].function, rootmap, NULL);
00162          break;
00163        }
00164     }
00165   return (keymap);
00166 }
00167 
00168 /* Free the keymap and its descendants. */
00169 void
00170 keymap_discard_keymap (Keymap map, Keymap rootmap)
00171 {
00172   int i;
00173 
00174   if (!map)
00175     return;
00176   if (!rootmap)
00177     rootmap = map;
00178 
00179   for (i = 0; i < 256; i++)
00180     {
00181 #if defined(INFOKEY)
00182       FUNCTION_KEYSEQ *ks;
00183 #endif /* INFOKEY */
00184       switch (map[i].type)
00185         {
00186         case ISFUNC:
00187 #if defined(INFOKEY)
00188          ks = find_function_keyseq(map, i, rootmap);
00189          if (ks)
00190            remove_function_keyseq (map[i].function, ks->keyseq, rootmap);
00191 #endif /* INFOKEY */
00192           break;
00193 
00194         case ISKMAP:
00195           keymap_discard_keymap ((Keymap)map[i].function, rootmap);
00196           break;
00197 
00198         }
00199     }
00200   free(map);
00201 }
00202 
00203 /* Conditionally bind key sequence. */
00204 static int
00205 keymap_bind_keyseq (Keymap map,
00206     const char *keyseq, KEYMAP_ENTRY *keyentry)
00207 {
00208   Keymap m = map;
00209   const unsigned char *s = (unsigned char *) keyseq;
00210   int c;
00211 
00212   if (s == NULL || *s == '\0') return 0;
00213 
00214   while ((c = *s++) != '\0')
00215     {
00216 #if defined(INFOKEY)
00217       FUNCTION_KEYSEQ *ks;
00218 #endif /* INFOKEY */
00219       switch (m[c].type)
00220         {
00221         case ISFUNC:
00222 #if defined(INFOKEY)
00223          ks = find_function_keyseq(m, c, map);
00224          if (ks)
00225            remove_function_keyseq (m[c].function, ks->keyseq, map);
00226 #else /* !INFOKEY */
00227           if (!(m[c].function == NULL || (
00228                 m != map &&
00229                 m[c].function == InfoCmd(info_do_lowercase_version))
00230              ))
00231             return 0;
00232 #endif /* !INFOKEY */
00233 
00234           if (*s != '\0')
00235             {
00236               m[c].type = ISKMAP;
00237               /* Here we are casting the Keymap pointer returned from
00238                  keymap_make_keymap to an InfoCommand pointer.  Ugh.
00239                  This makes the `function' structure garbage
00240                  if it's actually interpreted as an InfoCommand.
00241                  Should really be using a union, and taking steps to
00242                  avoid the possible error.  */
00243               m[c].function = (InfoCommand *)keymap_make_keymap ();
00244             }
00245           break;
00246 
00247         case ISKMAP:
00248 #if defined(INFOKEY)
00249          if (*s == '\0')
00250            keymap_discard_keymap ((Keymap)m[c].function, map);
00251 #else /* !INFOKEY */
00252           if (*s == '\0')
00253             return 0;
00254 #endif
00255           break;
00256         }
00257       if (*s != '\0')
00258         {
00259           m = (Keymap)m[c].function;
00260         }
00261       else
00262         {
00263 #if defined(INFOKEY)
00264          add_function_keyseq (keyentry->function, keyseq, map);
00265 #endif /* INFOKEY */
00266           m[c] = *keyentry;
00267         }
00268     }
00269 
00270   return 1;
00271 }
00272 
00273 /* Initialize the standard info keymaps. */
00274 
00275 Keymap info_keymap = NULL;
00276 Keymap echo_area_keymap = NULL;
00277 
00278 #if !defined(INFOKEY)
00279 
00280 static void
00281 initialize_emacs_like_keymaps ()
00282 {
00283   int i;
00284   Keymap map;
00285 
00286   if (!info_keymap)
00287     {
00288       info_keymap = keymap_make_keymap ();
00289       echo_area_keymap = keymap_make_keymap ();
00290     }
00291 
00292   info_keymap[ESC].type = ISKMAP;
00293   info_keymap[ESC].function = (InfoCommand *)keymap_make_keymap ();
00294   info_keymap[Control ('x')].type = ISKMAP;
00295   info_keymap[Control ('x')].function = (InfoCommand *)keymap_make_keymap ();
00296 
00297   /* Bind the echo area insert routines.  Let's make all characters
00298      insertable by default, regardless of which character set we might
00299      be using.  */
00300   for (i = 0; i < 256; i++)
00301     echo_area_keymap[i].function = ea_insert;
00302 
00303   echo_area_keymap[ESC].type = ISKMAP;
00304   echo_area_keymap[ESC].function = (InfoCommand *) keymap_make_keymap ();
00305   echo_area_keymap[Control ('x')].type = ISKMAP;
00306   echo_area_keymap[Control ('x')].function
00307     = (InfoCommand *) keymap_make_keymap ();
00308 
00309   /* Bind numeric arg functions for both echo area and info window maps. */
00310   for (i = '0'; i < '9' + 1; i++)
00311     {
00312       ((Keymap) info_keymap[ESC].function)[i].function
00313         = ((Keymap) echo_area_keymap[ESC].function)[i].function
00314         = info_add_digit_to_numeric_arg;
00315     }
00316   ((Keymap) info_keymap[ESC].function)['-'].function =
00317     ((Keymap) echo_area_keymap[ESC].function)['-'].function =
00318       info_add_digit_to_numeric_arg;
00319 
00320   info_keymap['-'].function = info_add_digit_to_numeric_arg;
00321 
00322   /* Bind the echo area routines. */
00323   map = echo_area_keymap;
00324 
00325   map[Control ('a')].function = ea_beg_of_line;
00326   map[Control ('b')].function = ea_backward;
00327   map[Control ('d')].function = ea_delete;
00328   map[Control ('e')].function = ea_end_of_line;
00329   map[Control ('f')].function = ea_forward;
00330   map[Control ('g')].function = ea_abort;
00331   map[Control ('h')].function = ea_rubout;
00332   map[Control ('k')].function = ea_kill_line;
00333   map[Control ('l')].function = info_redraw_display;
00334   map[Control ('q')].function = ea_quoted_insert;
00335   map[Control ('t')].function = ea_transpose_chars;
00336   map[Control ('u')].function = info_universal_argument;
00337   map[Control ('y')].function = ea_yank;
00338 
00339   map[LFD].function = ea_newline;
00340   map[RET].function = ea_newline;
00341   map[SPC].function = ea_complete;
00342   map[TAB].function = ea_complete;
00343   map['?'].function = ea_possible_completions;
00344 #ifdef __MSDOS__
00345   /* PC users will lynch me if I don't give them their usual DEL effect...  */
00346   map[DEL].function = ea_delete;
00347 #else
00348   map[DEL].function = ea_rubout;
00349 #endif
00350 
00351   /* Bind the echo area ESC keymap. */
00352   map = (Keymap)echo_area_keymap[ESC].function;
00353 
00354   map[Control ('g')].function = ea_abort;
00355   map[Control ('v')].function = ea_scroll_completions_window;
00356   map['b'].function = ea_backward_word;
00357   map['d'].function = ea_kill_word;
00358   map['f'].function = ea_forward_word;
00359 #if defined (NAMED_FUNCTIONS)
00360   /* map['x'].function = info_execute_command; */
00361 #endif /* NAMED_FUNCTIONS */
00362   map['y'].function = ea_yank_pop;
00363   map['?'].function = ea_possible_completions;
00364   map[TAB].function = ea_tab_insert;
00365   map[DEL].function = ea_backward_kill_word;
00366 
00367   /* Bind the echo area Control-x keymap. */
00368   map = (Keymap)echo_area_keymap[Control ('x')].function;
00369 
00370   map['o'].function = info_next_window;
00371   map[DEL].function = ea_backward_kill_line;
00372 
00373   /* Arrow key bindings for echo area keymaps.  It seems that some
00374      terminals do not match their termcap entries, so it's best to just
00375      define everything with both of the usual prefixes.  */
00376   map = echo_area_keymap;
00377   keymap_bind_keyseq (map, term_ku, &map[Control ('p')]); /* up */
00378   keymap_bind_keyseq (map, "\033OA", &map[Control ('p')]);
00379   keymap_bind_keyseq (map, "\033[A", &map[Control ('p')]);
00380   keymap_bind_keyseq (map, term_kd, &map[Control ('n')]); /* down */
00381   keymap_bind_keyseq (map, "\033OB", &map[Control ('n')]);
00382   keymap_bind_keyseq (map, "\033[B", &map[Control ('n')]);
00383   keymap_bind_keyseq (map, term_kr, &map[Control ('f')]); /* right */
00384   keymap_bind_keyseq (map, "\033OC", &map[Control ('f')]);
00385   keymap_bind_keyseq (map, "\033[C", &map[Control ('f')]);
00386   keymap_bind_keyseq (map, term_kl, &map[Control ('b')]); /* left */
00387   keymap_bind_keyseq (map, "\033OD", &map[Control ('b')]);
00388   keymap_bind_keyseq (map, "\033[D", &map[Control ('b')]);
00389   keymap_bind_keyseq (map, term_kD, &map[DEL]);  /* delete */
00390   keymap_bind_keyseq (map, term_kh, &map[Control ('a')]); /* home */
00391   keymap_bind_keyseq (map, term_ke, &map[Control ('e')]); /* end */
00392 
00393   map = (Keymap)echo_area_keymap[ESC].function;
00394   keymap_bind_keyseq (map, term_kl, &map['b']); /* left */
00395   keymap_bind_keyseq (map, "\033OA", &map['b']);
00396   keymap_bind_keyseq (map, "\033[A", &map['b']);
00397   keymap_bind_keyseq (map, term_kr, &map['f']); /* right */
00398   keymap_bind_keyseq (map, "\033OB", &map['f']);
00399   keymap_bind_keyseq (map, "\033[B", &map['f']);
00400   keymap_bind_keyseq (map, term_kD, &map[DEL]);  /* delete */
00401 
00402   map = (Keymap)echo_area_keymap[Control ('x')].function;
00403   keymap_bind_keyseq (map, term_kD, &map[DEL]);  /* delete */
00404 
00405   /* Bind commands for Info window keymaps. */
00406   map = info_keymap;
00407   map[TAB].function = info_move_to_next_xref;
00408   map[LFD].function = info_select_reference_this_line;
00409   map[RET].function = info_select_reference_this_line;
00410   map[SPC].function = info_scroll_forward;
00411   map[Control ('a')].function = info_beginning_of_line;
00412   map[Control ('b')].function = info_backward_char;
00413   map[Control ('e')].function = info_end_of_line;
00414   map[Control ('f')].function = info_forward_char;
00415   map[Control ('g')].function = info_abort_key;
00416   map[Control ('h')].function = info_get_help_window;
00417   map[Control ('l')].function = info_redraw_display;
00418   map[Control ('n')].function = info_next_line;
00419   map[Control ('p')].function = info_prev_line;
00420   map[Control ('r')].function = isearch_backward;
00421   map[Control ('s')].function = isearch_forward;
00422   map[Control ('u')].function = info_universal_argument;
00423   map[Control ('v')].function = info_scroll_forward_page_only;
00424   map[','].function = info_next_index_match;
00425   map['/'].function = info_search;
00426 
00427   for (i = '1'; i < '9' + 1; i++)
00428     map[i].function = info_menu_digit;
00429   map['0'].function = info_last_menu_item;
00430 
00431   map['<'].function = info_first_node;
00432   map['>'].function = info_last_node;
00433   map['?'].function = info_get_help_window;
00434   map['['].function = info_global_prev_node;
00435   map[']'].function = info_global_next_node;
00436 
00437   map['b'].function = info_beginning_of_node;
00438   map['d'].function = info_dir_node;
00439   map['e'].function = info_end_of_node;
00440   map['f'].function = info_xref_item;
00441   map['g'].function = info_goto_node;
00442   map['G'].function = info_menu_sequence;
00443   map['h'].function = info_get_info_help_node;
00444   map['i'].function = info_index_search;
00445   map['I'].function = info_goto_invocation_node;
00446   map['l'].function = info_history_node;
00447   map['m'].function = info_menu_item;
00448   map['n'].function = info_next_node;
00449   map['O'].function = info_goto_invocation_node;
00450   map['p'].function = info_prev_node;
00451   map['q'].function = info_quit;
00452   map['r'].function = info_xref_item;
00453   map['s'].function = info_search;
00454   map['S'].function = info_search_case_sensitively;
00455   map['t'].function = info_top_node;
00456   map['u'].function = info_up_node;
00457   map[DEL].function = info_scroll_backward;
00458 
00459   /* Bind members in the ESC map for Info windows. */
00460   map = (Keymap)info_keymap[ESC].function;
00461   map[Control ('f')].function = info_show_footnotes;
00462   map[Control ('g')].function = info_abort_key;
00463   map[TAB].function = info_move_to_prev_xref;
00464   map[Control ('v')].function = info_scroll_other_window;
00465   map['<'].function = info_beginning_of_node;
00466   map['>'].function = info_end_of_node;
00467   map['b'].function = info_backward_word;
00468   map['f'].function = info_forward_word;
00469   map['r'].function = info_move_to_window_line;
00470   map['v'].function = info_scroll_backward_page_only;
00471 #if defined (NAMED_FUNCTIONS)
00472   map['x'].function = info_execute_command;
00473 #endif /* NAMED_FUNCTIONS */
00474   map[DEL].function = info_scroll_other_window_backward;
00475 
00476   /* Bind members in the Control-X map for Info windows. */
00477   map = (Keymap)info_keymap[Control ('x')].function;
00478 
00479   map[Control ('b')].function = list_visited_nodes;
00480   map[Control ('c')].function = info_quit;
00481   map[Control ('f')].function = info_view_file;
00482   map[Control ('g')].function = info_abort_key;
00483   map[Control ('v')].function = info_view_file;
00484   map['0'].function = info_delete_window;
00485   map['1'].function = info_keep_one_window;
00486   map['2'].function = info_split_window;
00487   map['^'].function = info_grow_window;
00488   map['b'].function = select_visited_node;
00489   map['k'].function = info_kill_node;
00490   map['n'].function = info_search_next;
00491   map['N'].function = info_search_previous;
00492   map['o'].function = info_next_window;
00493   map['t'].function = info_tile_windows;
00494   map['w'].function = info_toggle_wrap;
00495 
00496   /* Arrow key bindings for Info windows keymap. */
00497   map = info_keymap;
00498   keymap_bind_keyseq (map, term_kN, &map[Control ('v')]); /* pagedown */
00499   keymap_bind_keyseq (map, term_ku, &map[Control ('p')]); /* up */
00500   keymap_bind_keyseq (map, "\033OA", &map[Control ('p')]);
00501   keymap_bind_keyseq (map, "\033[A", &map[Control ('p')]);
00502   keymap_bind_keyseq (map, term_kd, &map[Control ('n')]); /* down */
00503   keymap_bind_keyseq (map, "\033OB", &map[Control ('n')]);
00504   keymap_bind_keyseq (map, "\033[B", &map[Control ('n')]);
00505   keymap_bind_keyseq (map, term_kr, &map[Control ('f')]); /* right */
00506   keymap_bind_keyseq (map, "\033OC", &map[Control ('f')]);
00507   keymap_bind_keyseq (map, "\033[C", &map[Control ('f')]);
00508   keymap_bind_keyseq (map, term_kl, &map[Control ('b')]); /* left */
00509   keymap_bind_keyseq (map, "\033OD", &map[Control ('b')]);
00510   keymap_bind_keyseq (map, "\033[D", &map[Control ('b')]);
00511   keymap_bind_keyseq (map, term_kh, &map['b']);  /* home */
00512   keymap_bind_keyseq (map, term_ke, &map['e']);  /* end */
00513   keymap_bind_keyseq (map, term_kD, &map[DEL]);  /* delete */
00514 
00515   map = (Keymap)info_keymap[ESC].function;
00516   keymap_bind_keyseq (map, term_kl, &map['b']); /* left */
00517   keymap_bind_keyseq (map, "\033OA", &map['b']);
00518   keymap_bind_keyseq (map, "\033[A", &map['b']);
00519   keymap_bind_keyseq (map, term_kr, &map['f']); /* right */
00520   keymap_bind_keyseq (map, "\033OB", &map['f']);
00521   keymap_bind_keyseq (map, "\033[B", &map['f']);
00522   keymap_bind_keyseq (map, term_kN, &map[Control ('v')]); /* pagedown */
00523   keymap_bind_keyseq (map, term_kP, &map[DEL]); /* pageup */
00524   keymap_bind_keyseq (map, term_kD, &map[DEL]);  /* delete */
00525 
00526   /* The alternative to this definition of a `main map' key in the
00527      `ESC map' section, is something like:
00528     keymap_bind_keyseq (map, term_kP, &((KeyMap)map[ESC].function).map['v']);
00529   */
00530   keymap_bind_keyseq (info_keymap/*sic*/, term_kP, &map['v']); /* pageup */
00531 }
00532 
00533 static void
00534 initialize_vi_like_keymaps ()
00535 {
00536   int i;
00537   Keymap map;
00538 
00539   if (!info_keymap)
00540     {
00541       info_keymap = keymap_make_keymap ();
00542       echo_area_keymap = keymap_make_keymap ();
00543     }
00544 
00545   info_keymap[ESC].type = ISKMAP;
00546   info_keymap[ESC].function = (InfoCommand *)keymap_make_keymap ();
00547   info_keymap[Control ('x')].type = ISKMAP;
00548   info_keymap[Control ('x')].function = (InfoCommand *)keymap_make_keymap ();
00549 
00550   /* Bind the echo area insert routines. */
00551   for (i = 0; i < 256; i++)
00552     echo_area_keymap[i].function = ea_insert;
00553 
00554   echo_area_keymap[ESC].type = ISKMAP;
00555   echo_area_keymap[ESC].function = (InfoCommand *)keymap_make_keymap ();
00556   echo_area_keymap[Control ('x')].type = ISKMAP;
00557   echo_area_keymap[Control ('x')].function =
00558     (InfoCommand *)keymap_make_keymap ();
00559 
00560   /* Bind numeric arg functions for both echo area and info window maps. */
00561   for (i = '0'; i < '9' + 1; i++)
00562     {
00563       info_keymap[i].function =
00564         ((Keymap) echo_area_keymap[ESC].function)[i].function =
00565        info_add_digit_to_numeric_arg;
00566     }
00567   info_keymap['-'].function =
00568     ((Keymap) echo_area_keymap[ESC].function)['-'].function =
00569       info_add_digit_to_numeric_arg;
00570 
00571   /* Bind the echo area routines. */
00572   map = echo_area_keymap;
00573 
00574   map[Control ('a')].function = ea_beg_of_line;
00575   map[Control ('b')].function = ea_backward;
00576   map[Control ('d')].function = ea_delete;
00577   map[Control ('e')].function = ea_end_of_line;
00578   map[Control ('f')].function = ea_forward;
00579   map[Control ('g')].function = ea_abort;
00580   map[Control ('h')].function = ea_rubout;
00581   map[Control ('k')].function = ea_kill_line;
00582   map[Control ('l')].function = info_redraw_display;
00583   map[Control ('q')].function = ea_quoted_insert;
00584   map[Control ('t')].function = ea_transpose_chars;
00585   map[Control ('u')].function = ea_abort;
00586   map[Control ('v')].function = ea_quoted_insert;
00587   map[Control ('y')].function = ea_yank;
00588 
00589   map[LFD].function = ea_newline;
00590   map[RET].function = ea_newline;
00591   map[SPC].function = ea_complete;
00592   map[TAB].function = ea_complete;
00593   map['?'].function = ea_possible_completions;
00594 #ifdef __MSDOS__
00595   /* PC users will lynch me if I don't give them their usual DEL effect...  */
00596   map[DEL].function = ea_delete;
00597 #else
00598   map[DEL].function = ea_rubout;
00599 #endif
00600 
00601   /* Bind the echo area ESC keymap. */
00602   map = (Keymap)echo_area_keymap[ESC].function;
00603 
00604   map[Control ('g')].function = ea_abort;
00605   map[Control ('h')].function = ea_backward_kill_word;
00606   map[Control ('v')].function = ea_scroll_completions_window;
00607   map['0'].function = ea_beg_of_line;
00608   map['$'].function = ea_end_of_line;
00609   map['b'].function = ea_backward_word;
00610   map['d'].function = ea_kill_word;
00611   map['f'].function = ea_forward_word;
00612   map['h'].function = ea_backward;
00613   map['l'].function = ea_forward;
00614   map['w'].function = ea_forward_word;
00615   map['x'].function = ea_delete;
00616   map['X'].function = ea_kill_word;
00617   map['y'].function = ea_yank_pop;
00618   map['?'].function = ea_possible_completions;
00619   map[TAB].function = ea_tab_insert;
00620   map[DEL].function = ea_kill_word;
00621 
00622   /* Bind the echo area Control-x keymap. */
00623   map = (Keymap)echo_area_keymap[Control ('x')].function;
00624 
00625   map['o'].function = info_next_window;
00626   map[DEL].function = ea_backward_kill_line;
00627 
00628   /* Arrow key bindings for echo area keymaps.  It seems that some
00629      terminals do not match their termcap entries, so it's best to just
00630      define everything with both of the usual prefixes.  */
00631   map = echo_area_keymap;
00632   keymap_bind_keyseq (map, term_ku, &map[Control ('p')]); /* up */
00633   keymap_bind_keyseq (map, "\033OA", &map[Control ('p')]);
00634   keymap_bind_keyseq (map, "\033[A", &map[Control ('p')]);
00635   keymap_bind_keyseq (map, term_kd, &map[Control ('n')]); /* down */
00636   keymap_bind_keyseq (map, "\033OB", &map[Control ('n')]);
00637   keymap_bind_keyseq (map, "\033[B", &map[Control ('n')]);
00638   keymap_bind_keyseq (map, term_kr, &map[Control ('f')]); /* right */
00639   keymap_bind_keyseq (map, "\033OC", &map[Control ('f')]);
00640   keymap_bind_keyseq (map, "\033[C", &map[Control ('f')]);
00641   keymap_bind_keyseq (map, term_kl, &map[Control ('b')]); /* left */
00642   keymap_bind_keyseq (map, "\033OD", &map[Control ('b')]);
00643   keymap_bind_keyseq (map, "\033[D", &map[Control ('b')]);
00644   keymap_bind_keyseq (map, term_kh, &map[Control ('a')]); /* home */
00645   keymap_bind_keyseq (map, term_ke, &map[Control ('e')]); /* end */
00646   keymap_bind_keyseq (map, term_kD, &map[DEL]);  /* delete */
00647 
00648   map = (Keymap)echo_area_keymap[ESC].function;
00649   keymap_bind_keyseq (map, term_kl, &map['b']); /* left */
00650   keymap_bind_keyseq (map, "\033OA", &map['b']);
00651   keymap_bind_keyseq (map, "\033[A", &map['b']);
00652   keymap_bind_keyseq (map, term_kr, &map['f']); /* right */
00653   keymap_bind_keyseq (map, "\033OB", &map['f']);
00654   keymap_bind_keyseq (map, "\033[B", &map['f']);
00655   keymap_bind_keyseq (map, term_kD, &map[DEL]);  /* delete */
00656 
00657   map = (Keymap)echo_area_keymap[Control ('x')].function;
00658   keymap_bind_keyseq (map, term_kD, &map[DEL]);
00659 
00660   /* Bind commands for Info window keymaps. */
00661   map = info_keymap;
00662   map[TAB].function = info_move_to_next_xref;
00663   map[LFD].function = info_down_line;
00664   map[RET].function = info_down_line;
00665   map[SPC].function = info_scroll_forward;
00666   map[Control ('a')].function = info_beginning_of_line;
00667   map[Control ('b')].function = info_scroll_backward_page_only;
00668   map[Control ('d')].function = info_scroll_half_screen_down;
00669   map[Control ('e')].function = info_down_line;
00670   map[Control ('f')].function = info_scroll_forward_page_only;
00671   map[Control ('g')].function = info_abort_key;
00672   map[Control ('k')].function = info_up_line;
00673   map[Control ('l')].function = info_redraw_display;
00674   map[Control ('n')].function = info_down_line;
00675   map[Control ('p')].function = info_up_line;
00676   map[Control ('r')].function = info_redraw_display;
00677   map[Control ('s')].function = isearch_forward;
00678   map[Control ('u')].function = info_scroll_half_screen_up;
00679   map[Control ('v')].function = info_scroll_forward_page_only;
00680   map[Control ('y')].function = info_up_line;
00681   map[','].function = info_next_index_match;
00682   map['/'].function = info_search;
00683 
00684   for (i = '1'; i < '9' + 1; i++)
00685     ((Keymap) info_keymap[ESC].function)[i].function = info_menu_digit;
00686   ((Keymap) info_keymap[ESC].function)['0'].function = info_last_menu_item;
00687 
00688   map['<'].function = info_first_node;
00689   map['>'].function = info_last_node;
00690   map['?'].function = info_search_backward;
00691   map['['].function = info_global_prev_node;
00692   map[']'].function = info_global_next_node;
00693   map['\''].function = info_history_node;
00694 
00695   map['b'].function = info_scroll_backward;
00696   map['d'].function = info_scroll_half_screen_down;
00697   map['e'].function = info_down_line;
00698   map['E'].function = info_view_file;
00699   map['f'].function = info_scroll_forward_page_only;
00700   map['F'].function = info_scroll_forward_page_only;
00701   map['g'].function = info_first_node;
00702   map['G'].function = info_last_node;
00703   map['h'].function = info_get_help_window;
00704   map['H'].function = info_get_help_window;
00705   map['i'].function = info_index_search;
00706   map['I'].function = info_goto_invocation_node;
00707   map['j'].function = info_next_line;
00708   map['k'].function = info_prev_line;
00709   map['l'].function = info_history_node;
00710   map['m'].function = info_menu_item;
00711   map['n'].function = info_search_next;
00712   map['N'].function = info_search_previous;
00713   map['O'].function = info_goto_invocation_node;
00714   map['p'].function = info_prev_node;
00715   map['q'].function = info_quit;
00716   map['Q'].function = info_quit;
00717   map['r'].function = info_redraw_display;
00718   map['R'].function = info_redraw_display;
00719   map['s'].function = info_search;
00720   map['S'].function = info_search_case_sensitively;
00721   map['t'].function = info_top_node;
00722   map['u'].function = info_scroll_half_screen_up;
00723   map['w'].function = info_scroll_backward_page_only_set_window;
00724   map['y'].function = info_up_line;
00725   map['z'].function = info_scroll_forward_page_only_set_window;
00726   map['Z'].function = NULL; /* unbind, so it works to bind "ZZ" below */
00727   map[DEL].function = info_scroll_backward;
00728   keymap_bind_keyseq (map, term_kD, &map[DEL]);
00729   keymap_bind_keyseq (map, ":q", &map['q']);
00730   keymap_bind_keyseq (map, ":Q", &map['q']);
00731   keymap_bind_keyseq (map, "ZZ", &map['q']);
00732 
00733   /* Bind members in the ESC map for Info windows. */
00734   map = (Keymap)info_keymap[ESC].function;
00735   map[Control ('f')].function = info_show_footnotes;
00736   map[Control ('g')].function = info_abort_key;
00737   map[TAB].function = info_move_to_prev_xref;
00738   map[SPC].function = info_scroll_forward_page_only;
00739   map[Control ('v')].function = info_scroll_other_window;
00740   map['<'].function = info_beginning_of_node;
00741   map['>'].function = info_end_of_node;
00742   map['/'].function = info_search;
00743   map['?'].function = info_search_backward;
00744   map['b'].function = info_beginning_of_node;
00745   map['d'].function = info_dir_node;
00746   map['e'].function = info_end_of_node;
00747   map['f'].function = info_xref_item;
00748   map['g'].function = info_select_reference_this_line;
00749   map['h'].function = info_get_info_help_node;
00750   map['m'].function = info_menu_item;
00751   map['n'].function = info_search;
00752   map['N'].function = info_search_backward;
00753   map['r'].function = isearch_backward;
00754   map['s'].function = isearch_forward;
00755   map['t'].function = info_top_node;
00756   map['v'].function = info_scroll_backward_page_only;
00757 #if defined (NAMED_FUNCTIONS)
00758   map['x'].function = info_execute_command;
00759 #endif /* NAMED_FUNCTIONS */
00760   map[DEL].function = info_scroll_other_window_backward;
00761 
00762   /* Bind members in the Control-X map for Info windows. */
00763   map = (Keymap)info_keymap[Control ('x')].function;
00764 
00765   map[Control ('b')].function = list_visited_nodes;
00766   map[Control ('c')].function = info_quit;
00767   map[Control ('f')].function = info_view_file;
00768   map[Control ('g')].function = info_abort_key;
00769   map[Control ('v')].function = info_view_file;
00770   map[LFD].function = info_select_reference_this_line;
00771   map[RET].function = info_select_reference_this_line;
00772   map['0'].function = info_delete_window;
00773   map['1'].function = info_keep_one_window;
00774   map['2'].function = info_split_window;
00775   map['^'].function = info_grow_window;
00776   map['b'].function = select_visited_node;
00777   map['g'].function = info_goto_node;
00778   map['i'].function = info_index_search;
00779   map['I'].function = info_goto_invocation_node;
00780   map['k'].function = info_kill_node;
00781   map['n'].function = info_next_node;
00782   map['o'].function = info_next_window;
00783   map['O'].function = info_goto_invocation_node;
00784   map['p'].function = info_prev_node;
00785   map['r'].function = info_xref_item;
00786   map['t'].function = info_tile_windows;
00787   map['u'].function = info_up_node;
00788   map['w'].function = info_toggle_wrap;
00789   map[','].function = info_next_index_match;
00790   keymap_bind_keyseq (info_keymap, ":e", &map[Control ('v')]);
00791 
00792   /* Arrow key bindings for Info windows keymap. */
00793   map = info_keymap;
00794   keymap_bind_keyseq (map, term_kN, &map[Control ('v')]); /* pagedown */
00795   keymap_bind_keyseq (map, term_ku, &map[Control ('p')]); /* up */
00796   keymap_bind_keyseq (map, "\033OA", &map[Control ('p')]);
00797   keymap_bind_keyseq (map, "\033[A", &map[Control ('p')]);
00798   keymap_bind_keyseq (map, term_kd, &map[Control ('n')]); /* down */
00799   keymap_bind_keyseq (map, "\033OB", &map[Control ('n')]);
00800   keymap_bind_keyseq (map, "\033[B", &map[Control ('n')]);
00801   keymap_bind_keyseq (map, term_kr, &map[Control ('f')]); /* right */
00802   keymap_bind_keyseq (map, "\033OC", &map[Control ('f')]);
00803   keymap_bind_keyseq (map, "\033[C", &map[Control ('f')]);
00804   keymap_bind_keyseq (map, term_kl, &map[Control ('b')]); /* left */
00805   keymap_bind_keyseq (map, "\033OD", &map[Control ('b')]);
00806   keymap_bind_keyseq (map, "\033[D", &map[Control ('b')]);
00807   keymap_bind_keyseq (map, term_kh, &map['b']);  /* home */
00808   keymap_bind_keyseq (map, term_ke, &map['e']);  /* end */
00809 
00810   map = (Keymap)info_keymap[ESC].function;
00811   keymap_bind_keyseq (map, term_kl, &map['b']); /* left */
00812   keymap_bind_keyseq (map, "\033OA", &map['b']);
00813   keymap_bind_keyseq (map, "\033[A", &map['b']);
00814   keymap_bind_keyseq (map, term_kr, &map['f']); /* right */
00815   keymap_bind_keyseq (map, "\033OB", &map['f']);
00816   keymap_bind_keyseq (map, "\033[B", &map['f']);
00817   keymap_bind_keyseq (map, term_kN, &map[Control ('v')]); /* pagedown */
00818   keymap_bind_keyseq (map, term_kP, &map[DEL]); /* pageup */
00819   keymap_bind_keyseq (map, term_kD, &map[DEL]);  /* delete */
00820 
00821   /* The alternative to this definition of a `main map' key in the
00822      `ESC map' section, is something like:
00823     keymap_bind_keyseq (map, term_kP, &((KeyMap)map[ESC].function).map['v']);
00824   */
00825   keymap_bind_keyseq (info_keymap/*sic*/, term_kP, &map['v']); /* pageup */
00826 }
00827 
00828 void
00829 initialize_info_keymaps ()
00830 {
00831   if (vi_keys_p)
00832     initialize_vi_like_keymaps ();
00833   else
00834     initialize_emacs_like_keymaps ();
00835 }
00836 
00837 #else /* defined(INFOKEY) */
00838 
00839 /* Make sure that we don't have too many command codes defined. */
00840 
00841 #if A_NCOMMANDS > A_MAX_COMMAND + 1
00842 #error "too many commands defined"
00843 #endif
00844 
00845 /* Initialize the keymaps from the .info keymap file. */
00846 
00847 #define NUL   '\0'
00848 
00849 static unsigned char default_emacs_like_info_keys[] =
00850 {
00851        0,     /* suppress-default-keybindings flag */
00852        TAB, NUL,                   A_info_move_to_next_xref,
00853        LFD, NUL,                   A_info_select_reference_this_line,
00854        RET, NUL,                   A_info_select_reference_this_line,
00855        SPC, NUL,                   A_info_scroll_forward,
00856        CONTROL('a'), NUL,          A_info_beginning_of_line,
00857        CONTROL('b'), NUL,          A_info_backward_char,
00858        CONTROL('e'), NUL,          A_info_end_of_line,
00859        CONTROL('f'), NUL,          A_info_forward_char,
00860        CONTROL('g'), NUL,          A_info_abort_key,
00861        CONTROL('h'), NUL,          A_info_get_help_window,
00862        CONTROL('l'), NUL,          A_info_redraw_display,
00863        CONTROL('n'), NUL,          A_info_next_line,
00864        CONTROL('p'), NUL,          A_info_prev_line,
00865        CONTROL('r'), NUL,          A_isearch_backward,
00866        CONTROL('s'), NUL,          A_isearch_forward,
00867        CONTROL('u'), NUL,          A_info_universal_argument,
00868        CONTROL('v'), NUL,          A_info_scroll_forward_page_only,
00869        ',', NUL,                   A_info_next_index_match,
00870        '/', NUL,                   A_info_search,
00871        '0', NUL,                   A_info_last_menu_item,
00872        '1', NUL,                   A_info_menu_digit,
00873        '2', NUL,                   A_info_menu_digit,
00874        '3', NUL,                   A_info_menu_digit,
00875        '4', NUL,                   A_info_menu_digit,
00876        '5', NUL,                   A_info_menu_digit,
00877        '6', NUL,                   A_info_menu_digit,
00878        '7', NUL,                   A_info_menu_digit,
00879        '8', NUL,                   A_info_menu_digit,
00880        '9', NUL,                   A_info_menu_digit,
00881        '<', NUL,                   A_info_first_node,
00882        '>', NUL,                   A_info_last_node,
00883        '?', NUL,                   A_info_get_help_window,
00884        '[', NUL,                   A_info_global_prev_node,
00885        ']', NUL,                   A_info_global_next_node,
00886        'b', NUL,                   A_info_beginning_of_node,
00887        'd', NUL,                   A_info_dir_node,
00888        'e', NUL,                   A_info_end_of_node,
00889        'f', NUL,                   A_info_xref_item,
00890        'g', NUL,                   A_info_goto_node,
00891        'G', NUL,                   A_info_menu_sequence,
00892        'h', NUL,                   A_info_get_info_help_node,
00893        'i', NUL,                   A_info_index_search,
00894        'l', NUL,                   A_info_history_node,
00895        'm', NUL,                   A_info_menu_item,
00896        'n', NUL,                   A_info_next_node,
00897        'O', NUL,                   A_info_goto_invocation_node,
00898        'p', NUL,                   A_info_prev_node,
00899        'q', NUL,                   A_info_quit,
00900        'r', NUL,                   A_info_xref_item,
00901        's', NUL,                   A_info_search,
00902        'S', NUL,                   A_info_search_case_sensitively,
00903        't', NUL,                   A_info_top_node,
00904        'u', NUL,                   A_info_up_node,
00905        DEL, NUL,                   A_info_scroll_backward,
00906        ESC, '0', NUL,                     A_info_add_digit_to_numeric_arg,
00907        ESC, '1', NUL,                     A_info_add_digit_to_numeric_arg,
00908        ESC, '2', NUL,                     A_info_add_digit_to_numeric_arg,
00909        ESC, '3', NUL,                     A_info_add_digit_to_numeric_arg,
00910        ESC, '4', NUL,                     A_info_add_digit_to_numeric_arg,
00911        ESC, '5', NUL,                     A_info_add_digit_to_numeric_arg,
00912        ESC, '6', NUL,                     A_info_add_digit_to_numeric_arg,
00913        ESC, '7', NUL,                     A_info_add_digit_to_numeric_arg,
00914        ESC, '8', NUL,                     A_info_add_digit_to_numeric_arg,
00915        ESC, '9', NUL,                     A_info_add_digit_to_numeric_arg,
00916        ESC, '-', NUL,                     A_info_add_digit_to_numeric_arg,
00917        ESC, CONTROL('f'), NUL,            A_info_show_footnotes,
00918        ESC, CONTROL('g'), NUL,            A_info_abort_key,
00919        ESC, TAB, NUL,                     A_info_move_to_prev_xref,
00920        ESC, CONTROL('v'), NUL,            A_info_scroll_other_window,
00921        ESC, '<', NUL,                     A_info_beginning_of_node,
00922        ESC, '>', NUL,                     A_info_end_of_node,
00923        ESC, 'b', NUL,                     A_info_backward_word,
00924        ESC, 'f', NUL,                     A_info_forward_word,
00925        ESC, 'r', NUL,                     A_info_move_to_window_line,
00926        ESC, 'v', NUL,                     A_info_scroll_backward_page_only,
00927        Meta('0'), NUL,                    A_info_add_digit_to_numeric_arg,
00928        Meta('1'), NUL,                    A_info_add_digit_to_numeric_arg,
00929        Meta('2'), NUL,                    A_info_add_digit_to_numeric_arg,
00930        Meta('3'), NUL,                    A_info_add_digit_to_numeric_arg,
00931        Meta('4'), NUL,                    A_info_add_digit_to_numeric_arg,
00932        Meta('5'), NUL,                    A_info_add_digit_to_numeric_arg,
00933        Meta('6'), NUL,                    A_info_add_digit_to_numeric_arg,
00934        Meta('7'), NUL,                    A_info_add_digit_to_numeric_arg,
00935        Meta('8'), NUL,                    A_info_add_digit_to_numeric_arg,
00936        Meta('9'), NUL,                    A_info_add_digit_to_numeric_arg,
00937        Meta('-'), NUL,                    A_info_add_digit_to_numeric_arg,
00938        Meta(CONTROL('f')), NUL,    A_info_show_footnotes,
00939        Meta(CONTROL('g')), NUL,    A_info_abort_key,
00940        Meta(TAB), NUL,                    A_info_move_to_prev_xref,
00941        Meta(CONTROL('v')), NUL,    A_info_scroll_other_window,
00942        Meta('<'), NUL,                    A_info_beginning_of_node,
00943        Meta('>'), NUL,                    A_info_end_of_node,
00944        Meta('b'), NUL,                    A_info_backward_word,
00945        Meta('f'), NUL,                    A_info_forward_word,
00946        Meta('r'), NUL,                    A_info_move_to_window_line,
00947        Meta('v'), NUL,                    A_info_scroll_backward_page_only,
00948 #if defined (NAMED_FUNCTIONS)
00949        ESC, 'x', NUL,                     A_info_execute_command,
00950        Meta('x'), NUL,                    A_info_execute_command,
00951 #endif /* NAMED_FUNCTIONS */
00952 
00953        CONTROL('x'), CONTROL('b'), NUL,   A_list_visited_nodes,
00954        CONTROL('x'), CONTROL('c'), NUL,   A_info_quit,
00955        CONTROL('x'), CONTROL('f'), NUL,   A_info_view_file,
00956        CONTROL('x'), CONTROL('g'), NUL,   A_info_abort_key,
00957        CONTROL('x'), CONTROL('v'), NUL,   A_info_view_file,
00958        CONTROL('x'), '0', NUL,            A_info_delete_window,
00959        CONTROL('x'), '1', NUL,            A_info_keep_one_window,
00960        CONTROL('x'), '2', NUL,            A_info_split_window,
00961        CONTROL('x'), '^', NUL,            A_info_grow_window,
00962        CONTROL('x'), 'b', NUL,            A_select_visited_node,
00963        CONTROL('x'), 'k', NUL,            A_info_kill_node,
00964        CONTROL('x'), 'n', NUL,            A_info_search_next,
00965        CONTROL('x'), 'N', NUL,            A_info_search_previous,
00966        CONTROL('x'), 'o', NUL,            A_info_next_window,
00967        CONTROL('x'), 't', NUL,            A_info_tile_windows,
00968        CONTROL('x'), 'w', NUL,            A_info_toggle_wrap,
00969 
00970 /*     Arrow key bindings for info keymaps.  It seems that some
00971        terminals do not match their termcap entries, so it's best to just
00972        define everything with both of the usual prefixes.  */
00973 
00974        SK_ESCAPE, SK_PAGE_UP, NUL,        A_info_scroll_backward_page_only,
00975        SK_ESCAPE, SK_PAGE_DOWN, NUL,             A_info_scroll_forward_page_only,
00976        SK_ESCAPE, SK_UP_ARROW, NUL,              A_info_prev_line,
00977        '\033', 'O', 'A', NUL,                    A_info_prev_line,
00978        '\033', '[', 'A', NUL,                    A_info_prev_line,
00979        SK_ESCAPE, SK_DOWN_ARROW, NUL,            A_info_next_line,
00980        '\033', 'O', 'B', NUL,                    A_info_next_line,
00981        '\033', '[', 'B', NUL,                    A_info_next_line,
00982        SK_ESCAPE, SK_RIGHT_ARROW, NUL,           A_info_forward_char,
00983        '\033', 'O', 'C', NUL,                    A_info_forward_char,
00984        '\033', '[', 'C', NUL,                    A_info_forward_char,
00985        SK_ESCAPE, SK_LEFT_ARROW, NUL,            A_info_backward_char,
00986        '\033', 'O', 'D', NUL,                    A_info_backward_char,
00987        '\033', '[', 'D', NUL,                    A_info_backward_char,
00988        SK_ESCAPE, SK_HOME, NUL,           A_info_beginning_of_node,
00989        SK_ESCAPE, SK_END, NUL,                   A_info_end_of_node,
00990        SK_ESCAPE, SK_DELETE, NUL,         A_info_scroll_backward,
00991 
00992        ESC, SK_ESCAPE, SK_PAGE_UP, NUL,   A_info_scroll_other_window_backward,
00993        ESC, SK_ESCAPE, SK_PAGE_DOWN, NUL, A_info_scroll_other_window,
00994        ESC, SK_ESCAPE, SK_UP_ARROW, NUL,  A_info_prev_line,
00995        ESC, '\033', 'O', 'A', NUL,        A_info_prev_line,
00996        ESC, '\033', '[', 'A', NUL,        A_info_prev_line,
00997        ESC, SK_ESCAPE, SK_DOWN_ARROW, NUL,       A_info_next_line,
00998        ESC, '\033', 'O', 'B', NUL,        A_info_next_line,
00999        ESC, '\033', '[', 'B', NUL,        A_info_next_line,
01000        ESC, SK_ESCAPE, SK_RIGHT_ARROW, NUL,      A_info_forward_word,
01001        ESC, '\033', 'O', 'C', NUL,        A_info_forward_word,
01002        ESC, '\033', '[', 'C', NUL,        A_info_forward_word,
01003        ESC, SK_ESCAPE, SK_LEFT_ARROW, NUL,       A_info_backward_word,
01004        ESC, '\033', 'O', 'D', NUL,        A_info_backward_word,
01005        ESC, '\033', '[', 'D', NUL,        A_info_backward_word,
01006 };
01007 
01008 static unsigned char default_emacs_like_ea_keys[] =
01009 {
01010        0,     /* suppress-default-keybindings flag */
01011        ESC, '0', NUL,                     A_info_add_digit_to_numeric_arg,
01012        ESC, '1', NUL,                     A_info_add_digit_to_numeric_arg,
01013        ESC, '2', NUL,                     A_info_add_digit_to_numeric_arg,
01014        ESC, '3', NUL,                     A_info_add_digit_to_numeric_arg,
01015        ESC, '4', NUL,                     A_info_add_digit_to_numeric_arg,
01016        ESC, '5', NUL,                     A_info_add_digit_to_numeric_arg,
01017        ESC, '6', NUL,                     A_info_add_digit_to_numeric_arg,
01018        ESC, '7', NUL,                     A_info_add_digit_to_numeric_arg,
01019        ESC, '8', NUL,                     A_info_add_digit_to_numeric_arg,
01020        ESC, '9', NUL,                     A_info_add_digit_to_numeric_arg,
01021        ESC, '-', NUL,                     A_info_add_digit_to_numeric_arg,
01022        Meta('0'), NUL,                    A_info_add_digit_to_numeric_arg,
01023        Meta('1'), NUL,                    A_info_add_digit_to_numeric_arg,
01024        Meta('2'), NUL,                    A_info_add_digit_to_numeric_arg,
01025        Meta('3'), NUL,                    A_info_add_digit_to_numeric_arg,
01026        Meta('4'), NUL,                    A_info_add_digit_to_numeric_arg,
01027        Meta('5'), NUL,                    A_info_add_digit_to_numeric_arg,
01028        Meta('6'), NUL,                    A_info_add_digit_to_numeric_arg,
01029        Meta('7'), NUL,                    A_info_add_digit_to_numeric_arg,
01030        Meta('8'), NUL,                    A_info_add_digit_to_numeric_arg,
01031        Meta('9'), NUL,                    A_info_add_digit_to_numeric_arg,
01032        Meta('-'), NUL,                    A_info_add_digit_to_numeric_arg,
01033        ESC, CONTROL('g'), NUL,            A_ea_abort,
01034        ESC, CONTROL('v'), NUL,            A_ea_scroll_completions_window,
01035        ESC, 'b', NUL,                     A_ea_backward_word,
01036        ESC, 'd', NUL,                     A_ea_kill_word,
01037        ESC, 'f', NUL,                     A_ea_forward_word,
01038        ESC, 'y', NUL,                     A_ea_yank_pop,
01039        ESC, '?', NUL,                     A_ea_possible_completions,
01040        ESC, TAB, NUL,                     A_ea_tab_insert,
01041        ESC, DEL, NUL,                     A_ea_backward_kill_word,
01042        Meta(CONTROL('g')), NUL,    A_ea_abort,
01043        Meta(CONTROL('v')), NUL,    A_ea_scroll_completions_window,
01044        Meta('b'), NUL,                    A_ea_backward_word,
01045        Meta('d'), NUL,                    A_ea_kill_word,
01046        Meta('f'), NUL,                    A_ea_forward_word,
01047        Meta('y'), NUL,                    A_ea_yank_pop,
01048        Meta('?'), NUL,                    A_ea_possible_completions,
01049        Meta(TAB), NUL,                    A_ea_tab_insert,
01050        Meta(DEL), NUL,                    A_ea_backward_kill_word,
01051        CONTROL('a'), NUL,          A_ea_beg_of_line,
01052        CONTROL('b'), NUL,          A_ea_backward,
01053        CONTROL('d'), NUL,          A_ea_delete,
01054        CONTROL('e'), NUL,          A_ea_end_of_line,
01055        CONTROL('f'), NUL,          A_ea_forward,
01056        CONTROL('g'), NUL,          A_ea_abort,
01057        CONTROL('h'), NUL,          A_ea_rubout,
01058 /*     CONTROL('k') */
01059        SK_ESCAPE, SK_LITERAL, NUL, A_ea_kill_line,
01060        CONTROL('l'), NUL,          A_info_redraw_display,
01061        CONTROL('q'), NUL,          A_ea_quoted_insert,
01062        CONTROL('t'), NUL,          A_ea_transpose_chars,
01063        CONTROL('u'), NUL,          A_info_universal_argument,
01064        CONTROL('y'), NUL,          A_ea_yank,
01065        LFD, NUL,                   A_ea_newline,
01066        RET, NUL,                   A_ea_newline,
01067        SPC, NUL,                   A_ea_complete,
01068        TAB, NUL,                   A_ea_complete,
01069        '?', NUL,                   A_ea_possible_completions,
01070 #ifdef __MSDOS__
01071         /* PC users will lynch me if I don't give them their usual DEL
01072           effect...  */
01073        DEL, NUL,                   A_ea_delete,
01074 #else
01075        DEL, NUL,                   A_ea_rubout,
01076 #endif
01077 #if defined (NAMED_FUNCTIONS)
01078   /*   ESC, 'x', NUL,                     A_info_execute_command, */
01079   /*   Meta('x'), NUL,                    A_info_execute_command, */
01080 #endif /* NAMED_FUNCTIONS */
01081        CONTROL('x'), 'o', NUL,            A_info_next_window,
01082        CONTROL('x'), DEL, NUL,            A_ea_backward_kill_line,
01083 
01084 /*     Arrow key bindings for echo area keymaps.  It seems that some
01085        terminals do not match their termcap entries, so it's best to just
01086        define everything with both of the usual prefixes.  */
01087 
01088        SK_ESCAPE, SK_RIGHT_ARROW, NUL,           A_ea_forward,
01089        '\033', 'O', 'C', NUL,                    A_ea_forward,
01090        '\033', '[', 'C', NUL,                    A_ea_forward,
01091        SK_ESCAPE, SK_LEFT_ARROW, NUL,            A_ea_backward,
01092        '\033', 'O', 'D', NUL,                    A_ea_backward,
01093        '\033', '[', 'D', NUL,                    A_ea_backward,
01094        ESC, SK_ESCAPE, SK_RIGHT_ARROW, NUL,      A_ea_forward_word,
01095        ESC, '\033', 'O', 'C', NUL,        A_ea_forward_word,
01096        ESC, '\033', '[', 'C', NUL,        A_ea_forward_word,
01097        ESC, SK_ESCAPE, SK_LEFT_ARROW, NUL,       A_ea_backward_word,
01098        ESC, '\033', 'O', 'D', NUL,        A_ea_backward_word,
01099        ESC, '\033', '[', 'D', NUL,        A_ea_backward_word,
01100 #ifdef __MSDOS__
01101        SK_ESCAPE, SK_DELETE, NUL,         A_ea_delete,
01102 #else
01103        SK_ESCAPE, SK_DELETE, NUL,         A_ea_rubout,
01104 #endif
01105        SK_ESCAPE, SK_HOME, NUL,           A_ea_beg_of_line,
01106        SK_ESCAPE, SK_END, NUL,                   A_ea_end_of_line,
01107        ESC, SK_ESCAPE, SK_DELETE, NUL,           A_ea_backward_kill_word,
01108        CONTROL('x'), SK_ESCAPE, SK_DELETE, NUL,A_ea_backward_kill_line,
01109 };
01110 
01111 static unsigned char default_vi_like_info_keys[] =
01112 {
01113        0,     /* suppress-default-keybindings flag */
01114        '0', NUL,                   A_info_add_digit_to_numeric_arg,
01115        '1', NUL,                   A_info_add_digit_to_numeric_arg,
01116        '2', NUL,                   A_info_add_digit_to_numeric_arg,
01117        '3', NUL,                   A_info_add_digit_to_numeric_arg,
01118        '4', NUL,                   A_info_add_digit_to_numeric_arg,
01119        '5', NUL,                   A_info_add_digit_to_numeric_arg,
01120        '6', NUL,                   A_info_add_digit_to_numeric_arg,
01121        '7', NUL,                   A_info_add_digit_to_numeric_arg,
01122        '8', NUL,                   A_info_add_digit_to_numeric_arg,
01123        '9', NUL,                   A_info_add_digit_to_numeric_arg,
01124        '-', NUL,                   A_info_add_digit_to_numeric_arg,
01125        TAB, NUL,                   A_info_move_to_next_xref,
01126        LFD, NUL,                   A_info_down_line,
01127        RET, NUL,                   A_info_down_line,
01128        SPC, NUL,                   A_info_scroll_forward,
01129        CONTROL('a'), NUL,          A_info_beginning_of_line,
01130        CONTROL('b'), NUL,          A_info_scroll_backward_page_only,
01131        CONTROL('d'), NUL,          A_info_scroll_half_screen_down,
01132        CONTROL('e'), NUL,          A_info_down_line,
01133        CONTROL('f'), NUL,          A_info_scroll_forward_page_only,
01134        CONTROL('g'), NUL,          A_info_abort_key,
01135        CONTROL('k'), NUL,          A_info_up_line,
01136        CONTROL('l'), NUL,          A_info_redraw_display,
01137        CONTROL('n'), NUL,          A_info_down_line,
01138        CONTROL('p'), NUL,          A_info_up_line,
01139        CONTROL('r'), NUL,          A_info_redraw_display,
01140        CONTROL('s'), NUL,          A_isearch_forward,
01141        CONTROL('u'), NUL,          A_info_scroll_half_screen_up,
01142        CONTROL('v'), NUL,          A_info_scroll_forward_page_only,
01143        CONTROL('y'), NUL,          A_info_up_line,
01144        ',', NUL,                   A_info_next_index_match,
01145        '/', NUL,                   A_info_search,
01146        ESC, '0', NUL,                     A_info_last_menu_item,
01147        ESC, '1', NUL,                     A_info_menu_digit,
01148        ESC, '2', NUL,                     A_info_menu_digit,
01149        ESC, '3', NUL,                     A_info_menu_digit,
01150        ESC, '4', NUL,                     A_info_menu_digit,
01151        ESC, '5', NUL,                     A_info_menu_digit,
01152        ESC, '6', NUL,                     A_info_menu_digit,
01153        ESC, '7', NUL,                     A_info_menu_digit,
01154        ESC, '8', NUL,                     A_info_menu_digit,
01155        ESC, '9', NUL,                     A_info_menu_digit,
01156        Meta('0'), NUL,                    A_info_last_menu_item,
01157        Meta('1'), NUL,                    A_info_menu_digit,
01158        Meta('2'), NUL,                    A_info_menu_digit,
01159        Meta('3'), NUL,                    A_info_menu_digit,
01160        Meta('4'), NUL,                    A_info_menu_digit,
01161        Meta('5'), NUL,                    A_info_menu_digit,
01162        Meta('6'), NUL,                    A_info_menu_digit,
01163        Meta('7'), NUL,                    A_info_menu_digit,
01164        Meta('8'), NUL,                    A_info_menu_digit,
01165        Meta('9'), NUL,                    A_info_menu_digit,
01166        '<', NUL,                   A_info_first_node,
01167        '>', NUL,                   A_info_last_node,
01168        '?', NUL,                   A_info_search_backward,
01169        '[', NUL,                   A_info_global_prev_node,
01170        ']', NUL,                   A_info_global_next_node,
01171        '\'', NUL,                  A_info_history_node,
01172        'b', NUL,                   A_info_scroll_backward,
01173        'd', NUL,                   A_info_scroll_half_screen_down,
01174        'e', NUL,                   A_info_down_line,
01175        'E', NUL,                   A_info_view_file,
01176        ':', 'e', NUL,                     A_info_view_file,
01177        'f', NUL,                   A_info_scroll_forward_page_only,
01178        'F', NUL,                   A_info_scroll_forward_page_only,
01179        'g', NUL,                   A_info_first_node,
01180        'G', NUL,                   A_info_last_node,
01181        'h', NUL,                   A_info_get_help_window,
01182        'H', NUL,                   A_info_get_help_window,
01183        'i', NUL,                   A_info_index_search,
01184        'I', NUL,                   A_info_goto_invocation_node,
01185        'j', NUL,                   A_info_next_line,
01186        'k', NUL,                   A_info_prev_line,
01187        'l', NUL,                   A_info_history_node,
01188        'm', NUL,                   A_info_menu_item,
01189        'n', NUL,                   A_info_search_next,
01190        'N', NUL,                   A_info_search_previous,
01191        'O', NUL,                   A_info_goto_invocation_node,
01192        'p', NUL,                   A_info_prev_node,
01193        'q', NUL,                   A_info_quit,
01194        'Q', NUL,                   A_info_quit,
01195        ':', 'q', NUL,                     A_info_quit,
01196        ':', 'Q', NUL,                     A_info_quit,
01197        'Z', 'Z', NUL,                     A_info_quit,
01198        'r', NUL,                   A_info_redraw_display,
01199        'R', NUL,                   A_info_redraw_display,
01200        's', NUL,                   A_info_search,
01201        'S', NUL,                   A_info_search_case_sensitively,
01202        't', NUL,                   A_info_top_node,
01203        'u', NUL,                   A_info_scroll_half_screen_up,
01204        'w', NUL,                   A_info_scroll_backward_page_only_set_window,
01205        'y', NUL,                   A_info_up_line,
01206        'z', NUL,                   A_info_scroll_forward_page_only_set_window,
01207        DEL, NUL,                   A_info_scroll_backward,
01208        ESC, CONTROL('f'), NUL,            A_info_show_footnotes,
01209        ESC, CONTROL('g'), NUL,            A_info_abort_key,
01210        ESC, TAB, NUL,                     A_info_move_to_prev_xref,
01211        ESC, SPC, NUL,                     A_info_scroll_forward_page_only,
01212        ESC, CONTROL('v'), NUL,            A_info_scroll_other_window,
01213        ESC, '<', NUL,                     A_info_beginning_of_node,
01214        ESC, '>', NUL,                     A_info_end_of_node,
01215        ESC, '/', NUL,                     A_info_search,
01216        ESC, '?', NUL,                     A_info_search_backward,
01217        ESC, 'b', NUL,                     A_info_beginning_of_node,
01218        ESC, 'd', NUL,                     A_info_dir_node,
01219        ESC, 'e', NUL,                     A_info_end_of_node,
01220        ESC, 'f', NUL,                     A_info_xref_item,
01221        ESC, 'g', NUL,                     A_info_select_reference_this_line,
01222        ESC, 'h', NUL,                     A_info_get_info_help_node,
01223        ESC, 'm', NUL,                     A_info_menu_item,
01224        ESC, 'n', NUL,                     A_info_search,
01225        ESC, 'N', NUL,                     A_info_search_backward,
01226        ESC, 'r', NUL,                     A_isearch_backward,
01227        ESC, 's', NUL,                     A_isearch_forward,
01228        ESC, 't', NUL,                     A_info_top_node,
01229        ESC, 'v', NUL,                     A_info_scroll_backward_page_only,
01230 #if defined (NAMED_FUNCTIONS)
01231        ESC, 'x', NUL,                     A_info_execute_command,
01232        Meta('x'), NUL,                    A_info_execute_command,
01233 #endif /* NAMED_FUNCTIONS */
01234        ESC, DEL, NUL,                     A_info_scroll_other_window_backward,
01235        CONTROL('x'), CONTROL('b'), NUL,   A_list_visited_nodes,
01236        CONTROL('x'), CONTROL('c'), NUL,   A_info_quit,
01237        CONTROL('x'), CONTROL('f'), NUL,   A_info_view_file,
01238        CONTROL('x'), CONTROL('g'), NUL,   A_info_abort_key,
01239        CONTROL('x'), CONTROL('v'), NUL,   A_info_view_file,
01240        CONTROL('x'), LFD, NUL,            A_info_select_reference_this_line,
01241        CONTROL('x'), RET, NUL,            A_info_select_reference_this_line,
01242        CONTROL('x'), '0', NUL,            A_info_delete_window,
01243        CONTROL('x'), '1', NUL,            A_info_keep_one_window,
01244        CONTROL('x'), '2', NUL,            A_info_split_window,
01245        CONTROL('x'), '^', NUL,            A_info_grow_window,
01246        CONTROL('x'), 'b', NUL,            A_select_visited_node,
01247        CONTROL('x'), 'g', NUL,            A_info_goto_node,
01248        CONTROL('x'), 'i', NUL,            A_info_index_search,
01249        CONTROL('x'), 'I', NUL,            A_info_goto_invocation_node,
01250        CONTROL('x'), 'k', NUL,            A_info_kill_node,
01251        CONTROL('x'), 'n', NUL,            A_info_next_node,
01252        CONTROL('x'), 'o', NUL,            A_info_next_window,
01253        CONTROL('x'), 'O', NUL,            A_info_goto_invocation_node,
01254        CONTROL('x'), 'p', NUL,            A_info_prev_node,
01255        CONTROL('x'), 'r', NUL,            A_info_xref_item,
01256        CONTROL('x'), 't', NUL,            A_info_tile_windows,
01257        CONTROL('x'), 'u', NUL,            A_info_up_node,
01258        CONTROL('x'), 'w', NUL,            A_info_toggle_wrap,
01259        CONTROL('x'), ',', NUL,            A_info_next_index_match,
01260 
01261 /*     Arrow key bindings for info keymaps.  It seems that some
01262        terminals do not match their termcap entries, so it's best to just
01263        define everything with both of the usual prefixes.  */
01264 
01265        SK_ESCAPE, SK_PAGE_UP, NUL,        A_info_scroll_backward_page_only,
01266        SK_ESCAPE, SK_PAGE_DOWN, NUL,             A_info_scroll_forward_page_only,
01267        SK_ESCAPE, SK_UP_ARROW, NUL,              A_info_up_line,
01268        '\033', 'O', 'A', NUL,                    A_info_up_line,
01269        '\033', '[', 'A', NUL,                    A_info_up_line,
01270        SK_ESCAPE, SK_DOWN_ARROW, NUL,            A_info_down_line,
01271        '\033', 'O', 'B', NUL,                    A_info_down_line,
01272        '\033', '[', 'B', NUL,                    A_info_down_line,
01273        SK_ESCAPE, SK_RIGHT_ARROW, NUL,           A_info_scroll_forward_page_only,
01274        '\033', 'O', 'C', NUL,                    A_info_scroll_forward_page_only,
01275        '\033', '[', 'C', NUL,                    A_info_scroll_forward_page_only,
01276        SK_ESCAPE, SK_LEFT_ARROW, NUL,            A_info_scroll_backward_page_only,
01277        '\033', 'O', 'D', NUL,                    A_info_scroll_backward_page_only,
01278        '\033', '[', 'D', NUL,                    A_info_scroll_backward_page_only,
01279        SK_ESCAPE, SK_HOME, NUL,           A_info_beginning_of_node,
01280        SK_ESCAPE, SK_END, NUL,                   A_info_end_of_node,
01281        ESC, SK_ESCAPE, SK_PAGE_DOWN, NUL, A_info_scroll_other_window,
01282        ESC, SK_ESCAPE, SK_PAGE_UP, NUL,   A_info_scroll_other_window_backward,
01283        ESC, SK_ESCAPE, SK_DELETE, NUL,           A_info_scroll_other_window_backward,
01284        ESC, SK_ESCAPE, SK_UP_ARROW, NUL,  A_info_prev_node,
01285        ESC, '\033', 'O', 'A', NUL,        A_info_prev_node,
01286        ESC, '\033', '[', 'A', NUL,        A_info_prev_node,
01287        ESC, SK_ESCAPE, SK_DOWN_ARROW, NUL,       A_info_next_node,
01288        ESC, '\033', 'O', 'B', NUL,        A_info_next_node,
01289        ESC, '\033', '[', 'B', NUL,        A_info_next_node,
01290        ESC, SK_ESCAPE, SK_RIGHT_ARROW, NUL,      A_info_xref_item,
01291        ESC, '\033', 'O', 'C', NUL,        A_info_xref_item,
01292        ESC, '\033', '[', 'C', NUL,        A_info_xref_item,
01293        ESC, SK_ESCAPE, SK_LEFT_ARROW, NUL,       A_info_beginning_of_node,
01294        ESC, '\033', 'O', 'D', NUL,        A_info_beginning_of_node,
01295        ESC, '\033', '[', 'D', NUL,        A_info_beginning_of_node,
01296        CONTROL('x'), SK_ESCAPE, SK_DELETE, NUL,A_ea_backward_kill_line,
01297 };
01298 
01299 static unsigned char default_vi_like_ea_keys[] =
01300 {
01301        0,     /* suppress-default-keybindings flag */
01302        ESC, '1', NUL,                     A_info_add_digit_to_numeric_arg,
01303        ESC, '2', NUL,                     A_info_add_digit_to_numeric_arg,
01304        ESC, '3', NUL,                     A_info_add_digit_to_numeric_arg,
01305        ESC, '4', NUL,                     A_info_add_digit_to_numeric_arg,
01306        ESC, '5', NUL,                     A_info_add_digit_to_numeric_arg,
01307        ESC, '6', NUL,                     A_info_add_digit_to_numeric_arg,
01308        ESC, '7', NUL,                     A_info_add_digit_to_numeric_arg,
01309        ESC, '8', NUL,                     A_info_add_digit_to_numeric_arg,
01310        ESC, '9', NUL,                     A_info_add_digit_to_numeric_arg,
01311        ESC, '-', NUL,                     A_info_add_digit_to_numeric_arg,
01312        Meta('1'), NUL,                    A_info_add_digit_to_numeric_arg,
01313        Meta('2'), NUL,                    A_info_add_digit_to_numeric_arg,
01314        Meta('3'), NUL,                    A_info_add_digit_to_numeric_arg,
01315        Meta('4'), NUL,                    A_info_add_digit_to_numeric_arg,
01316        Meta('5'), NUL,                    A_info_add_digit_to_numeric_arg,
01317        Meta('6'), NUL,                    A_info_add_digit_to_numeric_arg,
01318        Meta('7'), NUL,                    A_info_add_digit_to_numeric_arg,
01319        Meta('8'), NUL,                    A_info_add_digit_to_numeric_arg,
01320        Meta('9'), NUL,                    A_info_add_digit_to_numeric_arg,
01321        Meta('-'), NUL,                    A_info_add_digit_to_numeric_arg,
01322        ESC, CONTROL('g'), NUL,            A_ea_abort,
01323        ESC, CONTROL('h'), NUL,            A_ea_backward_kill_word,
01324        ESC, CONTROL('v'), NUL,            A_ea_scroll_completions_window,
01325        ESC, '0', NUL,                     A_ea_beg_of_line,
01326        ESC, '$', NUL,                     A_ea_end_of_line,
01327        ESC, 'b', NUL,                     A_ea_backward_word,
01328        ESC, 'd', NUL,                     A_ea_kill_word,
01329        ESC, 'f', NUL,                     A_ea_forward_word,
01330        ESC, 'h', NUL,                     A_ea_forward,
01331        ESC, 'l', NUL,                     A_ea_backward,
01332        ESC, 'w', NUL,                     A_ea_forward_word,
01333        ESC, 'x', NUL,                     A_ea_delete,
01334        ESC, 'X', NUL,                     A_ea_kill_word,
01335        ESC, 'y', NUL,                     A_ea_yank_pop,
01336        ESC, '?', NUL,                     A_ea_possible_completions,
01337        ESC, TAB, NUL,                     A_ea_tab_insert,
01338        ESC, DEL, NUL,                     A_ea_kill_word,
01339        Meta(CONTROL('g')), NUL,    A_ea_abort,
01340        Meta(CONTROL('h')), NUL,    A_ea_backward_kill_word,
01341        Meta(CONTROL('v')), NUL,    A_ea_scroll_completions_window,
01342        Meta('0'), NUL,                    A_ea_beg_of_line,
01343        Meta('$'), NUL,                    A_ea_end_of_line,
01344        Meta('b'), NUL,                    A_ea_backward_word,
01345        Meta('d'), NUL,                    A_ea_kill_word,
01346        Meta('f'), NUL,                    A_ea_forward_word,
01347        Meta('h'), NUL,                    A_ea_forward,
01348        Meta('l'), NUL,                    A_ea_backward,
01349        Meta('w'), NUL,                    A_ea_forward_word,
01350        Meta('x'), NUL,                    A_ea_delete,
01351        Meta('X'), NUL,                    A_ea_kill_word,
01352        Meta('y'), NUL,                    A_ea_yank_pop,
01353        Meta('?'), NUL,                    A_ea_possible_completions,
01354        Meta(TAB), NUL,                    A_ea_tab_insert,
01355        Meta(DEL), NUL,                    A_ea_kill_word,
01356        CONTROL('a'), NUL,          A_ea_beg_of_line,
01357        CONTROL('b'), NUL,          A_ea_backward,
01358        CONTROL('d'), NUL,          A_ea_delete,
01359        CONTROL('e'), NUL,          A_ea_end_of_line,
01360        CONTROL('f'), NUL,          A_ea_forward,
01361        CONTROL('g'), NUL,          A_ea_abort,
01362        CONTROL('h'), NUL,          A_ea_rubout,
01363 /*     CONTROL('k') */
01364        SK_ESCAPE, SK_LITERAL, NUL, A_ea_kill_line,
01365        CONTROL('l'), NUL,          A_info_redraw_display,
01366        CONTROL('q'), NUL,          A_ea_quoted_insert,
01367        CONTROL('t'), NUL,          A_ea_transpose_chars,
01368        CONTROL('u'), NUL,          A_ea_abort,
01369        CONTROL('v'), NUL,          A_ea_quoted_insert,
01370        CONTROL('y'), NUL,          A_ea_yank,
01371        LFD, NUL,                   A_ea_newline,
01372        RET, NUL,                   A_ea_newline,
01373        SPC, NUL,                   A_ea_complete,
01374        TAB, NUL,                   A_ea_complete,
01375        '?', NUL,                   A_ea_possible_completions,
01376 #ifdef __MSDOS__
01377         /* PC users will lynch me if I don't give them their usual DEL
01378           effect...  */
01379        DEL, NUL,                   A_ea_delete,
01380 #else
01381        DEL, NUL,                   A_ea_rubout,
01382 #endif
01383        CONTROL('x'), 'o', NUL,            A_info_next_window,
01384        CONTROL('x'), DEL, NUL,            A_ea_backward_kill_line,
01385 
01386   /* Arrow key bindings for echo area keymaps.  It seems that some
01387      terminals do not match their termcap entries, so it's best to just
01388      define everything with both of the usual prefixes.  */
01389 
01390        SK_ESCAPE, SK_RIGHT_ARROW, NUL,           A_ea_forward,
01391        '\033', 'O', 'C', NUL,                    A_ea_forward,
01392        '\033', '[', 'C', NUL,                    A_ea_forward,
01393        SK_ESCAPE, SK_LEFT_ARROW, NUL,            A_ea_backward,
01394        '\033', 'O', 'D', NUL,                    A_ea_backward,
01395        '\033', '[', 'D', NUL,                    A_ea_backward,
01396        SK_ESCAPE, SK_HOME, NUL,           A_ea_beg_of_line,
01397        SK_ESCAPE, SK_END, NUL,                   A_ea_end_of_line,
01398 #ifdef __MSDOS__
01399        SK_ESCAPE, SK_DELETE, NUL,         A_ea_delete,
01400 #else
01401        SK_DELETE, SK_DELETE, NUL,         A_ea_rubout,
01402 #endif
01403        ESC, SK_ESCAPE, SK_RIGHT_ARROW, NUL,      A_ea_forward_word,
01404        ESC, '\033', 'O', 'C', NUL,        A_ea_forward_word,
01405        ESC, '\033', '[', 'C', NUL,        A_ea_forward_word,
01406        ESC, SK_ESCAPE, SK_LEFT_ARROW, NUL,       A_ea_backward_word,
01407        ESC, '\033', 'O', 'D', NUL,        A_ea_backward_word,
01408        ESC, '\033', '[', 'D', NUL,        A_ea_backward_word,
01409        ESC, SK_ESCAPE, SK_DELETE, NUL,           A_ea_kill_word,
01410        CONTROL('x'), SK_ESCAPE, SK_DELETE, NUL,A_ea_backward_kill_line,
01411 };
01412 
01413 static unsigned char *user_info_keys;
01414 static unsigned int user_info_keys_len;
01415 static unsigned char *user_ea_keys;
01416 static unsigned int user_ea_keys_len;
01417 static unsigned char *user_vars;
01418 static unsigned int user_vars_len;
01419 
01420 /*
01421  * Return the size of a file, or 0 if the size can't be determined.
01422  */
01423 static unsigned long
01424 filesize(int f)
01425 {
01426        long pos = lseek(f, 0L, SEEK_CUR);
01427        long sz = -1L;
01428        if (pos != -1L)
01429        {
01430               sz = lseek(f, 0L, SEEK_END);
01431               lseek(f, pos, SEEK_SET);
01432        }
01433        return sz == -1L ? 0L : sz;
01434 }
01435 
01436 /* Get an integer from a infokey file.
01437    Integers are stored as two bytes, low order first, in radix INFOKEY_RADIX.
01438  */
01439 static int
01440 getint(unsigned char **sp)
01441 {
01442        int n;
01443 
01444        if ( !((*sp)[0] < INFOKEY_RADIX && (*sp)[1] < INFOKEY_RADIX) )
01445               return -1;
01446        n = (*sp)[0] + (*sp)[1] * INFOKEY_RADIX;
01447        *sp += 2;
01448        return n;
01449 }
01450 
01451 
01452 /* Fetch the contents of the standard infokey file "$HOME/.info".  Return
01453    true if ok, false if not.  */
01454 static int
01455 fetch_user_maps(void)
01456 {
01457        char *filename = NULL;
01458        char *homedir;
01459        int f;
01460        unsigned char *buf;
01461        unsigned long len;
01462        long nread;
01463        unsigned char *p;
01464        int n;
01465 
01466        /* Find and open file. */
01467        if ((filename = getenv("INFOKEY")) != NULL)
01468               filename = xstrdup(filename);
01469        else if ((homedir = getenv("HOME")) != NULL)
01470        {
01471               filename = xmalloc(strlen(homedir) + 2 + strlen(INFOKEY_FILE));
01472               strcpy(filename, homedir);
01473               strcat(filename, "/");
01474               strcat(filename, INFOKEY_FILE);
01475        }
01476 #ifdef __MSDOS__
01477        /* Poor baby, she doesn't have a HOME...  */
01478        else
01479               filename = xstrdup(INFOKEY_FILE); /* try current directory */
01480 #endif
01481        if (filename == NULL || (f = open(filename, O_RDONLY)) == (-1))
01482        {
01483               if (filename && errno != ENOENT)
01484               {
01485                      info_error(filesys_error_string(filename, errno),
01486                             NULL, NULL);
01487                      free(filename);
01488               }
01489               return 0;
01490        }
01491        SET_BINARY (f);
01492 
01493        /* Ensure that the file is a reasonable size. */
01494        len = filesize(f);
01495        if (len < INFOKEY_NMAGIC + 2 || len > 100 * 1024)
01496        {
01497               /* Bad file (a valid file must have at least 9 chars, and
01498                  more than 100 KB is a problem). */
01499               if (len < INFOKEY_NMAGIC + 2)
01500                      info_error((char *) _("Ignoring invalid infokey file `%s' - too small"),
01501                                filename, NULL);
01502               else
01503                      info_error((char *) _("Ignoring invalid infokey file `%s' - too big"),
01504                                filename, NULL);
01505               close(f);
01506               free(filename);
01507               return 0;
01508        }
01509 
01510        /* Read the file into a buffer. */
01511        buf = (unsigned char *)xmalloc((int)len);
01512        nread = read(f, buf, (unsigned int) len);
01513        close(f);
01514        if ((unsigned int) nread != len)
01515        {
01516               info_error((char *) _("Error reading infokey file `%s' - short read"),
01517                     filename, NULL);
01518               free(buf);
01519               free(filename);
01520               return 0;
01521        }
01522 
01523        /* Check the header, trailer, and version of the file to increase
01524           our confidence that the contents are valid.  */
01525        if (   buf[0] != INFOKEY_MAGIC_S0
01526               || buf[1] != INFOKEY_MAGIC_S1
01527               || buf[2] != INFOKEY_MAGIC_S2
01528               || buf[3] != INFOKEY_MAGIC_S3
01529               || buf[len - 4] != INFOKEY_MAGIC_E0
01530               || buf[len - 3] != INFOKEY_MAGIC_E1
01531               || buf[len - 2] != INFOKEY_MAGIC_E2
01532               || buf[len - 1] != INFOKEY_MAGIC_E3
01533        )
01534        {
01535               info_error((char *) _("Invalid infokey file `%s' (bad magic numbers) -- run infokey to update it"),
01536                     filename, NULL);
01537               free(filename);
01538               return 0;
01539        }
01540        if (len < INFOKEY_NMAGIC + strlen(VERSION) + 1
01541             || strcmp(VERSION, (char *) (buf + 4)) != 0)
01542        {
01543               info_error
01544                   ((char *) _("Your infokey file `%s' is out of date -- run infokey to update it"),
01545                     filename, NULL);
01546               free(filename);
01547               return 0;
01548        }
01549 
01550        /* Extract the pieces.  */
01551        for (p = buf + 4 + strlen(VERSION) + 1;
01552              (unsigned int) (p - buf) < len - 4;
01553              p += n)
01554        {
01555               int s = *p++;
01556 
01557               n = getint(&p);
01558               if (n < 0 || (unsigned int) n > len - 4 - (p - buf))
01559               {
01560                      info_error((char *) _("Invalid infokey file `%s' (bad section length) -- run infokey to update it"),
01561                             filename, NULL);
01562                      free(filename);
01563                      return 0;
01564               }
01565 
01566               switch (s)
01567               {
01568               case INFOKEY_SECTION_INFO:
01569                      user_info_keys = p;
01570                      user_info_keys_len = n;
01571                      break;
01572               case INFOKEY_SECTION_EA:
01573                      user_ea_keys = p;
01574                      user_ea_keys_len = n;
01575                      break;
01576               case INFOKEY_SECTION_VAR:
01577                      user_vars = p;
01578                      user_vars_len = n;
01579                      break;
01580               default:
01581                      info_error((char *) _("Invalid infokey file `%s' (bad section code) -- run infokey to update it"),
01582                             filename, NULL);
01583                      free(filename);
01584                      return 0;
01585               }
01586        }
01587 
01588        free(filename);
01589        return 1;
01590 }
01591 
01592 /* Decode special key sequences from the infokey file.  Return zero
01593    if the key sequence includes special keys which the terminal
01594    doesn't define.
01595  */
01596 static int
01597 decode_keys(unsigned char *src, unsigned int slen,
01598     unsigned char *dst, unsigned int dlen)
01599 {
01600        unsigned char *s = src;
01601        unsigned char *d = dst;
01602 
01603 #define To_dst(c) do { \
01604   if ((unsigned int) (d - dst) < dlen) *d++ = (c); \
01605 } while (0)
01606 
01607        while ((unsigned int) (s - src) < slen)
01608        {
01609               unsigned char c = ISMETA(*s) ? UNMETA(*s) : *s;
01610 
01611               if (c == SK_ESCAPE)
01612               {
01613                      char *t;
01614                      static char lit[] = { SK_ESCAPE, NUL };
01615 
01616                      switch ((unsigned int) (s + 1 - src) < slen ? s[1] : '\0')
01617                      {
01618                      case SK_RIGHT_ARROW: t = term_kr; break;
01619                      case SK_LEFT_ARROW:  t = term_kl; break;
01620                      case SK_UP_ARROW:    t = term_ku; break;
01621                      case SK_DOWN_ARROW:  t = term_kd; break;
01622                      case SK_PAGE_UP:     t = term_kP; break;
01623                      case SK_PAGE_DOWN:   t = term_kN; break;
01624                      case SK_HOME:        t = term_kh; break;
01625                      case SK_END:         t = term_ke; break;
01626                      case SK_DELETE:             t = term_kx; break;
01627                      case SK_INSERT:             t = term_ki; break;
01628                      case SK_LITERAL:
01629                      default:             t = lit; break;
01630                      }
01631                      if (t == NULL)
01632                             return 0;
01633                      while (*t)
01634                             To_dst(ISMETA(*s) ? Meta(*t++) : *t++);
01635                      s += 2;
01636               }
01637               else
01638               {
01639                      if (ISMETA(*s))
01640                             To_dst(Meta(*s++));
01641                      else
01642                             To_dst(*s++);
01643               }
01644        }
01645 
01646        To_dst('\0');
01647 
01648        return 1;
01649 
01650 #undef To_dst
01651 
01652 }
01653 
01654 /* Convert an infokey file section to keymap bindings.  Return false if
01655    the default bindings are to be suppressed.  */
01656 static int
01657 section_to_keymaps(Keymap map, unsigned char *table, unsigned int len)
01658 {
01659        int stop;
01660        unsigned char *p;
01661        unsigned char *seq = NULL;
01662        unsigned int seqlen = 0;
01663        enum { getseq, gotseq, getaction } state = getseq;
01664 
01665        stop = len > 0 ? table[0] : 0;
01666 
01667        for (p = table + 1; (unsigned int) (p - table) < len; p++)
01668        {
01669               switch (state)
01670               {
01671               case getseq:
01672                      if (*p)
01673                      {
01674                             seq = p;
01675                             state = gotseq;
01676                      }
01677                      break;
01678 
01679               case gotseq:
01680                      if (!*p)
01681                      {
01682                             seqlen = p - seq;
01683                             state = getaction;
01684                      }
01685                      break;
01686 
01687               case getaction:
01688                      {
01689                             unsigned int action = *p;
01690                             unsigned char keyseq[256];
01691                             KEYMAP_ENTRY ke;
01692 
01693                             state = getseq;
01694                             /* If decode_keys returns zero, it
01695                                means that seq includes keys which
01696                                the terminal doesn't support, like
01697                                PageDown.  In that case, don't bind
01698                                the key sequence.  */
01699                             if (decode_keys(seq, seqlen, keyseq,
01700                                           sizeof keyseq))
01701                             {
01702                                    keyseq[sizeof keyseq - 1] = '\0';
01703                                    ke.type = ISFUNC;
01704                                    ke.function =
01705                                      action < A_NCOMMANDS
01706                                      ? &function_doc_array[action]
01707                                      : NULL;
01708                                    keymap_bind_keyseq(map,
01709                                             (const char *) keyseq, &ke);
01710                             }
01711                      }
01712                      break;
01713               }
01714        }
01715        if (state != getseq)
01716               info_error((char *) _("Bad data in infokey file -- some key bindings ignored"),
01717                     NULL, NULL);
01718        return !stop;
01719 }
01720 
01721 /* Convert an infokey file section to variable settings.
01722  */
01723 static void
01724 section_to_vars(unsigned char *table, unsigned int len)
01725 {
01726        enum { getvar, gotvar, getval, gotval } state = getvar;
01727        unsigned char *var = NULL;
01728        unsigned char *val = NULL;
01729        unsigned char *p;
01730 
01731        for (p = table; (unsigned int) (p - table) < len; p++)
01732          {
01733            switch (state)
01734              {
01735              case getvar:
01736               if (*p)
01737                 {
01738                   var = p;
01739                   state = gotvar;
01740                 }
01741               break;
01742 
01743              case gotvar:
01744               if (!*p)
01745                 state = getval;
01746               break;
01747 
01748              case getval:
01749               if (*p)
01750                 {
01751                   val = p;
01752                   state = gotval;
01753                 }
01754               break;
01755 
01756              case gotval:
01757               if (!*p)
01758                 {
01759                   set_variable_to_value((char *) var, (char *) val);
01760                   state = getvar;
01761                 }
01762               break;
01763              }
01764          }
01765       if (state != getvar)
01766        info_error((char *) _("Bad data in infokey file -- some var settings ignored"),
01767             NULL, NULL);
01768 }
01769 
01770 void
01771 initialize_info_keymaps (void)
01772 {
01773   int i;
01774   int suppress_info_default_bindings = 0;
01775   int suppress_ea_default_bindings = 0;
01776 
01777   if (!info_keymap)
01778     {
01779       info_keymap = keymap_make_keymap ();
01780       echo_area_keymap = keymap_make_keymap ();
01781     }
01782 
01783   /* Bind the echo area insert routines. */
01784   for (i = 0; i < 256; i++)
01785     if (isprint (i))
01786       echo_area_keymap[i].function = InfoCmd(ea_insert);
01787 
01788   /* Get user-defined keys and variables.  */
01789   if (fetch_user_maps())
01790     {
01791       if (user_info_keys_len && user_info_keys[0])
01792        suppress_info_default_bindings = 1;
01793       if (user_ea_keys_len && user_ea_keys[0])
01794        suppress_ea_default_bindings = 1;
01795     }
01796 
01797   /* Apply the default bindings, unless the user says to suppress
01798      them.  */
01799   if (vi_keys_p)
01800     {
01801       if (!suppress_info_default_bindings)
01802        section_to_keymaps(info_keymap, default_vi_like_info_keys,
01803                         sizeof(default_vi_like_info_keys));
01804       if (!suppress_ea_default_bindings)
01805          section_to_keymaps(echo_area_keymap, default_vi_like_ea_keys,
01806                           sizeof(default_vi_like_ea_keys));
01807     }
01808   else
01809     {
01810       if (!suppress_info_default_bindings)
01811        section_to_keymaps(info_keymap, default_emacs_like_info_keys,
01812                         sizeof(default_emacs_like_info_keys));
01813       if (!suppress_ea_default_bindings)
01814          section_to_keymaps(echo_area_keymap, default_emacs_like_ea_keys,
01815                           sizeof(default_emacs_like_ea_keys));
01816     }
01817 
01818   /* If the user specified custom bindings, apply them on top of the
01819      default ones.  */
01820   if (user_info_keys_len)
01821     section_to_keymaps(info_keymap, user_info_keys, user_info_keys_len);
01822 
01823   if (user_ea_keys_len)
01824     section_to_keymaps(echo_area_keymap, user_ea_keys, user_ea_keys_len);
01825 
01826   if (user_vars_len)
01827     section_to_vars(user_vars, user_vars_len);
01828 }
01829 
01830 #endif /* defined(INFOKEY) */
01831 /* vim: set sw=2 cino={1s>2sn-s^-se-s: */