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