Change the kernel dev_t, representing a pointer to a specinfo structure,
[dragonfly.git] / contrib / texinfo-4 / info / infomap.c
1 /* infomap.c -- keymaps for Info.
2    $Id: infomap.c,v 1.10 2004/07/30 20:43:40 karl Exp $
3
4    Copyright (C) 1993, 1997, 1998, 1999, 2001, 2002, 2003, 2004 Free Software
5    Foundation, Inc.
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2, or (at your option)
10    any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20
21    Written by Brian Fox (bfox@ai.mit.edu). */
22
23 #include "info.h"
24 #include "infomap.h"
25 #include "funs.h"
26 #include "terminal.h"
27
28 #if defined(INFOKEY)
29 #include "infokey.h"
30 #include "variables.h"
31 #endif /* INFOKEY */
32
33 static int keymap_bind_keyseq (Keymap map, const char *keyseq,
34     KEYMAP_ENTRY *keyentry);
35
36 /* Return a new keymap which has all the uppercase letters mapped to run
37    the function info_do_lowercase_version (). */
38 Keymap
39 keymap_make_keymap (void)
40 {
41   int i;
42   Keymap keymap;
43
44   keymap = (Keymap)xmalloc (256 * sizeof (KEYMAP_ENTRY));
45
46   for (i = 0; i < 256; i++)
47     {
48       keymap[i].type = ISFUNC;
49       keymap[i].function = (InfoCommand *)NULL;
50     }
51
52   for (i = 'A'; i < ('Z' + 1); i++)
53     {
54       keymap[i].type = ISFUNC;
55 #if defined(INFOKEY)
56       keymap[Meta(i)].type = ISFUNC;
57       keymap[Meta(i)].function =
58 #endif /* INFOKEY */
59       keymap[i].function = InfoCmd(info_do_lowercase_version);
60     }
61
62   return (keymap);
63 }
64
65 #if defined(INFOKEY)
66 static FUNCTION_KEYSEQ *
67 find_function_keyseq (Keymap map, int c, Keymap rootmap)
68 {
69   FUNCTION_KEYSEQ *k;
70
71   if (map[c].type != ISFUNC)
72     abort();
73   if (map[c].function == NULL)
74     return NULL;
75   for (k = map[c].function->keys; k; k = k->next)
76     {
77       const unsigned char *p;
78       Keymap m = rootmap;
79       if (k->map != rootmap)
80         continue;
81       for (p = (unsigned char *) k->keyseq; *p && m[*p].type == ISKMAP; p++)
82         m = (Keymap)m[*p].function;
83       if (*p != c || p[1])
84         continue;
85       if (m[*p].type != ISFUNC)
86         abort ();
87       break;
88     }
89   return k;
90 }
91
92 static void
93 add_function_keyseq (InfoCommand *function,
94     const char *keyseq, Keymap rootmap)
95 {
96   FUNCTION_KEYSEQ *ks;
97
98   if (function == NULL ||
99       function == InfoCmd(info_do_lowercase_version) ||
100       function == InfoCmd(ea_insert))
101     return;
102   ks = (FUNCTION_KEYSEQ *)xmalloc (sizeof(FUNCTION_KEYSEQ));
103   ks->next = function->keys;
104   ks->map = rootmap;
105   ks->keyseq = xstrdup(keyseq);
106   function->keys = ks;
107 }
108
109 static void
110 remove_function_keyseq (InfoCommand *function,
111     const char *keyseq, Keymap rootmap)
112 {
113
114   FUNCTION_KEYSEQ *k, *kp;
115
116   if (function == NULL ||
117       function == InfoCmd(info_do_lowercase_version) ||
118       function == InfoCmd(ea_insert))
119     return;
120   for (kp = NULL, k = function->keys; k; kp = k, k = k->next)
121     if (k->map == rootmap && strcmp(k->keyseq, keyseq) == 0)
122       break;
123   if (!k)
124     abort ();
125   if (kp)
126     kp->next = k->next;
127   else
128     function->keys = k->next;
129 }
130 #endif /* INFOKEY */
131
132 /* Return a new keymap which is a copy of MAP. */
133 Keymap
134 keymap_copy_keymap (Keymap map, Keymap rootmap, Keymap newroot)
135 {
136   int i;
137   Keymap keymap;
138 #if defined(INFOKEY)
139   FUNCTION_KEYSEQ *ks;
140 #endif /* INFOKEY */
141
142   keymap = keymap_make_keymap ();
143   if (!newroot)
144     newroot = keymap;
145
146   for (i = 0; i < 256; i++)
147     {
148       keymap[i].type = map[i].type;
149       switch (map[i].type)
150         {
151         case ISFUNC:
152           keymap[i].function = map[i].function;
153 #if defined(INFOKEY)
154           ks = find_function_keyseq (map, i, rootmap);
155           if (ks)
156             add_function_keyseq(map[i].function, ks->keyseq, newroot);
157 #endif /* INFOKEY */
158           break;
159         case ISKMAP:
160           keymap[i].function = (InfoCommand *)keymap_copy_keymap
161             ((Keymap)map[i].function, rootmap, NULL);
162           break;
163         }
164     }
165   return (keymap);
166 }
167
168 /* Free the keymap and its descendants. */
169 void
170 keymap_discard_keymap (Keymap map, Keymap rootmap)
171 {
172   int i;
173
174   if (!map)
175     return;
176   if (!rootmap)
177     rootmap = map;
178
179   for (i = 0; i < 256; i++)
180     {
181 #if defined(INFOKEY)
182       FUNCTION_KEYSEQ *ks;
183 #endif /* INFOKEY */
184       switch (map[i].type)
185         {
186         case ISFUNC:
187 #if defined(INFOKEY)
188           ks = find_function_keyseq(map, i, rootmap);
189           if (ks)
190             remove_function_keyseq (map[i].function, ks->keyseq, rootmap);
191 #endif /* INFOKEY */
192           break;
193
194         case ISKMAP:
195           keymap_discard_keymap ((Keymap)map[i].function, rootmap);
196           break;
197
198         }
199     }
200   free(map);
201 }
202
203 /* Conditionally bind key sequence. */
204 static int
205 keymap_bind_keyseq (Keymap map,
206     const char *keyseq, KEYMAP_ENTRY *keyentry)
207 {
208   Keymap m = map;
209   const unsigned char *s = (unsigned char *) keyseq;
210   int c;
211
212   if (s == NULL || *s == '\0') return 0;
213
214   while ((c = *s++) != '\0')
215     {
216 #if defined(INFOKEY)
217       FUNCTION_KEYSEQ *ks;
218 #endif /* INFOKEY */
219       switch (m[c].type)
220         {
221         case ISFUNC:
222 #if defined(INFOKEY)
223           ks = find_function_keyseq(m, c, map);
224           if (ks)
225             remove_function_keyseq (m[c].function, ks->keyseq, map);
226 #else /* !INFOKEY */
227           if (!(m[c].function == NULL || (
228                 m != map &&
229                 m[c].function == InfoCmd(info_do_lowercase_version))
230               ))
231             return 0;
232 #endif /* !INFOKEY */
233
234           if (*s != '\0')
235             {
236               m[c].type = ISKMAP;
237               /* Here we are casting the Keymap pointer returned from
238                  keymap_make_keymap to an InfoCommand pointer.  Ugh.
239                  This makes the `function' structure garbage
240                  if it's actually interpreted as an InfoCommand.
241                  Should really be using a union, and taking steps to
242                  avoid the possible error.  */
243               m[c].function = (InfoCommand *)keymap_make_keymap ();
244             }
245           break;
246
247         case ISKMAP:
248 #if defined(INFOKEY)
249           if (*s == '\0')
250             keymap_discard_keymap ((Keymap)m[c].function, map);
251 #else /* !INFOKEY */
252           if (*s == '\0')
253             return 0;
254 #endif
255           break;
256         }
257       if (*s != '\0')
258         {
259           m = (Keymap)m[c].function;
260         }
261       else
262         {
263 #if defined(INFOKEY)
264           add_function_keyseq (keyentry->function, keyseq, map);
265 #endif /* INFOKEY */
266           m[c] = *keyentry;
267         }
268     }
269
270   return 1;
271 }
272
273 /* Initialize the standard info keymaps. */
274
275 Keymap info_keymap = NULL;
276 Keymap echo_area_keymap = NULL;
277
278 #if !defined(INFOKEY)
279
280 static void
281 initialize_emacs_like_keymaps ()
282 {
283   int i;
284   Keymap map;
285
286   if (!info_keymap)
287     {
288       info_keymap = keymap_make_keymap ();
289       echo_area_keymap = keymap_make_keymap ();
290     }
291
292   info_keymap[ESC].type = ISKMAP;
293   info_keymap[ESC].function = (InfoCommand *)keymap_make_keymap ();
294   info_keymap[Control ('x')].type = ISKMAP;
295   info_keymap[Control ('x')].function = (InfoCommand *)keymap_make_keymap ();
296
297   /* Bind the echo area insert routines.  Let's make all characters
298      insertable by default, regardless of which character set we might
299      be using.  */
300   for (i = 0; i < 256; i++)
301     echo_area_keymap[i].function = ea_insert;
302
303   echo_area_keymap[ESC].type = ISKMAP;
304   echo_area_keymap[ESC].function = (InfoCommand *) keymap_make_keymap ();
305   echo_area_keymap[Control ('x')].type = ISKMAP;
306   echo_area_keymap[Control ('x')].function
307     = (InfoCommand *) keymap_make_keymap ();
308
309   /* Bind numeric arg functions for both echo area and info window maps. */
310   for (i = '0'; i < '9' + 1; i++)
311     {
312       ((Keymap) info_keymap[ESC].function)[i].function
313         = ((Keymap) echo_area_keymap[ESC].function)[i].function
314         = info_add_digit_to_numeric_arg;
315     }
316   ((Keymap) info_keymap[ESC].function)['-'].function =
317     ((Keymap) echo_area_keymap[ESC].function)['-'].function =
318       info_add_digit_to_numeric_arg;
319
320   info_keymap['-'].function = info_add_digit_to_numeric_arg;
321
322   /* Bind the echo area routines. */
323   map = echo_area_keymap;
324
325   map[Control ('a')].function = ea_beg_of_line;
326   map[Control ('b')].function = ea_backward;
327   map[Control ('d')].function = ea_delete;
328   map[Control ('e')].function = ea_end_of_line;
329   map[Control ('f')].function = ea_forward;
330   map[Control ('g')].function = ea_abort;
331   map[Control ('h')].function = ea_rubout;
332   map[Control ('k')].function = ea_kill_line;
333   map[Control ('l')].function = info_redraw_display;
334   map[Control ('q')].function = ea_quoted_insert;
335   map[Control ('t')].function = ea_transpose_chars;
336   map[Control ('u')].function = info_universal_argument;
337   map[Control ('y')].function = ea_yank;
338
339   map[LFD].function = ea_newline;
340   map[RET].function = ea_newline;
341   map[SPC].function = ea_complete;
342   map[TAB].function = ea_complete;
343   map['?'].function = ea_possible_completions;
344 #ifdef __MSDOS__
345   /* PC users will lynch me if I don't give them their usual DEL effect...  */
346   map[DEL].function = ea_delete;
347 #else
348   map[DEL].function = ea_rubout;
349 #endif
350
351   /* Bind the echo area ESC keymap. */
352   map = (Keymap)echo_area_keymap[ESC].function;
353
354   map[Control ('g')].function = ea_abort;
355   map[Control ('v')].function = ea_scroll_completions_window;
356   map['b'].function = ea_backward_word;
357   map['d'].function = ea_kill_word;
358   map['f'].function = ea_forward_word;
359 #if defined (NAMED_FUNCTIONS)
360   /* map['x'].function = info_execute_command; */
361 #endif /* NAMED_FUNCTIONS */
362   map['y'].function = ea_yank_pop;
363   map['?'].function = ea_possible_completions;
364   map[TAB].function = ea_tab_insert;
365   map[DEL].function = ea_backward_kill_word;
366
367   /* Bind the echo area Control-x keymap. */
368   map = (Keymap)echo_area_keymap[Control ('x')].function;
369
370   map['o'].function = info_next_window;
371   map[DEL].function = ea_backward_kill_line;
372
373   /* Arrow key bindings for echo area keymaps.  It seems that some
374      terminals do not match their termcap entries, so it's best to just
375      define everything with both of the usual prefixes.  */
376   map = echo_area_keymap;
377   keymap_bind_keyseq (map, term_ku, &map[Control ('p')]); /* up */
378   keymap_bind_keyseq (map, "\033OA", &map[Control ('p')]);
379   keymap_bind_keyseq (map, "\033[A", &map[Control ('p')]);
380   keymap_bind_keyseq (map, term_kd, &map[Control ('n')]); /* down */
381   keymap_bind_keyseq (map, "\033OB", &map[Control ('n')]);
382   keymap_bind_keyseq (map, "\033[B", &map[Control ('n')]);
383   keymap_bind_keyseq (map, term_kr, &map[Control ('f')]); /* right */
384   keymap_bind_keyseq (map, "\033OC", &map[Control ('f')]);
385   keymap_bind_keyseq (map, "\033[C", &map[Control ('f')]);
386   keymap_bind_keyseq (map, term_kl, &map[Control ('b')]); /* left */
387   keymap_bind_keyseq (map, "\033OD", &map[Control ('b')]);
388   keymap_bind_keyseq (map, "\033[D", &map[Control ('b')]);
389   keymap_bind_keyseq (map, term_kD, &map[DEL]); /* delete */
390   keymap_bind_keyseq (map, term_kh, &map[Control ('a')]); /* home */
391   keymap_bind_keyseq (map, term_ke, &map[Control ('e')]); /* end */
392
393   map = (Keymap)echo_area_keymap[ESC].function;
394   keymap_bind_keyseq (map, term_kl, &map['b']); /* left */
395   keymap_bind_keyseq (map, "\033OA", &map['b']);
396   keymap_bind_keyseq (map, "\033[A", &map['b']);
397   keymap_bind_keyseq (map, term_kr, &map['f']); /* right */
398   keymap_bind_keyseq (map, "\033OB", &map['f']);
399   keymap_bind_keyseq (map, "\033[B", &map['f']);
400   keymap_bind_keyseq (map, term_kD, &map[DEL]); /* delete */
401
402   map = (Keymap)echo_area_keymap[Control ('x')].function;
403   keymap_bind_keyseq (map, term_kD, &map[DEL]); /* delete */
404
405   /* Bind commands for Info window keymaps. */
406   map = info_keymap;
407   map[TAB].function = info_move_to_next_xref;
408   map[LFD].function = info_select_reference_this_line;
409   map[RET].function = info_select_reference_this_line;
410   map[SPC].function = info_scroll_forward;
411   map[Control ('a')].function = info_beginning_of_line;
412   map[Control ('b')].function = info_backward_char;
413   map[Control ('e')].function = info_end_of_line;
414   map[Control ('f')].function = info_forward_char;
415   map[Control ('g')].function = info_abort_key;
416   map[Control ('h')].function = info_get_help_window;
417   map[Control ('l')].function = info_redraw_display;
418   map[Control ('n')].function = info_next_line;
419   map[Control ('p')].function = info_prev_line;
420   map[Control ('r')].function = isearch_backward;
421   map[Control ('s')].function = isearch_forward;
422   map[Control ('u')].function = info_universal_argument;
423   map[Control ('v')].function = info_scroll_forward_page_only;
424   map[','].function = info_next_index_match;
425   map['/'].function = info_search;
426
427   for (i = '1'; i < '9' + 1; i++)
428     map[i].function = info_menu_digit;
429   map['0'].function = info_last_menu_item;
430
431   map['<'].function = info_first_node;
432   map['>'].function = info_last_node;
433   map['?'].function = info_get_help_window;
434   map['['].function = info_global_prev_node;
435   map[']'].function = info_global_next_node;
436
437   map['b'].function = info_beginning_of_node;
438   map['d'].function = info_dir_node;
439   map['e'].function = info_end_of_node;
440   map['f'].function = info_xref_item;
441   map['g'].function = info_goto_node;
442   map['G'].function = info_menu_sequence;
443   map['h'].function = info_get_info_help_node;
444   map['i'].function = info_index_search;
445   map['I'].function = info_goto_invocation_node;
446   map['l'].function = info_history_node;
447   map['m'].function = info_menu_item;
448   map['n'].function = info_next_node;
449   map['O'].function = info_goto_invocation_node;
450   map['p'].function = info_prev_node;
451   map['q'].function = info_quit;
452   map['r'].function = info_xref_item;
453   map['s'].function = info_search;
454   map['S'].function = info_search_case_sensitively;
455   map['t'].function = info_top_node;
456   map['u'].function = info_up_node;
457   map[DEL].function = info_scroll_backward;
458
459   /* Bind members in the ESC map for Info windows. */
460   map = (Keymap)info_keymap[ESC].function;
461   map[Control ('f')].function = info_show_footnotes;
462   map[Control ('g')].function = info_abort_key;
463   map[TAB].function = info_move_to_prev_xref;
464   map[Control ('v')].function = info_scroll_other_window;
465   map['<'].function = info_beginning_of_node;
466   map['>'].function = info_end_of_node;
467   map['b'].function = info_backward_word;
468   map['f'].function = info_forward_word;
469   map['r'].function = info_move_to_window_line;
470   map['v'].function = info_scroll_backward_page_only;
471 #if defined (NAMED_FUNCTIONS)
472   map['x'].function = info_execute_command;
473 #endif /* NAMED_FUNCTIONS */
474   map[DEL].function = info_scroll_other_window_backward;
475
476   /* Bind members in the Control-X map for Info windows. */
477   map = (Keymap)info_keymap[Control ('x')].function;
478
479   map[Control ('b')].function = list_visited_nodes;
480   map[Control ('c')].function = info_quit;
481   map[Control ('f')].function = info_view_file;
482   map[Control ('g')].function = info_abort_key;
483   map[Control ('v')].function = info_view_file;
484   map['0'].function = info_delete_window;
485   map['1'].function = info_keep_one_window;
486   map['2'].function = info_split_window;
487   map['^'].function = info_grow_window;
488   map['b'].function = select_visited_node;
489   map['k'].function = info_kill_node;
490   map['n'].function = info_search_next;
491   map['N'].function = info_search_previous;
492   map['o'].function = info_next_window;
493   map['t'].function = info_tile_windows;
494   map['w'].function = info_toggle_wrap;
495
496   /* Arrow key bindings for Info windows keymap. */
497   map = info_keymap;
498   keymap_bind_keyseq (map, term_kN, &map[Control ('v')]); /* pagedown */
499   keymap_bind_keyseq (map, term_ku, &map[Control ('p')]); /* up */
500   keymap_bind_keyseq (map, "\033OA", &map[Control ('p')]);
501   keymap_bind_keyseq (map, "\033[A", &map[Control ('p')]);
502   keymap_bind_keyseq (map, term_kd, &map[Control ('n')]); /* down */
503   keymap_bind_keyseq (map, "\033OB", &map[Control ('n')]);
504   keymap_bind_keyseq (map, "\033[B", &map[Control ('n')]);
505   keymap_bind_keyseq (map, term_kr, &map[Control ('f')]); /* right */
506   keymap_bind_keyseq (map, "\033OC", &map[Control ('f')]);
507   keymap_bind_keyseq (map, "\033[C", &map[Control ('f')]);
508   keymap_bind_keyseq (map, term_kl, &map[Control ('b')]); /* left */
509   keymap_bind_keyseq (map, "\033OD", &map[Control ('b')]);
510   keymap_bind_keyseq (map, "\033[D", &map[Control ('b')]);
511   keymap_bind_keyseq (map, term_kh, &map['b']); /* home */
512   keymap_bind_keyseq (map, term_ke, &map['e']); /* end */
513   keymap_bind_keyseq (map, term_kD, &map[DEL]); /* delete */
514
515   map = (Keymap)info_keymap[ESC].function;
516   keymap_bind_keyseq (map, term_kl, &map['b']); /* left */
517   keymap_bind_keyseq (map, "\033OA", &map['b']);
518   keymap_bind_keyseq (map, "\033[A", &map['b']);
519   keymap_bind_keyseq (map, term_kr, &map['f']); /* right */
520   keymap_bind_keyseq (map, "\033OB", &map['f']);
521   keymap_bind_keyseq (map, "\033[B", &map['f']);
522   keymap_bind_keyseq (map, term_kN, &map[Control ('v')]); /* pagedown */
523   keymap_bind_keyseq (map, term_kP, &map[DEL]); /* pageup */
524   keymap_bind_keyseq (map, term_kD, &map[DEL]); /* delete */
525
526   /* The alternative to this definition of a `main map' key in the
527      `ESC map' section, is something like:
528     keymap_bind_keyseq (map, term_kP, &((KeyMap)map[ESC].function).map['v']);
529   */
530   keymap_bind_keyseq (info_keymap/*sic*/, term_kP, &map['v']); /* pageup */
531 }
532
533 static void
534 initialize_vi_like_keymaps ()
535 {
536   int i;
537   Keymap map;
538
539   if (!info_keymap)
540     {
541       info_keymap = keymap_make_keymap ();
542       echo_area_keymap = keymap_make_keymap ();
543     }
544
545   info_keymap[ESC].type = ISKMAP;
546   info_keymap[ESC].function = (InfoCommand *)keymap_make_keymap ();
547   info_keymap[Control ('x')].type = ISKMAP;
548   info_keymap[Control ('x')].function = (InfoCommand *)keymap_make_keymap ();
549
550   /* Bind the echo area insert routines. */
551   for (i = 0; i < 256; i++)
552     echo_area_keymap[i].function = ea_insert;
553
554   echo_area_keymap[ESC].type = ISKMAP;
555   echo_area_keymap[ESC].function = (InfoCommand *)keymap_make_keymap ();
556   echo_area_keymap[Control ('x')].type = ISKMAP;
557   echo_area_keymap[Control ('x')].function =
558     (InfoCommand *)keymap_make_keymap ();
559
560   /* Bind numeric arg functions for both echo area and info window maps. */
561   for (i = '0'; i < '9' + 1; i++)
562     {
563       info_keymap[i].function =
564         ((Keymap) echo_area_keymap[ESC].function)[i].function =
565         info_add_digit_to_numeric_arg;
566     }
567   info_keymap['-'].function =
568     ((Keymap) echo_area_keymap[ESC].function)['-'].function =
569       info_add_digit_to_numeric_arg;
570
571   /* Bind the echo area routines. */
572   map = echo_area_keymap;
573
574   map[Control ('a')].function = ea_beg_of_line;
575   map[Control ('b')].function = ea_backward;
576   map[Control ('d')].function = ea_delete;
577   map[Control ('e')].function = ea_end_of_line;
578   map[Control ('f')].function = ea_forward;
579   map[Control ('g')].function = ea_abort;
580   map[Control ('h')].function = ea_rubout;
581   map[Control ('k')].function = ea_kill_line;
582   map[Control ('l')].function = info_redraw_display;
583   map[Control ('q')].function = ea_quoted_insert;
584   map[Control ('t')].function = ea_transpose_chars;
585   map[Control ('u')].function = ea_abort;
586   map[Control ('v')].function = ea_quoted_insert;
587   map[Control ('y')].function = ea_yank;
588
589   map[LFD].function = ea_newline;
590   map[RET].function = ea_newline;
591   map[SPC].function = ea_complete;
592   map[TAB].function = ea_complete;
593   map['?'].function = ea_possible_completions;
594 #ifdef __MSDOS__
595   /* PC users will lynch me if I don't give them their usual DEL effect...  */
596   map[DEL].function = ea_delete;
597 #else
598   map[DEL].function = ea_rubout;
599 #endif
600
601   /* Bind the echo area ESC keymap. */
602   map = (Keymap)echo_area_keymap[ESC].function;
603
604   map[Control ('g')].function = ea_abort;
605   map[Control ('h')].function = ea_backward_kill_word;
606   map[Control ('v')].function = ea_scroll_completions_window;
607   map['0'].function = ea_beg_of_line;
608   map['$'].function = ea_end_of_line;
609   map['b'].function = ea_backward_word;
610   map['d'].function = ea_kill_word;
611   map['f'].function = ea_forward_word;
612   map['h'].function = ea_backward;
613   map['l'].function = ea_forward;
614   map['w'].function = ea_forward_word;
615   map['x'].function = ea_delete;
616   map['X'].function = ea_kill_word;
617   map['y'].function = ea_yank_pop;
618   map['?'].function = ea_possible_completions;
619   map[TAB].function = ea_tab_insert;
620   map[DEL].function = ea_kill_word;
621
622   /* Bind the echo area Control-x keymap. */
623   map = (Keymap)echo_area_keymap[Control ('x')].function;
624
625   map['o'].function = info_next_window;
626   map[DEL].function = ea_backward_kill_line;
627
628   /* Arrow key bindings for echo area keymaps.  It seems that some
629      terminals do not match their termcap entries, so it's best to just
630      define everything with both of the usual prefixes.  */
631   map = echo_area_keymap;
632   keymap_bind_keyseq (map, term_ku, &map[Control ('p')]); /* up */
633   keymap_bind_keyseq (map, "\033OA", &map[Control ('p')]);
634   keymap_bind_keyseq (map, "\033[A", &map[Control ('p')]);
635   keymap_bind_keyseq (map, term_kd, &map[Control ('n')]); /* down */
636   keymap_bind_keyseq (map, "\033OB", &map[Control ('n')]);
637   keymap_bind_keyseq (map, "\033[B", &map[Control ('n')]);
638   keymap_bind_keyseq (map, term_kr, &map[Control ('f')]); /* right */
639   keymap_bind_keyseq (map, "\033OC", &map[Control ('f')]);
640   keymap_bind_keyseq (map, "\033[C", &map[Control ('f')]);
641   keymap_bind_keyseq (map, term_kl, &map[Control ('b')]); /* left */
642   keymap_bind_keyseq (map, "\033OD", &map[Control ('b')]);
643   keymap_bind_keyseq (map, "\033[D", &map[Control ('b')]);
644   keymap_bind_keyseq (map, term_kh, &map[Control ('a')]); /* home */
645   keymap_bind_keyseq (map, term_ke, &map[Control ('e')]); /* end */
646   keymap_bind_keyseq (map, term_kD, &map[DEL]); /* delete */
647
648   map = (Keymap)echo_area_keymap[ESC].function;
649   keymap_bind_keyseq (map, term_kl, &map['b']); /* left */
650   keymap_bind_keyseq (map, "\033OA", &map['b']);
651   keymap_bind_keyseq (map, "\033[A", &map['b']);
652   keymap_bind_keyseq (map, term_kr, &map['f']); /* right */
653   keymap_bind_keyseq (map, "\033OB", &map['f']);
654   keymap_bind_keyseq (map, "\033[B", &map['f']);
655   keymap_bind_keyseq (map, term_kD, &map[DEL]); /* delete */
656
657   map = (Keymap)echo_area_keymap[Control ('x')].function;
658   keymap_bind_keyseq (map, term_kD, &map[DEL]);
659
660   /* Bind commands for Info window keymaps. */
661   map = info_keymap;
662   map[TAB].function = info_move_to_next_xref;
663   map[LFD].function = info_down_line;
664   map[RET].function = info_down_line;
665   map[SPC].function = info_scroll_forward;
666   map[Control ('a')].function = info_beginning_of_line;
667   map[Control ('b')].function = info_scroll_backward_page_only;
668   map[Control ('d')].function = info_scroll_half_screen_down;
669   map[Control ('e')].function = info_down_line;
670   map[Control ('f')].function = info_scroll_forward_page_only;
671   map[Control ('g')].function = info_abort_key;
672   map[Control ('k')].function = info_up_line;
673   map[Control ('l')].function = info_redraw_display;
674   map[Control ('n')].function = info_down_line;
675   map[Control ('p')].function = info_up_line;
676   map[Control ('r')].function = info_redraw_display;
677   map[Control ('s')].function = isearch_forward;
678   map[Control ('u')].function = info_scroll_half_screen_up;
679   map[Control ('v')].function = info_scroll_forward_page_only;
680   map[Control ('y')].function = info_up_line;
681   map[','].function = info_next_index_match;
682   map['/'].function = info_search;
683
684   for (i = '1'; i < '9' + 1; i++)
685     ((Keymap) info_keymap[ESC].function)[i].function = info_menu_digit;
686   ((Keymap) info_keymap[ESC].function)['0'].function = info_last_menu_item;
687
688   map['<'].function = info_first_node;
689   map['>'].function = info_last_node;
690   map['?'].function = info_search_backward;
691   map['['].function = info_global_prev_node;
692   map[']'].function = info_global_next_node;
693   map['\''].function = info_history_node;
694
695   map['b'].function = info_scroll_backward;
696   map['d'].function = info_scroll_half_screen_down;
697   map['e'].function = info_down_line;
698   map['E'].function = info_view_file;
699   map['f'].function = info_scroll_forward_page_only;
700   map['F'].function = info_scroll_forward_page_only;
701   map['g'].function = info_first_node;
702   map['G'].function = info_last_node;
703   map['h'].function = info_get_help_window;
704   map['H'].function = info_get_help_window;
705   map['i'].function = info_index_search;
706   map['I'].function = info_goto_invocation_node;
707   map['j'].function = info_next_line;
708   map['k'].function = info_prev_line;
709   map['l'].function = info_history_node;
710   map['m'].function = info_menu_item;
711   map['n'].function = info_search_next;
712   map['N'].function = info_search_previous;
713   map['O'].function = info_goto_invocation_node;
714   map['p'].function = info_prev_node;
715   map['q'].function = info_quit;
716   map['Q'].function = info_quit;
717   map['r'].function = info_redraw_display;
718   map['R'].function = info_redraw_display;
719   map['s'].function = info_search;
720   map['S'].function = info_search_case_sensitively;
721   map['t'].function = info_top_node;
722   map['u'].function = info_scroll_half_screen_up;
723   map['w'].function = info_scroll_backward_page_only_set_window;
724   map['y'].function = info_up_line;
725   map['z'].function = info_scroll_forward_page_only_set_window;
726   map['Z'].function = NULL;     /* unbind, so it works to bind "ZZ" below */
727   map[DEL].function = info_scroll_backward;
728   keymap_bind_keyseq (map, term_kD, &map[DEL]);
729   keymap_bind_keyseq (map, ":q", &map['q']);
730   keymap_bind_keyseq (map, ":Q", &map['q']);
731   keymap_bind_keyseq (map, "ZZ", &map['q']);
732
733   /* Bind members in the ESC map for Info windows. */
734   map = (Keymap)info_keymap[ESC].function;
735   map[Control ('f')].function = info_show_footnotes;
736   map[Control ('g')].function = info_abort_key;
737   map[TAB].function = info_move_to_prev_xref;
738   map[SPC].function = info_scroll_forward_page_only;
739   map[Control ('v')].function = info_scroll_other_window;
740   map['<'].function = info_beginning_of_node;
741   map['>'].function = info_end_of_node;
742   map['/'].function = info_search;
743   map['?'].function = info_search_backward;
744   map['b'].function = info_beginning_of_node;
745   map['d'].function = info_dir_node;
746   map['e'].function = info_end_of_node;
747   map['f'].function = info_xref_item;
748   map['g'].function = info_select_reference_this_line;
749   map['h'].function = info_get_info_help_node;
750   map['m'].function = info_menu_item;
751   map['n'].function = info_search;
752   map['N'].function = info_search_backward;
753   map['r'].function = isearch_backward;
754   map['s'].function = isearch_forward;
755   map['t'].function = info_top_node;
756   map['v'].function = info_scroll_backward_page_only;
757 #if defined (NAMED_FUNCTIONS)
758   map['x'].function = info_execute_command;
759 #endif /* NAMED_FUNCTIONS */
760   map[DEL].function = info_scroll_other_window_backward;
761
762   /* Bind members in the Control-X map for Info windows. */
763   map = (Keymap)info_keymap[Control ('x')].function;
764
765   map[Control ('b')].function = list_visited_nodes;
766   map[Control ('c')].function = info_quit;
767   map[Control ('f')].function = info_view_file;
768   map[Control ('g')].function = info_abort_key;
769   map[Control ('v')].function = info_view_file;
770   map[LFD].function = info_select_reference_this_line;
771   map[RET].function = info_select_reference_this_line;
772   map['0'].function = info_delete_window;
773   map['1'].function = info_keep_one_window;
774   map['2'].function = info_split_window;
775   map['^'].function = info_grow_window;
776   map['b'].function = select_visited_node;
777   map['g'].function = info_goto_node;
778   map['i'].function = info_index_search;
779   map['I'].function = info_goto_invocation_node;
780   map['k'].function = info_kill_node;
781   map['n'].function = info_next_node;
782   map['o'].function = info_next_window;
783   map['O'].function = info_goto_invocation_node;
784   map['p'].function = info_prev_node;
785   map['r'].function = info_xref_item;
786   map['t'].function = info_tile_windows;
787   map['u'].function = info_up_node;
788   map['w'].function = info_toggle_wrap;
789   map[','].function = info_next_index_match;
790   keymap_bind_keyseq (info_keymap, ":e", &map[Control ('v')]);
791
792   /* Arrow key bindings for Info windows keymap. */
793   map = info_keymap;
794   keymap_bind_keyseq (map, term_kN, &map[Control ('v')]); /* pagedown */
795   keymap_bind_keyseq (map, term_ku, &map[Control ('p')]); /* up */
796   keymap_bind_keyseq (map, "\033OA", &map[Control ('p')]);
797   keymap_bind_keyseq (map, "\033[A", &map[Control ('p')]);
798   keymap_bind_keyseq (map, term_kd, &map[Control ('n')]); /* down */
799   keymap_bind_keyseq (map, "\033OB", &map[Control ('n')]);
800   keymap_bind_keyseq (map, "\033[B", &map[Control ('n')]);
801   keymap_bind_keyseq (map, term_kr, &map[Control ('f')]); /* right */
802   keymap_bind_keyseq (map, "\033OC", &map[Control ('f')]);
803   keymap_bind_keyseq (map, "\033[C", &map[Control ('f')]);
804   keymap_bind_keyseq (map, term_kl, &map[Control ('b')]); /* left */
805   keymap_bind_keyseq (map, "\033OD", &map[Control ('b')]);
806   keymap_bind_keyseq (map, "\033[D", &map[Control ('b')]);
807   keymap_bind_keyseq (map, term_kh, &map['b']); /* home */
808   keymap_bind_keyseq (map, term_ke, &map['e']); /* end */
809
810   map = (Keymap)info_keymap[ESC].function;
811   keymap_bind_keyseq (map, term_kl, &map['b']); /* left */
812   keymap_bind_keyseq (map, "\033OA", &map['b']);
813   keymap_bind_keyseq (map, "\033[A", &map['b']);
814   keymap_bind_keyseq (map, term_kr, &map['f']); /* right */
815   keymap_bind_keyseq (map, "\033OB", &map['f']);
816   keymap_bind_keyseq (map, "\033[B", &map['f']);
817   keymap_bind_keyseq (map, term_kN, &map[Control ('v')]); /* pagedown */
818   keymap_bind_keyseq (map, term_kP, &map[DEL]); /* pageup */
819   keymap_bind_keyseq (map, term_kD, &map[DEL]); /* delete */
820
821   /* The alternative to this definition of a `main map' key in the
822      `ESC map' section, is something like:
823     keymap_bind_keyseq (map, term_kP, &((KeyMap)map[ESC].function).map['v']);
824   */
825   keymap_bind_keyseq (info_keymap/*sic*/, term_kP, &map['v']); /* pageup */
826 }
827
828 void
829 initialize_info_keymaps ()
830 {
831   if (vi_keys_p)
832     initialize_vi_like_keymaps ();
833   else
834     initialize_emacs_like_keymaps ();
835 }
836
837 #else /* defined(INFOKEY) */
838
839 /* Make sure that we don't have too many command codes defined. */
840
841 #if A_NCOMMANDS > A_MAX_COMMAND + 1
842 #error "too many commands defined"
843 #endif
844
845 /* Initialize the keymaps from the .info keymap file. */
846
847 #define NUL     '\0'
848
849 static unsigned char default_emacs_like_info_keys[] =
850 {
851         0,      /* suppress-default-keybindings flag */
852         TAB, NUL,                       A_info_move_to_next_xref,
853         LFD, NUL,                       A_info_select_reference_this_line,
854         RET, NUL,                       A_info_select_reference_this_line,
855         SPC, NUL,                       A_info_scroll_forward,
856         CONTROL('a'), NUL,              A_info_beginning_of_line,
857         CONTROL('b'), NUL,              A_info_backward_char,
858         CONTROL('e'), NUL,              A_info_end_of_line,
859         CONTROL('f'), NUL,              A_info_forward_char,
860         CONTROL('g'), NUL,              A_info_abort_key,
861         CONTROL('h'), NUL,              A_info_get_help_window,
862         CONTROL('l'), NUL,              A_info_redraw_display,
863         CONTROL('n'), NUL,              A_info_next_line,
864         CONTROL('p'), NUL,              A_info_prev_line,
865         CONTROL('r'), NUL,              A_isearch_backward,
866         CONTROL('s'), NUL,              A_isearch_forward,
867         CONTROL('u'), NUL,              A_info_universal_argument,
868         CONTROL('v'), NUL,              A_info_scroll_forward_page_only,
869         ',', NUL,                       A_info_next_index_match,
870         '/', NUL,                       A_info_search,
871         '0', NUL,                       A_info_last_menu_item,
872         '1', NUL,                       A_info_menu_digit,
873         '2', NUL,                       A_info_menu_digit,
874         '3', NUL,                       A_info_menu_digit,
875         '4', NUL,                       A_info_menu_digit,
876         '5', NUL,                       A_info_menu_digit,
877         '6', NUL,                       A_info_menu_digit,
878         '7', NUL,                       A_info_menu_digit,
879         '8', NUL,                       A_info_menu_digit,
880         '9', NUL,                       A_info_menu_digit,
881         '<', NUL,                       A_info_first_node,
882         '>', NUL,                       A_info_last_node,
883         '?', NUL,                       A_info_get_help_window,
884         '[', NUL,                       A_info_global_prev_node,
885         ']', NUL,                       A_info_global_next_node,
886         'b', NUL,                       A_info_beginning_of_node,
887         'd', NUL,                       A_info_dir_node,
888         'e', NUL,                       A_info_end_of_node,
889         'f', NUL,                       A_info_xref_item,
890         'g', NUL,                       A_info_goto_node,
891         'G', NUL,                       A_info_menu_sequence,
892         'h', NUL,                       A_info_get_info_help_node,
893         'i', NUL,                       A_info_index_search,
894         'l', NUL,                       A_info_history_node,
895         'm', NUL,                       A_info_menu_item,
896         'n', NUL,                       A_info_next_node,
897         'O', NUL,                       A_info_goto_invocation_node,
898         'p', NUL,                       A_info_prev_node,
899         'q', NUL,                       A_info_quit,
900         'r', NUL,                       A_info_xref_item,
901         's', NUL,                       A_info_search,
902         'S', NUL,                       A_info_search_case_sensitively,
903         't', NUL,                       A_info_top_node,
904         'u', NUL,                       A_info_up_node,
905         DEL, NUL,                       A_info_scroll_backward,
906         ESC, '0', NUL,                  A_info_add_digit_to_numeric_arg,
907         ESC, '1', NUL,                  A_info_add_digit_to_numeric_arg,
908         ESC, '2', NUL,                  A_info_add_digit_to_numeric_arg,
909         ESC, '3', NUL,                  A_info_add_digit_to_numeric_arg,
910         ESC, '4', NUL,                  A_info_add_digit_to_numeric_arg,
911         ESC, '5', NUL,                  A_info_add_digit_to_numeric_arg,
912         ESC, '6', NUL,                  A_info_add_digit_to_numeric_arg,
913         ESC, '7', NUL,                  A_info_add_digit_to_numeric_arg,
914         ESC, '8', NUL,                  A_info_add_digit_to_numeric_arg,
915         ESC, '9', NUL,                  A_info_add_digit_to_numeric_arg,
916         ESC, '-', NUL,                  A_info_add_digit_to_numeric_arg,
917         ESC, CONTROL('f'), NUL,         A_info_show_footnotes,
918         ESC, CONTROL('g'), NUL,         A_info_abort_key,
919         ESC, TAB, NUL,                  A_info_move_to_prev_xref,
920         ESC, CONTROL('v'), NUL,         A_info_scroll_other_window,
921         ESC, '<', NUL,                  A_info_beginning_of_node,
922         ESC, '>', NUL,                  A_info_end_of_node,
923         ESC, 'b', NUL,                  A_info_backward_word,
924         ESC, 'f', NUL,                  A_info_forward_word,
925         ESC, 'r', NUL,                  A_info_move_to_window_line,
926         ESC, 'v', NUL,                  A_info_scroll_backward_page_only,
927         Meta('0'), NUL,                 A_info_add_digit_to_numeric_arg,
928         Meta('1'), NUL,                 A_info_add_digit_to_numeric_arg,
929         Meta('2'), NUL,                 A_info_add_digit_to_numeric_arg,
930         Meta('3'), NUL,                 A_info_add_digit_to_numeric_arg,
931         Meta('4'), NUL,                 A_info_add_digit_to_numeric_arg,
932         Meta('5'), NUL,                 A_info_add_digit_to_numeric_arg,
933         Meta('6'), NUL,                 A_info_add_digit_to_numeric_arg,
934         Meta('7'), NUL,                 A_info_add_digit_to_numeric_arg,
935         Meta('8'), NUL,                 A_info_add_digit_to_numeric_arg,
936         Meta('9'), NUL,                 A_info_add_digit_to_numeric_arg,
937         Meta('-'), NUL,                 A_info_add_digit_to_numeric_arg,
938         Meta(CONTROL('f')), NUL,        A_info_show_footnotes,
939         Meta(CONTROL('g')), NUL,        A_info_abort_key,
940         Meta(TAB), NUL,                 A_info_move_to_prev_xref,
941         Meta(CONTROL('v')), NUL,        A_info_scroll_other_window,
942         Meta('<'), NUL,                 A_info_beginning_of_node,
943         Meta('>'), NUL,                 A_info_end_of_node,
944         Meta('b'), NUL,                 A_info_backward_word,
945         Meta('f'), NUL,                 A_info_forward_word,
946         Meta('r'), NUL,                 A_info_move_to_window_line,
947         Meta('v'), NUL,                 A_info_scroll_backward_page_only,
948 #if defined (NAMED_FUNCTIONS)
949         ESC, 'x', NUL,                  A_info_execute_command,
950         Meta('x'), NUL,                 A_info_execute_command,
951 #endif /* NAMED_FUNCTIONS */
952
953         CONTROL('x'), CONTROL('b'), NUL,        A_list_visited_nodes,
954         CONTROL('x'), CONTROL('c'), NUL,        A_info_quit,
955         CONTROL('x'), CONTROL('f'), NUL,        A_info_view_file,
956         CONTROL('x'), CONTROL('g'), NUL,        A_info_abort_key,
957         CONTROL('x'), CONTROL('v'), NUL,        A_info_view_file,
958         CONTROL('x'), '0', NUL,         A_info_delete_window,
959         CONTROL('x'), '1', NUL,         A_info_keep_one_window,
960         CONTROL('x'), '2', NUL,         A_info_split_window,
961         CONTROL('x'), '^', NUL,         A_info_grow_window,
962         CONTROL('x'), 'b', NUL,         A_select_visited_node,
963         CONTROL('x'), 'k', NUL,         A_info_kill_node,
964         CONTROL('x'), 'n', NUL,         A_info_search_next,
965         CONTROL('x'), 'N', NUL,         A_info_search_previous,
966         CONTROL('x'), 'o', NUL,         A_info_next_window,
967         CONTROL('x'), 't', NUL,         A_info_tile_windows,
968         CONTROL('x'), 'w', NUL,         A_info_toggle_wrap,
969
970 /*      Arrow key bindings for info keymaps.  It seems that some
971         terminals do not match their termcap entries, so it's best to just
972         define everything with both of the usual prefixes.  */
973
974         SK_ESCAPE, SK_PAGE_UP, NUL,             A_info_scroll_backward_page_only,
975         SK_ESCAPE, SK_PAGE_DOWN, NUL,           A_info_scroll_forward_page_only,
976         SK_ESCAPE, SK_UP_ARROW, NUL,            A_info_prev_line,
977         '\033', 'O', 'A', NUL,                  A_info_prev_line,
978         '\033', '[', 'A', NUL,                  A_info_prev_line,
979         SK_ESCAPE, SK_DOWN_ARROW, NUL,          A_info_next_line,
980         '\033', 'O', 'B', NUL,                  A_info_next_line,
981         '\033', '[', 'B', NUL,                  A_info_next_line,
982         SK_ESCAPE, SK_RIGHT_ARROW, NUL,         A_info_forward_char,
983         '\033', 'O', 'C', NUL,                  A_info_forward_char,
984         '\033', '[', 'C', NUL,                  A_info_forward_char,
985         SK_ESCAPE, SK_LEFT_ARROW, NUL,          A_info_backward_char,
986         '\033', 'O', 'D', NUL,                  A_info_backward_char,
987         '\033', '[', 'D', NUL,                  A_info_backward_char,
988         SK_ESCAPE, SK_HOME, NUL,                A_info_beginning_of_node,
989         SK_ESCAPE, SK_END, NUL,                 A_info_end_of_node,
990         SK_ESCAPE, SK_DELETE, NUL,              A_info_scroll_backward,
991
992         ESC, SK_ESCAPE, SK_PAGE_UP, NUL,        A_info_scroll_other_window_backward,
993         ESC, SK_ESCAPE, SK_PAGE_DOWN, NUL,      A_info_scroll_other_window,
994         ESC, SK_ESCAPE, SK_UP_ARROW, NUL,       A_info_prev_line,
995         ESC, '\033', 'O', 'A', NUL,             A_info_prev_line,
996         ESC, '\033', '[', 'A', NUL,             A_info_prev_line,
997         ESC, SK_ESCAPE, SK_DOWN_ARROW, NUL,     A_info_next_line,
998         ESC, '\033', 'O', 'B', NUL,             A_info_next_line,
999         ESC, '\033', '[', 'B', NUL,             A_info_next_line,
1000         ESC, SK_ESCAPE, SK_RIGHT_ARROW, NUL,    A_info_forward_word,
1001         ESC, '\033', 'O', 'C', NUL,             A_info_forward_word,
1002         ESC, '\033', '[', 'C', NUL,             A_info_forward_word,
1003         ESC, SK_ESCAPE, SK_LEFT_ARROW, NUL,     A_info_backward_word,
1004         ESC, '\033', 'O', 'D', NUL,             A_info_backward_word,
1005         ESC, '\033', '[', 'D', NUL,             A_info_backward_word,
1006 };
1007
1008 static unsigned char default_emacs_like_ea_keys[] =
1009 {
1010         0,      /* suppress-default-keybindings flag */
1011         ESC, '0', NUL,                  A_info_add_digit_to_numeric_arg,
1012         ESC, '1', NUL,                  A_info_add_digit_to_numeric_arg,
1013         ESC, '2', NUL,                  A_info_add_digit_to_numeric_arg,
1014         ESC, '3', NUL,                  A_info_add_digit_to_numeric_arg,
1015         ESC, '4', NUL,                  A_info_add_digit_to_numeric_arg,
1016         ESC, '5', NUL,                  A_info_add_digit_to_numeric_arg,
1017         ESC, '6', NUL,                  A_info_add_digit_to_numeric_arg,
1018         ESC, '7', NUL,                  A_info_add_digit_to_numeric_arg,
1019         ESC, '8', NUL,                  A_info_add_digit_to_numeric_arg,
1020         ESC, '9', NUL,                  A_info_add_digit_to_numeric_arg,
1021         ESC, '-', NUL,                  A_info_add_digit_to_numeric_arg,
1022         Meta('0'), NUL,                 A_info_add_digit_to_numeric_arg,
1023         Meta('1'), NUL,                 A_info_add_digit_to_numeric_arg,
1024         Meta('2'), NUL,                 A_info_add_digit_to_numeric_arg,
1025         Meta('3'), NUL,                 A_info_add_digit_to_numeric_arg,
1026         Meta('4'), NUL,                 A_info_add_digit_to_numeric_arg,
1027         Meta('5'), NUL,                 A_info_add_digit_to_numeric_arg,
1028         Meta('6'), NUL,                 A_info_add_digit_to_numeric_arg,
1029         Meta('7'), NUL,                 A_info_add_digit_to_numeric_arg,
1030         Meta('8'), NUL,                 A_info_add_digit_to_numeric_arg,
1031         Meta('9'), NUL,                 A_info_add_digit_to_numeric_arg,
1032         Meta('-'), NUL,                 A_info_add_digit_to_numeric_arg,
1033         ESC, CONTROL('g'), NUL,         A_ea_abort,
1034         ESC, CONTROL('v'), NUL,         A_ea_scroll_completions_window,
1035         ESC, 'b', NUL,                  A_ea_backward_word,
1036         ESC, 'd', NUL,                  A_ea_kill_word,
1037         ESC, 'f', NUL,                  A_ea_forward_word,
1038         ESC, 'y', NUL,                  A_ea_yank_pop,
1039         ESC, '?', NUL,                  A_ea_possible_completions,
1040         ESC, TAB, NUL,                  A_ea_tab_insert,
1041         ESC, DEL, NUL,                  A_ea_backward_kill_word,
1042         Meta(CONTROL('g')), NUL,        A_ea_abort,
1043         Meta(CONTROL('v')), NUL,        A_ea_scroll_completions_window,
1044         Meta('b'), NUL,                 A_ea_backward_word,
1045         Meta('d'), NUL,                 A_ea_kill_word,
1046         Meta('f'), NUL,                 A_ea_forward_word,
1047         Meta('y'), NUL,                 A_ea_yank_pop,
1048         Meta('?'), NUL,                 A_ea_possible_completions,
1049         Meta(TAB), NUL,                 A_ea_tab_insert,
1050         Meta(DEL), NUL,                 A_ea_backward_kill_word,
1051         CONTROL('a'), NUL,              A_ea_beg_of_line,
1052         CONTROL('b'), NUL,              A_ea_backward,
1053         CONTROL('d'), NUL,              A_ea_delete,
1054         CONTROL('e'), NUL,              A_ea_end_of_line,
1055         CONTROL('f'), NUL,              A_ea_forward,
1056         CONTROL('g'), NUL,              A_ea_abort,
1057         CONTROL('h'), NUL,              A_ea_rubout,
1058 /*      CONTROL('k') */
1059         SK_ESCAPE, SK_LITERAL, NUL,     A_ea_kill_line,
1060         CONTROL('l'), NUL,              A_info_redraw_display,
1061         CONTROL('q'), NUL,              A_ea_quoted_insert,
1062         CONTROL('t'), NUL,              A_ea_transpose_chars,
1063         CONTROL('u'), NUL,              A_info_universal_argument,
1064         CONTROL('y'), NUL,              A_ea_yank,
1065         LFD, NUL,                       A_ea_newline,
1066         RET, NUL,                       A_ea_newline,
1067         SPC, NUL,                       A_ea_complete,
1068         TAB, NUL,                       A_ea_complete,
1069         '?', NUL,                       A_ea_possible_completions,
1070 #ifdef __MSDOS__
1071         /* PC users will lynch me if I don't give them their usual DEL
1072            effect...  */
1073         DEL, NUL,                       A_ea_delete,
1074 #else
1075         DEL, NUL,                       A_ea_rubout,
1076 #endif
1077 #if defined (NAMED_FUNCTIONS)
1078   /*    ESC, 'x', NUL,                  A_info_execute_command, */
1079   /*    Meta('x'), NUL,                 A_info_execute_command, */
1080 #endif /* NAMED_FUNCTIONS */
1081         CONTROL('x'), 'o', NUL,         A_info_next_window,
1082         CONTROL('x'), DEL, NUL,         A_ea_backward_kill_line,
1083
1084 /*      Arrow key bindings for echo area keymaps.  It seems that some
1085         terminals do not match their termcap entries, so it's best to just
1086         define everything with both of the usual prefixes.  */
1087
1088         SK_ESCAPE, SK_RIGHT_ARROW, NUL,         A_ea_forward,
1089         '\033', 'O', 'C', NUL,                  A_ea_forward,
1090         '\033', '[', 'C', NUL,                  A_ea_forward,
1091         SK_ESCAPE, SK_LEFT_ARROW, NUL,          A_ea_backward,
1092         '\033', 'O', 'D', NUL,                  A_ea_backward,
1093         '\033', '[', 'D', NUL,                  A_ea_backward,
1094         ESC, SK_ESCAPE, SK_RIGHT_ARROW, NUL,    A_ea_forward_word,
1095         ESC, '\033', 'O', 'C', NUL,             A_ea_forward_word,
1096         ESC, '\033', '[', 'C', NUL,             A_ea_forward_word,
1097         ESC, SK_ESCAPE, SK_LEFT_ARROW, NUL,     A_ea_backward_word,
1098         ESC, '\033', 'O', 'D', NUL,             A_ea_backward_word,
1099         ESC, '\033', '[', 'D', NUL,             A_ea_backward_word,
1100 #ifdef __MSDOS__
1101         SK_ESCAPE, SK_DELETE, NUL,              A_ea_delete,
1102 #else
1103         SK_ESCAPE, SK_DELETE, NUL,              A_ea_rubout,
1104 #endif
1105         SK_ESCAPE, SK_HOME, NUL,                A_ea_beg_of_line,
1106         SK_ESCAPE, SK_END, NUL,                 A_ea_end_of_line,
1107         ESC, SK_ESCAPE, SK_DELETE, NUL,         A_ea_backward_kill_word,
1108         CONTROL('x'), SK_ESCAPE, SK_DELETE, NUL,A_ea_backward_kill_line,
1109 };
1110
1111 static unsigned char default_vi_like_info_keys[] =
1112 {
1113         0,      /* suppress-default-keybindings flag */
1114         '0', NUL,                       A_info_add_digit_to_numeric_arg,
1115         '1', NUL,                       A_info_add_digit_to_numeric_arg,
1116         '2', NUL,                       A_info_add_digit_to_numeric_arg,
1117         '3', NUL,                       A_info_add_digit_to_numeric_arg,
1118         '4', NUL,                       A_info_add_digit_to_numeric_arg,
1119         '5', NUL,                       A_info_add_digit_to_numeric_arg,
1120         '6', NUL,                       A_info_add_digit_to_numeric_arg,
1121         '7', NUL,                       A_info_add_digit_to_numeric_arg,
1122         '8', NUL,                       A_info_add_digit_to_numeric_arg,
1123         '9', NUL,                       A_info_add_digit_to_numeric_arg,
1124         '-', NUL,                       A_info_add_digit_to_numeric_arg,
1125         TAB, NUL,                       A_info_move_to_next_xref,
1126         LFD, NUL,                       A_info_down_line,
1127         RET, NUL,                       A_info_down_line,
1128         SPC, NUL,                       A_info_scroll_forward,
1129         CONTROL('a'), NUL,              A_info_beginning_of_line,
1130         CONTROL('b'), NUL,              A_info_scroll_backward_page_only,
1131         CONTROL('d'), NUL,              A_info_scroll_half_screen_down,
1132         CONTROL('e'), NUL,              A_info_down_line,
1133         CONTROL('f'), NUL,              A_info_scroll_forward_page_only,
1134         CONTROL('g'), NUL,              A_info_abort_key,
1135         CONTROL('k'), NUL,              A_info_up_line,
1136         CONTROL('l'), NUL,              A_info_redraw_display,
1137         CONTROL('n'), NUL,              A_info_down_line,
1138         CONTROL('p'), NUL,              A_info_up_line,
1139         CONTROL('r'), NUL,              A_info_redraw_display,
1140         CONTROL('s'), NUL,              A_isearch_forward,
1141         CONTROL('u'), NUL,              A_info_scroll_half_screen_up,
1142         CONTROL('v'), NUL,              A_info_scroll_forward_page_only,
1143         CONTROL('y'), NUL,              A_info_up_line,
1144         ',', NUL,                       A_info_next_index_match,
1145         '/', NUL,                       A_info_search,
1146         ESC, '0', NUL,                  A_info_last_menu_item,
1147         ESC, '1', NUL,                  A_info_menu_digit,
1148         ESC, '2', NUL,                  A_info_menu_digit,
1149         ESC, '3', NUL,                  A_info_menu_digit,
1150         ESC, '4', NUL,                  A_info_menu_digit,
1151         ESC, '5', NUL,                  A_info_menu_digit,
1152         ESC, '6', NUL,                  A_info_menu_digit,
1153         ESC, '7', NUL,                  A_info_menu_digit,
1154         ESC, '8', NUL,                  A_info_menu_digit,
1155         ESC, '9', NUL,                  A_info_menu_digit,
1156         Meta('0'), NUL,                 A_info_last_menu_item,
1157         Meta('1'), NUL,                 A_info_menu_digit,
1158         Meta('2'), NUL,                 A_info_menu_digit,
1159         Meta('3'), NUL,                 A_info_menu_digit,
1160         Meta('4'), NUL,                 A_info_menu_digit,
1161         Meta('5'), NUL,                 A_info_menu_digit,
1162         Meta('6'), NUL,                 A_info_menu_digit,
1163         Meta('7'), NUL,                 A_info_menu_digit,
1164         Meta('8'), NUL,                 A_info_menu_digit,
1165         Meta('9'), NUL,                 A_info_menu_digit,
1166         '<', NUL,                       A_info_first_node,
1167         '>', NUL,                       A_info_last_node,
1168         '?', NUL,                       A_info_search_backward,
1169         '[', NUL,                       A_info_global_prev_node,
1170         ']', NUL,                       A_info_global_next_node,
1171         '\'', NUL,                      A_info_history_node,
1172         'b', NUL,                       A_info_scroll_backward,
1173         'd', NUL,                       A_info_scroll_half_screen_down,
1174         'e', NUL,                       A_info_down_line,
1175         'E', NUL,                       A_info_view_file,
1176         ':', 'e', NUL,                  A_info_view_file,
1177         'f', NUL,                       A_info_scroll_forward_page_only,
1178         'F', NUL,                       A_info_scroll_forward_page_only,
1179         'g', NUL,                       A_info_first_node,
1180         'G', NUL,                       A_info_last_node,
1181         'h', NUL,                       A_info_get_help_window,
1182         'H', NUL,                       A_info_get_help_window,
1183         'i', NUL,                       A_info_index_search,
1184         'I', NUL,                       A_info_goto_invocation_node,
1185         'j', NUL,                       A_info_next_line,
1186         'k', NUL,                       A_info_prev_line,
1187         'l', NUL,                       A_info_history_node,
1188         'm', NUL,                       A_info_menu_item,
1189         'n', NUL,                       A_info_search_next,
1190         'N', NUL,                       A_info_search_previous,
1191         'O', NUL,                       A_info_goto_invocation_node,
1192         'p', NUL,                       A_info_prev_node,
1193         'q', NUL,                       A_info_quit,
1194         'Q', NUL,                       A_info_quit,
1195         ':', 'q', NUL,                  A_info_quit,
1196         ':', 'Q', NUL,                  A_info_quit,
1197         'Z', 'Z', NUL,                  A_info_quit,
1198         'r', NUL,                       A_info_redraw_display,
1199         'R', NUL,                       A_info_redraw_display,
1200         's', NUL,                       A_info_search,
1201         'S', NUL,                       A_info_search_case_sensitively,
1202         't', NUL,                       A_info_top_node,
1203         'u', NUL,                       A_info_scroll_half_screen_up,
1204         'w', NUL,                       A_info_scroll_backward_page_only_set_window,
1205         'y', NUL,                       A_info_up_line,
1206         'z', NUL,                       A_info_scroll_forward_page_only_set_window,
1207         DEL, NUL,                       A_info_scroll_backward,
1208         ESC, CONTROL('f'), NUL,         A_info_show_footnotes,
1209         ESC, CONTROL('g'), NUL,         A_info_abort_key,
1210         ESC, TAB, NUL,                  A_info_move_to_prev_xref,
1211         ESC, SPC, NUL,                  A_info_scroll_forward_page_only,
1212         ESC, CONTROL('v'), NUL,         A_info_scroll_other_window,
1213         ESC, '<', NUL,                  A_info_beginning_of_node,
1214         ESC, '>', NUL,                  A_info_end_of_node,
1215         ESC, '/', NUL,                  A_info_search,
1216         ESC, '?', NUL,                  A_info_search_backward,
1217         ESC, 'b', NUL,                  A_info_beginning_of_node,
1218         ESC, 'd', NUL,                  A_info_dir_node,
1219         ESC, 'e', NUL,                  A_info_end_of_node,
1220         ESC, 'f', NUL,                  A_info_xref_item,
1221         ESC, 'g', NUL,                  A_info_select_reference_this_line,
1222         ESC, 'h', NUL,                  A_info_get_info_help_node,
1223         ESC, 'm', NUL,                  A_info_menu_item,
1224         ESC, 'n', NUL,                  A_info_search,
1225         ESC, 'N', NUL,                  A_info_search_backward,
1226         ESC, 'r', NUL,                  A_isearch_backward,
1227         ESC, 's', NUL,                  A_isearch_forward,
1228         ESC, 't', NUL,                  A_info_top_node,
1229         ESC, 'v', NUL,                  A_info_scroll_backward_page_only,
1230 #if defined (NAMED_FUNCTIONS)
1231         ESC, 'x', NUL,                  A_info_execute_command,
1232         Meta('x'), NUL,                 A_info_execute_command,
1233 #endif /* NAMED_FUNCTIONS */
1234         ESC, DEL, NUL,                  A_info_scroll_other_window_backward,
1235         CONTROL('x'), CONTROL('b'), NUL,        A_list_visited_nodes,
1236         CONTROL('x'), CONTROL('c'), NUL,        A_info_quit,
1237         CONTROL('x'), CONTROL('f'), NUL,        A_info_view_file,
1238         CONTROL('x'), CONTROL('g'), NUL,        A_info_abort_key,
1239         CONTROL('x'), CONTROL('v'), NUL,        A_info_view_file,
1240         CONTROL('x'), LFD, NUL,         A_info_select_reference_this_line,
1241         CONTROL('x'), RET, NUL,         A_info_select_reference_this_line,
1242         CONTROL('x'), '0', NUL,         A_info_delete_window,
1243         CONTROL('x'), '1', NUL,         A_info_keep_one_window,
1244         CONTROL('x'), '2', NUL,         A_info_split_window,
1245         CONTROL('x'), '^', NUL,         A_info_grow_window,
1246         CONTROL('x'), 'b', NUL,         A_select_visited_node,
1247         CONTROL('x'), 'g', NUL,         A_info_goto_node,
1248         CONTROL('x'), 'i', NUL,         A_info_index_search,
1249         CONTROL('x'), 'I', NUL,         A_info_goto_invocation_node,
1250         CONTROL('x'), 'k', NUL,         A_info_kill_node,
1251         CONTROL('x'), 'n', NUL,         A_info_next_node,
1252         CONTROL('x'), 'o', NUL,         A_info_next_window,
1253         CONTROL('x'), 'O', NUL,         A_info_goto_invocation_node,
1254         CONTROL('x'), 'p', NUL,         A_info_prev_node,
1255         CONTROL('x'), 'r', NUL,         A_info_xref_item,
1256         CONTROL('x'), 't', NUL,         A_info_tile_windows,
1257         CONTROL('x'), 'u', NUL,         A_info_up_node,
1258         CONTROL('x'), 'w', NUL,         A_info_toggle_wrap,
1259         CONTROL('x'), ',', NUL,         A_info_next_index_match,
1260
1261 /*      Arrow key bindings for info keymaps.  It seems that some
1262         terminals do not match their termcap entries, so it's best to just
1263         define everything with both of the usual prefixes.  */
1264
1265         SK_ESCAPE, SK_PAGE_UP, NUL,             A_info_scroll_backward_page_only,
1266         SK_ESCAPE, SK_PAGE_DOWN, NUL,           A_info_scroll_forward_page_only,
1267         SK_ESCAPE, SK_UP_ARROW, NUL,            A_info_up_line,
1268         '\033', 'O', 'A', NUL,                  A_info_up_line,
1269         '\033', '[', 'A', NUL,                  A_info_up_line,
1270         SK_ESCAPE, SK_DOWN_ARROW, NUL,          A_info_down_line,
1271         '\033', 'O', 'B', NUL,                  A_info_down_line,
1272         '\033', '[', 'B', NUL,                  A_info_down_line,
1273         SK_ESCAPE, SK_RIGHT_ARROW, NUL,         A_info_scroll_forward_page_only,
1274         '\033', 'O', 'C', NUL,                  A_info_scroll_forward_page_only,
1275         '\033', '[', 'C', NUL,                  A_info_scroll_forward_page_only,
1276         SK_ESCAPE, SK_LEFT_ARROW, NUL,          A_info_scroll_backward_page_only,
1277         '\033', 'O', 'D', NUL,                  A_info_scroll_backward_page_only,
1278         '\033', '[', 'D', NUL,                  A_info_scroll_backward_page_only,
1279         SK_ESCAPE, SK_HOME, NUL,                A_info_beginning_of_node,
1280         SK_ESCAPE, SK_END, NUL,                 A_info_end_of_node,
1281         ESC, SK_ESCAPE, SK_PAGE_DOWN, NUL,      A_info_scroll_other_window,
1282         ESC, SK_ESCAPE, SK_PAGE_UP, NUL,        A_info_scroll_other_window_backward,
1283         ESC, SK_ESCAPE, SK_DELETE, NUL,         A_info_scroll_other_window_backward,
1284         ESC, SK_ESCAPE, SK_UP_ARROW, NUL,       A_info_prev_node,
1285         ESC, '\033', 'O', 'A', NUL,             A_info_prev_node,
1286         ESC, '\033', '[', 'A', NUL,             A_info_prev_node,
1287         ESC, SK_ESCAPE, SK_DOWN_ARROW, NUL,     A_info_next_node,
1288         ESC, '\033', 'O', 'B', NUL,             A_info_next_node,
1289         ESC, '\033', '[', 'B', NUL,             A_info_next_node,
1290         ESC, SK_ESCAPE, SK_RIGHT_ARROW, NUL,    A_info_xref_item,
1291         ESC, '\033', 'O', 'C', NUL,             A_info_xref_item,
1292         ESC, '\033', '[', 'C', NUL,             A_info_xref_item,
1293         ESC, SK_ESCAPE, SK_LEFT_ARROW, NUL,     A_info_beginning_of_node,
1294         ESC, '\033', 'O', 'D', NUL,             A_info_beginning_of_node,
1295         ESC, '\033', '[', 'D', NUL,             A_info_beginning_of_node,
1296         CONTROL('x'), SK_ESCAPE, SK_DELETE, NUL,A_ea_backward_kill_line,
1297 };
1298
1299 static unsigned char default_vi_like_ea_keys[] =
1300 {
1301         0,      /* suppress-default-keybindings flag */
1302         ESC, '1', NUL,                  A_info_add_digit_to_numeric_arg,
1303         ESC, '2', NUL,                  A_info_add_digit_to_numeric_arg,
1304         ESC, '3', NUL,                  A_info_add_digit_to_numeric_arg,
1305         ESC, '4', NUL,                  A_info_add_digit_to_numeric_arg,
1306         ESC, '5', NUL,                  A_info_add_digit_to_numeric_arg,
1307         ESC, '6', NUL,                  A_info_add_digit_to_numeric_arg,
1308         ESC, '7', NUL,                  A_info_add_digit_to_numeric_arg,
1309         ESC, '8', NUL,                  A_info_add_digit_to_numeric_arg,
1310         ESC, '9', NUL,                  A_info_add_digit_to_numeric_arg,
1311         ESC, '-', NUL,                  A_info_add_digit_to_numeric_arg,
1312         Meta('1'), NUL,                 A_info_add_digit_to_numeric_arg,
1313         Meta('2'), NUL,                 A_info_add_digit_to_numeric_arg,
1314         Meta('3'), NUL,                 A_info_add_digit_to_numeric_arg,
1315         Meta('4'), NUL,                 A_info_add_digit_to_numeric_arg,
1316         Meta('5'), NUL,                 A_info_add_digit_to_numeric_arg,
1317         Meta('6'), NUL,                 A_info_add_digit_to_numeric_arg,
1318         Meta('7'), NUL,                 A_info_add_digit_to_numeric_arg,
1319         Meta('8'), NUL,                 A_info_add_digit_to_numeric_arg,
1320         Meta('9'), NUL,                 A_info_add_digit_to_numeric_arg,
1321         Meta('-'), NUL,                 A_info_add_digit_to_numeric_arg,
1322         ESC, CONTROL('g'), NUL,         A_ea_abort,
1323         ESC, CONTROL('h'), NUL,         A_ea_backward_kill_word,
1324         ESC, CONTROL('v'), NUL,         A_ea_scroll_completions_window,
1325         ESC, '0', NUL,                  A_ea_beg_of_line,
1326         ESC, '$', NUL,                  A_ea_end_of_line,
1327         ESC, 'b', NUL,                  A_ea_backward_word,
1328         ESC, 'd', NUL,                  A_ea_kill_word,
1329         ESC, 'f', NUL,                  A_ea_forward_word,
1330         ESC, 'h', NUL,                  A_ea_forward,
1331         ESC, 'l', NUL,                  A_ea_backward,
1332         ESC, 'w', NUL,                  A_ea_forward_word,
1333         ESC, 'x', NUL,                  A_ea_delete,
1334         ESC, 'X', NUL,                  A_ea_kill_word,
1335         ESC, 'y', NUL,                  A_ea_yank_pop,
1336         ESC, '?', NUL,                  A_ea_possible_completions,
1337         ESC, TAB, NUL,                  A_ea_tab_insert,
1338         ESC, DEL, NUL,                  A_ea_kill_word,
1339         Meta(CONTROL('g')), NUL,        A_ea_abort,
1340         Meta(CONTROL('h')), NUL,        A_ea_backward_kill_word,
1341         Meta(CONTROL('v')), NUL,        A_ea_scroll_completions_window,
1342         Meta('0'), NUL,                 A_ea_beg_of_line,
1343         Meta('$'), NUL,                 A_ea_end_of_line,
1344         Meta('b'), NUL,                 A_ea_backward_word,
1345         Meta('d'), NUL,                 A_ea_kill_word,
1346         Meta('f'), NUL,                 A_ea_forward_word,
1347         Meta('h'), NUL,                 A_ea_forward,
1348         Meta('l'), NUL,                 A_ea_backward,
1349         Meta('w'), NUL,                 A_ea_forward_word,
1350         Meta('x'), NUL,                 A_ea_delete,
1351         Meta('X'), NUL,                 A_ea_kill_word,
1352         Meta('y'), NUL,                 A_ea_yank_pop,
1353         Meta('?'), NUL,                 A_ea_possible_completions,
1354         Meta(TAB), NUL,                 A_ea_tab_insert,
1355         Meta(DEL), NUL,                 A_ea_kill_word,
1356         CONTROL('a'), NUL,              A_ea_beg_of_line,
1357         CONTROL('b'), NUL,              A_ea_backward,
1358         CONTROL('d'), NUL,              A_ea_delete,
1359         CONTROL('e'), NUL,              A_ea_end_of_line,
1360         CONTROL('f'), NUL,              A_ea_forward,
1361         CONTROL('g'), NUL,              A_ea_abort,
1362         CONTROL('h'), NUL,              A_ea_rubout,
1363 /*      CONTROL('k') */
1364         SK_ESCAPE, SK_LITERAL, NUL,     A_ea_kill_line,
1365         CONTROL('l'), NUL,              A_info_redraw_display,
1366         CONTROL('q'), NUL,              A_ea_quoted_insert,
1367         CONTROL('t'), NUL,              A_ea_transpose_chars,
1368         CONTROL('u'), NUL,              A_ea_abort,
1369         CONTROL('v'), NUL,              A_ea_quoted_insert,
1370         CONTROL('y'), NUL,              A_ea_yank,
1371         LFD, NUL,                       A_ea_newline,
1372         RET, NUL,                       A_ea_newline,
1373         SPC, NUL,                       A_ea_complete,
1374         TAB, NUL,                       A_ea_complete,
1375         '?', NUL,                       A_ea_possible_completions,
1376 #ifdef __MSDOS__
1377         /* PC users will lynch me if I don't give them their usual DEL
1378            effect...  */
1379         DEL, NUL,                       A_ea_delete,
1380 #else
1381         DEL, NUL,                       A_ea_rubout,
1382 #endif
1383         CONTROL('x'), 'o', NUL,         A_info_next_window,
1384         CONTROL('x'), DEL, NUL,         A_ea_backward_kill_line,
1385
1386   /* Arrow key bindings for echo area keymaps.  It seems that some
1387      terminals do not match their termcap entries, so it's best to just
1388      define everything with both of the usual prefixes.  */
1389
1390         SK_ESCAPE, SK_RIGHT_ARROW, NUL,         A_ea_forward,
1391         '\033', 'O', 'C', NUL,                  A_ea_forward,
1392         '\033', '[', 'C', NUL,                  A_ea_forward,
1393         SK_ESCAPE, SK_LEFT_ARROW, NUL,          A_ea_backward,
1394         '\033', 'O', 'D', NUL,                  A_ea_backward,
1395         '\033', '[', 'D', NUL,                  A_ea_backward,
1396         SK_ESCAPE, SK_HOME, NUL,                A_ea_beg_of_line,
1397         SK_ESCAPE, SK_END, NUL,                 A_ea_end_of_line,
1398 #ifdef __MSDOS__
1399         SK_ESCAPE, SK_DELETE, NUL,              A_ea_delete,
1400 #else
1401         SK_DELETE, SK_DELETE, NUL,              A_ea_rubout,
1402 #endif
1403         ESC, SK_ESCAPE, SK_RIGHT_ARROW, NUL,    A_ea_forward_word,
1404         ESC, '\033', 'O', 'C', NUL,             A_ea_forward_word,
1405         ESC, '\033', '[', 'C', NUL,             A_ea_forward_word,
1406         ESC, SK_ESCAPE, SK_LEFT_ARROW, NUL,     A_ea_backward_word,
1407         ESC, '\033', 'O', 'D', NUL,             A_ea_backward_word,
1408         ESC, '\033', '[', 'D', NUL,             A_ea_backward_word,
1409         ESC, SK_ESCAPE, SK_DELETE, NUL,         A_ea_kill_word,
1410         CONTROL('x'), SK_ESCAPE, SK_DELETE, NUL,A_ea_backward_kill_line,
1411 };
1412
1413 static unsigned char *user_info_keys;
1414 static unsigned int user_info_keys_len;
1415 static unsigned char *user_ea_keys;
1416 static unsigned int user_ea_keys_len;
1417 static unsigned char *user_vars;
1418 static unsigned int user_vars_len;
1419
1420 /*
1421  * Return the size of a file, or 0 if the size can't be determined.
1422  */
1423 static unsigned long
1424 filesize(int f)
1425 {
1426         long pos = lseek(f, 0L, SEEK_CUR);
1427         long sz = -1L;
1428         if (pos != -1L)
1429         {
1430                 sz = lseek(f, 0L, SEEK_END);
1431                 lseek(f, pos, SEEK_SET);
1432         }
1433         return sz == -1L ? 0L : sz;
1434 }
1435
1436 /* Get an integer from a infokey file.
1437    Integers are stored as two bytes, low order first, in radix INFOKEY_RADIX.
1438  */
1439 static int
1440 getint(unsigned char **sp)
1441 {
1442         int n;
1443
1444         if ( !((*sp)[0] < INFOKEY_RADIX && (*sp)[1] < INFOKEY_RADIX) )
1445                 return -1;
1446         n = (*sp)[0] + (*sp)[1] * INFOKEY_RADIX;
1447         *sp += 2;
1448         return n;
1449 }
1450
1451
1452 /* Fetch the contents of the standard infokey file "$HOME/.info".  Return
1453    true if ok, false if not.  */
1454 static int
1455 fetch_user_maps(void)
1456 {
1457         char *filename = NULL;
1458         char *homedir;
1459         int f;
1460         unsigned char *buf;
1461         unsigned long len;
1462         long nread;
1463         unsigned char *p;
1464         int n;
1465
1466         /* Find and open file. */
1467         if ((filename = getenv("INFOKEY")) != NULL)
1468                 filename = xstrdup(filename);
1469         else if ((homedir = getenv("HOME")) != NULL)
1470         {
1471                 filename = xmalloc(strlen(homedir) + 2 + strlen(INFOKEY_FILE));
1472                 strcpy(filename, homedir);
1473                 strcat(filename, "/");
1474                 strcat(filename, INFOKEY_FILE);
1475         }
1476 #ifdef __MSDOS__
1477         /* Poor baby, she doesn't have a HOME...  */
1478         else
1479                 filename = xstrdup(INFOKEY_FILE); /* try current directory */
1480 #endif
1481         if (filename == NULL || (f = open(filename, O_RDONLY)) == (-1))
1482         {
1483                 if (filename && errno != ENOENT)
1484                 {
1485                         info_error(filesys_error_string(filename, errno),
1486                             NULL, NULL);
1487                         free(filename);
1488                 }
1489                 return 0;
1490         }
1491         SET_BINARY (f);
1492
1493         /* Ensure that the file is a reasonable size. */
1494         len = filesize(f);
1495         if (len < INFOKEY_NMAGIC + 2 || len > 100 * 1024)
1496         {
1497                 /* Bad file (a valid file must have at least 9 chars, and
1498                    more than 100 KB is a problem). */
1499                 if (len < INFOKEY_NMAGIC + 2)
1500                         info_error((char *) _("Ignoring invalid infokey file `%s' - too small"),
1501                                    filename, NULL);
1502                 else
1503                         info_error((char *) _("Ignoring invalid infokey file `%s' - too big"),
1504                                    filename, NULL);
1505                 close(f);
1506                 free(filename);
1507                 return 0;
1508         }
1509
1510         /* Read the file into a buffer. */
1511         buf = (unsigned char *)xmalloc((int)len);
1512         nread = read(f, buf, (unsigned int) len);
1513         close(f);
1514         if ((unsigned int) nread != len)
1515         {
1516                 info_error((char *) _("Error reading infokey file `%s' - short read"),
1517                     filename, NULL);
1518                 free(buf);
1519                 free(filename);
1520                 return 0;
1521         }
1522
1523         /* Check the header, trailer, and version of the file to increase
1524            our confidence that the contents are valid.  */
1525         if (    buf[0] != INFOKEY_MAGIC_S0
1526                 || buf[1] != INFOKEY_MAGIC_S1
1527                 || buf[2] != INFOKEY_MAGIC_S2
1528                 || buf[3] != INFOKEY_MAGIC_S3
1529                 || buf[len - 4] != INFOKEY_MAGIC_E0
1530                 || buf[len - 3] != INFOKEY_MAGIC_E1
1531                 || buf[len - 2] != INFOKEY_MAGIC_E2
1532                 || buf[len - 1] != INFOKEY_MAGIC_E3
1533         )
1534         {
1535                 info_error((char *) _("Invalid infokey file `%s' (bad magic numbers) -- run infokey to update it"),
1536                     filename, NULL);
1537                 free(filename);
1538                 return 0;
1539         }
1540         if (len < INFOKEY_NMAGIC + strlen(VERSION) + 1
1541             || strcmp(VERSION, (char *) (buf + 4)) != 0)
1542         {
1543                 info_error
1544                   ((char *) _("Your infokey file `%s' is out of date -- run infokey to update it"),
1545                     filename, NULL);
1546                 free(filename);
1547                 return 0;
1548         }
1549
1550         /* Extract the pieces.  */
1551         for (p = buf + 4 + strlen(VERSION) + 1;
1552              (unsigned int) (p - buf) < len - 4;
1553              p += n)
1554         {
1555                 int s = *p++;
1556
1557                 n = getint(&p);
1558                 if (n < 0 || (unsigned int) n > len - 4 - (p - buf))
1559                 {
1560                         info_error((char *) _("Invalid infokey file `%s' (bad section length) -- run infokey to update it"),
1561                             filename, NULL);
1562                         free(filename);
1563                         return 0;
1564                 }
1565
1566                 switch (s)
1567                 {
1568                 case INFOKEY_SECTION_INFO:
1569                         user_info_keys = p;
1570                         user_info_keys_len = n;
1571                         break;
1572                 case INFOKEY_SECTION_EA:
1573                         user_ea_keys = p;
1574                         user_ea_keys_len = n;
1575                         break;
1576                 case INFOKEY_SECTION_VAR:
1577                         user_vars = p;
1578                         user_vars_len = n;
1579                         break;
1580                 default:
1581                         info_error((char *) _("Invalid infokey file `%s' (bad section code) -- run infokey to update it"),
1582                             filename, NULL);
1583                         free(filename);
1584                         return 0;
1585                 }
1586         }
1587
1588         free(filename);
1589         return 1;
1590 }
1591
1592 /* Decode special key sequences from the infokey file.  Return zero
1593    if the key sequence includes special keys which the terminal
1594    doesn't define.
1595  */
1596 static int
1597 decode_keys(unsigned char *src, unsigned int slen,
1598     unsigned char *dst, unsigned int dlen)
1599 {
1600         unsigned char *s = src;
1601         unsigned char *d = dst;
1602
1603 #define To_dst(c) do { \
1604   if ((unsigned int) (d - dst) < dlen) *d++ = (c); \
1605 } while (0)
1606
1607         while ((unsigned int) (s - src) < slen)
1608         {
1609                 unsigned char c = ISMETA(*s) ? UNMETA(*s) : *s;
1610
1611                 if (c == SK_ESCAPE)
1612                 {
1613                         char *t;
1614                         static char lit[] = { SK_ESCAPE, NUL };
1615
1616                         switch ((unsigned int) (s + 1 - src) < slen ? s[1] : '\0')
1617                         {
1618                         case SK_RIGHT_ARROW:    t = term_kr; break;
1619                         case SK_LEFT_ARROW:     t = term_kl; break;
1620                         case SK_UP_ARROW:       t = term_ku; break;
1621                         case SK_DOWN_ARROW:     t = term_kd; break;
1622                         case SK_PAGE_UP:        t = term_kP; break;
1623                         case SK_PAGE_DOWN:      t = term_kN; break;
1624                         case SK_HOME:           t = term_kh; break;
1625                         case SK_END:            t = term_ke; break;
1626                         case SK_DELETE:         t = term_kx; break;
1627                         case SK_INSERT:         t = term_ki; break;
1628                         case SK_LITERAL:
1629                         default:                t = lit; break;
1630                         }
1631                         if (t == NULL)
1632                                 return 0;
1633                         while (*t)
1634                                 To_dst(ISMETA(*s) ? Meta(*t++) : *t++);
1635                         s += 2;
1636                 }
1637                 else
1638                 {
1639                         if (ISMETA(*s))
1640                                 To_dst(Meta(*s++));
1641                         else
1642                                 To_dst(*s++);
1643                 }
1644         }
1645
1646         To_dst('\0');
1647
1648         return 1;
1649
1650 #undef To_dst
1651
1652 }
1653
1654 /* Convert an infokey file section to keymap bindings.  Return false if
1655    the default bindings are to be suppressed.  */
1656 static int
1657 section_to_keymaps(Keymap map, unsigned char *table, unsigned int len)
1658 {
1659         int stop;
1660         unsigned char *p;
1661         unsigned char *seq = NULL;
1662         unsigned int seqlen = 0;
1663         enum { getseq, gotseq, getaction } state = getseq;
1664
1665         stop = len > 0 ? table[0] : 0;
1666
1667         for (p = table + 1; (unsigned int) (p - table) < len; p++)
1668         {
1669                 switch (state)
1670                 {
1671                 case getseq:
1672                         if (*p)
1673                         {
1674                                 seq = p;
1675                                 state = gotseq;
1676                         }
1677                         break;
1678
1679                 case gotseq:
1680                         if (!*p)
1681                         {
1682                                 seqlen = p - seq;
1683                                 state = getaction;
1684                         }
1685                         break;
1686
1687                 case getaction:
1688                         {
1689                                 unsigned int action = *p;
1690                                 unsigned char keyseq[256];
1691                                 KEYMAP_ENTRY ke;
1692
1693                                 state = getseq;
1694                                 /* If decode_keys returns zero, it
1695                                    means that seq includes keys which
1696                                    the terminal doesn't support, like
1697                                    PageDown.  In that case, don't bind
1698                                    the key sequence.  */
1699                                 if (decode_keys(seq, seqlen, keyseq,
1700                                                 sizeof keyseq))
1701                                 {
1702                                         keyseq[sizeof keyseq - 1] = '\0';
1703                                         ke.type = ISFUNC;
1704                                         ke.function =
1705                                           action < A_NCOMMANDS
1706                                           ? &function_doc_array[action]
1707                                           : NULL;
1708                                         keymap_bind_keyseq(map,
1709                                             (const char *) keyseq, &ke);
1710                                 }
1711                         }
1712                         break;
1713                 }
1714         }
1715         if (state != getseq)
1716                 info_error((char *) _("Bad data in infokey file -- some key bindings ignored"),
1717                     NULL, NULL);
1718         return !stop;
1719 }
1720
1721 /* Convert an infokey file section to variable settings.
1722  */
1723 static void
1724 section_to_vars(unsigned char *table, unsigned int len)
1725 {
1726         enum { getvar, gotvar, getval, gotval } state = getvar;
1727         unsigned char *var = NULL;
1728         unsigned char *val = NULL;
1729         unsigned char *p;
1730
1731         for (p = table; (unsigned int) (p - table) < len; p++)
1732           {
1733             switch (state)
1734               {
1735               case getvar:
1736                 if (*p)
1737                   {
1738                     var = p;
1739                     state = gotvar;
1740                   }
1741                 break;
1742
1743               case gotvar:
1744                 if (!*p)
1745                   state = getval;
1746                 break;
1747
1748               case getval:
1749                 if (*p)
1750                   {
1751                     val = p;
1752                     state = gotval;
1753                   }
1754                 break;
1755
1756               case gotval:
1757                 if (!*p)
1758                   {
1759                     set_variable_to_value((char *) var, (char *) val);
1760                     state = getvar;
1761                   }
1762                 break;
1763               }
1764           }
1765       if (state != getvar)
1766         info_error((char *) _("Bad data in infokey file -- some var settings ignored"),
1767             NULL, NULL);
1768 }
1769
1770 void
1771 initialize_info_keymaps (void)
1772 {
1773   int i;
1774   int suppress_info_default_bindings = 0;
1775   int suppress_ea_default_bindings = 0;
1776
1777   if (!info_keymap)
1778     {
1779       info_keymap = keymap_make_keymap ();
1780       echo_area_keymap = keymap_make_keymap ();
1781     }
1782
1783   /* Bind the echo area insert routines. */
1784   for (i = 0; i < 256; i++)
1785     if (isprint (i))
1786       echo_area_keymap[i].function = InfoCmd(ea_insert);
1787
1788   /* Get user-defined keys and variables.  */
1789   if (fetch_user_maps())
1790     {
1791       if (user_info_keys_len && user_info_keys[0])
1792         suppress_info_default_bindings = 1;
1793       if (user_ea_keys_len && user_ea_keys[0])
1794         suppress_ea_default_bindings = 1;
1795     }
1796
1797   /* Apply the default bindings, unless the user says to suppress
1798      them.  */
1799   if (vi_keys_p)
1800     {
1801       if (!suppress_info_default_bindings)
1802         section_to_keymaps(info_keymap, default_vi_like_info_keys,
1803                            sizeof(default_vi_like_info_keys));
1804       if (!suppress_ea_default_bindings)
1805           section_to_keymaps(echo_area_keymap, default_vi_like_ea_keys,
1806                              sizeof(default_vi_like_ea_keys));
1807     }
1808   else
1809     {
1810       if (!suppress_info_default_bindings)
1811         section_to_keymaps(info_keymap, default_emacs_like_info_keys,
1812                            sizeof(default_emacs_like_info_keys));
1813       if (!suppress_ea_default_bindings)
1814           section_to_keymaps(echo_area_keymap, default_emacs_like_ea_keys,
1815                              sizeof(default_emacs_like_ea_keys));
1816     }
1817
1818   /* If the user specified custom bindings, apply them on top of the
1819      default ones.  */
1820   if (user_info_keys_len)
1821     section_to_keymaps(info_keymap, user_info_keys, user_info_keys_len);
1822
1823   if (user_ea_keys_len)
1824     section_to_keymaps(echo_area_keymap, user_ea_keys, user_ea_keys_len);
1825
1826   if (user_vars_len)
1827     section_to_vars(user_vars, user_vars_len);
1828 }
1829
1830 #endif /* defined(INFOKEY) */
1831 /* vim: set sw=2 cino={1s>2sn-s^-se-s: */