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