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