Bash-4.2 distribution sources and documentation
[platform/upstream/bash.git] / lib / readline / text.c
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 }