1 /* $NetBSD: infomap.c,v 1.1.1.1 2016/01/14 00:11:29 christos Exp $ */ 2 3 /* infomap.c -- keymaps for Info. 4 Id: infomap.c,v 1.10 2004/07/30 20:43:40 karl Exp 5 6 Copyright (C) 1993, 1997, 1998, 1999, 2001, 2002, 2003, 2004 Free Software 7 Foundation, Inc. 8 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. 13 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. 18 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. 22 23 Written by Brian Fox (bfox@ai.mit.edu). */ 24 25 #include "info.h" 26 #include "infomap.h" 27 #include "funs.h" 28 #include "terminal.h" 29 30 #if defined(INFOKEY) 31 #include "infokey.h" 32 #include "variables.h" 33 #endif /* INFOKEY */ 34 35 static int keymap_bind_keyseq (Keymap map, const char *keyseq, 36 KEYMAP_ENTRY *keyentry); 37 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) 42 { 43 int i; 44 Keymap keymap; 45 46 keymap = (Keymap)xmalloc (256 * sizeof (KEYMAP_ENTRY)); 47 48 for (i = 0; i < 256; i++) 49 { 50 keymap[i].type = ISFUNC; 51 keymap[i].function = (InfoCommand *)NULL; 52 } 53 54 for (i = 'A'; i < ('Z' + 1); i++) 55 { 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); 62 } 63 64 return (keymap); 65 } 66 67 #if defined(INFOKEY) 68 static FUNCTION_KEYSEQ * 69 find_function_keyseq (Keymap map, int c, Keymap rootmap) 70 { 71 FUNCTION_KEYSEQ *k; 72 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) 78 { 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; 90 } 91 return k; 92 } 93 94 static void 95 add_function_keyseq (InfoCommand *function, 96 const char *keyseq, Keymap rootmap) 97 { 98 FUNCTION_KEYSEQ *ks; 99 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; 109 } 110 111 static void 112 remove_function_keyseq (InfoCommand *function, 113 const char *keyseq, Keymap rootmap) 114 { 115 116 FUNCTION_KEYSEQ *k, *kp; 117 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; 131 } 132 #endif /* INFOKEY */ 133 134 /* Return a new keymap which is a copy of MAP. */ 135 Keymap 136 keymap_copy_keymap (Keymap map, Keymap rootmap, Keymap newroot) 137 { 138 int i; 139 Keymap keymap; 140 #if defined(INFOKEY) 141 FUNCTION_KEYSEQ *ks; 142 #endif /* INFOKEY */ 143 144 keymap = keymap_make_keymap (); 145 if (!newroot) 146 newroot = keymap; 147 148 for (i = 0; i < 256; i++) 149 { 150 keymap[i].type = map[i].type; 151 switch (map[i].type) 152 { 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; 165 } 166 } 167 return (keymap); 168 } 169 170 /* Free the keymap and its descendants. */ 171 void 172 keymap_discard_keymap (Keymap map, Keymap rootmap) 173 { 174 int i; 175 176 if (!map) 177 return; 178 if (!rootmap) 179 rootmap = map; 180 181 for (i = 0; i < 256; i++) 182 { 183 #if defined(INFOKEY) 184 FUNCTION_KEYSEQ *ks; 185 #endif /* INFOKEY */ 186 switch (map[i].type) 187 { 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; 195 196 case ISKMAP: 197 keymap_discard_keymap ((Keymap)map[i].function, rootmap); 198 break; 199 200 } 201 } 202 free(map); 203 } 204 205 /* Conditionally bind key sequence. */ 206 static int 207 keymap_bind_keyseq (Keymap map, 208 const char *keyseq, KEYMAP_ENTRY *keyentry) 209 { 210 Keymap m = map; 211 const unsigned char *s = (unsigned char *) keyseq; 212 int c; 213 214 if (s == NULL || *s == '\0') return 0; 215 216 while ((c = *s++) != '\0') 217 { 218 #if defined(INFOKEY) 219 FUNCTION_KEYSEQ *ks; 220 #endif /* INFOKEY */ 221 switch (m[c].type) 222 { 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)) 232 )) 233 return 0; 234 #endif /* !INFOKEY */ 235 236 if (*s != '\0') 237 { 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 (); 246 } 247 break; 248 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; 258 } 259 if (*s != '\0') 260 { 261 m = (Keymap)m[c].function; 262 } 263 else 264 { 265 #if defined(INFOKEY) 266 add_function_keyseq (keyentry->function, keyseq, map); 267 #endif /* INFOKEY */ 268 m[c] = *keyentry; 269 } 270 } 271 272 return 1; 273 } 274 275 /* Initialize the standard info keymaps. */ 276 277 Keymap info_keymap = NULL; 278 Keymap echo_area_keymap = NULL; 279 280 #if !defined(INFOKEY) 281 282 static void 283 initialize_emacs_like_keymaps () 284 { 285 int i; 286 Keymap map; 287 288 if (!info_keymap) 289 { 290 info_keymap = keymap_make_keymap (); 291 echo_area_keymap = keymap_make_keymap (); 292 } 293 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 (); 298 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; 304 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 (); 310 311 /* Bind numeric arg functions for both echo area and info window maps. */ 312 for (i = '0'; i < '9' + 1; i++) 313 { 314 ((Keymap) info_keymap[ESC].function)[i].function 315 = ((Keymap) echo_area_keymap[ESC].function)[i].function 316 = info_add_digit_to_numeric_arg; 317 } 318 ((Keymap) info_keymap[ESC].function)['-'].function = 319 ((Keymap) echo_area_keymap[ESC].function)['-'].function = 320 info_add_digit_to_numeric_arg; 321 322 info_keymap['-'].function = info_add_digit_to_numeric_arg; 323 324 /* Bind the echo area routines. */ 325 map = echo_area_keymap; 326 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; 340 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 352 353 /* Bind the echo area ESC keymap. */ 354 map = (Keymap)echo_area_keymap[ESC].function; 355 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; 368 369 /* Bind the echo area Control-x keymap. */ 370 map = (Keymap)echo_area_keymap[Control ('x')].function; 371 372 map['o'].function = info_next_window; 373 map[DEL].function = ea_backward_kill_line; 374 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 */ 394 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 */ 403 404 map = (Keymap)echo_area_keymap[Control ('x')].function; 405 keymap_bind_keyseq (map, term_kD, &map[DEL]); /* delete */ 406 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; 428 429 for (i = '1'; i < '9' + 1; i++) 430 map[i].function = info_menu_digit; 431 map['0'].function = info_last_menu_item; 432 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; 438 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; 460 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; 477 478 /* Bind members in the Control-X map for Info windows. */ 479 map = (Keymap)info_keymap[Control ('x')].function; 480 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; 497 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 */ 516 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 */ 527 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']); 531 */ 532 keymap_bind_keyseq (info_keymap/*sic*/, term_kP, &map['v']); /* pageup */ 533 } 534 535 static void 536 initialize_vi_like_keymaps () 537 { 538 int i; 539 Keymap map; 540 541 if (!info_keymap) 542 { 543 info_keymap = keymap_make_keymap (); 544 echo_area_keymap = keymap_make_keymap (); 545 } 546 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 (); 551 552 /* Bind the echo area insert routines. */ 553 for (i = 0; i < 256; i++) 554 echo_area_keymap[i].function = ea_insert; 555 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 (); 561 562 /* Bind numeric arg functions for both echo area and info window maps. */ 563 for (i = '0'; i < '9' + 1; i++) 564 { 565 info_keymap[i].function = 566 ((Keymap) echo_area_keymap[ESC].function)[i].function = 567 info_add_digit_to_numeric_arg; 568 } 569 info_keymap['-'].function = 570 ((Keymap) echo_area_keymap[ESC].function)['-'].function = 571 info_add_digit_to_numeric_arg; 572 573 /* Bind the echo area routines. */ 574 map = echo_area_keymap; 575 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; 590 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 602 603 /* Bind the echo area ESC keymap. */ 604 map = (Keymap)echo_area_keymap[ESC].function; 605 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; 623 624 /* Bind the echo area Control-x keymap. */ 625 map = (Keymap)echo_area_keymap[Control ('x')].function; 626 627 map['o'].function = info_next_window; 628 map[DEL].function = ea_backward_kill_line; 629 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 */ 649 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 */ 658 659 map = (Keymap)echo_area_keymap[Control ('x')].function; 660 keymap_bind_keyseq (map, term_kD, &map[DEL]); 661 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; 685 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; 689 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; 696 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']); 734 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; 763 764 /* Bind members in the Control-X map for Info windows. */ 765 map = (Keymap)info_keymap[Control ('x')].function; 766 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')]); 793 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 */ 811 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 */ 822 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']); 826 */ 827 keymap_bind_keyseq (info_keymap/*sic*/, term_kP, &map['v']); /* pageup */ 828 } 829 830 void 831 initialize_info_keymaps () 832 { 833 if (vi_keys_p) 834 initialize_vi_like_keymaps (); 835 else 836 initialize_emacs_like_keymaps (); 837 } 838 839 #else /* defined(INFOKEY) */ 840 841 /* Make sure that we don't have too many command codes defined. */ 842 843 #if A_NCOMMANDS > A_MAX_COMMAND + 1 844 #error "too many commands defined" 845 #endif 846 847 /* Initialize the keymaps from the .info keymap file. */ 848 849 #define NUL '\0' 850 851 static unsigned char default_emacs_like_info_keys[] = 852 { 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 */ 954 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, 971 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. */ 975 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, 993 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, 1008 }; 1009 1010 static unsigned char default_emacs_like_ea_keys[] = 1011 { 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, 1085 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. */ 1089 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, 1111 }; 1112 1113 static unsigned char default_vi_like_info_keys[] = 1114 { 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, 1262 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. */ 1266 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, 1299 }; 1300 1301 static unsigned char default_vi_like_ea_keys[] = 1302 { 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, 1387 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. */ 1391 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, 1413 }; 1414 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; 1421 1422 /* 1423 * Return the size of a file, or 0 if the size can't be determined. 1424 */ 1425 static unsigned long 1426 filesize(int f) 1427 { 1428 long pos = lseek(f, 0L, SEEK_CUR); 1429 long sz = -1L; 1430 if (pos != -1L) 1431 { 1432 sz = lseek(f, 0L, SEEK_END); 1433 lseek(f, pos, SEEK_SET); 1434 } 1435 return sz == -1L ? 0L : sz; 1436 } 1437 1438 /* Get an integer from a infokey file. 1439 Integers are stored as two bytes, low order first, in radix INFOKEY_RADIX. 1440 */ 1441 static int 1442 getint(unsigned char **sp) 1443 { 1444 int n; 1445 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; 1451 } 1452 1453 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) 1458 { 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; 1467 1468 /* Find and open file. */ 1469 if ((filename = getenv("INFOKEY")) != NULL) 1470 filename = xstrdup(filename); 1471 else if ((homedir = getenv("HOME")) != NULL) 1472 { 1473 filename = xmalloc(strlen(homedir) + 2 + strlen(INFOKEY_FILE)); 1474 strcpy(filename, homedir); 1475 strcat(filename, "/"); 1476 strcat(filename, INFOKEY_FILE); 1477 } 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)) 1484 { 1485 if (filename && errno != ENOENT) 1486 { 1487 info_error(filesys_error_string(filename, errno), 1488 NULL, NULL); 1489 free(filename); 1490 } 1491 return 0; 1492 } 1493 SET_BINARY (f); 1494 1495 /* Ensure that the file is a reasonable size. */ 1496 len = filesize(f); 1497 if (len < INFOKEY_NMAGIC + 2 || len > 100 * 1024) 1498 { 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; 1510 } 1511 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) 1517 { 1518 info_error((char *) _("Error reading infokey file `%s' - short read"), 1519 filename, NULL); 1520 free(buf); 1521 free(filename); 1522 return 0; 1523 } 1524 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 1535 ) 1536 { 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; 1541 } 1542 if (len < INFOKEY_NMAGIC + strlen(VERSION) + 1 1543 || strcmp(VERSION, (char *) (buf + 4)) != 0) 1544 { 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; 1550 } 1551 1552 /* Extract the pieces. */ 1553 for (p = buf + 4 + strlen(VERSION) + 1; 1554 (unsigned int) (p - buf) < len - 4; 1555 p += n) 1556 { 1557 int s = *p++; 1558 1559 n = getint(&p); 1560 if (n < 0 || (unsigned int) n > len - 4 - (p - buf)) 1561 { 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; 1566 } 1567 1568 switch (s) 1569 { 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; 1587 } 1588 } 1589 1590 free(filename); 1591 return 1; 1592 } 1593 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. 1597 */ 1598 static int 1599 decode_keys(unsigned char *src, unsigned int slen, 1600 unsigned char *dst, unsigned int dlen) 1601 { 1602 unsigned char *s = src; 1603 unsigned char *d = dst; 1604 1605 #define To_dst(c) do { \ 1606 if ((unsigned int) (d - dst) < dlen) *d++ = (c); \ 1607 } while (0) 1608 1609 while ((unsigned int) (s - src) < slen) 1610 { 1611 unsigned char c = ISMETA(*s) ? UNMETA(*s) : *s; 1612 1613 if (c == SK_ESCAPE) 1614 { 1615 char *t; 1616 static char lit[] = { SK_ESCAPE, NUL }; 1617 1618 switch ((unsigned int) (s + 1 - src) < slen ? s[1] : '\0') 1619 { 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; 1632 } 1633 if (t == NULL) 1634 return 0; 1635 while (*t) 1636 To_dst(ISMETA(*s) ? Meta(*t++) : *t++); 1637 s += 2; 1638 } 1639 else 1640 { 1641 if (ISMETA(*s)) 1642 To_dst(Meta(*s++)); 1643 else 1644 To_dst(*s++); 1645 } 1646 } 1647 1648 To_dst('\0'); 1649 1650 return 1; 1651 1652 #undef To_dst 1653 1654 } 1655 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) 1660 { 1661 int stop; 1662 unsigned char *p; 1663 unsigned char *seq = NULL; 1664 unsigned int seqlen = 0; 1665 enum { getseq, gotseq, getaction } state = getseq; 1666 1667 stop = len > 0 ? table[0] : 0; 1668 1669 for (p = table + 1; (unsigned int) (p - table) < len; p++) 1670 { 1671 switch (state) 1672 { 1673 case getseq: 1674 if (*p) 1675 { 1676 seq = p; 1677 state = gotseq; 1678 } 1679 break; 1680 1681 case gotseq: 1682 if (!*p) 1683 { 1684 seqlen = p - seq; 1685 state = getaction; 1686 } 1687 break; 1688 1689 case getaction: 1690 { 1691 unsigned int action = *p; 1692 unsigned char keyseq[256]; 1693 KEYMAP_ENTRY ke; 1694 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)) 1703 { 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); 1712 } 1713 } 1714 break; 1715 } 1716 } 1717 if (state != getseq) 1718 info_error((char *) _("Bad data in infokey file -- some key bindings ignored"), 1719 NULL, NULL); 1720 return !stop; 1721 } 1722 1723 /* Convert an infokey file section to variable settings. 1724 */ 1725 static void 1726 section_to_vars(unsigned char *table, unsigned int len) 1727 { 1728 enum { getvar, gotvar, getval, gotval } state = getvar; 1729 unsigned char *var = NULL; 1730 unsigned char *val = NULL; 1731 unsigned char *p; 1732 1733 for (p = table; (unsigned int) (p - table) < len; p++) 1734 { 1735 switch (state) 1736 { 1737 case getvar: 1738 if (*p) 1739 { 1740 var = p; 1741 state = gotvar; 1742 } 1743 break; 1744 1745 case gotvar: 1746 if (!*p) 1747 state = getval; 1748 break; 1749 1750 case getval: 1751 if (*p) 1752 { 1753 val = p; 1754 state = gotval; 1755 } 1756 break; 1757 1758 case gotval: 1759 if (!*p) 1760 { 1761 set_variable_to_value((char *) var, (char *) val); 1762 state = getvar; 1763 } 1764 break; 1765 } 1766 } 1767 if (state != getvar) 1768 info_error((char *) _("Bad data in infokey file -- some var settings ignored"), 1769 NULL, NULL); 1770 } 1771 1772 void 1773 initialize_info_keymaps (void) 1774 { 1775 int i; 1776 int suppress_info_default_bindings = 0; 1777 int suppress_ea_default_bindings = 0; 1778 1779 if (!info_keymap) 1780 { 1781 info_keymap = keymap_make_keymap (); 1782 echo_area_keymap = keymap_make_keymap (); 1783 } 1784 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); 1789 1790 /* Get user-defined keys and variables. */ 1791 if (fetch_user_maps()) 1792 { 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; 1797 } 1798 1799 /* Apply the default bindings, unless the user says to suppress 1800 them. */ 1801 if (vi_keys_p) 1802 { 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)); 1809 } 1810 else 1811 { 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)); 1818 } 1819 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); 1824 1825 if (user_ea_keys_len) 1826 section_to_keymaps(echo_area_keymap, user_ea_keys, user_ea_keys_len); 1827 1828 if (user_vars_len) 1829 section_to_vars(user_vars, user_vars_len); 1830 } 1831 1832 #endif /* defined(INFOKEY) */ 1833 /* vim: set sw=2 cino={1s>2sn-s^-se-s: */ 1834