1 /* text.c -- text handling commands for readline. */
3 /* Copyright (C) 1987-2004 Free Software Foundation, Inc.
5 This file is part of the GNU Readline Library, a library for
6 reading lines of text with interactive input and history editing.
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.
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.
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
24 #if defined (HAVE_CONFIG_H)
28 #if defined (HAVE_UNISTD_H)
30 #endif /* HAVE_UNISTD_H */
32 #if defined (HAVE_STDLIB_H)
35 # include "ansi_stdlib.h"
36 #endif /* HAVE_STDLIB_H */
38 #if defined (HAVE_LOCALE_H)
44 /* System-specific feature definitions and include files. */
49 # define INCL_DOSPROCESS
53 /* Some standard library routines. */
57 #include "rlprivate.h"
61 /* Forward declarations. */
62 static int rl_change_case
PARAMS((int, int));
63 static int _rl_char_search
PARAMS((int, int, int));
65 /* **************************************************************** */
67 /* Insert and Delete */
69 /* **************************************************************** */
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. */
75 rl_insert_text (string
)
80 l
= (string
&& *string
) ? strlen (string
) : 0;
84 if (rl_end
+ l
>= rl_line_buffer_len
)
85 rl_extend_line_buffer (rl_end
+ l
);
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
);
91 /* Remember how to undo this if we aren't undoing something. */
92 if (_rl_doing_an_undo
== 0)
94 /* If possible and desirable, concatenate the undos. */
97 (rl_undo_list
->what
== UNDO_INSERT
) &&
98 (rl_undo_list
->end
== rl_point
) &&
99 (rl_undo_list
->end
- rl_undo_list
->start
< 20))
102 rl_add_undo (UNDO_INSERT
, rl_point
, rl_point
+ l
, (char *)NULL
);
106 rl_line_buffer
[rl_end
] = '\0';
110 /* Delete the string between FROM and TO. FROM is inclusive, TO is not.
111 Returns the number of characters deleted. */
113 rl_delete_text (from
, to
)
117 register int diff
, i
;
119 /* Fix it if the caller is confused. */
133 text
= rl_copy_text (from
, to
);
135 /* Some versions of strncpy() can't handle overlapping arguments. */
137 for (i
= from
; i
< rl_end
- diff
; i
++)
138 rl_line_buffer
[i
] = rl_line_buffer
[i
+ diff
];
140 /* Remember how to undo this delete. */
141 if (_rl_doing_an_undo
== 0)
142 rl_add_undo (UNDO_DELETE
, from
, to
, text
);
147 rl_line_buffer
[rl_end
] = '\0';
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
155 #define _RL_FIX_POINT(x) \
164 _rl_fix_point (fix_mark_too
)
167 _RL_FIX_POINT (rl_point
);
169 _RL_FIX_POINT (rl_mark
);
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); */
177 _rl_replace_text (text
, start
, end
)
183 rl_begin_undo_group ();
184 rl_delete_text (start
, end
+ 1);
186 n
= rl_insert_text (text
);
187 rl_end_undo_group ();
192 /* Replace the current line buffer contents with TEXT. If CLEAR_UNDO is
193 non-zero, we free the current undo list. */
195 rl_replace_line (text
, clear_undo
)
202 if (len
>= rl_line_buffer_len
)
203 rl_extend_line_buffer (len
);
204 strcpy (rl_line_buffer
, text
);
208 rl_free_undo_list ();
213 /* **************************************************************** */
215 /* Readline character functions */
217 /* **************************************************************** */
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. */
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.
227 rl_point is the place in the string where the cursor is. Sometimes
228 this is the same as rl_end.
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.
235 /* **************************************************************** */
237 /* Movement Commands */
239 /* **************************************************************** */
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. */
246 /* Move forward COUNT bytes. */
248 rl_forward_byte (count
, key
)
252 return (rl_backward_byte (-count
, key
));
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
;
278 #if defined (HANDLE_MULTIBYTE)
279 /* Move forward COUNT characters. */
281 rl_forward_char (count
, key
)
286 if (MB_CUR_MAX
== 1 || rl_byte_oriented
)
287 return (rl_forward_byte (count
, key
));
290 return (rl_backward_char (-count
, key
));
294 point
= _rl_find_next_mbchar (rl_line_buffer
, rl_point
, count
, MB_FIND_NONZERO
);
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
);
301 if (rl_point
== point
)
312 #else /* !HANDLE_MULTIBYTE */
314 rl_forward_char (count
, key
)
317 return (rl_forward_byte (count
, key
));
319 #endif /* !HANDLE_MULTIBYTE */
321 /* Backwards compatibility. */
323 rl_forward (count
, key
)
326 return (rl_forward_char (count
, key
));
329 /* Move backward COUNT bytes. */
331 rl_backward_byte (count
, key
)
335 return (rl_forward_byte (-count
, key
));
339 if (rl_point
< count
)
354 #if defined (HANDLE_MULTIBYTE)
355 /* Move backward COUNT characters. */
357 rl_backward_char (count
, key
)
362 if (MB_CUR_MAX
== 1 || rl_byte_oriented
)
363 return (rl_backward_byte (count
, key
));
366 return (rl_forward_char (-count
, key
));
372 while (count
> 0 && point
> 0)
374 point
= _rl_find_prev_mbchar (rl_line_buffer
, point
, MB_FIND_NONZERO
);
390 rl_backward_char (count
, key
)
393 return (rl_backward_byte (count
, key
));
397 /* Backwards compatibility. */
399 rl_backward (count
, key
)
402 return (rl_backward_char (count
, key
));
405 /* Move to the beginning of the line. */
407 rl_beg_of_line (count
, key
)
414 /* Move to the end of the line. */
416 rl_end_of_line (count
, key
)
423 /* XXX - these might need changes for multibyte characters */
424 /* Move forward a word. We do what Emacs does. */
426 rl_forward_word (count
, key
)
432 return (rl_backward_word (-count
, key
));
436 if (rl_point
== rl_end
)
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)
444 while (++rl_point
< rl_end
)
446 c
= rl_line_buffer
[rl_point
];
447 if (rl_alphabetic (c
))
452 if (rl_point
== rl_end
)
455 while (++rl_point
< rl_end
)
457 c
= rl_line_buffer
[rl_point
];
458 if (rl_alphabetic (c
) == 0)
467 /* Move backward a word. We do what Emacs does. */
469 rl_backward_word (count
, key
)
475 return (rl_forward_word (-count
, key
));
482 /* Like rl_forward_word (), except that we look at the characters
483 just before point. */
485 c
= rl_line_buffer
[rl_point
- 1];
486 if (rl_alphabetic (c
) == 0)
490 c
= rl_line_buffer
[rl_point
- 1];
491 if (rl_alphabetic (c
))
498 c
= rl_line_buffer
[rl_point
- 1];
499 if (rl_alphabetic (c
) == 0)
511 /* Clear the current line. Numeric argument to C-l does this. */
513 rl_refresh_line (ignore1
, ignore2
)
514 int ignore1
, ignore2
;
518 curr_line
= _rl_current_display_line ();
520 _rl_move_vert (curr_line
);
521 _rl_move_cursor_relative (0, rl_line_buffer
); /* XXX is this right */
523 _rl_clear_to_eol (0); /* arg of 0 means to not use spaces */
525 rl_forced_update_display ();
526 rl_display_fixed
= 1;
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
535 rl_clear_screen (count
, key
)
540 rl_refresh_line (count
, key
);
544 _rl_clear_screen (); /* calls termcap function to clear screen */
545 rl_forced_update_display ();
546 rl_display_fixed
= 1;
552 rl_arrow_keys (count
, c
)
557 RL_SETSTATE(RL_STATE_MOREINPUT
);
559 RL_UNSETSTATE(RL_STATE_MOREINPUT
);
561 switch (_rl_to_upper (ch
))
564 rl_get_previous_history (count
, ch
);
568 rl_get_next_history (count
, ch
);
572 if (MB_CUR_MAX
> 1 && rl_byte_oriented
== 0)
573 rl_forward_char (count
, ch
);
575 rl_forward_byte (count
, ch
);
579 if (MB_CUR_MAX
> 1 && rl_byte_oriented
== 0)
580 rl_backward_char (count
, ch
);
582 rl_backward_byte (count
, ch
);
592 /* **************************************************************** */
596 /* **************************************************************** */
598 #ifdef HANDLE_MULTIBYTE
599 static char pending_bytes
[MB_LEN_MAX
];
600 static int pending_bytes_length
= 0;
601 static mbstate_t ps
= {0};
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. */
608 _rl_insert_char (count
, c
)
613 #ifdef HANDLE_MULTIBYTE
615 char incoming
[MB_LEN_MAX
+ 1];
616 int incoming_length
= 0;
618 static int stored_count
= 0;
624 #if defined (HANDLE_MULTIBYTE)
625 if (MB_CUR_MAX
== 1 || rl_byte_oriented
)
636 if (stored_count
<= 0)
637 stored_count
= count
;
639 count
= stored_count
;
642 pending_bytes
[pending_bytes_length
++] = c
;
643 ret
= mbrtowc (&wc
, pending_bytes
, pending_bytes_length
, &ps
);
645 if (ret
== (size_t)-2)
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. */
653 else if (ret
== (size_t)-1)
655 /* Invalid byte sequence for the current locale. Treat first byte
656 as a single character. */
657 incoming
[0] = pending_bytes
[0];
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));
666 else if (ret
== (size_t)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));
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;
684 #endif /* HANDLE_MULTIBYTE */
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)
690 #if defined (HANDLE_MULTIBYTE)
691 string_size
= count
* incoming_length
;
692 string
= (char *)xmalloc (1 + string_size
);
695 while (i
< string_size
)
697 strncpy (string
+ i
, incoming
, incoming_length
);
698 i
+= incoming_length
;
702 #else /* !HANDLE_MULTIBYTE */
703 string
= (char *)xmalloc (1 + count
);
705 for (i
= 0; i
< count
; i
++)
707 #endif /* !HANDLE_MULTIBYTE */
710 rl_insert_text (string
);
719 #if defined (HANDLE_MULTIBYTE)
720 string_size
= incoming_length
* 1024;
721 string
= (char *)xmalloc (1 + string_size
);
724 while (i
< string_size
)
726 strncpy (string
+ i
, incoming
, incoming_length
);
727 i
+= incoming_length
;
732 decreaser
= (count
> 1024) ? 1024 : count
;
733 string
[decreaser
*incoming_length
] = '\0';
734 rl_insert_text (string
);
741 #else /* !HANDLE_MULTIBYTE */
744 for (i
= 0; i
< 1024; i
++)
749 decreaser
= (count
> 1024 ? 1024 : count
);
750 str
[decreaser
] = '\0';
751 rl_insert_text (str
);
754 #endif /* !HANDLE_MULTIBYTE */
759 #if defined (HANDLE_MULTIBYTE)
760 if (MB_CUR_MAX
== 1 || rl_byte_oriented
)
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
767 if (_rl_any_typein ())
768 _rl_insert_typein (c
);
771 /* Inserting a single character. */
776 rl_insert_text (str
);
778 #if defined (HANDLE_MULTIBYTE)
782 rl_insert_text (incoming
);
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. */
794 _rl_overwrite_char (count
, c
)
798 #if defined (HANDLE_MULTIBYTE)
799 char mbkey
[MB_LEN_MAX
];
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
);
807 rl_begin_undo_group ();
809 for (i
= 0; i
< count
; i
++)
811 #if defined (HANDLE_MULTIBYTE)
812 if (MB_CUR_MAX
> 1 && rl_byte_oriented
== 0)
813 rl_insert_text (mbkey
);
816 _rl_insert_char (1, c
);
818 if (rl_point
< rl_end
)
822 rl_end_undo_group ();
831 return (rl_insert_mode
== RL_IM_INSERT
? _rl_insert_char (count
, c
)
832 : _rl_overwrite_char (count
, c
));
835 /* Insert the next typed character verbatim. */
837 rl_quoted_insert (count
, key
)
842 #if defined (HANDLE_SIGNALS)
843 _rl_disable_tty_signals ();
846 RL_SETSTATE(RL_STATE_MOREINPUT
);
848 RL_UNSETSTATE(RL_STATE_MOREINPUT
);
850 #if defined (HANDLE_SIGNALS)
851 _rl_restore_tty_signals ();
854 return (_rl_insert_char (count
, c
));
857 /* Insert a tab character. */
859 rl_tab_insert (count
, key
)
862 return (_rl_insert_char (count
, '\t'));
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. */
869 rl_newline (count
, key
)
874 if (_rl_history_preserve_point
)
875 _rl_history_saved_point
= (rl_point
== rl_end
) ? -1 : rl_point
;
877 RL_SETSTATE(RL_STATE_DONE
);
879 #if defined (VI_MODE)
880 if (rl_editing_mode
== vi_mode
)
882 _rl_vi_done_inserting ();
883 if (_rl_vi_textmod_command (_rl_vi_last_command
) == 0) /* XXX */
884 _rl_vi_reset_last ();
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)
893 if (readline_echoing_p
)
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 ()
903 rl_do_lowercase_version (ignore1
, ignore2
)
904 int ignore1
, ignore2
;
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. */
913 _rl_overwrite_rubout (count
, key
)
927 /* L == number of spaces to insert */
928 for (i
= l
= 0; i
< count
; i
++)
930 rl_backward_char (1, key
);
931 l
+= rl_character_len (rl_line_buffer
[rl_point
], rl_point
); /* not exactly right */
934 rl_begin_undo_group ();
936 if (count
> 1 || rl_explicit_arg
)
937 rl_kill_text (opoint
, rl_point
);
939 rl_delete_text (opoint
, rl_point
);
941 /* Emacs puts point at the beginning of the sequence of spaces. */
942 if (rl_point
< rl_end
)
945 _rl_insert_char (l
, ' ');
949 rl_end_undo_group ();
954 /* Rubout the character behind point. */
956 rl_rubout (count
, key
)
960 return (rl_delete (-count
, key
));
968 if (rl_insert_mode
== RL_IM_OVERWRITE
)
969 return (_rl_overwrite_rubout (count
, key
));
971 return (_rl_rubout_char (count
, key
));
975 _rl_rubout_char (count
, key
)
981 /* Duplicated code because this is called from other parts of the library. */
983 return (rl_delete (-count
, key
));
991 if (count
> 1 || rl_explicit_arg
)
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
);
999 rl_backward_byte (count
, key
);
1000 rl_kill_text (orig_point
, rl_point
);
1004 #if defined (HANDLE_MULTIBYTE)
1005 if (MB_CUR_MAX
== 1 || rl_byte_oriented
)
1008 c
= rl_line_buffer
[--rl_point
];
1009 rl_delete_text (rl_point
, rl_point
+ 1);
1010 #if defined (HANDLE_MULTIBYTE)
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
);
1021 #endif /* HANDLE_MULTIBYTE */
1023 /* I don't think that the hack for end of line is needed for
1025 #if defined (HANDLE_MULTIBYTE)
1026 if (MB_CUR_MAX
== 1 || rl_byte_oriented
)
1028 if (rl_point
== rl_end
&& ISPRINT (c
) && _rl_last_c_pos
)
1031 l
= rl_character_len (c
, rl_point
);
1032 _rl_erase_at_end_of_line (l
);
1039 /* Delete the character under the cursor. Given a numeric argument,
1040 kill that many characters instead. */
1042 rl_delete (count
, key
)
1048 return (_rl_rubout_char (-count
, key
));
1050 if (rl_point
== rl_end
)
1056 if (count
> 1 || rl_explicit_arg
)
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
);
1064 rl_forward_byte (count
, key
);
1066 r
= rl_kill_text (orig_point
, rl_point
);
1067 rl_point
= orig_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
);
1076 new_point
= rl_point
+ 1;
1078 return (rl_delete_text (rl_point
, new_point
));
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. */
1087 rl_rubout_or_delete (count
, key
)
1090 if (rl_end
!= 0 && rl_point
== rl_end
)
1091 return (_rl_rubout_char (count
, key
));
1093 return (rl_delete (count
, key
));
1096 /* Delete all spaces and tabs around point. */
1098 rl_delete_horizontal_space (count
, ignore
)
1101 int start
= rl_point
;
1103 while (rl_point
&& whitespace (rl_line_buffer
[rl_point
- 1]))
1108 while (rl_point
< rl_end
&& whitespace (rl_line_buffer
[rl_point
]))
1111 if (start
!= rl_point
)
1113 rl_delete_text (start
, rl_point
);
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. */
1123 rl_delete_or_show_completions (count
, key
)
1126 if (rl_end
!= 0 && rl_point
== rl_end
)
1127 return (rl_possible_completions (count
, key
));
1129 return (rl_delete (count
, key
));
1132 #ifndef RL_COMMENT_BEGIN_DEFAULT
1133 #define RL_COMMENT_BEGIN_DEFAULT "#"
1136 /* Turn the current line into a comment in shell history.
1137 A K*rn shell style function. */
1139 rl_insert_comment (count
, key
)
1142 char *rl_comment_text
;
1145 rl_beg_of_line (1, key
);
1146 rl_comment_text
= _rl_comment_begin
? _rl_comment_begin
: RL_COMMENT_BEGIN_DEFAULT
;
1148 if (rl_explicit_arg
== 0)
1149 rl_insert_text (rl_comment_text
);
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
);
1156 rl_insert_text (rl_comment_text
);
1159 (*rl_redisplay_function
) ();
1160 rl_newline (1, '\n');
1165 /* **************************************************************** */
1169 /* **************************************************************** */
1171 /* The three kinds of things that we know how to do. */
1176 /* Uppercase the word at point. */
1178 rl_upcase_word (count
, key
)
1181 return (rl_change_case (count
, UpCase
));
1184 /* Lowercase the word at point. */
1186 rl_downcase_word (count
, key
)
1189 return (rl_change_case (count
, DownCase
));
1192 /* Upcase the first letter, downcase the rest. */
1194 rl_capitalize_word (count
, key
)
1197 return (rl_change_case (count
, CapCase
));
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. */
1206 rl_change_case (count
, op
)
1209 register int start
, end
;
1213 rl_forward_word (count
, 0);
1219 /* We are going to modify some text, so let's prepare to undo it. */
1220 rl_modifying (start
, end
);
1222 for (inword
= 0; start
< end
; start
++)
1224 c
= rl_line_buffer
[start
];
1228 rl_line_buffer
[start
] = _rl_to_upper (c
);
1232 rl_line_buffer
[start
] = _rl_to_lower (c
);
1236 rl_line_buffer
[start
] = (inword
== 0) ? _rl_to_upper (c
) : _rl_to_lower (c
);
1237 inword
= rl_alphabetic (rl_line_buffer
[start
]);
1249 /* **************************************************************** */
1253 /* **************************************************************** */
1255 /* Transpose the words at point. If point is at the end of the line,
1256 transpose the two words before point. */
1258 rl_transpose_words (count
, key
)
1261 char *word1
, *word2
;
1262 int w1_beg
, w1_end
, w2_beg
, w2_end
;
1263 int orig_point
= rl_point
;
1268 /* Find the two words. */
1269 rl_forward_word (count
, key
);
1271 rl_backward_word (1, key
);
1273 rl_backward_word (count
, key
);
1275 rl_forward_word (1, key
);
1278 /* Do some check to make sure that there really are two words. */
1279 if ((w1_beg
== w2_beg
) || (w2_beg
< w1_end
))
1282 rl_point
= orig_point
;
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
);
1290 /* We are about to do many insertions and deletions. Remember them
1291 as one operation. */
1292 rl_begin_undo_group ();
1294 /* Do the stuff at word2 first, so that we don't have to worry
1295 about word1 moving. */
1297 rl_delete_text (w2_beg
, w2_end
);
1298 rl_insert_text (word1
);
1301 rl_delete_text (w1_beg
, w1_end
);
1302 rl_insert_text (word2
);
1304 /* This is exactly correct since the text before this point has not
1305 changed in length. */
1308 /* I think that does it. */
1309 rl_end_undo_group ();
1316 /* Transpose the characters at point. If point is at the end of the line,
1317 then transpose the characters before point. */
1319 rl_transpose_chars (count
, key
)
1322 #if defined (HANDLE_MULTIBYTE)
1333 if (!rl_point
|| rl_end
< 2)
1339 rl_begin_undo_group ();
1341 if (rl_point
== rl_end
)
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
);
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
);
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
];
1365 dummy
[0] = rl_line_buffer
[rl_point
];
1366 dummy
[char_length
= 1] = '\0';
1369 rl_delete_text (rl_point
, rl_point
+ char_length
);
1371 rl_point
= _rl_find_next_mbchar (rl_line_buffer
, rl_point
, count
, MB_FIND_NONZERO
);
1374 rl_insert_text (dummy
);
1375 rl_end_undo_group ();
1377 #if defined (HANDLE_MULTIBYTE)
1384 /* **************************************************************** */
1386 /* Character Searching */
1388 /* **************************************************************** */
1391 #if defined (HANDLE_MULTIBYTE)
1392 _rl_char_search_internal (count
, dir
, smbchar
, len
)
1397 _rl_char_search_internal (count
, dir
, schar
)
1398 int count
, dir
, schar
;
1402 #if defined (HANDLE_MULTIBYTE)
1407 inc
= (dir
< 0) ? -1 : 1;
1410 if ((dir
< 0 && pos
<= 0) || (dir
> 0 && pos
>= rl_end
))
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
);
1424 #if defined (HANDLE_MULTIBYTE)
1425 if (_rl_is_mbchar_matched (rl_line_buffer
, pos
, rl_end
, smbchar
, len
))
1427 if (rl_line_buffer
[pos
] == schar
)
1432 rl_point
= (dir
== BTO
) ? _rl_find_next_mbchar (rl_line_buffer
, pos
, 1, MB_FIND_ANY
)
1435 rl_point
= (dir
== FTO
) ? _rl_find_prev_mbchar (rl_line_buffer
, pos
, MB_FIND_ANY
)
1439 #if defined (HANDLE_MULTIBYTE)
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
);
1447 while ((dir
< 0) ? pos
-- : ++pos
< rl_end
);
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)
1459 _rl_char_search (count
, fdir
, bdir
)
1460 int count
, fdir
, bdir
;
1462 char mbchar
[MB_LEN_MAX
];
1465 mb_len
= _rl_read_mbchar (mbchar
, MB_LEN_MAX
);
1468 return (_rl_char_search_internal (-count
, bdir
, mbchar
, mb_len
));
1470 return (_rl_char_search_internal (count
, fdir
, mbchar
, mb_len
));
1472 #else /* !HANDLE_MULTIBYTE */
1474 _rl_char_search (count
, fdir
, bdir
)
1475 int count
, fdir
, bdir
;
1479 RL_SETSTATE(RL_STATE_MOREINPUT
);
1481 RL_UNSETSTATE(RL_STATE_MOREINPUT
);
1484 return (_rl_char_search_internal (-count
, bdir
, c
));
1486 return (_rl_char_search_internal (count
, fdir
, c
));
1488 #endif /* !HANDLE_MULTIBYTE */
1491 rl_char_search (count
, key
)
1494 return (_rl_char_search (count
, FFIND
, BFIND
));
1498 rl_backward_char_search (count
, key
)
1501 return (_rl_char_search (count
, BFIND
, FFIND
));
1504 /* **************************************************************** */
1506 /* The Mark and the Region. */
1508 /* **************************************************************** */
1510 /* Set the mark at POSITION. */
1512 _rl_set_mark_at_pos (position
)
1515 if (position
> rl_end
)
1522 /* A bindable command to set the mark. */
1524 rl_set_mark (count
, key
)
1527 return (_rl_set_mark_at_pos (rl_explicit_arg
? count
: rl_point
));
1530 /* Exchange the position of mark and point. */
1532 rl_exchange_point_and_mark (count
, key
)
1535 if (rl_mark
> rl_end
)
1544 SWAP (rl_point
, rl_mark
);