xref: /openbsd-src/gnu/lib/libreadline/text.c (revision 9704b281e65e1189747652d0ba55eee892cff5f7)
115b117eaSkettenis /* text.c -- text handling commands for readline. */
215b117eaSkettenis 
315b117eaSkettenis /* Copyright (C) 1987-2002 Free Software Foundation, Inc.
415b117eaSkettenis 
515b117eaSkettenis    This file is part of the GNU Readline Library, a library for
615b117eaSkettenis    reading lines of text with interactive input and history editing.
715b117eaSkettenis 
815b117eaSkettenis    The GNU Readline Library is free software; you can redistribute it
915b117eaSkettenis    and/or modify it under the terms of the GNU General Public License
1015b117eaSkettenis    as published by the Free Software Foundation; either version 2, or
1115b117eaSkettenis    (at your option) any later version.
1215b117eaSkettenis 
1315b117eaSkettenis    The GNU Readline Library is distributed in the hope that it will be
1415b117eaSkettenis    useful, but WITHOUT ANY WARRANTY; without even the implied warranty
1515b117eaSkettenis    of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1615b117eaSkettenis    GNU General Public License for more details.
1715b117eaSkettenis 
1815b117eaSkettenis    The GNU General Public License is often shipped with GNU software, and
1915b117eaSkettenis    is generally kept in a file called COPYING or LICENSE.  If you do not
2015b117eaSkettenis    have a copy of the license, write to the Free Software Foundation,
2115b117eaSkettenis    59 Temple Place, Suite 330, Boston, MA 02111 USA. */
2215b117eaSkettenis #define READLINE_LIBRARY
2315b117eaSkettenis 
2415b117eaSkettenis #if defined (HAVE_CONFIG_H)
2515b117eaSkettenis #  include <config.h>
2615b117eaSkettenis #endif
2715b117eaSkettenis 
2815b117eaSkettenis #if defined (HAVE_UNISTD_H)
2915b117eaSkettenis #  include <unistd.h>
3015b117eaSkettenis #endif /* HAVE_UNISTD_H */
3115b117eaSkettenis 
3215b117eaSkettenis #if defined (HAVE_STDLIB_H)
3315b117eaSkettenis #  include <stdlib.h>
3415b117eaSkettenis #else
3515b117eaSkettenis #  include "ansi_stdlib.h"
3615b117eaSkettenis #endif /* HAVE_STDLIB_H */
3715b117eaSkettenis 
3815b117eaSkettenis #if defined (HAVE_LOCALE_H)
3915b117eaSkettenis #  include <locale.h>
4015b117eaSkettenis #endif
4115b117eaSkettenis 
4215b117eaSkettenis #include <stdio.h>
4315b117eaSkettenis 
4415b117eaSkettenis /* System-specific feature definitions and include files. */
4515b117eaSkettenis #include "rldefs.h"
4615b117eaSkettenis #include "rlmbutil.h"
4715b117eaSkettenis 
4815b117eaSkettenis #if defined (__EMX__)
4915b117eaSkettenis #  define INCL_DOSPROCESS
5015b117eaSkettenis #  include <os2.h>
5115b117eaSkettenis #endif /* __EMX__ */
5215b117eaSkettenis 
5315b117eaSkettenis /* Some standard library routines. */
5415b117eaSkettenis #include "readline.h"
5515b117eaSkettenis #include "history.h"
5615b117eaSkettenis 
5715b117eaSkettenis #include "rlprivate.h"
5815b117eaSkettenis #include "rlshell.h"
5915b117eaSkettenis #include "xmalloc.h"
6015b117eaSkettenis 
6115b117eaSkettenis /* Forward declarations. */
6215b117eaSkettenis static int rl_change_case PARAMS((int, int));
6315b117eaSkettenis static int _rl_char_search PARAMS((int, int, int));
6415b117eaSkettenis 
6515b117eaSkettenis /* **************************************************************** */
6615b117eaSkettenis /*								    */
6715b117eaSkettenis /*			Insert and Delete			    */
6815b117eaSkettenis /*								    */
6915b117eaSkettenis /* **************************************************************** */
7015b117eaSkettenis 
7115b117eaSkettenis /* Insert a string of text into the line at point.  This is the only
7215b117eaSkettenis    way that you should do insertion.  _rl_insert_char () calls this
7315b117eaSkettenis    function.  Returns the number of characters inserted. */
7415b117eaSkettenis int
rl_insert_text(string)7515b117eaSkettenis rl_insert_text (string)
7615b117eaSkettenis      const char *string;
7715b117eaSkettenis {
7815b117eaSkettenis   register int i, l;
7915b117eaSkettenis 
8015b117eaSkettenis   l = (string && *string) ? strlen (string) : 0;
8115b117eaSkettenis   if (l == 0)
8215b117eaSkettenis     return 0;
8315b117eaSkettenis 
8415b117eaSkettenis   if (rl_end + l >= rl_line_buffer_len)
8515b117eaSkettenis     rl_extend_line_buffer (rl_end + l);
8615b117eaSkettenis 
8715b117eaSkettenis   for (i = rl_end; i >= rl_point; i--)
8815b117eaSkettenis     rl_line_buffer[i + l] = rl_line_buffer[i];
8915b117eaSkettenis   strncpy (rl_line_buffer + rl_point, string, l);
9015b117eaSkettenis 
9115b117eaSkettenis   /* Remember how to undo this if we aren't undoing something. */
9215b117eaSkettenis   if (_rl_doing_an_undo == 0)
9315b117eaSkettenis     {
9415b117eaSkettenis       /* If possible and desirable, concatenate the undos. */
9515b117eaSkettenis       if ((l == 1) &&
9615b117eaSkettenis 	  rl_undo_list &&
9715b117eaSkettenis 	  (rl_undo_list->what == UNDO_INSERT) &&
9815b117eaSkettenis 	  (rl_undo_list->end == rl_point) &&
9915b117eaSkettenis 	  (rl_undo_list->end - rl_undo_list->start < 20))
10015b117eaSkettenis 	rl_undo_list->end++;
10115b117eaSkettenis       else
10215b117eaSkettenis 	rl_add_undo (UNDO_INSERT, rl_point, rl_point + l, (char *)NULL);
10315b117eaSkettenis     }
10415b117eaSkettenis   rl_point += l;
10515b117eaSkettenis   rl_end += l;
10615b117eaSkettenis   rl_line_buffer[rl_end] = '\0';
10715b117eaSkettenis   return l;
10815b117eaSkettenis }
10915b117eaSkettenis 
11015b117eaSkettenis /* Delete the string between FROM and TO.  FROM is inclusive, TO is not.
11115b117eaSkettenis    Returns the number of characters deleted. */
11215b117eaSkettenis int
rl_delete_text(from,to)11315b117eaSkettenis rl_delete_text (from, to)
11415b117eaSkettenis      int from, to;
11515b117eaSkettenis {
11615b117eaSkettenis   register char *text;
11715b117eaSkettenis   register int diff, i;
11815b117eaSkettenis 
11915b117eaSkettenis   /* Fix it if the caller is confused. */
12015b117eaSkettenis   if (from > to)
12115b117eaSkettenis     SWAP (from, to);
12215b117eaSkettenis 
12315b117eaSkettenis   /* fix boundaries */
12415b117eaSkettenis   if (to > rl_end)
12515b117eaSkettenis     {
12615b117eaSkettenis       to = rl_end;
12715b117eaSkettenis       if (from > to)
12815b117eaSkettenis 	from = to;
12915b117eaSkettenis     }
13015b117eaSkettenis   if (from < 0)
13115b117eaSkettenis     from = 0;
13215b117eaSkettenis 
13315b117eaSkettenis   text = rl_copy_text (from, to);
13415b117eaSkettenis 
13515b117eaSkettenis   /* Some versions of strncpy() can't handle overlapping arguments. */
13615b117eaSkettenis   diff = to - from;
13715b117eaSkettenis   for (i = from; i < rl_end - diff; i++)
13815b117eaSkettenis     rl_line_buffer[i] = rl_line_buffer[i + diff];
13915b117eaSkettenis 
14015b117eaSkettenis   /* Remember how to undo this delete. */
14115b117eaSkettenis   if (_rl_doing_an_undo == 0)
14215b117eaSkettenis     rl_add_undo (UNDO_DELETE, from, to, text);
14315b117eaSkettenis   else
14415b117eaSkettenis     free (text);
14515b117eaSkettenis 
14615b117eaSkettenis   rl_end -= diff;
14715b117eaSkettenis   rl_line_buffer[rl_end] = '\0';
14815b117eaSkettenis   return (diff);
14915b117eaSkettenis }
15015b117eaSkettenis 
15115b117eaSkettenis /* Fix up point so that it is within the line boundaries after killing
15215b117eaSkettenis    text.  If FIX_MARK_TOO is non-zero, the mark is forced within line
15315b117eaSkettenis    boundaries also. */
15415b117eaSkettenis 
15515b117eaSkettenis #define _RL_FIX_POINT(x) \
15615b117eaSkettenis 	do { \
15715b117eaSkettenis 	if (x > rl_end) \
15815b117eaSkettenis 	  x = rl_end; \
15915b117eaSkettenis 	else if (x < 0) \
16015b117eaSkettenis 	  x = 0; \
16115b117eaSkettenis 	} while (0)
16215b117eaSkettenis 
16315b117eaSkettenis void
_rl_fix_point(fix_mark_too)16415b117eaSkettenis _rl_fix_point (fix_mark_too)
16515b117eaSkettenis      int fix_mark_too;
16615b117eaSkettenis {
16715b117eaSkettenis   _RL_FIX_POINT (rl_point);
16815b117eaSkettenis   if (fix_mark_too)
16915b117eaSkettenis     _RL_FIX_POINT (rl_mark);
17015b117eaSkettenis }
17115b117eaSkettenis #undef _RL_FIX_POINT
17215b117eaSkettenis 
17315b117eaSkettenis int
_rl_replace_text(text,start,end)17415b117eaSkettenis _rl_replace_text (text, start, end)
17515b117eaSkettenis      const char *text;
17615b117eaSkettenis      int start, end;
17715b117eaSkettenis {
17815b117eaSkettenis   int n;
17915b117eaSkettenis 
18015b117eaSkettenis   rl_begin_undo_group ();
18115b117eaSkettenis   rl_delete_text (start, end + 1);
18215b117eaSkettenis   rl_point = start;
18315b117eaSkettenis   n = rl_insert_text (text);
18415b117eaSkettenis   rl_end_undo_group ();
18515b117eaSkettenis 
18615b117eaSkettenis   return n;
18715b117eaSkettenis }
18815b117eaSkettenis 
18915b117eaSkettenis /* Replace the current line buffer contents with TEXT.  If CLEAR_UNDO is
19015b117eaSkettenis    non-zero, we free the current undo list. */
19115b117eaSkettenis void
rl_replace_line(text,clear_undo)19215b117eaSkettenis rl_replace_line (text, clear_undo)
19315b117eaSkettenis      const char *text;
19415b117eaSkettenis      int clear_undo;
19515b117eaSkettenis {
19615b117eaSkettenis   int len;
19715b117eaSkettenis 
19815b117eaSkettenis   len = strlen (text);
19915b117eaSkettenis   if (len >= rl_line_buffer_len)
20015b117eaSkettenis     rl_extend_line_buffer (len);
201*9480732dSkettenis   strlcpy (rl_line_buffer, text, rl_line_buffer_len);
20215b117eaSkettenis   rl_end = len;
20315b117eaSkettenis 
20415b117eaSkettenis   if (clear_undo)
20515b117eaSkettenis     rl_free_undo_list ();
20615b117eaSkettenis 
20715b117eaSkettenis   _rl_fix_point (1);
20815b117eaSkettenis }
20915b117eaSkettenis 
21015b117eaSkettenis /* **************************************************************** */
21115b117eaSkettenis /*								    */
21215b117eaSkettenis /*			Readline character functions		    */
21315b117eaSkettenis /*								    */
21415b117eaSkettenis /* **************************************************************** */
21515b117eaSkettenis 
21615b117eaSkettenis /* This is not a gap editor, just a stupid line input routine.  No hair
21715b117eaSkettenis    is involved in writing any of the functions, and none should be. */
21815b117eaSkettenis 
21915b117eaSkettenis /* Note that:
22015b117eaSkettenis 
22115b117eaSkettenis    rl_end is the place in the string that we would place '\0';
22215b117eaSkettenis    i.e., it is always safe to place '\0' there.
22315b117eaSkettenis 
22415b117eaSkettenis    rl_point is the place in the string where the cursor is.  Sometimes
22515b117eaSkettenis    this is the same as rl_end.
22615b117eaSkettenis 
22715b117eaSkettenis    Any command that is called interactively receives two arguments.
22815b117eaSkettenis    The first is a count: the numeric arg pased to this command.
22915b117eaSkettenis    The second is the key which invoked this command.
23015b117eaSkettenis */
23115b117eaSkettenis 
23215b117eaSkettenis /* **************************************************************** */
23315b117eaSkettenis /*								    */
23415b117eaSkettenis /*			Movement Commands			    */
23515b117eaSkettenis /*								    */
23615b117eaSkettenis /* **************************************************************** */
23715b117eaSkettenis 
23815b117eaSkettenis /* Note that if you `optimize' the display for these functions, you cannot
23915b117eaSkettenis    use said functions in other functions which do not do optimizing display.
24015b117eaSkettenis    I.e., you will have to update the data base for rl_redisplay, and you
24115b117eaSkettenis    might as well let rl_redisplay do that job. */
24215b117eaSkettenis 
24315b117eaSkettenis /* Move forward COUNT bytes. */
24415b117eaSkettenis int
rl_forward_byte(count,key)24515b117eaSkettenis rl_forward_byte (count, key)
24615b117eaSkettenis      int count, key;
24715b117eaSkettenis {
24815b117eaSkettenis   if (count < 0)
24915b117eaSkettenis     return (rl_backward_byte (-count, key));
25015b117eaSkettenis 
25115b117eaSkettenis   if (count > 0)
25215b117eaSkettenis     {
25315b117eaSkettenis       int end = rl_point + count;
25415b117eaSkettenis #if defined (VI_MODE)
25515b117eaSkettenis       int lend = rl_end > 0 ? rl_end - (rl_editing_mode == vi_mode) : rl_end;
25615b117eaSkettenis #else
25715b117eaSkettenis       int lend = rl_end;
25815b117eaSkettenis #endif
25915b117eaSkettenis 
26015b117eaSkettenis       if (end > lend)
26115b117eaSkettenis 	{
26215b117eaSkettenis 	  rl_point = lend;
26315b117eaSkettenis 	  rl_ding ();
26415b117eaSkettenis 	}
26515b117eaSkettenis       else
26615b117eaSkettenis 	rl_point = end;
26715b117eaSkettenis     }
26815b117eaSkettenis 
26915b117eaSkettenis   if (rl_end < 0)
27015b117eaSkettenis     rl_end = 0;
27115b117eaSkettenis 
27215b117eaSkettenis   return 0;
27315b117eaSkettenis }
27415b117eaSkettenis 
27515b117eaSkettenis #if defined (HANDLE_MULTIBYTE)
27615b117eaSkettenis /* Move forward COUNT characters. */
27715b117eaSkettenis int
rl_forward_char(count,key)27815b117eaSkettenis rl_forward_char (count, key)
27915b117eaSkettenis      int count, key;
28015b117eaSkettenis {
28115b117eaSkettenis   int point;
28215b117eaSkettenis 
28315b117eaSkettenis   if (MB_CUR_MAX == 1 || rl_byte_oriented)
28415b117eaSkettenis     return (rl_forward_byte (count, key));
28515b117eaSkettenis 
28615b117eaSkettenis   if (count < 0)
28715b117eaSkettenis     return (rl_backward_char (-count, key));
28815b117eaSkettenis 
28915b117eaSkettenis   if (count > 0)
29015b117eaSkettenis     {
29115b117eaSkettenis       point = _rl_find_next_mbchar (rl_line_buffer, rl_point, count, MB_FIND_NONZERO);
29215b117eaSkettenis 
29315b117eaSkettenis #if defined (VI_MODE)
29415b117eaSkettenis       if (rl_end <= point && rl_editing_mode == vi_mode)
29515b117eaSkettenis 	point = _rl_find_prev_mbchar (rl_line_buffer, rl_end, MB_FIND_NONZERO);
29615b117eaSkettenis #endif
29715b117eaSkettenis 
29815b117eaSkettenis       if (rl_point == point)
29915b117eaSkettenis 	rl_ding ();
30015b117eaSkettenis 
30115b117eaSkettenis       rl_point = point;
30215b117eaSkettenis 
30315b117eaSkettenis       if (rl_end < 0)
30415b117eaSkettenis 	rl_end = 0;
30515b117eaSkettenis     }
30615b117eaSkettenis 
30715b117eaSkettenis   return 0;
30815b117eaSkettenis }
30915b117eaSkettenis #else /* !HANDLE_MULTIBYTE */
31015b117eaSkettenis int
rl_forward_char(count,key)31115b117eaSkettenis rl_forward_char (count, key)
31215b117eaSkettenis      int count, key;
31315b117eaSkettenis {
31415b117eaSkettenis   return (rl_forward_byte (count, key));
31515b117eaSkettenis }
31615b117eaSkettenis #endif /* !HANDLE_MULTIBYTE */
31715b117eaSkettenis 
31815b117eaSkettenis /* Backwards compatibility. */
31915b117eaSkettenis int
rl_forward(count,key)32015b117eaSkettenis rl_forward (count, key)
32115b117eaSkettenis      int count, key;
32215b117eaSkettenis {
32315b117eaSkettenis   return (rl_forward_char (count, key));
32415b117eaSkettenis }
32515b117eaSkettenis 
32615b117eaSkettenis /* Move backward COUNT bytes. */
32715b117eaSkettenis int
rl_backward_byte(count,key)32815b117eaSkettenis rl_backward_byte (count, key)
32915b117eaSkettenis      int count, key;
33015b117eaSkettenis {
33115b117eaSkettenis   if (count < 0)
33215b117eaSkettenis     return (rl_forward_byte (-count, key));
33315b117eaSkettenis 
33415b117eaSkettenis   if (count > 0)
33515b117eaSkettenis     {
33615b117eaSkettenis       if (rl_point < count)
33715b117eaSkettenis 	{
33815b117eaSkettenis 	  rl_point = 0;
33915b117eaSkettenis 	  rl_ding ();
34015b117eaSkettenis 	}
34115b117eaSkettenis       else
34215b117eaSkettenis 	rl_point -= count;
34315b117eaSkettenis     }
34415b117eaSkettenis 
34515b117eaSkettenis   if (rl_point < 0)
34615b117eaSkettenis     rl_point = 0;
34715b117eaSkettenis 
34815b117eaSkettenis   return 0;
34915b117eaSkettenis }
35015b117eaSkettenis 
35115b117eaSkettenis #if defined (HANDLE_MULTIBYTE)
35215b117eaSkettenis /* Move backward COUNT characters. */
35315b117eaSkettenis int
rl_backward_char(count,key)35415b117eaSkettenis rl_backward_char (count, key)
35515b117eaSkettenis      int count, key;
35615b117eaSkettenis {
35715b117eaSkettenis   int point;
35815b117eaSkettenis 
35915b117eaSkettenis   if (MB_CUR_MAX == 1 || rl_byte_oriented)
36015b117eaSkettenis     return (rl_backward_byte (count, key));
36115b117eaSkettenis 
36215b117eaSkettenis   if (count < 0)
36315b117eaSkettenis     return (rl_forward_char (-count, key));
36415b117eaSkettenis 
36515b117eaSkettenis   if (count > 0)
36615b117eaSkettenis     {
36715b117eaSkettenis       point = rl_point;
36815b117eaSkettenis 
36915b117eaSkettenis       while (count > 0 && point > 0)
37015b117eaSkettenis 	{
37115b117eaSkettenis 	  point = _rl_find_prev_mbchar (rl_line_buffer, point, MB_FIND_NONZERO);
37215b117eaSkettenis 	  count--;
37315b117eaSkettenis 	}
37415b117eaSkettenis       if (count > 0)
37515b117eaSkettenis 	{
37615b117eaSkettenis 	  rl_point = 0;
37715b117eaSkettenis 	  rl_ding ();
37815b117eaSkettenis 	}
37915b117eaSkettenis       else
38015b117eaSkettenis         rl_point = point;
38115b117eaSkettenis     }
38215b117eaSkettenis 
38315b117eaSkettenis   return 0;
38415b117eaSkettenis }
38515b117eaSkettenis #else
38615b117eaSkettenis int
rl_backward_char(count,key)38715b117eaSkettenis rl_backward_char (count, key)
38815b117eaSkettenis      int count, key;
38915b117eaSkettenis {
39015b117eaSkettenis   return (rl_backward_byte (count, key));
39115b117eaSkettenis }
39215b117eaSkettenis #endif
39315b117eaSkettenis 
39415b117eaSkettenis /* Backwards compatibility. */
39515b117eaSkettenis int
rl_backward(count,key)39615b117eaSkettenis rl_backward (count, key)
39715b117eaSkettenis      int count, key;
39815b117eaSkettenis {
39915b117eaSkettenis   return (rl_backward_char (count, key));
40015b117eaSkettenis }
40115b117eaSkettenis 
40215b117eaSkettenis /* Move to the beginning of the line. */
40315b117eaSkettenis int
rl_beg_of_line(count,key)40415b117eaSkettenis rl_beg_of_line (count, key)
40515b117eaSkettenis      int count, key;
40615b117eaSkettenis {
40715b117eaSkettenis   rl_point = 0;
40815b117eaSkettenis   return 0;
40915b117eaSkettenis }
41015b117eaSkettenis 
41115b117eaSkettenis /* Move to the end of the line. */
41215b117eaSkettenis int
rl_end_of_line(count,key)41315b117eaSkettenis rl_end_of_line (count, key)
41415b117eaSkettenis      int count, key;
41515b117eaSkettenis {
41615b117eaSkettenis   rl_point = rl_end;
41715b117eaSkettenis   return 0;
41815b117eaSkettenis }
41915b117eaSkettenis 
42015b117eaSkettenis /* XXX - these might need changes for multibyte characters */
42115b117eaSkettenis /* Move forward a word.  We do what Emacs does. */
42215b117eaSkettenis int
rl_forward_word(count,key)42315b117eaSkettenis rl_forward_word (count, key)
42415b117eaSkettenis      int count, key;
42515b117eaSkettenis {
42615b117eaSkettenis   int c;
42715b117eaSkettenis 
42815b117eaSkettenis   if (count < 0)
42915b117eaSkettenis     return (rl_backward_word (-count, key));
43015b117eaSkettenis 
43115b117eaSkettenis   while (count)
43215b117eaSkettenis     {
43315b117eaSkettenis       if (rl_point == rl_end)
43415b117eaSkettenis 	return 0;
43515b117eaSkettenis 
43615b117eaSkettenis       /* If we are not in a word, move forward until we are in one.
43715b117eaSkettenis 	 Then, move forward until we hit a non-alphabetic character. */
43815b117eaSkettenis       c = rl_line_buffer[rl_point];
43915b117eaSkettenis       if (rl_alphabetic (c) == 0)
44015b117eaSkettenis 	{
44115b117eaSkettenis 	  while (++rl_point < rl_end)
44215b117eaSkettenis 	    {
44315b117eaSkettenis 	      c = rl_line_buffer[rl_point];
44415b117eaSkettenis 	      if (rl_alphabetic (c))
44515b117eaSkettenis 		break;
44615b117eaSkettenis 	    }
44715b117eaSkettenis 	}
44815b117eaSkettenis 
44915b117eaSkettenis       if (rl_point == rl_end)
45015b117eaSkettenis 	return 0;
45115b117eaSkettenis 
45215b117eaSkettenis       while (++rl_point < rl_end)
45315b117eaSkettenis 	{
45415b117eaSkettenis 	  c = rl_line_buffer[rl_point];
45515b117eaSkettenis 	  if (rl_alphabetic (c) == 0)
45615b117eaSkettenis 	    break;
45715b117eaSkettenis 	}
45815b117eaSkettenis       --count;
45915b117eaSkettenis     }
46015b117eaSkettenis 
46115b117eaSkettenis   return 0;
46215b117eaSkettenis }
46315b117eaSkettenis 
46415b117eaSkettenis /* Move backward a word.  We do what Emacs does. */
46515b117eaSkettenis int
rl_backward_word(count,key)46615b117eaSkettenis rl_backward_word (count, key)
46715b117eaSkettenis      int count, key;
46815b117eaSkettenis {
46915b117eaSkettenis   int c;
47015b117eaSkettenis 
47115b117eaSkettenis   if (count < 0)
47215b117eaSkettenis     return (rl_forward_word (-count, key));
47315b117eaSkettenis 
47415b117eaSkettenis   while (count)
47515b117eaSkettenis     {
47615b117eaSkettenis       if (!rl_point)
47715b117eaSkettenis 	return 0;
47815b117eaSkettenis 
47915b117eaSkettenis       /* Like rl_forward_word (), except that we look at the characters
48015b117eaSkettenis 	 just before point. */
48115b117eaSkettenis 
48215b117eaSkettenis       c = rl_line_buffer[rl_point - 1];
48315b117eaSkettenis       if (rl_alphabetic (c) == 0)
48415b117eaSkettenis 	{
48515b117eaSkettenis 	  while (--rl_point)
48615b117eaSkettenis 	    {
48715b117eaSkettenis 	      c = rl_line_buffer[rl_point - 1];
48815b117eaSkettenis 	      if (rl_alphabetic (c))
48915b117eaSkettenis 		break;
49015b117eaSkettenis 	    }
49115b117eaSkettenis 	}
49215b117eaSkettenis 
49315b117eaSkettenis       while (rl_point)
49415b117eaSkettenis 	{
49515b117eaSkettenis 	  c = rl_line_buffer[rl_point - 1];
49615b117eaSkettenis 	  if (rl_alphabetic (c) == 0)
49715b117eaSkettenis 	    break;
49815b117eaSkettenis 	  else
49915b117eaSkettenis 	    --rl_point;
50015b117eaSkettenis 	}
50115b117eaSkettenis 
50215b117eaSkettenis       --count;
50315b117eaSkettenis     }
50415b117eaSkettenis 
50515b117eaSkettenis   return 0;
50615b117eaSkettenis }
50715b117eaSkettenis 
50815b117eaSkettenis /* Clear the current line.  Numeric argument to C-l does this. */
50915b117eaSkettenis int
rl_refresh_line(ignore1,ignore2)51015b117eaSkettenis rl_refresh_line (ignore1, ignore2)
51115b117eaSkettenis      int ignore1, ignore2;
51215b117eaSkettenis {
51315b117eaSkettenis   int curr_line;
51415b117eaSkettenis 
51515b117eaSkettenis   curr_line = _rl_current_display_line ();
51615b117eaSkettenis 
51715b117eaSkettenis   _rl_move_vert (curr_line);
51815b117eaSkettenis   _rl_move_cursor_relative (0, rl_line_buffer);   /* XXX is this right */
51915b117eaSkettenis 
52015b117eaSkettenis   _rl_clear_to_eol (0);		/* arg of 0 means to not use spaces */
52115b117eaSkettenis 
52215b117eaSkettenis   rl_forced_update_display ();
52315b117eaSkettenis   rl_display_fixed = 1;
52415b117eaSkettenis 
52515b117eaSkettenis   return 0;
52615b117eaSkettenis }
52715b117eaSkettenis 
52815b117eaSkettenis /* C-l typed to a line without quoting clears the screen, and then reprints
52915b117eaSkettenis    the prompt and the current input line.  Given a numeric arg, redraw only
53015b117eaSkettenis    the current line. */
53115b117eaSkettenis int
rl_clear_screen(count,key)53215b117eaSkettenis rl_clear_screen (count, key)
53315b117eaSkettenis      int count, key;
53415b117eaSkettenis {
53515b117eaSkettenis   if (rl_explicit_arg)
53615b117eaSkettenis     {
53715b117eaSkettenis       rl_refresh_line (count, key);
53815b117eaSkettenis       return 0;
53915b117eaSkettenis     }
54015b117eaSkettenis 
54115b117eaSkettenis   _rl_clear_screen ();		/* calls termcap function to clear screen */
54215b117eaSkettenis   rl_forced_update_display ();
54315b117eaSkettenis   rl_display_fixed = 1;
54415b117eaSkettenis 
54515b117eaSkettenis   return 0;
54615b117eaSkettenis }
54715b117eaSkettenis 
54815b117eaSkettenis int
rl_arrow_keys(count,c)54915b117eaSkettenis rl_arrow_keys (count, c)
55015b117eaSkettenis      int count, c;
55115b117eaSkettenis {
55215b117eaSkettenis   int ch;
55315b117eaSkettenis 
55415b117eaSkettenis   RL_SETSTATE(RL_STATE_MOREINPUT);
55515b117eaSkettenis   ch = rl_read_key ();
55615b117eaSkettenis   RL_UNSETSTATE(RL_STATE_MOREINPUT);
55715b117eaSkettenis 
55815b117eaSkettenis   switch (_rl_to_upper (ch))
55915b117eaSkettenis     {
56015b117eaSkettenis     case 'A':
56115b117eaSkettenis       rl_get_previous_history (count, ch);
56215b117eaSkettenis       break;
56315b117eaSkettenis 
56415b117eaSkettenis     case 'B':
56515b117eaSkettenis       rl_get_next_history (count, ch);
56615b117eaSkettenis       break;
56715b117eaSkettenis 
56815b117eaSkettenis     case 'C':
56915b117eaSkettenis       if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
57015b117eaSkettenis 	rl_forward_char (count, ch);
57115b117eaSkettenis       else
57215b117eaSkettenis 	rl_forward_byte (count, ch);
57315b117eaSkettenis       break;
57415b117eaSkettenis 
57515b117eaSkettenis     case 'D':
57615b117eaSkettenis       if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
57715b117eaSkettenis 	rl_backward_char (count, ch);
57815b117eaSkettenis       else
57915b117eaSkettenis 	rl_backward_byte (count, ch);
58015b117eaSkettenis       break;
58115b117eaSkettenis 
58215b117eaSkettenis     default:
58315b117eaSkettenis       rl_ding ();
58415b117eaSkettenis     }
58515b117eaSkettenis 
58615b117eaSkettenis   return 0;
58715b117eaSkettenis }
58815b117eaSkettenis 
58915b117eaSkettenis /* **************************************************************** */
59015b117eaSkettenis /*								    */
59115b117eaSkettenis /*			Text commands				    */
59215b117eaSkettenis /*								    */
59315b117eaSkettenis /* **************************************************************** */
59415b117eaSkettenis 
59515b117eaSkettenis #ifdef HANDLE_MULTIBYTE
59615b117eaSkettenis static char pending_bytes[MB_LEN_MAX];
59715b117eaSkettenis static int pending_bytes_length = 0;
59815b117eaSkettenis static mbstate_t ps = {0};
59915b117eaSkettenis #endif
60015b117eaSkettenis 
60115b117eaSkettenis /* Insert the character C at the current location, moving point forward.
60215b117eaSkettenis    If C introduces a multibyte sequence, we read the whole sequence and
60315b117eaSkettenis    then insert the multibyte char into the line buffer. */
60415b117eaSkettenis int
_rl_insert_char(count,c)60515b117eaSkettenis _rl_insert_char (count, c)
60615b117eaSkettenis      int count, c;
60715b117eaSkettenis {
60815b117eaSkettenis   register int i;
60915b117eaSkettenis   char *string;
61015b117eaSkettenis #ifdef HANDLE_MULTIBYTE
61115b117eaSkettenis   int string_size;
61215b117eaSkettenis   char incoming[MB_LEN_MAX + 1];
61315b117eaSkettenis   int incoming_length = 0;
61415b117eaSkettenis   mbstate_t ps_back;
61515b117eaSkettenis   static int stored_count = 0;
61615b117eaSkettenis #endif
61715b117eaSkettenis 
61815b117eaSkettenis   if (count <= 0)
61915b117eaSkettenis     return 0;
62015b117eaSkettenis 
62115b117eaSkettenis #if defined (HANDLE_MULTIBYTE)
62215b117eaSkettenis   if (MB_CUR_MAX == 1 || rl_byte_oriented)
62315b117eaSkettenis     {
62415b117eaSkettenis       incoming[0] = c;
62515b117eaSkettenis       incoming[1] = '\0';
62615b117eaSkettenis       incoming_length = 1;
62715b117eaSkettenis     }
62815b117eaSkettenis   else
62915b117eaSkettenis     {
63015b117eaSkettenis       wchar_t wc;
63115b117eaSkettenis       size_t ret;
63215b117eaSkettenis 
63315b117eaSkettenis       if (stored_count <= 0)
63415b117eaSkettenis 	stored_count = count;
63515b117eaSkettenis       else
63615b117eaSkettenis 	count = stored_count;
63715b117eaSkettenis 
63815b117eaSkettenis       ps_back = ps;
63915b117eaSkettenis       pending_bytes[pending_bytes_length++] = c;
64015b117eaSkettenis       ret = mbrtowc (&wc, pending_bytes, pending_bytes_length, &ps);
64115b117eaSkettenis 
64215b117eaSkettenis       if (ret == (size_t)-2)
64315b117eaSkettenis 	{
64415b117eaSkettenis 	  /* Bytes too short to compose character, try to wait for next byte.
64515b117eaSkettenis 	     Restore the state of the byte sequence, because in this case the
64615b117eaSkettenis 	     effect of mbstate is undefined. */
64715b117eaSkettenis 	  ps = ps_back;
64815b117eaSkettenis 	  return 1;
64915b117eaSkettenis 	}
65015b117eaSkettenis       else if (ret == (size_t)-1)
65115b117eaSkettenis 	{
65215b117eaSkettenis 	  /* Invalid byte sequence for the current locale.  Treat first byte
65315b117eaSkettenis 	     as a single character. */
65415b117eaSkettenis 	  incoming[0] = pending_bytes[0];
65515b117eaSkettenis 	  incoming[1] = '\0';
65615b117eaSkettenis 	  incoming_length = 1;
65715b117eaSkettenis 	  pending_bytes_length--;
65815b117eaSkettenis 	  memmove (pending_bytes, pending_bytes + 1, pending_bytes_length);
65915b117eaSkettenis 	  /* Clear the state of the byte sequence, because in this case the
66015b117eaSkettenis 	     effect of mbstate is undefined. */
66115b117eaSkettenis 	  memset (&ps, 0, sizeof (mbstate_t));
66215b117eaSkettenis 	}
66315b117eaSkettenis       else if (ret == (size_t)0)
66415b117eaSkettenis 	{
66515b117eaSkettenis 	  incoming[0] = '\0';
66615b117eaSkettenis 	  incoming_length = 0;
66715b117eaSkettenis 	  pending_bytes_length--;
66815b117eaSkettenis 	  /* Clear the state of the byte sequence, because in this case the
66915b117eaSkettenis 	     effect of mbstate is undefined. */
67015b117eaSkettenis 	  memset (&ps, 0, sizeof (mbstate_t));
67115b117eaSkettenis 	}
67215b117eaSkettenis       else
67315b117eaSkettenis 	{
67415b117eaSkettenis 	  /* We successfully read a single multibyte character. */
67515b117eaSkettenis 	  memcpy (incoming, pending_bytes, pending_bytes_length);
67615b117eaSkettenis 	  incoming[pending_bytes_length] = '\0';
67715b117eaSkettenis 	  incoming_length = pending_bytes_length;
67815b117eaSkettenis 	  pending_bytes_length = 0;
67915b117eaSkettenis 	}
68015b117eaSkettenis     }
68115b117eaSkettenis #endif /* HANDLE_MULTIBYTE */
68215b117eaSkettenis 
68315b117eaSkettenis   /* If we can optimize, then do it.  But don't let people crash
68415b117eaSkettenis      readline because of extra large arguments. */
68515b117eaSkettenis   if (count > 1 && count <= 1024)
68615b117eaSkettenis     {
68715b117eaSkettenis #if defined (HANDLE_MULTIBYTE)
68815b117eaSkettenis       string_size = count * incoming_length;
68915b117eaSkettenis       string = (char *)xmalloc (1 + string_size);
69015b117eaSkettenis 
69115b117eaSkettenis       i = 0;
69215b117eaSkettenis       while (i < string_size)
69315b117eaSkettenis 	{
69415b117eaSkettenis 	  strncpy (string + i, incoming, incoming_length);
69515b117eaSkettenis 	  i += incoming_length;
69615b117eaSkettenis 	}
69715b117eaSkettenis       incoming_length = 0;
69815b117eaSkettenis       stored_count = 0;
69915b117eaSkettenis #else /* !HANDLE_MULTIBYTE */
70015b117eaSkettenis       string = (char *)xmalloc (1 + count);
70115b117eaSkettenis 
70215b117eaSkettenis       for (i = 0; i < count; i++)
70315b117eaSkettenis 	string[i] = c;
70415b117eaSkettenis #endif /* !HANDLE_MULTIBYTE */
70515b117eaSkettenis 
70615b117eaSkettenis       string[i] = '\0';
70715b117eaSkettenis       rl_insert_text (string);
70815b117eaSkettenis       free (string);
70915b117eaSkettenis 
71015b117eaSkettenis       return 0;
71115b117eaSkettenis     }
71215b117eaSkettenis 
71315b117eaSkettenis   if (count > 1024)
71415b117eaSkettenis     {
71515b117eaSkettenis       int decreaser;
71615b117eaSkettenis #if defined (HANDLE_MULTIBYTE)
71715b117eaSkettenis       string_size = incoming_length * 1024;
71815b117eaSkettenis       string = (char *)xmalloc (1 + string_size);
71915b117eaSkettenis 
72015b117eaSkettenis       i = 0;
72115b117eaSkettenis       while (i < string_size)
72215b117eaSkettenis 	{
72315b117eaSkettenis 	  strncpy (string + i, incoming, incoming_length);
72415b117eaSkettenis 	  i += incoming_length;
72515b117eaSkettenis 	}
72615b117eaSkettenis 
72715b117eaSkettenis       while (count)
72815b117eaSkettenis 	{
72915b117eaSkettenis 	  decreaser = (count > 1024) ? 1024 : count;
73015b117eaSkettenis 	  string[decreaser*incoming_length] = '\0';
73115b117eaSkettenis 	  rl_insert_text (string);
73215b117eaSkettenis 	  count -= decreaser;
73315b117eaSkettenis 	}
73415b117eaSkettenis 
73515b117eaSkettenis       free (string);
73615b117eaSkettenis       incoming_length = 0;
73715b117eaSkettenis       stored_count = 0;
73815b117eaSkettenis #else /* !HANDLE_MULTIBYTE */
73915b117eaSkettenis       char str[1024+1];
74015b117eaSkettenis 
74115b117eaSkettenis       for (i = 0; i < 1024; i++)
74215b117eaSkettenis 	str[i] = c;
74315b117eaSkettenis 
74415b117eaSkettenis       while (count)
74515b117eaSkettenis 	{
74615b117eaSkettenis 	  decreaser = (count > 1024 ? 1024 : count);
74715b117eaSkettenis 	  str[decreaser] = '\0';
74815b117eaSkettenis 	  rl_insert_text (str);
74915b117eaSkettenis 	  count -= decreaser;
75015b117eaSkettenis 	}
75115b117eaSkettenis #endif /* !HANDLE_MULTIBYTE */
75215b117eaSkettenis 
75315b117eaSkettenis       return 0;
75415b117eaSkettenis     }
75515b117eaSkettenis 
75615b117eaSkettenis #if defined (HANDLE_MULTIBYTE)
75715b117eaSkettenis   if (MB_CUR_MAX == 1 || rl_byte_oriented)
75815b117eaSkettenis     {
75915b117eaSkettenis #endif
76015b117eaSkettenis       /* We are inserting a single character.
76115b117eaSkettenis 	 If there is pending input, then make a string of all of the
76215b117eaSkettenis 	 pending characters that are bound to rl_insert, and insert
76315b117eaSkettenis 	 them all. */
76415b117eaSkettenis       if (_rl_any_typein ())
76515b117eaSkettenis 	_rl_insert_typein (c);
76615b117eaSkettenis       else
76715b117eaSkettenis 	{
76815b117eaSkettenis 	  /* Inserting a single character. */
76915b117eaSkettenis 	  char str[2];
77015b117eaSkettenis 
77115b117eaSkettenis 	  str[1] = '\0';
77215b117eaSkettenis 	  str[0] = c;
77315b117eaSkettenis 	  rl_insert_text (str);
77415b117eaSkettenis 	}
77515b117eaSkettenis #if defined (HANDLE_MULTIBYTE)
77615b117eaSkettenis     }
77715b117eaSkettenis   else
77815b117eaSkettenis     {
77915b117eaSkettenis       rl_insert_text (incoming);
78015b117eaSkettenis       stored_count = 0;
78115b117eaSkettenis     }
78215b117eaSkettenis #endif
78315b117eaSkettenis 
78415b117eaSkettenis   return 0;
78515b117eaSkettenis }
78615b117eaSkettenis 
78715b117eaSkettenis /* Overwrite the character at point (or next COUNT characters) with C.
78815b117eaSkettenis    If C introduces a multibyte character sequence, read the entire sequence
78915b117eaSkettenis    before starting the overwrite loop. */
79015b117eaSkettenis int
_rl_overwrite_char(count,c)79115b117eaSkettenis _rl_overwrite_char (count, c)
79215b117eaSkettenis      int count, c;
79315b117eaSkettenis {
79415b117eaSkettenis   int i;
79515b117eaSkettenis #if defined (HANDLE_MULTIBYTE)
79615b117eaSkettenis   char mbkey[MB_LEN_MAX];
79715b117eaSkettenis   int k;
79815b117eaSkettenis 
79915b117eaSkettenis   /* Read an entire multibyte character sequence to insert COUNT times. */
80015b117eaSkettenis   if (count > 0 && MB_CUR_MAX > 1 && rl_byte_oriented == 0)
80115b117eaSkettenis     k = _rl_read_mbstring (c, mbkey, MB_LEN_MAX);
80215b117eaSkettenis #endif
80315b117eaSkettenis 
80415b117eaSkettenis   for (i = 0; i < count; i++)
80515b117eaSkettenis     {
80615b117eaSkettenis       rl_begin_undo_group ();
80715b117eaSkettenis 
80815b117eaSkettenis       if (rl_point < rl_end)
80915b117eaSkettenis 	rl_delete (1, c);
81015b117eaSkettenis 
81115b117eaSkettenis #if defined (HANDLE_MULTIBYTE)
81215b117eaSkettenis       if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
81315b117eaSkettenis 	rl_insert_text (mbkey);
81415b117eaSkettenis       else
81515b117eaSkettenis #endif
81615b117eaSkettenis 	_rl_insert_char (1, c);
81715b117eaSkettenis 
81815b117eaSkettenis       rl_end_undo_group ();
81915b117eaSkettenis     }
82015b117eaSkettenis 
82115b117eaSkettenis   return 0;
82215b117eaSkettenis }
82315b117eaSkettenis 
82415b117eaSkettenis int
rl_insert(count,c)82515b117eaSkettenis rl_insert (count, c)
82615b117eaSkettenis      int count, c;
82715b117eaSkettenis {
82815b117eaSkettenis   return (rl_insert_mode == RL_IM_INSERT ? _rl_insert_char (count, c)
82915b117eaSkettenis 					 : _rl_overwrite_char (count, c));
83015b117eaSkettenis }
83115b117eaSkettenis 
83215b117eaSkettenis /* Insert the next typed character verbatim. */
83315b117eaSkettenis int
rl_quoted_insert(count,key)83415b117eaSkettenis rl_quoted_insert (count, key)
83515b117eaSkettenis      int count, key;
83615b117eaSkettenis {
83715b117eaSkettenis   int c;
83815b117eaSkettenis 
83915b117eaSkettenis #if defined (HANDLE_SIGNALS)
84015b117eaSkettenis   _rl_disable_tty_signals ();
84115b117eaSkettenis #endif
84215b117eaSkettenis 
84315b117eaSkettenis   RL_SETSTATE(RL_STATE_MOREINPUT);
84415b117eaSkettenis   c = rl_read_key ();
84515b117eaSkettenis   RL_UNSETSTATE(RL_STATE_MOREINPUT);
84615b117eaSkettenis 
84715b117eaSkettenis #if defined (HANDLE_SIGNALS)
84815b117eaSkettenis   _rl_restore_tty_signals ();
84915b117eaSkettenis #endif
85015b117eaSkettenis 
85115b117eaSkettenis   return (_rl_insert_char (count, c));
85215b117eaSkettenis }
85315b117eaSkettenis 
85415b117eaSkettenis /* Insert a tab character. */
85515b117eaSkettenis int
rl_tab_insert(count,key)85615b117eaSkettenis rl_tab_insert (count, key)
85715b117eaSkettenis      int count, key;
85815b117eaSkettenis {
85915b117eaSkettenis   return (_rl_insert_char (count, '\t'));
86015b117eaSkettenis }
86115b117eaSkettenis 
86215b117eaSkettenis /* What to do when a NEWLINE is pressed.  We accept the whole line.
86315b117eaSkettenis    KEY is the key that invoked this command.  I guess it could have
86415b117eaSkettenis    meaning in the future. */
86515b117eaSkettenis int
rl_newline(count,key)86615b117eaSkettenis rl_newline (count, key)
86715b117eaSkettenis      int count, key;
86815b117eaSkettenis {
86915b117eaSkettenis   rl_done = 1;
87015b117eaSkettenis 
87115b117eaSkettenis   if (_rl_history_preserve_point)
87215b117eaSkettenis     _rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point;
87315b117eaSkettenis 
87415b117eaSkettenis   RL_SETSTATE(RL_STATE_DONE);
87515b117eaSkettenis 
87615b117eaSkettenis #if defined (VI_MODE)
87715b117eaSkettenis   if (rl_editing_mode == vi_mode)
87815b117eaSkettenis     {
87915b117eaSkettenis       _rl_vi_done_inserting ();
88015b117eaSkettenis       _rl_vi_reset_last ();
88115b117eaSkettenis     }
88215b117eaSkettenis #endif /* VI_MODE */
88315b117eaSkettenis 
88415b117eaSkettenis   /* If we've been asked to erase empty lines, suppress the final update,
88515b117eaSkettenis      since _rl_update_final calls rl_crlf(). */
88615b117eaSkettenis   if (rl_erase_empty_line && rl_point == 0 && rl_end == 0)
88715b117eaSkettenis     return 0;
88815b117eaSkettenis 
88915b117eaSkettenis   if (readline_echoing_p)
89015b117eaSkettenis     _rl_update_final ();
89115b117eaSkettenis   return 0;
89215b117eaSkettenis }
89315b117eaSkettenis 
89415b117eaSkettenis /* What to do for some uppercase characters, like meta characters,
89515b117eaSkettenis    and some characters appearing in emacs_ctlx_keymap.  This function
89615b117eaSkettenis    is just a stub, you bind keys to it and the code in _rl_dispatch ()
89715b117eaSkettenis    is special cased. */
89815b117eaSkettenis int
rl_do_lowercase_version(ignore1,ignore2)89915b117eaSkettenis rl_do_lowercase_version (ignore1, ignore2)
90015b117eaSkettenis      int ignore1, ignore2;
90115b117eaSkettenis {
90215b117eaSkettenis   return 0;
90315b117eaSkettenis }
90415b117eaSkettenis 
90515b117eaSkettenis /* This is different from what vi does, so the code's not shared.  Emacs
90615b117eaSkettenis    rubout in overwrite mode has one oddity:  it replaces a control
90715b117eaSkettenis    character that's displayed as two characters (^X) with two spaces. */
90815b117eaSkettenis int
_rl_overwrite_rubout(count,key)90915b117eaSkettenis _rl_overwrite_rubout (count, key)
91015b117eaSkettenis      int count, key;
91115b117eaSkettenis {
91215b117eaSkettenis   int opoint;
91315b117eaSkettenis   int i, l;
91415b117eaSkettenis 
91515b117eaSkettenis   if (rl_point == 0)
91615b117eaSkettenis     {
91715b117eaSkettenis       rl_ding ();
91815b117eaSkettenis       return 1;
91915b117eaSkettenis     }
92015b117eaSkettenis 
92115b117eaSkettenis   opoint = rl_point;
92215b117eaSkettenis 
92315b117eaSkettenis   /* L == number of spaces to insert */
92415b117eaSkettenis   for (i = l = 0; i < count; i++)
92515b117eaSkettenis     {
92615b117eaSkettenis       rl_backward_char (1, key);
92715b117eaSkettenis       l += rl_character_len (rl_line_buffer[rl_point], rl_point);	/* not exactly right */
92815b117eaSkettenis     }
92915b117eaSkettenis 
93015b117eaSkettenis   rl_begin_undo_group ();
93115b117eaSkettenis 
93215b117eaSkettenis   if (count > 1 || rl_explicit_arg)
93315b117eaSkettenis     rl_kill_text (opoint, rl_point);
93415b117eaSkettenis   else
93515b117eaSkettenis     rl_delete_text (opoint, rl_point);
93615b117eaSkettenis 
93715b117eaSkettenis   /* Emacs puts point at the beginning of the sequence of spaces. */
93815b117eaSkettenis   opoint = rl_point;
93915b117eaSkettenis   _rl_insert_char (l, ' ');
94015b117eaSkettenis   rl_point = opoint;
94115b117eaSkettenis 
94215b117eaSkettenis   rl_end_undo_group ();
94315b117eaSkettenis 
94415b117eaSkettenis   return 0;
94515b117eaSkettenis }
94615b117eaSkettenis 
94715b117eaSkettenis /* Rubout the character behind point. */
94815b117eaSkettenis int
rl_rubout(count,key)94915b117eaSkettenis rl_rubout (count, key)
95015b117eaSkettenis      int count, key;
95115b117eaSkettenis {
95215b117eaSkettenis   if (count < 0)
95315b117eaSkettenis     return (rl_delete (-count, key));
95415b117eaSkettenis 
95515b117eaSkettenis   if (!rl_point)
95615b117eaSkettenis     {
95715b117eaSkettenis       rl_ding ();
95815b117eaSkettenis       return -1;
95915b117eaSkettenis     }
96015b117eaSkettenis 
96115b117eaSkettenis   if (rl_insert_mode == RL_IM_OVERWRITE)
96215b117eaSkettenis     return (_rl_overwrite_rubout (count, key));
96315b117eaSkettenis 
96415b117eaSkettenis   return (_rl_rubout_char (count, key));
96515b117eaSkettenis }
96615b117eaSkettenis 
96715b117eaSkettenis int
_rl_rubout_char(count,key)96815b117eaSkettenis _rl_rubout_char (count, key)
96915b117eaSkettenis      int count, key;
97015b117eaSkettenis {
97115b117eaSkettenis   int orig_point;
97215b117eaSkettenis   unsigned char c;
97315b117eaSkettenis 
97415b117eaSkettenis   /* Duplicated code because this is called from other parts of the library. */
97515b117eaSkettenis   if (count < 0)
97615b117eaSkettenis     return (rl_delete (-count, key));
97715b117eaSkettenis 
97815b117eaSkettenis   if (rl_point == 0)
97915b117eaSkettenis     {
98015b117eaSkettenis       rl_ding ();
98115b117eaSkettenis       return -1;
98215b117eaSkettenis     }
98315b117eaSkettenis 
98415b117eaSkettenis   if (count > 1 || rl_explicit_arg)
98515b117eaSkettenis     {
98615b117eaSkettenis       orig_point = rl_point;
98715b117eaSkettenis #if defined (HANDLE_MULTIBYTE)
98815b117eaSkettenis       if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
98915b117eaSkettenis 	rl_backward_char (count, key);
99015b117eaSkettenis       else
99115b117eaSkettenis #endif
99215b117eaSkettenis         rl_backward_byte (count, key);
99315b117eaSkettenis       rl_kill_text (orig_point, rl_point);
99415b117eaSkettenis     }
99515b117eaSkettenis   else
99615b117eaSkettenis     {
99715b117eaSkettenis #if defined (HANDLE_MULTIBYTE)
99815b117eaSkettenis       if (MB_CUR_MAX == 1 || rl_byte_oriented)
99915b117eaSkettenis 	{
100015b117eaSkettenis #endif
100115b117eaSkettenis 	  c = rl_line_buffer[--rl_point];
100215b117eaSkettenis 	  rl_delete_text (rl_point, rl_point + 1);
100315b117eaSkettenis #if defined (HANDLE_MULTIBYTE)
100415b117eaSkettenis 	}
100515b117eaSkettenis       else
100615b117eaSkettenis 	{
100715b117eaSkettenis 	  int orig_point;
100815b117eaSkettenis 
100915b117eaSkettenis 	  orig_point = rl_point;
101015b117eaSkettenis 	  rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO);
101115b117eaSkettenis 	  c = rl_line_buffer[rl_point];
101215b117eaSkettenis 	  rl_delete_text (rl_point, orig_point);
101315b117eaSkettenis 	}
101415b117eaSkettenis #endif /* HANDLE_MULTIBYTE */
101515b117eaSkettenis 
101615b117eaSkettenis       /* I don't think that the hack for end of line is needed for
101715b117eaSkettenis 	 multibyte chars. */
101815b117eaSkettenis #if defined (HANDLE_MULTIBYTE)
101915b117eaSkettenis       if (MB_CUR_MAX == 1 || rl_byte_oriented)
102015b117eaSkettenis #endif
102115b117eaSkettenis       if (rl_point == rl_end && ISPRINT (c) && _rl_last_c_pos)
102215b117eaSkettenis 	{
102315b117eaSkettenis 	  int l;
102415b117eaSkettenis 	  l = rl_character_len (c, rl_point);
102515b117eaSkettenis 	  _rl_erase_at_end_of_line (l);
102615b117eaSkettenis 	}
102715b117eaSkettenis     }
102815b117eaSkettenis 
102915b117eaSkettenis   return 0;
103015b117eaSkettenis }
103115b117eaSkettenis 
103215b117eaSkettenis /* Delete the character under the cursor.  Given a numeric argument,
103315b117eaSkettenis    kill that many characters instead. */
103415b117eaSkettenis int
rl_delete(count,key)103515b117eaSkettenis rl_delete (count, key)
103615b117eaSkettenis      int count, key;
103715b117eaSkettenis {
103815b117eaSkettenis   int r;
103915b117eaSkettenis 
104015b117eaSkettenis   if (count < 0)
104115b117eaSkettenis     return (_rl_rubout_char (-count, key));
104215b117eaSkettenis 
104315b117eaSkettenis   if (rl_point == rl_end)
104415b117eaSkettenis     {
104515b117eaSkettenis       rl_ding ();
104615b117eaSkettenis       return -1;
104715b117eaSkettenis     }
104815b117eaSkettenis 
104915b117eaSkettenis   if (count > 1 || rl_explicit_arg)
105015b117eaSkettenis     {
105115b117eaSkettenis       int orig_point = rl_point;
105215b117eaSkettenis #if defined (HANDLE_MULTIBYTE)
105315b117eaSkettenis       if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
105415b117eaSkettenis 	rl_forward_char (count, key);
105515b117eaSkettenis       else
105615b117eaSkettenis #endif
105715b117eaSkettenis 	rl_forward_byte (count, key);
105815b117eaSkettenis 
105915b117eaSkettenis       r = rl_kill_text (orig_point, rl_point);
106015b117eaSkettenis       rl_point = orig_point;
106115b117eaSkettenis       return r;
106215b117eaSkettenis     }
106315b117eaSkettenis   else
106415b117eaSkettenis     {
106515b117eaSkettenis       int new_point;
106615b117eaSkettenis       if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
106715b117eaSkettenis 	new_point = _rl_find_next_mbchar (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO);
106815b117eaSkettenis       else
106915b117eaSkettenis 	new_point = rl_point + 1;
107015b117eaSkettenis 
107115b117eaSkettenis       return (rl_delete_text (rl_point, new_point));
107215b117eaSkettenis     }
107315b117eaSkettenis }
107415b117eaSkettenis 
107515b117eaSkettenis /* Delete the character under the cursor, unless the insertion
107615b117eaSkettenis    point is at the end of the line, in which case the character
107715b117eaSkettenis    behind the cursor is deleted.  COUNT is obeyed and may be used
107815b117eaSkettenis    to delete forward or backward that many characters. */
107915b117eaSkettenis int
rl_rubout_or_delete(count,key)108015b117eaSkettenis rl_rubout_or_delete (count, key)
108115b117eaSkettenis      int count, key;
108215b117eaSkettenis {
108315b117eaSkettenis   if (rl_end != 0 && rl_point == rl_end)
108415b117eaSkettenis     return (_rl_rubout_char (count, key));
108515b117eaSkettenis   else
108615b117eaSkettenis     return (rl_delete (count, key));
108715b117eaSkettenis }
108815b117eaSkettenis 
108915b117eaSkettenis /* Delete all spaces and tabs around point. */
109015b117eaSkettenis int
rl_delete_horizontal_space(count,ignore)109115b117eaSkettenis rl_delete_horizontal_space (count, ignore)
109215b117eaSkettenis      int count, ignore;
109315b117eaSkettenis {
109415b117eaSkettenis   int start = rl_point;
109515b117eaSkettenis 
109615b117eaSkettenis   while (rl_point && whitespace (rl_line_buffer[rl_point - 1]))
109715b117eaSkettenis     rl_point--;
109815b117eaSkettenis 
109915b117eaSkettenis   start = rl_point;
110015b117eaSkettenis 
110115b117eaSkettenis   while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
110215b117eaSkettenis     rl_point++;
110315b117eaSkettenis 
110415b117eaSkettenis   if (start != rl_point)
110515b117eaSkettenis     {
110615b117eaSkettenis       rl_delete_text (start, rl_point);
110715b117eaSkettenis       rl_point = start;
110815b117eaSkettenis     }
110915b117eaSkettenis   return 0;
111015b117eaSkettenis }
111115b117eaSkettenis 
111215b117eaSkettenis /* Like the tcsh editing function delete-char-or-list.  The eof character
111315b117eaSkettenis    is caught before this is invoked, so this really does the same thing as
111415b117eaSkettenis    delete-char-or-list-or-eof, as long as it's bound to the eof character. */
111515b117eaSkettenis int
rl_delete_or_show_completions(count,key)111615b117eaSkettenis rl_delete_or_show_completions (count, key)
111715b117eaSkettenis      int count, key;
111815b117eaSkettenis {
111915b117eaSkettenis   if (rl_end != 0 && rl_point == rl_end)
112015b117eaSkettenis     return (rl_possible_completions (count, key));
112115b117eaSkettenis   else
112215b117eaSkettenis     return (rl_delete (count, key));
112315b117eaSkettenis }
112415b117eaSkettenis 
112515b117eaSkettenis #ifndef RL_COMMENT_BEGIN_DEFAULT
112615b117eaSkettenis #define RL_COMMENT_BEGIN_DEFAULT "#"
112715b117eaSkettenis #endif
112815b117eaSkettenis 
112915b117eaSkettenis /* Turn the current line into a comment in shell history.
113015b117eaSkettenis    A K*rn shell style function. */
113115b117eaSkettenis int
rl_insert_comment(count,key)113215b117eaSkettenis rl_insert_comment (count, key)
113315b117eaSkettenis      int count, key;
113415b117eaSkettenis {
113515b117eaSkettenis   char *rl_comment_text;
113615b117eaSkettenis   int rl_comment_len;
113715b117eaSkettenis 
113815b117eaSkettenis   rl_beg_of_line (1, key);
113915b117eaSkettenis   rl_comment_text = _rl_comment_begin ? _rl_comment_begin : RL_COMMENT_BEGIN_DEFAULT;
114015b117eaSkettenis 
114115b117eaSkettenis   if (rl_explicit_arg == 0)
114215b117eaSkettenis     rl_insert_text (rl_comment_text);
114315b117eaSkettenis   else
114415b117eaSkettenis     {
114515b117eaSkettenis       rl_comment_len = strlen (rl_comment_text);
114615b117eaSkettenis       if (STREQN (rl_comment_text, rl_line_buffer, rl_comment_len))
114715b117eaSkettenis 	rl_delete_text (rl_point, rl_point + rl_comment_len);
114815b117eaSkettenis       else
114915b117eaSkettenis 	rl_insert_text (rl_comment_text);
115015b117eaSkettenis     }
115115b117eaSkettenis 
115215b117eaSkettenis   (*rl_redisplay_function) ();
115315b117eaSkettenis   rl_newline (1, '\n');
115415b117eaSkettenis 
115515b117eaSkettenis   return (0);
115615b117eaSkettenis }
115715b117eaSkettenis 
115815b117eaSkettenis /* **************************************************************** */
115915b117eaSkettenis /*								    */
116015b117eaSkettenis /*			Changing Case				    */
116115b117eaSkettenis /*								    */
116215b117eaSkettenis /* **************************************************************** */
116315b117eaSkettenis 
116415b117eaSkettenis /* The three kinds of things that we know how to do. */
116515b117eaSkettenis #define UpCase 1
116615b117eaSkettenis #define DownCase 2
116715b117eaSkettenis #define CapCase 3
116815b117eaSkettenis 
116915b117eaSkettenis /* Uppercase the word at point. */
117015b117eaSkettenis int
rl_upcase_word(count,key)117115b117eaSkettenis rl_upcase_word (count, key)
117215b117eaSkettenis      int count, key;
117315b117eaSkettenis {
117415b117eaSkettenis   return (rl_change_case (count, UpCase));
117515b117eaSkettenis }
117615b117eaSkettenis 
117715b117eaSkettenis /* Lowercase the word at point. */
117815b117eaSkettenis int
rl_downcase_word(count,key)117915b117eaSkettenis rl_downcase_word (count, key)
118015b117eaSkettenis      int count, key;
118115b117eaSkettenis {
118215b117eaSkettenis   return (rl_change_case (count, DownCase));
118315b117eaSkettenis }
118415b117eaSkettenis 
118515b117eaSkettenis /* Upcase the first letter, downcase the rest. */
118615b117eaSkettenis int
rl_capitalize_word(count,key)118715b117eaSkettenis rl_capitalize_word (count, key)
118815b117eaSkettenis      int count, key;
118915b117eaSkettenis {
119015b117eaSkettenis  return (rl_change_case (count, CapCase));
119115b117eaSkettenis }
119215b117eaSkettenis 
119315b117eaSkettenis /* The meaty function.
119415b117eaSkettenis    Change the case of COUNT words, performing OP on them.
119515b117eaSkettenis    OP is one of UpCase, DownCase, or CapCase.
119615b117eaSkettenis    If a negative argument is given, leave point where it started,
119715b117eaSkettenis    otherwise, leave it where it moves to. */
119815b117eaSkettenis static int
rl_change_case(count,op)119915b117eaSkettenis rl_change_case (count, op)
120015b117eaSkettenis      int count, op;
120115b117eaSkettenis {
120215b117eaSkettenis   register int start, end;
120315b117eaSkettenis   int inword, c;
120415b117eaSkettenis 
120515b117eaSkettenis   start = rl_point;
120615b117eaSkettenis   rl_forward_word (count, 0);
120715b117eaSkettenis   end = rl_point;
120815b117eaSkettenis 
120915b117eaSkettenis   if (count < 0)
121015b117eaSkettenis     SWAP (start, end);
121115b117eaSkettenis 
121215b117eaSkettenis   /* We are going to modify some text, so let's prepare to undo it. */
121315b117eaSkettenis   rl_modifying (start, end);
121415b117eaSkettenis 
121515b117eaSkettenis   for (inword = 0; start < end; start++)
121615b117eaSkettenis     {
121715b117eaSkettenis       c = rl_line_buffer[start];
121815b117eaSkettenis       switch (op)
121915b117eaSkettenis 	{
122015b117eaSkettenis 	case UpCase:
122115b117eaSkettenis 	  rl_line_buffer[start] = _rl_to_upper (c);
122215b117eaSkettenis 	  break;
122315b117eaSkettenis 
122415b117eaSkettenis 	case DownCase:
122515b117eaSkettenis 	  rl_line_buffer[start] = _rl_to_lower (c);
122615b117eaSkettenis 	  break;
122715b117eaSkettenis 
122815b117eaSkettenis 	case CapCase:
122915b117eaSkettenis 	  rl_line_buffer[start] = (inword == 0) ? _rl_to_upper (c) : _rl_to_lower (c);
123015b117eaSkettenis 	  inword = rl_alphabetic (rl_line_buffer[start]);
123115b117eaSkettenis 	  break;
123215b117eaSkettenis 
123315b117eaSkettenis 	default:
123415b117eaSkettenis 	  rl_ding ();
123515b117eaSkettenis 	  return -1;
123615b117eaSkettenis 	}
123715b117eaSkettenis     }
123815b117eaSkettenis   rl_point = end;
123915b117eaSkettenis   return 0;
124015b117eaSkettenis }
124115b117eaSkettenis 
124215b117eaSkettenis /* **************************************************************** */
124315b117eaSkettenis /*								    */
124415b117eaSkettenis /*			Transposition				    */
124515b117eaSkettenis /*								    */
124615b117eaSkettenis /* **************************************************************** */
124715b117eaSkettenis 
124815b117eaSkettenis /* Transpose the words at point.  If point is at the end of the line,
124915b117eaSkettenis    transpose the two words before point. */
125015b117eaSkettenis int
rl_transpose_words(count,key)125115b117eaSkettenis rl_transpose_words (count, key)
125215b117eaSkettenis      int count, key;
125315b117eaSkettenis {
125415b117eaSkettenis   char *word1, *word2;
125515b117eaSkettenis   int w1_beg, w1_end, w2_beg, w2_end;
125615b117eaSkettenis   int orig_point = rl_point;
125715b117eaSkettenis 
125815b117eaSkettenis   if (!count)
125915b117eaSkettenis     return 0;
126015b117eaSkettenis 
126115b117eaSkettenis   /* Find the two words. */
126215b117eaSkettenis   rl_forward_word (count, key);
126315b117eaSkettenis   w2_end = rl_point;
126415b117eaSkettenis   rl_backward_word (1, key);
126515b117eaSkettenis   w2_beg = rl_point;
126615b117eaSkettenis   rl_backward_word (count, key);
126715b117eaSkettenis   w1_beg = rl_point;
126815b117eaSkettenis   rl_forward_word (1, key);
126915b117eaSkettenis   w1_end = rl_point;
127015b117eaSkettenis 
127115b117eaSkettenis   /* Do some check to make sure that there really are two words. */
127215b117eaSkettenis   if ((w1_beg == w2_beg) || (w2_beg < w1_end))
127315b117eaSkettenis     {
127415b117eaSkettenis       rl_ding ();
127515b117eaSkettenis       rl_point = orig_point;
127615b117eaSkettenis       return -1;
127715b117eaSkettenis     }
127815b117eaSkettenis 
127915b117eaSkettenis   /* Get the text of the words. */
128015b117eaSkettenis   word1 = rl_copy_text (w1_beg, w1_end);
128115b117eaSkettenis   word2 = rl_copy_text (w2_beg, w2_end);
128215b117eaSkettenis 
128315b117eaSkettenis   /* We are about to do many insertions and deletions.  Remember them
128415b117eaSkettenis      as one operation. */
128515b117eaSkettenis   rl_begin_undo_group ();
128615b117eaSkettenis 
128715b117eaSkettenis   /* Do the stuff at word2 first, so that we don't have to worry
128815b117eaSkettenis      about word1 moving. */
128915b117eaSkettenis   rl_point = w2_beg;
129015b117eaSkettenis   rl_delete_text (w2_beg, w2_end);
129115b117eaSkettenis   rl_insert_text (word1);
129215b117eaSkettenis 
129315b117eaSkettenis   rl_point = w1_beg;
129415b117eaSkettenis   rl_delete_text (w1_beg, w1_end);
129515b117eaSkettenis   rl_insert_text (word2);
129615b117eaSkettenis 
129715b117eaSkettenis   /* This is exactly correct since the text before this point has not
129815b117eaSkettenis      changed in length. */
129915b117eaSkettenis   rl_point = w2_end;
130015b117eaSkettenis 
130115b117eaSkettenis   /* I think that does it. */
130215b117eaSkettenis   rl_end_undo_group ();
130315b117eaSkettenis   free (word1);
130415b117eaSkettenis   free (word2);
130515b117eaSkettenis 
130615b117eaSkettenis   return 0;
130715b117eaSkettenis }
130815b117eaSkettenis 
130915b117eaSkettenis /* Transpose the characters at point.  If point is at the end of the line,
131015b117eaSkettenis    then transpose the characters before point. */
131115b117eaSkettenis int
rl_transpose_chars(count,key)131215b117eaSkettenis rl_transpose_chars (count, key)
131315b117eaSkettenis      int count, key;
131415b117eaSkettenis {
131515b117eaSkettenis #if defined (HANDLE_MULTIBYTE)
131615b117eaSkettenis   char *dummy;
131715b117eaSkettenis   int i, prev_point;
131815b117eaSkettenis #else
131915b117eaSkettenis   char dummy[2];
132015b117eaSkettenis #endif
132115b117eaSkettenis   int char_length;
132215b117eaSkettenis 
132315b117eaSkettenis   if (count == 0)
132415b117eaSkettenis     return 0;
132515b117eaSkettenis 
132615b117eaSkettenis   if (!rl_point || rl_end < 2)
132715b117eaSkettenis     {
132815b117eaSkettenis       rl_ding ();
132915b117eaSkettenis       return -1;
133015b117eaSkettenis     }
133115b117eaSkettenis 
133215b117eaSkettenis   rl_begin_undo_group ();
133315b117eaSkettenis 
133415b117eaSkettenis   if (rl_point == rl_end)
133515b117eaSkettenis     {
133615b117eaSkettenis       if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
133715b117eaSkettenis 	rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO);
133815b117eaSkettenis       else
133915b117eaSkettenis 	--rl_point;
134015b117eaSkettenis       count = 1;
134115b117eaSkettenis     }
134215b117eaSkettenis 
134315b117eaSkettenis #if defined (HANDLE_MULTIBYTE)
134415b117eaSkettenis   prev_point = rl_point;
134515b117eaSkettenis   if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
134615b117eaSkettenis     rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO);
134715b117eaSkettenis   else
134815b117eaSkettenis #endif
134915b117eaSkettenis     rl_point--;
135015b117eaSkettenis 
135115b117eaSkettenis #if defined (HANDLE_MULTIBYTE)
135215b117eaSkettenis   char_length = prev_point - rl_point;
135315b117eaSkettenis   dummy = (char *)xmalloc (char_length + 1);
135415b117eaSkettenis   for (i = 0; i < char_length; i++)
135515b117eaSkettenis     dummy[i] = rl_line_buffer[rl_point + i];
135615b117eaSkettenis   dummy[i] = '\0';
135715b117eaSkettenis #else
135815b117eaSkettenis   dummy[0] = rl_line_buffer[rl_point];
135915b117eaSkettenis   dummy[char_length = 1] = '\0';
136015b117eaSkettenis #endif
136115b117eaSkettenis 
136215b117eaSkettenis   rl_delete_text (rl_point, rl_point + char_length);
136315b117eaSkettenis 
136415b117eaSkettenis   rl_point = _rl_find_next_mbchar (rl_line_buffer, rl_point, count, MB_FIND_NONZERO);
136515b117eaSkettenis 
136615b117eaSkettenis   _rl_fix_point (0);
136715b117eaSkettenis   rl_insert_text (dummy);
136815b117eaSkettenis   rl_end_undo_group ();
136915b117eaSkettenis 
137015b117eaSkettenis #if defined (HANDLE_MULTIBYTE)
137115b117eaSkettenis   free (dummy);
137215b117eaSkettenis #endif
137315b117eaSkettenis 
137415b117eaSkettenis   return 0;
137515b117eaSkettenis }
137615b117eaSkettenis 
137715b117eaSkettenis /* **************************************************************** */
137815b117eaSkettenis /*								    */
137915b117eaSkettenis /*			Character Searching			    */
138015b117eaSkettenis /*								    */
138115b117eaSkettenis /* **************************************************************** */
138215b117eaSkettenis 
138315b117eaSkettenis int
138415b117eaSkettenis #if defined (HANDLE_MULTIBYTE)
_rl_char_search_internal(count,dir,smbchar,len)138515b117eaSkettenis _rl_char_search_internal (count, dir, smbchar, len)
138615b117eaSkettenis      int count, dir;
138715b117eaSkettenis      char *smbchar;
138815b117eaSkettenis      int len;
138915b117eaSkettenis #else
139015b117eaSkettenis _rl_char_search_internal (count, dir, schar)
139115b117eaSkettenis      int count, dir, schar;
139215b117eaSkettenis #endif
139315b117eaSkettenis {
139415b117eaSkettenis   int pos, inc;
139515b117eaSkettenis #if defined (HANDLE_MULTIBYTE)
139615b117eaSkettenis   int prepos;
139715b117eaSkettenis #endif
139815b117eaSkettenis 
139915b117eaSkettenis   pos = rl_point;
140015b117eaSkettenis   inc = (dir < 0) ? -1 : 1;
140115b117eaSkettenis   while (count)
140215b117eaSkettenis     {
140315b117eaSkettenis       if ((dir < 0 && pos <= 0) || (dir > 0 && pos >= rl_end))
140415b117eaSkettenis 	{
140515b117eaSkettenis 	  rl_ding ();
140615b117eaSkettenis 	  return -1;
140715b117eaSkettenis 	}
140815b117eaSkettenis 
140915b117eaSkettenis #if defined (HANDLE_MULTIBYTE)
141015b117eaSkettenis       pos = (inc > 0) ? _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY)
141115b117eaSkettenis 		      : _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY);
141215b117eaSkettenis #else
141315b117eaSkettenis       pos += inc;
141415b117eaSkettenis #endif
141515b117eaSkettenis       do
141615b117eaSkettenis 	{
141715b117eaSkettenis #if defined (HANDLE_MULTIBYTE)
141815b117eaSkettenis 	  if (_rl_is_mbchar_matched (rl_line_buffer, pos, rl_end, smbchar, len))
141915b117eaSkettenis #else
142015b117eaSkettenis 	  if (rl_line_buffer[pos] == schar)
142115b117eaSkettenis #endif
142215b117eaSkettenis 	    {
142315b117eaSkettenis 	      count--;
142415b117eaSkettenis 	      if (dir < 0)
142515b117eaSkettenis 	        rl_point = (dir == BTO) ? _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY)
142615b117eaSkettenis 					: pos;
142715b117eaSkettenis 	      else
142815b117eaSkettenis 		rl_point = (dir == FTO) ? _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY)
142915b117eaSkettenis 					: pos;
143015b117eaSkettenis 	      break;
143115b117eaSkettenis 	    }
143215b117eaSkettenis #if defined (HANDLE_MULTIBYTE)
143315b117eaSkettenis 	  prepos = pos;
143415b117eaSkettenis #endif
143515b117eaSkettenis 	}
143615b117eaSkettenis #if defined (HANDLE_MULTIBYTE)
143715b117eaSkettenis       while ((dir < 0) ? (pos = _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY)) != prepos
143815b117eaSkettenis 		       : (pos = _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY)) != prepos);
143915b117eaSkettenis #else
144015b117eaSkettenis       while ((dir < 0) ? pos-- : ++pos < rl_end);
144115b117eaSkettenis #endif
144215b117eaSkettenis     }
144315b117eaSkettenis   return (0);
144415b117eaSkettenis }
144515b117eaSkettenis 
144615b117eaSkettenis /* Search COUNT times for a character read from the current input stream.
144715b117eaSkettenis    FDIR is the direction to search if COUNT is non-negative; otherwise
144815b117eaSkettenis    the search goes in BDIR.  So much is dependent on HANDLE_MULTIBYTE
144915b117eaSkettenis    that there are two separate versions of this function. */
145015b117eaSkettenis #if defined (HANDLE_MULTIBYTE)
145115b117eaSkettenis static int
_rl_char_search(count,fdir,bdir)145215b117eaSkettenis _rl_char_search (count, fdir, bdir)
145315b117eaSkettenis      int count, fdir, bdir;
145415b117eaSkettenis {
145515b117eaSkettenis   char mbchar[MB_LEN_MAX];
145615b117eaSkettenis   int mb_len;
145715b117eaSkettenis 
145815b117eaSkettenis   mb_len = _rl_read_mbchar (mbchar, MB_LEN_MAX);
145915b117eaSkettenis 
146015b117eaSkettenis   if (count < 0)
146115b117eaSkettenis     return (_rl_char_search_internal (-count, bdir, mbchar, mb_len));
146215b117eaSkettenis   else
146315b117eaSkettenis     return (_rl_char_search_internal (count, fdir, mbchar, mb_len));
146415b117eaSkettenis }
146515b117eaSkettenis #else /* !HANDLE_MULTIBYTE */
146615b117eaSkettenis static int
_rl_char_search(count,fdir,bdir)146715b117eaSkettenis _rl_char_search (count, fdir, bdir)
146815b117eaSkettenis      int count, fdir, bdir;
146915b117eaSkettenis {
147015b117eaSkettenis   int c;
147115b117eaSkettenis 
147215b117eaSkettenis   RL_SETSTATE(RL_STATE_MOREINPUT);
147315b117eaSkettenis   c = rl_read_key ();
147415b117eaSkettenis   RL_UNSETSTATE(RL_STATE_MOREINPUT);
147515b117eaSkettenis 
147615b117eaSkettenis   if (count < 0)
147715b117eaSkettenis     return (_rl_char_search_internal (-count, bdir, c));
147815b117eaSkettenis   else
147915b117eaSkettenis     return (_rl_char_search_internal (count, fdir, c));
148015b117eaSkettenis }
148115b117eaSkettenis #endif /* !HANDLE_MULTIBYTE */
148215b117eaSkettenis 
148315b117eaSkettenis int
rl_char_search(count,key)148415b117eaSkettenis rl_char_search (count, key)
148515b117eaSkettenis      int count, key;
148615b117eaSkettenis {
148715b117eaSkettenis   return (_rl_char_search (count, FFIND, BFIND));
148815b117eaSkettenis }
148915b117eaSkettenis 
149015b117eaSkettenis int
rl_backward_char_search(count,key)149115b117eaSkettenis rl_backward_char_search (count, key)
149215b117eaSkettenis      int count, key;
149315b117eaSkettenis {
149415b117eaSkettenis   return (_rl_char_search (count, BFIND, FFIND));
149515b117eaSkettenis }
149615b117eaSkettenis 
149715b117eaSkettenis /* **************************************************************** */
149815b117eaSkettenis /*								    */
149915b117eaSkettenis /*		   The Mark and the Region.			    */
150015b117eaSkettenis /*								    */
150115b117eaSkettenis /* **************************************************************** */
150215b117eaSkettenis 
150315b117eaSkettenis /* Set the mark at POSITION. */
150415b117eaSkettenis int
_rl_set_mark_at_pos(position)150515b117eaSkettenis _rl_set_mark_at_pos (position)
150615b117eaSkettenis      int position;
150715b117eaSkettenis {
150815b117eaSkettenis   if (position > rl_end)
150915b117eaSkettenis     return -1;
151015b117eaSkettenis 
151115b117eaSkettenis   rl_mark = position;
151215b117eaSkettenis   return 0;
151315b117eaSkettenis }
151415b117eaSkettenis 
151515b117eaSkettenis /* A bindable command to set the mark. */
151615b117eaSkettenis int
rl_set_mark(count,key)151715b117eaSkettenis rl_set_mark (count, key)
151815b117eaSkettenis      int count, key;
151915b117eaSkettenis {
152015b117eaSkettenis   return (_rl_set_mark_at_pos (rl_explicit_arg ? count : rl_point));
152115b117eaSkettenis }
152215b117eaSkettenis 
152315b117eaSkettenis /* Exchange the position of mark and point. */
152415b117eaSkettenis int
rl_exchange_point_and_mark(count,key)152515b117eaSkettenis rl_exchange_point_and_mark (count, key)
152615b117eaSkettenis      int count, key;
152715b117eaSkettenis {
152815b117eaSkettenis   if (rl_mark > rl_end)
152915b117eaSkettenis     rl_mark = -1;
153015b117eaSkettenis 
153115b117eaSkettenis   if (rl_mark == -1)
153215b117eaSkettenis     {
153315b117eaSkettenis       rl_ding ();
153415b117eaSkettenis       return -1;
153515b117eaSkettenis     }
153615b117eaSkettenis   else
153715b117eaSkettenis     SWAP (rl_point, rl_mark);
153815b117eaSkettenis 
153915b117eaSkettenis   return 0;
154015b117eaSkettenis }
1541