diff options
Diffstat (limited to 'contrib/texinfo/info/infomap.c')
-rw-r--r-- | contrib/texinfo/info/infomap.c | 1110 |
1 files changed, 1076 insertions, 34 deletions
diff --git a/contrib/texinfo/info/infomap.c b/contrib/texinfo/info/infomap.c index 932435e8d845..7749d53ede0d 100644 --- a/contrib/texinfo/info/infomap.c +++ b/contrib/texinfo/info/infomap.c @@ -1,7 +1,7 @@ -/* infomap.c -- Keymaps for Info. - $Id: infomap.c,v 1.20 1999/06/25 21:57:40 karl Exp $ +/* infomap.c -- keymaps for Info. + $Id: infomap.c,v 1.28 2002/02/08 23:02:53 karl Exp $ - Copyright (C) 1993, 97, 98, 99 Free Software Foundation, Inc. + Copyright (C) 1993, 97, 98, 99, 2001, 02 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 @@ -24,12 +24,17 @@ #include "funs.h" #include "terminal.h" +#if defined(INFOKEY) +#include "infokey.h" +#include "variables.h" +#endif /* INFOKEY */ + /* Return a new keymap which has all the uppercase letters mapped to run the function info_do_lowercase_version (). */ Keymap keymap_make_keymap () { - register int i; + int i; Keymap keymap; keymap = (Keymap)xmalloc (256 * sizeof (KEYMAP_ENTRY)); @@ -37,13 +42,17 @@ keymap_make_keymap () for (i = 0; i < 256; i++) { keymap[i].type = ISFUNC; - keymap[i].function = (VFunction *)NULL; + keymap[i].function = (InfoCommand *)NULL; } for (i = 'A'; i < ('Z' + 1); i++) { keymap[i].type = ISFUNC; - keymap[i].function = info_do_lowercase_version; +#if defined(INFOKEY) + keymap[Meta(i)].type = ISFUNC; + keymap[Meta(i)].function = +#endif /* INFOKEY */ + keymap[i].function = InfoCmd(info_do_lowercase_version); } return (keymap); @@ -54,7 +63,7 @@ Keymap keymap_copy_keymap (map) Keymap map; { - register int i; + int i; Keymap keymap; keymap = keymap_make_keymap (); @@ -72,7 +81,7 @@ void keymap_discard_keymap (map) Keymap (map); { - register int i; + int i; if (!map) return; @@ -99,9 +108,9 @@ keymap_bind_keyseq (map, keyseq, keyentry) const unsigned char *keyseq; KEYMAP_ENTRY *keyentry; { - register Keymap m = map; - register const unsigned char *s = keyseq; - register int c; + Keymap m = map; + const unsigned char *s = keyseq; + int c; if (s == NULL || *s == '\0') return 0; @@ -110,14 +119,18 @@ keymap_bind_keyseq (map, keyseq, keyentry) switch (m[c].type) { case ISFUNC: - if (!(m[c].function == NULL || - (m != map && m[c].function == info_do_lowercase_version))) + if (!(m[c].function == NULL || ( +#if !defined(INFOKEY) + m != map && +#endif /* !INFOKEY */ + m[c].function == InfoCmd(info_do_lowercase_version)) + )) return 0; if (*s != '\0') { m[c].type = ISKMAP; - m[c].function = (VFunction *)keymap_make_keymap (); + m[c].function = (InfoCommand *)keymap_make_keymap (); } break; @@ -132,6 +145,20 @@ keymap_bind_keyseq (map, keyseq, keyentry) } else { +#if defined(INFOKEY) + FUNCTION_KEYSEQ *k; + + for (k = keyentry->function->keys; k && k->map != map; k = k->next) + ; + if (!k) + { + FUNCTION_KEYSEQ *ks = (FUNCTION_KEYSEQ *)xmalloc (sizeof(FUNCTION_KEYSEQ)); + ks->next = keyentry->function->keys; + ks->map = map; + ks->keyseq = xstrdup (keyseq); + keyentry->function->keys = ks; + } +#endif /* INFOKEY */ m[c] = *keyentry; } } @@ -144,6 +171,8 @@ keymap_bind_keyseq (map, keyseq, keyentry) Keymap info_keymap = NULL; Keymap echo_area_keymap = NULL; +#if !defined(INFOKEY) + static void initialize_emacs_like_keymaps () { @@ -157,9 +186,9 @@ initialize_emacs_like_keymaps () } info_keymap[ESC].type = ISKMAP; - info_keymap[ESC].function = (VFunction *)keymap_make_keymap (); + info_keymap[ESC].function = (InfoCommand *)keymap_make_keymap (); info_keymap[Control ('x')].type = ISKMAP; - info_keymap[Control ('x')].function = (VFunction *)keymap_make_keymap (); + 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 @@ -168,10 +197,10 @@ initialize_emacs_like_keymaps () echo_area_keymap[i].function = ea_insert; echo_area_keymap[ESC].type = ISKMAP; - echo_area_keymap[ESC].function = (VFunction *) keymap_make_keymap (); + echo_area_keymap[ESC].function = (InfoCommand *) keymap_make_keymap (); echo_area_keymap[Control ('x')].type = ISKMAP; echo_area_keymap[Control ('x')].function - = (VFunction *) keymap_make_keymap (); + = (InfoCommand *) keymap_make_keymap (); /* Bind numeric arg functions for both echo area and info window maps. */ for (i = '0'; i < '9' + 1; i++) @@ -253,6 +282,9 @@ initialize_emacs_like_keymaps () 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 */ @@ -261,6 +293,10 @@ initialize_emacs_like_keymaps () 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; @@ -280,7 +316,7 @@ initialize_emacs_like_keymaps () 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; + map[Control ('v')].function = info_scroll_forward_page_only; map[','].function = info_next_index_match; map['/'].function = info_search; @@ -327,7 +363,7 @@ initialize_emacs_like_keymaps () 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; + map['v'].function = info_scroll_backward_page_only; #if defined (NAMED_FUNCTIONS) map['x'].function = info_execute_command; #endif /* NAMED_FUNCTIONS */ @@ -368,6 +404,9 @@ initialize_emacs_like_keymaps () 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 */ @@ -378,6 +417,7 @@ initialize_emacs_like_keymaps () 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: @@ -389,7 +429,7 @@ initialize_emacs_like_keymaps () static void initialize_vi_like_keymaps () { - register int i; + int i; Keymap map; if (!info_keymap) @@ -399,19 +439,19 @@ initialize_vi_like_keymaps () } info_keymap[ESC].type = ISKMAP; - info_keymap[ESC].function = (VFunction *)keymap_make_keymap (); + info_keymap[ESC].function = (InfoCommand *)keymap_make_keymap (); info_keymap[Control ('x')].type = ISKMAP; - info_keymap[Control ('x')].function = (VFunction *)keymap_make_keymap (); + 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 = (VFunction *)keymap_make_keymap (); + echo_area_keymap[ESC].function = (InfoCommand *)keymap_make_keymap (); echo_area_keymap[Control ('x')].type = ISKMAP; echo_area_keymap[Control ('x')].function = - (VFunction *)keymap_make_keymap (); + (InfoCommand *)keymap_make_keymap (); /* Bind numeric arg functions for both echo area and info window maps. */ for (i = '0'; i < '9' + 1; i++) @@ -497,6 +537,9 @@ initialize_vi_like_keymaps () 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 */ @@ -505,6 +548,10 @@ initialize_vi_like_keymaps () 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; @@ -513,10 +560,10 @@ initialize_vi_like_keymaps () 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; + 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; + 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; @@ -525,7 +572,7 @@ initialize_vi_like_keymaps () 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; + 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; @@ -545,8 +592,8 @@ initialize_vi_like_keymaps () 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; - map['F'].function = info_scroll_forward; + 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; @@ -569,11 +616,12 @@ initialize_vi_like_keymaps () 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_set_window; + map['w'].function = info_scroll_backward_page_only_set_window; map['y'].function = info_up_line; - map['z'].function = info_scroll_forward_set_window; + 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']); @@ -583,7 +631,7 @@ initialize_vi_like_keymaps () 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; + 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; @@ -601,7 +649,7 @@ initialize_vi_like_keymaps () map['r'].function = isearch_backward; map['s'].function = isearch_forward; map['t'].function = info_top_node; - map['v'].function = info_scroll_backward; + map['v'].function = info_scroll_backward_page_only; #if defined (NAMED_FUNCTIONS) map['x'].function = info_execute_command; #endif /* NAMED_FUNCTIONS */ @@ -652,6 +700,8 @@ initialize_vi_like_keymaps () 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 */ @@ -662,6 +712,7 @@ initialize_vi_like_keymaps () 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: @@ -679,3 +730,994 @@ initialize_info_keymaps () 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_down_line, + 'k', NUL, A_info_up_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(f) + 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(sp) + 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() +{ + 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) + { + info_error(filesys_error_string(filename, errno)); + 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(_("Ignoring invalid infokey file `%s' - too small"), + filename); + else + info_error(_("Ignoring invalid infokey file `%s' - too big"), + filename); + 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 (nread != len) + { + info_error(_("Error reading infokey file `%s' - short read"), filename); + 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(_("Invalid infokey file `%s' (bad magic numbers) -- run infokey to update it"), filename); + free(filename); + return 0; + } + if (len < INFOKEY_NMAGIC + strlen(VERSION) + 1 || strcmp(VERSION, buf + 4) != 0) + { + info_error(_("Your infokey file `%s' is out of date -- run infokey to update it"), filename); + free(filename); + return 0; + } + + /* Extract the pieces. */ + for (p = buf + 4 + strlen(VERSION) + 1; p - buf < len - 4; p += n) + { + int s = *p++; + + n = getint(&p); + if (n < 0 || n > len - 4 - (p - buf)) + { + info_error(_("Invalid infokey file `%s' (bad section length) -- run infokey to update it"), filename); + 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(_("Invalid infokey file `%s' (bad section code) -- run infokey to update it"), filename); + 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(src, slen, dst, dlen) + 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 (d - dst < dlen) *d++ = (c); } while (0) + + while (s - src < slen) + { + unsigned char c = ISMETA(*s) ? UNMETA(*s) : *s; + + if (c == SK_ESCAPE) + { + unsigned char *t; + static char lit[] = { SK_ESCAPE, NUL }; + + switch (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(map, table, len) + Keymap map; + unsigned char *table; + unsigned int len; +{ + int stop; + unsigned char *p; + unsigned char *seq; + unsigned int seqlen; + KEYMAP_ENTRY ke; + enum { getseq, gotseq, getaction } state = getseq; + + stop = len > 0 ? table[0] : 0; + + for (p = table + 1; 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, keyseq, &ke); + } + } + break; + } + } + if (state != getseq) + info_error(_("Bad data in infokey file -- some key bindings ignored")); + return !stop; +} + +/* Convert an infokey file section to variable settings. + */ +static void +section_to_vars(table, len) + 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; 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(var, val); + state = getvar; + } + break; + } + } + if (state != getvar) + info_error(_("Bad data in infokey file -- some var settings ignored")); +} + +void +initialize_info_keymaps () +{ + int i; + int suppress_info_default_bindings = 0; + int suppress_ea_default_bindings = 0; + Keymap map; + + 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) */ |