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