1 /* text.c -- text handling commands for readline. */ 2 3 /* Copyright (C) 1987-2002 Free Software Foundation, Inc. 4 5 This file is part of the GNU Readline Library, a library for 6 reading lines of text with interactive input and history editing. 7 8 The GNU Readline Library is free software; you can redistribute it 9 and/or modify it under the terms of the GNU General Public License 10 as published by the Free Software Foundation; either version 2, or 11 (at your option) any later version. 12 13 The GNU Readline Library is distributed in the hope that it will be 14 useful, but WITHOUT ANY WARRANTY; without even the implied warranty 15 of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 The GNU General Public License is often shipped with GNU software, and 19 is generally kept in a file called COPYING or LICENSE. If you do not 20 have a copy of the license, write to the Free Software Foundation, 21 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ 22 #define READLINE_LIBRARY 23 24 #if defined (HAVE_CONFIG_H) 25 # include <config.h> 26 #endif 27 28 #if defined (HAVE_UNISTD_H) 29 # include <unistd.h> 30 #endif /* HAVE_UNISTD_H */ 31 32 #if defined (HAVE_STDLIB_H) 33 # include <stdlib.h> 34 #else 35 # include "ansi_stdlib.h" 36 #endif /* HAVE_STDLIB_H */ 37 38 #if defined (HAVE_LOCALE_H) 39 # include <locale.h> 40 #endif 41 42 #include <stdio.h> 43 44 /* System-specific feature definitions and include files. */ 45 #include "rldefs.h" 46 #include "rlmbutil.h" 47 48 #if defined (__EMX__) 49 # define INCL_DOSPROCESS 50 # include <os2.h> 51 #endif /* __EMX__ */ 52 53 /* Some standard library routines. */ 54 #include "readline.h" 55 #include "history.h" 56 57 #include "rlprivate.h" 58 #include "rlshell.h" 59 #include "xmalloc.h" 60 61 /* Forward declarations. */ 62 static int rl_change_case PARAMS((int, int)); 63 static int _rl_char_search PARAMS((int, int, int)); 64 65 /* **************************************************************** */ 66 /* */ 67 /* Insert and Delete */ 68 /* */ 69 /* **************************************************************** */ 70 71 /* Insert a string of text into the line at point. This is the only 72 way that you should do insertion. _rl_insert_char () calls this 73 function. Returns the number of characters inserted. */ 74 int 75 rl_insert_text (string) 76 const char *string; 77 { 78 register int i, l; 79 80 l = (string && *string) ? strlen (string) : 0; 81 if (l == 0) 82 return 0; 83 84 if (rl_end + l >= rl_line_buffer_len) 85 rl_extend_line_buffer (rl_end + l); 86 87 for (i = rl_end; i >= rl_point; i--) 88 rl_line_buffer[i + l] = rl_line_buffer[i]; 89 strncpy (rl_line_buffer + rl_point, string, l); 90 91 /* Remember how to undo this if we aren't undoing something. */ 92 if (_rl_doing_an_undo == 0) 93 { 94 /* If possible and desirable, concatenate the undos. */ 95 if ((l == 1) && 96 rl_undo_list && 97 (rl_undo_list->what == UNDO_INSERT) && 98 (rl_undo_list->end == rl_point) && 99 (rl_undo_list->end - rl_undo_list->start < 20)) 100 rl_undo_list->end++; 101 else 102 rl_add_undo (UNDO_INSERT, rl_point, rl_point + l, (char *)NULL); 103 } 104 rl_point += l; 105 rl_end += l; 106 rl_line_buffer[rl_end] = '\0'; 107 return l; 108 } 109 110 /* Delete the string between FROM and TO. FROM is inclusive, TO is not. 111 Returns the number of characters deleted. */ 112 int 113 rl_delete_text (from, to) 114 int from, to; 115 { 116 register char *text; 117 register int diff, i; 118 119 /* Fix it if the caller is confused. */ 120 if (from > to) 121 SWAP (from, to); 122 123 /* fix boundaries */ 124 if (to > rl_end) 125 { 126 to = rl_end; 127 if (from > to) 128 from = to; 129 } 130 if (from < 0) 131 from = 0; 132 133 text = rl_copy_text (from, to); 134 135 /* Some versions of strncpy() can't handle overlapping arguments. */ 136 diff = to - from; 137 for (i = from; i < rl_end - diff; i++) 138 rl_line_buffer[i] = rl_line_buffer[i + diff]; 139 140 /* Remember how to undo this delete. */ 141 if (_rl_doing_an_undo == 0) 142 rl_add_undo (UNDO_DELETE, from, to, text); 143 else 144 free (text); 145 146 rl_end -= diff; 147 rl_line_buffer[rl_end] = '\0'; 148 return (diff); 149 } 150 151 /* Fix up point so that it is within the line boundaries after killing 152 text. If FIX_MARK_TOO is non-zero, the mark is forced within line 153 boundaries also. */ 154 155 #define _RL_FIX_POINT(x) \ 156 do { \ 157 if (x > rl_end) \ 158 x = rl_end; \ 159 else if (x < 0) \ 160 x = 0; \ 161 } while (0) 162 163 void 164 _rl_fix_point (fix_mark_too) 165 int fix_mark_too; 166 { 167 _RL_FIX_POINT (rl_point); 168 if (fix_mark_too) 169 _RL_FIX_POINT (rl_mark); 170 } 171 #undef _RL_FIX_POINT 172 173 int 174 _rl_replace_text (text, start, end) 175 const char *text; 176 int start, end; 177 { 178 int n; 179 180 rl_begin_undo_group (); 181 rl_delete_text (start, end + 1); 182 rl_point = start; 183 n = rl_insert_text (text); 184 rl_end_undo_group (); 185 186 return n; 187 } 188 189 /* Replace the current line buffer contents with TEXT. If CLEAR_UNDO is 190 non-zero, we free the current undo list. */ 191 void 192 rl_replace_line (text, clear_undo) 193 const char *text; 194 int clear_undo; 195 { 196 int len; 197 198 len = strlen (text); 199 if (len >= rl_line_buffer_len) 200 rl_extend_line_buffer (len); 201 strlcpy (rl_line_buffer, text, rl_line_buffer_len); 202 rl_end = len; 203 204 if (clear_undo) 205 rl_free_undo_list (); 206 207 _rl_fix_point (1); 208 } 209 210 /* **************************************************************** */ 211 /* */ 212 /* Readline character functions */ 213 /* */ 214 /* **************************************************************** */ 215 216 /* This is not a gap editor, just a stupid line input routine. No hair 217 is involved in writing any of the functions, and none should be. */ 218 219 /* Note that: 220 221 rl_end is the place in the string that we would place '\0'; 222 i.e., it is always safe to place '\0' there. 223 224 rl_point is the place in the string where the cursor is. Sometimes 225 this is the same as rl_end. 226 227 Any command that is called interactively receives two arguments. 228 The first is a count: the numeric arg pased to this command. 229 The second is the key which invoked this command. 230 */ 231 232 /* **************************************************************** */ 233 /* */ 234 /* Movement Commands */ 235 /* */ 236 /* **************************************************************** */ 237 238 /* Note that if you `optimize' the display for these functions, you cannot 239 use said functions in other functions which do not do optimizing display. 240 I.e., you will have to update the data base for rl_redisplay, and you 241 might as well let rl_redisplay do that job. */ 242 243 /* Move forward COUNT bytes. */ 244 int 245 rl_forward_byte (count, key) 246 int count, key; 247 { 248 if (count < 0) 249 return (rl_backward_byte (-count, key)); 250 251 if (count > 0) 252 { 253 int end = rl_point + count; 254 #if defined (VI_MODE) 255 int lend = rl_end > 0 ? rl_end - (rl_editing_mode == vi_mode) : rl_end; 256 #else 257 int lend = rl_end; 258 #endif 259 260 if (end > lend) 261 { 262 rl_point = lend; 263 rl_ding (); 264 } 265 else 266 rl_point = end; 267 } 268 269 if (rl_end < 0) 270 rl_end = 0; 271 272 return 0; 273 } 274 275 #if defined (HANDLE_MULTIBYTE) 276 /* Move forward COUNT characters. */ 277 int 278 rl_forward_char (count, key) 279 int count, key; 280 { 281 int point; 282 283 if (MB_CUR_MAX == 1 || rl_byte_oriented) 284 return (rl_forward_byte (count, key)); 285 286 if (count < 0) 287 return (rl_backward_char (-count, key)); 288 289 if (count > 0) 290 { 291 point = _rl_find_next_mbchar (rl_line_buffer, rl_point, count, MB_FIND_NONZERO); 292 293 #if defined (VI_MODE) 294 if (rl_end <= point && rl_editing_mode == vi_mode) 295 point = _rl_find_prev_mbchar (rl_line_buffer, rl_end, MB_FIND_NONZERO); 296 #endif 297 298 if (rl_point == point) 299 rl_ding (); 300 301 rl_point = point; 302 303 if (rl_end < 0) 304 rl_end = 0; 305 } 306 307 return 0; 308 } 309 #else /* !HANDLE_MULTIBYTE */ 310 int 311 rl_forward_char (count, key) 312 int count, key; 313 { 314 return (rl_forward_byte (count, key)); 315 } 316 #endif /* !HANDLE_MULTIBYTE */ 317 318 /* Backwards compatibility. */ 319 int 320 rl_forward (count, key) 321 int count, key; 322 { 323 return (rl_forward_char (count, key)); 324 } 325 326 /* Move backward COUNT bytes. */ 327 int 328 rl_backward_byte (count, key) 329 int count, key; 330 { 331 if (count < 0) 332 return (rl_forward_byte (-count, key)); 333 334 if (count > 0) 335 { 336 if (rl_point < count) 337 { 338 rl_point = 0; 339 rl_ding (); 340 } 341 else 342 rl_point -= count; 343 } 344 345 if (rl_point < 0) 346 rl_point = 0; 347 348 return 0; 349 } 350 351 #if defined (HANDLE_MULTIBYTE) 352 /* Move backward COUNT characters. */ 353 int 354 rl_backward_char (count, key) 355 int count, key; 356 { 357 int point; 358 359 if (MB_CUR_MAX == 1 || rl_byte_oriented) 360 return (rl_backward_byte (count, key)); 361 362 if (count < 0) 363 return (rl_forward_char (-count, key)); 364 365 if (count > 0) 366 { 367 point = rl_point; 368 369 while (count > 0 && point > 0) 370 { 371 point = _rl_find_prev_mbchar (rl_line_buffer, point, MB_FIND_NONZERO); 372 count--; 373 } 374 if (count > 0) 375 { 376 rl_point = 0; 377 rl_ding (); 378 } 379 else 380 rl_point = point; 381 } 382 383 return 0; 384 } 385 #else 386 int 387 rl_backward_char (count, key) 388 int count, key; 389 { 390 return (rl_backward_byte (count, key)); 391 } 392 #endif 393 394 /* Backwards compatibility. */ 395 int 396 rl_backward (count, key) 397 int count, key; 398 { 399 return (rl_backward_char (count, key)); 400 } 401 402 /* Move to the beginning of the line. */ 403 int 404 rl_beg_of_line (count, key) 405 int count, key; 406 { 407 rl_point = 0; 408 return 0; 409 } 410 411 /* Move to the end of the line. */ 412 int 413 rl_end_of_line (count, key) 414 int count, key; 415 { 416 rl_point = rl_end; 417 return 0; 418 } 419 420 /* XXX - these might need changes for multibyte characters */ 421 /* Move forward a word. We do what Emacs does. */ 422 int 423 rl_forward_word (count, key) 424 int count, key; 425 { 426 int c; 427 428 if (count < 0) 429 return (rl_backward_word (-count, key)); 430 431 while (count) 432 { 433 if (rl_point == rl_end) 434 return 0; 435 436 /* If we are not in a word, move forward until we are in one. 437 Then, move forward until we hit a non-alphabetic character. */ 438 c = rl_line_buffer[rl_point]; 439 if (rl_alphabetic (c) == 0) 440 { 441 while (++rl_point < rl_end) 442 { 443 c = rl_line_buffer[rl_point]; 444 if (rl_alphabetic (c)) 445 break; 446 } 447 } 448 449 if (rl_point == rl_end) 450 return 0; 451 452 while (++rl_point < rl_end) 453 { 454 c = rl_line_buffer[rl_point]; 455 if (rl_alphabetic (c) == 0) 456 break; 457 } 458 --count; 459 } 460 461 return 0; 462 } 463 464 /* Move backward a word. We do what Emacs does. */ 465 int 466 rl_backward_word (count, key) 467 int count, key; 468 { 469 int c; 470 471 if (count < 0) 472 return (rl_forward_word (-count, key)); 473 474 while (count) 475 { 476 if (!rl_point) 477 return 0; 478 479 /* Like rl_forward_word (), except that we look at the characters 480 just before point. */ 481 482 c = rl_line_buffer[rl_point - 1]; 483 if (rl_alphabetic (c) == 0) 484 { 485 while (--rl_point) 486 { 487 c = rl_line_buffer[rl_point - 1]; 488 if (rl_alphabetic (c)) 489 break; 490 } 491 } 492 493 while (rl_point) 494 { 495 c = rl_line_buffer[rl_point - 1]; 496 if (rl_alphabetic (c) == 0) 497 break; 498 else 499 --rl_point; 500 } 501 502 --count; 503 } 504 505 return 0; 506 } 507 508 /* Clear the current line. Numeric argument to C-l does this. */ 509 int 510 rl_refresh_line (ignore1, ignore2) 511 int ignore1, ignore2; 512 { 513 int curr_line; 514 515 curr_line = _rl_current_display_line (); 516 517 _rl_move_vert (curr_line); 518 _rl_move_cursor_relative (0, rl_line_buffer); /* XXX is this right */ 519 520 _rl_clear_to_eol (0); /* arg of 0 means to not use spaces */ 521 522 rl_forced_update_display (); 523 rl_display_fixed = 1; 524 525 return 0; 526 } 527 528 /* C-l typed to a line without quoting clears the screen, and then reprints 529 the prompt and the current input line. Given a numeric arg, redraw only 530 the current line. */ 531 int 532 rl_clear_screen (count, key) 533 int count, key; 534 { 535 if (rl_explicit_arg) 536 { 537 rl_refresh_line (count, key); 538 return 0; 539 } 540 541 _rl_clear_screen (); /* calls termcap function to clear screen */ 542 rl_forced_update_display (); 543 rl_display_fixed = 1; 544 545 return 0; 546 } 547 548 int 549 rl_arrow_keys (count, c) 550 int count, c; 551 { 552 int ch; 553 554 RL_SETSTATE(RL_STATE_MOREINPUT); 555 ch = rl_read_key (); 556 RL_UNSETSTATE(RL_STATE_MOREINPUT); 557 558 switch (_rl_to_upper (ch)) 559 { 560 case 'A': 561 rl_get_previous_history (count, ch); 562 break; 563 564 case 'B': 565 rl_get_next_history (count, ch); 566 break; 567 568 case 'C': 569 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 570 rl_forward_char (count, ch); 571 else 572 rl_forward_byte (count, ch); 573 break; 574 575 case 'D': 576 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 577 rl_backward_char (count, ch); 578 else 579 rl_backward_byte (count, ch); 580 break; 581 582 default: 583 rl_ding (); 584 } 585 586 return 0; 587 } 588 589 /* **************************************************************** */ 590 /* */ 591 /* Text commands */ 592 /* */ 593 /* **************************************************************** */ 594 595 #ifdef HANDLE_MULTIBYTE 596 static char pending_bytes[MB_LEN_MAX]; 597 static int pending_bytes_length = 0; 598 static mbstate_t ps = {0}; 599 #endif 600 601 /* Insert the character C at the current location, moving point forward. 602 If C introduces a multibyte sequence, we read the whole sequence and 603 then insert the multibyte char into the line buffer. */ 604 int 605 _rl_insert_char (count, c) 606 int count, c; 607 { 608 register int i; 609 char *string; 610 #ifdef HANDLE_MULTIBYTE 611 int string_size; 612 char incoming[MB_LEN_MAX + 1]; 613 int incoming_length = 0; 614 mbstate_t ps_back; 615 static int stored_count = 0; 616 #endif 617 618 if (count <= 0) 619 return 0; 620 621 #if defined (HANDLE_MULTIBYTE) 622 if (MB_CUR_MAX == 1 || rl_byte_oriented) 623 { 624 incoming[0] = c; 625 incoming[1] = '\0'; 626 incoming_length = 1; 627 } 628 else 629 { 630 wchar_t wc; 631 size_t ret; 632 633 if (stored_count <= 0) 634 stored_count = count; 635 else 636 count = stored_count; 637 638 ps_back = ps; 639 pending_bytes[pending_bytes_length++] = c; 640 ret = mbrtowc (&wc, pending_bytes, pending_bytes_length, &ps); 641 642 if (ret == (size_t)-2) 643 { 644 /* Bytes too short to compose character, try to wait for next byte. 645 Restore the state of the byte sequence, because in this case the 646 effect of mbstate is undefined. */ 647 ps = ps_back; 648 return 1; 649 } 650 else if (ret == (size_t)-1) 651 { 652 /* Invalid byte sequence for the current locale. Treat first byte 653 as a single character. */ 654 incoming[0] = pending_bytes[0]; 655 incoming[1] = '\0'; 656 incoming_length = 1; 657 pending_bytes_length--; 658 memmove (pending_bytes, pending_bytes + 1, pending_bytes_length); 659 /* Clear the state of the byte sequence, because in this case the 660 effect of mbstate is undefined. */ 661 memset (&ps, 0, sizeof (mbstate_t)); 662 } 663 else if (ret == (size_t)0) 664 { 665 incoming[0] = '\0'; 666 incoming_length = 0; 667 pending_bytes_length--; 668 /* Clear the state of the byte sequence, because in this case the 669 effect of mbstate is undefined. */ 670 memset (&ps, 0, sizeof (mbstate_t)); 671 } 672 else 673 { 674 /* We successfully read a single multibyte character. */ 675 memcpy (incoming, pending_bytes, pending_bytes_length); 676 incoming[pending_bytes_length] = '\0'; 677 incoming_length = pending_bytes_length; 678 pending_bytes_length = 0; 679 } 680 } 681 #endif /* HANDLE_MULTIBYTE */ 682 683 /* If we can optimize, then do it. But don't let people crash 684 readline because of extra large arguments. */ 685 if (count > 1 && count <= 1024) 686 { 687 #if defined (HANDLE_MULTIBYTE) 688 string_size = count * incoming_length; 689 string = (char *)xmalloc (1 + string_size); 690 691 i = 0; 692 while (i < string_size) 693 { 694 strncpy (string + i, incoming, incoming_length); 695 i += incoming_length; 696 } 697 incoming_length = 0; 698 stored_count = 0; 699 #else /* !HANDLE_MULTIBYTE */ 700 string = (char *)xmalloc (1 + count); 701 702 for (i = 0; i < count; i++) 703 string[i] = c; 704 #endif /* !HANDLE_MULTIBYTE */ 705 706 string[i] = '\0'; 707 rl_insert_text (string); 708 free (string); 709 710 return 0; 711 } 712 713 if (count > 1024) 714 { 715 int decreaser; 716 #if defined (HANDLE_MULTIBYTE) 717 string_size = incoming_length * 1024; 718 string = (char *)xmalloc (1 + string_size); 719 720 i = 0; 721 while (i < string_size) 722 { 723 strncpy (string + i, incoming, incoming_length); 724 i += incoming_length; 725 } 726 727 while (count) 728 { 729 decreaser = (count > 1024) ? 1024 : count; 730 string[decreaser*incoming_length] = '\0'; 731 rl_insert_text (string); 732 count -= decreaser; 733 } 734 735 free (string); 736 incoming_length = 0; 737 stored_count = 0; 738 #else /* !HANDLE_MULTIBYTE */ 739 char str[1024+1]; 740 741 for (i = 0; i < 1024; i++) 742 str[i] = c; 743 744 while (count) 745 { 746 decreaser = (count > 1024 ? 1024 : count); 747 str[decreaser] = '\0'; 748 rl_insert_text (str); 749 count -= decreaser; 750 } 751 #endif /* !HANDLE_MULTIBYTE */ 752 753 return 0; 754 } 755 756 #if defined (HANDLE_MULTIBYTE) 757 if (MB_CUR_MAX == 1 || rl_byte_oriented) 758 { 759 #endif 760 /* We are inserting a single character. 761 If there is pending input, then make a string of all of the 762 pending characters that are bound to rl_insert, and insert 763 them all. */ 764 if (_rl_any_typein ()) 765 _rl_insert_typein (c); 766 else 767 { 768 /* Inserting a single character. */ 769 char str[2]; 770 771 str[1] = '\0'; 772 str[0] = c; 773 rl_insert_text (str); 774 } 775 #if defined (HANDLE_MULTIBYTE) 776 } 777 else 778 { 779 rl_insert_text (incoming); 780 stored_count = 0; 781 } 782 #endif 783 784 return 0; 785 } 786 787 /* Overwrite the character at point (or next COUNT characters) with C. 788 If C introduces a multibyte character sequence, read the entire sequence 789 before starting the overwrite loop. */ 790 int 791 _rl_overwrite_char (count, c) 792 int count, c; 793 { 794 int i; 795 #if defined (HANDLE_MULTIBYTE) 796 char mbkey[MB_LEN_MAX]; 797 int k; 798 799 /* Read an entire multibyte character sequence to insert COUNT times. */ 800 if (count > 0 && MB_CUR_MAX > 1 && rl_byte_oriented == 0) 801 k = _rl_read_mbstring (c, mbkey, MB_LEN_MAX); 802 #endif 803 804 for (i = 0; i < count; i++) 805 { 806 rl_begin_undo_group (); 807 808 if (rl_point < rl_end) 809 rl_delete (1, c); 810 811 #if defined (HANDLE_MULTIBYTE) 812 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 813 rl_insert_text (mbkey); 814 else 815 #endif 816 _rl_insert_char (1, c); 817 818 rl_end_undo_group (); 819 } 820 821 return 0; 822 } 823 824 int 825 rl_insert (count, c) 826 int count, c; 827 { 828 return (rl_insert_mode == RL_IM_INSERT ? _rl_insert_char (count, c) 829 : _rl_overwrite_char (count, c)); 830 } 831 832 /* Insert the next typed character verbatim. */ 833 int 834 rl_quoted_insert (count, key) 835 int count, key; 836 { 837 int c; 838 839 #if defined (HANDLE_SIGNALS) 840 _rl_disable_tty_signals (); 841 #endif 842 843 RL_SETSTATE(RL_STATE_MOREINPUT); 844 c = rl_read_key (); 845 RL_UNSETSTATE(RL_STATE_MOREINPUT); 846 847 #if defined (HANDLE_SIGNALS) 848 _rl_restore_tty_signals (); 849 #endif 850 851 return (_rl_insert_char (count, c)); 852 } 853 854 /* Insert a tab character. */ 855 int 856 rl_tab_insert (count, key) 857 int count, key; 858 { 859 return (_rl_insert_char (count, '\t')); 860 } 861 862 /* What to do when a NEWLINE is pressed. We accept the whole line. 863 KEY is the key that invoked this command. I guess it could have 864 meaning in the future. */ 865 int 866 rl_newline (count, key) 867 int count, key; 868 { 869 rl_done = 1; 870 871 if (_rl_history_preserve_point) 872 _rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point; 873 874 RL_SETSTATE(RL_STATE_DONE); 875 876 #if defined (VI_MODE) 877 if (rl_editing_mode == vi_mode) 878 { 879 _rl_vi_done_inserting (); 880 _rl_vi_reset_last (); 881 } 882 #endif /* VI_MODE */ 883 884 /* If we've been asked to erase empty lines, suppress the final update, 885 since _rl_update_final calls rl_crlf(). */ 886 if (rl_erase_empty_line && rl_point == 0 && rl_end == 0) 887 return 0; 888 889 if (readline_echoing_p) 890 _rl_update_final (); 891 return 0; 892 } 893 894 /* What to do for some uppercase characters, like meta characters, 895 and some characters appearing in emacs_ctlx_keymap. This function 896 is just a stub, you bind keys to it and the code in _rl_dispatch () 897 is special cased. */ 898 int 899 rl_do_lowercase_version (ignore1, ignore2) 900 int ignore1, ignore2; 901 { 902 return 0; 903 } 904 905 /* This is different from what vi does, so the code's not shared. Emacs 906 rubout in overwrite mode has one oddity: it replaces a control 907 character that's displayed as two characters (^X) with two spaces. */ 908 int 909 _rl_overwrite_rubout (count, key) 910 int count, key; 911 { 912 int opoint; 913 int i, l; 914 915 if (rl_point == 0) 916 { 917 rl_ding (); 918 return 1; 919 } 920 921 opoint = rl_point; 922 923 /* L == number of spaces to insert */ 924 for (i = l = 0; i < count; i++) 925 { 926 rl_backward_char (1, key); 927 l += rl_character_len (rl_line_buffer[rl_point], rl_point); /* not exactly right */ 928 } 929 930 rl_begin_undo_group (); 931 932 if (count > 1 || rl_explicit_arg) 933 rl_kill_text (opoint, rl_point); 934 else 935 rl_delete_text (opoint, rl_point); 936 937 /* Emacs puts point at the beginning of the sequence of spaces. */ 938 opoint = rl_point; 939 _rl_insert_char (l, ' '); 940 rl_point = opoint; 941 942 rl_end_undo_group (); 943 944 return 0; 945 } 946 947 /* Rubout the character behind point. */ 948 int 949 rl_rubout (count, key) 950 int count, key; 951 { 952 if (count < 0) 953 return (rl_delete (-count, key)); 954 955 if (!rl_point) 956 { 957 rl_ding (); 958 return -1; 959 } 960 961 if (rl_insert_mode == RL_IM_OVERWRITE) 962 return (_rl_overwrite_rubout (count, key)); 963 964 return (_rl_rubout_char (count, key)); 965 } 966 967 int 968 _rl_rubout_char (count, key) 969 int count, key; 970 { 971 int orig_point; 972 unsigned char c; 973 974 /* Duplicated code because this is called from other parts of the library. */ 975 if (count < 0) 976 return (rl_delete (-count, key)); 977 978 if (rl_point == 0) 979 { 980 rl_ding (); 981 return -1; 982 } 983 984 if (count > 1 || rl_explicit_arg) 985 { 986 orig_point = rl_point; 987 #if defined (HANDLE_MULTIBYTE) 988 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 989 rl_backward_char (count, key); 990 else 991 #endif 992 rl_backward_byte (count, key); 993 rl_kill_text (orig_point, rl_point); 994 } 995 else 996 { 997 #if defined (HANDLE_MULTIBYTE) 998 if (MB_CUR_MAX == 1 || rl_byte_oriented) 999 { 1000 #endif 1001 c = rl_line_buffer[--rl_point]; 1002 rl_delete_text (rl_point, rl_point + 1); 1003 #if defined (HANDLE_MULTIBYTE) 1004 } 1005 else 1006 { 1007 int orig_point; 1008 1009 orig_point = rl_point; 1010 rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO); 1011 c = rl_line_buffer[rl_point]; 1012 rl_delete_text (rl_point, orig_point); 1013 } 1014 #endif /* HANDLE_MULTIBYTE */ 1015 1016 /* I don't think that the hack for end of line is needed for 1017 multibyte chars. */ 1018 #if defined (HANDLE_MULTIBYTE) 1019 if (MB_CUR_MAX == 1 || rl_byte_oriented) 1020 #endif 1021 if (rl_point == rl_end && ISPRINT (c) && _rl_last_c_pos) 1022 { 1023 int l; 1024 l = rl_character_len (c, rl_point); 1025 _rl_erase_at_end_of_line (l); 1026 } 1027 } 1028 1029 return 0; 1030 } 1031 1032 /* Delete the character under the cursor. Given a numeric argument, 1033 kill that many characters instead. */ 1034 int 1035 rl_delete (count, key) 1036 int count, key; 1037 { 1038 int r; 1039 1040 if (count < 0) 1041 return (_rl_rubout_char (-count, key)); 1042 1043 if (rl_point == rl_end) 1044 { 1045 rl_ding (); 1046 return -1; 1047 } 1048 1049 if (count > 1 || rl_explicit_arg) 1050 { 1051 int orig_point = rl_point; 1052 #if defined (HANDLE_MULTIBYTE) 1053 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1054 rl_forward_char (count, key); 1055 else 1056 #endif 1057 rl_forward_byte (count, key); 1058 1059 r = rl_kill_text (orig_point, rl_point); 1060 rl_point = orig_point; 1061 return r; 1062 } 1063 else 1064 { 1065 int new_point; 1066 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1067 new_point = _rl_find_next_mbchar (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO); 1068 else 1069 new_point = rl_point + 1; 1070 1071 return (rl_delete_text (rl_point, new_point)); 1072 } 1073 } 1074 1075 /* Delete the character under the cursor, unless the insertion 1076 point is at the end of the line, in which case the character 1077 behind the cursor is deleted. COUNT is obeyed and may be used 1078 to delete forward or backward that many characters. */ 1079 int 1080 rl_rubout_or_delete (count, key) 1081 int count, key; 1082 { 1083 if (rl_end != 0 && rl_point == rl_end) 1084 return (_rl_rubout_char (count, key)); 1085 else 1086 return (rl_delete (count, key)); 1087 } 1088 1089 /* Delete all spaces and tabs around point. */ 1090 int 1091 rl_delete_horizontal_space (count, ignore) 1092 int count, ignore; 1093 { 1094 int start = rl_point; 1095 1096 while (rl_point && whitespace (rl_line_buffer[rl_point - 1])) 1097 rl_point--; 1098 1099 start = rl_point; 1100 1101 while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point])) 1102 rl_point++; 1103 1104 if (start != rl_point) 1105 { 1106 rl_delete_text (start, rl_point); 1107 rl_point = start; 1108 } 1109 return 0; 1110 } 1111 1112 /* Like the tcsh editing function delete-char-or-list. The eof character 1113 is caught before this is invoked, so this really does the same thing as 1114 delete-char-or-list-or-eof, as long as it's bound to the eof character. */ 1115 int 1116 rl_delete_or_show_completions (count, key) 1117 int count, key; 1118 { 1119 if (rl_end != 0 && rl_point == rl_end) 1120 return (rl_possible_completions (count, key)); 1121 else 1122 return (rl_delete (count, key)); 1123 } 1124 1125 #ifndef RL_COMMENT_BEGIN_DEFAULT 1126 #define RL_COMMENT_BEGIN_DEFAULT "#" 1127 #endif 1128 1129 /* Turn the current line into a comment in shell history. 1130 A K*rn shell style function. */ 1131 int 1132 rl_insert_comment (count, key) 1133 int count, key; 1134 { 1135 char *rl_comment_text; 1136 int rl_comment_len; 1137 1138 rl_beg_of_line (1, key); 1139 rl_comment_text = _rl_comment_begin ? _rl_comment_begin : RL_COMMENT_BEGIN_DEFAULT; 1140 1141 if (rl_explicit_arg == 0) 1142 rl_insert_text (rl_comment_text); 1143 else 1144 { 1145 rl_comment_len = strlen (rl_comment_text); 1146 if (STREQN (rl_comment_text, rl_line_buffer, rl_comment_len)) 1147 rl_delete_text (rl_point, rl_point + rl_comment_len); 1148 else 1149 rl_insert_text (rl_comment_text); 1150 } 1151 1152 (*rl_redisplay_function) (); 1153 rl_newline (1, '\n'); 1154 1155 return (0); 1156 } 1157 1158 /* **************************************************************** */ 1159 /* */ 1160 /* Changing Case */ 1161 /* */ 1162 /* **************************************************************** */ 1163 1164 /* The three kinds of things that we know how to do. */ 1165 #define UpCase 1 1166 #define DownCase 2 1167 #define CapCase 3 1168 1169 /* Uppercase the word at point. */ 1170 int 1171 rl_upcase_word (count, key) 1172 int count, key; 1173 { 1174 return (rl_change_case (count, UpCase)); 1175 } 1176 1177 /* Lowercase the word at point. */ 1178 int 1179 rl_downcase_word (count, key) 1180 int count, key; 1181 { 1182 return (rl_change_case (count, DownCase)); 1183 } 1184 1185 /* Upcase the first letter, downcase the rest. */ 1186 int 1187 rl_capitalize_word (count, key) 1188 int count, key; 1189 { 1190 return (rl_change_case (count, CapCase)); 1191 } 1192 1193 /* The meaty function. 1194 Change the case of COUNT words, performing OP on them. 1195 OP is one of UpCase, DownCase, or CapCase. 1196 If a negative argument is given, leave point where it started, 1197 otherwise, leave it where it moves to. */ 1198 static int 1199 rl_change_case (count, op) 1200 int count, op; 1201 { 1202 register int start, end; 1203 int inword, c; 1204 1205 start = rl_point; 1206 rl_forward_word (count, 0); 1207 end = rl_point; 1208 1209 if (count < 0) 1210 SWAP (start, end); 1211 1212 /* We are going to modify some text, so let's prepare to undo it. */ 1213 rl_modifying (start, end); 1214 1215 for (inword = 0; start < end; start++) 1216 { 1217 c = rl_line_buffer[start]; 1218 switch (op) 1219 { 1220 case UpCase: 1221 rl_line_buffer[start] = _rl_to_upper (c); 1222 break; 1223 1224 case DownCase: 1225 rl_line_buffer[start] = _rl_to_lower (c); 1226 break; 1227 1228 case CapCase: 1229 rl_line_buffer[start] = (inword == 0) ? _rl_to_upper (c) : _rl_to_lower (c); 1230 inword = rl_alphabetic (rl_line_buffer[start]); 1231 break; 1232 1233 default: 1234 rl_ding (); 1235 return -1; 1236 } 1237 } 1238 rl_point = end; 1239 return 0; 1240 } 1241 1242 /* **************************************************************** */ 1243 /* */ 1244 /* Transposition */ 1245 /* */ 1246 /* **************************************************************** */ 1247 1248 /* Transpose the words at point. If point is at the end of the line, 1249 transpose the two words before point. */ 1250 int 1251 rl_transpose_words (count, key) 1252 int count, key; 1253 { 1254 char *word1, *word2; 1255 int w1_beg, w1_end, w2_beg, w2_end; 1256 int orig_point = rl_point; 1257 1258 if (!count) 1259 return 0; 1260 1261 /* Find the two words. */ 1262 rl_forward_word (count, key); 1263 w2_end = rl_point; 1264 rl_backward_word (1, key); 1265 w2_beg = rl_point; 1266 rl_backward_word (count, key); 1267 w1_beg = rl_point; 1268 rl_forward_word (1, key); 1269 w1_end = rl_point; 1270 1271 /* Do some check to make sure that there really are two words. */ 1272 if ((w1_beg == w2_beg) || (w2_beg < w1_end)) 1273 { 1274 rl_ding (); 1275 rl_point = orig_point; 1276 return -1; 1277 } 1278 1279 /* Get the text of the words. */ 1280 word1 = rl_copy_text (w1_beg, w1_end); 1281 word2 = rl_copy_text (w2_beg, w2_end); 1282 1283 /* We are about to do many insertions and deletions. Remember them 1284 as one operation. */ 1285 rl_begin_undo_group (); 1286 1287 /* Do the stuff at word2 first, so that we don't have to worry 1288 about word1 moving. */ 1289 rl_point = w2_beg; 1290 rl_delete_text (w2_beg, w2_end); 1291 rl_insert_text (word1); 1292 1293 rl_point = w1_beg; 1294 rl_delete_text (w1_beg, w1_end); 1295 rl_insert_text (word2); 1296 1297 /* This is exactly correct since the text before this point has not 1298 changed in length. */ 1299 rl_point = w2_end; 1300 1301 /* I think that does it. */ 1302 rl_end_undo_group (); 1303 free (word1); 1304 free (word2); 1305 1306 return 0; 1307 } 1308 1309 /* Transpose the characters at point. If point is at the end of the line, 1310 then transpose the characters before point. */ 1311 int 1312 rl_transpose_chars (count, key) 1313 int count, key; 1314 { 1315 #if defined (HANDLE_MULTIBYTE) 1316 char *dummy; 1317 int i, prev_point; 1318 #else 1319 char dummy[2]; 1320 #endif 1321 int char_length; 1322 1323 if (count == 0) 1324 return 0; 1325 1326 if (!rl_point || rl_end < 2) 1327 { 1328 rl_ding (); 1329 return -1; 1330 } 1331 1332 rl_begin_undo_group (); 1333 1334 if (rl_point == rl_end) 1335 { 1336 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1337 rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO); 1338 else 1339 --rl_point; 1340 count = 1; 1341 } 1342 1343 #if defined (HANDLE_MULTIBYTE) 1344 prev_point = rl_point; 1345 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) 1346 rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO); 1347 else 1348 #endif 1349 rl_point--; 1350 1351 #if defined (HANDLE_MULTIBYTE) 1352 char_length = prev_point - rl_point; 1353 dummy = (char *)xmalloc (char_length + 1); 1354 for (i = 0; i < char_length; i++) 1355 dummy[i] = rl_line_buffer[rl_point + i]; 1356 dummy[i] = '\0'; 1357 #else 1358 dummy[0] = rl_line_buffer[rl_point]; 1359 dummy[char_length = 1] = '\0'; 1360 #endif 1361 1362 rl_delete_text (rl_point, rl_point + char_length); 1363 1364 rl_point = _rl_find_next_mbchar (rl_line_buffer, rl_point, count, MB_FIND_NONZERO); 1365 1366 _rl_fix_point (0); 1367 rl_insert_text (dummy); 1368 rl_end_undo_group (); 1369 1370 #if defined (HANDLE_MULTIBYTE) 1371 free (dummy); 1372 #endif 1373 1374 return 0; 1375 } 1376 1377 /* **************************************************************** */ 1378 /* */ 1379 /* Character Searching */ 1380 /* */ 1381 /* **************************************************************** */ 1382 1383 int 1384 #if defined (HANDLE_MULTIBYTE) 1385 _rl_char_search_internal (count, dir, smbchar, len) 1386 int count, dir; 1387 char *smbchar; 1388 int len; 1389 #else 1390 _rl_char_search_internal (count, dir, schar) 1391 int count, dir, schar; 1392 #endif 1393 { 1394 int pos, inc; 1395 #if defined (HANDLE_MULTIBYTE) 1396 int prepos; 1397 #endif 1398 1399 pos = rl_point; 1400 inc = (dir < 0) ? -1 : 1; 1401 while (count) 1402 { 1403 if ((dir < 0 && pos <= 0) || (dir > 0 && pos >= rl_end)) 1404 { 1405 rl_ding (); 1406 return -1; 1407 } 1408 1409 #if defined (HANDLE_MULTIBYTE) 1410 pos = (inc > 0) ? _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY) 1411 : _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY); 1412 #else 1413 pos += inc; 1414 #endif 1415 do 1416 { 1417 #if defined (HANDLE_MULTIBYTE) 1418 if (_rl_is_mbchar_matched (rl_line_buffer, pos, rl_end, smbchar, len)) 1419 #else 1420 if (rl_line_buffer[pos] == schar) 1421 #endif 1422 { 1423 count--; 1424 if (dir < 0) 1425 rl_point = (dir == BTO) ? _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY) 1426 : pos; 1427 else 1428 rl_point = (dir == FTO) ? _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY) 1429 : pos; 1430 break; 1431 } 1432 #if defined (HANDLE_MULTIBYTE) 1433 prepos = pos; 1434 #endif 1435 } 1436 #if defined (HANDLE_MULTIBYTE) 1437 while ((dir < 0) ? (pos = _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY)) != prepos 1438 : (pos = _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY)) != prepos); 1439 #else 1440 while ((dir < 0) ? pos-- : ++pos < rl_end); 1441 #endif 1442 } 1443 return (0); 1444 } 1445 1446 /* Search COUNT times for a character read from the current input stream. 1447 FDIR is the direction to search if COUNT is non-negative; otherwise 1448 the search goes in BDIR. So much is dependent on HANDLE_MULTIBYTE 1449 that there are two separate versions of this function. */ 1450 #if defined (HANDLE_MULTIBYTE) 1451 static int 1452 _rl_char_search (count, fdir, bdir) 1453 int count, fdir, bdir; 1454 { 1455 char mbchar[MB_LEN_MAX]; 1456 int mb_len; 1457 1458 mb_len = _rl_read_mbchar (mbchar, MB_LEN_MAX); 1459 1460 if (count < 0) 1461 return (_rl_char_search_internal (-count, bdir, mbchar, mb_len)); 1462 else 1463 return (_rl_char_search_internal (count, fdir, mbchar, mb_len)); 1464 } 1465 #else /* !HANDLE_MULTIBYTE */ 1466 static int 1467 _rl_char_search (count, fdir, bdir) 1468 int count, fdir, bdir; 1469 { 1470 int c; 1471 1472 RL_SETSTATE(RL_STATE_MOREINPUT); 1473 c = rl_read_key (); 1474 RL_UNSETSTATE(RL_STATE_MOREINPUT); 1475 1476 if (count < 0) 1477 return (_rl_char_search_internal (-count, bdir, c)); 1478 else 1479 return (_rl_char_search_internal (count, fdir, c)); 1480 } 1481 #endif /* !HANDLE_MULTIBYTE */ 1482 1483 int 1484 rl_char_search (count, key) 1485 int count, key; 1486 { 1487 return (_rl_char_search (count, FFIND, BFIND)); 1488 } 1489 1490 int 1491 rl_backward_char_search (count, key) 1492 int count, key; 1493 { 1494 return (_rl_char_search (count, BFIND, FFIND)); 1495 } 1496 1497 /* **************************************************************** */ 1498 /* */ 1499 /* The Mark and the Region. */ 1500 /* */ 1501 /* **************************************************************** */ 1502 1503 /* Set the mark at POSITION. */ 1504 int 1505 _rl_set_mark_at_pos (position) 1506 int position; 1507 { 1508 if (position > rl_end) 1509 return -1; 1510 1511 rl_mark = position; 1512 return 0; 1513 } 1514 1515 /* A bindable command to set the mark. */ 1516 int 1517 rl_set_mark (count, key) 1518 int count, key; 1519 { 1520 return (_rl_set_mark_at_pos (rl_explicit_arg ? count : rl_point)); 1521 } 1522 1523 /* Exchange the position of mark and point. */ 1524 int 1525 rl_exchange_point_and_mark (count, key) 1526 int count, key; 1527 { 1528 if (rl_mark > rl_end) 1529 rl_mark = -1; 1530 1531 if (rl_mark == -1) 1532 { 1533 rl_ding (); 1534 return -1; 1535 } 1536 else 1537 SWAP (rl_point, rl_mark); 1538 1539 return 0; 1540 } 1541