1 /* vi_mode.c -- A vi emulation mode for Bash. 2 Derived from code written by Jeff Sparkes (jsparkes@bnr.ca). */ 3 4 /* Copyright (C) 1987-2010 Free Software Foundation, Inc. 5 6 This file is part of the GNU Readline Library (Readline), a library 7 for reading lines of text with interactive input and history editing. 8 9 Readline 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 3 of the License, or 12 (at your option) any later version. 13 14 Readline 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 Readline. If not, see <http://www.gnu.org/licenses/>. 21 */ 22 23 #define READLINE_LIBRARY 24 25 /* **************************************************************** */ 26 /* */ 27 /* VI Emulation Mode */ 28 /* */ 29 /* **************************************************************** */ 30 #include "rlconf.h" 31 32 #if defined (VI_MODE) 33 34 #if defined (HAVE_CONFIG_H) 35 # include <config.h> 36 #endif 37 38 #include <sys/types.h> 39 40 #if defined (HAVE_STDLIB_H) 41 # include <stdlib.h> 42 #else 43 # include "ansi_stdlib.h" 44 #endif /* HAVE_STDLIB_H */ 45 46 #if defined (HAVE_UNISTD_H) 47 # include <unistd.h> 48 #endif 49 50 #include <stdio.h> 51 52 /* Some standard library routines. */ 53 #include "rldefs.h" 54 #include "rlmbutil.h" 55 56 #include "readline.h" 57 #include "history.h" 58 59 #include "rlprivate.h" 60 #include "xmalloc.h" 61 62 #ifndef member 63 #define member(c, s) ((c) ? (char *)strchr ((s), (c)) != (char *)NULL : 0) 64 #endif 65 66 int _rl_vi_last_command = 'i'; /* default `.' puts you in insert mode */ 67 68 _rl_vimotion_cxt *_rl_vimvcxt = 0; 69 70 /* Non-zero means enter insertion mode. */ 71 static int _rl_vi_doing_insert; 72 73 /* Command keys which do movement for xxx_to commands. */ 74 static const char * const vi_motion = " hl^$0ftFT;,%wbeWBE|`"; 75 76 /* Keymap used for vi replace characters. Created dynamically since 77 rarely used. */ 78 static Keymap vi_replace_map; 79 80 /* The number of characters inserted in the last replace operation. */ 81 static int vi_replace_count; 82 83 /* If non-zero, we have text inserted after a c[motion] command that put 84 us implicitly into insert mode. Some people want this text to be 85 attached to the command so that it is `redoable' with `.'. */ 86 static int vi_continued_command; 87 static char *vi_insert_buffer; 88 static int vi_insert_buffer_size; 89 90 static int _rl_vi_last_repeat = 1; 91 static int _rl_vi_last_arg_sign = 1; 92 static int _rl_vi_last_motion; 93 #if defined (HANDLE_MULTIBYTE) 94 static char _rl_vi_last_search_mbchar[MB_LEN_MAX]; 95 static int _rl_vi_last_search_mblen; 96 #else 97 static int _rl_vi_last_search_char; 98 #endif 99 static int _rl_vi_last_replacement; 100 101 static int _rl_vi_last_key_before_insert; 102 103 static int vi_redoing; 104 105 /* Text modification commands. These are the `redoable' commands. */ 106 static const char * const vi_textmod = "_*\\AaIiCcDdPpYyRrSsXx~"; 107 108 /* Arrays for the saved marks. */ 109 static int vi_mark_chars['z' - 'a' + 1]; 110 111 static void _rl_vi_stuff_insert PARAMS((int)); 112 static void _rl_vi_save_insert PARAMS((UNDO_LIST *)); 113 114 static void _rl_vi_backup PARAMS((void)); 115 116 static int _rl_vi_arg_dispatch PARAMS((int)); 117 static int rl_digit_loop1 PARAMS((void)); 118 119 static int _rl_vi_set_mark PARAMS((void)); 120 static int _rl_vi_goto_mark PARAMS((void)); 121 122 static void _rl_vi_append_forward PARAMS((int)); 123 124 static int _rl_vi_callback_getchar PARAMS((char *, int)); 125 126 #if defined (READLINE_CALLBACKS) 127 static int _rl_vi_callback_set_mark PARAMS((_rl_callback_generic_arg *)); 128 static int _rl_vi_callback_goto_mark PARAMS((_rl_callback_generic_arg *)); 129 static int _rl_vi_callback_change_char PARAMS((_rl_callback_generic_arg *)); 130 static int _rl_vi_callback_char_search PARAMS((_rl_callback_generic_arg *)); 131 #endif 132 133 static int rl_domove_read_callback PARAMS((_rl_vimotion_cxt *)); 134 static int rl_domove_motion_callback PARAMS((_rl_vimotion_cxt *)); 135 static int rl_vi_domove_getchar PARAMS((_rl_vimotion_cxt *)); 136 137 static int vi_change_dispatch PARAMS((_rl_vimotion_cxt *)); 138 static int vi_delete_dispatch PARAMS((_rl_vimotion_cxt *)); 139 static int vi_yank_dispatch PARAMS((_rl_vimotion_cxt *)); 140 141 static int vidomove_dispatch PARAMS((_rl_vimotion_cxt *)); 142 143 void 144 _rl_vi_initialize_line () 145 { 146 register int i, n; 147 148 n = sizeof (vi_mark_chars) / sizeof (vi_mark_chars[0]); 149 for (i = 0; i < n; i++) 150 vi_mark_chars[i] = -1; 151 152 RL_UNSETSTATE(RL_STATE_VICMDONCE); 153 } 154 155 void 156 _rl_vi_reset_last () 157 { 158 _rl_vi_last_command = 'i'; 159 _rl_vi_last_repeat = 1; 160 _rl_vi_last_arg_sign = 1; 161 _rl_vi_last_motion = 0; 162 } 163 164 void 165 _rl_vi_set_last (key, repeat, sign) 166 int key, repeat, sign; 167 { 168 _rl_vi_last_command = key; 169 _rl_vi_last_repeat = repeat; 170 _rl_vi_last_arg_sign = sign; 171 } 172 173 /* A convenience function that calls _rl_vi_set_last to save the last command 174 information and enters insertion mode. */ 175 void 176 rl_vi_start_inserting (key, repeat, sign) 177 int key, repeat, sign; 178 { 179 _rl_vi_set_last (key, repeat, sign); 180 rl_vi_insertion_mode (1, key); 181 } 182 183 /* Is the command C a VI mode text modification command? */ 184 int 185 _rl_vi_textmod_command (c) 186 int c; 187 { 188 return (member (c, vi_textmod)); 189 } 190 191 static void 192 _rl_vi_stuff_insert (count) 193 int count; 194 { 195 rl_begin_undo_group (); 196 while (count--) 197 rl_insert_text (vi_insert_buffer); 198 rl_end_undo_group (); 199 } 200 201 /* Bound to `.'. Called from command mode, so we know that we have to 202 redo a text modification command. The default for _rl_vi_last_command 203 puts you back into insert mode. */ 204 int 205 rl_vi_redo (count, c) 206 int count, c; 207 { 208 int r; 209 210 if (!rl_explicit_arg) 211 { 212 rl_numeric_arg = _rl_vi_last_repeat; 213 rl_arg_sign = _rl_vi_last_arg_sign; 214 } 215 216 r = 0; 217 vi_redoing = 1; 218 /* If we're redoing an insert with `i', stuff in the inserted text 219 and do not go into insertion mode. */ 220 if (_rl_vi_last_command == 'i' && vi_insert_buffer && *vi_insert_buffer) 221 { 222 _rl_vi_stuff_insert (count); 223 /* And back up point over the last character inserted. */ 224 if (rl_point > 0) 225 _rl_vi_backup (); 226 } 227 /* Ditto for redoing an insert with `I', but move to the beginning of the 228 line like the `I' command does. */ 229 else if (_rl_vi_last_command == 'I' && vi_insert_buffer && *vi_insert_buffer) 230 { 231 rl_beg_of_line (1, 'I'); 232 _rl_vi_stuff_insert (count); 233 if (rl_point > 0) 234 _rl_vi_backup (); 235 } 236 /* Ditto for redoing an insert with `a', but move forward a character first 237 like the `a' command does. */ 238 else if (_rl_vi_last_command == 'a' && vi_insert_buffer && *vi_insert_buffer) 239 { 240 _rl_vi_append_forward ('a'); 241 _rl_vi_stuff_insert (count); 242 if (rl_point > 0) 243 _rl_vi_backup (); 244 } 245 /* Ditto for redoing an insert with `A', but move to the end of the line 246 like the `A' command does. */ 247 else if (_rl_vi_last_command == 'A' && vi_insert_buffer && *vi_insert_buffer) 248 { 249 rl_end_of_line (1, 'A'); 250 _rl_vi_stuff_insert (count); 251 if (rl_point > 0) 252 _rl_vi_backup (); 253 } 254 else 255 r = _rl_dispatch (_rl_vi_last_command, _rl_keymap); 256 vi_redoing = 0; 257 258 return (r); 259 } 260 261 /* A placeholder for further expansion. */ 262 int 263 rl_vi_undo (count, key) 264 int count, key; 265 { 266 return (rl_undo_command (count, key)); 267 } 268 269 /* Yank the nth arg from the previous line into this line at point. */ 270 int 271 rl_vi_yank_arg (count, key) 272 int count, key; 273 { 274 /* Readline thinks that the first word on a line is the 0th, while vi 275 thinks the first word on a line is the 1st. Compensate. */ 276 if (rl_explicit_arg) 277 rl_yank_nth_arg (count - 1, 0); 278 else 279 rl_yank_nth_arg ('$', 0); 280 281 return (0); 282 } 283 284 /* With an argument, move back that many history lines, else move to the 285 beginning of history. */ 286 int 287 rl_vi_fetch_history (count, c) 288 int count, c; 289 { 290 int wanted; 291 292 /* Giving an argument of n means we want the nth command in the history 293 file. The command number is interpreted the same way that the bash 294 `history' command does it -- that is, giving an argument count of 450 295 to this command would get the command listed as number 450 in the 296 output of `history'. */ 297 if (rl_explicit_arg) 298 { 299 wanted = history_base + where_history () - count; 300 if (wanted <= 0) 301 rl_beginning_of_history (0, 0); 302 else 303 rl_get_previous_history (wanted, c); 304 } 305 else 306 rl_beginning_of_history (count, 0); 307 return (0); 308 } 309 310 /* Search again for the last thing searched for. */ 311 int 312 rl_vi_search_again (count, key) 313 int count, key; 314 { 315 switch (key) 316 { 317 case 'n': 318 rl_noninc_reverse_search_again (count, key); 319 break; 320 321 case 'N': 322 rl_noninc_forward_search_again (count, key); 323 break; 324 } 325 return (0); 326 } 327 328 /* Do a vi style search. */ 329 int 330 rl_vi_search (count, key) 331 int count, key; 332 { 333 switch (key) 334 { 335 case '?': 336 _rl_free_saved_history_line (); 337 rl_noninc_forward_search (count, key); 338 break; 339 340 case '/': 341 _rl_free_saved_history_line (); 342 rl_noninc_reverse_search (count, key); 343 break; 344 345 default: 346 rl_ding (); 347 break; 348 } 349 return (0); 350 } 351 352 /* Completion, from vi's point of view. */ 353 int 354 rl_vi_complete (ignore, key) 355 int ignore, key; 356 { 357 if ((rl_point < rl_end) && (!whitespace (rl_line_buffer[rl_point]))) 358 { 359 if (!whitespace (rl_line_buffer[rl_point + 1])) 360 rl_vi_end_word (1, 'E'); 361 rl_point++; 362 } 363 364 if (key == '*') 365 rl_complete_internal ('*'); /* Expansion and replacement. */ 366 else if (key == '=') 367 rl_complete_internal ('?'); /* List possible completions. */ 368 else if (key == '\\') 369 rl_complete_internal (TAB); /* Standard Readline completion. */ 370 else 371 rl_complete (0, key); 372 373 if (key == '*' || key == '\\') 374 rl_vi_start_inserting (key, 1, rl_arg_sign); 375 376 return (0); 377 } 378 379 /* Tilde expansion for vi mode. */ 380 int 381 rl_vi_tilde_expand (ignore, key) 382 int ignore, key; 383 { 384 rl_tilde_expand (0, key); 385 rl_vi_start_inserting (key, 1, rl_arg_sign); 386 return (0); 387 } 388 389 /* Previous word in vi mode. */ 390 int 391 rl_vi_prev_word (count, key) 392 int count, key; 393 { 394 if (count < 0) 395 return (rl_vi_next_word (-count, key)); 396 397 if (rl_point == 0) 398 { 399 rl_ding (); 400 return (0); 401 } 402 403 if (_rl_uppercase_p (key)) 404 rl_vi_bWord (count, key); 405 else 406 rl_vi_bword (count, key); 407 408 return (0); 409 } 410 411 /* Next word in vi mode. */ 412 int 413 rl_vi_next_word (count, key) 414 int count, key; 415 { 416 if (count < 0) 417 return (rl_vi_prev_word (-count, key)); 418 419 if (rl_point >= (rl_end - 1)) 420 { 421 rl_ding (); 422 return (0); 423 } 424 425 if (_rl_uppercase_p (key)) 426 rl_vi_fWord (count, key); 427 else 428 rl_vi_fword (count, key); 429 return (0); 430 } 431 432 /* Move to the end of the ?next? word. */ 433 int 434 rl_vi_end_word (count, key) 435 int count, key; 436 { 437 if (count < 0) 438 { 439 rl_ding (); 440 return -1; 441 } 442 443 if (_rl_uppercase_p (key)) 444 rl_vi_eWord (count, key); 445 else 446 rl_vi_eword (count, key); 447 return (0); 448 } 449 450 /* Move forward a word the way that 'W' does. */ 451 int 452 rl_vi_fWord (count, ignore) 453 int count, ignore; 454 { 455 while (count-- && rl_point < (rl_end - 1)) 456 { 457 /* Skip until whitespace. */ 458 while (!whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end) 459 rl_point++; 460 461 /* Now skip whitespace. */ 462 while (whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end) 463 rl_point++; 464 } 465 return (0); 466 } 467 468 int 469 rl_vi_bWord (count, ignore) 470 int count, ignore; 471 { 472 while (count-- && rl_point > 0) 473 { 474 /* If we are at the start of a word, move back to whitespace so 475 we will go back to the start of the previous word. */ 476 if (!whitespace (rl_line_buffer[rl_point]) && 477 whitespace (rl_line_buffer[rl_point - 1])) 478 rl_point--; 479 480 while (rl_point > 0 && whitespace (rl_line_buffer[rl_point])) 481 rl_point--; 482 483 if (rl_point > 0) 484 { 485 while (--rl_point >= 0 && !whitespace (rl_line_buffer[rl_point])); 486 rl_point++; 487 } 488 } 489 return (0); 490 } 491 492 int 493 rl_vi_eWord (count, ignore) 494 int count, ignore; 495 { 496 while (count-- && rl_point < (rl_end - 1)) 497 { 498 if (!whitespace (rl_line_buffer[rl_point])) 499 rl_point++; 500 501 /* Move to the next non-whitespace character (to the start of the 502 next word). */ 503 while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point])) 504 rl_point++; 505 506 if (rl_point && rl_point < rl_end) 507 { 508 /* Skip whitespace. */ 509 while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point])) 510 rl_point++; 511 512 /* Skip until whitespace. */ 513 while (rl_point < rl_end && !whitespace (rl_line_buffer[rl_point])) 514 rl_point++; 515 516 /* Move back to the last character of the word. */ 517 rl_point--; 518 } 519 } 520 return (0); 521 } 522 523 int 524 rl_vi_fword (count, ignore) 525 int count, ignore; 526 { 527 while (count-- && rl_point < (rl_end - 1)) 528 { 529 /* Move to white space (really non-identifer). */ 530 if (_rl_isident (rl_line_buffer[rl_point])) 531 { 532 while (_rl_isident (rl_line_buffer[rl_point]) && rl_point < rl_end) 533 rl_point++; 534 } 535 else /* if (!whitespace (rl_line_buffer[rl_point])) */ 536 { 537 while (!_rl_isident (rl_line_buffer[rl_point]) && 538 !whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end) 539 rl_point++; 540 } 541 542 /* Move past whitespace. */ 543 while (whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end) 544 rl_point++; 545 } 546 return (0); 547 } 548 549 int 550 rl_vi_bword (count, ignore) 551 int count, ignore; 552 { 553 while (count-- && rl_point > 0) 554 { 555 int last_is_ident; 556 557 /* If we are at the start of a word, move back to whitespace 558 so we will go back to the start of the previous word. */ 559 if (!whitespace (rl_line_buffer[rl_point]) && 560 whitespace (rl_line_buffer[rl_point - 1])) 561 rl_point--; 562 563 /* If this character and the previous character are `opposite', move 564 back so we don't get messed up by the rl_point++ down there in 565 the while loop. Without this code, words like `l;' screw up the 566 function. */ 567 last_is_ident = _rl_isident (rl_line_buffer[rl_point - 1]); 568 if ((_rl_isident (rl_line_buffer[rl_point]) && !last_is_ident) || 569 (!_rl_isident (rl_line_buffer[rl_point]) && last_is_ident)) 570 rl_point--; 571 572 while (rl_point > 0 && whitespace (rl_line_buffer[rl_point])) 573 rl_point--; 574 575 if (rl_point > 0) 576 { 577 if (_rl_isident (rl_line_buffer[rl_point])) 578 while (--rl_point >= 0 && _rl_isident (rl_line_buffer[rl_point])); 579 else 580 while (--rl_point >= 0 && !_rl_isident (rl_line_buffer[rl_point]) && 581 !whitespace (rl_line_buffer[rl_point])); 582 rl_point++; 583 } 584 } 585 return (0); 586 } 587 588 int 589 rl_vi_eword (count, ignore) 590 int count, ignore; 591 { 592 while (count-- && rl_point < rl_end - 1) 593 { 594 if (!whitespace (rl_line_buffer[rl_point])) 595 rl_point++; 596 597 while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point])) 598 rl_point++; 599 600 if (rl_point < rl_end) 601 { 602 if (_rl_isident (rl_line_buffer[rl_point])) 603 while (++rl_point < rl_end && _rl_isident (rl_line_buffer[rl_point])); 604 else 605 while (++rl_point < rl_end && !_rl_isident (rl_line_buffer[rl_point]) 606 && !whitespace (rl_line_buffer[rl_point])); 607 } 608 rl_point--; 609 } 610 return (0); 611 } 612 613 int 614 rl_vi_insert_beg (count, key) 615 int count, key; 616 { 617 rl_beg_of_line (1, key); 618 rl_vi_insert_mode (1, key); 619 return (0); 620 } 621 622 static void 623 _rl_vi_append_forward (key) 624 int key; 625 { 626 int point; 627 628 if (rl_point < rl_end) 629 { 630 if (MB_CUR_MAX == 1 || rl_byte_oriented) 631 rl_point++; 632 else 633 { 634 point = rl_point; 635 #if 0 636 rl_forward_char (1, key); 637 #else 638 rl_point = _rl_forward_char_internal (1); 639 #endif 640 if (point == rl_point) 641 rl_point = rl_end; 642 } 643 } 644 } 645 646 int 647 rl_vi_append_mode (count, key) 648 int count, key; 649 { 650 _rl_vi_append_forward (key); 651 rl_vi_start_inserting (key, 1, rl_arg_sign); 652 return (0); 653 } 654 655 int 656 rl_vi_append_eol (count, key) 657 int count, key; 658 { 659 rl_end_of_line (1, key); 660 rl_vi_append_mode (1, key); 661 return (0); 662 } 663 664 /* What to do in the case of C-d. */ 665 int 666 rl_vi_eof_maybe (count, c) 667 int count, c; 668 { 669 return (rl_newline (1, '\n')); 670 } 671 672 /* Insertion mode stuff. */ 673 674 /* Switching from one mode to the other really just involves 675 switching keymaps. */ 676 int 677 rl_vi_insertion_mode (count, key) 678 int count, key; 679 { 680 _rl_keymap = vi_insertion_keymap; 681 _rl_vi_last_key_before_insert = key; 682 return (0); 683 } 684 685 int 686 rl_vi_insert_mode (count, key) 687 int count, key; 688 { 689 rl_vi_start_inserting (key, 1, rl_arg_sign); 690 return (0); 691 } 692 693 static void 694 _rl_vi_save_insert (up) 695 UNDO_LIST *up; 696 { 697 int len, start, end; 698 699 if (up == 0 || up->what != UNDO_INSERT) 700 { 701 if (vi_insert_buffer_size >= 1) 702 vi_insert_buffer[0] = '\0'; 703 return; 704 } 705 706 start = up->start; 707 end = up->end; 708 len = end - start + 1; 709 if (len >= vi_insert_buffer_size) 710 { 711 vi_insert_buffer_size += (len + 32) - (len % 32); 712 vi_insert_buffer = (char *)xrealloc (vi_insert_buffer, vi_insert_buffer_size); 713 } 714 strncpy (vi_insert_buffer, rl_line_buffer + start, len - 1); 715 vi_insert_buffer[len-1] = '\0'; 716 } 717 718 void 719 _rl_vi_done_inserting () 720 { 721 if (_rl_vi_doing_insert) 722 { 723 /* The `C', `s', and `S' commands set this. */ 724 rl_end_undo_group (); 725 /* Now, the text between rl_undo_list->next->start and 726 rl_undo_list->next->end is what was inserted while in insert 727 mode. It gets copied to VI_INSERT_BUFFER because it depends 728 on absolute indices into the line which may change (though they 729 probably will not). */ 730 _rl_vi_doing_insert = 0; 731 _rl_vi_save_insert (rl_undo_list->next); 732 vi_continued_command = 1; 733 } 734 else 735 { 736 if (rl_undo_list && (_rl_vi_last_key_before_insert == 'i' || 737 _rl_vi_last_key_before_insert == 'a' || 738 _rl_vi_last_key_before_insert == 'I' || 739 _rl_vi_last_key_before_insert == 'A')) 740 _rl_vi_save_insert (rl_undo_list); 741 /* XXX - Other keys probably need to be checked. */ 742 else if (_rl_vi_last_key_before_insert == 'C') 743 rl_end_undo_group (); 744 while (_rl_undo_group_level > 0) 745 rl_end_undo_group (); 746 vi_continued_command = 0; 747 } 748 } 749 750 int 751 rl_vi_movement_mode (count, key) 752 int count, key; 753 { 754 if (rl_point > 0) 755 rl_backward_char (1, key); 756 757 _rl_keymap = vi_movement_keymap; 758 _rl_vi_done_inserting (); 759 760 /* This is how POSIX.2 says `U' should behave -- everything up until the 761 first time you go into command mode should not be undone. */ 762 if (RL_ISSTATE (RL_STATE_VICMDONCE) == 0) 763 rl_free_undo_list (); 764 765 RL_SETSTATE (RL_STATE_VICMDONCE); 766 return (0); 767 } 768 769 int 770 rl_vi_arg_digit (count, c) 771 int count, c; 772 { 773 if (c == '0' && rl_numeric_arg == 1 && !rl_explicit_arg) 774 return (rl_beg_of_line (1, c)); 775 else 776 return (rl_digit_argument (count, c)); 777 } 778 779 /* Change the case of the next COUNT characters. */ 780 #if defined (HANDLE_MULTIBYTE) 781 static int 782 _rl_vi_change_mbchar_case (count) 783 int count; 784 { 785 wchar_t wc; 786 char mb[MB_LEN_MAX+1]; 787 int mlen, p; 788 size_t m; 789 mbstate_t ps; 790 791 memset (&ps, 0, sizeof (mbstate_t)); 792 if (_rl_adjust_point (rl_line_buffer, rl_point, &ps) > 0) 793 count--; 794 while (count-- && rl_point < rl_end) 795 { 796 m = mbrtowc (&wc, rl_line_buffer + rl_point, rl_end - rl_point, &ps); 797 if (MB_INVALIDCH (m)) 798 wc = (wchar_t)rl_line_buffer[rl_point]; 799 else if (MB_NULLWCH (m)) 800 wc = L'\0'; 801 if (iswupper (wc)) 802 wc = towlower (wc); 803 else if (iswlower (wc)) 804 wc = towupper (wc); 805 else 806 { 807 /* Just skip over chars neither upper nor lower case */ 808 rl_forward_char (1, 0); 809 continue; 810 } 811 812 /* Vi is kind of strange here. */ 813 if (wc) 814 { 815 p = rl_point; 816 mlen = wcrtomb (mb, wc, &ps); 817 if (mlen >= 0) 818 mb[mlen] = '\0'; 819 rl_begin_undo_group (); 820 rl_vi_delete (1, 0); 821 if (rl_point < p) /* Did we retreat at EOL? */ 822 rl_point++; /* XXX - should we advance more than 1 for mbchar? */ 823 rl_insert_text (mb); 824 rl_end_undo_group (); 825 rl_vi_check (); 826 } 827 else 828 rl_forward_char (1, 0); 829 } 830 831 return 0; 832 } 833 #endif 834 835 int 836 rl_vi_change_case (count, ignore) 837 int count, ignore; 838 { 839 int c, p; 840 841 /* Don't try this on an empty line. */ 842 if (rl_point >= rl_end) 843 return (0); 844 845 c = 0; 846 #if defined (HANDLE_MULTIBYTE) 847 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 848 return (_rl_vi_change_mbchar_case (count)); 849 #endif 850 851 while (count-- && rl_point < rl_end) 852 { 853 if (_rl_uppercase_p (rl_line_buffer[rl_point])) 854 c = _rl_to_lower (rl_line_buffer[rl_point]); 855 else if (_rl_lowercase_p (rl_line_buffer[rl_point])) 856 c = _rl_to_upper (rl_line_buffer[rl_point]); 857 else 858 { 859 /* Just skip over characters neither upper nor lower case. */ 860 rl_forward_char (1, c); 861 continue; 862 } 863 864 /* Vi is kind of strange here. */ 865 if (c) 866 { 867 p = rl_point; 868 rl_begin_undo_group (); 869 rl_vi_delete (1, c); 870 if (rl_point < p) /* Did we retreat at EOL? */ 871 rl_point++; 872 _rl_insert_char (1, c); 873 rl_end_undo_group (); 874 rl_vi_check (); 875 } 876 else 877 rl_forward_char (1, c); 878 } 879 return (0); 880 } 881 882 int 883 rl_vi_put (count, key) 884 int count, key; 885 { 886 if (!_rl_uppercase_p (key) && (rl_point + 1 <= rl_end)) 887 rl_point = _rl_find_next_mbchar (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO); 888 889 while (count--) 890 rl_yank (1, key); 891 892 rl_backward_char (1, key); 893 return (0); 894 } 895 896 static void 897 _rl_vi_backup () 898 { 899 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 900 rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO); 901 else 902 rl_point--; 903 } 904 905 int 906 rl_vi_check () 907 { 908 if (rl_point && rl_point == rl_end) 909 { 910 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 911 rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO); 912 else 913 rl_point--; 914 } 915 return (0); 916 } 917 918 int 919 rl_vi_column (count, key) 920 int count, key; 921 { 922 if (count > rl_end) 923 rl_end_of_line (1, key); 924 else 925 rl_point = count - 1; 926 return (0); 927 } 928 929 /* Process C as part of the current numeric argument. Return -1 if the 930 argument should be aborted, 0 if we should not read any more chars, and 931 1 if we should continue to read chars. */ 932 static int 933 _rl_vi_arg_dispatch (c) 934 int c; 935 { 936 int key; 937 938 key = c; 939 if (c >= 0 && _rl_keymap[c].type == ISFUNC && _rl_keymap[c].function == rl_universal_argument) 940 { 941 rl_numeric_arg *= 4; 942 return 1; 943 } 944 945 c = UNMETA (c); 946 947 if (_rl_digit_p (c)) 948 { 949 if (rl_explicit_arg) 950 rl_numeric_arg = (rl_numeric_arg * 10) + _rl_digit_value (c); 951 else 952 rl_numeric_arg = _rl_digit_value (c); 953 rl_explicit_arg = 1; 954 return 1; /* keep going */ 955 } 956 else 957 { 958 rl_clear_message (); 959 rl_stuff_char (key); 960 return 0; /* done */ 961 } 962 } 963 964 /* A simplified loop for vi. Don't dispatch key at end. 965 Don't recognize minus sign? 966 Should this do rl_save_prompt/rl_restore_prompt? */ 967 static int 968 rl_digit_loop1 () 969 { 970 int c, r; 971 972 while (1) 973 { 974 if (_rl_arg_overflow ()) 975 return 1; 976 977 c = _rl_arg_getchar (); 978 979 r = _rl_vi_arg_dispatch (c); 980 if (r <= 0) 981 break; 982 } 983 984 RL_UNSETSTATE(RL_STATE_NUMERICARG); 985 return (0); 986 } 987 988 static void 989 _rl_mvcxt_init (m, op, key) 990 _rl_vimotion_cxt *m; 991 int op, key; 992 { 993 m->op = op; 994 m->state = m->flags = 0; 995 m->ncxt = 0; 996 m->numeric_arg = -1; 997 m->start = rl_point; 998 m->end = rl_end; 999 m->key = key; 1000 m->motion = -1; 1001 } 1002 1003 static _rl_vimotion_cxt * 1004 _rl_mvcxt_alloc (op, key) 1005 int op, key; 1006 { 1007 _rl_vimotion_cxt *m; 1008 1009 m = xmalloc (sizeof (_rl_vimotion_cxt)); 1010 _rl_mvcxt_init (m, op, key); 1011 return m; 1012 } 1013 1014 static void 1015 _rl_mvcxt_dispose (m) 1016 _rl_vimotion_cxt *m; 1017 { 1018 xfree (m); 1019 } 1020 1021 static int 1022 rl_domove_motion_callback (m) 1023 _rl_vimotion_cxt *m; 1024 { 1025 int c, save, r; 1026 int old_end; 1027 1028 _rl_vi_last_motion = c = m->motion; 1029 1030 /* Append a blank character temporarily so that the motion routines 1031 work right at the end of the line. */ 1032 old_end = rl_end; 1033 rl_line_buffer[rl_end++] = ' '; 1034 rl_line_buffer[rl_end] = '\0'; 1035 1036 _rl_dispatch (c, _rl_keymap); 1037 1038 /* Remove the blank that we added. */ 1039 rl_end = old_end; 1040 rl_line_buffer[rl_end] = '\0'; 1041 if (rl_point > rl_end) 1042 rl_point = rl_end; 1043 1044 /* No change in position means the command failed. */ 1045 if (rl_mark == rl_point) 1046 return (-1); 1047 1048 /* rl_vi_f[wW]ord () leaves the cursor on the first character of the next 1049 word. If we are not at the end of the line, and we are on a 1050 non-whitespace character, move back one (presumably to whitespace). */ 1051 if ((_rl_to_upper (c) == 'W') && rl_point < rl_end && rl_point > rl_mark && 1052 !whitespace (rl_line_buffer[rl_point])) 1053 rl_point--; 1054 1055 /* If cw or cW, back up to the end of a word, so the behaviour of ce 1056 or cE is the actual result. Brute-force, no subtlety. */ 1057 if (m->key == 'c' && rl_point >= rl_mark && (_rl_to_upper (c) == 'W')) 1058 { 1059 /* Don't move farther back than where we started. */ 1060 while (rl_point > rl_mark && whitespace (rl_line_buffer[rl_point])) 1061 rl_point--; 1062 1063 /* Posix.2 says that if cw or cW moves the cursor towards the end of 1064 the line, the character under the cursor should be deleted. */ 1065 if (rl_point == rl_mark) 1066 rl_point++; 1067 else 1068 { 1069 /* Move past the end of the word so that the kill doesn't 1070 remove the last letter of the previous word. Only do this 1071 if we are not at the end of the line. */ 1072 if (rl_point >= 0 && rl_point < (rl_end - 1) && !whitespace (rl_line_buffer[rl_point])) 1073 rl_point++; 1074 } 1075 } 1076 1077 if (rl_mark < rl_point) 1078 SWAP (rl_point, rl_mark); 1079 1080 #if defined (READLINE_CALLBACKS) 1081 if (RL_ISSTATE (RL_STATE_CALLBACK)) 1082 (*rl_redisplay_function)(); /* make sure motion is displayed */ 1083 #endif 1084 1085 r = vidomove_dispatch (m); 1086 1087 return (r); 1088 } 1089 1090 #define RL_VIMOVENUMARG() (RL_ISSTATE (RL_STATE_VIMOTION) && RL_ISSTATE (RL_STATE_NUMERICARG)) 1091 1092 static int 1093 rl_domove_read_callback (m) 1094 _rl_vimotion_cxt *m; 1095 { 1096 int c, save; 1097 1098 c = m->motion; 1099 1100 if (member (c, vi_motion)) 1101 { 1102 #if defined (READLINE_CALLBACKS) 1103 /* If we just read a vi-mode motion command numeric argument, turn off 1104 the `reading numeric arg' state */ 1105 if (RL_ISSTATE (RL_STATE_CALLBACK) && RL_VIMOVENUMARG()) 1106 RL_UNSETSTATE (RL_STATE_NUMERICARG); 1107 #endif 1108 /* Should do everything, including turning off RL_STATE_VIMOTION */ 1109 return (rl_domove_motion_callback (m)); 1110 } 1111 else if (m->key == c && (m->key == 'd' || m->key == 'y' || m->key == 'c')) 1112 { 1113 rl_mark = rl_end; 1114 rl_beg_of_line (1, c); 1115 _rl_vi_last_motion = c; 1116 RL_UNSETSTATE (RL_STATE_VIMOTION); 1117 return (vidomove_dispatch (m)); 1118 } 1119 #if defined (READLINE_CALLBACKS) 1120 /* XXX - these need to handle rl_universal_argument bindings */ 1121 /* Reading vi motion char continuing numeric argument */ 1122 else if (_rl_digit_p (c) && RL_ISSTATE (RL_STATE_CALLBACK) && RL_VIMOVENUMARG()) 1123 { 1124 return (_rl_vi_arg_dispatch (c)); 1125 } 1126 /* Readine vi motion char starting numeric argument */ 1127 else if (_rl_digit_p (c) && RL_ISSTATE (RL_STATE_CALLBACK) && RL_ISSTATE (RL_STATE_VIMOTION) && (RL_ISSTATE (RL_STATE_NUMERICARG) == 0)) 1128 { 1129 RL_SETSTATE (RL_STATE_NUMERICARG); 1130 return (_rl_vi_arg_dispatch (c)); 1131 } 1132 #endif 1133 else if (_rl_digit_p (c)) 1134 { 1135 /* This code path taken when not in callback mode */ 1136 save = rl_numeric_arg; 1137 rl_numeric_arg = _rl_digit_value (c); 1138 rl_explicit_arg = 1; 1139 RL_SETSTATE (RL_STATE_NUMERICARG); 1140 rl_digit_loop1 (); 1141 rl_numeric_arg *= save; 1142 c = rl_vi_domove_getchar (m); 1143 if (c < 0) 1144 { 1145 m->motion = 0; 1146 return -1; 1147 } 1148 m->motion = c; 1149 return (rl_domove_motion_callback (m)); 1150 } 1151 else 1152 { 1153 RL_UNSETSTATE (RL_STATE_VIMOTION); 1154 RL_UNSETSTATE (RL_STATE_NUMERICARG); 1155 return (1); 1156 } 1157 } 1158 1159 static int 1160 rl_vi_domove_getchar (m) 1161 _rl_vimotion_cxt *m; 1162 { 1163 int c; 1164 1165 RL_SETSTATE(RL_STATE_MOREINPUT); 1166 c = rl_read_key (); 1167 RL_UNSETSTATE(RL_STATE_MOREINPUT); 1168 1169 return c; 1170 } 1171 1172 #if defined (READLINE_CALLBACKS) 1173 int 1174 _rl_vi_domove_callback (m) 1175 _rl_vimotion_cxt *m; 1176 { 1177 int c, r; 1178 1179 m->motion = c = rl_vi_domove_getchar (m); 1180 /* XXX - what to do if this returns -1? Should we return 1 for eof to 1181 callback code? */ 1182 r = rl_domove_read_callback (m); 1183 1184 return ((r == 0) ? r : 1); /* normalize return values */ 1185 } 1186 #endif 1187 1188 /* This code path taken when not in callback mode. */ 1189 int 1190 rl_vi_domove (x, ignore) 1191 int x, *ignore; 1192 { 1193 int r; 1194 _rl_vimotion_cxt *m; 1195 1196 m = _rl_vimvcxt; 1197 *ignore = m->motion = rl_vi_domove_getchar (m); 1198 1199 if (m->motion < 0) 1200 { 1201 m->motion = 0; 1202 return -1; 1203 } 1204 1205 return (rl_domove_read_callback (m)); 1206 } 1207 1208 static int 1209 vi_delete_dispatch (m) 1210 _rl_vimotion_cxt *m; 1211 { 1212 /* These are the motion commands that do not require adjusting the 1213 mark. */ 1214 if (((strchr (" l|h^0bBFT`", m->motion) == 0) && (rl_point >= m->start)) && 1215 (rl_mark < rl_end)) 1216 rl_mark++; 1217 1218 rl_kill_text (rl_point, rl_mark); 1219 return (0); 1220 } 1221 1222 int 1223 rl_vi_delete_to (count, key) 1224 int count, key; 1225 { 1226 int c, r; 1227 1228 _rl_vimvcxt = _rl_mvcxt_alloc (VIM_DELETE, key); 1229 _rl_vimvcxt->start = rl_point; 1230 1231 rl_mark = rl_point; 1232 if (_rl_uppercase_p (key)) 1233 { 1234 _rl_vimvcxt->motion = '$'; 1235 r = rl_domove_motion_callback (_rl_vimvcxt); 1236 } 1237 else if (vi_redoing) 1238 { 1239 _rl_vimvcxt->motion = _rl_vi_last_motion; 1240 r = rl_domove_motion_callback (_rl_vimvcxt); 1241 } 1242 #if defined (READLINE_CALLBACKS) 1243 else if (RL_ISSTATE (RL_STATE_CALLBACK)) 1244 { 1245 RL_SETSTATE (RL_STATE_VIMOTION); 1246 return (0); 1247 } 1248 #endif 1249 else 1250 r = rl_vi_domove (key, &c); 1251 1252 if (r < 0) 1253 { 1254 rl_ding (); 1255 r = -1; 1256 } 1257 1258 _rl_mvcxt_dispose (_rl_vimvcxt); 1259 _rl_vimvcxt = 0; 1260 1261 return r; 1262 } 1263 1264 static int 1265 vi_change_dispatch (m) 1266 _rl_vimotion_cxt *m; 1267 { 1268 /* These are the motion commands that do not require adjusting the 1269 mark. c[wW] are handled by special-case code in rl_vi_domove(), 1270 and already leave the mark at the correct location. */ 1271 if (((strchr (" l|hwW^0bBFT`", m->motion) == 0) && (rl_point >= m->start)) && 1272 (rl_mark < rl_end)) 1273 rl_mark++; 1274 1275 /* The cursor never moves with c[wW]. */ 1276 if ((_rl_to_upper (m->motion) == 'W') && rl_point < m->start) 1277 rl_point = m->start; 1278 1279 if (vi_redoing) 1280 { 1281 if (vi_insert_buffer && *vi_insert_buffer) 1282 rl_begin_undo_group (); 1283 rl_delete_text (rl_point, rl_mark); 1284 if (vi_insert_buffer && *vi_insert_buffer) 1285 { 1286 rl_insert_text (vi_insert_buffer); 1287 rl_end_undo_group (); 1288 } 1289 } 1290 else 1291 { 1292 rl_begin_undo_group (); /* to make the `u' command work */ 1293 rl_kill_text (rl_point, rl_mark); 1294 /* `C' does not save the text inserted for undoing or redoing. */ 1295 if (_rl_uppercase_p (m->key) == 0) 1296 _rl_vi_doing_insert = 1; 1297 /* XXX -- TODO -- use m->numericarg? */ 1298 rl_vi_start_inserting (m->key, rl_numeric_arg, rl_arg_sign); 1299 } 1300 1301 return (0); 1302 } 1303 1304 int 1305 rl_vi_change_to (count, key) 1306 int count, key; 1307 { 1308 int c, r; 1309 1310 _rl_vimvcxt = _rl_mvcxt_alloc (VIM_CHANGE, key); 1311 _rl_vimvcxt->start = rl_point; 1312 1313 rl_mark = rl_point; 1314 if (_rl_uppercase_p (key)) 1315 { 1316 _rl_vimvcxt->motion = '$'; 1317 r = rl_domove_motion_callback (_rl_vimvcxt); 1318 } 1319 else if (vi_redoing) 1320 { 1321 _rl_vimvcxt->motion = _rl_vi_last_motion; 1322 r = rl_domove_motion_callback (_rl_vimvcxt); 1323 } 1324 #if defined (READLINE_CALLBACKS) 1325 else if (RL_ISSTATE (RL_STATE_CALLBACK)) 1326 { 1327 RL_SETSTATE (RL_STATE_VIMOTION); 1328 return (0); 1329 } 1330 #endif 1331 else 1332 r = rl_vi_domove (key, &c); 1333 1334 if (r < 0) 1335 { 1336 rl_ding (); 1337 r = -1; /* normalize return value */ 1338 } 1339 1340 _rl_mvcxt_dispose (_rl_vimvcxt); 1341 _rl_vimvcxt = 0; 1342 1343 return r; 1344 } 1345 1346 static int 1347 vi_yank_dispatch (m) 1348 _rl_vimotion_cxt *m; 1349 { 1350 /* These are the motion commands that do not require adjusting the 1351 mark. */ 1352 if (((strchr (" l|h^0%bBFT`", m->motion) == 0) && (rl_point >= m->start)) && 1353 (rl_mark < rl_end)) 1354 rl_mark++; 1355 1356 rl_begin_undo_group (); 1357 rl_kill_text (rl_point, rl_mark); 1358 rl_end_undo_group (); 1359 rl_do_undo (); 1360 rl_point = m->start; 1361 1362 return (0); 1363 } 1364 1365 int 1366 rl_vi_yank_to (count, key) 1367 int count, key; 1368 { 1369 int c, r; 1370 1371 _rl_vimvcxt = _rl_mvcxt_alloc (VIM_YANK, key); 1372 _rl_vimvcxt->start = rl_point; 1373 1374 rl_mark = rl_point; 1375 if (_rl_uppercase_p (key)) 1376 { 1377 _rl_vimvcxt->motion = '$'; 1378 r = rl_domove_motion_callback (_rl_vimvcxt); 1379 } 1380 #if defined (READLINE_CALLBACKS) 1381 else if (RL_ISSTATE (RL_STATE_CALLBACK)) 1382 { 1383 RL_SETSTATE (RL_STATE_VIMOTION); 1384 return (0); 1385 } 1386 #endif 1387 else 1388 r = rl_vi_domove (key, &c); 1389 1390 if (r < 0) 1391 { 1392 rl_ding (); 1393 r = -1; 1394 } 1395 1396 _rl_mvcxt_dispose (_rl_vimvcxt); 1397 _rl_vimvcxt = 0; 1398 1399 return r; 1400 } 1401 1402 static int 1403 vidomove_dispatch (m) 1404 _rl_vimotion_cxt *m; 1405 { 1406 int r; 1407 1408 switch (m->op) 1409 { 1410 case VIM_DELETE: 1411 r = vi_delete_dispatch (m); 1412 break; 1413 case VIM_CHANGE: 1414 r = vi_change_dispatch (m); 1415 break; 1416 case VIM_YANK: 1417 r = vi_yank_dispatch (m); 1418 break; 1419 default: 1420 _rl_errmsg ("vidomove_dispatch: unknown operator %d", m->op); 1421 r = 1; 1422 break; 1423 } 1424 1425 RL_UNSETSTATE (RL_STATE_VIMOTION); 1426 return r; 1427 } 1428 1429 int 1430 rl_vi_rubout (count, key) 1431 int count, key; 1432 { 1433 int opoint; 1434 1435 if (count < 0) 1436 return (rl_vi_delete (-count, key)); 1437 1438 if (rl_point == 0) 1439 { 1440 rl_ding (); 1441 return -1; 1442 } 1443 1444 opoint = rl_point; 1445 if (count > 1 && MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1446 rl_backward_char (count, key); 1447 else if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1448 rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO); 1449 else 1450 rl_point -= count; 1451 1452 if (rl_point < 0) 1453 rl_point = 0; 1454 1455 rl_kill_text (rl_point, opoint); 1456 1457 return (0); 1458 } 1459 1460 int 1461 rl_vi_delete (count, key) 1462 int count, key; 1463 { 1464 int end; 1465 1466 if (count < 0) 1467 return (rl_vi_rubout (-count, key)); 1468 1469 if (rl_end == 0) 1470 { 1471 rl_ding (); 1472 return -1; 1473 } 1474 1475 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1476 end = _rl_find_next_mbchar (rl_line_buffer, rl_point, count, MB_FIND_NONZERO); 1477 else 1478 end = rl_point + count; 1479 1480 if (end >= rl_end) 1481 end = rl_end; 1482 1483 rl_kill_text (rl_point, end); 1484 1485 if (rl_point > 0 && rl_point == rl_end) 1486 rl_backward_char (1, key); 1487 1488 return (0); 1489 } 1490 1491 int 1492 rl_vi_back_to_indent (count, key) 1493 int count, key; 1494 { 1495 rl_beg_of_line (1, key); 1496 while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point])) 1497 rl_point++; 1498 return (0); 1499 } 1500 1501 int 1502 rl_vi_first_print (count, key) 1503 int count, key; 1504 { 1505 return (rl_vi_back_to_indent (1, key)); 1506 } 1507 1508 static int _rl_cs_dir, _rl_cs_orig_dir; 1509 1510 #if defined (READLINE_CALLBACKS) 1511 static int 1512 _rl_vi_callback_char_search (data) 1513 _rl_callback_generic_arg *data; 1514 { 1515 int c; 1516 #if defined (HANDLE_MULTIBYTE) 1517 c = _rl_vi_last_search_mblen = _rl_read_mbchar (_rl_vi_last_search_mbchar, MB_LEN_MAX); 1518 #else 1519 RL_SETSTATE(RL_STATE_MOREINPUT); 1520 c = rl_read_key (); 1521 RL_UNSETSTATE(RL_STATE_MOREINPUT); 1522 #endif 1523 1524 if (c <= 0) 1525 return -1; 1526 1527 #if !defined (HANDLE_MULTIBYTE) 1528 _rl_vi_last_search_char = c; 1529 #endif 1530 1531 _rl_callback_func = 0; 1532 _rl_want_redisplay = 1; 1533 1534 #if defined (HANDLE_MULTIBYTE) 1535 return (_rl_char_search_internal (data->count, _rl_cs_dir, _rl_vi_last_search_mbchar, _rl_vi_last_search_mblen)); 1536 #else 1537 return (_rl_char_search_internal (data->count, _rl_cs_dir, _rl_vi_last_search_char)); 1538 #endif 1539 } 1540 #endif 1541 1542 int 1543 rl_vi_char_search (count, key) 1544 int count, key; 1545 { 1546 int c; 1547 #if defined (HANDLE_MULTIBYTE) 1548 static char *target; 1549 static int tlen; 1550 #else 1551 static char target; 1552 #endif 1553 1554 if (key == ';' || key == ',') 1555 { 1556 if (_rl_cs_orig_dir == 0) 1557 return -1; 1558 #if defined (HANDLE_MULTIBYTE) 1559 if (_rl_vi_last_search_mblen == 0) 1560 return -1; 1561 #else 1562 if (_rl_vi_last_search_char == 0) 1563 return -1; 1564 #endif 1565 _rl_cs_dir = (key == ';') ? _rl_cs_orig_dir : -_rl_cs_orig_dir; 1566 } 1567 else 1568 { 1569 switch (key) 1570 { 1571 case 't': 1572 _rl_cs_orig_dir = _rl_cs_dir = FTO; 1573 break; 1574 1575 case 'T': 1576 _rl_cs_orig_dir = _rl_cs_dir = BTO; 1577 break; 1578 1579 case 'f': 1580 _rl_cs_orig_dir = _rl_cs_dir = FFIND; 1581 break; 1582 1583 case 'F': 1584 _rl_cs_orig_dir = _rl_cs_dir = BFIND; 1585 break; 1586 } 1587 1588 if (vi_redoing) 1589 { 1590 /* set target and tlen below */ 1591 } 1592 #if defined (READLINE_CALLBACKS) 1593 else if (RL_ISSTATE (RL_STATE_CALLBACK)) 1594 { 1595 _rl_callback_data = _rl_callback_data_alloc (count); 1596 _rl_callback_data->i1 = _rl_cs_dir; 1597 _rl_callback_func = _rl_vi_callback_char_search; 1598 return (0); 1599 } 1600 #endif 1601 else 1602 { 1603 #if defined (HANDLE_MULTIBYTE) 1604 c = _rl_read_mbchar (_rl_vi_last_search_mbchar, MB_LEN_MAX); 1605 if (c <= 0) 1606 return -1; 1607 _rl_vi_last_search_mblen = c; 1608 #else 1609 RL_SETSTATE(RL_STATE_MOREINPUT); 1610 c = rl_read_key (); 1611 RL_UNSETSTATE(RL_STATE_MOREINPUT); 1612 if (c < 0) 1613 return -1; 1614 _rl_vi_last_search_char = c; 1615 #endif 1616 } 1617 } 1618 1619 #if defined (HANDLE_MULTIBYTE) 1620 target = _rl_vi_last_search_mbchar; 1621 tlen = _rl_vi_last_search_mblen; 1622 #else 1623 target = _rl_vi_last_search_char; 1624 #endif 1625 1626 #if defined (HANDLE_MULTIBYTE) 1627 return (_rl_char_search_internal (count, _rl_cs_dir, target, tlen)); 1628 #else 1629 return (_rl_char_search_internal (count, _rl_cs_dir, target)); 1630 #endif 1631 } 1632 1633 /* Match brackets */ 1634 int 1635 rl_vi_match (ignore, key) 1636 int ignore, key; 1637 { 1638 int count = 1, brack, pos, tmp, pre; 1639 1640 pos = rl_point; 1641 if ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0) 1642 { 1643 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1644 { 1645 while ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0) 1646 { 1647 pre = rl_point; 1648 rl_forward_char (1, key); 1649 if (pre == rl_point) 1650 break; 1651 } 1652 } 1653 else 1654 while ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0 && 1655 rl_point < rl_end - 1) 1656 rl_forward_char (1, key); 1657 1658 if (brack <= 0) 1659 { 1660 rl_point = pos; 1661 rl_ding (); 1662 return -1; 1663 } 1664 } 1665 1666 pos = rl_point; 1667 1668 if (brack < 0) 1669 { 1670 while (count) 1671 { 1672 tmp = pos; 1673 if (MB_CUR_MAX == 1 || rl_byte_oriented) 1674 pos--; 1675 else 1676 { 1677 pos = _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY); 1678 if (tmp == pos) 1679 pos--; 1680 } 1681 if (pos >= 0) 1682 { 1683 int b = rl_vi_bracktype (rl_line_buffer[pos]); 1684 if (b == -brack) 1685 count--; 1686 else if (b == brack) 1687 count++; 1688 } 1689 else 1690 { 1691 rl_ding (); 1692 return -1; 1693 } 1694 } 1695 } 1696 else 1697 { /* brack > 0 */ 1698 while (count) 1699 { 1700 if (MB_CUR_MAX == 1 || rl_byte_oriented) 1701 pos++; 1702 else 1703 pos = _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY); 1704 1705 if (pos < rl_end) 1706 { 1707 int b = rl_vi_bracktype (rl_line_buffer[pos]); 1708 if (b == -brack) 1709 count--; 1710 else if (b == brack) 1711 count++; 1712 } 1713 else 1714 { 1715 rl_ding (); 1716 return -1; 1717 } 1718 } 1719 } 1720 rl_point = pos; 1721 return (0); 1722 } 1723 1724 int 1725 rl_vi_bracktype (c) 1726 int c; 1727 { 1728 switch (c) 1729 { 1730 case '(': return 1; 1731 case ')': return -1; 1732 case '[': return 2; 1733 case ']': return -2; 1734 case '{': return 3; 1735 case '}': return -3; 1736 default: return 0; 1737 } 1738 } 1739 1740 static int 1741 _rl_vi_change_char (count, c, mb) 1742 int count, c; 1743 char *mb; 1744 { 1745 int p; 1746 1747 if (c == '\033' || c == CTRL ('C')) 1748 return -1; 1749 1750 rl_begin_undo_group (); 1751 while (count-- && rl_point < rl_end) 1752 { 1753 p = rl_point; 1754 rl_vi_delete (1, c); 1755 if (rl_point < p) /* Did we retreat at EOL? */ 1756 rl_point++; 1757 #if defined (HANDLE_MULTIBYTE) 1758 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1759 rl_insert_text (mb); 1760 else 1761 #endif 1762 _rl_insert_char (1, c); 1763 } 1764 1765 /* The cursor shall be left on the last character changed. */ 1766 rl_backward_char (1, c); 1767 1768 rl_end_undo_group (); 1769 1770 return (0); 1771 } 1772 1773 static int 1774 _rl_vi_callback_getchar (mb, mlen) 1775 char *mb; 1776 int mlen; 1777 { 1778 int c; 1779 1780 RL_SETSTATE(RL_STATE_MOREINPUT); 1781 c = rl_read_key (); 1782 RL_UNSETSTATE(RL_STATE_MOREINPUT); 1783 1784 if (c < 0) 1785 return -1; 1786 1787 #if defined (HANDLE_MULTIBYTE) 1788 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1789 c = _rl_read_mbstring (c, mb, mlen); 1790 #endif 1791 1792 return c; 1793 } 1794 1795 #if defined (READLINE_CALLBACKS) 1796 static int 1797 _rl_vi_callback_change_char (data) 1798 _rl_callback_generic_arg *data; 1799 { 1800 int c; 1801 char mb[MB_LEN_MAX]; 1802 1803 _rl_vi_last_replacement = c = _rl_vi_callback_getchar (mb, MB_LEN_MAX); 1804 1805 if (c < 0) 1806 return -1; 1807 1808 _rl_callback_func = 0; 1809 _rl_want_redisplay = 1; 1810 1811 return (_rl_vi_change_char (data->count, c, mb)); 1812 } 1813 #endif 1814 1815 int 1816 rl_vi_change_char (count, key) 1817 int count, key; 1818 { 1819 int c; 1820 char mb[MB_LEN_MAX]; 1821 1822 if (vi_redoing) 1823 { 1824 c = _rl_vi_last_replacement; 1825 mb[0] = c; 1826 mb[1] = '\0'; 1827 } 1828 #if defined (READLINE_CALLBACKS) 1829 else if (RL_ISSTATE (RL_STATE_CALLBACK)) 1830 { 1831 _rl_callback_data = _rl_callback_data_alloc (count); 1832 _rl_callback_func = _rl_vi_callback_change_char; 1833 return (0); 1834 } 1835 #endif 1836 else 1837 _rl_vi_last_replacement = c = _rl_vi_callback_getchar (mb, MB_LEN_MAX); 1838 1839 if (c < 0) 1840 return -1; 1841 1842 return (_rl_vi_change_char (count, c, mb)); 1843 } 1844 1845 int 1846 rl_vi_subst (count, key) 1847 int count, key; 1848 { 1849 /* If we are redoing, rl_vi_change_to will stuff the last motion char */ 1850 if (vi_redoing == 0) 1851 rl_stuff_char ((key == 'S') ? 'c' : 'l'); /* `S' == `cc', `s' == `cl' */ 1852 1853 return (rl_vi_change_to (count, 'c')); 1854 } 1855 1856 int 1857 rl_vi_overstrike (count, key) 1858 int count, key; 1859 { 1860 if (_rl_vi_doing_insert == 0) 1861 { 1862 _rl_vi_doing_insert = 1; 1863 rl_begin_undo_group (); 1864 } 1865 1866 if (count > 0) 1867 { 1868 _rl_overwrite_char (count, key); 1869 vi_replace_count += count; 1870 } 1871 1872 return (0); 1873 } 1874 1875 int 1876 rl_vi_overstrike_delete (count, key) 1877 int count, key; 1878 { 1879 int i, s; 1880 1881 for (i = 0; i < count; i++) 1882 { 1883 if (vi_replace_count == 0) 1884 { 1885 rl_ding (); 1886 break; 1887 } 1888 s = rl_point; 1889 1890 if (rl_do_undo ()) 1891 vi_replace_count--; 1892 1893 if (rl_point == s) 1894 rl_backward_char (1, key); 1895 } 1896 1897 if (vi_replace_count == 0 && _rl_vi_doing_insert) 1898 { 1899 rl_end_undo_group (); 1900 rl_do_undo (); 1901 _rl_vi_doing_insert = 0; 1902 } 1903 return (0); 1904 } 1905 1906 int 1907 rl_vi_replace (count, key) 1908 int count, key; 1909 { 1910 int i; 1911 1912 vi_replace_count = 0; 1913 1914 if (!vi_replace_map) 1915 { 1916 vi_replace_map = rl_make_bare_keymap (); 1917 1918 for (i = ' '; i < KEYMAP_SIZE; i++) 1919 vi_replace_map[i].function = rl_vi_overstrike; 1920 1921 vi_replace_map[RUBOUT].function = rl_vi_overstrike_delete; 1922 vi_replace_map[ESC].function = rl_vi_movement_mode; 1923 vi_replace_map[RETURN].function = rl_newline; 1924 vi_replace_map[NEWLINE].function = rl_newline; 1925 1926 /* If the normal vi insertion keymap has ^H bound to erase, do the 1927 same here. Probably should remove the assignment to RUBOUT up 1928 there, but I don't think it will make a difference in real life. */ 1929 if (vi_insertion_keymap[CTRL ('H')].type == ISFUNC && 1930 vi_insertion_keymap[CTRL ('H')].function == rl_rubout) 1931 vi_replace_map[CTRL ('H')].function = rl_vi_overstrike_delete; 1932 1933 } 1934 _rl_keymap = vi_replace_map; 1935 return (0); 1936 } 1937 1938 #if 0 1939 /* Try to complete the word we are standing on or the word that ends with 1940 the previous character. A space matches everything. Word delimiters are 1941 space and ;. */ 1942 int 1943 rl_vi_possible_completions() 1944 { 1945 int save_pos = rl_point; 1946 1947 if (rl_line_buffer[rl_point] != ' ' && rl_line_buffer[rl_point] != ';') 1948 { 1949 while (rl_point < rl_end && rl_line_buffer[rl_point] != ' ' && 1950 rl_line_buffer[rl_point] != ';') 1951 rl_point++; 1952 } 1953 else if (rl_line_buffer[rl_point - 1] == ';') 1954 { 1955 rl_ding (); 1956 return (0); 1957 } 1958 1959 rl_possible_completions (); 1960 rl_point = save_pos; 1961 1962 return (0); 1963 } 1964 #endif 1965 1966 /* Functions to save and restore marks. */ 1967 static int 1968 _rl_vi_set_mark () 1969 { 1970 int ch; 1971 1972 RL_SETSTATE(RL_STATE_MOREINPUT); 1973 ch = rl_read_key (); 1974 RL_UNSETSTATE(RL_STATE_MOREINPUT); 1975 1976 if (ch < 0 || ch < 'a' || ch > 'z') /* make test against 0 explicit */ 1977 { 1978 rl_ding (); 1979 return -1; 1980 } 1981 ch -= 'a'; 1982 vi_mark_chars[ch] = rl_point; 1983 return 0; 1984 } 1985 1986 #if defined (READLINE_CALLBACKS) 1987 static int 1988 _rl_vi_callback_set_mark (data) 1989 _rl_callback_generic_arg *data; 1990 { 1991 _rl_callback_func = 0; 1992 _rl_want_redisplay = 1; 1993 1994 return (_rl_vi_set_mark ()); 1995 } 1996 #endif 1997 1998 int 1999 rl_vi_set_mark (count, key) 2000 int count, key; 2001 { 2002 #if defined (READLINE_CALLBACKS) 2003 if (RL_ISSTATE (RL_STATE_CALLBACK)) 2004 { 2005 _rl_callback_data = 0; 2006 _rl_callback_func = _rl_vi_callback_set_mark; 2007 return (0); 2008 } 2009 #endif 2010 2011 return (_rl_vi_set_mark ()); 2012 } 2013 2014 static int 2015 _rl_vi_goto_mark () 2016 { 2017 int ch; 2018 2019 RL_SETSTATE(RL_STATE_MOREINPUT); 2020 ch = rl_read_key (); 2021 RL_UNSETSTATE(RL_STATE_MOREINPUT); 2022 2023 if (ch == '`') 2024 { 2025 rl_point = rl_mark; 2026 return 0; 2027 } 2028 else if (ch < 0 || ch < 'a' || ch > 'z') /* make test against 0 explicit */ 2029 { 2030 rl_ding (); 2031 return -1; 2032 } 2033 2034 ch -= 'a'; 2035 if (vi_mark_chars[ch] == -1) 2036 { 2037 rl_ding (); 2038 return -1; 2039 } 2040 rl_point = vi_mark_chars[ch]; 2041 return 0; 2042 } 2043 2044 #if defined (READLINE_CALLBACKS) 2045 static int 2046 _rl_vi_callback_goto_mark (data) 2047 _rl_callback_generic_arg *data; 2048 { 2049 _rl_callback_func = 0; 2050 _rl_want_redisplay = 1; 2051 2052 return (_rl_vi_goto_mark ()); 2053 } 2054 #endif 2055 2056 int 2057 rl_vi_goto_mark (count, key) 2058 int count, key; 2059 { 2060 #if defined (READLINE_CALLBACKS) 2061 if (RL_ISSTATE (RL_STATE_CALLBACK)) 2062 { 2063 _rl_callback_data = 0; 2064 _rl_callback_func = _rl_vi_callback_goto_mark; 2065 return (0); 2066 } 2067 #endif 2068 2069 return (_rl_vi_goto_mark ()); 2070 } 2071 #endif /* VI_MODE */ 2072