Fix incomplete stack traces by gdb.
[dragonfly.git] / contrib / texinfo-4 / info / infomap.c
blobc7dc2f4aea9faad7e0bdbeac2fedc44876c8bb93
1 /* infomap.c -- keymaps for Info.
2 $Id: infomap.c,v 1.10 2004/07/30 20:43:40 karl Exp $
4 Copyright (C) 1993, 1997, 1998, 1999, 2001, 2002, 2003, 2004 Free Software
5 Foundation, Inc.
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.
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.
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.
21 Written by Brian Fox (bfox@ai.mit.edu). */
23 #include "info.h"
24 #include "infomap.h"
25 #include "funs.h"
26 #include "terminal.h"
28 #if defined(INFOKEY)
29 #include "infokey.h"
30 #include "variables.h"
31 #endif /* INFOKEY */
33 static int keymap_bind_keyseq (Keymap map, const char *keyseq,
34 KEYMAP_ENTRY *keyentry);
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)
41 int i;
42 Keymap keymap;
44 keymap = (Keymap)xmalloc (256 * sizeof (KEYMAP_ENTRY));
46 for (i = 0; i < 256; i++)
48 keymap[i].type = ISFUNC;
49 keymap[i].function = (InfoCommand *)NULL;
52 for (i = 'A'; i < ('Z' + 1); i++)
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);
62 return (keymap);
65 #if defined(INFOKEY)
66 static FUNCTION_KEYSEQ *
67 find_function_keyseq (Keymap map, int c, Keymap rootmap)
69 FUNCTION_KEYSEQ *k;
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)
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;
89 return k;
92 static void
93 add_function_keyseq (InfoCommand *function,
94 const char *keyseq, Keymap rootmap)
96 FUNCTION_KEYSEQ *ks;
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;
109 static void
110 remove_function_keyseq (InfoCommand *function,
111 const char *keyseq, Keymap rootmap)
114 FUNCTION_KEYSEQ *k, *kp;
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;
130 #endif /* INFOKEY */
132 /* Return a new keymap which is a copy of MAP. */
133 Keymap
134 keymap_copy_keymap (Keymap map, Keymap rootmap, Keymap newroot)
136 int i;
137 Keymap keymap;
138 #if defined(INFOKEY)
139 FUNCTION_KEYSEQ *ks;
140 #endif /* INFOKEY */
142 keymap = keymap_make_keymap ();
143 if (!newroot)
144 newroot = keymap;
146 for (i = 0; i < 256; i++)
148 keymap[i].type = map[i].type;
149 switch (map[i].type)
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;
165 return (keymap);
168 /* Free the keymap and its descendants. */
169 void
170 keymap_discard_keymap (Keymap map, Keymap rootmap)
172 int i;
174 if (!map)
175 return;
176 if (!rootmap)
177 rootmap = map;
179 for (i = 0; i < 256; i++)
181 #if defined(INFOKEY)
182 FUNCTION_KEYSEQ *ks;
183 #endif /* INFOKEY */
184 switch (map[i].type)
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;
194 case ISKMAP:
195 keymap_discard_keymap ((Keymap)map[i].function, rootmap);
196 break;
200 free(map);
203 /* Conditionally bind key sequence. */
204 static int
205 keymap_bind_keyseq (Keymap map,
206 const char *keyseq, KEYMAP_ENTRY *keyentry)
208 Keymap m = map;
209 const unsigned char *s = (unsigned char *) keyseq;
210 int c;
212 if (s == NULL || *s == '\0') return 0;
214 while ((c = *s++) != '\0')
216 #if defined(INFOKEY)
217 FUNCTION_KEYSEQ *ks;
218 #endif /* INFOKEY */
219 switch (m[c].type)
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))
231 return 0;
232 #endif /* !INFOKEY */
234 if (*s != '\0')
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 ();
245 break;
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;
257 if (*s != '\0')
259 m = (Keymap)m[c].function;
261 else
263 #if defined(INFOKEY)
264 add_function_keyseq (keyentry->function, keyseq, map);
265 #endif /* INFOKEY */
266 m[c] = *keyentry;
270 return 1;
273 /* Initialize the standard info keymaps. */
275 Keymap info_keymap = NULL;
276 Keymap echo_area_keymap = NULL;
278 #if !defined(INFOKEY)
280 static void
281 initialize_emacs_like_keymaps ()
283 int i;
284 Keymap map;
286 if (!info_keymap)
288 info_keymap = keymap_make_keymap ();
289 echo_area_keymap = keymap_make_keymap ();
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 ();
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;
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 ();
309 /* Bind numeric arg functions for both echo area and info window maps. */
310 for (i = '0'; i < '9' + 1; i++)
312 ((Keymap) info_keymap[ESC].function)[i].function
313 = ((Keymap) echo_area_keymap[ESC].function)[i].function
314 = info_add_digit_to_numeric_arg;
316 ((Keymap) info_keymap[ESC].function)['-'].function =
317 ((Keymap) echo_area_keymap[ESC].function)['-'].function =
318 info_add_digit_to_numeric_arg;
320 info_keymap['-'].function = info_add_digit_to_numeric_arg;
322 /* Bind the echo area routines. */
323 map = echo_area_keymap;
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;
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
351 /* Bind the echo area ESC keymap. */
352 map = (Keymap)echo_area_keymap[ESC].function;
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;
367 /* Bind the echo area Control-x keymap. */
368 map = (Keymap)echo_area_keymap[Control ('x')].function;
370 map['o'].function = info_next_window;
371 map[DEL].function = ea_backward_kill_line;
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 */
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 */
402 map = (Keymap)echo_area_keymap[Control ('x')].function;
403 keymap_bind_keyseq (map, term_kD, &map[DEL]); /* delete */
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;
427 for (i = '1'; i < '9' + 1; i++)
428 map[i].function = info_menu_digit;
429 map['0'].function = info_last_menu_item;
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;
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;
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;
476 /* Bind members in the Control-X map for Info windows. */
477 map = (Keymap)info_keymap[Control ('x')].function;
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;
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 */
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 */
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']);
530 keymap_bind_keyseq (info_keymap/*sic*/, term_kP, &map['v']); /* pageup */
533 static void
534 initialize_vi_like_keymaps ()
536 int i;
537 Keymap map;
539 if (!info_keymap)
541 info_keymap = keymap_make_keymap ();
542 echo_area_keymap = keymap_make_keymap ();
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 ();
550 /* Bind the echo area insert routines. */
551 for (i = 0; i < 256; i++)
552 echo_area_keymap[i].function = ea_insert;
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 ();
560 /* Bind numeric arg functions for both echo area and info window maps. */
561 for (i = '0'; i < '9' + 1; i++)
563 info_keymap[i].function =
564 ((Keymap) echo_area_keymap[ESC].function)[i].function =
565 info_add_digit_to_numeric_arg;
567 info_keymap['-'].function =
568 ((Keymap) echo_area_keymap[ESC].function)['-'].function =
569 info_add_digit_to_numeric_arg;
571 /* Bind the echo area routines. */
572 map = echo_area_keymap;
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;
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
601 /* Bind the echo area ESC keymap. */
602 map = (Keymap)echo_area_keymap[ESC].function;
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;
622 /* Bind the echo area Control-x keymap. */
623 map = (Keymap)echo_area_keymap[Control ('x')].function;
625 map['o'].function = info_next_window;
626 map[DEL].function = ea_backward_kill_line;
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 */
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 */
657 map = (Keymap)echo_area_keymap[Control ('x')].function;
658 keymap_bind_keyseq (map, term_kD, &map[DEL]);
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;
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;
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;
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']);
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;
762 /* Bind members in the Control-X map for Info windows. */
763 map = (Keymap)info_keymap[Control ('x')].function;
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')]);
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 */
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 */
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']);
825 keymap_bind_keyseq (info_keymap/*sic*/, term_kP, &map['v']); /* pageup */
828 void
829 initialize_info_keymaps ()
831 if (vi_keys_p)
832 initialize_vi_like_keymaps ();
833 else
834 initialize_emacs_like_keymaps ();
837 #else /* defined(INFOKEY) */
839 /* Make sure that we don't have too many command codes defined. */
841 #if A_NCOMMANDS > A_MAX_COMMAND + 1
842 #error "too many commands defined"
843 #endif
845 /* Initialize the keymaps from the .info keymap file. */
847 #define NUL '\0'
849 static unsigned char default_emacs_like_info_keys[] =
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 */
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,
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. */
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,
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,
1008 static unsigned char default_emacs_like_ea_keys[] =
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,
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. */
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,
1111 static unsigned char default_vi_like_info_keys[] =
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,
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. */
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,
1299 static unsigned char default_vi_like_ea_keys[] =
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,
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. */
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,
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;
1421 * Return the size of a file, or 0 if the size can't be determined.
1423 static unsigned long
1424 filesize(int f)
1426 long pos = lseek(f, 0L, SEEK_CUR);
1427 long sz = -1L;
1428 if (pos != -1L)
1430 sz = lseek(f, 0L, SEEK_END);
1431 lseek(f, pos, SEEK_SET);
1433 return sz == -1L ? 0L : sz;
1436 /* Get an integer from a infokey file.
1437 Integers are stored as two bytes, low order first, in radix INFOKEY_RADIX.
1439 static int
1440 getint(unsigned char **sp)
1442 int n;
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;
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)
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;
1466 /* Find and open file. */
1467 if ((filename = getenv("INFOKEY")) != NULL)
1468 filename = xstrdup(filename);
1469 else if ((homedir = getenv("HOME")) != NULL)
1471 filename = xmalloc(strlen(homedir) + 2 + strlen(INFOKEY_FILE));
1472 strcpy(filename, homedir);
1473 strcat(filename, "/");
1474 strcat(filename, INFOKEY_FILE);
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))
1483 if (filename && errno != ENOENT)
1485 info_error(filesys_error_string(filename, errno),
1486 NULL, NULL);
1487 free(filename);
1489 return 0;
1491 SET_BINARY (f);
1493 /* Ensure that the file is a reasonable size. */
1494 len = filesize(f);
1495 if (len < INFOKEY_NMAGIC + 2 || len > 100 * 1024)
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;
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)
1516 info_error((char *) _("Error reading infokey file `%s' - short read"),
1517 filename, NULL);
1518 free(buf);
1519 free(filename);
1520 return 0;
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
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;
1540 if (len < INFOKEY_NMAGIC + strlen(VERSION) + 1
1541 || strcmp(VERSION, (char *) (buf + 4)) != 0)
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;
1550 /* Extract the pieces. */
1551 for (p = buf + 4 + strlen(VERSION) + 1;
1552 (unsigned int) (p - buf) < len - 4;
1553 p += n)
1555 int s = *p++;
1557 n = getint(&p);
1558 if (n < 0 || (unsigned int) n > len - 4 - (p - buf))
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;
1566 switch (s)
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;
1588 free(filename);
1589 return 1;
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.
1596 static int
1597 decode_keys(unsigned char *src, unsigned int slen,
1598 unsigned char *dst, unsigned int dlen)
1600 unsigned char *s = src;
1601 unsigned char *d = dst;
1603 #define To_dst(c) do { \
1604 if ((unsigned int) (d - dst) < dlen) *d++ = (c); \
1605 } while (0)
1607 while ((unsigned int) (s - src) < slen)
1609 unsigned char c = ISMETA(*s) ? UNMETA(*s) : *s;
1611 if (c == SK_ESCAPE)
1613 char *t;
1614 static char lit[] = { SK_ESCAPE, NUL };
1616 switch ((unsigned int) (s + 1 - src) < slen ? s[1] : '\0')
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;
1631 if (t == NULL)
1632 return 0;
1633 while (*t)
1634 To_dst(ISMETA(*s) ? Meta(*t++) : *t++);
1635 s += 2;
1637 else
1639 if (ISMETA(*s))
1640 To_dst(Meta(*s++));
1641 else
1642 To_dst(*s++);
1646 To_dst('\0');
1648 return 1;
1650 #undef To_dst
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)
1659 int stop;
1660 unsigned char *p;
1661 unsigned char *seq = NULL;
1662 unsigned int seqlen = 0;
1663 enum { getseq, gotseq, getaction } state = getseq;
1665 stop = len > 0 ? table[0] : 0;
1667 for (p = table + 1; (unsigned int) (p - table) < len; p++)
1669 switch (state)
1671 case getseq:
1672 if (*p)
1674 seq = p;
1675 state = gotseq;
1677 break;
1679 case gotseq:
1680 if (!*p)
1682 seqlen = p - seq;
1683 state = getaction;
1685 break;
1687 case getaction:
1689 unsigned int action = *p;
1690 unsigned char keyseq[256];
1691 KEYMAP_ENTRY ke;
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))
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);
1712 break;
1715 if (state != getseq)
1716 info_error((char *) _("Bad data in infokey file -- some key bindings ignored"),
1717 NULL, NULL);
1718 return !stop;
1721 /* Convert an infokey file section to variable settings.
1723 static void
1724 section_to_vars(unsigned char *table, unsigned int len)
1726 enum { getvar, gotvar, getval, gotval } state = getvar;
1727 unsigned char *var = NULL;
1728 unsigned char *val = NULL;
1729 unsigned char *p;
1731 for (p = table; (unsigned int) (p - table) < len; p++)
1733 switch (state)
1735 case getvar:
1736 if (*p)
1738 var = p;
1739 state = gotvar;
1741 break;
1743 case gotvar:
1744 if (!*p)
1745 state = getval;
1746 break;
1748 case getval:
1749 if (*p)
1751 val = p;
1752 state = gotval;
1754 break;
1756 case gotval:
1757 if (!*p)
1759 set_variable_to_value((char *) var, (char *) val);
1760 state = getvar;
1762 break;
1765 if (state != getvar)
1766 info_error((char *) _("Bad data in infokey file -- some var settings ignored"),
1767 NULL, NULL);
1770 void
1771 initialize_info_keymaps (void)
1773 int i;
1774 int suppress_info_default_bindings = 0;
1775 int suppress_ea_default_bindings = 0;
1777 if (!info_keymap)
1779 info_keymap = keymap_make_keymap ();
1780 echo_area_keymap = keymap_make_keymap ();
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);
1788 /* Get user-defined keys and variables. */
1789 if (fetch_user_maps())
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;
1797 /* Apply the default bindings, unless the user says to suppress
1798 them. */
1799 if (vi_keys_p)
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));
1808 else
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));
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);
1823 if (user_ea_keys_len)
1824 section_to_keymaps(echo_area_keymap, user_ea_keys, user_ea_keys_len);
1826 if (user_vars_len)
1827 section_to_vars(user_vars, user_vars_len);
1830 #endif /* defined(INFOKEY) */
1831 /* vim: set sw=2 cino={1s>2sn-s^-se-s: */