diff options
Diffstat (limited to 'Build/source/utils/texinfo/info/infomap.c')
-rw-r--r-- | Build/source/utils/texinfo/info/infomap.c | 1831 |
1 files changed, 1831 insertions, 0 deletions
diff --git a/Build/source/utils/texinfo/info/infomap.c b/Build/source/utils/texinfo/info/infomap.c new file mode 100644 index 00000000000..c7dc2f4aea9 --- /dev/null +++ b/Build/source/utils/texinfo/info/infomap.c @@ -0,0 +1,1831 @@ +/* infomap.c -- keymaps for Info. + $Id: infomap.c,v 1.10 2004/07/30 20:43:40 karl Exp $ + + Copyright (C) 1993, 1997, 1998, 1999, 2001, 2002, 2003, 2004 Free Software + Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + Written by Brian Fox (bfox@ai.mit.edu). */ + +#include "info.h" +#include "infomap.h" +#include "funs.h" +#include "terminal.h" + +#if defined(INFOKEY) +#include "infokey.h" +#include "variables.h" +#endif /* INFOKEY */ + +static int keymap_bind_keyseq (Keymap map, const char *keyseq, + KEYMAP_ENTRY *keyentry); + +/* Return a new keymap which has all the uppercase letters mapped to run + the function info_do_lowercase_version (). */ +Keymap +keymap_make_keymap (void) +{ + int i; + Keymap keymap; + + keymap = (Keymap)xmalloc (256 * sizeof (KEYMAP_ENTRY)); + + for (i = 0; i < 256; i++) + { + keymap[i].type = ISFUNC; + keymap[i].function = (InfoCommand *)NULL; + } + + for (i = 'A'; i < ('Z' + 1); i++) + { + keymap[i].type = ISFUNC; +#if defined(INFOKEY) + keymap[Meta(i)].type = ISFUNC; + keymap[Meta(i)].function = +#endif /* INFOKEY */ + keymap[i].function = InfoCmd(info_do_lowercase_version); + } + + return (keymap); +} + +#if defined(INFOKEY) +static FUNCTION_KEYSEQ * +find_function_keyseq (Keymap map, int c, Keymap rootmap) +{ + FUNCTION_KEYSEQ *k; + + if (map[c].type != ISFUNC) + abort(); + if (map[c].function == NULL) + return NULL; + for (k = map[c].function->keys; k; k = k->next) + { + const unsigned char *p; + Keymap m = rootmap; + if (k->map != rootmap) + continue; + for (p = (unsigned char *) k->keyseq; *p && m[*p].type == ISKMAP; p++) + m = (Keymap)m[*p].function; + if (*p != c || p[1]) + continue; + if (m[*p].type != ISFUNC) + abort (); + break; + } + return k; +} + +static void +add_function_keyseq (InfoCommand *function, + const char *keyseq, Keymap rootmap) +{ + FUNCTION_KEYSEQ *ks; + + if (function == NULL || + function == InfoCmd(info_do_lowercase_version) || + function == InfoCmd(ea_insert)) + return; + ks = (FUNCTION_KEYSEQ *)xmalloc (sizeof(FUNCTION_KEYSEQ)); + ks->next = function->keys; + ks->map = rootmap; + ks->keyseq = xstrdup(keyseq); + function->keys = ks; +} + +static void +remove_function_keyseq (InfoCommand *function, + const char *keyseq, Keymap rootmap) +{ + + FUNCTION_KEYSEQ *k, *kp; + + if (function == NULL || + function == InfoCmd(info_do_lowercase_version) || + function == InfoCmd(ea_insert)) + return; + for (kp = NULL, k = function->keys; k; kp = k, k = k->next) + if (k->map == rootmap && strcmp(k->keyseq, keyseq) == 0) + break; + if (!k) + abort (); + if (kp) + kp->next = k->next; + else + function->keys = k->next; +} +#endif /* INFOKEY */ + +/* Return a new keymap which is a copy of MAP. */ +Keymap +keymap_copy_keymap (Keymap map, Keymap rootmap, Keymap newroot) +{ + int i; + Keymap keymap; +#if defined(INFOKEY) + FUNCTION_KEYSEQ *ks; +#endif /* INFOKEY */ + + keymap = keymap_make_keymap (); + if (!newroot) + newroot = keymap; + + for (i = 0; i < 256; i++) + { + keymap[i].type = map[i].type; + switch (map[i].type) + { + case ISFUNC: + keymap[i].function = map[i].function; +#if defined(INFOKEY) + ks = find_function_keyseq (map, i, rootmap); + if (ks) + add_function_keyseq(map[i].function, ks->keyseq, newroot); +#endif /* INFOKEY */ + break; + case ISKMAP: + keymap[i].function = (InfoCommand *)keymap_copy_keymap + ((Keymap)map[i].function, rootmap, NULL); + break; + } + } + return (keymap); +} + +/* Free the keymap and its descendants. */ +void +keymap_discard_keymap (Keymap map, Keymap rootmap) +{ + int i; + + if (!map) + return; + if (!rootmap) + rootmap = map; + + for (i = 0; i < 256; i++) + { +#if defined(INFOKEY) + FUNCTION_KEYSEQ *ks; +#endif /* INFOKEY */ + switch (map[i].type) + { + case ISFUNC: +#if defined(INFOKEY) + ks = find_function_keyseq(map, i, rootmap); + if (ks) + remove_function_keyseq (map[i].function, ks->keyseq, rootmap); +#endif /* INFOKEY */ + break; + + case ISKMAP: + keymap_discard_keymap ((Keymap)map[i].function, rootmap); + break; + + } + } + free(map); +} + +/* Conditionally bind key sequence. */ +static int +keymap_bind_keyseq (Keymap map, + const char *keyseq, KEYMAP_ENTRY *keyentry) +{ + Keymap m = map; + const unsigned char *s = (unsigned char *) keyseq; + int c; + + if (s == NULL || *s == '\0') return 0; + + while ((c = *s++) != '\0') + { +#if defined(INFOKEY) + FUNCTION_KEYSEQ *ks; +#endif /* INFOKEY */ + switch (m[c].type) + { + case ISFUNC: +#if defined(INFOKEY) + ks = find_function_keyseq(m, c, map); + if (ks) + remove_function_keyseq (m[c].function, ks->keyseq, map); +#else /* !INFOKEY */ + if (!(m[c].function == NULL || ( + m != map && + m[c].function == InfoCmd(info_do_lowercase_version)) + )) + return 0; +#endif /* !INFOKEY */ + + if (*s != '\0') + { + m[c].type = ISKMAP; + /* Here we are casting the Keymap pointer returned from + keymap_make_keymap to an InfoCommand pointer. Ugh. + This makes the `function' structure garbage + if it's actually interpreted as an InfoCommand. + Should really be using a union, and taking steps to + avoid the possible error. */ + m[c].function = (InfoCommand *)keymap_make_keymap (); + } + break; + + case ISKMAP: +#if defined(INFOKEY) + if (*s == '\0') + keymap_discard_keymap ((Keymap)m[c].function, map); +#else /* !INFOKEY */ + if (*s == '\0') + return 0; +#endif + break; + } + if (*s != '\0') + { + m = (Keymap)m[c].function; + } + else + { +#if defined(INFOKEY) + add_function_keyseq (keyentry->function, keyseq, map); +#endif /* INFOKEY */ + m[c] = *keyentry; + } + } + + return 1; +} + +/* Initialize the standard info keymaps. */ + +Keymap info_keymap = NULL; +Keymap echo_area_keymap = NULL; + +#if !defined(INFOKEY) + +static void +initialize_emacs_like_keymaps () +{ + int i; + Keymap map; + + if (!info_keymap) + { + info_keymap = keymap_make_keymap (); + echo_area_keymap = keymap_make_keymap (); + } + + info_keymap[ESC].type = ISKMAP; + info_keymap[ESC].function = (InfoCommand *)keymap_make_keymap (); + info_keymap[Control ('x')].type = ISKMAP; + info_keymap[Control ('x')].function = (InfoCommand *)keymap_make_keymap (); + + /* Bind the echo area insert routines. Let's make all characters + insertable by default, regardless of which character set we might + be using. */ + for (i = 0; i < 256; i++) + echo_area_keymap[i].function = ea_insert; + + echo_area_keymap[ESC].type = ISKMAP; + echo_area_keymap[ESC].function = (InfoCommand *) keymap_make_keymap (); + echo_area_keymap[Control ('x')].type = ISKMAP; + echo_area_keymap[Control ('x')].function + = (InfoCommand *) keymap_make_keymap (); + + /* Bind numeric arg functions for both echo area and info window maps. */ + for (i = '0'; i < '9' + 1; i++) + { + ((Keymap) info_keymap[ESC].function)[i].function + = ((Keymap) echo_area_keymap[ESC].function)[i].function + = info_add_digit_to_numeric_arg; + } + ((Keymap) info_keymap[ESC].function)['-'].function = + ((Keymap) echo_area_keymap[ESC].function)['-'].function = + info_add_digit_to_numeric_arg; + + info_keymap['-'].function = info_add_digit_to_numeric_arg; + + /* Bind the echo area routines. */ + map = echo_area_keymap; + + map[Control ('a')].function = ea_beg_of_line; + map[Control ('b')].function = ea_backward; + map[Control ('d')].function = ea_delete; + map[Control ('e')].function = ea_end_of_line; + map[Control ('f')].function = ea_forward; + map[Control ('g')].function = ea_abort; + map[Control ('h')].function = ea_rubout; + map[Control ('k')].function = ea_kill_line; + map[Control ('l')].function = info_redraw_display; + map[Control ('q')].function = ea_quoted_insert; + map[Control ('t')].function = ea_transpose_chars; + map[Control ('u')].function = info_universal_argument; + map[Control ('y')].function = ea_yank; + + map[LFD].function = ea_newline; + map[RET].function = ea_newline; + map[SPC].function = ea_complete; + map[TAB].function = ea_complete; + map['?'].function = ea_possible_completions; +#ifdef __MSDOS__ + /* PC users will lynch me if I don't give them their usual DEL effect... */ + map[DEL].function = ea_delete; +#else + map[DEL].function = ea_rubout; +#endif + + /* Bind the echo area ESC keymap. */ + map = (Keymap)echo_area_keymap[ESC].function; + + map[Control ('g')].function = ea_abort; + map[Control ('v')].function = ea_scroll_completions_window; + map['b'].function = ea_backward_word; + map['d'].function = ea_kill_word; + map['f'].function = ea_forward_word; +#if defined (NAMED_FUNCTIONS) + /* map['x'].function = info_execute_command; */ +#endif /* NAMED_FUNCTIONS */ + map['y'].function = ea_yank_pop; + map['?'].function = ea_possible_completions; + map[TAB].function = ea_tab_insert; + map[DEL].function = ea_backward_kill_word; + + /* Bind the echo area Control-x keymap. */ + map = (Keymap)echo_area_keymap[Control ('x')].function; + + map['o'].function = info_next_window; + map[DEL].function = ea_backward_kill_line; + + /* Arrow key bindings for echo area keymaps. It seems that some + terminals do not match their termcap entries, so it's best to just + define everything with both of the usual prefixes. */ + map = echo_area_keymap; + keymap_bind_keyseq (map, term_ku, &map[Control ('p')]); /* up */ + keymap_bind_keyseq (map, "\033OA", &map[Control ('p')]); + keymap_bind_keyseq (map, "\033[A", &map[Control ('p')]); + keymap_bind_keyseq (map, term_kd, &map[Control ('n')]); /* down */ + keymap_bind_keyseq (map, "\033OB", &map[Control ('n')]); + keymap_bind_keyseq (map, "\033[B", &map[Control ('n')]); + keymap_bind_keyseq (map, term_kr, &map[Control ('f')]); /* right */ + keymap_bind_keyseq (map, "\033OC", &map[Control ('f')]); + keymap_bind_keyseq (map, "\033[C", &map[Control ('f')]); + keymap_bind_keyseq (map, term_kl, &map[Control ('b')]); /* left */ + keymap_bind_keyseq (map, "\033OD", &map[Control ('b')]); + keymap_bind_keyseq (map, "\033[D", &map[Control ('b')]); + keymap_bind_keyseq (map, term_kD, &map[DEL]); /* delete */ + keymap_bind_keyseq (map, term_kh, &map[Control ('a')]); /* home */ + keymap_bind_keyseq (map, term_ke, &map[Control ('e')]); /* end */ + + map = (Keymap)echo_area_keymap[ESC].function; + keymap_bind_keyseq (map, term_kl, &map['b']); /* left */ + keymap_bind_keyseq (map, "\033OA", &map['b']); + keymap_bind_keyseq (map, "\033[A", &map['b']); + keymap_bind_keyseq (map, term_kr, &map['f']); /* right */ + keymap_bind_keyseq (map, "\033OB", &map['f']); + keymap_bind_keyseq (map, "\033[B", &map['f']); + keymap_bind_keyseq (map, term_kD, &map[DEL]); /* delete */ + + map = (Keymap)echo_area_keymap[Control ('x')].function; + keymap_bind_keyseq (map, term_kD, &map[DEL]); /* delete */ + + /* Bind commands for Info window keymaps. */ + map = info_keymap; + map[TAB].function = info_move_to_next_xref; + map[LFD].function = info_select_reference_this_line; + map[RET].function = info_select_reference_this_line; + map[SPC].function = info_scroll_forward; + map[Control ('a')].function = info_beginning_of_line; + map[Control ('b')].function = info_backward_char; + map[Control ('e')].function = info_end_of_line; + map[Control ('f')].function = info_forward_char; + map[Control ('g')].function = info_abort_key; + map[Control ('h')].function = info_get_help_window; + map[Control ('l')].function = info_redraw_display; + map[Control ('n')].function = info_next_line; + map[Control ('p')].function = info_prev_line; + map[Control ('r')].function = isearch_backward; + map[Control ('s')].function = isearch_forward; + map[Control ('u')].function = info_universal_argument; + map[Control ('v')].function = info_scroll_forward_page_only; + map[','].function = info_next_index_match; + map['/'].function = info_search; + + for (i = '1'; i < '9' + 1; i++) + map[i].function = info_menu_digit; + map['0'].function = info_last_menu_item; + + map['<'].function = info_first_node; + map['>'].function = info_last_node; + map['?'].function = info_get_help_window; + map['['].function = info_global_prev_node; + map[']'].function = info_global_next_node; + + map['b'].function = info_beginning_of_node; + map['d'].function = info_dir_node; + map['e'].function = info_end_of_node; + map['f'].function = info_xref_item; + map['g'].function = info_goto_node; + map['G'].function = info_menu_sequence; + map['h'].function = info_get_info_help_node; + map['i'].function = info_index_search; + map['I'].function = info_goto_invocation_node; + map['l'].function = info_history_node; + map['m'].function = info_menu_item; + map['n'].function = info_next_node; + map['O'].function = info_goto_invocation_node; + map['p'].function = info_prev_node; + map['q'].function = info_quit; + map['r'].function = info_xref_item; + map['s'].function = info_search; + map['S'].function = info_search_case_sensitively; + map['t'].function = info_top_node; + map['u'].function = info_up_node; + map[DEL].function = info_scroll_backward; + + /* Bind members in the ESC map for Info windows. */ + map = (Keymap)info_keymap[ESC].function; + map[Control ('f')].function = info_show_footnotes; + map[Control ('g')].function = info_abort_key; + map[TAB].function = info_move_to_prev_xref; + map[Control ('v')].function = info_scroll_other_window; + map['<'].function = info_beginning_of_node; + map['>'].function = info_end_of_node; + map['b'].function = info_backward_word; + map['f'].function = info_forward_word; + map['r'].function = info_move_to_window_line; + map['v'].function = info_scroll_backward_page_only; +#if defined (NAMED_FUNCTIONS) + map['x'].function = info_execute_command; +#endif /* NAMED_FUNCTIONS */ + map[DEL].function = info_scroll_other_window_backward; + + /* Bind members in the Control-X map for Info windows. */ + map = (Keymap)info_keymap[Control ('x')].function; + + map[Control ('b')].function = list_visited_nodes; + map[Control ('c')].function = info_quit; + map[Control ('f')].function = info_view_file; + map[Control ('g')].function = info_abort_key; + map[Control ('v')].function = info_view_file; + map['0'].function = info_delete_window; + map['1'].function = info_keep_one_window; + map['2'].function = info_split_window; + map['^'].function = info_grow_window; + map['b'].function = select_visited_node; + map['k'].function = info_kill_node; + map['n'].function = info_search_next; + map['N'].function = info_search_previous; + map['o'].function = info_next_window; + map['t'].function = info_tile_windows; + map['w'].function = info_toggle_wrap; + + /* Arrow key bindings for Info windows keymap. */ + map = info_keymap; + keymap_bind_keyseq (map, term_kN, &map[Control ('v')]); /* pagedown */ + keymap_bind_keyseq (map, term_ku, &map[Control ('p')]); /* up */ + keymap_bind_keyseq (map, "\033OA", &map[Control ('p')]); + keymap_bind_keyseq (map, "\033[A", &map[Control ('p')]); + keymap_bind_keyseq (map, term_kd, &map[Control ('n')]); /* down */ + keymap_bind_keyseq (map, "\033OB", &map[Control ('n')]); + keymap_bind_keyseq (map, "\033[B", &map[Control ('n')]); + keymap_bind_keyseq (map, term_kr, &map[Control ('f')]); /* right */ + keymap_bind_keyseq (map, "\033OC", &map[Control ('f')]); + keymap_bind_keyseq (map, "\033[C", &map[Control ('f')]); + keymap_bind_keyseq (map, term_kl, &map[Control ('b')]); /* left */ + keymap_bind_keyseq (map, "\033OD", &map[Control ('b')]); + keymap_bind_keyseq (map, "\033[D", &map[Control ('b')]); + keymap_bind_keyseq (map, term_kh, &map['b']); /* home */ + keymap_bind_keyseq (map, term_ke, &map['e']); /* end */ + keymap_bind_keyseq (map, term_kD, &map[DEL]); /* delete */ + + map = (Keymap)info_keymap[ESC].function; + keymap_bind_keyseq (map, term_kl, &map['b']); /* left */ + keymap_bind_keyseq (map, "\033OA", &map['b']); + keymap_bind_keyseq (map, "\033[A", &map['b']); + keymap_bind_keyseq (map, term_kr, &map['f']); /* right */ + keymap_bind_keyseq (map, "\033OB", &map['f']); + keymap_bind_keyseq (map, "\033[B", &map['f']); + keymap_bind_keyseq (map, term_kN, &map[Control ('v')]); /* pagedown */ + keymap_bind_keyseq (map, term_kP, &map[DEL]); /* pageup */ + keymap_bind_keyseq (map, term_kD, &map[DEL]); /* delete */ + + /* The alternative to this definition of a `main map' key in the + `ESC map' section, is something like: + keymap_bind_keyseq (map, term_kP, &((KeyMap)map[ESC].function).map['v']); + */ + keymap_bind_keyseq (info_keymap/*sic*/, term_kP, &map['v']); /* pageup */ +} + +static void +initialize_vi_like_keymaps () +{ + int i; + Keymap map; + + if (!info_keymap) + { + info_keymap = keymap_make_keymap (); + echo_area_keymap = keymap_make_keymap (); + } + + info_keymap[ESC].type = ISKMAP; + info_keymap[ESC].function = (InfoCommand *)keymap_make_keymap (); + info_keymap[Control ('x')].type = ISKMAP; + info_keymap[Control ('x')].function = (InfoCommand *)keymap_make_keymap (); + + /* Bind the echo area insert routines. */ + for (i = 0; i < 256; i++) + echo_area_keymap[i].function = ea_insert; + + echo_area_keymap[ESC].type = ISKMAP; + echo_area_keymap[ESC].function = (InfoCommand *)keymap_make_keymap (); + echo_area_keymap[Control ('x')].type = ISKMAP; + echo_area_keymap[Control ('x')].function = + (InfoCommand *)keymap_make_keymap (); + + /* Bind numeric arg functions for both echo area and info window maps. */ + for (i = '0'; i < '9' + 1; i++) + { + info_keymap[i].function = + ((Keymap) echo_area_keymap[ESC].function)[i].function = + info_add_digit_to_numeric_arg; + } + info_keymap['-'].function = + ((Keymap) echo_area_keymap[ESC].function)['-'].function = + info_add_digit_to_numeric_arg; + + /* Bind the echo area routines. */ + map = echo_area_keymap; + + map[Control ('a')].function = ea_beg_of_line; + map[Control ('b')].function = ea_backward; + map[Control ('d')].function = ea_delete; + map[Control ('e')].function = ea_end_of_line; + map[Control ('f')].function = ea_forward; + map[Control ('g')].function = ea_abort; + map[Control ('h')].function = ea_rubout; + map[Control ('k')].function = ea_kill_line; + map[Control ('l')].function = info_redraw_display; + map[Control ('q')].function = ea_quoted_insert; + map[Control ('t')].function = ea_transpose_chars; + map[Control ('u')].function = ea_abort; + map[Control ('v')].function = ea_quoted_insert; + map[Control ('y')].function = ea_yank; + + map[LFD].function = ea_newline; + map[RET].function = ea_newline; + map[SPC].function = ea_complete; + map[TAB].function = ea_complete; + map['?'].function = ea_possible_completions; +#ifdef __MSDOS__ + /* PC users will lynch me if I don't give them their usual DEL effect... */ + map[DEL].function = ea_delete; +#else + map[DEL].function = ea_rubout; +#endif + + /* Bind the echo area ESC keymap. */ + map = (Keymap)echo_area_keymap[ESC].function; + + map[Control ('g')].function = ea_abort; + map[Control ('h')].function = ea_backward_kill_word; + map[Control ('v')].function = ea_scroll_completions_window; + map['0'].function = ea_beg_of_line; + map['$'].function = ea_end_of_line; + map['b'].function = ea_backward_word; + map['d'].function = ea_kill_word; + map['f'].function = ea_forward_word; + map['h'].function = ea_backward; + map['l'].function = ea_forward; + map['w'].function = ea_forward_word; + map['x'].function = ea_delete; + map['X'].function = ea_kill_word; + map['y'].function = ea_yank_pop; + map['?'].function = ea_possible_completions; + map[TAB].function = ea_tab_insert; + map[DEL].function = ea_kill_word; + + /* Bind the echo area Control-x keymap. */ + map = (Keymap)echo_area_keymap[Control ('x')].function; + + map['o'].function = info_next_window; + map[DEL].function = ea_backward_kill_line; + + /* Arrow key bindings for echo area keymaps. It seems that some + terminals do not match their termcap entries, so it's best to just + define everything with both of the usual prefixes. */ + map = echo_area_keymap; + keymap_bind_keyseq (map, term_ku, &map[Control ('p')]); /* up */ + keymap_bind_keyseq (map, "\033OA", &map[Control ('p')]); + keymap_bind_keyseq (map, "\033[A", &map[Control ('p')]); + keymap_bind_keyseq (map, term_kd, &map[Control ('n')]); /* down */ + keymap_bind_keyseq (map, "\033OB", &map[Control ('n')]); + keymap_bind_keyseq (map, "\033[B", &map[Control ('n')]); + keymap_bind_keyseq (map, term_kr, &map[Control ('f')]); /* right */ + keymap_bind_keyseq (map, "\033OC", &map[Control ('f')]); + keymap_bind_keyseq (map, "\033[C", &map[Control ('f')]); + keymap_bind_keyseq (map, term_kl, &map[Control ('b')]); /* left */ + keymap_bind_keyseq (map, "\033OD", &map[Control ('b')]); + keymap_bind_keyseq (map, "\033[D", &map[Control ('b')]); + keymap_bind_keyseq (map, term_kh, &map[Control ('a')]); /* home */ + keymap_bind_keyseq (map, term_ke, &map[Control ('e')]); /* end */ + keymap_bind_keyseq (map, term_kD, &map[DEL]); /* delete */ + + map = (Keymap)echo_area_keymap[ESC].function; + keymap_bind_keyseq (map, term_kl, &map['b']); /* left */ + keymap_bind_keyseq (map, "\033OA", &map['b']); + keymap_bind_keyseq (map, "\033[A", &map['b']); + keymap_bind_keyseq (map, term_kr, &map['f']); /* right */ + keymap_bind_keyseq (map, "\033OB", &map['f']); + keymap_bind_keyseq (map, "\033[B", &map['f']); + keymap_bind_keyseq (map, term_kD, &map[DEL]); /* delete */ + + map = (Keymap)echo_area_keymap[Control ('x')].function; + keymap_bind_keyseq (map, term_kD, &map[DEL]); + + /* Bind commands for Info window keymaps. */ + map = info_keymap; + map[TAB].function = info_move_to_next_xref; + map[LFD].function = info_down_line; + map[RET].function = info_down_line; + map[SPC].function = info_scroll_forward; + map[Control ('a')].function = info_beginning_of_line; + map[Control ('b')].function = info_scroll_backward_page_only; + map[Control ('d')].function = info_scroll_half_screen_down; + map[Control ('e')].function = info_down_line; + map[Control ('f')].function = info_scroll_forward_page_only; + map[Control ('g')].function = info_abort_key; + map[Control ('k')].function = info_up_line; + map[Control ('l')].function = info_redraw_display; + map[Control ('n')].function = info_down_line; + map[Control ('p')].function = info_up_line; + map[Control ('r')].function = info_redraw_display; + map[Control ('s')].function = isearch_forward; + map[Control ('u')].function = info_scroll_half_screen_up; + map[Control ('v')].function = info_scroll_forward_page_only; + map[Control ('y')].function = info_up_line; + map[','].function = info_next_index_match; + map['/'].function = info_search; + + for (i = '1'; i < '9' + 1; i++) + ((Keymap) info_keymap[ESC].function)[i].function = info_menu_digit; + ((Keymap) info_keymap[ESC].function)['0'].function = info_last_menu_item; + + map['<'].function = info_first_node; + map['>'].function = info_last_node; + map['?'].function = info_search_backward; + map['['].function = info_global_prev_node; + map[']'].function = info_global_next_node; + map['\''].function = info_history_node; + + map['b'].function = info_scroll_backward; + map['d'].function = info_scroll_half_screen_down; + map['e'].function = info_down_line; + map['E'].function = info_view_file; + map['f'].function = info_scroll_forward_page_only; + map['F'].function = info_scroll_forward_page_only; + map['g'].function = info_first_node; + map['G'].function = info_last_node; + map['h'].function = info_get_help_window; + map['H'].function = info_get_help_window; + map['i'].function = info_index_search; + map['I'].function = info_goto_invocation_node; + map['j'].function = info_next_line; + map['k'].function = info_prev_line; + map['l'].function = info_history_node; + map['m'].function = info_menu_item; + map['n'].function = info_search_next; + map['N'].function = info_search_previous; + map['O'].function = info_goto_invocation_node; + map['p'].function = info_prev_node; + map['q'].function = info_quit; + map['Q'].function = info_quit; + map['r'].function = info_redraw_display; + map['R'].function = info_redraw_display; + map['s'].function = info_search; + map['S'].function = info_search_case_sensitively; + map['t'].function = info_top_node; + map['u'].function = info_scroll_half_screen_up; + map['w'].function = info_scroll_backward_page_only_set_window; + map['y'].function = info_up_line; + map['z'].function = info_scroll_forward_page_only_set_window; + map['Z'].function = NULL; /* unbind, so it works to bind "ZZ" below */ + map[DEL].function = info_scroll_backward; + keymap_bind_keyseq (map, term_kD, &map[DEL]); + keymap_bind_keyseq (map, ":q", &map['q']); + keymap_bind_keyseq (map, ":Q", &map['q']); + keymap_bind_keyseq (map, "ZZ", &map['q']); + + /* Bind members in the ESC map for Info windows. */ + map = (Keymap)info_keymap[ESC].function; + map[Control ('f')].function = info_show_footnotes; + map[Control ('g')].function = info_abort_key; + map[TAB].function = info_move_to_prev_xref; + map[SPC].function = info_scroll_forward_page_only; + map[Control ('v')].function = info_scroll_other_window; + map['<'].function = info_beginning_of_node; + map['>'].function = info_end_of_node; + map['/'].function = info_search; + map['?'].function = info_search_backward; + map['b'].function = info_beginning_of_node; + map['d'].function = info_dir_node; + map['e'].function = info_end_of_node; + map['f'].function = info_xref_item; + map['g'].function = info_select_reference_this_line; + map['h'].function = info_get_info_help_node; + map['m'].function = info_menu_item; + map['n'].function = info_search; + map['N'].function = info_search_backward; + map['r'].function = isearch_backward; + map['s'].function = isearch_forward; + map['t'].function = info_top_node; + map['v'].function = info_scroll_backward_page_only; +#if defined (NAMED_FUNCTIONS) + map['x'].function = info_execute_command; +#endif /* NAMED_FUNCTIONS */ + map[DEL].function = info_scroll_other_window_backward; + + /* Bind members in the Control-X map for Info windows. */ + map = (Keymap)info_keymap[Control ('x')].function; + + map[Control ('b')].function = list_visited_nodes; + map[Control ('c')].function = info_quit; + map[Control ('f')].function = info_view_file; + map[Control ('g')].function = info_abort_key; + map[Control ('v')].function = info_view_file; + map[LFD].function = info_select_reference_this_line; + map[RET].function = info_select_reference_this_line; + map['0'].function = info_delete_window; + map['1'].function = info_keep_one_window; + map['2'].function = info_split_window; + map['^'].function = info_grow_window; + map['b'].function = select_visited_node; + map['g'].function = info_goto_node; + map['i'].function = info_index_search; + map['I'].function = info_goto_invocation_node; + map['k'].function = info_kill_node; + map['n'].function = info_next_node; + map['o'].function = info_next_window; + map['O'].function = info_goto_invocation_node; + map['p'].function = info_prev_node; + map['r'].function = info_xref_item; + map['t'].function = info_tile_windows; + map['u'].function = info_up_node; + map['w'].function = info_toggle_wrap; + map[','].function = info_next_index_match; + keymap_bind_keyseq (info_keymap, ":e", &map[Control ('v')]); + + /* Arrow key bindings for Info windows keymap. */ + map = info_keymap; + keymap_bind_keyseq (map, term_kN, &map[Control ('v')]); /* pagedown */ + keymap_bind_keyseq (map, term_ku, &map[Control ('p')]); /* up */ + keymap_bind_keyseq (map, "\033OA", &map[Control ('p')]); + keymap_bind_keyseq (map, "\033[A", &map[Control ('p')]); + keymap_bind_keyseq (map, term_kd, &map[Control ('n')]); /* down */ + keymap_bind_keyseq (map, "\033OB", &map[Control ('n')]); + keymap_bind_keyseq (map, "\033[B", &map[Control ('n')]); + keymap_bind_keyseq (map, term_kr, &map[Control ('f')]); /* right */ + keymap_bind_keyseq (map, "\033OC", &map[Control ('f')]); + keymap_bind_keyseq (map, "\033[C", &map[Control ('f')]); + keymap_bind_keyseq (map, term_kl, &map[Control ('b')]); /* left */ + keymap_bind_keyseq (map, "\033OD", &map[Control ('b')]); + keymap_bind_keyseq (map, "\033[D", &map[Control ('b')]); + keymap_bind_keyseq (map, term_kh, &map['b']); /* home */ + keymap_bind_keyseq (map, term_ke, &map['e']); /* end */ + + map = (Keymap)info_keymap[ESC].function; + keymap_bind_keyseq (map, term_kl, &map['b']); /* left */ + keymap_bind_keyseq (map, "\033OA", &map['b']); + keymap_bind_keyseq (map, "\033[A", &map['b']); + keymap_bind_keyseq (map, term_kr, &map['f']); /* right */ + keymap_bind_keyseq (map, "\033OB", &map['f']); + keymap_bind_keyseq (map, "\033[B", &map['f']); + keymap_bind_keyseq (map, term_kN, &map[Control ('v')]); /* pagedown */ + keymap_bind_keyseq (map, term_kP, &map[DEL]); /* pageup */ + keymap_bind_keyseq (map, term_kD, &map[DEL]); /* delete */ + + /* The alternative to this definition of a `main map' key in the + `ESC map' section, is something like: + keymap_bind_keyseq (map, term_kP, &((KeyMap)map[ESC].function).map['v']); + */ + keymap_bind_keyseq (info_keymap/*sic*/, term_kP, &map['v']); /* pageup */ +} + +void +initialize_info_keymaps () +{ + if (vi_keys_p) + initialize_vi_like_keymaps (); + else + initialize_emacs_like_keymaps (); +} + +#else /* defined(INFOKEY) */ + +/* Make sure that we don't have too many command codes defined. */ + +#if A_NCOMMANDS > A_MAX_COMMAND + 1 +#error "too many commands defined" +#endif + +/* Initialize the keymaps from the .info keymap file. */ + +#define NUL '\0' + +static unsigned char default_emacs_like_info_keys[] = +{ + 0, /* suppress-default-keybindings flag */ + TAB, NUL, A_info_move_to_next_xref, + LFD, NUL, A_info_select_reference_this_line, + RET, NUL, A_info_select_reference_this_line, + SPC, NUL, A_info_scroll_forward, + CONTROL('a'), NUL, A_info_beginning_of_line, + CONTROL('b'), NUL, A_info_backward_char, + CONTROL('e'), NUL, A_info_end_of_line, + CONTROL('f'), NUL, A_info_forward_char, + CONTROL('g'), NUL, A_info_abort_key, + CONTROL('h'), NUL, A_info_get_help_window, + CONTROL('l'), NUL, A_info_redraw_display, + CONTROL('n'), NUL, A_info_next_line, + CONTROL('p'), NUL, A_info_prev_line, + CONTROL('r'), NUL, A_isearch_backward, + CONTROL('s'), NUL, A_isearch_forward, + CONTROL('u'), NUL, A_info_universal_argument, + CONTROL('v'), NUL, A_info_scroll_forward_page_only, + ',', NUL, A_info_next_index_match, + '/', NUL, A_info_search, + '0', NUL, A_info_last_menu_item, + '1', NUL, A_info_menu_digit, + '2', NUL, A_info_menu_digit, + '3', NUL, A_info_menu_digit, + '4', NUL, A_info_menu_digit, + '5', NUL, A_info_menu_digit, + '6', NUL, A_info_menu_digit, + '7', NUL, A_info_menu_digit, + '8', NUL, A_info_menu_digit, + '9', NUL, A_info_menu_digit, + '<', NUL, A_info_first_node, + '>', NUL, A_info_last_node, + '?', NUL, A_info_get_help_window, + '[', NUL, A_info_global_prev_node, + ']', NUL, A_info_global_next_node, + 'b', NUL, A_info_beginning_of_node, + 'd', NUL, A_info_dir_node, + 'e', NUL, A_info_end_of_node, + 'f', NUL, A_info_xref_item, + 'g', NUL, A_info_goto_node, + 'G', NUL, A_info_menu_sequence, + 'h', NUL, A_info_get_info_help_node, + 'i', NUL, A_info_index_search, + 'l', NUL, A_info_history_node, + 'm', NUL, A_info_menu_item, + 'n', NUL, A_info_next_node, + 'O', NUL, A_info_goto_invocation_node, + 'p', NUL, A_info_prev_node, + 'q', NUL, A_info_quit, + 'r', NUL, A_info_xref_item, + 's', NUL, A_info_search, + 'S', NUL, A_info_search_case_sensitively, + 't', NUL, A_info_top_node, + 'u', NUL, A_info_up_node, + DEL, NUL, A_info_scroll_backward, + ESC, '0', NUL, A_info_add_digit_to_numeric_arg, + ESC, '1', NUL, A_info_add_digit_to_numeric_arg, + ESC, '2', NUL, A_info_add_digit_to_numeric_arg, + ESC, '3', NUL, A_info_add_digit_to_numeric_arg, + ESC, '4', NUL, A_info_add_digit_to_numeric_arg, + ESC, '5', NUL, A_info_add_digit_to_numeric_arg, + ESC, '6', NUL, A_info_add_digit_to_numeric_arg, + ESC, '7', NUL, A_info_add_digit_to_numeric_arg, + ESC, '8', NUL, A_info_add_digit_to_numeric_arg, + ESC, '9', NUL, A_info_add_digit_to_numeric_arg, + ESC, '-', NUL, A_info_add_digit_to_numeric_arg, + ESC, CONTROL('f'), NUL, A_info_show_footnotes, + ESC, CONTROL('g'), NUL, A_info_abort_key, + ESC, TAB, NUL, A_info_move_to_prev_xref, + ESC, CONTROL('v'), NUL, A_info_scroll_other_window, + ESC, '<', NUL, A_info_beginning_of_node, + ESC, '>', NUL, A_info_end_of_node, + ESC, 'b', NUL, A_info_backward_word, + ESC, 'f', NUL, A_info_forward_word, + ESC, 'r', NUL, A_info_move_to_window_line, + ESC, 'v', NUL, A_info_scroll_backward_page_only, + Meta('0'), NUL, A_info_add_digit_to_numeric_arg, + Meta('1'), NUL, A_info_add_digit_to_numeric_arg, + Meta('2'), NUL, A_info_add_digit_to_numeric_arg, + Meta('3'), NUL, A_info_add_digit_to_numeric_arg, + Meta('4'), NUL, A_info_add_digit_to_numeric_arg, + Meta('5'), NUL, A_info_add_digit_to_numeric_arg, + Meta('6'), NUL, A_info_add_digit_to_numeric_arg, + Meta('7'), NUL, A_info_add_digit_to_numeric_arg, + Meta('8'), NUL, A_info_add_digit_to_numeric_arg, + Meta('9'), NUL, A_info_add_digit_to_numeric_arg, + Meta('-'), NUL, A_info_add_digit_to_numeric_arg, + Meta(CONTROL('f')), NUL, A_info_show_footnotes, + Meta(CONTROL('g')), NUL, A_info_abort_key, + Meta(TAB), NUL, A_info_move_to_prev_xref, + Meta(CONTROL('v')), NUL, A_info_scroll_other_window, + Meta('<'), NUL, A_info_beginning_of_node, + Meta('>'), NUL, A_info_end_of_node, + Meta('b'), NUL, A_info_backward_word, + Meta('f'), NUL, A_info_forward_word, + Meta('r'), NUL, A_info_move_to_window_line, + Meta('v'), NUL, A_info_scroll_backward_page_only, +#if defined (NAMED_FUNCTIONS) + ESC, 'x', NUL, A_info_execute_command, + Meta('x'), NUL, A_info_execute_command, +#endif /* NAMED_FUNCTIONS */ + + CONTROL('x'), CONTROL('b'), NUL, A_list_visited_nodes, + CONTROL('x'), CONTROL('c'), NUL, A_info_quit, + CONTROL('x'), CONTROL('f'), NUL, A_info_view_file, + CONTROL('x'), CONTROL('g'), NUL, A_info_abort_key, + CONTROL('x'), CONTROL('v'), NUL, A_info_view_file, + CONTROL('x'), '0', NUL, A_info_delete_window, + CONTROL('x'), '1', NUL, A_info_keep_one_window, + CONTROL('x'), '2', NUL, A_info_split_window, + CONTROL('x'), '^', NUL, A_info_grow_window, + CONTROL('x'), 'b', NUL, A_select_visited_node, + CONTROL('x'), 'k', NUL, A_info_kill_node, + CONTROL('x'), 'n', NUL, A_info_search_next, + CONTROL('x'), 'N', NUL, A_info_search_previous, + CONTROL('x'), 'o', NUL, A_info_next_window, + CONTROL('x'), 't', NUL, A_info_tile_windows, + CONTROL('x'), 'w', NUL, A_info_toggle_wrap, + +/* Arrow key bindings for info keymaps. It seems that some + terminals do not match their termcap entries, so it's best to just + define everything with both of the usual prefixes. */ + + SK_ESCAPE, SK_PAGE_UP, NUL, A_info_scroll_backward_page_only, + SK_ESCAPE, SK_PAGE_DOWN, NUL, A_info_scroll_forward_page_only, + SK_ESCAPE, SK_UP_ARROW, NUL, A_info_prev_line, + '\033', 'O', 'A', NUL, A_info_prev_line, + '\033', '[', 'A', NUL, A_info_prev_line, + SK_ESCAPE, SK_DOWN_ARROW, NUL, A_info_next_line, + '\033', 'O', 'B', NUL, A_info_next_line, + '\033', '[', 'B', NUL, A_info_next_line, + SK_ESCAPE, SK_RIGHT_ARROW, NUL, A_info_forward_char, + '\033', 'O', 'C', NUL, A_info_forward_char, + '\033', '[', 'C', NUL, A_info_forward_char, + SK_ESCAPE, SK_LEFT_ARROW, NUL, A_info_backward_char, + '\033', 'O', 'D', NUL, A_info_backward_char, + '\033', '[', 'D', NUL, A_info_backward_char, + SK_ESCAPE, SK_HOME, NUL, A_info_beginning_of_node, + SK_ESCAPE, SK_END, NUL, A_info_end_of_node, + SK_ESCAPE, SK_DELETE, NUL, A_info_scroll_backward, + + ESC, SK_ESCAPE, SK_PAGE_UP, NUL, A_info_scroll_other_window_backward, + ESC, SK_ESCAPE, SK_PAGE_DOWN, NUL, A_info_scroll_other_window, + ESC, SK_ESCAPE, SK_UP_ARROW, NUL, A_info_prev_line, + ESC, '\033', 'O', 'A', NUL, A_info_prev_line, + ESC, '\033', '[', 'A', NUL, A_info_prev_line, + ESC, SK_ESCAPE, SK_DOWN_ARROW, NUL, A_info_next_line, + ESC, '\033', 'O', 'B', NUL, A_info_next_line, + ESC, '\033', '[', 'B', NUL, A_info_next_line, + ESC, SK_ESCAPE, SK_RIGHT_ARROW, NUL, A_info_forward_word, + ESC, '\033', 'O', 'C', NUL, A_info_forward_word, + ESC, '\033', '[', 'C', NUL, A_info_forward_word, + ESC, SK_ESCAPE, SK_LEFT_ARROW, NUL, A_info_backward_word, + ESC, '\033', 'O', 'D', NUL, A_info_backward_word, + ESC, '\033', '[', 'D', NUL, A_info_backward_word, +}; + +static unsigned char default_emacs_like_ea_keys[] = +{ + 0, /* suppress-default-keybindings flag */ + ESC, '0', NUL, A_info_add_digit_to_numeric_arg, + ESC, '1', NUL, A_info_add_digit_to_numeric_arg, + ESC, '2', NUL, A_info_add_digit_to_numeric_arg, + ESC, '3', NUL, A_info_add_digit_to_numeric_arg, + ESC, '4', NUL, A_info_add_digit_to_numeric_arg, + ESC, '5', NUL, A_info_add_digit_to_numeric_arg, + ESC, '6', NUL, A_info_add_digit_to_numeric_arg, + ESC, '7', NUL, A_info_add_digit_to_numeric_arg, + ESC, '8', NUL, A_info_add_digit_to_numeric_arg, + ESC, '9', NUL, A_info_add_digit_to_numeric_arg, + ESC, '-', NUL, A_info_add_digit_to_numeric_arg, + Meta('0'), NUL, A_info_add_digit_to_numeric_arg, + Meta('1'), NUL, A_info_add_digit_to_numeric_arg, + Meta('2'), NUL, A_info_add_digit_to_numeric_arg, + Meta('3'), NUL, A_info_add_digit_to_numeric_arg, + Meta('4'), NUL, A_info_add_digit_to_numeric_arg, + Meta('5'), NUL, A_info_add_digit_to_numeric_arg, + Meta('6'), NUL, A_info_add_digit_to_numeric_arg, + Meta('7'), NUL, A_info_add_digit_to_numeric_arg, + Meta('8'), NUL, A_info_add_digit_to_numeric_arg, + Meta('9'), NUL, A_info_add_digit_to_numeric_arg, + Meta('-'), NUL, A_info_add_digit_to_numeric_arg, + ESC, CONTROL('g'), NUL, A_ea_abort, + ESC, CONTROL('v'), NUL, A_ea_scroll_completions_window, + ESC, 'b', NUL, A_ea_backward_word, + ESC, 'd', NUL, A_ea_kill_word, + ESC, 'f', NUL, A_ea_forward_word, + ESC, 'y', NUL, A_ea_yank_pop, + ESC, '?', NUL, A_ea_possible_completions, + ESC, TAB, NUL, A_ea_tab_insert, + ESC, DEL, NUL, A_ea_backward_kill_word, + Meta(CONTROL('g')), NUL, A_ea_abort, + Meta(CONTROL('v')), NUL, A_ea_scroll_completions_window, + Meta('b'), NUL, A_ea_backward_word, + Meta('d'), NUL, A_ea_kill_word, + Meta('f'), NUL, A_ea_forward_word, + Meta('y'), NUL, A_ea_yank_pop, + Meta('?'), NUL, A_ea_possible_completions, + Meta(TAB), NUL, A_ea_tab_insert, + Meta(DEL), NUL, A_ea_backward_kill_word, + CONTROL('a'), NUL, A_ea_beg_of_line, + CONTROL('b'), NUL, A_ea_backward, + CONTROL('d'), NUL, A_ea_delete, + CONTROL('e'), NUL, A_ea_end_of_line, + CONTROL('f'), NUL, A_ea_forward, + CONTROL('g'), NUL, A_ea_abort, + CONTROL('h'), NUL, A_ea_rubout, +/* CONTROL('k') */ + SK_ESCAPE, SK_LITERAL, NUL, A_ea_kill_line, + CONTROL('l'), NUL, A_info_redraw_display, + CONTROL('q'), NUL, A_ea_quoted_insert, + CONTROL('t'), NUL, A_ea_transpose_chars, + CONTROL('u'), NUL, A_info_universal_argument, + CONTROL('y'), NUL, A_ea_yank, + LFD, NUL, A_ea_newline, + RET, NUL, A_ea_newline, + SPC, NUL, A_ea_complete, + TAB, NUL, A_ea_complete, + '?', NUL, A_ea_possible_completions, +#ifdef __MSDOS__ + /* PC users will lynch me if I don't give them their usual DEL + effect... */ + DEL, NUL, A_ea_delete, +#else + DEL, NUL, A_ea_rubout, +#endif +#if defined (NAMED_FUNCTIONS) + /* ESC, 'x', NUL, A_info_execute_command, */ + /* Meta('x'), NUL, A_info_execute_command, */ +#endif /* NAMED_FUNCTIONS */ + CONTROL('x'), 'o', NUL, A_info_next_window, + CONTROL('x'), DEL, NUL, A_ea_backward_kill_line, + +/* Arrow key bindings for echo area keymaps. It seems that some + terminals do not match their termcap entries, so it's best to just + define everything with both of the usual prefixes. */ + + SK_ESCAPE, SK_RIGHT_ARROW, NUL, A_ea_forward, + '\033', 'O', 'C', NUL, A_ea_forward, + '\033', '[', 'C', NUL, A_ea_forward, + SK_ESCAPE, SK_LEFT_ARROW, NUL, A_ea_backward, + '\033', 'O', 'D', NUL, A_ea_backward, + '\033', '[', 'D', NUL, A_ea_backward, + ESC, SK_ESCAPE, SK_RIGHT_ARROW, NUL, A_ea_forward_word, + ESC, '\033', 'O', 'C', NUL, A_ea_forward_word, + ESC, '\033', '[', 'C', NUL, A_ea_forward_word, + ESC, SK_ESCAPE, SK_LEFT_ARROW, NUL, A_ea_backward_word, + ESC, '\033', 'O', 'D', NUL, A_ea_backward_word, + ESC, '\033', '[', 'D', NUL, A_ea_backward_word, +#ifdef __MSDOS__ + SK_ESCAPE, SK_DELETE, NUL, A_ea_delete, +#else + SK_ESCAPE, SK_DELETE, NUL, A_ea_rubout, +#endif + SK_ESCAPE, SK_HOME, NUL, A_ea_beg_of_line, + SK_ESCAPE, SK_END, NUL, A_ea_end_of_line, + ESC, SK_ESCAPE, SK_DELETE, NUL, A_ea_backward_kill_word, + CONTROL('x'), SK_ESCAPE, SK_DELETE, NUL,A_ea_backward_kill_line, +}; + +static unsigned char default_vi_like_info_keys[] = +{ + 0, /* suppress-default-keybindings flag */ + '0', NUL, A_info_add_digit_to_numeric_arg, + '1', NUL, A_info_add_digit_to_numeric_arg, + '2', NUL, A_info_add_digit_to_numeric_arg, + '3', NUL, A_info_add_digit_to_numeric_arg, + '4', NUL, A_info_add_digit_to_numeric_arg, + '5', NUL, A_info_add_digit_to_numeric_arg, + '6', NUL, A_info_add_digit_to_numeric_arg, + '7', NUL, A_info_add_digit_to_numeric_arg, + '8', NUL, A_info_add_digit_to_numeric_arg, + '9', NUL, A_info_add_digit_to_numeric_arg, + '-', NUL, A_info_add_digit_to_numeric_arg, + TAB, NUL, A_info_move_to_next_xref, + LFD, NUL, A_info_down_line, + RET, NUL, A_info_down_line, + SPC, NUL, A_info_scroll_forward, + CONTROL('a'), NUL, A_info_beginning_of_line, + CONTROL('b'), NUL, A_info_scroll_backward_page_only, + CONTROL('d'), NUL, A_info_scroll_half_screen_down, + CONTROL('e'), NUL, A_info_down_line, + CONTROL('f'), NUL, A_info_scroll_forward_page_only, + CONTROL('g'), NUL, A_info_abort_key, + CONTROL('k'), NUL, A_info_up_line, + CONTROL('l'), NUL, A_info_redraw_display, + CONTROL('n'), NUL, A_info_down_line, + CONTROL('p'), NUL, A_info_up_line, + CONTROL('r'), NUL, A_info_redraw_display, + CONTROL('s'), NUL, A_isearch_forward, + CONTROL('u'), NUL, A_info_scroll_half_screen_up, + CONTROL('v'), NUL, A_info_scroll_forward_page_only, + CONTROL('y'), NUL, A_info_up_line, + ',', NUL, A_info_next_index_match, + '/', NUL, A_info_search, + ESC, '0', NUL, A_info_last_menu_item, + ESC, '1', NUL, A_info_menu_digit, + ESC, '2', NUL, A_info_menu_digit, + ESC, '3', NUL, A_info_menu_digit, + ESC, '4', NUL, A_info_menu_digit, + ESC, '5', NUL, A_info_menu_digit, + ESC, '6', NUL, A_info_menu_digit, + ESC, '7', NUL, A_info_menu_digit, + ESC, '8', NUL, A_info_menu_digit, + ESC, '9', NUL, A_info_menu_digit, + Meta('0'), NUL, A_info_last_menu_item, + Meta('1'), NUL, A_info_menu_digit, + Meta('2'), NUL, A_info_menu_digit, + Meta('3'), NUL, A_info_menu_digit, + Meta('4'), NUL, A_info_menu_digit, + Meta('5'), NUL, A_info_menu_digit, + Meta('6'), NUL, A_info_menu_digit, + Meta('7'), NUL, A_info_menu_digit, + Meta('8'), NUL, A_info_menu_digit, + Meta('9'), NUL, A_info_menu_digit, + '<', NUL, A_info_first_node, + '>', NUL, A_info_last_node, + '?', NUL, A_info_search_backward, + '[', NUL, A_info_global_prev_node, + ']', NUL, A_info_global_next_node, + '\'', NUL, A_info_history_node, + 'b', NUL, A_info_scroll_backward, + 'd', NUL, A_info_scroll_half_screen_down, + 'e', NUL, A_info_down_line, + 'E', NUL, A_info_view_file, + ':', 'e', NUL, A_info_view_file, + 'f', NUL, A_info_scroll_forward_page_only, + 'F', NUL, A_info_scroll_forward_page_only, + 'g', NUL, A_info_first_node, + 'G', NUL, A_info_last_node, + 'h', NUL, A_info_get_help_window, + 'H', NUL, A_info_get_help_window, + 'i', NUL, A_info_index_search, + 'I', NUL, A_info_goto_invocation_node, + 'j', NUL, A_info_next_line, + 'k', NUL, A_info_prev_line, + 'l', NUL, A_info_history_node, + 'm', NUL, A_info_menu_item, + 'n', NUL, A_info_search_next, + 'N', NUL, A_info_search_previous, + 'O', NUL, A_info_goto_invocation_node, + 'p', NUL, A_info_prev_node, + 'q', NUL, A_info_quit, + 'Q', NUL, A_info_quit, + ':', 'q', NUL, A_info_quit, + ':', 'Q', NUL, A_info_quit, + 'Z', 'Z', NUL, A_info_quit, + 'r', NUL, A_info_redraw_display, + 'R', NUL, A_info_redraw_display, + 's', NUL, A_info_search, + 'S', NUL, A_info_search_case_sensitively, + 't', NUL, A_info_top_node, + 'u', NUL, A_info_scroll_half_screen_up, + 'w', NUL, A_info_scroll_backward_page_only_set_window, + 'y', NUL, A_info_up_line, + 'z', NUL, A_info_scroll_forward_page_only_set_window, + DEL, NUL, A_info_scroll_backward, + ESC, CONTROL('f'), NUL, A_info_show_footnotes, + ESC, CONTROL('g'), NUL, A_info_abort_key, + ESC, TAB, NUL, A_info_move_to_prev_xref, + ESC, SPC, NUL, A_info_scroll_forward_page_only, + ESC, CONTROL('v'), NUL, A_info_scroll_other_window, + ESC, '<', NUL, A_info_beginning_of_node, + ESC, '>', NUL, A_info_end_of_node, + ESC, '/', NUL, A_info_search, + ESC, '?', NUL, A_info_search_backward, + ESC, 'b', NUL, A_info_beginning_of_node, + ESC, 'd', NUL, A_info_dir_node, + ESC, 'e', NUL, A_info_end_of_node, + ESC, 'f', NUL, A_info_xref_item, + ESC, 'g', NUL, A_info_select_reference_this_line, + ESC, 'h', NUL, A_info_get_info_help_node, + ESC, 'm', NUL, A_info_menu_item, + ESC, 'n', NUL, A_info_search, + ESC, 'N', NUL, A_info_search_backward, + ESC, 'r', NUL, A_isearch_backward, + ESC, 's', NUL, A_isearch_forward, + ESC, 't', NUL, A_info_top_node, + ESC, 'v', NUL, A_info_scroll_backward_page_only, +#if defined (NAMED_FUNCTIONS) + ESC, 'x', NUL, A_info_execute_command, + Meta('x'), NUL, A_info_execute_command, +#endif /* NAMED_FUNCTIONS */ + ESC, DEL, NUL, A_info_scroll_other_window_backward, + CONTROL('x'), CONTROL('b'), NUL, A_list_visited_nodes, + CONTROL('x'), CONTROL('c'), NUL, A_info_quit, + CONTROL('x'), CONTROL('f'), NUL, A_info_view_file, + CONTROL('x'), CONTROL('g'), NUL, A_info_abort_key, + CONTROL('x'), CONTROL('v'), NUL, A_info_view_file, + CONTROL('x'), LFD, NUL, A_info_select_reference_this_line, + CONTROL('x'), RET, NUL, A_info_select_reference_this_line, + CONTROL('x'), '0', NUL, A_info_delete_window, + CONTROL('x'), '1', NUL, A_info_keep_one_window, + CONTROL('x'), '2', NUL, A_info_split_window, + CONTROL('x'), '^', NUL, A_info_grow_window, + CONTROL('x'), 'b', NUL, A_select_visited_node, + CONTROL('x'), 'g', NUL, A_info_goto_node, + CONTROL('x'), 'i', NUL, A_info_index_search, + CONTROL('x'), 'I', NUL, A_info_goto_invocation_node, + CONTROL('x'), 'k', NUL, A_info_kill_node, + CONTROL('x'), 'n', NUL, A_info_next_node, + CONTROL('x'), 'o', NUL, A_info_next_window, + CONTROL('x'), 'O', NUL, A_info_goto_invocation_node, + CONTROL('x'), 'p', NUL, A_info_prev_node, + CONTROL('x'), 'r', NUL, A_info_xref_item, + CONTROL('x'), 't', NUL, A_info_tile_windows, + CONTROL('x'), 'u', NUL, A_info_up_node, + CONTROL('x'), 'w', NUL, A_info_toggle_wrap, + CONTROL('x'), ',', NUL, A_info_next_index_match, + +/* Arrow key bindings for info keymaps. It seems that some + terminals do not match their termcap entries, so it's best to just + define everything with both of the usual prefixes. */ + + SK_ESCAPE, SK_PAGE_UP, NUL, A_info_scroll_backward_page_only, + SK_ESCAPE, SK_PAGE_DOWN, NUL, A_info_scroll_forward_page_only, + SK_ESCAPE, SK_UP_ARROW, NUL, A_info_up_line, + '\033', 'O', 'A', NUL, A_info_up_line, + '\033', '[', 'A', NUL, A_info_up_line, + SK_ESCAPE, SK_DOWN_ARROW, NUL, A_info_down_line, + '\033', 'O', 'B', NUL, A_info_down_line, + '\033', '[', 'B', NUL, A_info_down_line, + SK_ESCAPE, SK_RIGHT_ARROW, NUL, A_info_scroll_forward_page_only, + '\033', 'O', 'C', NUL, A_info_scroll_forward_page_only, + '\033', '[', 'C', NUL, A_info_scroll_forward_page_only, + SK_ESCAPE, SK_LEFT_ARROW, NUL, A_info_scroll_backward_page_only, + '\033', 'O', 'D', NUL, A_info_scroll_backward_page_only, + '\033', '[', 'D', NUL, A_info_scroll_backward_page_only, + SK_ESCAPE, SK_HOME, NUL, A_info_beginning_of_node, + SK_ESCAPE, SK_END, NUL, A_info_end_of_node, + ESC, SK_ESCAPE, SK_PAGE_DOWN, NUL, A_info_scroll_other_window, + ESC, SK_ESCAPE, SK_PAGE_UP, NUL, A_info_scroll_other_window_backward, + ESC, SK_ESCAPE, SK_DELETE, NUL, A_info_scroll_other_window_backward, + ESC, SK_ESCAPE, SK_UP_ARROW, NUL, A_info_prev_node, + ESC, '\033', 'O', 'A', NUL, A_info_prev_node, + ESC, '\033', '[', 'A', NUL, A_info_prev_node, + ESC, SK_ESCAPE, SK_DOWN_ARROW, NUL, A_info_next_node, + ESC, '\033', 'O', 'B', NUL, A_info_next_node, + ESC, '\033', '[', 'B', NUL, A_info_next_node, + ESC, SK_ESCAPE, SK_RIGHT_ARROW, NUL, A_info_xref_item, + ESC, '\033', 'O', 'C', NUL, A_info_xref_item, + ESC, '\033', '[', 'C', NUL, A_info_xref_item, + ESC, SK_ESCAPE, SK_LEFT_ARROW, NUL, A_info_beginning_of_node, + ESC, '\033', 'O', 'D', NUL, A_info_beginning_of_node, + ESC, '\033', '[', 'D', NUL, A_info_beginning_of_node, + CONTROL('x'), SK_ESCAPE, SK_DELETE, NUL,A_ea_backward_kill_line, +}; + +static unsigned char default_vi_like_ea_keys[] = +{ + 0, /* suppress-default-keybindings flag */ + ESC, '1', NUL, A_info_add_digit_to_numeric_arg, + ESC, '2', NUL, A_info_add_digit_to_numeric_arg, + ESC, '3', NUL, A_info_add_digit_to_numeric_arg, + ESC, '4', NUL, A_info_add_digit_to_numeric_arg, + ESC, '5', NUL, A_info_add_digit_to_numeric_arg, + ESC, '6', NUL, A_info_add_digit_to_numeric_arg, + ESC, '7', NUL, A_info_add_digit_to_numeric_arg, + ESC, '8', NUL, A_info_add_digit_to_numeric_arg, + ESC, '9', NUL, A_info_add_digit_to_numeric_arg, + ESC, '-', NUL, A_info_add_digit_to_numeric_arg, + Meta('1'), NUL, A_info_add_digit_to_numeric_arg, + Meta('2'), NUL, A_info_add_digit_to_numeric_arg, + Meta('3'), NUL, A_info_add_digit_to_numeric_arg, + Meta('4'), NUL, A_info_add_digit_to_numeric_arg, + Meta('5'), NUL, A_info_add_digit_to_numeric_arg, + Meta('6'), NUL, A_info_add_digit_to_numeric_arg, + Meta('7'), NUL, A_info_add_digit_to_numeric_arg, + Meta('8'), NUL, A_info_add_digit_to_numeric_arg, + Meta('9'), NUL, A_info_add_digit_to_numeric_arg, + Meta('-'), NUL, A_info_add_digit_to_numeric_arg, + ESC, CONTROL('g'), NUL, A_ea_abort, + ESC, CONTROL('h'), NUL, A_ea_backward_kill_word, + ESC, CONTROL('v'), NUL, A_ea_scroll_completions_window, + ESC, '0', NUL, A_ea_beg_of_line, + ESC, '$', NUL, A_ea_end_of_line, + ESC, 'b', NUL, A_ea_backward_word, + ESC, 'd', NUL, A_ea_kill_word, + ESC, 'f', NUL, A_ea_forward_word, + ESC, 'h', NUL, A_ea_forward, + ESC, 'l', NUL, A_ea_backward, + ESC, 'w', NUL, A_ea_forward_word, + ESC, 'x', NUL, A_ea_delete, + ESC, 'X', NUL, A_ea_kill_word, + ESC, 'y', NUL, A_ea_yank_pop, + ESC, '?', NUL, A_ea_possible_completions, + ESC, TAB, NUL, A_ea_tab_insert, + ESC, DEL, NUL, A_ea_kill_word, + Meta(CONTROL('g')), NUL, A_ea_abort, + Meta(CONTROL('h')), NUL, A_ea_backward_kill_word, + Meta(CONTROL('v')), NUL, A_ea_scroll_completions_window, + Meta('0'), NUL, A_ea_beg_of_line, + Meta('$'), NUL, A_ea_end_of_line, + Meta('b'), NUL, A_ea_backward_word, + Meta('d'), NUL, A_ea_kill_word, + Meta('f'), NUL, A_ea_forward_word, + Meta('h'), NUL, A_ea_forward, + Meta('l'), NUL, A_ea_backward, + Meta('w'), NUL, A_ea_forward_word, + Meta('x'), NUL, A_ea_delete, + Meta('X'), NUL, A_ea_kill_word, + Meta('y'), NUL, A_ea_yank_pop, + Meta('?'), NUL, A_ea_possible_completions, + Meta(TAB), NUL, A_ea_tab_insert, + Meta(DEL), NUL, A_ea_kill_word, + CONTROL('a'), NUL, A_ea_beg_of_line, + CONTROL('b'), NUL, A_ea_backward, + CONTROL('d'), NUL, A_ea_delete, + CONTROL('e'), NUL, A_ea_end_of_line, + CONTROL('f'), NUL, A_ea_forward, + CONTROL('g'), NUL, A_ea_abort, + CONTROL('h'), NUL, A_ea_rubout, +/* CONTROL('k') */ + SK_ESCAPE, SK_LITERAL, NUL, A_ea_kill_line, + CONTROL('l'), NUL, A_info_redraw_display, + CONTROL('q'), NUL, A_ea_quoted_insert, + CONTROL('t'), NUL, A_ea_transpose_chars, + CONTROL('u'), NUL, A_ea_abort, + CONTROL('v'), NUL, A_ea_quoted_insert, + CONTROL('y'), NUL, A_ea_yank, + LFD, NUL, A_ea_newline, + RET, NUL, A_ea_newline, + SPC, NUL, A_ea_complete, + TAB, NUL, A_ea_complete, + '?', NUL, A_ea_possible_completions, +#ifdef __MSDOS__ + /* PC users will lynch me if I don't give them their usual DEL + effect... */ + DEL, NUL, A_ea_delete, +#else + DEL, NUL, A_ea_rubout, +#endif + CONTROL('x'), 'o', NUL, A_info_next_window, + CONTROL('x'), DEL, NUL, A_ea_backward_kill_line, + + /* Arrow key bindings for echo area keymaps. It seems that some + terminals do not match their termcap entries, so it's best to just + define everything with both of the usual prefixes. */ + + SK_ESCAPE, SK_RIGHT_ARROW, NUL, A_ea_forward, + '\033', 'O', 'C', NUL, A_ea_forward, + '\033', '[', 'C', NUL, A_ea_forward, + SK_ESCAPE, SK_LEFT_ARROW, NUL, A_ea_backward, + '\033', 'O', 'D', NUL, A_ea_backward, + '\033', '[', 'D', NUL, A_ea_backward, + SK_ESCAPE, SK_HOME, NUL, A_ea_beg_of_line, + SK_ESCAPE, SK_END, NUL, A_ea_end_of_line, +#ifdef __MSDOS__ + SK_ESCAPE, SK_DELETE, NUL, A_ea_delete, +#else + SK_DELETE, SK_DELETE, NUL, A_ea_rubout, +#endif + ESC, SK_ESCAPE, SK_RIGHT_ARROW, NUL, A_ea_forward_word, + ESC, '\033', 'O', 'C', NUL, A_ea_forward_word, + ESC, '\033', '[', 'C', NUL, A_ea_forward_word, + ESC, SK_ESCAPE, SK_LEFT_ARROW, NUL, A_ea_backward_word, + ESC, '\033', 'O', 'D', NUL, A_ea_backward_word, + ESC, '\033', '[', 'D', NUL, A_ea_backward_word, + ESC, SK_ESCAPE, SK_DELETE, NUL, A_ea_kill_word, + CONTROL('x'), SK_ESCAPE, SK_DELETE, NUL,A_ea_backward_kill_line, +}; + +static unsigned char *user_info_keys; +static unsigned int user_info_keys_len; +static unsigned char *user_ea_keys; +static unsigned int user_ea_keys_len; +static unsigned char *user_vars; +static unsigned int user_vars_len; + +/* + * Return the size of a file, or 0 if the size can't be determined. + */ +static unsigned long +filesize(int f) +{ + long pos = lseek(f, 0L, SEEK_CUR); + long sz = -1L; + if (pos != -1L) + { + sz = lseek(f, 0L, SEEK_END); + lseek(f, pos, SEEK_SET); + } + return sz == -1L ? 0L : sz; +} + +/* Get an integer from a infokey file. + Integers are stored as two bytes, low order first, in radix INFOKEY_RADIX. + */ +static int +getint(unsigned char **sp) +{ + int n; + + if ( !((*sp)[0] < INFOKEY_RADIX && (*sp)[1] < INFOKEY_RADIX) ) + return -1; + n = (*sp)[0] + (*sp)[1] * INFOKEY_RADIX; + *sp += 2; + return n; +} + + +/* Fetch the contents of the standard infokey file "$HOME/.info". Return + true if ok, false if not. */ +static int +fetch_user_maps(void) +{ + char *filename = NULL; + char *homedir; + int f; + unsigned char *buf; + unsigned long len; + long nread; + unsigned char *p; + int n; + + /* Find and open file. */ + if ((filename = getenv("INFOKEY")) != NULL) + filename = xstrdup(filename); + else if ((homedir = getenv("HOME")) != NULL) + { + filename = xmalloc(strlen(homedir) + 2 + strlen(INFOKEY_FILE)); + strcpy(filename, homedir); + strcat(filename, "/"); + strcat(filename, INFOKEY_FILE); + } +#ifdef __MSDOS__ + /* Poor baby, she doesn't have a HOME... */ + else + filename = xstrdup(INFOKEY_FILE); /* try current directory */ +#endif + if (filename == NULL || (f = open(filename, O_RDONLY)) == (-1)) + { + if (filename && errno != ENOENT) + { + info_error(filesys_error_string(filename, errno), + NULL, NULL); + free(filename); + } + return 0; + } + SET_BINARY (f); + + /* Ensure that the file is a reasonable size. */ + len = filesize(f); + if (len < INFOKEY_NMAGIC + 2 || len > 100 * 1024) + { + /* Bad file (a valid file must have at least 9 chars, and + more than 100 KB is a problem). */ + if (len < INFOKEY_NMAGIC + 2) + info_error((char *) _("Ignoring invalid infokey file `%s' - too small"), + filename, NULL); + else + info_error((char *) _("Ignoring invalid infokey file `%s' - too big"), + filename, NULL); + close(f); + free(filename); + return 0; + } + + /* Read the file into a buffer. */ + buf = (unsigned char *)xmalloc((int)len); + nread = read(f, buf, (unsigned int) len); + close(f); + if ((unsigned int) nread != len) + { + info_error((char *) _("Error reading infokey file `%s' - short read"), + filename, NULL); + free(buf); + free(filename); + return 0; + } + + /* Check the header, trailer, and version of the file to increase + our confidence that the contents are valid. */ + if ( buf[0] != INFOKEY_MAGIC_S0 + || buf[1] != INFOKEY_MAGIC_S1 + || buf[2] != INFOKEY_MAGIC_S2 + || buf[3] != INFOKEY_MAGIC_S3 + || buf[len - 4] != INFOKEY_MAGIC_E0 + || buf[len - 3] != INFOKEY_MAGIC_E1 + || buf[len - 2] != INFOKEY_MAGIC_E2 + || buf[len - 1] != INFOKEY_MAGIC_E3 + ) + { + info_error((char *) _("Invalid infokey file `%s' (bad magic numbers) -- run infokey to update it"), + filename, NULL); + free(filename); + return 0; + } + if (len < INFOKEY_NMAGIC + strlen(VERSION) + 1 + || strcmp(VERSION, (char *) (buf + 4)) != 0) + { + info_error + ((char *) _("Your infokey file `%s' is out of date -- run infokey to update it"), + filename, NULL); + free(filename); + return 0; + } + + /* Extract the pieces. */ + for (p = buf + 4 + strlen(VERSION) + 1; + (unsigned int) (p - buf) < len - 4; + p += n) + { + int s = *p++; + + n = getint(&p); + if (n < 0 || (unsigned int) n > len - 4 - (p - buf)) + { + info_error((char *) _("Invalid infokey file `%s' (bad section length) -- run infokey to update it"), + filename, NULL); + free(filename); + return 0; + } + + switch (s) + { + case INFOKEY_SECTION_INFO: + user_info_keys = p; + user_info_keys_len = n; + break; + case INFOKEY_SECTION_EA: + user_ea_keys = p; + user_ea_keys_len = n; + break; + case INFOKEY_SECTION_VAR: + user_vars = p; + user_vars_len = n; + break; + default: + info_error((char *) _("Invalid infokey file `%s' (bad section code) -- run infokey to update it"), + filename, NULL); + free(filename); + return 0; + } + } + + free(filename); + return 1; +} + +/* Decode special key sequences from the infokey file. Return zero + if the key sequence includes special keys which the terminal + doesn't define. + */ +static int +decode_keys(unsigned char *src, unsigned int slen, + unsigned char *dst, unsigned int dlen) +{ + unsigned char *s = src; + unsigned char *d = dst; + +#define To_dst(c) do { \ + if ((unsigned int) (d - dst) < dlen) *d++ = (c); \ +} while (0) + + while ((unsigned int) (s - src) < slen) + { + unsigned char c = ISMETA(*s) ? UNMETA(*s) : *s; + + if (c == SK_ESCAPE) + { + char *t; + static char lit[] = { SK_ESCAPE, NUL }; + + switch ((unsigned int) (s + 1 - src) < slen ? s[1] : '\0') + { + case SK_RIGHT_ARROW: t = term_kr; break; + case SK_LEFT_ARROW: t = term_kl; break; + case SK_UP_ARROW: t = term_ku; break; + case SK_DOWN_ARROW: t = term_kd; break; + case SK_PAGE_UP: t = term_kP; break; + case SK_PAGE_DOWN: t = term_kN; break; + case SK_HOME: t = term_kh; break; + case SK_END: t = term_ke; break; + case SK_DELETE: t = term_kx; break; + case SK_INSERT: t = term_ki; break; + case SK_LITERAL: + default: t = lit; break; + } + if (t == NULL) + return 0; + while (*t) + To_dst(ISMETA(*s) ? Meta(*t++) : *t++); + s += 2; + } + else + { + if (ISMETA(*s)) + To_dst(Meta(*s++)); + else + To_dst(*s++); + } + } + + To_dst('\0'); + + return 1; + +#undef To_dst + +} + +/* Convert an infokey file section to keymap bindings. Return false if + the default bindings are to be suppressed. */ +static int +section_to_keymaps(Keymap map, unsigned char *table, unsigned int len) +{ + int stop; + unsigned char *p; + unsigned char *seq = NULL; + unsigned int seqlen = 0; + enum { getseq, gotseq, getaction } state = getseq; + + stop = len > 0 ? table[0] : 0; + + for (p = table + 1; (unsigned int) (p - table) < len; p++) + { + switch (state) + { + case getseq: + if (*p) + { + seq = p; + state = gotseq; + } + break; + + case gotseq: + if (!*p) + { + seqlen = p - seq; + state = getaction; + } + break; + + case getaction: + { + unsigned int action = *p; + unsigned char keyseq[256]; + KEYMAP_ENTRY ke; + + state = getseq; + /* If decode_keys returns zero, it + means that seq includes keys which + the terminal doesn't support, like + PageDown. In that case, don't bind + the key sequence. */ + if (decode_keys(seq, seqlen, keyseq, + sizeof keyseq)) + { + keyseq[sizeof keyseq - 1] = '\0'; + ke.type = ISFUNC; + ke.function = + action < A_NCOMMANDS + ? &function_doc_array[action] + : NULL; + keymap_bind_keyseq(map, + (const char *) keyseq, &ke); + } + } + break; + } + } + if (state != getseq) + info_error((char *) _("Bad data in infokey file -- some key bindings ignored"), + NULL, NULL); + return !stop; +} + +/* Convert an infokey file section to variable settings. + */ +static void +section_to_vars(unsigned char *table, unsigned int len) +{ + enum { getvar, gotvar, getval, gotval } state = getvar; + unsigned char *var = NULL; + unsigned char *val = NULL; + unsigned char *p; + + for (p = table; (unsigned int) (p - table) < len; p++) + { + switch (state) + { + case getvar: + if (*p) + { + var = p; + state = gotvar; + } + break; + + case gotvar: + if (!*p) + state = getval; + break; + + case getval: + if (*p) + { + val = p; + state = gotval; + } + break; + + case gotval: + if (!*p) + { + set_variable_to_value((char *) var, (char *) val); + state = getvar; + } + break; + } + } + if (state != getvar) + info_error((char *) _("Bad data in infokey file -- some var settings ignored"), + NULL, NULL); +} + +void +initialize_info_keymaps (void) +{ + int i; + int suppress_info_default_bindings = 0; + int suppress_ea_default_bindings = 0; + + if (!info_keymap) + { + info_keymap = keymap_make_keymap (); + echo_area_keymap = keymap_make_keymap (); + } + + /* Bind the echo area insert routines. */ + for (i = 0; i < 256; i++) + if (isprint (i)) + echo_area_keymap[i].function = InfoCmd(ea_insert); + + /* Get user-defined keys and variables. */ + if (fetch_user_maps()) + { + if (user_info_keys_len && user_info_keys[0]) + suppress_info_default_bindings = 1; + if (user_ea_keys_len && user_ea_keys[0]) + suppress_ea_default_bindings = 1; + } + + /* Apply the default bindings, unless the user says to suppress + them. */ + if (vi_keys_p) + { + if (!suppress_info_default_bindings) + section_to_keymaps(info_keymap, default_vi_like_info_keys, + sizeof(default_vi_like_info_keys)); + if (!suppress_ea_default_bindings) + section_to_keymaps(echo_area_keymap, default_vi_like_ea_keys, + sizeof(default_vi_like_ea_keys)); + } + else + { + if (!suppress_info_default_bindings) + section_to_keymaps(info_keymap, default_emacs_like_info_keys, + sizeof(default_emacs_like_info_keys)); + if (!suppress_ea_default_bindings) + section_to_keymaps(echo_area_keymap, default_emacs_like_ea_keys, + sizeof(default_emacs_like_ea_keys)); + } + + /* If the user specified custom bindings, apply them on top of the + default ones. */ + if (user_info_keys_len) + section_to_keymaps(info_keymap, user_info_keys, user_info_keys_len); + + if (user_ea_keys_len) + section_to_keymaps(echo_area_keymap, user_ea_keys, user_ea_keys_len); + + if (user_vars_len) + section_to_vars(user_vars, user_vars_len); +} + +#endif /* defined(INFOKEY) */ +/* vim: set sw=2 cino={1s>2sn-s^-se-s: */ |