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